Trivial conflict in CAN, keep the net-next + the byteswap wrapper. Conflicts: drivers/net/can/usb/gs_usb.c
Unified · Split
| @@ -290,6 +290,7 @@ Santosh Shilimkar <ssantosh@kernel.org> · 289 unmodified lines | ||
| 290 | 290 | Sarangdhar Joshi <spjoshi@codeaurora.org> |
| 291 | 291 | Sascha Hauer <s.hauer@pengutronix.de> |
| 292 | 292 | S.Çağlar Onur <caglar@pardus.org.tr> |
| 293 | +Sean Christopherson <seanjc@google.com> <sean.j.christopherson@intel.com> | |
| 293 | 294 | Sean Nyekjaer <sean@geanix.com> <sean.nyekjaer@prevas.dk> |
| 294 | 295 | Sebastian Reichel <sre@kernel.org> <sebastian.reichel@collabora.co.uk> |
| 295 | 296 | Sebastian Reichel <sre@kernel.org> <sre@debian.org> |
| @@ -109,30 +109,6 @@ Description: · 108 unmodified lines | ||
| 109 | 109 | When counting down the counter start from preset value |
| 110 | 110 | and fire event when reach 0. |
| 111 | 111 | |
| 112 | −What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available | |
| 113 | −KernelVersion: 4.12 | |
| 114 | −Contact: benjamin.gaignard@st.com | |
| 115 | −Description: | |
| 116 | − Reading returns the list possible quadrature modes. | |
| 117 | − | |
| 118 | −What: /sys/bus/iio/devices/iio:deviceX/in_count0_quadrature_mode | |
| 119 | −KernelVersion: 4.12 | |
| 120 | −Contact: benjamin.gaignard@st.com | |
| 121 | −Description: | |
| 122 | − Configure the device counter quadrature modes: | |
| 123 | − | |
| 124 | − channel_A: | |
| 125 | − Encoder A input servers as the count input and B as | |
| 126 | − the UP/DOWN direction control input. | |
| 127 | − | |
| 128 | − channel_B: | |
| 129 | − Encoder B input serves as the count input and A as | |
| 130 | − the UP/DOWN direction control input. | |
| 131 | − | |
| 132 | − quadrature: | |
| 133 | − Encoder A and B inputs are mixed to get direction | |
| 134 | − and count with a scale of 0.25. | |
| 135 | − | |
| 136 | 112 | What: /sys/bus/iio/devices/iio:deviceX/in_count_enable_mode_available |
| 137 | 113 | KernelVersion: 4.12 |
| 138 | 114 | Contact: benjamin.gaignard@st.com |
| @@ -76,6 +76,12 @@ properties: · 75 unmodified lines | ||
| 76 | 76 | resets: |
| 77 | 77 | maxItems: 1 |
| 78 | 78 | |
| 79 | + wifi-2.4ghz-coexistence: | |
| 80 | + type: boolean | |
| 81 | + description: > | |
| 82 | + Should the pixel frequencies in the WiFi frequencies range be | |
| 83 | + avoided? | |
| 84 | + | |
| 79 | 85 | required: |
| 80 | 86 | - compatible |
| 81 | 87 | - reg |
| @@ -8,10 +8,16 @@ Required properties: · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | - reg : The I2C address of the device. |
| 10 | 10 | |
| 11 | +Optional properties: | |
| 12 | + | |
| 13 | +- realtek,power-up-delay-ms | |
| 14 | + Set a delay time for flush work to be completed, | |
| 15 | + this value is adjustable depending on platform. | |
| 11 | 16 | |
| 12 | 17 | Example: |
| 13 | 18 | |
| 14 | 19 | rt1015: codec@28 { |
| 15 | 20 | compatible = "realtek,rt1015"; |
| 16 | 21 | reg = <0x28>; |
| 22 | + realtek,power-up-delay-ms = <50>; | |
| 17 | 23 | }; |
| @@ -149,11 +149,11 @@ vidtv_psi.[ch] · 148 unmodified lines | ||
| 149 | 149 | Because the generator is implemented in a separate file, it can be |
| 150 | 150 | reused elsewhere in the media subsystem. |
| 151 | 151 | |
| 152 | − Currently vidtv supports working with 3 PSI tables: PAT, PMT and | |
| 153 | − SDT. | |
| 152 | + Currently vidtv supports working with 5 PSI tables: PAT, PMT, | |
| 153 | + SDT, NIT and EIT. | |
| 154 | 154 | |
| 155 | 155 | The specification for PAT and PMT can be found in *ISO 13818-1: |
| 156 | − Systems*, while the specification for the SDT can be found in *ETSI | |
| 156 | + Systems*, while the specification for the SDT, NIT, EIT can be found in *ETSI | |
| 157 | 157 | EN 300 468: Specification for Service Information (SI) in DVB |
| 158 | 158 | systems*. |
| 159 | 159 | |
| @@ -197,6 +197,8 @@ vidtv_channel.[ch] · 37 unmodified lines | ||
| 197 | 197 | |
| 198 | 198 | #. Their programs will be concatenated to populate the PAT |
| 199 | 199 | |
| 200 | + #. Their events will be concatenated to populate the EIT | |
| 201 | + | |
| 200 | 202 | #. For each program in the PAT, a PMT section will be created |
| 201 | 203 | |
| 202 | 204 | #. The PMT section for a channel will be assigned its streams. |
| @@ -256,6 +258,42 @@ Using dvb-fe-tool · 53 unmodified lines | ||
| 256 | 258 | The first step to check whether the demod loaded successfully is to run:: |
| 257 | 259 | |
| 258 | 260 | $ dvb-fe-tool |
| 261 | + Device Dummy demod for DVB-T/T2/C/S/S2 (/dev/dvb/adapter0/frontend0) capabilities: | |
| 262 | + CAN_FEC_1_2 | |
| 263 | + CAN_FEC_2_3 | |
| 264 | + CAN_FEC_3_4 | |
| 265 | + CAN_FEC_4_5 | |
| 266 | + CAN_FEC_5_6 | |
| 267 | + CAN_FEC_6_7 | |
| 268 | + CAN_FEC_7_8 | |
| 269 | + CAN_FEC_8_9 | |
| 270 | + CAN_FEC_AUTO | |
| 271 | + CAN_GUARD_INTERVAL_AUTO | |
| 272 | + CAN_HIERARCHY_AUTO | |
| 273 | + CAN_INVERSION_AUTO | |
| 274 | + CAN_QAM_16 | |
| 275 | + CAN_QAM_32 | |
| 276 | + CAN_QAM_64 | |
| 277 | + CAN_QAM_128 | |
| 278 | + CAN_QAM_256 | |
| 279 | + CAN_QAM_AUTO | |
| 280 | + CAN_QPSK | |
| 281 | + CAN_TRANSMISSION_MODE_AUTO | |
| 282 | + DVB API Version 5.11, Current v5 delivery system: DVBC/ANNEX_A | |
| 283 | + Supported delivery systems: | |
| 284 | + DVBT | |
| 285 | + DVBT2 | |
| 286 | + [DVBC/ANNEX_A] | |
| 287 | + DVBS | |
| 288 | + DVBS2 | |
| 289 | + Frequency range for the current standard: | |
| 290 | + From: 51.0 MHz | |
| 291 | + To: 2.15 GHz | |
| 292 | + Step: 62.5 kHz | |
| 293 | + Tolerance: 29.5 MHz | |
| 294 | + Symbol rate ranges for the current standard: | |
| 295 | + From: 1.00 MBauds | |
| 296 | + To: 45.0 MBauds | |
| 259 | 297 | |
| 260 | 298 | This should return what is currently set up at the demod struct, i.e.:: |
| 261 | 299 | |
| @@ -314,7 +352,7 @@ For this, one should provide a configuration file known as a 'scan file', · 52 unmodified lines | ||
| 314 | 352 | here's an example:: |
| 315 | 353 | |
| 316 | 354 | [Channel] |
| 317 | − FREQUENCY = 330000000 | |
| 355 | + FREQUENCY = 474000000 | |
| 318 | 356 | MODULATION = QAM/AUTO |
| 319 | 357 | SYMBOL_RATE = 6940000 |
| 320 | 358 | INNER_FEC = AUTO |
| @@ -335,6 +373,14 @@ You can browse scan tables online here: `dvb-scan-tables · 14 unmodified lines | ||
| 335 | 373 | Assuming this channel is named 'channel.conf', you can then run:: |
| 336 | 374 | |
| 337 | 375 | $ dvbv5-scan channel.conf |
| 376 | + dvbv5-scan ~/vidtv.conf | |
| 377 | + ERROR command BANDWIDTH_HZ (5) not found during retrieve | |
| 378 | + Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet). | |
| 379 | + Scanning frequency #1 330000000 | |
| 380 | + (0x00) Signal= -68.00dBm | |
| 381 | + Scanning frequency #2 474000000 | |
| 382 | + Lock (0x1f) Signal= -34.45dBm C/N= 33.74dB UCB= 0 | |
| 383 | + Service Beethoven, provider LinuxTV.org: digital television | |
| 338 | 384 | |
| 339 | 385 | For more information on dvb-scan, check its documentation online here: |
| 340 | 386 | `dvb-scan Documentation <https://www.linuxtv.org/wiki/index.php/Dvbscan>`_. |
| @@ -344,23 +390,38 @@ Using dvb-zap · 3 unmodified lines | ||
| 344 | 390 | |
| 345 | 391 | dvbv5-zap is a command line tool that can be used to record MPEG-TS to disk. The |
| 346 | 392 | typical use is to tune into a channel and put it into record mode. The example |
| 347 | −below - which is taken from the documentation - illustrates that:: | |
| 393 | +below - which is taken from the documentation - illustrates that\ [1]_:: | |
| 348 | 394 | |
| 349 | − $ dvbv5-zap -c dvb_channel.conf "trilhas sonoras" -r | |
| 350 | − using demux '/dev/dvb/adapter0/demux0' | |
| 395 | + $ dvbv5-zap -c dvb_channel.conf "beethoven" -o music.ts -P -t 10 | |
| 396 | + using demux 'dvb0.demux0' | |
| 351 | 397 | reading channels from file 'dvb_channel.conf' |
| 352 | − service has pid type 05: 204 | |
| 353 | − tuning to 573000000 Hz | |
| 354 | − audio pid 104 | |
| 355 | − dvb_set_pesfilter 104 | |
| 356 | − Lock (0x1f) Quality= Good Signal= 100.00% C/N= -13.80dB UCB= 70 postBER= 3.14x10^-3 PER= 0 | |
| 357 | − DVR interface '/dev/dvb/adapter0/dvr0' can now be opened | |
| 398 | + tuning to 474000000 Hz | |
| 399 | + pass all PID's to TS | |
| 400 | + dvb_set_pesfilter 8192 | |
| 401 | + dvb_dev_set_bufsize: buffer set to 6160384 | |
| 402 | + Lock (0x1f) Quality= Good Signal= -34.66dBm C/N= 33.41dB UCB= 0 postBER= 0 preBER= 1.05x10^-3 PER= 0 | |
| 403 | + Lock (0x1f) Quality= Good Signal= -34.57dBm C/N= 33.46dB UCB= 0 postBER= 0 preBER= 1.05x10^-3 PER= 0 | |
| 404 | + Record to file 'music.ts' started | |
| 405 | + received 24587768 bytes (2401 Kbytes/sec) | |
| 406 | + Lock (0x1f) Quality= Good Signal= -34.42dBm C/N= 33.89dB UCB= 0 postBER= 0 preBER= 2.44x10^-3 PER= 0 | |
| 407 | + | |
| 408 | +.. [1] In this example, it records 10 seconds with all program ID's stored | |
| 409 | + at the music.ts file. | |
| 410 | + | |
| 358 | 411 | |
| 359 | −The channel can be watched by playing the contents of the DVR interface, with | |
| 360 | −some player that recognizes the MPEG-TS format, such as *mplayer* or *vlc*. | |
| 412 | +The channel can be watched by playing the contents of the stream with some | |
| 413 | +player that recognizes the MPEG-TS format, such as ``mplayer`` or ``vlc``. | |
| 361 | 414 | |
| 362 | 415 | By playing the contents of the stream one can visually inspect the workings of |
| 363 | −vidtv, e.g.:: | |
| 416 | +vidtv, e.g., to play a recorded TS file with:: | |
| 417 | + | |
| 418 | + $ mplayer music.ts | |
| 419 | + | |
| 420 | +or, alternatively, running this command on one terminal:: | |
| 421 | + | |
| 422 | + $ dvbv5-zap -c dvb_channel.conf "beethoven" -P -r & | |
| 423 | + | |
| 424 | +And, on a second terminal, playing the contents from DVR interface with:: | |
| 364 | 425 | |
| 365 | 426 | $ mplayer /dev/dvb/adapter0/dvr0 |
| 366 | 427 | |
| @@ -423,3 +484,30 @@ A nice addition is to simulate some noise when the signal quality is bad by: · 56 unmodified lines | ||
| 423 | 484 | - Updating the error statistics accordingly (e.g. BER, etc). |
| 424 | 485 | |
| 425 | 486 | - Simulating some noise in the encoded data. |
| 487 | + | |
| 488 | +Functions and structs used within vidtv | |
| 489 | +--------------------------------------- | |
| 490 | + | |
| 491 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_bridge.h | |
| 492 | + | |
| 493 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_channel.h | |
| 494 | + | |
| 495 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_demod.h | |
| 496 | + | |
| 497 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_encoder.h | |
| 498 | + | |
| 499 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_mux.h | |
| 500 | + | |
| 501 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_pes.h | |
| 502 | + | |
| 503 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_psi.h | |
| 504 | + | |
| 505 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_s302m.h | |
| 506 | + | |
| 507 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_ts.h | |
| 508 | + | |
| 509 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_tuner.h | |
| 510 | + | |
| 511 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_common.c | |
| 512 | + | |
| 513 | +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_tuner.c | |
| @@ -254,6 +254,32 @@ you will have done run-time testing specific to your change, but at a · 253 unmodified lines | ||
| 254 | 254 | minimum, your changes should survive an ``allyesconfig`` and an |
| 255 | 255 | ``allmodconfig`` build without new warnings or failures. |
| 256 | 256 | |
| 257 | +Q: How do I post corresponding changes to user space components? | |
| 258 | +---------------------------------------------------------------- | |
| 259 | +A: User space code exercising kernel features should be posted | |
| 260 | +alongside kernel patches. This gives reviewers a chance to see | |
| 261 | +how any new interface is used and how well it works. | |
| 262 | + | |
| 263 | +When user space tools reside in the kernel repo itself all changes | |
| 264 | +should generally come as one series. If series becomes too large | |
| 265 | +or the user space project is not reviewed on netdev include a link | |
| 266 | +to a public repo where user space patches can be seen. | |
| 267 | + | |
| 268 | +In case user space tooling lives in a separate repository but is | |
| 269 | +reviewed on netdev (e.g. patches to `iproute2` tools) kernel and | |
| 270 | +user space patches should form separate series (threads) when posted | |
| 271 | +to the mailing list, e.g.:: | |
| 272 | + | |
| 273 | + [PATCH net-next 0/3] net: some feature cover letter | |
| 274 | + └─ [PATCH net-next 1/3] net: some feature prep | |
| 275 | + └─ [PATCH net-next 2/3] net: some feature do it | |
| 276 | + └─ [PATCH net-next 3/3] selftest: net: some feature | |
| 277 | + | |
| 278 | + [PATCH iproute2-next] ip: add support for some feature | |
| 279 | + | |
| 280 | +Posting as one thread is discouraged because it confuses patchwork | |
| 281 | +(as of patchwork 2.2.2). | |
| 282 | + | |
| 257 | 283 | Q: Any other tips to help ensure my net/net-next patch gets OK'd? |
| 258 | 284 | ----------------------------------------------------------------- |
| 259 | 285 | A: Attention to detail. Re-read your own work as if you were the |
| @@ -1995,7 +1995,6 @@ N: lpc18xx · 1994 unmodified lines | ||
| 1995 | 1995 | |
| 1996 | 1996 | ARM/LPC32XX SOC SUPPORT |
| 1997 | 1997 | M: Vladimir Zapolskiy <vz@mleia.com> |
| 1998 | −M: Sylvain Lemieux <slemieux.tyco@gmail.com> | |
| 1999 | 1998 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2000 | 1999 | S: Maintained |
| 2001 | 2000 | T: git git://github.com/vzapolskiy/linux-lpc32xx.git |
| @@ -3528,11 +3527,12 @@ BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER · 1526 unmodified lines | ||
| 3528 | 3527 | M: Arend van Spriel <arend.vanspriel@broadcom.com> |
| 3529 | 3528 | M: Franky Lin <franky.lin@broadcom.com> |
| 3530 | 3529 | M: Hante Meuleman <hante.meuleman@broadcom.com> |
| 3531 | −M: Chi-Hsien Lin <chi-hsien.lin@cypress.com> | |
| 3532 | −M: Wright Feng <wright.feng@cypress.com> | |
| 3530 | +M: Chi-hsien Lin <chi-hsien.lin@infineon.com> | |
| 3531 | +M: Wright Feng <wright.feng@infineon.com> | |
| 3532 | +M: Chung-hsien Hsu <chung-hsien.hsu@infineon.com> | |
| 3533 | 3533 | L: linux-wireless@vger.kernel.org |
| 3534 | 3534 | L: brcm80211-dev-list.pdl@broadcom.com |
| 3535 | −L: brcm80211-dev-list@cypress.com | |
| 3535 | +L: SHA-cyfmac-dev-list@infineon.com | |
| 3536 | 3536 | S: Supported |
| 3537 | 3537 | F: drivers/net/wireless/broadcom/brcm80211/ |
| 3538 | 3538 | |
| @@ -9155,6 +9155,7 @@ F: include/linux/iomap.h · 5616 unmodified lines | ||
| 9155 | 9155 | |
| 9156 | 9156 | IOMMU DRIVERS |
| 9157 | 9157 | M: Joerg Roedel <joro@8bytes.org> |
| 9158 | +M: Will Deacon <will@kernel.org> | |
| 9158 | 9159 | L: iommu@lists.linux-foundation.org |
| 9159 | 9160 | S: Maintained |
| 9160 | 9161 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git |
| @@ -9638,6 +9639,7 @@ F: Documentation/virt/kvm/s390* · 477 unmodified lines | ||
| 9638 | 9639 | F: arch/s390/include/asm/gmap.h |
| 9639 | 9640 | F: arch/s390/include/asm/kvm* |
| 9640 | 9641 | F: arch/s390/include/uapi/asm/kvm* |
| 9642 | +F: arch/s390/kernel/uv.c | |
| 9641 | 9643 | F: arch/s390/kvm/ |
| 9642 | 9644 | F: arch/s390/mm/gmap.c |
| 9643 | 9645 | F: tools/testing/selftests/kvm/*/s390x/ |
| @@ -13156,7 +13158,9 @@ M: Jesper Dangaard Brouer <hawk@kernel.org> · 3512 unmodified lines | ||
| 13156 | 13158 | M: Ilias Apalodimas <ilias.apalodimas@linaro.org> |
| 13157 | 13159 | L: netdev@vger.kernel.org |
| 13158 | 13160 | S: Supported |
| 13161 | +F: Documentation/networking/page_pool.rst | |
| 13159 | 13162 | F: include/net/page_pool.h |
| 13163 | +F: include/trace/events/page_pool.h | |
| 13160 | 13164 | F: net/core/page_pool.c |
| 13161 | 13165 | |
| 13162 | 13166 | PANASONIC LAPTOP ACPI EXTRAS DRIVER |
| @@ -14798,7 +14802,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.g · 1635 unmodified lines | ||
| 14798 | 14802 | F: drivers/net/wireless/realtek/rtlwifi/ |
| 14799 | 14803 | |
| 14800 | 14804 | REALTEK WIRELESS DRIVER (rtw88) |
| 14801 | −M: Yan-Hsuan Chuang <yhchuang@realtek.com> | |
| 14805 | +M: Yan-Hsuan Chuang <tony0620emma@gmail.com> | |
| 14802 | 14806 | L: linux-wireless@vger.kernel.org |
| 14803 | 14807 | S: Maintained |
| 14804 | 14808 | F: drivers/net/wireless/realtek/rtw88/ |
| @@ -15771,9 +15775,8 @@ F: drivers/slimbus/ · 966 unmodified lines | ||
| 15771 | 15775 | F: include/linux/slimbus.h |
| 15772 | 15776 | |
| 15773 | 15777 | SFC NETWORK DRIVER |
| 15774 | −M: Solarflare linux maintainers <linux-net-drivers@solarflare.com> | |
| 15775 | −M: Edward Cree <ecree@solarflare.com> | |
| 15776 | −M: Martin Habets <mhabets@solarflare.com> | |
| 15778 | +M: Edward Cree <ecree.xilinx@gmail.com> | |
| 15779 | +M: Martin Habets <habetsm.xilinx@gmail.com> | |
| 15777 | 15780 | L: netdev@vger.kernel.org |
| 15778 | 15781 | S: Supported |
| 15779 | 15782 | F: drivers/net/ethernet/sfc/ |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 5 |
| 3 | 3 | PATCHLEVEL = 10 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc4 | |
| 5 | +EXTRAVERSION = -rc5 | |
| 6 | 6 | NAME = Kleptomaniac Octopus |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -243,10 +243,8 @@ static inline int constant_fls(unsigned int x) · 242 unmodified lines | ||
| 243 | 243 | x <<= 2; |
| 244 | 244 | r -= 2; |
| 245 | 245 | } |
| 246 | − if (!(x & 0x80000000u)) { | |
| 247 | − x <<= 1; | |
| 246 | + if (!(x & 0x80000000u)) | |
| 248 | 247 | r -= 1; |
| 249 | − } | |
| 250 | 248 | return r; |
| 251 | 249 | } |
| 252 | 250 | |
| @@ -134,8 +134,10 @@ · 133 unmodified lines | ||
| 134 | 134 | |
| 135 | 135 | #ifdef CONFIG_ARC_HAS_PAE40 |
| 136 | 136 | #define PTE_BITS_NON_RWX_IN_PD1 (0xff00000000 | PAGE_MASK | _PAGE_CACHEABLE) |
| 137 | +#define MAX_POSSIBLE_PHYSMEM_BITS 40 | |
| 137 | 138 | #else |
| 138 | 139 | #define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK | _PAGE_CACHEABLE) |
| 140 | +#define MAX_POSSIBLE_PHYSMEM_BITS 32 | |
| 139 | 141 | #endif |
| 140 | 142 | |
| 141 | 143 | /************************************************************************** |
| @@ -38,15 +38,27 @@ · 37 unmodified lines | ||
| 38 | 38 | |
| 39 | 39 | #ifdef CONFIG_ARC_DW2_UNWIND |
| 40 | 40 | |
| 41 | −static void seed_unwind_frame_info(struct task_struct *tsk, | |
| 42 | − struct pt_regs *regs, | |
| 43 | − struct unwind_frame_info *frame_info) | |
| 41 | +static int | |
| 42 | +seed_unwind_frame_info(struct task_struct *tsk, struct pt_regs *regs, | |
| 43 | + struct unwind_frame_info *frame_info) | |
| 44 | 44 | { |
| 45 | − /* | |
| 46 | − * synchronous unwinding (e.g. dump_stack) | |
| 47 | − * - uses current values of SP and friends | |
| 48 | − */ | |
| 49 | − if (tsk == NULL && regs == NULL) { | |
| 45 | + if (regs) { | |
| 46 | + /* | |
| 47 | + * Asynchronous unwinding of intr/exception | |
| 48 | + * - Just uses the pt_regs passed | |
| 49 | + */ | |
| 50 | + frame_info->task = tsk; | |
| 51 | + | |
| 52 | + frame_info->regs.r27 = regs->fp; | |
| 53 | + frame_info->regs.r28 = regs->sp; | |
| 54 | + frame_info->regs.r31 = regs->blink; | |
| 55 | + frame_info->regs.r63 = regs->ret; | |
| 56 | + frame_info->call_frame = 0; | |
| 57 | + } else if (tsk == NULL || tsk == current) { | |
| 58 | + /* | |
| 59 | + * synchronous unwinding (e.g. dump_stack) | |
| 60 | + * - uses current values of SP and friends | |
| 61 | + */ | |
| 50 | 62 | unsigned long fp, sp, blink, ret; |
| 51 | 63 | frame_info->task = current; |
| 52 | 64 | |
| @@ -63,13 +75,17 @@ static void seed_unwind_frame_info(struct task_struct *tsk, · 10 unmodified lines | ||
| 63 | 75 | frame_info->regs.r31 = blink; |
| 64 | 76 | frame_info->regs.r63 = ret; |
| 65 | 77 | frame_info->call_frame = 0; |
| 66 | − } else if (regs == NULL) { | |
| 78 | + } else { | |
| 67 | 79 | /* |
| 68 | − * Asynchronous unwinding of sleeping task | |
| 69 | − * - Gets SP etc from task's pt_regs (saved bottom of kernel | |
| 70 | − * mode stack of task) | |
| 80 | + * Asynchronous unwinding of a likely sleeping task | |
| 81 | + * - first ensure it is actually sleeping | |
| 82 | + * - if so, it will be in __switch_to, kernel mode SP of task | |
| 83 | + * is safe-kept and BLINK at a well known location in there | |
| 71 | 84 | */ |
| 72 | 85 | |
| 86 | + if (tsk->state == TASK_RUNNING) | |
| 87 | + return -1; | |
| 88 | + | |
| 73 | 89 | frame_info->task = tsk; |
| 74 | 90 | |
| 75 | 91 | frame_info->regs.r27 = TSK_K_FP(tsk); |
| @@ -90,19 +106,8 @@ static void seed_unwind_frame_info(struct task_struct *tsk, · 14 unmodified lines | ||
| 90 | 106 | frame_info->regs.r28 += 60; |
| 91 | 107 | frame_info->call_frame = 0; |
| 92 | 108 | |
| 93 | − } else { | |
| 94 | − /* | |
| 95 | − * Asynchronous unwinding of intr/exception | |
| 96 | − * - Just uses the pt_regs passed | |
| 97 | − */ | |
| 98 | − frame_info->task = tsk; | |
| 99 | − | |
| 100 | − frame_info->regs.r27 = regs->fp; | |
| 101 | − frame_info->regs.r28 = regs->sp; | |
| 102 | − frame_info->regs.r31 = regs->blink; | |
| 103 | − frame_info->regs.r63 = regs->ret; | |
| 104 | − frame_info->call_frame = 0; | |
| 105 | 109 | } |
| 110 | + return 0; | |
| 106 | 111 | } |
| 107 | 112 | |
| 108 | 113 | #endif |
| @@ -116,7 +121,8 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs, · 7 unmodified lines | ||
| 116 | 121 | unsigned int address; |
| 117 | 122 | struct unwind_frame_info frame_info; |
| 118 | 123 | |
| 119 | − seed_unwind_frame_info(tsk, regs, &frame_info); | |
| 124 | + if (seed_unwind_frame_info(tsk, regs, &frame_info)) | |
| 125 | + return 0; | |
| 120 | 126 | |
| 121 | 127 | while (1) { |
| 122 | 128 | address = UNW_PC(&frame_info); |
| @@ -30,14 +30,14 @@ · 29 unmodified lines | ||
| 30 | 30 | * -Changes related to MMU v2 (Rel 4.8) |
| 31 | 31 | * |
| 32 | 32 | * Vineetg: Aug 29th 2008 |
| 33 | − * -In TLB Flush operations (Metal Fix MMU) there is a explict command to | |
| 33 | + * -In TLB Flush operations (Metal Fix MMU) there is a explicit command to | |
| 34 | 34 | * flush Micro-TLBS. If TLB Index Reg is invalid prior to TLBIVUTLB cmd, |
| 35 | 35 | * it fails. Thus need to load it with ANY valid value before invoking |
| 36 | 36 | * TLBIVUTLB cmd |
| 37 | 37 | * |
| 38 | 38 | * Vineetg: Aug 21th 2008: |
| 39 | 39 | * -Reduced the duration of IRQ lockouts in TLB Flush routines |
| 40 | − * -Multiple copies of TLB erase code seperated into a "single" function | |
| 40 | + * -Multiple copies of TLB erase code separated into a "single" function | |
| 41 | 41 | * -In TLB Flush routines, interrupt disabling moved UP to retrieve ASID |
| 42 | 42 | * in interrupt-safe region. |
| 43 | 43 | * |
| @@ -66,7 +66,7 @@ · 22 unmodified lines | ||
| 66 | 66 | * |
| 67 | 67 | * Although J-TLB is 2 way set assoc, ARC700 caches J-TLB into uTLBS which has |
| 68 | 68 | * much higher associativity. u-D-TLB is 8 ways, u-I-TLB is 4 ways. |
| 69 | − * Given this, the thrasing problem should never happen because once the 3 | |
| 69 | + * Given this, the thrashing problem should never happen because once the 3 | |
| 70 | 70 | * J-TLB entries are created (even though 3rd will knock out one of the prev |
| 71 | 71 | * two), the u-D-TLB and u-I-TLB will have what is required to accomplish memcpy |
| 72 | 72 | * |
| @@ -127,7 +127,7 @@ static void utlb_invalidate(void) · 54 unmodified lines | ||
| 127 | 127 | * There was however an obscure hardware bug, where uTLB flush would |
| 128 | 128 | * fail when a prior probe for J-TLB (both totally unrelated) would |
| 129 | 129 | * return lkup err - because the entry didn't exist in MMU. |
| 130 | − * The Workround was to set Index reg with some valid value, prior to | |
| 130 | + * The Workaround was to set Index reg with some valid value, prior to | |
| 131 | 131 | * flush. This was fixed in MMU v3 |
| 132 | 132 | */ |
| 133 | 133 | unsigned int idx; |
| @@ -272,7 +272,7 @@ noinline void local_flush_tlb_all(void) · 138 unmodified lines | ||
| 272 | 272 | } |
| 273 | 273 | |
| 274 | 274 | /* |
| 275 | − * Flush the entrie MM for userland. The fastest way is to move to Next ASID | |
| 275 | + * Flush the entire MM for userland. The fastest way is to move to Next ASID | |
| 276 | 276 | */ |
| 277 | 277 | noinline void local_flush_tlb_mm(struct mm_struct *mm) |
| 278 | 278 | { |
| @@ -303,7 +303,7 @@ noinline void local_flush_tlb_mm(struct mm_struct *mm) · 24 unmodified lines | ||
| 303 | 303 | * Difference between this and Kernel Range Flush is |
| 304 | 304 | * -Here the fastest way (if range is too large) is to move to next ASID |
| 305 | 305 | * without doing any explicit Shootdown |
| 306 | − * -In case of kernel Flush, entry has to be shot down explictly | |
| 306 | + * -In case of kernel Flush, entry has to be shot down explicitly | |
| 307 | 307 | */ |
| 308 | 308 | void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
| 309 | 309 | unsigned long end) |
| @@ -620,7 +620,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, · 310 unmodified lines | ||
| 620 | 620 | * Super Page size is configurable in hardware (4K to 16M), but fixed once |
| 621 | 621 | * RTL builds. |
| 622 | 622 | * |
| 623 | − * The exact THP size a Linx configuration will support is a function of: | |
| 623 | + * The exact THP size a Linux configuration will support is a function of: | |
| 624 | 624 | * - MMU page size (typical 8K, RTL fixed) |
| 625 | 625 | * - software page walker address split between PGD:PTE:PFN (typical |
| 626 | 626 | * 11:8:13, but can be changed with 1 line) |
| @@ -698,7 +698,7 @@ void local_flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, · 71 unmodified lines | ||
| 698 | 698 | |
| 699 | 699 | #endif |
| 700 | 700 | |
| 701 | −/* Read the Cache Build Confuration Registers, Decode them and save into | |
| 701 | +/* Read the Cache Build Configuration Registers, Decode them and save into | |
| 702 | 702 | * the cpuinfo structure for later use. |
| 703 | 703 | * No Validation is done here, simply read/convert the BCRs |
| 704 | 704 | */ |
| @@ -803,13 +803,13 @@ void arc_mmu_init(void) · 98 unmodified lines | ||
| 803 | 803 | pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str))); |
| 804 | 804 | |
| 805 | 805 | /* |
| 806 | − * Can't be done in processor.h due to header include depenedencies | |
| 806 | + * Can't be done in processor.h due to header include dependencies | |
| 807 | 807 | */ |
| 808 | 808 | BUILD_BUG_ON(!IS_ALIGNED((CONFIG_ARC_KVADDR_SIZE << 20), PMD_SIZE)); |
| 809 | 809 | |
| 810 | 810 | /* |
| 811 | 811 | * stack top size sanity check, |
| 812 | − * Can't be done in processor.h due to header include depenedencies | |
| 812 | + * Can't be done in processor.h due to header include dependencies | |
| 813 | 813 | */ |
| 814 | 814 | BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE)); |
| 815 | 815 | |
| @@ -881,7 +881,7 @@ void arc_mmu_init(void) · 65 unmodified lines | ||
| 881 | 881 | * the duplicate one. |
| 882 | 882 | * -Knob to be verbose abt it.(TODO: hook them up to debugfs) |
| 883 | 883 | */ |
| 884 | −volatile int dup_pd_silent; /* Be slient abt it or complain (default) */ | |
| 884 | +volatile int dup_pd_silent; /* Be silent abt it or complain (default) */ | |
| 885 | 885 | |
| 886 | 886 | void do_tlb_overlap_fault(unsigned long cause, unsigned long address, |
| 887 | 887 | struct pt_regs *regs) |
| @@ -948,7 +948,7 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, · 60 unmodified lines | ||
| 948 | 948 | |
| 949 | 949 | /*********************************************************************** |
| 950 | 950 | * Diagnostic Routines |
| 951 | − * -Called from Low Level TLB Hanlders if things don;t look good | |
| 951 | + * -Called from Low Level TLB Handlers if things don;t look good | |
| 952 | 952 | **********************************************************************/ |
| 953 | 953 | |
| 954 | 954 | #ifdef CONFIG_ARC_DBG_TLB_PARANOIA |
| @@ -1472,6 +1472,9 @@ ENTRY(efi_enter_kernel) · 1471 unmodified lines | ||
| 1472 | 1472 | @ issued from HYP mode take us to the correct handler code. We |
| 1473 | 1473 | @ will disable the MMU before jumping to the kernel proper. |
| 1474 | 1474 | @ |
| 1475 | + ARM( bic r1, r1, #(1 << 30) ) @ clear HSCTLR.TE | |
| 1476 | + THUMB( orr r1, r1, #(1 << 30) ) @ set HSCTLR.TE | |
| 1477 | + mcr p15, 4, r1, c1, c0, 0 | |
| 1475 | 1478 | adr r0, __hyp_reentry_vectors |
| 1476 | 1479 | mcr p15, 4, r0, c12, c0, 0 @ set HYP vector base (HVBAR) |
| 1477 | 1480 | isb |
| @@ -521,7 +521,7 @@ · 520 unmodified lines | ||
| 521 | 521 | ranges = <0x0 0x100000 0x8000>; |
| 522 | 522 | |
| 523 | 523 | mac_sw: switch@0 { |
| 524 | − compatible = "ti,am4372-cpsw","ti,cpsw-switch"; | |
| 524 | + compatible = "ti,am4372-cpsw-switch", "ti,cpsw-switch"; | |
| 525 | 525 | reg = <0x0 0x4000>; |
| 526 | 526 | ranges = <0 0 0x4000>; |
| 527 | 527 | clocks = <&cpsw_125mhz_gclk>, <&dpll_clksel_mac_clk>; |
| @@ -32,8 +32,8 @@ · 31 unmodified lines | ||
| 32 | 32 | interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, |
| 33 | 33 | <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; |
| 34 | 34 | interrupt-names = "int0", "int1"; |
| 35 | − clocks = <&mcan_clk>, <&l3_iclk_div>; | |
| 36 | − clock-names = "cclk", "hclk"; | |
| 35 | + clocks = <&l3_iclk_div>, <&mcan_clk>; | |
| 36 | + clock-names = "hclk", "cclk"; | |
| 37 | 37 | bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>; |
| 38 | 38 | }; |
| 39 | 39 | }; |
| @@ -75,6 +75,8 @@ · 74 unmodified lines | ||
| 75 | 75 | #define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t)) |
| 76 | 76 | #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32)) |
| 77 | 77 | |
| 78 | +#define MAX_POSSIBLE_PHYSMEM_BITS 32 | |
| 79 | + | |
| 78 | 80 | /* |
| 79 | 81 | * PMD_SHIFT determines the size of the area a second-level page table can map |
| 80 | 82 | * PGDIR_SHIFT determines what a third-level page table entry can map |
| @@ -25,6 +25,8 @@ · 24 unmodified lines | ||
| 25 | 25 | #define PTE_HWTABLE_OFF (0) |
| 26 | 26 | #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u64)) |
| 27 | 27 | |
| 28 | +#define MAX_POSSIBLE_PHYSMEM_BITS 40 | |
| 29 | + | |
| 28 | 30 | /* |
| 29 | 31 | * PGDIR_SHIFT determines the size a top-level page table entry can map. |
| 30 | 32 | */ |
| @@ -7,7 +7,6 @@ config ARCH_OMAP2 · 6 unmodified lines | ||
| 7 | 7 | depends on ARCH_MULTI_V6 |
| 8 | 8 | select ARCH_OMAP2PLUS |
| 9 | 9 | select CPU_V6 |
| 10 | − select PM_GENERIC_DOMAINS if PM | |
| 11 | 10 | select SOC_HAS_OMAP2_SDRC |
| 12 | 11 | |
| 13 | 12 | config ARCH_OMAP3 |
| @@ -106,6 +105,8 @@ config ARCH_OMAP2PLUS · 92 unmodified lines | ||
| 106 | 105 | select OMAP_DM_TIMER |
| 107 | 106 | select OMAP_GPMC |
| 108 | 107 | select PINCTRL |
| 108 | + select PM_GENERIC_DOMAINS if PM | |
| 109 | + select PM_GENERIC_DOMAINS_OF if PM | |
| 109 | 110 | select RESET_CONTROLLER |
| 110 | 111 | select SOC_BUS |
| 111 | 112 | select TI_SYSC |
| @@ -175,8 +175,11 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, · 174 unmodified lines | ||
| 175 | 175 | if (mpuss_can_lose_context) { |
| 176 | 176 | error = cpu_cluster_pm_enter(); |
| 177 | 177 | if (error) { |
| 178 | − omap_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON); | |
| 179 | − goto cpu_cluster_pm_out; | |
| 178 | + index = 0; | |
| 179 | + cx = state_ptr + index; | |
| 180 | + pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); | |
| 181 | + omap_set_pwrdm_state(mpu_pd, cx->mpu_state); | |
| 182 | + mpuss_can_lose_context = 0; | |
| 180 | 183 | } |
| 181 | 184 | } |
| 182 | 185 | } |
| @@ -184,7 +187,6 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, · 1 unmodified line | ||
| 184 | 187 | omap4_enter_lowpower(dev->cpu, cx->cpu_state); |
| 185 | 188 | cpu_done[dev->cpu] = true; |
| 186 | 189 | |
| 187 | −cpu_cluster_pm_out: | |
| 188 | 190 | /* Wakeup CPU1 only if it is not offlined */ |
| 189 | 191 | if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { |
| 190 | 192 | |
| @@ -5,20 +5,20 @@ · 4 unmodified lines | ||
| 5 | 5 | usb { |
| 6 | 6 | compatible = "simple-bus"; |
| 7 | 7 | dma-ranges; |
| 8 | − #address-cells = <1>; | |
| 9 | − #size-cells = <1>; | |
| 10 | − ranges = <0x0 0x0 0x68500000 0x00400000>; | |
| 8 | + #address-cells = <2>; | |
| 9 | + #size-cells = <2>; | |
| 10 | + ranges = <0x0 0x0 0x0 0x68500000 0x0 0x00400000>; | |
| 11 | 11 | |
| 12 | 12 | usbphy0: usb-phy@0 { |
| 13 | 13 | compatible = "brcm,sr-usb-combo-phy"; |
| 14 | − reg = <0x00000000 0x100>; | |
| 14 | + reg = <0x0 0x00000000 0x0 0x100>; | |
| 15 | 15 | #phy-cells = <1>; |
| 16 | 16 | status = "disabled"; |
| 17 | 17 | }; |
| 18 | 18 | |
| 19 | 19 | xhci0: usb@1000 { |
| 20 | 20 | compatible = "generic-xhci"; |
| 21 | − reg = <0x00001000 0x1000>; | |
| 21 | + reg = <0x0 0x00001000 0x0 0x1000>; | |
| 22 | 22 | interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>; |
| 23 | 23 | phys = <&usbphy0 1>, <&usbphy0 0>; |
| 24 | 24 | phy-names = "phy0", "phy1"; |
| @@ -28,7 +28,7 @@ · 3 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | bdc0: usb@2000 { |
| 30 | 30 | compatible = "brcm,bdc-v0.16"; |
| 31 | − reg = <0x00002000 0x1000>; | |
| 31 | + reg = <0x0 0x00002000 0x0 0x1000>; | |
| 32 | 32 | interrupts = <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>; |
| 33 | 33 | phys = <&usbphy0 0>, <&usbphy0 1>; |
| 34 | 34 | phy-names = "phy0", "phy1"; |
| @@ -38,21 +38,21 @@ · 3 unmodified lines | ||
| 38 | 38 | |
| 39 | 39 | usbphy1: usb-phy@10000 { |
| 40 | 40 | compatible = "brcm,sr-usb-combo-phy"; |
| 41 | − reg = <0x00010000 0x100>; | |
| 41 | + reg = <0x0 0x00010000 0x0 0x100>; | |
| 42 | 42 | #phy-cells = <1>; |
| 43 | 43 | status = "disabled"; |
| 44 | 44 | }; |
| 45 | 45 | |
| 46 | 46 | usbphy2: usb-phy@20000 { |
| 47 | 47 | compatible = "brcm,sr-usb-hs-phy"; |
| 48 | − reg = <0x00020000 0x100>; | |
| 48 | + reg = <0x0 0x00020000 0x0 0x100>; | |
| 49 | 49 | #phy-cells = <0>; |
| 50 | 50 | status = "disabled"; |
| 51 | 51 | }; |
| 52 | 52 | |
| 53 | 53 | xhci1: usb@11000 { |
| 54 | 54 | compatible = "generic-xhci"; |
| 55 | − reg = <0x00011000 0x1000>; | |
| 55 | + reg = <0x0 0x00011000 0x0 0x1000>; | |
| 56 | 56 | interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>; |
| 57 | 57 | phys = <&usbphy1 1>, <&usbphy2>, <&usbphy1 0>; |
| 58 | 58 | phy-names = "phy0", "phy1", "phy2"; |
| @@ -62,7 +62,7 @@ · 3 unmodified lines | ||
| 62 | 62 | |
| 63 | 63 | bdc1: usb@21000 { |
| 64 | 64 | compatible = "brcm,bdc-v0.16"; |
| 65 | − reg = <0x00021000 0x1000>; | |
| 65 | + reg = <0x0 0x00021000 0x0 0x1000>; | |
| 66 | 66 | interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>; |
| 67 | 67 | phys = <&usbphy2>; |
| 68 | 68 | phy-names = "phy0"; |
| @@ -10,18 +10,6 @@ · 9 unmodified lines | ||
| 10 | 10 | model = "NVIDIA Jetson TX2 Developer Kit"; |
| 11 | 11 | compatible = "nvidia,p2771-0000", "nvidia,tegra186"; |
| 12 | 12 | |
| 13 | − aconnect { | |
| 14 | − status = "okay"; | |
| 15 | − | |
| 16 | − dma-controller@2930000 { | |
| 17 | − status = "okay"; | |
| 18 | − }; | |
| 19 | − | |
| 20 | − interrupt-controller@2a40000 { | |
| 21 | − status = "okay"; | |
| 22 | − }; | |
| 23 | − }; | |
| 24 | − | |
| 25 | 13 | i2c@3160000 { |
| 26 | 14 | power-monitor@42 { |
| 27 | 15 | compatible = "ti,ina3221"; |
| @@ -54,7 +54,7 @@ · 53 unmodified lines | ||
| 54 | 54 | status = "okay"; |
| 55 | 55 | }; |
| 56 | 56 | |
| 57 | − serial@c280000 { | |
| 57 | + serial@3100000 { | |
| 58 | 58 | status = "okay"; |
| 59 | 59 | }; |
| 60 | 60 | |
| @@ -1161,7 +1161,7 @@ · 1160 unmodified lines | ||
| 1161 | 1161 | |
| 1162 | 1162 | hsp_aon: hsp@c150000 { |
| 1163 | 1163 | compatible = "nvidia,tegra194-hsp", "nvidia,tegra186-hsp"; |
| 1164 | − reg = <0x0c150000 0xa0000>; | |
| 1164 | + reg = <0x0c150000 0x90000>; | |
| 1165 | 1165 | interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, |
| 1166 | 1166 | <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, |
| 1167 | 1167 | <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, |
| @@ -1663,16 +1663,6 @@ · 1662 unmodified lines | ||
| 1663 | 1663 | vin-supply = <&vdd_5v0_sys>; |
| 1664 | 1664 | }; |
| 1665 | 1665 | |
| 1666 | − vdd_usb_vbus_otg: regulator@11 { | |
| 1667 | − compatible = "regulator-fixed"; | |
| 1668 | − regulator-name = "USB_VBUS_EN0"; | |
| 1669 | − regulator-min-microvolt = <5000000>; | |
| 1670 | − regulator-max-microvolt = <5000000>; | |
| 1671 | − gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>; | |
| 1672 | − enable-active-high; | |
| 1673 | − vin-supply = <&vdd_5v0_sys>; | |
| 1674 | − }; | |
| 1675 | − | |
| 1676 | 1666 | vdd_hdmi: regulator@10 { |
| 1677 | 1667 | compatible = "regulator-fixed"; |
| 1678 | 1668 | regulator-name = "VDD_HDMI_5V0"; |
| @@ -1712,4 +1702,14 @@ · 33 unmodified lines | ||
| 1712 | 1702 | enable-active-high; |
| 1713 | 1703 | vin-supply = <&vdd_3v3_sys>; |
| 1714 | 1704 | }; |
| 1705 | + | |
| 1706 | + vdd_usb_vbus_otg: regulator@14 { | |
| 1707 | + compatible = "regulator-fixed"; | |
| 1708 | + regulator-name = "USB_VBUS_EN0"; | |
| 1709 | + regulator-min-microvolt = <5000000>; | |
| 1710 | + regulator-max-microvolt = <5000000>; | |
| 1711 | + gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>; | |
| 1712 | + enable-active-high; | |
| 1713 | + vin-supply = <&vdd_5v0_sys>; | |
| 1714 | + }; | |
| 1715 | 1715 | }; |
| @@ -8,7 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | compatible = "nvidia,tegra234-vdk", "nvidia,tegra234"; |
| 9 | 9 | |
| 10 | 10 | aliases { |
| 11 | − sdhci3 = "/cbb@0/sdhci@3460000"; | |
| 11 | + mmc3 = "/bus@0/mmc@3460000"; | |
| 12 | 12 | serial0 = &uarta; |
| 13 | 13 | }; |
| 14 | 14 | |
| @@ -17,12 +17,12 @@ · 2 unmodified lines | ||
| 17 | 17 | stdout-path = "serial0:115200n8"; |
| 18 | 18 | }; |
| 19 | 19 | |
| 20 | − cbb@0 { | |
| 20 | + bus@0 { | |
| 21 | 21 | serial@3100000 { |
| 22 | 22 | status = "okay"; |
| 23 | 23 | }; |
| 24 | 24 | |
| 25 | − sdhci@3460000 { | |
| 25 | + mmc@3460000 { | |
| 26 | 26 | status = "okay"; |
| 27 | 27 | bus-width = <8>; |
| 28 | 28 | non-removable; |
| @@ -179,22 +179,22 @@ · 178 unmodified lines | ||
| 179 | 179 | }; |
| 180 | 180 | |
| 181 | 181 | soc: soc { |
| 182 | − #address-cells = <1>; | |
| 183 | − #size-cells = <1>; | |
| 184 | − ranges = <0 0 0 0xffffffff>; | |
| 182 | + #address-cells = <2>; | |
| 183 | + #size-cells = <2>; | |
| 184 | + ranges = <0 0 0 0 0x0 0xffffffff>; | |
| 185 | 185 | dma-ranges; |
| 186 | 186 | compatible = "simple-bus"; |
| 187 | 187 | |
| 188 | 188 | prng: qrng@e1000 { |
| 189 | 189 | compatible = "qcom,prng-ee"; |
| 190 | − reg = <0xe3000 0x1000>; | |
| 190 | + reg = <0x0 0xe3000 0x0 0x1000>; | |
| 191 | 191 | clocks = <&gcc GCC_PRNG_AHB_CLK>; |
| 192 | 192 | clock-names = "core"; |
| 193 | 193 | }; |
| 194 | 194 | |
| 195 | 195 | cryptobam: dma@704000 { |
| 196 | 196 | compatible = "qcom,bam-v1.7.0"; |
| 197 | − reg = <0x00704000 0x20000>; | |
| 197 | + reg = <0x0 0x00704000 0x0 0x20000>; | |
| 198 | 198 | interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>; |
| 199 | 199 | clocks = <&gcc GCC_CRYPTO_AHB_CLK>; |
| 200 | 200 | clock-names = "bam_clk"; |
| @@ -206,7 +206,7 @@ · 5 unmodified lines | ||
| 206 | 206 | |
| 207 | 207 | crypto: crypto@73a000 { |
| 208 | 208 | compatible = "qcom,crypto-v5.1"; |
| 209 | − reg = <0x0073a000 0x6000>; | |
| 209 | + reg = <0x0 0x0073a000 0x0 0x6000>; | |
| 210 | 210 | clocks = <&gcc GCC_CRYPTO_AHB_CLK>, |
| 211 | 211 | <&gcc GCC_CRYPTO_AXI_CLK>, |
| 212 | 212 | <&gcc GCC_CRYPTO_CLK>; |
| @@ -217,7 +217,7 @@ · 4 unmodified lines | ||
| 217 | 217 | |
| 218 | 218 | tlmm: pinctrl@1000000 { |
| 219 | 219 | compatible = "qcom,ipq6018-pinctrl"; |
| 220 | − reg = <0x01000000 0x300000>; | |
| 220 | + reg = <0x0 0x01000000 0x0 0x300000>; | |
| 221 | 221 | interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; |
| 222 | 222 | gpio-controller; |
| 223 | 223 | #gpio-cells = <2>; |
| @@ -235,7 +235,7 @@ · 11 unmodified lines | ||
| 235 | 235 | |
| 236 | 236 | gcc: gcc@1800000 { |
| 237 | 237 | compatible = "qcom,gcc-ipq6018"; |
| 238 | − reg = <0x01800000 0x80000>; | |
| 238 | + reg = <0x0 0x01800000 0x0 0x80000>; | |
| 239 | 239 | clocks = <&xo>, <&sleep_clk>; |
| 240 | 240 | clock-names = "xo", "sleep_clk"; |
| 241 | 241 | #clock-cells = <1>; |
| @@ -244,17 +244,17 @@ · 2 unmodified lines | ||
| 244 | 244 | |
| 245 | 245 | tcsr_mutex_regs: syscon@1905000 { |
| 246 | 246 | compatible = "syscon"; |
| 247 | − reg = <0x01905000 0x8000>; | |
| 247 | + reg = <0x0 0x01905000 0x0 0x8000>; | |
| 248 | 248 | }; |
| 249 | 249 | |
| 250 | 250 | tcsr_q6: syscon@1945000 { |
| 251 | 251 | compatible = "syscon"; |
| 252 | − reg = <0x01945000 0xe000>; | |
| 252 | + reg = <0x0 0x01945000 0x0 0xe000>; | |
| 253 | 253 | }; |
| 254 | 254 | |
| 255 | 255 | blsp_dma: dma@7884000 { |
| 256 | 256 | compatible = "qcom,bam-v1.7.0"; |
| 257 | − reg = <0x07884000 0x2b000>; | |
| 257 | + reg = <0x0 0x07884000 0x0 0x2b000>; | |
| 258 | 258 | interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>; |
| 259 | 259 | clocks = <&gcc GCC_BLSP1_AHB_CLK>; |
| 260 | 260 | clock-names = "bam_clk"; |
| @@ -264,7 +264,7 @@ · 3 unmodified lines | ||
| 264 | 264 | |
| 265 | 265 | blsp1_uart3: serial@78b1000 { |
| 266 | 266 | compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; |
| 267 | − reg = <0x078b1000 0x200>; | |
| 267 | + reg = <0x0 0x078b1000 0x0 0x200>; | |
| 268 | 268 | interrupts = <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>; |
| 269 | 269 | clocks = <&gcc GCC_BLSP1_UART3_APPS_CLK>, |
| 270 | 270 | <&gcc GCC_BLSP1_AHB_CLK>; |
| @@ -276,7 +276,7 @@ · 5 unmodified lines | ||
| 276 | 276 | compatible = "qcom,spi-qup-v2.2.1"; |
| 277 | 277 | #address-cells = <1>; |
| 278 | 278 | #size-cells = <0>; |
| 279 | − reg = <0x078b5000 0x600>; | |
| 279 | + reg = <0x0 0x078b5000 0x0 0x600>; | |
| 280 | 280 | interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; |
| 281 | 281 | spi-max-frequency = <50000000>; |
| 282 | 282 | clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, |
| @@ -291,7 +291,7 @@ · 8 unmodified lines | ||
| 291 | 291 | compatible = "qcom,spi-qup-v2.2.1"; |
| 292 | 292 | #address-cells = <1>; |
| 293 | 293 | #size-cells = <0>; |
| 294 | − reg = <0x078b6000 0x600>; | |
| 294 | + reg = <0x0 0x078b6000 0x0 0x600>; | |
| 295 | 295 | interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; |
| 296 | 296 | spi-max-frequency = <50000000>; |
| 297 | 297 | clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>, |
| @@ -306,7 +306,7 @@ · 8 unmodified lines | ||
| 306 | 306 | compatible = "qcom,i2c-qup-v2.2.1"; |
| 307 | 307 | #address-cells = <1>; |
| 308 | 308 | #size-cells = <0>; |
| 309 | − reg = <0x078b6000 0x600>; | |
| 309 | + reg = <0x0 0x078b6000 0x0 0x600>; | |
| 310 | 310 | interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; |
| 311 | 311 | clocks = <&gcc GCC_BLSP1_AHB_CLK>, |
| 312 | 312 | <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; |
| @@ -321,7 +321,7 @@ · 8 unmodified lines | ||
| 321 | 321 | compatible = "qcom,i2c-qup-v2.2.1"; |
| 322 | 322 | #address-cells = <1>; |
| 323 | 323 | #size-cells = <0>; |
| 324 | − reg = <0x078b7000 0x600>; | |
| 324 | + reg = <0x0 0x078b7000 0x0 0x600>; | |
| 325 | 325 | interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>; |
| 326 | 326 | clocks = <&gcc GCC_BLSP1_AHB_CLK>, |
| 327 | 327 | <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>; |
| @@ -336,24 +336,24 @@ · 8 unmodified lines | ||
| 336 | 336 | compatible = "qcom,msm-qgic2"; |
| 337 | 337 | interrupt-controller; |
| 338 | 338 | #interrupt-cells = <0x3>; |
| 339 | − reg = <0x0b000000 0x1000>, /*GICD*/ | |
| 340 | − <0x0b002000 0x1000>, /*GICC*/ | |
| 341 | − <0x0b001000 0x1000>, /*GICH*/ | |
| 342 | − <0x0b004000 0x1000>; /*GICV*/ | |
| 339 | + reg = <0x0 0x0b000000 0x0 0x1000>, /*GICD*/ | |
| 340 | + <0x0 0x0b002000 0x0 0x1000>, /*GICC*/ | |
| 341 | + <0x0 0x0b001000 0x0 0x1000>, /*GICH*/ | |
| 342 | + <0x0 0x0b004000 0x0 0x1000>; /*GICV*/ | |
| 343 | 343 | interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; |
| 344 | 344 | }; |
| 345 | 345 | |
| 346 | 346 | watchdog@b017000 { |
| 347 | 347 | compatible = "qcom,kpss-wdt"; |
| 348 | 348 | interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>; |
| 349 | − reg = <0x0b017000 0x40>; | |
| 349 | + reg = <0x0 0x0b017000 0x0 0x40>; | |
| 350 | 350 | clocks = <&sleep_clk>; |
| 351 | 351 | timeout-sec = <10>; |
| 352 | 352 | }; |
| 353 | 353 | |
| 354 | 354 | apcs_glb: mailbox@b111000 { |
| 355 | 355 | compatible = "qcom,ipq6018-apcs-apps-global"; |
| 356 | − reg = <0x0b111000 0x1000>; | |
| 356 | + reg = <0x0 0x0b111000 0x0 0x1000>; | |
| 357 | 357 | #clock-cells = <1>; |
| 358 | 358 | clocks = <&a53pll>, <&xo>; |
| 359 | 359 | clock-names = "pll", "xo"; |
| @@ -362,7 +362,7 @@ · 2 unmodified lines | ||
| 362 | 362 | |
| 363 | 363 | a53pll: clock@b116000 { |
| 364 | 364 | compatible = "qcom,ipq6018-a53pll"; |
| 365 | − reg = <0x0b116000 0x40>; | |
| 365 | + reg = <0x0 0x0b116000 0x0 0x40>; | |
| 366 | 366 | #clock-cells = <0>; |
| 367 | 367 | clocks = <&xo>; |
| 368 | 368 | clock-names = "xo"; |
| @@ -377,68 +377,68 @@ · 8 unmodified lines | ||
| 377 | 377 | }; |
| 378 | 378 | |
| 379 | 379 | timer@b120000 { |
| 380 | − #address-cells = <1>; | |
| 381 | − #size-cells = <1>; | |
| 380 | + #address-cells = <2>; | |
| 381 | + #size-cells = <2>; | |
| 382 | 382 | ranges; |
| 383 | 383 | compatible = "arm,armv7-timer-mem"; |
| 384 | − reg = <0x0b120000 0x1000>; | |
| 384 | + reg = <0x0 0x0b120000 0x0 0x1000>; | |
| 385 | 385 | clock-frequency = <19200000>; |
| 386 | 386 | |
| 387 | 387 | frame@b120000 { |
| 388 | 388 | frame-number = <0>; |
| 389 | 389 | interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, |
| 390 | 390 | <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; |
| 391 | − reg = <0x0b121000 0x1000>, | |
| 392 | − <0x0b122000 0x1000>; | |
| 391 | + reg = <0x0 0x0b121000 0x0 0x1000>, | |
| 392 | + <0x0 0x0b122000 0x0 0x1000>; | |
| 393 | 393 | }; |
| 394 | 394 | |
| 395 | 395 | frame@b123000 { |
| 396 | 396 | frame-number = <1>; |
| 397 | 397 | interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; |
| 398 | − reg = <0xb123000 0x1000>; | |
| 398 | + reg = <0x0 0xb123000 0x0 0x1000>; | |
| 399 | 399 | status = "disabled"; |
| 400 | 400 | }; |
| 401 | 401 | |
| 402 | 402 | frame@b124000 { |
| 403 | 403 | frame-number = <2>; |
| 404 | 404 | interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; |
| 405 | − reg = <0x0b124000 0x1000>; | |
| 405 | + reg = <0x0 0x0b124000 0x0 0x1000>; | |
| 406 | 406 | status = "disabled"; |
| 407 | 407 | }; |
| 408 | 408 | |
| 409 | 409 | frame@b125000 { |
| 410 | 410 | frame-number = <3>; |
| 411 | 411 | interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; |
| 412 | − reg = <0x0b125000 0x1000>; | |
| 412 | + reg = <0x0 0x0b125000 0x0 0x1000>; | |
| 413 | 413 | status = "disabled"; |
| 414 | 414 | }; |
| 415 | 415 | |
| 416 | 416 | frame@b126000 { |
| 417 | 417 | frame-number = <4>; |
| 418 | 418 | interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; |
| 419 | − reg = <0x0b126000 0x1000>; | |
| 419 | + reg = <0x0 0x0b126000 0x0 0x1000>; | |
| 420 | 420 | status = "disabled"; |
| 421 | 421 | }; |
| 422 | 422 | |
| 423 | 423 | frame@b127000 { |
| 424 | 424 | frame-number = <5>; |
| 425 | 425 | interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; |
| 426 | − reg = <0x0b127000 0x1000>; | |
| 426 | + reg = <0x0 0x0b127000 0x0 0x1000>; | |
| 427 | 427 | status = "disabled"; |
| 428 | 428 | }; |
| 429 | 429 | |
| 430 | 430 | frame@b128000 { |
| 431 | 431 | frame-number = <6>; |
| 432 | 432 | interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; |
| 433 | − reg = <0x0b128000 0x1000>; | |
| 433 | + reg = <0x0 0x0b128000 0x0 0x1000>; | |
| 434 | 434 | status = "disabled"; |
| 435 | 435 | }; |
| 436 | 436 | }; |
| 437 | 437 | |
| 438 | 438 | q6v5_wcss: remoteproc@cd00000 { |
| 439 | 439 | compatible = "qcom,ipq8074-wcss-pil"; |
| 440 | − reg = <0x0cd00000 0x4040>, | |
| 441 | − <0x004ab000 0x20>; | |
| 440 | + reg = <0x0 0x0cd00000 0x0 0x4040>, | |
| 441 | + <0x0 0x004ab000 0x0 0x20>; | |
| 442 | 442 | reg-names = "qdsp6", |
| 443 | 443 | "rmb"; |
| 444 | 444 | interrupts-extended = <&intc GIC_SPI 325 IRQ_TYPE_EDGE_RISING>, |
| @@ -243,7 +243,6 @@ · 242 unmodified lines | ||
| 243 | 243 | interrupts = <RK_PB2 IRQ_TYPE_LEVEL_LOW>; |
| 244 | 244 | pinctrl-names = "default"; |
| 245 | 245 | pinctrl-0 = <&pmic_int>; |
| 246 | − rockchip,system-power-controller; | |
| 247 | 246 | wakeup-source; |
| 248 | 247 | #clock-cells = <1>; |
| 249 | 248 | clock-output-names = "rk808-clkout1", "xin32k"; |
| @@ -20,7 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | gmac_clk: gmac-clock { |
| 21 | 21 | compatible = "fixed-clock"; |
| 22 | 22 | clock-frequency = <125000000>; |
| 23 | − clock-output-names = "gmac_clk"; | |
| 23 | + clock-output-names = "gmac_clkin"; | |
| 24 | 24 | #clock-cells = <0>; |
| 25 | 25 | }; |
| 26 | 26 | |
| @@ -74,14 +74,14 @@ · 73 unmodified lines | ||
| 74 | 74 | label = "red:diy"; |
| 75 | 75 | gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; |
| 76 | 76 | default-state = "off"; |
| 77 | − linux,default-trigger = "mmc1"; | |
| 77 | + linux,default-trigger = "mmc2"; | |
| 78 | 78 | }; |
| 79 | 79 | |
| 80 | 80 | yellow_led: led-2 { |
| 81 | 81 | label = "yellow:yellow-led"; |
| 82 | 82 | gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; |
| 83 | 83 | default-state = "off"; |
| 84 | − linux,default-trigger = "mmc0"; | |
| 84 | + linux,default-trigger = "mmc1"; | |
| 85 | 85 | }; |
| 86 | 86 | }; |
| 87 | 87 | |
| @@ -29,6 +29,9 @@ · 28 unmodified lines | ||
| 29 | 29 | i2c6 = &i2c6; |
| 30 | 30 | i2c7 = &i2c7; |
| 31 | 31 | i2c8 = &i2c8; |
| 32 | + mmc0 = &sdio0; | |
| 33 | + mmc1 = &sdmmc; | |
| 34 | + mmc2 = &sdhci; | |
| 32 | 35 | serial0 = &uart0; |
| 33 | 36 | serial1 = &uart1; |
| 34 | 37 | serial2 = &uart2; |
| @@ -115,8 +115,6 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; · 114 unmodified lines | ||
| 115 | 115 | #define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID)) |
| 116 | 116 | #define pte_valid_not_user(pte) \ |
| 117 | 117 | ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID) |
| 118 | −#define pte_valid_young(pte) \ | |
| 119 | − ((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF)) | |
| 120 | 118 | #define pte_valid_user(pte) \ |
| 121 | 119 | ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) |
| 122 | 120 | |
| @@ -124,9 +122,12 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; · 1 unmodified line | ||
| 124 | 122 | * Could the pte be present in the TLB? We must check mm_tlb_flush_pending |
| 125 | 123 | * so that we don't erroneously return false for pages that have been |
| 126 | 124 | * remapped as PROT_NONE but are yet to be flushed from the TLB. |
| 125 | + * Note that we can't make any assumptions based on the state of the access | |
| 126 | + * flag, since ptep_clear_flush_young() elides a DSB when invalidating the | |
| 127 | + * TLB. | |
| 127 | 128 | */ |
| 128 | 129 | #define pte_accessible(mm, pte) \ |
| 129 | − (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid_young(pte)) | |
| 130 | + (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte)) | |
| 130 | 131 | |
| 131 | 132 | /* |
| 132 | 133 | * p??_access_permitted() is true for valid user mappings (subject to the |
| @@ -164,13 +165,6 @@ static inline pmd_t set_pmd_bit(pmd_t pmd, pgprot_t prot) · 31 unmodified lines | ||
| 164 | 165 | return pmd; |
| 165 | 166 | } |
| 166 | 167 | |
| 167 | −static inline pte_t pte_wrprotect(pte_t pte) | |
| 168 | −{ | |
| 169 | − pte = clear_pte_bit(pte, __pgprot(PTE_WRITE)); | |
| 170 | − pte = set_pte_bit(pte, __pgprot(PTE_RDONLY)); | |
| 171 | − return pte; | |
| 172 | −} | |
| 173 | − | |
| 174 | 168 | static inline pte_t pte_mkwrite(pte_t pte) |
| 175 | 169 | { |
| 176 | 170 | pte = set_pte_bit(pte, __pgprot(PTE_WRITE)); |
| @@ -196,6 +190,20 @@ static inline pte_t pte_mkdirty(pte_t pte) · 19 unmodified lines | ||
| 196 | 190 | return pte; |
| 197 | 191 | } |
| 198 | 192 | |
| 193 | +static inline pte_t pte_wrprotect(pte_t pte) | |
| 194 | +{ | |
| 195 | + /* | |
| 196 | + * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY | |
| 197 | + * clear), set the PTE_DIRTY bit. | |
| 198 | + */ | |
| 199 | + if (pte_hw_dirty(pte)) | |
| 200 | + pte = pte_mkdirty(pte); | |
| 201 | + | |
| 202 | + pte = clear_pte_bit(pte, __pgprot(PTE_WRITE)); | |
| 203 | + pte = set_pte_bit(pte, __pgprot(PTE_RDONLY)); | |
| 204 | + return pte; | |
| 205 | +} | |
| 206 | + | |
| 199 | 207 | static inline pte_t pte_mkold(pte_t pte) |
| 200 | 208 | { |
| 201 | 209 | return clear_pte_bit(pte, __pgprot(PTE_AF)); |
| @@ -845,12 +853,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres · 643 unmodified lines | ||
| 845 | 853 | pte = READ_ONCE(*ptep); |
| 846 | 854 | do { |
| 847 | 855 | old_pte = pte; |
| 848 | − /* | |
| 849 | − * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY | |
| 850 | − * clear), set the PTE_DIRTY bit. | |
| 851 | − */ | |
| 852 | − if (pte_hw_dirty(pte)) | |
| 853 | − pte = pte_mkdirty(pte); | |
| 854 | 856 | pte = pte_wrprotect(pte); |
| 855 | 857 | pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep), |
| 856 | 858 | pte_val(old_pte), pte_val(pte)); |
| @@ -7,6 +7,8 @@ · 6 unmodified lines | ||
| 7 | 7 | #ifndef _ARM_PROBES_H |
| 8 | 8 | #define _ARM_PROBES_H |
| 9 | 9 | |
| 10 | +#include <asm/insn.h> | |
| 11 | + | |
| 10 | 12 | typedef u32 probe_opcode_t; |
| 11 | 13 | typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *); |
| 12 | 14 | |
| @@ -13,6 +13,11 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | SECTIONS { |
| 15 | 15 | HYP_SECTION(.text) |
| 16 | + /* | |
| 17 | + * .hyp..data..percpu needs to be page aligned to maintain the same | |
| 18 | + * alignment for when linking into vmlinux. | |
| 19 | + */ | |
| 20 | + . = ALIGN(PAGE_SIZE); | |
| 16 | 21 | HYP_SECTION_NAME(.data..percpu) : { |
| 17 | 22 | PERCPU_INPUT(L1_CACHE_BYTES) |
| 18 | 23 | } |
| @@ -273,6 +273,23 @@ static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu, · 272 unmodified lines | ||
| 273 | 273 | return extract_bytes(value, addr & 7, len); |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | +static unsigned long vgic_uaccess_read_v3r_typer(struct kvm_vcpu *vcpu, | |
| 277 | + gpa_t addr, unsigned int len) | |
| 278 | +{ | |
| 279 | + unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu); | |
| 280 | + int target_vcpu_id = vcpu->vcpu_id; | |
| 281 | + u64 value; | |
| 282 | + | |
| 283 | + value = (u64)(mpidr & GENMASK(23, 0)) << 32; | |
| 284 | + value |= ((target_vcpu_id & 0xffff) << 8); | |
| 285 | + | |
| 286 | + if (vgic_has_its(vcpu->kvm)) | |
| 287 | + value |= GICR_TYPER_PLPIS; | |
| 288 | + | |
| 289 | + /* reporting of the Last bit is not supported for userspace */ | |
| 290 | + return extract_bytes(value, addr & 7, len); | |
| 291 | +} | |
| 292 | + | |
| 276 | 293 | static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu, |
| 277 | 294 | gpa_t addr, unsigned int len) |
| 278 | 295 | { |
| @@ -593,8 +610,9 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = { · 314 unmodified lines | ||
| 593 | 610 | REGISTER_DESC_WITH_LENGTH(GICR_IIDR, |
| 594 | 611 | vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4, |
| 595 | 612 | VGIC_ACCESS_32bit), |
| 596 | − REGISTER_DESC_WITH_LENGTH(GICR_TYPER, | |
| 597 | − vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8, | |
| 613 | + REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_TYPER, | |
| 614 | + vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, | |
| 615 | + vgic_uaccess_read_v3r_typer, vgic_mmio_uaccess_write_wi, 8, | |
| 598 | 616 | VGIC_ACCESS_64bit | VGIC_ACCESS_32bit), |
| 599 | 617 | REGISTER_DESC_WITH_LENGTH(GICR_WAKER, |
| 600 | 618 | vgic_mmio_read_raz, vgic_mmio_write_wi, 4, |
| @@ -18,4 +18,10 @@ · 17 unmodified lines | ||
| 18 | 18 | #endif |
| 19 | 19 | |
| 20 | 20 | #endif /* CONFIG_SPARSEMEM */ |
| 21 | + | |
| 22 | +#ifdef CONFIG_MEMORY_HOTPLUG | |
| 23 | +int memory_add_physaddr_to_nid(u64 addr); | |
| 24 | +#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid | |
| 25 | +#endif | |
| 26 | + | |
| 21 | 27 | #endif /* _ASM_IA64_SPARSEMEM_H */ |
| @@ -154,6 +154,7 @@ static inline void pmd_clear(pmd_t *pmdp) · 153 unmodified lines | ||
| 154 | 154 | |
| 155 | 155 | #if defined(CONFIG_XPA) |
| 156 | 156 | |
| 157 | +#define MAX_POSSIBLE_PHYSMEM_BITS 40 | |
| 157 | 158 | #define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT)) |
| 158 | 159 | static inline pte_t |
| 159 | 160 | pfn_pte(unsigned long pfn, pgprot_t prot) |
| @@ -169,6 +170,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot) · 9 unmodified lines | ||
| 169 | 170 | |
| 170 | 171 | #elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) |
| 171 | 172 | |
| 173 | +#define MAX_POSSIBLE_PHYSMEM_BITS 36 | |
| 172 | 174 | #define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) |
| 173 | 175 | |
| 174 | 176 | static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) |
| @@ -183,6 +185,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) · 8 unmodified lines | ||
| 183 | 185 | |
| 184 | 186 | #else |
| 185 | 187 | |
| 188 | +#define MAX_POSSIBLE_PHYSMEM_BITS 32 | |
| 186 | 189 | #ifdef CONFIG_CPU_VR41XX |
| 187 | 190 | #define pte_pfn(x) ((unsigned long)((x).pte >> (PAGE_SHIFT + 2))) |
| 188 | 191 | #define pfn_pte(pfn, prot) __pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot)) |
| @@ -248,7 +248,6 @@ KBUILD_CFLAGS += $(call cc-option,-mno-string) · 247 unmodified lines | ||
| 248 | 248 | cpu-as-$(CONFIG_40x) += -Wa,-m405 |
| 249 | 249 | cpu-as-$(CONFIG_44x) += -Wa,-m440 |
| 250 | 250 | cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec) |
| 251 | −cpu-as-$(CONFIG_E200) += -Wa,-me200 | |
| 252 | 251 | cpu-as-$(CONFIG_E500) += -Wa,-me500 |
| 253 | 252 | |
| 254 | 253 | # When using '-many -mpower4' gas will first try and find a matching power4 |
| @@ -36,8 +36,10 @@ static inline bool pte_user(pte_t pte) · 35 unmodified lines | ||
| 36 | 36 | */ |
| 37 | 37 | #ifdef CONFIG_PTE_64BIT |
| 38 | 38 | #define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) |
| 39 | +#define MAX_POSSIBLE_PHYSMEM_BITS 36 | |
| 39 | 40 | #else |
| 40 | 41 | #define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) |
| 42 | +#define MAX_POSSIBLE_PHYSMEM_BITS 32 | |
| 41 | 43 | #endif |
| 42 | 44 | |
| 43 | 45 | /* |
| @@ -63,6 +63,8 @@ · 62 unmodified lines | ||
| 63 | 63 | |
| 64 | 64 | #else /* !__ASSEMBLY__ */ |
| 65 | 65 | |
| 66 | +#include <linux/jump_label.h> | |
| 67 | + | |
| 66 | 68 | DECLARE_STATIC_KEY_FALSE(uaccess_flush_key); |
| 67 | 69 | |
| 68 | 70 | #ifdef CONFIG_PPC_KUAP |
| @@ -46,5 +46,10 @@ u64 memory_hotplug_max(void); · 45 unmodified lines | ||
| 46 | 46 | #define __HAVE_ARCH_RESERVED_KERNEL_PAGES |
| 47 | 47 | #endif |
| 48 | 48 | |
| 49 | +#ifdef CONFIG_MEMORY_HOTPLUG | |
| 50 | +extern int create_section_mapping(unsigned long start, unsigned long end, | |
| 51 | + int nid, pgprot_t prot); | |
| 52 | +#endif | |
| 53 | + | |
| 49 | 54 | #endif /* __KERNEL__ */ |
| 50 | 55 | #endif /* _ASM_MMZONE_H_ */ |
| @@ -153,8 +153,10 @@ int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); · 152 unmodified lines | ||
| 153 | 153 | */ |
| 154 | 154 | #if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) |
| 155 | 155 | #define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) |
| 156 | +#define MAX_POSSIBLE_PHYSMEM_BITS 36 | |
| 156 | 157 | #else |
| 157 | 158 | #define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) |
| 159 | +#define MAX_POSSIBLE_PHYSMEM_BITS 32 | |
| 158 | 160 | #endif |
| 159 | 161 | |
| 160 | 162 | /* |
| @@ -13,9 +13,9 @@ · 12 unmodified lines | ||
| 13 | 13 | #endif /* CONFIG_SPARSEMEM */ |
| 14 | 14 | |
| 15 | 15 | #ifdef CONFIG_MEMORY_HOTPLUG |
| 16 | −extern int create_section_mapping(unsigned long start, unsigned long end, | |
| 17 | − int nid, pgprot_t prot); | |
| 18 | 16 | extern int remove_section_mapping(unsigned long start, unsigned long end); |
| 17 | +extern int memory_add_physaddr_to_nid(u64 start); | |
| 18 | +#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid | |
| 19 | 19 | |
| 20 | 20 | #ifdef CONFIG_NUMA |
| 21 | 21 | extern int hot_add_scn_to_nid(unsigned long scn_addr); |
| @@ -26,6 +26,5 @@ static inline int hot_add_scn_to_nid(unsigned long scn_addr) · 4 unmodified lines | ||
| 26 | 26 | } |
| 27 | 27 | #endif /* CONFIG_NUMA */ |
| 28 | 28 | #endif /* CONFIG_MEMORY_HOTPLUG */ |
| 29 | − | |
| 30 | 29 | #endif /* __KERNEL__ */ |
| 31 | 30 | #endif /* _ASM_POWERPC_SPARSEMEM_H */ |
| @@ -1000,8 +1000,6 @@ TRAMP_REAL_BEGIN(system_reset_idle_wake) · 999 unmodified lines | ||
| 1000 | 1000 | * Vectors for the FWNMI option. Share common code. |
| 1001 | 1001 | */ |
| 1002 | 1002 | TRAMP_REAL_BEGIN(system_reset_fwnmi) |
| 1003 | − /* XXX: fwnmi guest could run a nested/PR guest, so why no test? */ | |
| 1004 | − __IKVM_REAL(system_reset)=0 | |
| 1005 | 1003 | GEN_INT_ENTRY system_reset, virt=0 |
| 1006 | 1004 | |
| 1007 | 1005 | #endif /* CONFIG_PPC_PSERIES */ |
| @@ -1412,6 +1410,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) · 404 unmodified lines | ||
| 1412 | 1410 | * If none is found, do a Linux page fault. Linux page faults can happen in |
| 1413 | 1411 | * kernel mode due to user copy operations of course. |
| 1414 | 1412 | * |
| 1413 | + * KVM: The KVM HDSI handler may perform a load with MSR[DR]=1 in guest | |
| 1414 | + * MMU context, which may cause a DSI in the host, which must go to the | |
| 1415 | + * KVM handler. MSR[IR] is not enabled, so the real-mode handler will | |
| 1416 | + * always be used regardless of AIL setting. | |
| 1417 | + * | |
| 1415 | 1418 | * - Radix MMU |
| 1416 | 1419 | * The hardware loads from the Linux page table directly, so a fault goes |
| 1417 | 1420 | * immediately to Linux page fault. |
| @@ -1422,10 +1425,8 @@ INT_DEFINE_BEGIN(data_access) · 4 unmodified lines | ||
| 1422 | 1425 | IVEC=0x300 |
| 1423 | 1426 | IDAR=1 |
| 1424 | 1427 | IDSISR=1 |
| 1425 | −#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | |
| 1426 | 1428 | IKVM_SKIP=1 |
| 1427 | 1429 | IKVM_REAL=1 |
| 1428 | −#endif | |
| 1429 | 1430 | INT_DEFINE_END(data_access) |
| 1430 | 1431 | |
| 1431 | 1432 | EXC_REAL_BEGIN(data_access, 0x300, 0x80) |
| @@ -1464,6 +1465,8 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) · 32 unmodified lines | ||
| 1464 | 1465 | * ppc64_bolted_size (first segment). The kernel handler must avoid stomping |
| 1465 | 1466 | * on user-handler data structures. |
| 1466 | 1467 | * |
| 1468 | + * KVM: Same as 0x300, DSLB must test for KVM guest. | |
| 1469 | + * | |
| 1467 | 1470 | * A dedicated save area EXSLB is used (XXX: but it actually need not be |
| 1468 | 1471 | * these days, we could use EXGEN). |
| 1469 | 1472 | */ |
| @@ -1472,10 +1475,8 @@ INT_DEFINE_BEGIN(data_access_slb) · 2 unmodified lines | ||
| 1472 | 1475 | IAREA=PACA_EXSLB |
| 1473 | 1476 | IRECONCILE=0 |
| 1474 | 1477 | IDAR=1 |
| 1475 | −#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | |
| 1476 | 1478 | IKVM_SKIP=1 |
| 1477 | 1479 | IKVM_REAL=1 |
| 1478 | −#endif | |
| 1479 | 1480 | INT_DEFINE_END(data_access_slb) |
| 1480 | 1481 | |
| 1481 | 1482 | EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80) |
| @@ -156,6 +156,7 @@ __after_mmu_off: · 155 unmodified lines | ||
| 156 | 156 | bl initial_bats |
| 157 | 157 | bl load_segment_registers |
| 158 | 158 | BEGIN_MMU_FTR_SECTION |
| 159 | + bl reloc_offset | |
| 159 | 160 | bl early_hash_table |
| 160 | 161 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE) |
| 161 | 162 | #if defined(CONFIG_BOOTX_TEXT) |
| @@ -920,7 +921,7 @@ early_hash_table: · 758 unmodified lines | ||
| 920 | 921 | ori r6, r6, 3 /* 256kB table */ |
| 921 | 922 | mtspr SPRN_SDR1, r6 |
| 922 | 923 | lis r6, early_hash@h |
| 923 | − lis r3, Hash@ha | |
| 924 | + addis r3, r3, Hash@ha | |
| 924 | 925 | stw r6, Hash@l(r3) |
| 925 | 926 | blr |
| 926 | 927 | |
| @@ -251,6 +251,13 @@ static vm_fault_t xive_native_esb_fault(struct vm_fault *vmf) · 250 unmodified lines | ||
| 251 | 251 | } |
| 252 | 252 | |
| 253 | 253 | state = &sb->irq_state[src]; |
| 254 | + | |
| 255 | + /* Some sanity checking */ | |
| 256 | + if (!state->valid) { | |
| 257 | + pr_devel("%s: source %lx invalid !\n", __func__, irq); | |
| 258 | + return VM_FAULT_SIGBUS; | |
| 259 | + } | |
| 260 | + | |
| 254 | 261 | kvmppc_xive_select_irq(state, &hw_num, &xd); |
| 255 | 262 | |
| 256 | 263 | arch_spin_lock(&sb->lock); |
| @@ -50,6 +50,7 @@ · 49 unmodified lines | ||
| 50 | 50 | #include <asm/rtas.h> |
| 51 | 51 | #include <asm/kasan.h> |
| 52 | 52 | #include <asm/svm.h> |
| 53 | +#include <asm/mmzone.h> | |
| 53 | 54 | |
| 54 | 55 | #include <mm/mmu_decl.h> |
| 55 | 56 | |
| @@ -14,4 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) |
| 15 | 15 | #define PGDIR_MASK (~(PGDIR_SIZE - 1)) |
| 16 | 16 | |
| 17 | +#define MAX_POSSIBLE_PHYSMEM_BITS 34 | |
| 18 | + | |
| 17 | 19 | #endif /* _ASM_RISCV_PGTABLE_32_H */ |
| @@ -53,11 +53,11 @@ int main(void) · 52 unmodified lines | ||
| 53 | 53 | /* stack_frame offsets */ |
| 54 | 54 | OFFSET(__SF_BACKCHAIN, stack_frame, back_chain); |
| 55 | 55 | OFFSET(__SF_GPRS, stack_frame, gprs); |
| 56 | − OFFSET(__SF_EMPTY, stack_frame, empty1); | |
| 57 | − OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[0]); | |
| 58 | − OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[1]); | |
| 59 | − OFFSET(__SF_SIE_REASON, stack_frame, empty1[2]); | |
| 60 | − OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[3]); | |
| 56 | + OFFSET(__SF_EMPTY, stack_frame, empty1[0]); | |
| 57 | + OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[1]); | |
| 58 | + OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[2]); | |
| 59 | + OFFSET(__SF_SIE_REASON, stack_frame, empty1[3]); | |
| 60 | + OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[4]); | |
| 61 | 61 | BLANK(); |
| 62 | 62 | OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val); |
| 63 | 63 | BLANK(); |
| @@ -1068,6 +1068,7 @@ EXPORT_SYMBOL(save_fpu_regs) · 1067 unmodified lines | ||
| 1068 | 1068 | * %r4 |
| 1069 | 1069 | */ |
| 1070 | 1070 | load_fpu_regs: |
| 1071 | + stnsm __SF_EMPTY(%r15),0xfc | |
| 1071 | 1072 | lg %r4,__LC_CURRENT |
| 1072 | 1073 | aghi %r4,__TASK_thread |
| 1073 | 1074 | TSTMSK __LC_CPU_FLAGS,_CIF_FPU |
| @@ -1099,6 +1100,7 @@ load_fpu_regs: · 25 unmodified lines | ||
| 1099 | 1100 | .Lload_fpu_regs_done: |
| 1100 | 1101 | ni __LC_CPU_FLAGS+7,255-_CIF_FPU |
| 1101 | 1102 | .Lload_fpu_regs_exit: |
| 1103 | + ssm __SF_EMPTY(%r15) | |
| 1102 | 1104 | BR_EX %r14 |
| 1103 | 1105 | .Lload_fpu_regs_end: |
| 1104 | 1106 | ENDPROC(load_fpu_regs) |
| @@ -129,8 +129,15 @@ int uv_destroy_page(unsigned long paddr) · 128 unmodified lines | ||
| 129 | 129 | .paddr = paddr |
| 130 | 130 | }; |
| 131 | 131 | |
| 132 | − if (uv_call(0, (u64)&uvcb)) | |
| 132 | + if (uv_call(0, (u64)&uvcb)) { | |
| 133 | + /* | |
| 134 | + * Older firmware uses 107/d as an indication of a non secure | |
| 135 | + * page. Let us emulate the newer variant (no-op). | |
| 136 | + */ | |
| 137 | + if (uvcb.header.rc == 0x107 && uvcb.header.rrc == 0xd) | |
| 138 | + return 0; | |
| 133 | 139 | return -EINVAL; |
| 140 | + } | |
| 134 | 141 | return 0; |
| 135 | 142 | } |
| 136 | 143 | |
| @@ -2312,7 +2312,7 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd) · 2311 unmodified lines | ||
| 2312 | 2312 | struct kvm_s390_pv_unp unp = {}; |
| 2313 | 2313 | |
| 2314 | 2314 | r = -EINVAL; |
| 2315 | − if (!kvm_s390_pv_is_protected(kvm)) | |
| 2315 | + if (!kvm_s390_pv_is_protected(kvm) || !mm_is_protected(kvm->mm)) | |
| 2316 | 2316 | break; |
| 2317 | 2317 | |
| 2318 | 2318 | r = -EFAULT; |
| @@ -3564,7 +3564,6 @@ static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu) · 1245 unmodified lines | ||
| 3564 | 3564 | vcpu->arch.sie_block->pp = 0; |
| 3565 | 3565 | vcpu->arch.sie_block->fpf &= ~FPF_BPBC; |
| 3566 | 3566 | vcpu->arch.sie_block->todpr = 0; |
| 3567 | − vcpu->arch.sie_block->cpnc = 0; | |
| 3568 | 3567 | } |
| 3569 | 3568 | } |
| 3570 | 3569 | |
| @@ -3582,7 +3581,6 @@ static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu) · 11 unmodified lines | ||
| 3582 | 3581 | |
| 3583 | 3582 | regs->etoken = 0; |
| 3584 | 3583 | regs->etoken_extension = 0; |
| 3585 | − regs->diag318 = 0; | |
| 3586 | 3584 | } |
| 3587 | 3585 | |
| 3588 | 3586 | int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) |
| @@ -208,7 +208,6 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc) · 207 unmodified lines | ||
| 208 | 208 | return -EIO; |
| 209 | 209 | } |
| 210 | 210 | kvm->arch.gmap->guest_handle = uvcb.guest_handle; |
| 211 | − atomic_set(&kvm->mm->context.is_protected, 1); | |
| 212 | 211 | return 0; |
| 213 | 212 | } |
| 214 | 213 | |
| @@ -228,6 +227,8 @@ int kvm_s390_pv_set_sec_parms(struct kvm *kvm, void *hdr, u64 length, u16 *rc, · 13 unmodified lines | ||
| 228 | 227 | *rrc = uvcb.header.rrc; |
| 229 | 228 | KVM_UV_EVENT(kvm, 3, "PROTVIRT VM SET PARMS: rc %x rrc %x", |
| 230 | 229 | *rc, *rrc); |
| 230 | + if (!cc) | |
| 231 | + atomic_set(&kvm->mm->context.is_protected, 1); | |
| 231 | 232 | return cc ? -EINVAL : 0; |
| 232 | 233 | } |
| 233 | 234 | |
| @@ -2690,6 +2690,8 @@ static const struct mm_walk_ops reset_acc_walk_ops = { · 2689 unmodified lines | ||
| 2690 | 2690 | #include <linux/sched/mm.h> |
| 2691 | 2691 | void s390_reset_acc(struct mm_struct *mm) |
| 2692 | 2692 | { |
| 2693 | + if (!mm_is_protected(mm)) | |
| 2694 | + return; | |
| 2693 | 2695 | /* |
| 2694 | 2696 | * we might be called during |
| 2695 | 2697 | * reset: we walk the pages and clear |
| @@ -107,14 +107,14 @@ · 106 unmodified lines | ||
| 107 | 107 | MODULE_LICENSE("GPL"); |
| 108 | 108 | |
| 109 | 109 | #define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \ |
| 110 | −static ssize_t __cstate_##_var##_show(struct kobject *kobj, \ | |
| 111 | − struct kobj_attribute *attr, \ | |
| 110 | +static ssize_t __cstate_##_var##_show(struct device *dev, \ | |
| 111 | + struct device_attribute *attr, \ | |
| 112 | 112 | char *page) \ |
| 113 | 113 | { \ |
| 114 | 114 | BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ |
| 115 | 115 | return sprintf(page, _format "\n"); \ |
| 116 | 116 | } \ |
| 117 | −static struct kobj_attribute format_attr_##_var = \ | |
| 117 | +static struct device_attribute format_attr_##_var = \ | |
| 118 | 118 | __ATTR(_name, 0444, __cstate_##_var##_show, NULL) |
| 119 | 119 | |
| 120 | 120 | static ssize_t cstate_get_attr_cpumask(struct device *dev, |
| @@ -94,8 +94,8 @@ end: · 93 unmodified lines | ||
| 94 | 94 | return map; |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | −ssize_t uncore_event_show(struct kobject *kobj, | |
| 98 | − struct kobj_attribute *attr, char *buf) | |
| 97 | +ssize_t uncore_event_show(struct device *dev, | |
| 98 | + struct device_attribute *attr, char *buf) | |
| 99 | 99 | { |
| 100 | 100 | struct uncore_event_desc *event = |
| 101 | 101 | container_of(attr, struct uncore_event_desc, attr); |
| @@ -157,7 +157,7 @@ struct intel_uncore_box { · 156 unmodified lines | ||
| 157 | 157 | #define UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS 2 |
| 158 | 158 | |
| 159 | 159 | struct uncore_event_desc { |
| 160 | − struct kobj_attribute attr; | |
| 160 | + struct device_attribute attr; | |
| 161 | 161 | const char *config; |
| 162 | 162 | }; |
| 163 | 163 | |
| @@ -179,8 +179,8 @@ struct pci2phy_map { · 15 unmodified lines | ||
| 179 | 179 | struct pci2phy_map *__find_pci2phy_map(int segment); |
| 180 | 180 | int uncore_pcibus_to_physid(struct pci_bus *bus); |
| 181 | 181 | |
| 182 | −ssize_t uncore_event_show(struct kobject *kobj, | |
| 183 | − struct kobj_attribute *attr, char *buf); | |
| 182 | +ssize_t uncore_event_show(struct device *dev, | |
| 183 | + struct device_attribute *attr, char *buf); | |
| 184 | 184 | |
| 185 | 185 | static inline struct intel_uncore_pmu *dev_to_uncore_pmu(struct device *dev) |
| 186 | 186 | { |
| @@ -201,14 +201,14 @@ extern int __uncore_max_dies; · 14 unmodified lines | ||
| 201 | 201 | } |
| 202 | 202 | |
| 203 | 203 | #define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format) \ |
| 204 | −static ssize_t __uncore_##_var##_show(struct kobject *kobj, \ | |
| 205 | − struct kobj_attribute *attr, \ | |
| 204 | +static ssize_t __uncore_##_var##_show(struct device *dev, \ | |
| 205 | + struct device_attribute *attr, \ | |
| 206 | 206 | char *page) \ |
| 207 | 207 | { \ |
| 208 | 208 | BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ |
| 209 | 209 | return sprintf(page, _format "\n"); \ |
| 210 | 210 | } \ |
| 211 | −static struct kobj_attribute format_attr_##_var = \ | |
| 211 | +static struct device_attribute format_attr_##_var = \ | |
| 212 | 212 | __ATTR(_name, 0444, __uncore_##_var##_show, NULL) |
| 213 | 213 | |
| 214 | 214 | static inline bool uncore_pmc_fixed(int idx) |
| @@ -93,18 +93,6 @@ static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = { · 92 unmodified lines | ||
| 93 | 93 | * any other bit is reserved |
| 94 | 94 | */ |
| 95 | 95 | #define RAPL_EVENT_MASK 0xFFULL |
| 96 | − | |
| 97 | −#define DEFINE_RAPL_FORMAT_ATTR(_var, _name, _format) \ | |
| 98 | −static ssize_t __rapl_##_var##_show(struct kobject *kobj, \ | |
| 99 | − struct kobj_attribute *attr, \ | |
| 100 | − char *page) \ | |
| 101 | −{ \ | |
| 102 | − BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ | |
| 103 | − return sprintf(page, _format "\n"); \ | |
| 104 | −} \ | |
| 105 | −static struct kobj_attribute format_attr_##_var = \ | |
| 106 | − __ATTR(_name, 0444, __rapl_##_var##_show, NULL) | |
| 107 | − | |
| 108 | 96 | #define RAPL_CNTR_WIDTH 32 |
| 109 | 97 | |
| 110 | 98 | #define RAPL_EVENT_ATTR_STR(_name, v, str) \ |
| @@ -441,7 +429,7 @@ static struct attribute_group rapl_pmu_events_group = { · 330 unmodified lines | ||
| 441 | 429 | .attrs = attrs_empty, |
| 442 | 430 | }; |
| 443 | 431 | |
| 444 | −DEFINE_RAPL_FORMAT_ATTR(event, event, "config:0-7"); | |
| 432 | +PMU_FORMAT_ATTR(event, "config:0-7"); | |
| 445 | 433 | static struct attribute *rapl_formats_attr[] = { |
| 446 | 434 | &format_attr_event.attr, |
| 447 | 435 | NULL, |
| @@ -1656,6 +1656,7 @@ int kvm_test_age_hva(struct kvm *kvm, unsigned long hva); · 1655 unmodified lines | ||
| 1656 | 1656 | int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); |
| 1657 | 1657 | int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v); |
| 1658 | 1658 | int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu); |
| 1659 | +int kvm_cpu_has_extint(struct kvm_vcpu *v); | |
| 1659 | 1660 | int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu); |
| 1660 | 1661 | int kvm_cpu_get_interrupt(struct kvm_vcpu *v); |
| 1661 | 1662 | void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event); |
| @@ -28,4 +28,14 @@ · 27 unmodified lines | ||
| 28 | 28 | #endif |
| 29 | 29 | |
| 30 | 30 | #endif /* CONFIG_SPARSEMEM */ |
| 31 | + | |
| 32 | +#ifndef __ASSEMBLY__ | |
| 33 | +#ifdef CONFIG_NUMA_KEEP_MEMINFO | |
| 34 | +extern int phys_to_target_node(phys_addr_t start); | |
| 35 | +#define phys_to_target_node phys_to_target_node | |
| 36 | +extern int memory_add_physaddr_to_nid(u64 start); | |
| 37 | +#define memory_add_physaddr_to_nid memory_add_physaddr_to_nid | |
| 38 | +#endif | |
| 39 | +#endif /* __ASSEMBLY__ */ | |
| 40 | + | |
| 31 | 41 | #endif /* _ASM_X86_SPARSEMEM_H */ |
| @@ -100,53 +100,6 @@ static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev · 99 unmodified lines | ||
| 100 | 100 | return find_matching_signature(mc, csig, cpf); |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | −/* | |
| 104 | − * Given CPU signature and a microcode patch, this function finds if the | |
| 105 | − * microcode patch has matching family and model with the CPU. | |
| 106 | − * | |
| 107 | − * %true - if there's a match | |
| 108 | − * %false - otherwise | |
| 109 | − */ | |
| 110 | −static bool microcode_matches(struct microcode_header_intel *mc_header, | |
| 111 | − unsigned long sig) | |
| 112 | −{ | |
| 113 | − unsigned long total_size = get_totalsize(mc_header); | |
| 114 | − unsigned long data_size = get_datasize(mc_header); | |
| 115 | − struct extended_sigtable *ext_header; | |
| 116 | − unsigned int fam_ucode, model_ucode; | |
| 117 | − struct extended_signature *ext_sig; | |
| 118 | − unsigned int fam, model; | |
| 119 | − int ext_sigcount, i; | |
| 120 | − | |
| 121 | − fam = x86_family(sig); | |
| 122 | − model = x86_model(sig); | |
| 123 | − | |
| 124 | − fam_ucode = x86_family(mc_header->sig); | |
| 125 | − model_ucode = x86_model(mc_header->sig); | |
| 126 | − | |
| 127 | − if (fam == fam_ucode && model == model_ucode) | |
| 128 | − return true; | |
| 129 | − | |
| 130 | − /* Look for ext. headers: */ | |
| 131 | − if (total_size <= data_size + MC_HEADER_SIZE) | |
| 132 | − return false; | |
| 133 | − | |
| 134 | − ext_header = (void *) mc_header + data_size + MC_HEADER_SIZE; | |
| 135 | − ext_sig = (void *)ext_header + EXT_HEADER_SIZE; | |
| 136 | − ext_sigcount = ext_header->count; | |
| 137 | − | |
| 138 | − for (i = 0; i < ext_sigcount; i++) { | |
| 139 | − fam_ucode = x86_family(ext_sig->sig); | |
| 140 | − model_ucode = x86_model(ext_sig->sig); | |
| 141 | − | |
| 142 | − if (fam == fam_ucode && model == model_ucode) | |
| 143 | − return true; | |
| 144 | − | |
| 145 | − ext_sig++; | |
| 146 | − } | |
| 147 | − return false; | |
| 148 | −} | |
| 149 | − | |
| 150 | 103 | static struct ucode_patch *memdup_patch(void *data, unsigned int size) |
| 151 | 104 | { |
| 152 | 105 | struct ucode_patch *p; |
| @@ -164,7 +117,7 @@ static struct ucode_patch *memdup_patch(void *data, unsigned int size) · 11 unmodified lines | ||
| 164 | 117 | return p; |
| 165 | 118 | } |
| 166 | 119 | |
| 167 | −static void save_microcode_patch(void *data, unsigned int size) | |
| 120 | +static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigned int size) | |
| 168 | 121 | { |
| 169 | 122 | struct microcode_header_intel *mc_hdr, *mc_saved_hdr; |
| 170 | 123 | struct ucode_patch *iter, *tmp, *p = NULL; |
| @@ -210,6 +163,9 @@ static void save_microcode_patch(void *data, unsigned int size) · 39 unmodified lines | ||
| 210 | 163 | if (!p) |
| 211 | 164 | return; |
| 212 | 165 | |
| 166 | + if (!find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf)) | |
| 167 | + return; | |
| 168 | + | |
| 213 | 169 | /* |
| 214 | 170 | * Save for early loading. On 32-bit, that needs to be a physical |
| 215 | 171 | * address as the APs are running from physical addresses, before |
| @@ -344,13 +300,14 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save) · 128 unmodified lines | ||
| 344 | 300 | |
| 345 | 301 | size -= mc_size; |
| 346 | 302 | |
| 347 | − if (!microcode_matches(mc_header, uci->cpu_sig.sig)) { | |
| 303 | + if (!find_matching_signature(data, uci->cpu_sig.sig, | |
| 304 | + uci->cpu_sig.pf)) { | |
| 348 | 305 | data += mc_size; |
| 349 | 306 | continue; |
| 350 | 307 | } |
| 351 | 308 | |
| 352 | 309 | if (save) { |
| 353 | − save_microcode_patch(data, mc_size); | |
| 310 | + save_microcode_patch(uci, data, mc_size); | |
| 354 | 311 | goto next; |
| 355 | 312 | } |
| 356 | 313 | |
| @@ -483,14 +440,14 @@ static void show_saved_mc(void) · 126 unmodified lines | ||
| 483 | 440 | * Save this microcode patch. It will be loaded early when a CPU is |
| 484 | 441 | * hot-added or resumes. |
| 485 | 442 | */ |
| 486 | −static void save_mc_for_early(u8 *mc, unsigned int size) | |
| 443 | +static void save_mc_for_early(struct ucode_cpu_info *uci, u8 *mc, unsigned int size) | |
| 487 | 444 | { |
| 488 | 445 | /* Synchronization during CPU hotplug. */ |
| 489 | 446 | static DEFINE_MUTEX(x86_cpu_microcode_mutex); |
| 490 | 447 | |
| 491 | 448 | mutex_lock(&x86_cpu_microcode_mutex); |
| 492 | 449 | |
| 493 | − save_microcode_patch(mc, size); | |
| 450 | + save_microcode_patch(uci, mc, size); | |
| 494 | 451 | show_saved_mc(); |
| 495 | 452 | |
| 496 | 453 | mutex_unlock(&x86_cpu_microcode_mutex); |
| @@ -935,7 +892,7 @@ static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter) · 438 unmodified lines | ||
| 935 | 892 | * permanent memory. So it will be loaded early when a CPU is hot added |
| 936 | 893 | * or resumes. |
| 937 | 894 | */ |
| 938 | − save_mc_for_early(new_mc, new_mc_size); | |
| 895 | + save_mc_for_early(uci, new_mc, new_mc_size); | |
| 939 | 896 | |
| 940 | 897 | pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", |
| 941 | 898 | cpu, new_rev, uci->cpu_sig.rev); |
| @@ -78,6 +78,9 @@ static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src, · 77 unmodified lines | ||
| 78 | 78 | if (!user_mode(regs)) |
| 79 | 79 | return copy_from_kernel_nofault(buf, (u8 *)src, nbytes); |
| 80 | 80 | |
| 81 | + /* The user space code from other tasks cannot be accessed. */ | |
| 82 | + if (regs != task_pt_regs(current)) | |
| 83 | + return -EPERM; | |
| 81 | 84 | /* |
| 82 | 85 | * Make sure userspace isn't trying to trick us into dumping kernel |
| 83 | 86 | * memory by pointing the userspace instruction pointer at it. |
| @@ -85,6 +88,12 @@ static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src, · 1 unmodified line | ||
| 85 | 88 | if (__chk_range_not_ok(src, nbytes, TASK_SIZE_MAX)) |
| 86 | 89 | return -EINVAL; |
| 87 | 90 | |
| 91 | + /* | |
| 92 | + * Even if named copy_from_user_nmi() this can be invoked from | |
| 93 | + * other contexts and will not try to resolve a pagefault, which is | |
| 94 | + * the correct thing to do here as this code can be called from any | |
| 95 | + * context. | |
| 96 | + */ | |
| 88 | 97 | return copy_from_user_nmi(buf, (void __user *)src, nbytes); |
| 89 | 98 | } |
| 90 | 99 | |
| @@ -115,13 +124,19 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl) · 24 unmodified lines | ||
| 115 | 124 | u8 opcodes[OPCODE_BUFSIZE]; |
| 116 | 125 | unsigned long prologue = regs->ip - PROLOGUE_SIZE; |
| 117 | 126 | |
| 118 | − if (copy_code(regs, opcodes, prologue, sizeof(opcodes))) { | |
| 119 | − printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n", | |
| 120 | − loglvl, prologue); | |
| 121 | − } else { | |
| 127 | + switch (copy_code(regs, opcodes, prologue, sizeof(opcodes))) { | |
| 128 | + case 0: | |
| 122 | 129 | printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %" |
| 123 | 130 | __stringify(EPILOGUE_SIZE) "ph\n", loglvl, opcodes, |
| 124 | 131 | opcodes[PROLOGUE_SIZE], opcodes + PROLOGUE_SIZE + 1); |
| 132 | + break; | |
| 133 | + case -EPERM: | |
| 134 | + /* No access to the user space stack of other tasks. Ignore. */ | |
| 135 | + break; | |
| 136 | + default: | |
| 137 | + printk("%sCode: Unable to access opcode bytes at RIP 0x%lx.\n", | |
| 138 | + loglvl, prologue); | |
| 139 | + break; | |
| 125 | 140 | } |
| 126 | 141 | } |
| 127 | 142 | |
| @@ -514,16 +514,10 @@ int tboot_force_iommu(void) · 513 unmodified lines | ||
| 514 | 514 | if (!tboot_enabled()) |
| 515 | 515 | return 0; |
| 516 | 516 | |
| 517 | − if (intel_iommu_tboot_noforce) | |
| 518 | − return 1; | |
| 519 | − | |
| 520 | − if (no_iommu || swiotlb || dmar_disabled) | |
| 517 | + if (no_iommu || dmar_disabled) | |
| 521 | 518 | pr_warn("Forcing Intel-IOMMU to enabled\n"); |
| 522 | 519 | |
| 523 | 520 | dmar_disabled = 0; |
| 524 | −#ifdef CONFIG_SWIOTLB | |
| 525 | − swiotlb = 0; | |
| 526 | −#endif | |
| 527 | 521 | no_iommu = 0; |
| 528 | 522 | |
| 529 | 523 | return 1; |
| @@ -40,29 +40,10 @@ static int pending_userspace_extint(struct kvm_vcpu *v) · 39 unmodified lines | ||
| 40 | 40 | * check if there is pending interrupt from |
| 41 | 41 | * non-APIC source without intack. |
| 42 | 42 | */ |
| 43 | −static int kvm_cpu_has_extint(struct kvm_vcpu *v) | |
| 44 | −{ | |
| 45 | − u8 accept = kvm_apic_accept_pic_intr(v); | |
| 46 | − | |
| 47 | − if (accept) { | |
| 48 | − if (irqchip_split(v->kvm)) | |
| 49 | − return pending_userspace_extint(v); | |
| 50 | − else | |
| 51 | − return v->kvm->arch.vpic->output; | |
| 52 | − } else | |
| 53 | − return 0; | |
| 54 | −} | |
| 55 | − | |
| 56 | −/* | |
| 57 | − * check if there is injectable interrupt: | |
| 58 | − * when virtual interrupt delivery enabled, | |
| 59 | − * interrupt from apic will handled by hardware, | |
| 60 | − * we don't need to check it here. | |
| 61 | − */ | |
| 62 | −int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) | |
| 43 | +int kvm_cpu_has_extint(struct kvm_vcpu *v) | |
| 63 | 44 | { |
| 64 | 45 | /* |
| 65 | − * FIXME: interrupt.injected represents an interrupt that it's | |
| 46 | + * FIXME: interrupt.injected represents an interrupt whose | |
| 66 | 47 | * side-effects have already been applied (e.g. bit from IRR |
| 67 | 48 | * already moved to ISR). Therefore, it is incorrect to rely |
| 68 | 49 | * on interrupt.injected to know if there is a pending |
| @@ -75,6 +56,23 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) · 6 unmodified lines | ||
| 75 | 56 | if (!lapic_in_kernel(v)) |
| 76 | 57 | return v->arch.interrupt.injected; |
| 77 | 58 | |
| 59 | + if (!kvm_apic_accept_pic_intr(v)) | |
| 60 | + return 0; | |
| 61 | + | |
| 62 | + if (irqchip_split(v->kvm)) | |
| 63 | + return pending_userspace_extint(v); | |
| 64 | + else | |
| 65 | + return v->kvm->arch.vpic->output; | |
| 66 | +} | |
| 67 | + | |
| 68 | +/* | |
| 69 | + * check if there is injectable interrupt: | |
| 70 | + * when virtual interrupt delivery enabled, | |
| 71 | + * interrupt from apic will handled by hardware, | |
| 72 | + * we don't need to check it here. | |
| 73 | + */ | |
| 74 | +int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) | |
| 75 | +{ | |
| 78 | 76 | if (kvm_cpu_has_extint(v)) |
| 79 | 77 | return 1; |
| 80 | 78 | |
| @@ -91,20 +89,6 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_injectable_intr); · 10 unmodified lines | ||
| 91 | 89 | */ |
| 92 | 90 | int kvm_cpu_has_interrupt(struct kvm_vcpu *v) |
| 93 | 91 | { |
| 94 | − /* | |
| 95 | − * FIXME: interrupt.injected represents an interrupt that it's | |
| 96 | − * side-effects have already been applied (e.g. bit from IRR | |
| 97 | − * already moved to ISR). Therefore, it is incorrect to rely | |
| 98 | − * on interrupt.injected to know if there is a pending | |
| 99 | − * interrupt in the user-mode LAPIC. | |
| 100 | − * This leads to nVMX/nSVM not be able to distinguish | |
| 101 | − * if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on | |
| 102 | − * pending interrupt or should re-inject an injected | |
| 103 | − * interrupt. | |
| 104 | − */ | |
| 105 | − if (!lapic_in_kernel(v)) | |
| 106 | − return v->arch.interrupt.injected; | |
| 107 | − | |
| 108 | 92 | if (kvm_cpu_has_extint(v)) |
| 109 | 93 | return 1; |
| 110 | 94 | |
| @@ -118,16 +102,21 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); · 7 unmodified lines | ||
| 118 | 102 | */ |
| 119 | 103 | static int kvm_cpu_get_extint(struct kvm_vcpu *v) |
| 120 | 104 | { |
| 121 | − if (kvm_cpu_has_extint(v)) { | |
| 122 | − if (irqchip_split(v->kvm)) { | |
| 123 | − int vector = v->arch.pending_external_vector; | |
| 124 | − | |
| 125 | − v->arch.pending_external_vector = -1; | |
| 126 | − return vector; | |
| 127 | − } else | |
| 128 | − return kvm_pic_read_irq(v->kvm); /* PIC */ | |
| 129 | − } else | |
| 105 | + if (!kvm_cpu_has_extint(v)) { | |
| 106 | + WARN_ON(!lapic_in_kernel(v)); | |
| 130 | 107 | return -1; |
| 108 | + } | |
| 109 | + | |
| 110 | + if (!lapic_in_kernel(v)) | |
| 111 | + return v->arch.interrupt.nr; | |
| 112 | + | |
| 113 | + if (irqchip_split(v->kvm)) { | |
| 114 | + int vector = v->arch.pending_external_vector; | |
| 115 | + | |
| 116 | + v->arch.pending_external_vector = -1; | |
| 117 | + return vector; | |
| 118 | + } else | |
| 119 | + return kvm_pic_read_irq(v->kvm); /* PIC */ | |
| 131 | 120 | } |
| 132 | 121 | |
| 133 | 122 | /* |
| @@ -135,13 +124,7 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v) · 1 unmodified line | ||
| 135 | 124 | */ |
| 136 | 125 | int kvm_cpu_get_interrupt(struct kvm_vcpu *v) |
| 137 | 126 | { |
| 138 | − int vector; | |
| 139 | − | |
| 140 | − if (!lapic_in_kernel(v)) | |
| 141 | − return v->arch.interrupt.nr; | |
| 142 | − | |
| 143 | − vector = kvm_cpu_get_extint(v); | |
| 144 | − | |
| 127 | + int vector = kvm_cpu_get_extint(v); | |
| 145 | 128 | if (vector != -1) |
| 146 | 129 | return vector; /* PIC */ |
| 147 | 130 | |
| @@ -2465,7 +2465,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu) · 2464 unmodified lines | ||
| 2465 | 2465 | struct kvm_lapic *apic = vcpu->arch.apic; |
| 2466 | 2466 | u32 ppr; |
| 2467 | 2467 | |
| 2468 | − if (!kvm_apic_hw_enabled(apic)) | |
| 2468 | + if (!kvm_apic_present(vcpu)) | |
| 2469 | 2469 | return -1; |
| 2470 | 2470 | |
| 2471 | 2471 | __apic_update_ppr(apic, &ppr); |
| @@ -3517,7 +3517,7 @@ static bool get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep) · 3516 unmodified lines | ||
| 3517 | 3517 | { |
| 3518 | 3518 | u64 sptes[PT64_ROOT_MAX_LEVEL]; |
| 3519 | 3519 | struct rsvd_bits_validate *rsvd_check; |
| 3520 | − int root = vcpu->arch.mmu->root_level; | |
| 3520 | + int root = vcpu->arch.mmu->shadow_root_level; | |
| 3521 | 3521 | int leaf; |
| 3522 | 3522 | int level; |
| 3523 | 3523 | bool reserved = false; |
| @@ -642,8 +642,8 @@ static int __sev_dbg_decrypt(struct kvm *kvm, unsigned long src_paddr, · 641 unmodified lines | ||
| 642 | 642 | * Its safe to read more than we are asked, caller should ensure that |
| 643 | 643 | * destination has enough space. |
| 644 | 644 | */ |
| 645 | − src_paddr = round_down(src_paddr, 16); | |
| 646 | 645 | offset = src_paddr & 15; |
| 646 | + src_paddr = round_down(src_paddr, 16); | |
| 647 | 647 | sz = round_up(sz + offset, 16); |
| 648 | 648 | |
| 649 | 649 | return __sev_issue_dbg_cmd(kvm, src_paddr, dst_paddr, sz, err, false); |
| @@ -1309,8 +1309,10 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu) · 1308 unmodified lines | ||
| 1309 | 1309 | svm->avic_is_running = true; |
| 1310 | 1310 | |
| 1311 | 1311 | svm->msrpm = svm_vcpu_alloc_msrpm(); |
| 1312 | − if (!svm->msrpm) | |
| 1312 | + if (!svm->msrpm) { | |
| 1313 | + err = -ENOMEM; | |
| 1313 | 1314 | goto error_free_vmcb_page; |
| 1315 | + } | |
| 1314 | 1316 | |
| 1315 | 1317 | svm_vcpu_init_msrpm(vcpu, svm->msrpm); |
| 1316 | 1318 | |
| @@ -4051,21 +4051,23 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu, · 4050 unmodified lines | ||
| 4051 | 4051 | |
| 4052 | 4052 | static int kvm_cpu_accept_dm_intr(struct kvm_vcpu *vcpu) |
| 4053 | 4053 | { |
| 4054 | + /* | |
| 4055 | + * We can accept userspace's request for interrupt injection | |
| 4056 | + * as long as we have a place to store the interrupt number. | |
| 4057 | + * The actual injection will happen when the CPU is able to | |
| 4058 | + * deliver the interrupt. | |
| 4059 | + */ | |
| 4060 | + if (kvm_cpu_has_extint(vcpu)) | |
| 4061 | + return false; | |
| 4062 | + | |
| 4063 | + /* Acknowledging ExtINT does not happen if LINT0 is masked. */ | |
| 4054 | 4064 | return (!lapic_in_kernel(vcpu) || |
| 4055 | 4065 | kvm_apic_accept_pic_intr(vcpu)); |
| 4056 | 4066 | } |
| 4057 | 4067 | |
| 4058 | −/* | |
| 4059 | − * if userspace requested an interrupt window, check that the | |
| 4060 | − * interrupt window is open. | |
| 4061 | − * | |
| 4062 | − * No need to exit to userspace if we already have an interrupt queued. | |
| 4063 | − */ | |
| 4064 | 4068 | static int kvm_vcpu_ready_for_interrupt_injection(struct kvm_vcpu *vcpu) |
| 4065 | 4069 | { |
| 4066 | 4070 | return kvm_arch_interrupt_allowed(vcpu) && |
| 4067 | − !kvm_cpu_has_interrupt(vcpu) && | |
| 4068 | − !kvm_event_needs_reinjection(vcpu) && | |
| 4069 | 4071 | kvm_cpu_accept_dm_intr(vcpu); |
| 4070 | 4072 | } |
| 4071 | 4073 | |
| @@ -938,6 +938,7 @@ int phys_to_target_node(phys_addr_t start) · 937 unmodified lines | ||
| 938 | 938 | |
| 939 | 939 | return meminfo_to_nid(&numa_reserved_meminfo, start); |
| 940 | 940 | } |
| 941 | +EXPORT_SYMBOL_GPL(phys_to_target_node); | |
| 941 | 942 | |
| 942 | 943 | int memory_add_physaddr_to_nid(u64 start) |
| 943 | 944 | { |
| @@ -947,4 +948,5 @@ int memory_add_physaddr_to_nid(u64 start) · 3 unmodified lines | ||
| 947 | 948 | nid = numa_meminfo.blk[0].nid; |
| 948 | 949 | return nid; |
| 949 | 950 | } |
| 951 | +EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); | |
| 950 | 952 | #endif |
| @@ -78,28 +78,30 @@ int __init efi_alloc_page_tables(void) · 77 unmodified lines | ||
| 78 | 78 | gfp_mask = GFP_KERNEL | __GFP_ZERO; |
| 79 | 79 | efi_pgd = (pgd_t *)__get_free_pages(gfp_mask, PGD_ALLOCATION_ORDER); |
| 80 | 80 | if (!efi_pgd) |
| 81 | − return -ENOMEM; | |
| 81 | + goto fail; | |
| 82 | 82 | |
| 83 | 83 | pgd = efi_pgd + pgd_index(EFI_VA_END); |
| 84 | 84 | p4d = p4d_alloc(&init_mm, pgd, EFI_VA_END); |
| 85 | − if (!p4d) { | |
| 86 | − free_page((unsigned long)efi_pgd); | |
| 87 | − return -ENOMEM; | |
| 88 | − } | |
| 85 | + if (!p4d) | |
| 86 | + goto free_pgd; | |
| 89 | 87 | |
| 90 | 88 | pud = pud_alloc(&init_mm, p4d, EFI_VA_END); |
| 91 | − if (!pud) { | |
| 92 | − if (pgtable_l5_enabled()) | |
| 93 | − free_page((unsigned long) pgd_page_vaddr(*pgd)); | |
| 94 | − free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER); | |
| 95 | − return -ENOMEM; | |
| 96 | − } | |
| 89 | + if (!pud) | |
| 90 | + goto free_p4d; | |
| 97 | 91 | |
| 98 | 92 | efi_mm.pgd = efi_pgd; |
| 99 | 93 | mm_init_cpumask(&efi_mm); |
| 100 | 94 | init_new_context(NULL, &efi_mm); |
| 101 | 95 | |
| 102 | 96 | return 0; |
| 97 | + | |
| 98 | +free_p4d: | |
| 99 | + if (pgtable_l5_enabled()) | |
| 100 | + free_page((unsigned long)pgd_page_vaddr(*pgd)); | |
| 101 | +free_pgd: | |
| 102 | + free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER); | |
| 103 | +fail: | |
| 104 | + return -ENOMEM; | |
| 103 | 105 | } |
| 104 | 106 | |
| 105 | 107 | /* |
| @@ -93,10 +93,20 @@ void xen_init_lock_cpu(int cpu) · 92 unmodified lines | ||
| 93 | 93 | |
| 94 | 94 | void xen_uninit_lock_cpu(int cpu) |
| 95 | 95 | { |
| 96 | + int irq; | |
| 97 | + | |
| 96 | 98 | if (!xen_pvspin) |
| 97 | 99 | return; |
| 98 | 100 | |
| 99 | − unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL); | |
| 101 | + /* | |
| 102 | + * When booting the kernel with 'mitigations=auto,nosmt', the secondary | |
| 103 | + * CPUs are not activated, and lock_kicker_irq is not initialized. | |
| 104 | + */ | |
| 105 | + irq = per_cpu(lock_kicker_irq, cpu); | |
| 106 | + if (irq == -1) | |
| 107 | + return; | |
| 108 | + | |
| 109 | + unbind_from_irqhandler(irq, NULL); | |
| 100 | 110 | per_cpu(lock_kicker_irq, cpu) = -1; |
| 101 | 111 | kfree(per_cpu(irq_name, cpu)); |
| 102 | 112 | per_cpu(irq_name, cpu) = NULL; |
| @@ -849,6 +849,7 @@ static void blkcg_fill_root_iostats(void) · 848 unmodified lines | ||
| 849 | 849 | blkg_iostat_set(&blkg->iostat.cur, &tmp); |
| 850 | 850 | u64_stats_update_end(&blkg->iostat.sync); |
| 851 | 851 | } |
| 852 | + disk_put_part(part); | |
| 852 | 853 | } |
| 853 | 854 | } |
| 854 | 855 | |
| @@ -225,13 +225,18 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error) · 224 unmodified lines | ||
| 225 | 225 | /* release the tag's ownership to the req cloned from */ |
| 226 | 226 | spin_lock_irqsave(&fq->mq_flush_lock, flags); |
| 227 | 227 | |
| 228 | − WRITE_ONCE(flush_rq->state, MQ_RQ_IDLE); | |
| 229 | 228 | if (!refcount_dec_and_test(&flush_rq->ref)) { |
| 230 | 229 | fq->rq_status = error; |
| 231 | 230 | spin_unlock_irqrestore(&fq->mq_flush_lock, flags); |
| 232 | 231 | return; |
| 233 | 232 | } |
| 234 | 233 | |
| 234 | + /* | |
| 235 | + * Flush request has to be marked as IDLE when it is really ended | |
| 236 | + * because its .end_io() is called from timeout code path too for | |
| 237 | + * avoiding use-after-free. | |
| 238 | + */ | |
| 239 | + WRITE_ONCE(flush_rq->state, MQ_RQ_IDLE); | |
| 235 | 240 | if (fq->rq_status != BLK_STS_OK) |
| 236 | 241 | error = fq->rq_status; |
| 237 | 242 | |
| @@ -103,6 +103,13 @@ int blk_ksm_init(struct blk_keyslot_manager *ksm, unsigned int num_slots) · 102 unmodified lines | ||
| 103 | 103 | spin_lock_init(&ksm->idle_slots_lock); |
| 104 | 104 | |
| 105 | 105 | slot_hashtable_size = roundup_pow_of_two(num_slots); |
| 106 | + /* | |
| 107 | + * hash_ptr() assumes bits != 0, so ensure the hash table has at least 2 | |
| 108 | + * buckets. This only makes a difference when there is only 1 keyslot. | |
| 109 | + */ | |
| 110 | + if (slot_hashtable_size < 2) | |
| 111 | + slot_hashtable_size = 2; | |
| 112 | + | |
| 106 | 113 | ksm->log_slot_ht_size = ilog2(slot_hashtable_size); |
| 107 | 114 | ksm->slot_hashtable = kvmalloc_array(slot_hashtable_size, |
| 108 | 115 | sizeof(ksm->slot_hashtable[0]), |
| @@ -49,15 +49,25 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty) · 48 unmodified lines | ||
| 49 | 49 | |
| 50 | 50 | if (!tty->ops->write) |
| 51 | 51 | return -EOPNOTSUPP; |
| 52 | + | |
| 53 | + mutex_lock(&speakup_tty_mutex); | |
| 54 | + if (speakup_tty) { | |
| 55 | + mutex_unlock(&speakup_tty_mutex); | |
| 56 | + return -EBUSY; | |
| 57 | + } | |
| 52 | 58 | speakup_tty = tty; |
| 53 | 59 | |
| 54 | 60 | ldisc_data = kmalloc(sizeof(*ldisc_data), GFP_KERNEL); |
| 55 | − if (!ldisc_data) | |
| 61 | + if (!ldisc_data) { | |
| 62 | + speakup_tty = NULL; | |
| 63 | + mutex_unlock(&speakup_tty_mutex); | |
| 56 | 64 | return -ENOMEM; |
| 65 | + } | |
| 57 | 66 | |
| 58 | 67 | init_completion(&ldisc_data->completion); |
| 59 | 68 | ldisc_data->buf_free = true; |
| 60 | 69 | speakup_tty->disc_data = ldisc_data; |
| 70 | + mutex_unlock(&speakup_tty_mutex); | |
| 61 | 71 | |
| 62 | 72 | return 0; |
| 63 | 73 | } |
| @@ -44,7 +44,7 @@ static DEFINE_SPINLOCK(iort_fwnode_lock); · 43 unmodified lines | ||
| 44 | 44 | * iort_set_fwnode() - Create iort_fwnode and use it to register |
| 45 | 45 | * iommu data in the iort_fwnode_list |
| 46 | 46 | * |
| 47 | − * @node: IORT table node associated with the IOMMU | |
| 47 | + * @iort_node: IORT table node associated with the IOMMU | |
| 48 | 48 | * @fwnode: fwnode associated with the IORT node |
| 49 | 49 | * |
| 50 | 50 | * Returns: 0 on success |
| @@ -673,7 +673,8 @@ static int iort_dev_find_its_id(struct device *dev, u32 id, · 622 unmodified lines | ||
| 673 | 673 | /** |
| 674 | 674 | * iort_get_device_domain() - Find MSI domain related to a device |
| 675 | 675 | * @dev: The device. |
| 676 | − * @req_id: Requester ID for the device. | |
| 676 | + * @id: Requester ID for the device. | |
| 677 | + * @bus_token: irq domain bus token. | |
| 677 | 678 | * |
| 678 | 679 | * Returns: the MSI domain for this device, NULL otherwise |
| 679 | 680 | */ |
| @@ -1136,7 +1137,7 @@ static int rc_dma_get_range(struct device *dev, u64 *size) · 456 unmodified lines | ||
| 1136 | 1137 | * |
| 1137 | 1138 | * @dev: device to configure |
| 1138 | 1139 | * @dma_addr: device DMA address result pointer |
| 1139 | − * @size: DMA range size result pointer | |
| 1140 | + * @dma_size: DMA range size result pointer | |
| 1140 | 1141 | */ |
| 1141 | 1142 | void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size) |
| 1142 | 1143 | { |
| @@ -1526,6 +1527,7 @@ static __init const struct iort_dev_config *iort_get_dev_cfg( · 383 unmodified lines | ||
| 1526 | 1527 | /** |
| 1527 | 1528 | * iort_add_platform_device() - Allocate a platform device for IORT node |
| 1528 | 1529 | * @node: Pointer to device ACPI IORT node |
| 1530 | + * @ops: Pointer to IORT device config struct | |
| 1529 | 1531 | * |
| 1530 | 1532 | * Returns: 0 on success, <0 failure |
| 1531 | 1533 | */ |
| @@ -227,6 +227,9 @@ static int sysc_wait_softreset(struct sysc *ddata) · 226 unmodified lines | ||
| 227 | 227 | u32 sysc_mask, syss_done, rstval; |
| 228 | 228 | int syss_offset, error = 0; |
| 229 | 229 | |
| 230 | + if (ddata->cap->regbits->srst_shift < 0) | |
| 231 | + return 0; | |
| 232 | + | |
| 230 | 233 | syss_offset = ddata->offsets[SYSC_SYSSTATUS]; |
| 231 | 234 | sysc_mask = BIT(ddata->cap->regbits->srst_shift); |
| 232 | 235 | |
| @@ -970,9 +973,15 @@ static int sysc_enable_module(struct device *dev) · 737 unmodified lines | ||
| 970 | 973 | return error; |
| 971 | 974 | } |
| 972 | 975 | } |
| 973 | − error = sysc_wait_softreset(ddata); | |
| 974 | − if (error) | |
| 975 | − dev_warn(ddata->dev, "OCP softreset timed out\n"); | |
| 976 | + /* | |
| 977 | + * Some modules like i2c and hdq1w have unusable reset status unless | |
| 978 | + * the module reset quirk is enabled. Skip status check on enable. | |
| 979 | + */ | |
| 980 | + if (!(ddata->cfg.quirks & SYSC_MODULE_QUIRK_ENA_RESETDONE)) { | |
| 981 | + error = sysc_wait_softreset(ddata); | |
| 982 | + if (error) | |
| 983 | + dev_warn(ddata->dev, "OCP softreset timed out\n"); | |
| 984 | + } | |
| 976 | 985 | if (ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_IN_RESET) |
| 977 | 986 | sysc_disable_opt_clocks(ddata); |
| 978 | 987 | |
| @@ -1373,17 +1382,17 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 394 unmodified lines | ||
| 1373 | 1382 | SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50030200, 0xffffffff, |
| 1374 | 1383 | SYSC_QUIRK_OPT_CLKS_NEEDED), |
| 1375 | 1384 | SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, |
| 1376 | − SYSC_MODULE_QUIRK_HDQ1W), | |
| 1385 | + SYSC_MODULE_QUIRK_HDQ1W | SYSC_MODULE_QUIRK_ENA_RESETDONE), | |
| 1377 | 1386 | SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, |
| 1378 | − SYSC_MODULE_QUIRK_HDQ1W), | |
| 1387 | + SYSC_MODULE_QUIRK_HDQ1W | SYSC_MODULE_QUIRK_ENA_RESETDONE), | |
| 1379 | 1388 | SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000036, 0x000000ff, |
| 1380 | − SYSC_MODULE_QUIRK_I2C), | |
| 1389 | + SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE), | |
| 1381 | 1390 | SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x0000003c, 0x000000ff, |
| 1382 | − SYSC_MODULE_QUIRK_I2C), | |
| 1391 | + SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE), | |
| 1383 | 1392 | SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000040, 0x000000ff, |
| 1384 | − SYSC_MODULE_QUIRK_I2C), | |
| 1393 | + SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE), | |
| 1385 | 1394 | SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, |
| 1386 | − SYSC_MODULE_QUIRK_I2C), | |
| 1395 | + SYSC_MODULE_QUIRK_I2C | SYSC_MODULE_QUIRK_ENA_RESETDONE), | |
| 1387 | 1396 | SYSC_QUIRK("gpu", 0x50000000, 0x14, -ENODEV, -ENODEV, 0x00010201, 0xffffffff, 0), |
| 1388 | 1397 | SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff, |
| 1389 | 1398 | SYSC_MODULE_QUIRK_SGX), |
| @@ -2880,7 +2889,7 @@ static int sysc_check_active_timer(struct sysc *ddata) · 1490 unmodified lines | ||
| 2880 | 2889 | |
| 2881 | 2890 | if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) && |
| 2882 | 2891 | (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE)) |
| 2883 | − return -EBUSY; | |
| 2892 | + return -ENXIO; | |
| 2884 | 2893 | |
| 2885 | 2894 | return 0; |
| 2886 | 2895 | } |
| @@ -368,7 +368,7 @@ static const struct regmap_config ti_eqep_regmap32_config = { · 367 unmodified lines | ||
| 368 | 368 | .reg_bits = 32, |
| 369 | 369 | .val_bits = 32, |
| 370 | 370 | .reg_stride = 4, |
| 371 | − .max_register = 0x24, | |
| 371 | + .max_register = QUPRD, | |
| 372 | 372 | }; |
| 373 | 373 | |
| 374 | 374 | static const struct regmap_config ti_eqep_regmap16_config = { |
| @@ -376,7 +376,7 @@ static const struct regmap_config ti_eqep_regmap16_config = { · 1 unmodified line | ||
| 376 | 376 | .reg_bits = 16, |
| 377 | 377 | .val_bits = 16, |
| 378 | 378 | .reg_stride = 2, |
| 379 | − .max_register = 0x1e, | |
| 379 | + .max_register = QCPRDLAT, | |
| 380 | 380 | }; |
| 381 | 381 | |
| 382 | 382 | static int ti_eqep_probe(struct platform_device *pdev) |
| @@ -236,13 +236,15 @@ static int scmi_cpufreq_probe(struct scmi_device *sdev) · 235 unmodified lines | ||
| 236 | 236 | if (!handle || !handle->perf_ops) |
| 237 | 237 | return -ENODEV; |
| 238 | 238 | |
| 239 | +#ifdef CONFIG_COMMON_CLK | |
| 239 | 240 | /* dummy clock provider as needed by OPP if clocks property is used */ |
| 240 | 241 | if (of_find_property(dev->of_node, "#clock-cells", NULL)) |
| 241 | 242 | devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, NULL); |
| 243 | +#endif | |
| 242 | 244 | |
| 243 | 245 | ret = cpufreq_register_driver(&scmi_cpufreq_driver); |
| 244 | 246 | if (ret) { |
| 245 | − dev_err(&sdev->dev, "%s: registering cpufreq failed, err: %d\n", | |
| 247 | + dev_err(dev, "%s: registering cpufreq failed, err: %d\n", | |
| 246 | 248 | __func__, ret); |
| 247 | 249 | } |
| 248 | 250 | |
| @@ -50,7 +50,6 @@ config DEV_DAX_HMEM · 49 unmodified lines | ||
| 50 | 50 | Say M if unsure. |
| 51 | 51 | |
| 52 | 52 | config DEV_DAX_HMEM_DEVICES |
| 53 | − depends on NUMA_KEEP_MEMINFO # for phys_to_target_node() | |
| 54 | 53 | depends on DEV_DAX_HMEM && DAX=y |
| 55 | 54 | def_bool y |
| 56 | 55 | |
| @@ -1039,16 +1039,15 @@ static int get_dma_id(struct dma_device *device) · 1038 unmodified lines | ||
| 1039 | 1039 | static int __dma_async_device_channel_register(struct dma_device *device, |
| 1040 | 1040 | struct dma_chan *chan) |
| 1041 | 1041 | { |
| 1042 | − int rc = 0; | |
| 1042 | + int rc; | |
| 1043 | 1043 | |
| 1044 | 1044 | chan->local = alloc_percpu(typeof(*chan->local)); |
| 1045 | 1045 | if (!chan->local) |
| 1046 | − goto err_out; | |
| 1046 | + return -ENOMEM; | |
| 1047 | 1047 | chan->dev = kzalloc(sizeof(*chan->dev), GFP_KERNEL); |
| 1048 | 1048 | if (!chan->dev) { |
| 1049 | − free_percpu(chan->local); | |
| 1050 | − chan->local = NULL; | |
| 1051 | − goto err_out; | |
| 1049 | + rc = -ENOMEM; | |
| 1050 | + goto err_free_local; | |
| 1052 | 1051 | } |
| 1053 | 1052 | |
| 1054 | 1053 | /* |
| @@ -1061,7 +1060,8 @@ static int __dma_async_device_channel_register(struct dma_device *device, · 6 unmodified lines | ||
| 1061 | 1060 | if (chan->chan_id < 0) { |
| 1062 | 1061 | pr_err("%s: unable to alloc ida for chan: %d\n", |
| 1063 | 1062 | __func__, chan->chan_id); |
| 1064 | − goto err_out; | |
| 1063 | + rc = chan->chan_id; | |
| 1064 | + goto err_free_dev; | |
| 1065 | 1065 | } |
| 1066 | 1066 | |
| 1067 | 1067 | chan->dev->device.class = &dma_devclass; |
| @@ -1082,9 +1082,10 @@ static int __dma_async_device_channel_register(struct dma_device *device, · 14 unmodified lines | ||
| 1082 | 1082 | mutex_lock(&device->chan_mutex); |
| 1083 | 1083 | ida_free(&device->chan_ida, chan->chan_id); |
| 1084 | 1084 | mutex_unlock(&device->chan_mutex); |
| 1085 | − err_out: | |
| 1086 | − free_percpu(chan->local); | |
| 1085 | + err_free_dev: | |
| 1087 | 1086 | kfree(chan->dev); |
| 1087 | + err_free_local: | |
| 1088 | + free_percpu(chan->local); | |
| 1088 | 1089 | return rc; |
| 1089 | 1090 | } |
| 1090 | 1091 | |
| @@ -271,7 +271,7 @@ int idxd_wq_map_portal(struct idxd_wq *wq) · 270 unmodified lines | ||
| 271 | 271 | resource_size_t start; |
| 272 | 272 | |
| 273 | 273 | start = pci_resource_start(pdev, IDXD_WQ_BAR); |
| 274 | − start = start + wq->id * IDXD_PORTAL_SIZE; | |
| 274 | + start += idxd_get_wq_portal_full_offset(wq->id, IDXD_PORTAL_LIMITED); | |
| 275 | 275 | |
| 276 | 276 | wq->dportal = devm_ioremap(dev, start, IDXD_PORTAL_SIZE); |
| 277 | 277 | if (!wq->dportal) |
| @@ -295,7 +295,7 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq) · 17 unmodified lines | ||
| 295 | 295 | int i, wq_offset; |
| 296 | 296 | |
| 297 | 297 | lockdep_assert_held(&idxd->dev_lock); |
| 298 | − memset(&wq->wqcfg, 0, sizeof(wq->wqcfg)); | |
| 298 | + memset(wq->wqcfg, 0, idxd->wqcfg_size); | |
| 299 | 299 | wq->type = IDXD_WQT_NONE; |
| 300 | 300 | wq->size = 0; |
| 301 | 301 | wq->group = NULL; |
| @@ -304,8 +304,8 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq) · 2 unmodified lines | ||
| 304 | 304 | clear_bit(WQ_FLAG_DEDICATED, &wq->flags); |
| 305 | 305 | memset(wq->name, 0, WQ_NAME_SIZE); |
| 306 | 306 | |
| 307 | − for (i = 0; i < 8; i++) { | |
| 308 | − wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32); | |
| 307 | + for (i = 0; i < WQCFG_STRIDES(idxd); i++) { | |
| 308 | + wq_offset = WQCFG_OFFSET(idxd, wq->id, i); | |
| 309 | 309 | iowrite32(0, idxd->reg_base + wq_offset); |
| 310 | 310 | dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n", |
| 311 | 311 | wq->id, i, wq_offset, |
| @@ -539,10 +539,10 @@ static int idxd_wq_config_write(struct idxd_wq *wq) · 227 unmodified lines | ||
| 539 | 539 | if (!wq->group) |
| 540 | 540 | return 0; |
| 541 | 541 | |
| 542 | − memset(&wq->wqcfg, 0, sizeof(union wqcfg)); | |
| 542 | + memset(wq->wqcfg, 0, idxd->wqcfg_size); | |
| 543 | 543 | |
| 544 | 544 | /* byte 0-3 */ |
| 545 | − wq->wqcfg.wq_size = wq->size; | |
| 545 | + wq->wqcfg->wq_size = wq->size; | |
| 546 | 546 | |
| 547 | 547 | if (wq->size == 0) { |
| 548 | 548 | dev_warn(dev, "Incorrect work queue size: 0\n"); |
| @@ -550,22 +550,21 @@ static int idxd_wq_config_write(struct idxd_wq *wq) · 1 unmodified line | ||
| 550 | 550 | } |
| 551 | 551 | |
| 552 | 552 | /* bytes 4-7 */ |
| 553 | − wq->wqcfg.wq_thresh = wq->threshold; | |
| 553 | + wq->wqcfg->wq_thresh = wq->threshold; | |
| 554 | 554 | |
| 555 | 555 | /* byte 8-11 */ |
| 556 | − wq->wqcfg.priv = !!(wq->type == IDXD_WQT_KERNEL); | |
| 557 | − wq->wqcfg.mode = 1; | |
| 558 | − | |
| 559 | − wq->wqcfg.priority = wq->priority; | |
| 556 | + wq->wqcfg->priv = !!(wq->type == IDXD_WQT_KERNEL); | |
| 557 | + wq->wqcfg->mode = 1; | |
| 558 | + wq->wqcfg->priority = wq->priority; | |
| 560 | 559 | |
| 561 | 560 | /* bytes 12-15 */ |
| 562 | − wq->wqcfg.max_xfer_shift = ilog2(wq->max_xfer_bytes); | |
| 563 | − wq->wqcfg.max_batch_shift = ilog2(wq->max_batch_size); | |
| 561 | + wq->wqcfg->max_xfer_shift = ilog2(wq->max_xfer_bytes); | |
| 562 | + wq->wqcfg->max_batch_shift = ilog2(wq->max_batch_size); | |
| 564 | 563 | |
| 565 | 564 | dev_dbg(dev, "WQ %d CFGs\n", wq->id); |
| 566 | − for (i = 0; i < 8; i++) { | |
| 567 | − wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32); | |
| 568 | − iowrite32(wq->wqcfg.bits[i], idxd->reg_base + wq_offset); | |
| 565 | + for (i = 0; i < WQCFG_STRIDES(idxd); i++) { | |
| 566 | + wq_offset = WQCFG_OFFSET(idxd, wq->id, i); | |
| 567 | + iowrite32(wq->wqcfg->bits[i], idxd->reg_base + wq_offset); | |
| 569 | 568 | dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n", |
| 570 | 569 | wq->id, i, wq_offset, |
| 571 | 570 | ioread32(idxd->reg_base + wq_offset)); |
| @@ -103,7 +103,7 @@ struct idxd_wq { · 102 unmodified lines | ||
| 103 | 103 | u32 priority; |
| 104 | 104 | enum idxd_wq_state state; |
| 105 | 105 | unsigned long flags; |
| 106 | − union wqcfg wqcfg; | |
| 106 | + union wqcfg *wqcfg; | |
| 107 | 107 | u32 vec_ptr; /* interrupt steering */ |
| 108 | 108 | struct dsa_hw_desc **hw_descs; |
| 109 | 109 | int num_descs; |
| @@ -183,6 +183,7 @@ struct idxd_device { · 73 unmodified lines | ||
| 183 | 183 | int max_wq_size; |
| 184 | 184 | int token_limit; |
| 185 | 185 | int nr_tokens; /* non-reserved tokens */ |
| 186 | + unsigned int wqcfg_size; | |
| 186 | 187 | |
| 187 | 188 | union sw_err_reg sw_err; |
| 188 | 189 | wait_queue_head_t cmd_waitq; |
| @@ -178,6 +178,9 @@ static int idxd_setup_internals(struct idxd_device *idxd) · 177 unmodified lines | ||
| 178 | 178 | wq->idxd_cdev.minor = -1; |
| 179 | 179 | wq->max_xfer_bytes = idxd->max_xfer_bytes; |
| 180 | 180 | wq->max_batch_size = idxd->max_batch_size; |
| 181 | + wq->wqcfg = devm_kzalloc(dev, idxd->wqcfg_size, GFP_KERNEL); | |
| 182 | + if (!wq->wqcfg) | |
| 183 | + return -ENOMEM; | |
| 181 | 184 | } |
| 182 | 185 | |
| 183 | 186 | for (i = 0; i < idxd->max_engines; i++) { |
| @@ -251,6 +254,8 @@ static void idxd_read_caps(struct idxd_device *idxd) · 67 unmodified lines | ||
| 251 | 254 | dev_dbg(dev, "total workqueue size: %u\n", idxd->max_wq_size); |
| 252 | 255 | idxd->max_wqs = idxd->hw.wq_cap.num_wqs; |
| 253 | 256 | dev_dbg(dev, "max workqueues: %u\n", idxd->max_wqs); |
| 257 | + idxd->wqcfg_size = 1 << (idxd->hw.wq_cap.wqcfg_size + IDXD_WQCFG_MIN); | |
| 258 | + dev_dbg(dev, "wqcfg size: %u\n", idxd->wqcfg_size); | |
| 254 | 259 | |
| 255 | 260 | /* reading operation capabilities */ |
| 256 | 261 | for (i = 0; i < 4; i++) { |
| @@ -8,7 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | #define IDXD_MMIO_BAR 0 |
| 10 | 10 | #define IDXD_WQ_BAR 2 |
| 11 | −#define IDXD_PORTAL_SIZE 0x4000 | |
| 11 | +#define IDXD_PORTAL_SIZE PAGE_SIZE | |
| 12 | 12 | |
| 13 | 13 | /* MMIO Device BAR0 Registers */ |
| 14 | 14 | #define IDXD_VER_OFFSET 0x00 |
| @@ -43,7 +43,8 @@ union wq_cap_reg { · 28 unmodified lines | ||
| 43 | 43 | struct { |
| 44 | 44 | u64 total_wq_size:16; |
| 45 | 45 | u64 num_wqs:8; |
| 46 | − u64 rsvd:24; | |
| 46 | + u64 wqcfg_size:4; | |
| 47 | + u64 rsvd:20; | |
| 47 | 48 | u64 shared_mode:1; |
| 48 | 49 | u64 dedicated_mode:1; |
| 49 | 50 | u64 rsvd2:1; |
| @@ -55,6 +56,7 @@ union wq_cap_reg { · 5 unmodified lines | ||
| 55 | 56 | u64 bits; |
| 56 | 57 | } __packed; |
| 57 | 58 | #define IDXD_WQCAP_OFFSET 0x20 |
| 59 | +#define IDXD_WQCFG_MIN 5 | |
| 58 | 60 | |
| 59 | 61 | union group_cap_reg { |
| 60 | 62 | struct { |
| @@ -333,4 +335,23 @@ union wqcfg { · 272 unmodified lines | ||
| 333 | 335 | }; |
| 334 | 336 | u32 bits[8]; |
| 335 | 337 | } __packed; |
| 338 | + | |
| 339 | +/* | |
| 340 | + * This macro calculates the offset into the WQCFG register | |
| 341 | + * idxd - struct idxd * | |
| 342 | + * n - wq id | |
| 343 | + * ofs - the index of the 32b dword for the config register | |
| 344 | + * | |
| 345 | + * The WQCFG register block is divided into groups per each wq. The n index | |
| 346 | + * allows us to move to the register group that's for that particular wq. | |
| 347 | + * Each register is 32bits. The ofs gives us the number of register to access. | |
| 348 | + */ | |
| 349 | +#define WQCFG_OFFSET(_idxd_dev, n, ofs) \ | |
| 350 | +({\ | |
| 351 | + typeof(_idxd_dev) __idxd_dev = (_idxd_dev); \ | |
| 352 | + (__idxd_dev)->wqcfg_offset + (n) * (__idxd_dev)->wqcfg_size + sizeof(u32) * (ofs); \ | |
| 353 | +}) | |
| 354 | + | |
| 355 | +#define WQCFG_STRIDES(_idxd_dev) ((_idxd_dev)->wqcfg_size / sizeof(u32)) | |
| 356 | + | |
| 336 | 357 | #endif |
| @@ -74,7 +74,7 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc) · 73 unmodified lines | ||
| 74 | 74 | if (idxd->state != IDXD_DEV_ENABLED) |
| 75 | 75 | return -EIO; |
| 76 | 76 | |
| 77 | − portal = wq->dportal + idxd_get_wq_portal_offset(IDXD_PORTAL_UNLIMITED); | |
| 77 | + portal = wq->dportal; | |
| 78 | 78 | /* |
| 79 | 79 | * The wmb() flushes writes to coherent DMA data before possibly |
| 80 | 80 | * triggering a DMA read. The wmb() is necessary even on UP because |
| @@ -40,16 +40,6 @@ · 39 unmodified lines | ||
| 40 | 40 | #define DCA2_TAG_MAP_BYTE3 0x82 |
| 41 | 41 | #define DCA2_TAG_MAP_BYTE4 0x82 |
| 42 | 42 | |
| 43 | −/* verify if tag map matches expected values */ | |
| 44 | −static inline int dca2_tag_map_valid(u8 *tag_map) | |
| 45 | −{ | |
| 46 | − return ((tag_map[0] == DCA2_TAG_MAP_BYTE0) && | |
| 47 | − (tag_map[1] == DCA2_TAG_MAP_BYTE1) && | |
| 48 | − (tag_map[2] == DCA2_TAG_MAP_BYTE2) && | |
| 49 | − (tag_map[3] == DCA2_TAG_MAP_BYTE3) && | |
| 50 | − (tag_map[4] == DCA2_TAG_MAP_BYTE4)); | |
| 51 | −} | |
| 52 | − | |
| 53 | 43 | /* |
| 54 | 44 | * "Legacy" DCA systems do not implement the DCA register set in the |
| 55 | 45 | * I/OAT device. Software needs direct support for their tag mappings. |
| @@ -2799,7 +2799,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, · 2798 unmodified lines | ||
| 2799 | 2799 | * If burst size is smaller than bus width then make sure we only |
| 2800 | 2800 | * transfer one at a time to avoid a burst stradling an MFIFO entry. |
| 2801 | 2801 | */ |
| 2802 | − if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width) | |
| 2802 | + if (burst * 8 < pl330->pcfg.data_bus_width) | |
| 2803 | 2803 | desc->rqcfg.brst_len = 1; |
| 2804 | 2804 | |
| 2805 | 2805 | desc->bytes_requested = len; |
| @@ -83,7 +83,7 @@ EXPORT_SYMBOL(xudma_rflow_is_gp); · 82 unmodified lines | ||
| 83 | 83 | #define XUDMA_GET_PUT_RESOURCE(res) \ |
| 84 | 84 | struct udma_##res *xudma_##res##_get(struct udma_dev *ud, int id) \ |
| 85 | 85 | { \ |
| 86 | − return __udma_reserve_##res(ud, false, id); \ | |
| 86 | + return __udma_reserve_##res(ud, UDMA_TP_NORMAL, id); \ | |
| 87 | 87 | } \ |
| 88 | 88 | EXPORT_SYMBOL(xudma_##res##_get); \ |
| 89 | 89 | \ |
| @@ -1522,29 +1522,38 @@ static void omap_dma_free(struct omap_dmadev *od) · 1521 unmodified lines | ||
| 1522 | 1522 | } |
| 1523 | 1523 | } |
| 1524 | 1524 | |
| 1525 | +/* Currently used by omap2 & 3 to block deeper SoC idle states */ | |
| 1526 | +static bool omap_dma_busy(struct omap_dmadev *od) | |
| 1527 | +{ | |
| 1528 | + struct omap_chan *c; | |
| 1529 | + int lch = -1; | |
| 1530 | + | |
| 1531 | + while (1) { | |
| 1532 | + lch = find_next_bit(od->lch_bitmap, od->lch_count, lch + 1); | |
| 1533 | + if (lch >= od->lch_count) | |
| 1534 | + break; | |
| 1535 | + c = od->lch_map[lch]; | |
| 1536 | + if (!c) | |
| 1537 | + continue; | |
| 1538 | + if (omap_dma_chan_read(c, CCR) & CCR_ENABLE) | |
| 1539 | + return true; | |
| 1540 | + } | |
| 1541 | + | |
| 1542 | + return false; | |
| 1543 | +} | |
| 1544 | + | |
| 1525 | 1545 | /* Currently only used for omap2. For omap1, also a check for lcd_dma is needed */ |
| 1526 | 1546 | static int omap_dma_busy_notifier(struct notifier_block *nb, |
| 1527 | 1547 | unsigned long cmd, void *v) |
| 1528 | 1548 | { |
| 1529 | 1549 | struct omap_dmadev *od; |
| 1530 | − struct omap_chan *c; | |
| 1531 | − int lch = -1; | |
| 1532 | 1550 | |
| 1533 | 1551 | od = container_of(nb, struct omap_dmadev, nb); |
| 1534 | 1552 | |
| 1535 | 1553 | switch (cmd) { |
| 1536 | 1554 | case CPU_CLUSTER_PM_ENTER: |
| 1537 | − while (1) { | |
| 1538 | − lch = find_next_bit(od->lch_bitmap, od->lch_count, | |
| 1539 | − lch + 1); | |
| 1540 | − if (lch >= od->lch_count) | |
| 1541 | − break; | |
| 1542 | − c = od->lch_map[lch]; | |
| 1543 | − if (!c) | |
| 1544 | − continue; | |
| 1545 | − if (omap_dma_chan_read(c, CCR) & CCR_ENABLE) | |
| 1546 | − return NOTIFY_BAD; | |
| 1547 | − } | |
| 1555 | + if (omap_dma_busy(od)) | |
| 1556 | + return NOTIFY_BAD; | |
| 1548 | 1557 | break; |
| 1549 | 1558 | case CPU_CLUSTER_PM_ENTER_FAILED: |
| 1550 | 1559 | case CPU_CLUSTER_PM_EXIT: |
| @@ -1595,6 +1604,8 @@ static int omap_dma_context_notifier(struct notifier_block *nb, · 44 unmodified lines | ||
| 1595 | 1604 | |
| 1596 | 1605 | switch (cmd) { |
| 1597 | 1606 | case CPU_CLUSTER_PM_ENTER: |
| 1607 | + if (omap_dma_busy(od)) | |
| 1608 | + return NOTIFY_BAD; | |
| 1598 | 1609 | omap_dma_context_save(od); |
| 1599 | 1610 | break; |
| 1600 | 1611 | case CPU_CLUSTER_PM_ENTER_FAILED: |
| @@ -517,8 +517,8 @@ struct xilinx_dma_device { · 516 unmodified lines | ||
| 517 | 517 | #define to_dma_tx_descriptor(tx) \ |
| 518 | 518 | container_of(tx, struct xilinx_dma_tx_descriptor, async_tx) |
| 519 | 519 | #define xilinx_dma_poll_timeout(chan, reg, val, cond, delay_us, timeout_us) \ |
| 520 | − readl_poll_timeout(chan->xdev->regs + chan->ctrl_offset + reg, val, \ | |
| 521 | − cond, delay_us, timeout_us) | |
| 520 | + readl_poll_timeout_atomic(chan->xdev->regs + chan->ctrl_offset + reg, \ | |
| 521 | + val, cond, delay_us, timeout_us) | |
| 522 | 522 | |
| 523 | 523 | /* IO accessors */ |
| 524 | 524 | static inline u32 dma_read(struct xilinx_dma_chan *chan, u32 reg) |
| @@ -948,8 +948,10 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan, · 423 unmodified lines | ||
| 948 | 948 | { |
| 949 | 949 | struct xilinx_cdma_tx_segment *cdma_seg; |
| 950 | 950 | struct xilinx_axidma_tx_segment *axidma_seg; |
| 951 | + struct xilinx_aximcdma_tx_segment *aximcdma_seg; | |
| 951 | 952 | struct xilinx_cdma_desc_hw *cdma_hw; |
| 952 | 953 | struct xilinx_axidma_desc_hw *axidma_hw; |
| 954 | + struct xilinx_aximcdma_desc_hw *aximcdma_hw; | |
| 953 | 955 | struct list_head *entry; |
| 954 | 956 | u32 residue = 0; |
| 955 | 957 | |
| @@ -961,13 +963,23 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan, · 5 unmodified lines | ||
| 961 | 963 | cdma_hw = &cdma_seg->hw; |
| 962 | 964 | residue += (cdma_hw->control - cdma_hw->status) & |
| 963 | 965 | chan->xdev->max_buffer_len; |
| 964 | − } else { | |
| 966 | + } else if (chan->xdev->dma_config->dmatype == | |
| 967 | + XDMA_TYPE_AXIDMA) { | |
| 965 | 968 | axidma_seg = list_entry(entry, |
| 966 | 969 | struct xilinx_axidma_tx_segment, |
| 967 | 970 | node); |
| 968 | 971 | axidma_hw = &axidma_seg->hw; |
| 969 | 972 | residue += (axidma_hw->control - axidma_hw->status) & |
| 970 | 973 | chan->xdev->max_buffer_len; |
| 974 | + } else { | |
| 975 | + aximcdma_seg = | |
| 976 | + list_entry(entry, | |
| 977 | + struct xilinx_aximcdma_tx_segment, | |
| 978 | + node); | |
| 979 | + aximcdma_hw = &aximcdma_seg->hw; | |
| 980 | + residue += | |
| 981 | + (aximcdma_hw->control - aximcdma_hw->status) & | |
| 982 | + chan->xdev->max_buffer_len; | |
| 971 | 983 | } |
| 972 | 984 | } |
| 973 | 985 | |
| @@ -1135,7 +1147,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan) · 161 unmodified lines | ||
| 1135 | 1147 | upper_32_bits(chan->seg_p + sizeof(*chan->seg_mv) * |
| 1136 | 1148 | ((i + 1) % XILINX_DMA_NUM_DESCS)); |
| 1137 | 1149 | chan->seg_mv[i].phys = chan->seg_p + |
| 1138 | − sizeof(*chan->seg_v) * i; | |
| 1150 | + sizeof(*chan->seg_mv) * i; | |
| 1139 | 1151 | list_add_tail(&chan->seg_mv[i].node, |
| 1140 | 1152 | &chan->free_seg_list); |
| 1141 | 1153 | } |
| @@ -1560,7 +1572,7 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan) · 418 unmodified lines | ||
| 1560 | 1572 | static void xilinx_mcdma_start_transfer(struct xilinx_dma_chan *chan) |
| 1561 | 1573 | { |
| 1562 | 1574 | struct xilinx_dma_tx_descriptor *head_desc, *tail_desc; |
| 1563 | − struct xilinx_axidma_tx_segment *tail_segment; | |
| 1575 | + struct xilinx_aximcdma_tx_segment *tail_segment; | |
| 1564 | 1576 | u32 reg; |
| 1565 | 1577 | |
| 1566 | 1578 | /* |
| @@ -1582,7 +1594,7 @@ static void xilinx_mcdma_start_transfer(struct xilinx_dma_chan *chan) · 15 unmodified lines | ||
| 1582 | 1594 | tail_desc = list_last_entry(&chan->pending_list, |
| 1583 | 1595 | struct xilinx_dma_tx_descriptor, node); |
| 1584 | 1596 | tail_segment = list_last_entry(&tail_desc->segments, |
| 1585 | − struct xilinx_axidma_tx_segment, node); | |
| 1597 | + struct xilinx_aximcdma_tx_segment, node); | |
| 1586 | 1598 | |
| 1587 | 1599 | reg = dma_ctrl_read(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest)); |
| 1588 | 1600 | |
| @@ -1864,6 +1876,7 @@ static void append_desc_queue(struct xilinx_dma_chan *chan, · 275 unmodified lines | ||
| 1864 | 1876 | struct xilinx_vdma_tx_segment *tail_segment; |
| 1865 | 1877 | struct xilinx_dma_tx_descriptor *tail_desc; |
| 1866 | 1878 | struct xilinx_axidma_tx_segment *axidma_tail_segment; |
| 1879 | + struct xilinx_aximcdma_tx_segment *aximcdma_tail_segment; | |
| 1867 | 1880 | struct xilinx_cdma_tx_segment *cdma_tail_segment; |
| 1868 | 1881 | |
| 1869 | 1882 | if (list_empty(&chan->pending_list)) |
| @@ -1885,11 +1898,17 @@ static void append_desc_queue(struct xilinx_dma_chan *chan, · 15 unmodified lines | ||
| 1885 | 1898 | struct xilinx_cdma_tx_segment, |
| 1886 | 1899 | node); |
| 1887 | 1900 | cdma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys; |
| 1888 | − } else { | |
| 1901 | + } else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) { | |
| 1889 | 1902 | axidma_tail_segment = list_last_entry(&tail_desc->segments, |
| 1890 | 1903 | struct xilinx_axidma_tx_segment, |
| 1891 | 1904 | node); |
| 1892 | 1905 | axidma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys; |
| 1906 | + } else { | |
| 1907 | + aximcdma_tail_segment = | |
| 1908 | + list_last_entry(&tail_desc->segments, | |
| 1909 | + struct xilinx_aximcdma_tx_segment, | |
| 1910 | + node); | |
| 1911 | + aximcdma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys; | |
| 1893 | 1912 | } |
| 1894 | 1913 | |
| 1895 | 1914 | /* |
| @@ -2836,10 +2855,11 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, · 940 unmodified lines | ||
| 2836 | 2855 | chan->stop_transfer = xilinx_dma_stop_transfer; |
| 2837 | 2856 | } |
| 2838 | 2857 | |
| 2839 | − /* check if SG is enabled (only for AXIDMA and CDMA) */ | |
| 2858 | + /* check if SG is enabled (only for AXIDMA, AXIMCDMA, and CDMA) */ | |
| 2840 | 2859 | if (xdev->dma_config->dmatype != XDMA_TYPE_VDMA) { |
| 2841 | − if (dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) & | |
| 2842 | − XILINX_DMA_DMASR_SG_MASK) | |
| 2860 | + if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA || | |
| 2861 | + dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) & | |
| 2862 | + XILINX_DMA_DMASR_SG_MASK) | |
| 2843 | 2863 | chan->has_sg = true; |
| 2844 | 2864 | dev_dbg(chan->dev, "ch %d: SG %s\n", chan->id, |
| 2845 | 2865 | chan->has_sg ? "enabled" : "disabled"); |
| @@ -20,12 +20,28 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/of_platform.h> |
| 21 | 21 | #include <linux/slab.h> |
| 22 | 22 | #include <linux/uaccess.h> |
| 23 | +#include <linux/hashtable.h> | |
| 23 | 24 | |
| 24 | 25 | #include <linux/firmware/xlnx-zynqmp.h> |
| 25 | 26 | #include "zynqmp-debug.h" |
| 26 | 27 | |
| 28 | +/* Max HashMap Order for PM API feature check (1<<7 = 128) */ | |
| 29 | +#define PM_API_FEATURE_CHECK_MAX_ORDER 7 | |
| 30 | + | |
| 27 | 31 | static bool feature_check_enabled; |
| 28 | −static u32 zynqmp_pm_features[PM_API_MAX]; | |
| 32 | +DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER); | |
| 33 | + | |
| 34 | +/** | |
| 35 | + * struct pm_api_feature_data - PM API Feature data | |
| 36 | + * @pm_api_id: PM API Id, used as key to index into hashmap | |
| 37 | + * @feature_status: status of PM API feature: valid, invalid | |
| 38 | + * @hentry: hlist_node that hooks this entry into hashtable | |
| 39 | + */ | |
| 40 | +struct pm_api_feature_data { | |
| 41 | + u32 pm_api_id; | |
| 42 | + int feature_status; | |
| 43 | + struct hlist_node hentry; | |
| 44 | +}; | |
| 29 | 45 | |
| 30 | 46 | static const struct mfd_cell firmware_devs[] = { |
| 31 | 47 | { |
| @@ -142,29 +158,37 @@ static int zynqmp_pm_feature(u32 api_id) · 110 unmodified lines | ||
| 142 | 158 | int ret; |
| 143 | 159 | u32 ret_payload[PAYLOAD_ARG_CNT]; |
| 144 | 160 | u64 smc_arg[2]; |
| 161 | + struct pm_api_feature_data *feature_data; | |
| 145 | 162 | |
| 146 | 163 | if (!feature_check_enabled) |
| 147 | 164 | return 0; |
| 148 | 165 | |
| 149 | − /* Return value if feature is already checked */ | |
| 150 | − if (api_id > ARRAY_SIZE(zynqmp_pm_features)) | |
| 151 | − return PM_FEATURE_INVALID; | |
| 166 | + /* Check for existing entry in hash table for given api */ | |
| 167 | + hash_for_each_possible(pm_api_features_map, feature_data, hentry, | |
| 168 | + api_id) { | |
| 169 | + if (feature_data->pm_api_id == api_id) | |
| 170 | + return feature_data->feature_status; | |
| 171 | + } | |
| 152 | 172 | |
| 153 | − if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED) | |
| 154 | − return zynqmp_pm_features[api_id]; | |
| 173 | + /* Add new entry if not present */ | |
| 174 | + feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL); | |
| 175 | + if (!feature_data) | |
| 176 | + return -ENOMEM; | |
| 155 | 177 | |
| 178 | + feature_data->pm_api_id = api_id; | |
| 156 | 179 | smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK; |
| 157 | 180 | smc_arg[1] = api_id; |
| 158 | 181 | |
| 159 | 182 | ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload); |
| 160 | − if (ret) { | |
| 161 | − zynqmp_pm_features[api_id] = PM_FEATURE_INVALID; | |
| 162 | − return PM_FEATURE_INVALID; | |
| 163 | − } | |
| 183 | + if (ret) | |
| 184 | + ret = -EOPNOTSUPP; | |
| 185 | + else | |
| 186 | + ret = ret_payload[1]; | |
| 164 | 187 | |
| 165 | − zynqmp_pm_features[api_id] = ret_payload[1]; | |
| 188 | + feature_data->feature_status = ret; | |
| 189 | + hash_add(pm_api_features_map, &feature_data->hentry, api_id); | |
| 166 | 190 | |
| 167 | − return zynqmp_pm_features[api_id]; | |
| 191 | + return ret; | |
| 168 | 192 | } |
| 169 | 193 | |
| 170 | 194 | /** |
| @@ -200,9 +224,12 @@ int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1, · 29 unmodified lines | ||
| 200 | 224 | * Make sure to stay in x0 register |
| 201 | 225 | */ |
| 202 | 226 | u64 smc_arg[4]; |
| 227 | + int ret; | |
| 203 | 228 | |
| 204 | − if (zynqmp_pm_feature(pm_api_id) == PM_FEATURE_INVALID) | |
| 205 | − return -ENOTSUPP; | |
| 229 | + /* Check if feature is supported or not */ | |
| 230 | + ret = zynqmp_pm_feature(pm_api_id); | |
| 231 | + if (ret < 0) | |
| 232 | + return ret; | |
| 206 | 233 | |
| 207 | 234 | smc_arg[0] = PM_SIP_SVC | pm_api_id; |
| 208 | 235 | smc_arg[1] = ((u64)arg1 << 32) | arg0; |
| @@ -615,7 +642,7 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay); · 406 unmodified lines | ||
| 615 | 642 | */ |
| 616 | 643 | int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type) |
| 617 | 644 | { |
| 618 | − return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY, | |
| 645 | + return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET, | |
| 619 | 646 | type, 0, NULL); |
| 620 | 647 | } |
| 621 | 648 | EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset); |
| @@ -1252,9 +1279,17 @@ static int zynqmp_firmware_probe(struct platform_device *pdev) · 630 unmodified lines | ||
| 1252 | 1279 | |
| 1253 | 1280 | static int zynqmp_firmware_remove(struct platform_device *pdev) |
| 1254 | 1281 | { |
| 1282 | + struct pm_api_feature_data *feature_data; | |
| 1283 | + int i; | |
| 1284 | + | |
| 1255 | 1285 | mfd_remove_devices(&pdev->dev); |
| 1256 | 1286 | zynqmp_pm_api_debugfs_exit(); |
| 1257 | 1287 | |
| 1288 | + hash_for_each(pm_api_features_map, i, feature_data, hentry) { | |
| 1289 | + hash_del(&feature_data->hentry); | |
| 1290 | + kfree(feature_data); | |
| 1291 | + } | |
| 1292 | + | |
| 1258 | 1293 | return 0; |
| 1259 | 1294 | } |
| 1260 | 1295 | |
| @@ -4852,7 +4852,7 @@ int amdgpu_device_baco_enter(struct drm_device *dev) · 4851 unmodified lines | ||
| 4852 | 4852 | if (!amdgpu_device_supports_baco(adev_to_drm(adev))) |
| 4853 | 4853 | return -ENOTSUPP; |
| 4854 | 4854 | |
| 4855 | − if (ras && ras->supported) | |
| 4855 | + if (ras && ras->supported && adev->nbio.funcs->enable_doorbell_interrupt) | |
| 4856 | 4856 | adev->nbio.funcs->enable_doorbell_interrupt(adev, false); |
| 4857 | 4857 | |
| 4858 | 4858 | return amdgpu_dpm_baco_enter(adev); |
| @@ -4871,7 +4871,7 @@ int amdgpu_device_baco_exit(struct drm_device *dev) · 12 unmodified lines | ||
| 4871 | 4871 | if (ret) |
| 4872 | 4872 | return ret; |
| 4873 | 4873 | |
| 4874 | − if (ras && ras->supported) | |
| 4874 | + if (ras && ras->supported && adev->nbio.funcs->enable_doorbell_interrupt) | |
| 4875 | 4875 | adev->nbio.funcs->enable_doorbell_interrupt(adev, true); |
| 4876 | 4876 | |
| 4877 | 4877 | return 0; |
| @@ -1055,10 +1055,10 @@ static const struct pci_device_id pciidlist[] = { · 1054 unmodified lines | ||
| 1055 | 1055 | {0x1002, 0x15dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU}, |
| 1056 | 1056 | {0x1002, 0x15d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RAVEN|AMD_IS_APU}, |
| 1057 | 1057 | /* Arcturus */ |
| 1058 | − {0x1002, 0x738C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS|AMD_EXP_HW_SUPPORT}, | |
| 1059 | − {0x1002, 0x7388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS|AMD_EXP_HW_SUPPORT}, | |
| 1060 | − {0x1002, 0x738E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS|AMD_EXP_HW_SUPPORT}, | |
| 1061 | − {0x1002, 0x7390, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS|AMD_EXP_HW_SUPPORT}, | |
| 1058 | + {0x1002, 0x738C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS}, | |
| 1059 | + {0x1002, 0x7388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS}, | |
| 1060 | + {0x1002, 0x738E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS}, | |
| 1061 | + {0x1002, 0x7390, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARCTURUS}, | |
| 1062 | 1062 | /* Navi10 */ |
| 1063 | 1063 | {0x1002, 0x7310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10}, |
| 1064 | 1064 | {0x1002, 0x7312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10}, |
| @@ -69,10 +69,10 @@ static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev, · 68 unmodified lines | ||
| 69 | 69 | |
| 70 | 70 | static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev, |
| 71 | 71 | unsigned int type, |
| 72 | − uint64_t size) | |
| 72 | + uint64_t size_in_page) | |
| 73 | 73 | { |
| 74 | 74 | return ttm_range_man_init(&adev->mman.bdev, type, |
| 75 | − false, size >> PAGE_SHIFT); | |
| 75 | + false, size_in_page); | |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | /** |
| @@ -67,6 +67,7 @@ struct amdgpu_uvd { · 66 unmodified lines | ||
| 67 | 67 | unsigned harvest_config; |
| 68 | 68 | /* store image width to adjust nb memory state */ |
| 69 | 69 | unsigned decode_image_width; |
| 70 | + uint32_t keyselect; | |
| 70 | 71 | }; |
| 71 | 72 | |
| 72 | 73 | int amdgpu_uvd_sw_init(struct amdgpu_device *adev); |
| @@ -3105,6 +3105,8 @@ static const struct soc15_reg_golden golden_settings_gc_10_3[] = · 3104 unmodified lines | ||
| 3105 | 3105 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000280), |
| 3106 | 3106 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x00800000), |
| 3107 | 3107 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_EXCEPTION_CONTROL, 0x7fff0f1f, 0x00b80000), |
| 3108 | + SOC15_REG_GOLDEN_VALUE(GC, 0 ,mmGCEA_SDP_TAG_RESERVE0, 0xffffffff, 0x10100100), | |
| 3109 | + SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCEA_SDP_TAG_RESERVE1, 0xffffffff, 0x17000088), | |
| 3108 | 3110 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL_Sienna_Cichlid, 0x1ff1ffff, 0x00000500), |
| 3109 | 3111 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmGE_PC_CNTL, 0x003fffff, 0x00280400), |
| 3110 | 3112 | SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xffffffcf), |
| @@ -277,15 +277,8 @@ static void uvd_v3_1_mc_resume(struct amdgpu_device *adev) · 276 unmodified lines | ||
| 277 | 277 | */ |
| 278 | 278 | static int uvd_v3_1_fw_validate(struct amdgpu_device *adev) |
| 279 | 279 | { |
| 280 | − void *ptr; | |
| 281 | − uint32_t ucode_len, i; | |
| 282 | − uint32_t keysel; | |
| 283 | − | |
| 284 | − ptr = adev->uvd.inst[0].cpu_addr; | |
| 285 | − ptr += 192 + 16; | |
| 286 | − memcpy(&ucode_len, ptr, 4); | |
| 287 | − ptr += ucode_len; | |
| 288 | − memcpy(&keysel, ptr, 4); | |
| 280 | + int i; | |
| 281 | + uint32_t keysel = adev->uvd.keyselect; | |
| 289 | 282 | |
| 290 | 283 | WREG32(mmUVD_FW_START, keysel); |
| 291 | 284 | |
| @@ -550,6 +543,8 @@ static int uvd_v3_1_sw_init(void *handle) · 258 unmodified lines | ||
| 550 | 543 | struct amdgpu_ring *ring; |
| 551 | 544 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 552 | 545 | int r; |
| 546 | + void *ptr; | |
| 547 | + uint32_t ucode_len; | |
| 553 | 548 | |
| 554 | 549 | /* UVD TRAP */ |
| 555 | 550 | r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 124, &adev->uvd.inst->irq); |
| @@ -571,6 +566,13 @@ static int uvd_v3_1_sw_init(void *handle) · 15 unmodified lines | ||
| 571 | 566 | if (r) |
| 572 | 567 | return r; |
| 573 | 568 | |
| 569 | + /* Retrieval firmware validate key */ | |
| 570 | + ptr = adev->uvd.inst[0].cpu_addr; | |
| 571 | + ptr += 192 + 16; | |
| 572 | + memcpy(&ucode_len, ptr, 4); | |
| 573 | + ptr += ucode_len; | |
| 574 | + memcpy(&adev->uvd.keyselect, ptr, 4); | |
| 575 | + | |
| 574 | 576 | r = amdgpu_uvd_entity_init(adev); |
| 575 | 577 | |
| 576 | 578 | return r; |
| @@ -1041,7 +1041,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) · 1040 unmodified lines | ||
| 1041 | 1041 | amdgpu_dm_init_color_mod(); |
| 1042 | 1042 | |
| 1043 | 1043 | #ifdef CONFIG_DRM_AMD_DC_HDCP |
| 1044 | − if (adev->asic_type >= CHIP_RAVEN) { | |
| 1044 | + if (adev->dm.dc->caps.max_links > 0 && adev->asic_type >= CHIP_RAVEN) { | |
| 1045 | 1045 | adev->dm.hdcp_workqueue = hdcp_create_workqueue(adev, &init_params.cp_psp, adev->dm.dc); |
| 1046 | 1046 | |
| 1047 | 1047 | if (!adev->dm.hdcp_workqueue) |
| @@ -7506,7 +7506,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 6458 unmodified lines | ||
| 7506 | 7506 | bool mode_set_reset_required = false; |
| 7507 | 7507 | |
| 7508 | 7508 | drm_atomic_helper_update_legacy_modeset_state(dev, state); |
| 7509 | − drm_atomic_helper_calc_timestamping_constants(state); | |
| 7510 | 7509 | |
| 7511 | 7510 | dm_state = dm_atomic_get_new_state(state); |
| 7512 | 7511 | if (dm_state && dm_state->context) { |
| @@ -7533,6 +7532,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 20 unmodified lines | ||
| 7533 | 7532 | } |
| 7534 | 7533 | } |
| 7535 | 7534 | |
| 7535 | + drm_atomic_helper_calc_timestamping_constants(state); | |
| 7536 | + | |
| 7536 | 7537 | /* update changed items */ |
| 7537 | 7538 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
| 7538 | 7539 | struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); |
| @@ -299,8 +299,8 @@ irq_source_info_dcn20[DAL_IRQ_SOURCES_NUMBER] = { · 298 unmodified lines | ||
| 299 | 299 | pflip_int_entry(1), |
| 300 | 300 | pflip_int_entry(2), |
| 301 | 301 | pflip_int_entry(3), |
| 302 | − [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(), | |
| 303 | − [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(), | |
| 302 | + pflip_int_entry(4), | |
| 303 | + pflip_int_entry(5), | |
| 304 | 304 | [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), |
| 305 | 305 | gpio_pad_int_entry(0), |
| 306 | 306 | gpio_pad_int_entry(1), |
| @@ -742,7 +742,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) · 741 unmodified lines | ||
| 742 | 742 | case DRM_MODE_DPMS_SUSPEND: |
| 743 | 743 | if (ast->tx_chip_type == AST_TX_DP501) |
| 744 | 744 | ast_set_dp501_video_output(crtc->dev, 1); |
| 745 | − ast_crtc_load_lut(ast, crtc); | |
| 746 | 745 | break; |
| 747 | 746 | case DRM_MODE_DPMS_OFF: |
| 748 | 747 | if (ast->tx_chip_type == AST_TX_DP501) |
| @@ -777,6 +776,21 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, · 28 unmodified lines | ||
| 777 | 776 | return 0; |
| 778 | 777 | } |
| 779 | 778 | |
| 779 | +static void | |
| 780 | +ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) | |
| 781 | +{ | |
| 782 | + struct ast_private *ast = to_ast_private(crtc->dev); | |
| 783 | + struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc->state); | |
| 784 | + struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state); | |
| 785 | + | |
| 786 | + /* | |
| 787 | + * The gamma LUT has to be reloaded after changing the primary | |
| 788 | + * plane's color format. | |
| 789 | + */ | |
| 790 | + if (old_ast_crtc_state->format != ast_crtc_state->format) | |
| 791 | + ast_crtc_load_lut(ast, crtc); | |
| 792 | +} | |
| 793 | + | |
| 780 | 794 | static void |
| 781 | 795 | ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, |
| 782 | 796 | struct drm_crtc_state *old_crtc_state) |
| @@ -830,6 +844,7 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, · 47 unmodified lines | ||
| 830 | 844 | |
| 831 | 845 | static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { |
| 832 | 846 | .atomic_check = ast_crtc_helper_atomic_check, |
| 847 | + .atomic_flush = ast_crtc_helper_atomic_flush, | |
| 833 | 848 | .atomic_enable = ast_crtc_helper_atomic_enable, |
| 834 | 849 | .atomic_disable = ast_crtc_helper_atomic_disable, |
| 835 | 850 | }; |
| @@ -2327,12 +2327,6 @@ static enum drm_connector_status dw_hdmi_detect(struct dw_hdmi *hdmi) · 2326 unmodified lines | ||
| 2327 | 2327 | { |
| 2328 | 2328 | enum drm_connector_status result; |
| 2329 | 2329 | |
| 2330 | − mutex_lock(&hdmi->mutex); | |
| 2331 | − hdmi->force = DRM_FORCE_UNSPECIFIED; | |
| 2332 | − dw_hdmi_update_power(hdmi); | |
| 2333 | − dw_hdmi_update_phy_mask(hdmi); | |
| 2334 | − mutex_unlock(&hdmi->mutex); | |
| 2335 | − | |
| 2336 | 2330 | result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); |
| 2337 | 2331 | |
| 2338 | 2332 | mutex_lock(&hdmi->mutex); |
| @@ -140,7 +140,7 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, · 139 unmodified lines | ||
| 140 | 140 | unsigned int c = 0; |
| 141 | 141 | |
| 142 | 142 | if (pl_flag & DRM_GEM_VRAM_PL_FLAG_TOPDOWN) |
| 143 | − pl_flag = TTM_PL_FLAG_TOPDOWN; | |
| 143 | + invariant_flags = TTM_PL_FLAG_TOPDOWN; | |
| 144 | 144 | |
| 145 | 145 | gbo->placement.placement = gbo->placements; |
| 146 | 146 | gbo->placement.busy_placement = gbo->placements; |
| @@ -1,7 +1,8 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | 2 | config DRM_EXYNOS |
| 3 | 3 | tristate "DRM Support for Samsung SoC Exynos Series" |
| 4 | − depends on OF && DRM && (ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_MULTIPLATFORM || COMPILE_TEST) | |
| 4 | + depends on OF && DRM && COMMON_CLK | |
| 5 | + depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_MULTIPLATFORM || COMPILE_TEST | |
| 5 | 6 | depends on MMU |
| 6 | 7 | select DRM_KMS_HELPER |
| 7 | 8 | select VIDEOMODE_HELPERS |
| @@ -12878,10 +12878,11 @@ compute_sink_pipe_bpp(const struct drm_connector_state *conn_state, · 12877 unmodified lines | ||
| 12878 | 12878 | case 10 ... 11: |
| 12879 | 12879 | bpp = 10 * 3; |
| 12880 | 12880 | break; |
| 12881 | − case 12: | |
| 12881 | + case 12 ... 16: | |
| 12882 | 12882 | bpp = 12 * 3; |
| 12883 | 12883 | break; |
| 12884 | 12884 | default: |
| 12885 | + MISSING_CASE(conn_state->max_bpc); | |
| 12885 | 12886 | return -EINVAL; |
| 12886 | 12887 | } |
| 12887 | 12888 | |
| @@ -30,18 +30,21 @@ · 29 unmodified lines | ||
| 30 | 30 | #include "i915_trace.h" |
| 31 | 31 | #include "intel_breadcrumbs.h" |
| 32 | 32 | #include "intel_context.h" |
| 33 | +#include "intel_engine_pm.h" | |
| 33 | 34 | #include "intel_gt_pm.h" |
| 34 | 35 | #include "intel_gt_requests.h" |
| 35 | 36 | |
| 36 | −static void irq_enable(struct intel_engine_cs *engine) | |
| 37 | +static bool irq_enable(struct intel_engine_cs *engine) | |
| 37 | 38 | { |
| 38 | 39 | if (!engine->irq_enable) |
| 39 | − return; | |
| 40 | + return false; | |
| 40 | 41 | |
| 41 | 42 | /* Caller disables interrupts */ |
| 42 | 43 | spin_lock(&engine->gt->irq_lock); |
| 43 | 44 | engine->irq_enable(engine); |
| 44 | 45 | spin_unlock(&engine->gt->irq_lock); |
| 46 | + | |
| 47 | + return true; | |
| 45 | 48 | } |
| 46 | 49 | |
| 47 | 50 | static void irq_disable(struct intel_engine_cs *engine) |
| @@ -57,12 +60,11 @@ static void irq_disable(struct intel_engine_cs *engine) · 9 unmodified lines | ||
| 57 | 60 | |
| 58 | 61 | static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) |
| 59 | 62 | { |
| 60 | − lockdep_assert_held(&b->irq_lock); | |
| 61 | − | |
| 62 | − if (!b->irq_engine || b->irq_armed) | |
| 63 | − return; | |
| 64 | − | |
| 65 | − if (!intel_gt_pm_get_if_awake(b->irq_engine->gt)) | |
| 63 | + /* | |
| 64 | + * Since we are waiting on a request, the GPU should be busy | |
| 65 | + * and should have its own rpm reference. | |
| 66 | + */ | |
| 67 | + if (GEM_WARN_ON(!intel_gt_pm_get_if_awake(b->irq_engine->gt))) | |
| 66 | 68 | return; |
| 67 | 69 | |
| 68 | 70 | /* |
| @@ -73,25 +75,24 @@ static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) · 4 unmodified lines | ||
| 73 | 75 | */ |
| 74 | 76 | WRITE_ONCE(b->irq_armed, true); |
| 75 | 77 | |
| 76 | − /* | |
| 77 | − * Since we are waiting on a request, the GPU should be busy | |
| 78 | − * and should have its own rpm reference. This is tracked | |
| 79 | − * by i915->gt.awake, we can forgo holding our own wakref | |
| 80 | − * for the interrupt as before i915->gt.awake is released (when | |
| 81 | − * the driver is idle) we disarm the breadcrumbs. | |
| 82 | − */ | |
| 83 | − | |
| 84 | − if (!b->irq_enabled++) | |
| 85 | − irq_enable(b->irq_engine); | |
| 78 | + /* Requests may have completed before we could enable the interrupt. */ | |
| 79 | + if (!b->irq_enabled++ && irq_enable(b->irq_engine)) | |
| 80 | + irq_work_queue(&b->irq_work); | |
| 86 | 81 | } |
| 87 | 82 | |
| 88 | −static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) | |
| 83 | +static void intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) | |
| 89 | 84 | { |
| 90 | − lockdep_assert_held(&b->irq_lock); | |
| 91 | − | |
| 92 | − if (!b->irq_engine || !b->irq_armed) | |
| 85 | + if (!b->irq_engine) | |
| 93 | 86 | return; |
| 94 | 87 | |
| 88 | + spin_lock(&b->irq_lock); | |
| 89 | + if (!b->irq_armed) | |
| 90 | + __intel_breadcrumbs_arm_irq(b); | |
| 91 | + spin_unlock(&b->irq_lock); | |
| 92 | +} | |
| 93 | + | |
| 94 | +static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) | |
| 95 | +{ | |
| 95 | 96 | GEM_BUG_ON(!b->irq_enabled); |
| 96 | 97 | if (!--b->irq_enabled) |
| 97 | 98 | irq_disable(b->irq_engine); |
| @@ -105,8 +106,6 @@ static void add_signaling_context(struct intel_breadcrumbs *b, · 7 unmodified lines | ||
| 105 | 106 | { |
| 106 | 107 | intel_context_get(ce); |
| 107 | 108 | list_add_tail(&ce->signal_link, &b->signalers); |
| 108 | − if (list_is_first(&ce->signal_link, &b->signalers)) | |
| 109 | − __intel_breadcrumbs_arm_irq(b); | |
| 110 | 109 | } |
| 111 | 110 | |
| 112 | 111 | static void remove_signaling_context(struct intel_breadcrumbs *b, |
| @@ -174,34 +173,65 @@ static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl) · 61 unmodified lines | ||
| 174 | 173 | intel_engine_add_retire(b->irq_engine, tl); |
| 175 | 174 | } |
| 176 | 175 | |
| 177 | −static bool __signal_request(struct i915_request *rq, struct list_head *signals) | |
| 176 | +static bool __signal_request(struct i915_request *rq) | |
| 178 | 177 | { |
| 179 | − clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); | |
| 180 | − | |
| 181 | 178 | if (!__dma_fence_signal(&rq->fence)) { |
| 182 | 179 | i915_request_put(rq); |
| 183 | 180 | return false; |
| 184 | 181 | } |
| 185 | 182 | |
| 186 | − list_add_tail(&rq->signal_link, signals); | |
| 187 | 183 | return true; |
| 188 | 184 | } |
| 189 | 185 | |
| 186 | +static struct llist_node * | |
| 187 | +slist_add(struct llist_node *node, struct llist_node *head) | |
| 188 | +{ | |
| 189 | + node->next = head; | |
| 190 | + return node; | |
| 191 | +} | |
| 192 | + | |
| 190 | 193 | static void signal_irq_work(struct irq_work *work) |
| 191 | 194 | { |
| 192 | 195 | struct intel_breadcrumbs *b = container_of(work, typeof(*b), irq_work); |
| 193 | 196 | const ktime_t timestamp = ktime_get(); |
| 197 | + struct llist_node *signal, *sn; | |
| 194 | 198 | struct intel_context *ce, *cn; |
| 195 | 199 | struct list_head *pos, *next; |
| 196 | − LIST_HEAD(signal); | |
| 200 | + | |
| 201 | + signal = NULL; | |
| 202 | + if (unlikely(!llist_empty(&b->signaled_requests))) | |
| 203 | + signal = llist_del_all(&b->signaled_requests); | |
| 197 | 204 | |
| 198 | 205 | spin_lock(&b->irq_lock); |
| 199 | 206 | |
| 200 | − if (list_empty(&b->signalers)) | |
| 207 | + /* | |
| 208 | + * Keep the irq armed until the interrupt after all listeners are gone. | |
| 209 | + * | |
| 210 | + * Enabling/disabling the interrupt is rather costly, roughly a couple | |
| 211 | + * of hundred microseconds. If we are proactive and enable/disable | |
| 212 | + * the interrupt around every request that wants a breadcrumb, we | |
| 213 | + * quickly drown in the extra orders of magnitude of latency imposed | |
| 214 | + * on request submission. | |
| 215 | + * | |
| 216 | + * So we try to be lazy, and keep the interrupts enabled until no | |
| 217 | + * more listeners appear within a breadcrumb interrupt interval (that | |
| 218 | + * is until a request completes that no one cares about). The | |
| 219 | + * observation is that listeners come in batches, and will often | |
| 220 | + * listen to a bunch of requests in succession. Though note on icl+, | |
| 221 | + * interrupts are always enabled due to concerns with rc6 being | |
| 222 | + * dysfunctional with per-engine interrupt masking. | |
| 223 | + * | |
| 224 | + * We also try to avoid raising too many interrupts, as they may | |
| 225 | + * be generated by userspace batches and it is unfortunately rather | |
| 226 | + * too easy to drown the CPU under a flood of GPU interrupts. Thus | |
| 227 | + * whenever no one appears to be listening, we turn off the interrupts. | |
| 228 | + * Fewer interrupts should conserve power -- at the very least, fewer | |
| 229 | + * interrupt draw less ire from other users of the system and tools | |
| 230 | + * like powertop. | |
| 231 | + */ | |
| 232 | + if (!signal && b->irq_armed && list_empty(&b->signalers)) | |
| 201 | 233 | __intel_breadcrumbs_disarm_irq(b); |
| 202 | 234 | |
| 203 | − list_splice_init(&b->signaled_requests, &signal); | |
| 204 | − | |
| 205 | 235 | list_for_each_entry_safe(ce, cn, &b->signalers, signal_link) { |
| 206 | 236 | GEM_BUG_ON(list_empty(&ce->signals)); |
| 207 | 237 | |
| @@ -218,7 +248,10 @@ static void signal_irq_work(struct irq_work *work) · 10 unmodified lines | ||
| 218 | 248 | * spinlock as the callback chain may end up adding |
| 219 | 249 | * more signalers to the same context or engine. |
| 220 | 250 | */ |
| 221 | − __signal_request(rq, &signal); | |
| 251 | + clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); | |
| 252 | + if (__signal_request(rq)) | |
| 253 | + /* We own signal_node now, xfer to local list */ | |
| 254 | + signal = slist_add(&rq->signal_node, signal); | |
| 222 | 255 | } |
| 223 | 256 | |
| 224 | 257 | /* |
| @@ -238,9 +271,9 @@ static void signal_irq_work(struct irq_work *work) · 13 unmodified lines | ||
| 238 | 271 | |
| 239 | 272 | spin_unlock(&b->irq_lock); |
| 240 | 273 | |
| 241 | − list_for_each_safe(pos, next, &signal) { | |
| 274 | + llist_for_each_safe(signal, sn, signal) { | |
| 242 | 275 | struct i915_request *rq = |
| 243 | − list_entry(pos, typeof(*rq), signal_link); | |
| 276 | + llist_entry(signal, typeof(*rq), signal_node); | |
| 244 | 277 | struct list_head cb_list; |
| 245 | 278 | |
| 246 | 279 | spin_lock(&rq->lock); |
| @@ -251,6 +284,9 @@ static void signal_irq_work(struct irq_work *work) · 4 unmodified lines | ||
| 251 | 284 | |
| 252 | 285 | i915_request_put(rq); |
| 253 | 286 | } |
| 287 | + | |
| 288 | + if (!READ_ONCE(b->irq_armed) && !list_empty(&b->signalers)) | |
| 289 | + intel_breadcrumbs_arm_irq(b); | |
| 254 | 290 | } |
| 255 | 291 | |
| 256 | 292 | struct intel_breadcrumbs * |
| @@ -264,7 +300,7 @@ intel_breadcrumbs_create(struct intel_engine_cs *irq_engine) · 7 unmodified lines | ||
| 264 | 300 | |
| 265 | 301 | spin_lock_init(&b->irq_lock); |
| 266 | 302 | INIT_LIST_HEAD(&b->signalers); |
| 267 | − INIT_LIST_HEAD(&b->signaled_requests); | |
| 303 | + init_llist_head(&b->signaled_requests); | |
| 268 | 304 | |
| 269 | 305 | init_irq_work(&b->irq_work, signal_irq_work); |
| 270 | 306 | |
| @@ -292,21 +328,22 @@ void intel_breadcrumbs_reset(struct intel_breadcrumbs *b) · 21 unmodified lines | ||
| 292 | 328 | |
| 293 | 329 | void intel_breadcrumbs_park(struct intel_breadcrumbs *b) |
| 294 | 330 | { |
| 295 | − unsigned long flags; | |
| 296 | − | |
| 297 | − if (!READ_ONCE(b->irq_armed)) | |
| 298 | − return; | |
| 299 | − | |
| 300 | − spin_lock_irqsave(&b->irq_lock, flags); | |
| 301 | − __intel_breadcrumbs_disarm_irq(b); | |
| 302 | − spin_unlock_irqrestore(&b->irq_lock, flags); | |
| 303 | − | |
| 304 | − if (!list_empty(&b->signalers)) | |
| 305 | − irq_work_queue(&b->irq_work); | |
| 331 | + /* Kick the work once more to drain the signalers */ | |
| 332 | + irq_work_sync(&b->irq_work); | |
| 333 | + while (unlikely(READ_ONCE(b->irq_armed))) { | |
| 334 | + local_irq_disable(); | |
| 335 | + signal_irq_work(&b->irq_work); | |
| 336 | + local_irq_enable(); | |
| 337 | + cond_resched(); | |
| 338 | + } | |
| 339 | + GEM_BUG_ON(!list_empty(&b->signalers)); | |
| 306 | 340 | } |
| 307 | 341 | |
| 308 | 342 | void intel_breadcrumbs_free(struct intel_breadcrumbs *b) |
| 309 | 343 | { |
| 344 | + irq_work_sync(&b->irq_work); | |
| 345 | + GEM_BUG_ON(!list_empty(&b->signalers)); | |
| 346 | + GEM_BUG_ON(b->irq_armed); | |
| 310 | 347 | kfree(b); |
| 311 | 348 | } |
| 312 | 349 | |
| @@ -327,7 +364,8 @@ static void insert_breadcrumb(struct i915_request *rq, · 14 unmodified lines | ||
| 327 | 364 | * its signal completion. |
| 328 | 365 | */ |
| 329 | 366 | if (__request_completed(rq)) { |
| 330 | − if (__signal_request(rq, &b->signaled_requests)) | |
| 367 | + if (__signal_request(rq) && | |
| 368 | + llist_add(&rq->signal_node, &b->signaled_requests)) | |
| 331 | 369 | irq_work_queue(&b->irq_work); |
| 332 | 370 | return; |
| 333 | 371 | } |
| @@ -362,9 +400,12 @@ static void insert_breadcrumb(struct i915_request *rq, · 28 unmodified lines | ||
| 362 | 400 | GEM_BUG_ON(!check_signal_order(ce, rq)); |
| 363 | 401 | set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); |
| 364 | 402 | |
| 365 | − /* Check after attaching to irq, interrupt may have already fired. */ | |
| 366 | − if (__request_completed(rq)) | |
| 367 | − irq_work_queue(&b->irq_work); | |
| 403 | + /* | |
| 404 | + * Defer enabling the interrupt to after HW submission and recheck | |
| 405 | + * the request as it may have completed and raised the interrupt as | |
| 406 | + * we were attaching it into the lists. | |
| 407 | + */ | |
| 408 | + irq_work_queue(&b->irq_work); | |
| 368 | 409 | } |
| 369 | 410 | |
| 370 | 411 | bool i915_request_enable_breadcrumb(struct i915_request *rq) |
| @@ -35,7 +35,7 @@ struct intel_breadcrumbs { · 34 unmodified lines | ||
| 35 | 35 | struct intel_engine_cs *irq_engine; |
| 36 | 36 | |
| 37 | 37 | struct list_head signalers; |
| 38 | − struct list_head signaled_requests; | |
| 38 | + struct llist_head signaled_requests; | |
| 39 | 39 | |
| 40 | 40 | struct irq_work irq_work; /* for use from inside irq_lock */ |
| 41 | 41 | |
| @@ -182,6 +182,7 @@ · 181 unmodified lines | ||
| 182 | 182 | struct virtual_engine { |
| 183 | 183 | struct intel_engine_cs base; |
| 184 | 184 | struct intel_context context; |
| 185 | + struct rcu_work rcu; | |
| 185 | 186 | |
| 186 | 187 | /* |
| 187 | 188 | * We allow only a single request through the virtual engine at a time |
| @@ -5425,44 +5426,90 @@ static struct list_head *virtual_queue(struct virtual_engine *ve) · 5237 unmodified lines | ||
| 5425 | 5426 | return &ve->base.execlists.default_priolist.requests[0]; |
| 5426 | 5427 | } |
| 5427 | 5428 | |
| 5428 | −static void virtual_context_destroy(struct kref *kref) | |
| 5429 | +static void rcu_virtual_context_destroy(struct work_struct *wrk) | |
| 5429 | 5430 | { |
| 5430 | 5431 | struct virtual_engine *ve = |
| 5431 | − container_of(kref, typeof(*ve), context.ref); | |
| 5432 | + container_of(wrk, typeof(*ve), rcu.work); | |
| 5432 | 5433 | unsigned int n; |
| 5433 | 5434 | |
| 5434 | − GEM_BUG_ON(!list_empty(virtual_queue(ve))); | |
| 5435 | − GEM_BUG_ON(ve->request); | |
| 5436 | 5435 | GEM_BUG_ON(ve->context.inflight); |
| 5437 | 5436 | |
| 5437 | + /* Preempt-to-busy may leave a stale request behind. */ | |
| 5438 | + if (unlikely(ve->request)) { | |
| 5439 | + struct i915_request *old; | |
| 5440 | + | |
| 5441 | + spin_lock_irq(&ve->base.active.lock); | |
| 5442 | + | |
| 5443 | + old = fetch_and_zero(&ve->request); | |
| 5444 | + if (old) { | |
| 5445 | + GEM_BUG_ON(!i915_request_completed(old)); | |
| 5446 | + __i915_request_submit(old); | |
| 5447 | + i915_request_put(old); | |
| 5448 | + } | |
| 5449 | + | |
| 5450 | + spin_unlock_irq(&ve->base.active.lock); | |
| 5451 | + } | |
| 5452 | + | |
| 5453 | + /* | |
| 5454 | + * Flush the tasklet in case it is still running on another core. | |
| 5455 | + * | |
| 5456 | + * This needs to be done before we remove ourselves from the siblings' | |
| 5457 | + * rbtrees as in the case it is running in parallel, it may reinsert | |
| 5458 | + * the rb_node into a sibling. | |
| 5459 | + */ | |
| 5460 | + tasklet_kill(&ve->base.execlists.tasklet); | |
| 5461 | + | |
| 5462 | + /* Decouple ourselves from the siblings, no more access allowed. */ | |
| 5438 | 5463 | for (n = 0; n < ve->num_siblings; n++) { |
| 5439 | 5464 | struct intel_engine_cs *sibling = ve->siblings[n]; |
| 5440 | 5465 | struct rb_node *node = &ve->nodes[sibling->id].rb; |
| 5441 | − unsigned long flags; | |
| 5442 | 5466 | |
| 5443 | 5467 | if (RB_EMPTY_NODE(node)) |
| 5444 | 5468 | continue; |
| 5445 | 5469 | |
| 5446 | − spin_lock_irqsave(&sibling->active.lock, flags); | |
| 5470 | + spin_lock_irq(&sibling->active.lock); | |
| 5447 | 5471 | |
| 5448 | 5472 | /* Detachment is lazily performed in the execlists tasklet */ |
| 5449 | 5473 | if (!RB_EMPTY_NODE(node)) |
| 5450 | 5474 | rb_erase_cached(node, &sibling->execlists.virtual); |
| 5451 | 5475 | |
| 5452 | − spin_unlock_irqrestore(&sibling->active.lock, flags); | |
| 5476 | + spin_unlock_irq(&sibling->active.lock); | |
| 5453 | 5477 | } |
| 5454 | 5478 | GEM_BUG_ON(__tasklet_is_scheduled(&ve->base.execlists.tasklet)); |
| 5479 | + GEM_BUG_ON(!list_empty(virtual_queue(ve))); | |
| 5455 | 5480 | |
| 5456 | 5481 | if (ve->context.state) |
| 5457 | 5482 | __execlists_context_fini(&ve->context); |
| 5458 | 5483 | intel_context_fini(&ve->context); |
| 5459 | 5484 | |
| 5485 | + intel_breadcrumbs_free(ve->base.breadcrumbs); | |
| 5460 | 5486 | intel_engine_free_request_pool(&ve->base); |
| 5461 | 5487 | |
| 5462 | 5488 | kfree(ve->bonds); |
| 5463 | 5489 | kfree(ve); |
| 5464 | 5490 | } |
| 5465 | 5491 | |
| 5492 | +static void virtual_context_destroy(struct kref *kref) | |
| 5493 | +{ | |
| 5494 | + struct virtual_engine *ve = | |
| 5495 | + container_of(kref, typeof(*ve), context.ref); | |
| 5496 | + | |
| 5497 | + GEM_BUG_ON(!list_empty(&ve->context.signals)); | |
| 5498 | + | |
| 5499 | + /* | |
| 5500 | + * When destroying the virtual engine, we have to be aware that | |
| 5501 | + * it may still be in use from an hardirq/softirq context causing | |
| 5502 | + * the resubmission of a completed request (background completion | |
| 5503 | + * due to preempt-to-busy). Before we can free the engine, we need | |
| 5504 | + * to flush the submission code and tasklets that are still potentially | |
| 5505 | + * accessing the engine. Flushing the tasklets requires process context, | |
| 5506 | + * and since we can guard the resubmit onto the engine with an RCU read | |
| 5507 | + * lock, we can delegate the free of the engine to an RCU worker. | |
| 5508 | + */ | |
| 5509 | + INIT_RCU_WORK(&ve->rcu, rcu_virtual_context_destroy); | |
| 5510 | + queue_rcu_work(system_wq, &ve->rcu); | |
| 5511 | +} | |
| 5512 | + | |
| 5466 | 5513 | static void virtual_engine_initial_hint(struct virtual_engine *ve) |
| 5467 | 5514 | { |
| 5468 | 5515 | int swp; |
| @@ -243,8 +243,9 @@ static const struct drm_i915_mocs_entry tgl_mocs_table[] = { · 242 unmodified lines | ||
| 243 | 243 | * only, __init_mocs_table() take care to program unused index with |
| 244 | 244 | * this entry. |
| 245 | 245 | */ |
| 246 | − MOCS_ENTRY(1, LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), | |
| 247 | − L3_3_WB), | |
| 246 | + MOCS_ENTRY(I915_MOCS_PTE, | |
| 247 | + LE_0_PAGETABLE | LE_TC_0_PAGETABLE, | |
| 248 | + L3_1_UC), | |
| 248 | 249 | GEN11_MOCS_ENTRIES, |
| 249 | 250 | |
| 250 | 251 | /* Implicitly enable L1 - HDC:L1 + L3 + LLC */ |
| @@ -56,9 +56,12 @@ static inline void set(struct intel_uncore *uncore, i915_reg_t reg, u32 val) · 55 unmodified lines | ||
| 56 | 56 | |
| 57 | 57 | static void gen11_rc6_enable(struct intel_rc6 *rc6) |
| 58 | 58 | { |
| 59 | − struct intel_uncore *uncore = rc6_to_uncore(rc6); | |
| 59 | + struct intel_gt *gt = rc6_to_gt(rc6); | |
| 60 | + struct intel_uncore *uncore = gt->uncore; | |
| 60 | 61 | struct intel_engine_cs *engine; |
| 61 | 62 | enum intel_engine_id id; |
| 63 | + u32 pg_enable; | |
| 64 | + int i; | |
| 62 | 65 | |
| 63 | 66 | /* 2b: Program RC6 thresholds.*/ |
| 64 | 67 | set(uncore, GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16 | 85); |
| @@ -102,10 +105,19 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) · 37 unmodified lines | ||
| 102 | 105 | GEN6_RC_CTL_RC6_ENABLE | |
| 103 | 106 | GEN6_RC_CTL_EI_MODE(1); |
| 104 | 107 | |
| 105 | − set(uncore, GEN9_PG_ENABLE, | |
| 106 | − GEN9_RENDER_PG_ENABLE | | |
| 107 | − GEN9_MEDIA_PG_ENABLE | | |
| 108 | − GEN11_MEDIA_SAMPLER_PG_ENABLE); | |
| 108 | + pg_enable = | |
| 109 | + GEN9_RENDER_PG_ENABLE | | |
| 110 | + GEN9_MEDIA_PG_ENABLE | | |
| 111 | + GEN11_MEDIA_SAMPLER_PG_ENABLE; | |
| 112 | + | |
| 113 | + if (INTEL_GEN(gt->i915) >= 12) { | |
| 114 | + for (i = 0; i < I915_MAX_VCS; i++) | |
| 115 | + if (HAS_ENGINE(gt, _VCS(i))) | |
| 116 | + pg_enable |= (VDN_HCP_POWERGATE_ENABLE(i) | | |
| 117 | + VDN_MFX_POWERGATE_ENABLE(i)); | |
| 118 | + } | |
| 119 | + | |
| 120 | + set(uncore, GEN9_PG_ENABLE, pg_enable); | |
| 109 | 121 | } |
| 110 | 122 | |
| 111 | 123 | static void gen9_rc6_enable(struct intel_rc6 *rc6) |
| @@ -131,8 +131,10 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) · 130 unmodified lines | ||
| 131 | 131 | return; |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | − if (wal->list) | |
| 134 | + if (wal->list) { | |
| 135 | 135 | memcpy(list, wal->list, sizeof(*wa) * wal->count); |
| 136 | + kfree(wal->list); | |
| 137 | + } | |
| 136 | 138 | |
| 137 | 139 | wal->list = list; |
| 138 | 140 | } |
| @@ -164,7 +164,7 @@ static unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = { · 163 unmodified lines | ||
| 164 | 164 | |
| 165 | 165 | /* let the virtual display supports DP1.2 */ |
| 166 | 166 | static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { |
| 167 | − 0x12, 0x014, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
| 167 | + 0x12, 0x014, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
| 168 | 168 | }; |
| 169 | 169 | |
| 170 | 170 | static void emulate_monitor_status_change(struct intel_vgpu *vgpu) |
| @@ -255,7 +255,7 @@ struct intel_gvt_mmio { · 254 unmodified lines | ||
| 255 | 255 | #define F_CMD_ACCESS (1 << 3) |
| 256 | 256 | /* This reg has been accessed by a VM */ |
| 257 | 257 | #define F_ACCESSED (1 << 4) |
| 258 | −/* This reg has been accessed through GPU commands */ | |
| 258 | +/* This reg could be accessed by unaligned address */ | |
| 259 | 259 | #define F_UNALIGN (1 << 6) |
| 260 | 260 | /* This reg is in GVT's mmio save-restor list and in hardware |
| 261 | 261 | * logical context image |
| @@ -829,8 +829,10 @@ static int intel_vgpu_open(struct mdev_device *mdev) · 828 unmodified lines | ||
| 829 | 829 | /* Take a module reference as mdev core doesn't take |
| 830 | 830 | * a reference for vendor driver. |
| 831 | 831 | */ |
| 832 | − if (!try_module_get(THIS_MODULE)) | |
| 832 | + if (!try_module_get(THIS_MODULE)) { | |
| 833 | + ret = -ENODEV; | |
| 833 | 834 | goto undo_group; |
| 835 | + } | |
| 834 | 836 | |
| 835 | 837 | ret = kvmgt_guest_init(mdev); |
| 836 | 838 | if (ret) |
| @@ -439,7 +439,8 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, · 438 unmodified lines | ||
| 439 | 439 | |
| 440 | 440 | if (IS_BROADWELL(dev_priv)) |
| 441 | 441 | ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_B); |
| 442 | − else | |
| 442 | + /* FixMe: Re-enable APL/BXT once vfio_edid enabled */ | |
| 443 | + else if (!IS_BROXTON(dev_priv)) | |
| 443 | 444 | ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_D); |
| 444 | 445 | if (ret) |
| 445 | 446 | goto out_clean_sched_policy; |
| @@ -909,8 +909,13 @@ static int gen8_oa_read(struct i915_perf_stream *stream, · 908 unmodified lines | ||
| 909 | 909 | DRM_I915_PERF_RECORD_OA_REPORT_LOST); |
| 910 | 910 | if (ret) |
| 911 | 911 | return ret; |
| 912 | − intel_uncore_write(uncore, oastatus_reg, | |
| 913 | − oastatus & ~GEN8_OASTATUS_REPORT_LOST); | |
| 912 | + | |
| 913 | + intel_uncore_rmw(uncore, oastatus_reg, | |
| 914 | + GEN8_OASTATUS_COUNTER_OVERFLOW | | |
| 915 | + GEN8_OASTATUS_REPORT_LOST, | |
| 916 | + IS_GEN_RANGE(uncore->i915, 8, 10) ? | |
| 917 | + (GEN8_OASTATUS_HEAD_POINTER_WRAP | | |
| 918 | + GEN8_OASTATUS_TAIL_POINTER_WRAP) : 0); | |
| 914 | 919 | } |
| 915 | 920 | |
| 916 | 921 | return gen8_append_oa_reports(stream, buf, count, offset); |
| @@ -676,6 +676,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) · 675 unmodified lines | ||
| 676 | 676 | #define GEN7_OASTATUS2_MEM_SELECT_GGTT (1 << 0) /* 0: PPGTT, 1: GGTT */ |
| 677 | 677 | |
| 678 | 678 | #define GEN8_OASTATUS _MMIO(0x2b08) |
| 679 | +#define GEN8_OASTATUS_TAIL_POINTER_WRAP (1 << 17) | |
| 680 | +#define GEN8_OASTATUS_HEAD_POINTER_WRAP (1 << 16) | |
| 679 | 681 | #define GEN8_OASTATUS_OVERRUN_STATUS (1 << 3) |
| 680 | 682 | #define GEN8_OASTATUS_COUNTER_OVERFLOW (1 << 2) |
| 681 | 683 | #define GEN8_OASTATUS_OABUFFER_OVERFLOW (1 << 1) |
| @@ -8971,10 +8973,6 @@ enum { · 8289 unmodified lines | ||
| 8971 | 8973 | #define GEN9_PWRGT_MEDIA_STATUS_MASK (1 << 0) |
| 8972 | 8974 | #define GEN9_PWRGT_RENDER_STATUS_MASK (1 << 1) |
| 8973 | 8975 | |
| 8974 | −#define POWERGATE_ENABLE _MMIO(0xa210) | |
| 8975 | −#define VDN_HCP_POWERGATE_ENABLE(n) BIT(((n) * 2) + 3) | |
| 8976 | −#define VDN_MFX_POWERGATE_ENABLE(n) BIT(((n) * 2) + 4) | |
| 8977 | − | |
| 8978 | 8976 | #define GTFIFODBG _MMIO(0x120000) |
| 8979 | 8977 | #define GT_FIFO_SBDEDICATE_FREE_ENTRY_CHV (0x1f << 20) |
| 8980 | 8978 | #define GT_FIFO_FREE_ENTRIES_CHV (0x7f << 13) |
| @@ -9114,9 +9112,11 @@ enum { · 133 unmodified lines | ||
| 9114 | 9112 | #define GEN9_MEDIA_PG_IDLE_HYSTERESIS _MMIO(0xA0C4) |
| 9115 | 9113 | #define GEN9_RENDER_PG_IDLE_HYSTERESIS _MMIO(0xA0C8) |
| 9116 | 9114 | #define GEN9_PG_ENABLE _MMIO(0xA210) |
| 9117 | −#define GEN9_RENDER_PG_ENABLE REG_BIT(0) | |
| 9118 | −#define GEN9_MEDIA_PG_ENABLE REG_BIT(1) | |
| 9119 | −#define GEN11_MEDIA_SAMPLER_PG_ENABLE REG_BIT(2) | |
| 9115 | +#define GEN9_RENDER_PG_ENABLE REG_BIT(0) | |
| 9116 | +#define GEN9_MEDIA_PG_ENABLE REG_BIT(1) | |
| 9117 | +#define GEN11_MEDIA_SAMPLER_PG_ENABLE REG_BIT(2) | |
| 9118 | +#define VDN_HCP_POWERGATE_ENABLE(n) REG_BIT(3 + 2 * (n)) | |
| 9119 | +#define VDN_MFX_POWERGATE_ENABLE(n) REG_BIT(4 + 2 * (n)) | |
| 9120 | 9120 | #define GEN8_PUSHBUS_CONTROL _MMIO(0xA248) |
| 9121 | 9121 | #define GEN8_PUSHBUS_ENABLE _MMIO(0xA250) |
| 9122 | 9122 | #define GEN8_PUSHBUS_SHIFT _MMIO(0xA25C) |
| @@ -176,7 +176,11 @@ struct i915_request { · 175 unmodified lines | ||
| 176 | 176 | struct intel_context *context; |
| 177 | 177 | struct intel_ring *ring; |
| 178 | 178 | struct intel_timeline __rcu *timeline; |
| 179 | − struct list_head signal_link; | |
| 179 | + | |
| 180 | + union { | |
| 181 | + struct list_head signal_link; | |
| 182 | + struct llist_node signal_node; | |
| 183 | + }; | |
| 180 | 184 | |
| 181 | 185 | /* |
| 182 | 186 | * The rcu epoch of when this request was allocated. Used to judiciously |
| @@ -7118,23 +7118,10 @@ static void icl_init_clock_gating(struct drm_i915_private *dev_priv) · 7117 unmodified lines | ||
| 7118 | 7118 | |
| 7119 | 7119 | static void tgl_init_clock_gating(struct drm_i915_private *dev_priv) |
| 7120 | 7120 | { |
| 7121 | − u32 vd_pg_enable = 0; | |
| 7122 | − unsigned int i; | |
| 7123 | − | |
| 7124 | 7121 | /* Wa_1409120013:tgl */ |
| 7125 | 7122 | I915_WRITE(ILK_DPFC_CHICKEN, |
| 7126 | 7123 | ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL); |
| 7127 | 7124 | |
| 7128 | − /* This is not a WA. Enable VD HCP & MFX_ENC powergate */ | |
| 7129 | − for (i = 0; i < I915_MAX_VCS; i++) { | |
| 7130 | − if (HAS_ENGINE(&dev_priv->gt, _VCS(i))) | |
| 7131 | − vd_pg_enable |= VDN_HCP_POWERGATE_ENABLE(i) | | |
| 7132 | − VDN_MFX_POWERGATE_ENABLE(i); | |
| 7133 | − } | |
| 7134 | − | |
| 7135 | − I915_WRITE(POWERGATE_ENABLE, | |
| 7136 | − I915_READ(POWERGATE_ENABLE) | vd_pg_enable); | |
| 7137 | − | |
| 7138 | 7125 | /* Wa_1409825376:tgl (pre-prod)*/ |
| 7139 | 7126 | if (IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_B1)) |
| 7140 | 7127 | I915_WRITE(GEN9_CLKGATE_DIS_3, I915_READ(GEN9_CLKGATE_DIS_3) | |
| @@ -2293,8 +2293,10 @@ static int perf_request_latency(void *arg) · 2292 unmodified lines | ||
| 2293 | 2293 | struct intel_context *ce; |
| 2294 | 2294 | |
| 2295 | 2295 | ce = intel_context_create(engine); |
| 2296 | − if (IS_ERR(ce)) | |
| 2296 | + if (IS_ERR(ce)) { | |
| 2297 | + err = PTR_ERR(ce); | |
| 2297 | 2298 | goto out; |
| 2299 | + } | |
| 2298 | 2300 | |
| 2299 | 2301 | err = intel_context_pin(ce); |
| 2300 | 2302 | if (err) { |
| @@ -2467,8 +2469,10 @@ static int perf_series_engines(void *arg) · 166 unmodified lines | ||
| 2467 | 2469 | struct intel_context *ce; |
| 2468 | 2470 | |
| 2469 | 2471 | ce = intel_context_create(engine); |
| 2470 | − if (IS_ERR(ce)) | |
| 2472 | + if (IS_ERR(ce)) { | |
| 2473 | + err = PTR_ERR(ce); | |
| 2471 | 2474 | goto out; |
| 2475 | + } | |
| 2472 | 2476 | |
| 2473 | 2477 | err = intel_context_pin(ce); |
| 2474 | 2478 | if (err) { |
| @@ -522,15 +522,6 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, · 521 unmodified lines | ||
| 522 | 522 | return 0; |
| 523 | 523 | } |
| 524 | 524 | |
| 525 | −static void mtk_dpi_encoder_destroy(struct drm_encoder *encoder) | |
| 526 | −{ | |
| 527 | − drm_encoder_cleanup(encoder); | |
| 528 | −} | |
| 529 | − | |
| 530 | −static const struct drm_encoder_funcs mtk_dpi_encoder_funcs = { | |
| 531 | − .destroy = mtk_dpi_encoder_destroy, | |
| 532 | −}; | |
| 533 | − | |
| 534 | 525 | static int mtk_dpi_bridge_attach(struct drm_bridge *bridge, |
| 535 | 526 | enum drm_bridge_attach_flags flags) |
| 536 | 527 | { |
| @@ -444,7 +444,10 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) · 443 unmodified lines | ||
| 444 | 444 | u32 horizontal_sync_active_byte; |
| 445 | 445 | u32 horizontal_backporch_byte; |
| 446 | 446 | u32 horizontal_frontporch_byte; |
| 447 | + u32 horizontal_front_back_byte; | |
| 448 | + u32 data_phy_cycles_byte; | |
| 447 | 449 | u32 dsi_tmp_buf_bpp, data_phy_cycles; |
| 450 | + u32 delta; | |
| 448 | 451 | struct mtk_phy_timing *timing = &dsi->phy_timing; |
| 449 | 452 | |
| 450 | 453 | struct videomode *vm = &dsi->vm; |
| @@ -466,50 +469,30 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) · 15 unmodified lines | ||
| 466 | 469 | horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10); |
| 467 | 470 | |
| 468 | 471 | if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) |
| 469 | − horizontal_backporch_byte = vm->hback_porch * dsi_tmp_buf_bpp; | |
| 472 | + horizontal_backporch_byte = vm->hback_porch * dsi_tmp_buf_bpp - 10; | |
| 470 | 473 | else |
| 471 | 474 | horizontal_backporch_byte = (vm->hback_porch + vm->hsync_len) * |
| 472 | − dsi_tmp_buf_bpp; | |
| 475 | + dsi_tmp_buf_bpp - 10; | |
| 473 | 476 | |
| 474 | 477 | data_phy_cycles = timing->lpx + timing->da_hs_prepare + |
| 475 | − timing->da_hs_zero + timing->da_hs_exit; | |
| 476 | − | |
| 477 | − if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) { | |
| 478 | − if ((vm->hfront_porch + vm->hback_porch) * dsi_tmp_buf_bpp > | |
| 479 | − data_phy_cycles * dsi->lanes + 18) { | |
| 480 | − horizontal_frontporch_byte = | |
| 481 | − vm->hfront_porch * dsi_tmp_buf_bpp - | |
| 482 | − (data_phy_cycles * dsi->lanes + 18) * | |
| 483 | − vm->hfront_porch / | |
| 484 | − (vm->hfront_porch + vm->hback_porch); | |
| 485 | − | |
| 486 | − horizontal_backporch_byte = | |
| 487 | − horizontal_backporch_byte - | |
| 488 | − (data_phy_cycles * dsi->lanes + 18) * | |
| 489 | − vm->hback_porch / | |
| 490 | − (vm->hfront_porch + vm->hback_porch); | |
| 491 | − } else { | |
| 492 | − DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n"); | |
| 493 | − horizontal_frontporch_byte = vm->hfront_porch * | |
| 494 | − dsi_tmp_buf_bpp; | |
| 495 | − } | |
| 478 | + timing->da_hs_zero + timing->da_hs_exit + 3; | |
| 479 | + | |
| 480 | + delta = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? 18 : 12; | |
| 481 | + | |
| 482 | + horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp; | |
| 483 | + horizontal_front_back_byte = horizontal_frontporch_byte + horizontal_backporch_byte; | |
| 484 | + data_phy_cycles_byte = data_phy_cycles * dsi->lanes + delta; | |
| 485 | + | |
| 486 | + if (horizontal_front_back_byte > data_phy_cycles_byte) { | |
| 487 | + horizontal_frontporch_byte -= data_phy_cycles_byte * | |
| 488 | + horizontal_frontporch_byte / | |
| 489 | + horizontal_front_back_byte; | |
| 490 | + | |
| 491 | + horizontal_backporch_byte -= data_phy_cycles_byte * | |
| 492 | + horizontal_backporch_byte / | |
| 493 | + horizontal_front_back_byte; | |
| 496 | 494 | } else { |
| 497 | − if ((vm->hfront_porch + vm->hback_porch) * dsi_tmp_buf_bpp > | |
| 498 | − data_phy_cycles * dsi->lanes + 12) { | |
| 499 | − horizontal_frontporch_byte = | |
| 500 | − vm->hfront_porch * dsi_tmp_buf_bpp - | |
| 501 | − (data_phy_cycles * dsi->lanes + 12) * | |
| 502 | − vm->hfront_porch / | |
| 503 | − (vm->hfront_porch + vm->hback_porch); | |
| 504 | − horizontal_backporch_byte = horizontal_backporch_byte - | |
| 505 | − (data_phy_cycles * dsi->lanes + 12) * | |
| 506 | − vm->hback_porch / | |
| 507 | − (vm->hfront_porch + vm->hback_porch); | |
| 508 | − } else { | |
| 509 | − DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n"); | |
| 510 | − horizontal_frontporch_byte = vm->hfront_porch * | |
| 511 | − dsi_tmp_buf_bpp; | |
| 512 | − } | |
| 495 | + DRM_WARN("HFP + HBP less than d-phy, FPS will under 60Hz\n"); | |
| 513 | 496 | } |
| 514 | 497 | |
| 515 | 498 | writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC); |
| @@ -558,8 +558,10 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, · 557 unmodified lines | ||
| 558 | 558 | NV_PRINTK(err, cli, "validating bo list\n"); |
| 559 | 559 | validate_fini(op, chan, NULL, NULL); |
| 560 | 560 | return ret; |
| 561 | + } else if (ret > 0) { | |
| 562 | + *apply_relocs = true; | |
| 561 | 563 | } |
| 562 | − *apply_relocs = ret; | |
| 564 | + | |
| 563 | 565 | return 0; |
| 564 | 566 | } |
| 565 | 567 | |
| @@ -662,7 +664,6 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, · 96 unmodified lines | ||
| 662 | 664 | nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); |
| 663 | 665 | } |
| 664 | 666 | |
| 665 | − u_free(reloc); | |
| 666 | 667 | return ret; |
| 667 | 668 | } |
| 668 | 669 | |
| @@ -872,9 +873,10 @@ out: · 203 unmodified lines | ||
| 872 | 873 | break; |
| 873 | 874 | } |
| 874 | 875 | } |
| 875 | − u_free(reloc); | |
| 876 | 876 | } |
| 877 | 877 | out_prevalid: |
| 878 | + if (!IS_ERR(reloc)) | |
| 879 | + u_free(reloc); | |
| 878 | 880 | u_free(bo); |
| 879 | 881 | u_free(push); |
| 880 | 882 | |
| @@ -814,9 +814,15 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, · 813 unmodified lines | ||
| 814 | 814 | * |
| 815 | 815 | * XXX(hch): this has no business in a driver and needs to move |
| 816 | 816 | * to the device tree. |
| 817 | + * | |
| 818 | + * If we have two subsequent calls to dma_direct_set_offset | |
| 819 | + * returns -EINVAL. Unfortunately, this happens when we have two | |
| 820 | + * backends in the system, and will result in the driver | |
| 821 | + * reporting an error while it has been setup properly before. | |
| 822 | + * Ignore EINVAL, but it should really be removed eventually. | |
| 817 | 823 | */ |
| 818 | 824 | ret = dma_direct_set_offset(drm->dev, PHYS_OFFSET, 0, SZ_4G); |
| 819 | − if (ret) | |
| 825 | + if (ret && ret != -EINVAL) | |
| 820 | 826 | return ret; |
| 821 | 827 | } |
| 822 | 828 | |
| @@ -208,6 +208,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, · 207 unmodified lines | ||
| 208 | 208 | phy_node = of_parse_phandle(dev->of_node, "phys", 0); |
| 209 | 209 | if (!phy_node) { |
| 210 | 210 | dev_err(dev, "Can't found PHY phandle\n"); |
| 211 | + ret = -EINVAL; | |
| 211 | 212 | goto err_disable_clk_tmds; |
| 212 | 213 | } |
| 213 | 214 | |
| @@ -219,6 +219,7 @@ struct vc4_dev { · 218 unmodified lines | ||
| 219 | 219 | |
| 220 | 220 | struct drm_modeset_lock ctm_state_lock; |
| 221 | 221 | struct drm_private_obj ctm_manager; |
| 222 | + struct drm_private_obj hvs_channels; | |
| 222 | 223 | struct drm_private_obj load_tracker; |
| 223 | 224 | |
| 224 | 225 | /* List of vc4_debugfs_info_entry for adding to debugfs once |
| @@ -531,6 +532,9 @@ struct vc4_crtc_state { · 306 unmodified lines | ||
| 531 | 532 | unsigned int top; |
| 532 | 533 | unsigned int bottom; |
| 533 | 534 | } margins; |
| 535 | + | |
| 536 | + /* Transitional state below, only valid during atomic commits */ | |
| 537 | + bool update_muxing; | |
| 534 | 538 | }; |
| 535 | 539 | |
| 536 | 540 | #define VC4_HVS_CHANNEL_DISABLED ((unsigned int)-1) |
| @@ -760,12 +760,54 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) · 759 unmodified lines | ||
| 760 | 760 | { |
| 761 | 761 | } |
| 762 | 762 | |
| 763 | +#define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL | |
| 764 | +#define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL | |
| 765 | + | |
| 766 | +static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, | |
| 767 | + struct drm_crtc_state *crtc_state, | |
| 768 | + struct drm_connector_state *conn_state) | |
| 769 | +{ | |
| 770 | + struct drm_display_mode *mode = &crtc_state->adjusted_mode; | |
| 771 | + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); | |
| 772 | + unsigned long long pixel_rate = mode->clock * 1000; | |
| 773 | + unsigned long long tmds_rate; | |
| 774 | + | |
| 775 | + if (vc4_hdmi->variant->unsupported_odd_h_timings && | |
| 776 | + ((mode->hdisplay % 2) || (mode->hsync_start % 2) || | |
| 777 | + (mode->hsync_end % 2) || (mode->htotal % 2))) | |
| 778 | + return -EINVAL; | |
| 779 | + | |
| 780 | + /* | |
| 781 | + * The 1440p@60 pixel rate is in the same range than the first | |
| 782 | + * WiFi channel (between 2.4GHz and 2.422GHz with 22MHz | |
| 783 | + * bandwidth). Slightly lower the frequency to bring it out of | |
| 784 | + * the WiFi range. | |
| 785 | + */ | |
| 786 | + tmds_rate = pixel_rate * 10; | |
| 787 | + if (vc4_hdmi->disable_wifi_frequencies && | |
| 788 | + (tmds_rate >= WIFI_2_4GHz_CH1_MIN_FREQ && | |
| 789 | + tmds_rate <= WIFI_2_4GHz_CH1_MAX_FREQ)) { | |
| 790 | + mode->clock = 238560; | |
| 791 | + pixel_rate = mode->clock * 1000; | |
| 792 | + } | |
| 793 | + | |
| 794 | + if (pixel_rate > vc4_hdmi->variant->max_pixel_clock) | |
| 795 | + return -EINVAL; | |
| 796 | + | |
| 797 | + return 0; | |
| 798 | +} | |
| 799 | + | |
| 763 | 800 | static enum drm_mode_status |
| 764 | 801 | vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, |
| 765 | 802 | const struct drm_display_mode *mode) |
| 766 | 803 | { |
| 767 | 804 | struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); |
| 768 | 805 | |
| 806 | + if (vc4_hdmi->variant->unsupported_odd_h_timings && | |
| 807 | + ((mode->hdisplay % 2) || (mode->hsync_start % 2) || | |
| 808 | + (mode->hsync_end % 2) || (mode->htotal % 2))) | |
| 809 | + return MODE_H_ILLEGAL; | |
| 810 | + | |
| 769 | 811 | if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) |
| 770 | 812 | return MODE_CLOCK_HIGH; |
| 771 | 813 | |
| @@ -773,6 +815,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, · 1 unmodified line | ||
| 773 | 815 | } |
| 774 | 816 | |
| 775 | 817 | static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { |
| 818 | + .atomic_check = vc4_hdmi_encoder_atomic_check, | |
| 776 | 819 | .mode_valid = vc4_hdmi_encoder_mode_valid, |
| 777 | 820 | .disable = vc4_hdmi_encoder_disable, |
| 778 | 821 | .enable = vc4_hdmi_encoder_enable, |
| @@ -1694,6 +1737,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) · 915 unmodified lines | ||
| 1694 | 1737 | vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; |
| 1695 | 1738 | } |
| 1696 | 1739 | |
| 1740 | + vc4_hdmi->disable_wifi_frequencies = | |
| 1741 | + of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence"); | |
| 1742 | + | |
| 1697 | 1743 | pm_runtime_enable(dev); |
| 1698 | 1744 | |
| 1699 | 1745 | drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); |
| @@ -1817,6 +1863,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { · 117 unmodified lines | ||
| 1817 | 1863 | PHY_LANE_2, |
| 1818 | 1864 | PHY_LANE_CK, |
| 1819 | 1865 | }, |
| 1866 | + .unsupported_odd_h_timings = true, | |
| 1820 | 1867 | |
| 1821 | 1868 | .init_resources = vc5_hdmi_init_resources, |
| 1822 | 1869 | .csc_setup = vc5_hdmi_csc_setup, |
| @@ -1842,6 +1889,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { · 19 unmodified lines | ||
| 1842 | 1889 | PHY_LANE_CK, |
| 1843 | 1890 | PHY_LANE_2, |
| 1844 | 1891 | }, |
| 1892 | + .unsupported_odd_h_timings = true, | |
| 1845 | 1893 | |
| 1846 | 1894 | .init_resources = vc5_hdmi_init_resources, |
| 1847 | 1895 | .csc_setup = vc5_hdmi_csc_setup, |
| @@ -62,6 +62,9 @@ struct vc4_hdmi_variant { · 61 unmodified lines | ||
| 62 | 62 | */ |
| 63 | 63 | enum vc4_hdmi_phy_channel phy_lane_mapping[4]; |
| 64 | 64 | |
| 65 | + /* The BCM2711 cannot deal with odd horizontal pixel timings */ | |
| 66 | + bool unsupported_odd_h_timings; | |
| 67 | + | |
| 65 | 68 | /* Callback to get the resources (memory region, interrupts, |
| 66 | 69 | * clocks, etc) for that variant. |
| 67 | 70 | */ |
| @@ -139,6 +142,14 @@ struct vc4_hdmi { · 71 unmodified lines | ||
| 139 | 142 | int hpd_gpio; |
| 140 | 143 | bool hpd_active_low; |
| 141 | 144 | |
| 145 | + /* | |
| 146 | + * On some systems (like the RPi4), some modes are in the same | |
| 147 | + * frequency range than the WiFi channels (1440p@60Hz for | |
| 148 | + * example). Should we take evasive actions because that system | |
| 149 | + * has a wifi adapter? | |
| 150 | + */ | |
| 151 | + bool disable_wifi_frequencies; | |
| 152 | + | |
| 142 | 153 | struct cec_adapter *cec_adap; |
| 143 | 154 | struct cec_msg cec_rx_msg; |
| 144 | 155 | bool cec_tx_ok; |
| @@ -24,6 +24,8 @@ · 23 unmodified lines | ||
| 24 | 24 | #include "vc4_drv.h" |
| 25 | 25 | #include "vc4_regs.h" |
| 26 | 26 | |
| 27 | +#define HVS_NUM_CHANNELS 3 | |
| 28 | + | |
| 27 | 29 | struct vc4_ctm_state { |
| 28 | 30 | struct drm_private_state base; |
| 29 | 31 | struct drm_color_ctm *ctm; |
| @@ -35,6 +37,17 @@ static struct vc4_ctm_state *to_vc4_ctm_state(struct drm_private_state *priv) · 5 unmodified lines | ||
| 35 | 37 | return container_of(priv, struct vc4_ctm_state, base); |
| 36 | 38 | } |
| 37 | 39 | |
| 40 | +struct vc4_hvs_state { | |
| 41 | + struct drm_private_state base; | |
| 42 | + unsigned int unassigned_channels; | |
| 43 | +}; | |
| 44 | + | |
| 45 | +static struct vc4_hvs_state * | |
| 46 | +to_vc4_hvs_state(struct drm_private_state *priv) | |
| 47 | +{ | |
| 48 | + return container_of(priv, struct vc4_hvs_state, base); | |
| 49 | +} | |
| 50 | + | |
| 38 | 51 | struct vc4_load_tracker_state { |
| 39 | 52 | struct drm_private_state base; |
| 40 | 53 | u64 hvs_load; |
| @@ -113,7 +126,7 @@ static int vc4_ctm_obj_init(struct vc4_dev *vc4) · 72 unmodified lines | ||
| 113 | 126 | drm_atomic_private_obj_init(&vc4->base, &vc4->ctm_manager, &ctm_state->base, |
| 114 | 127 | &vc4_ctm_state_funcs); |
| 115 | 128 | |
| 116 | − return drmm_add_action(&vc4->base, vc4_ctm_obj_fini, NULL); | |
| 129 | + return drmm_add_action_or_reset(&vc4->base, vc4_ctm_obj_fini, NULL); | |
| 117 | 130 | } |
| 118 | 131 | |
| 119 | 132 | /* Converts a DRM S31.32 value to the HW S0.9 format. */ |
| @@ -169,6 +182,19 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state) · 49 unmodified lines | ||
| 169 | 182 | VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO)); |
| 170 | 183 | } |
| 171 | 184 | |
| 185 | +static struct vc4_hvs_state * | |
| 186 | +vc4_hvs_get_global_state(struct drm_atomic_state *state) | |
| 187 | +{ | |
| 188 | + struct vc4_dev *vc4 = to_vc4_dev(state->dev); | |
| 189 | + struct drm_private_state *priv_state; | |
| 190 | + | |
| 191 | + priv_state = drm_atomic_get_private_obj_state(state, &vc4->hvs_channels); | |
| 192 | + if (IS_ERR(priv_state)) | |
| 193 | + return ERR_CAST(priv_state); | |
| 194 | + | |
| 195 | + return to_vc4_hvs_state(priv_state); | |
| 196 | +} | |
| 197 | + | |
| 172 | 198 | static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, |
| 173 | 199 | struct drm_atomic_state *state) |
| 174 | 200 | { |
| @@ -213,10 +239,7 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4, · 38 unmodified lines | ||
| 213 | 239 | { |
| 214 | 240 | struct drm_crtc_state *crtc_state; |
| 215 | 241 | struct drm_crtc *crtc; |
| 216 | − unsigned char dsp2_mux = 0; | |
| 217 | − unsigned char dsp3_mux = 3; | |
| 218 | − unsigned char dsp4_mux = 3; | |
| 219 | − unsigned char dsp5_mux = 3; | |
| 242 | + unsigned char mux; | |
| 220 | 243 | unsigned int i; |
| 221 | 244 | u32 reg; |
| 222 | 245 | |
| @@ -224,50 +247,59 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4, · 1 unmodified line | ||
| 224 | 247 | struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); |
| 225 | 248 | struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); |
| 226 | 249 | |
| 227 | − if (!crtc_state->active) | |
| 250 | + if (!vc4_state->update_muxing) | |
| 228 | 251 | continue; |
| 229 | 252 | |
| 230 | 253 | switch (vc4_crtc->data->hvs_output) { |
| 231 | 254 | case 2: |
| 232 | − dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1; | |
| 255 | + mux = (vc4_state->assigned_channel == 2) ? 0 : 1; | |
| 256 | + reg = HVS_READ(SCALER_DISPECTRL); | |
| 257 | + HVS_WRITE(SCALER_DISPECTRL, | |
| 258 | + (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) | | |
| 259 | + VC4_SET_FIELD(mux, SCALER_DISPECTRL_DSP2_MUX)); | |
| 233 | 260 | break; |
| 234 | 261 | |
| 235 | 262 | case 3: |
| 236 | − dsp3_mux = vc4_state->assigned_channel; | |
| 263 | + if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED) | |
| 264 | + mux = 3; | |
| 265 | + else | |
| 266 | + mux = vc4_state->assigned_channel; | |
| 267 | + | |
| 268 | + reg = HVS_READ(SCALER_DISPCTRL); | |
| 269 | + HVS_WRITE(SCALER_DISPCTRL, | |
| 270 | + (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) | | |
| 271 | + VC4_SET_FIELD(mux, SCALER_DISPCTRL_DSP3_MUX)); | |
| 237 | 272 | break; |
| 238 | 273 | |
| 239 | 274 | case 4: |
| 240 | − dsp4_mux = vc4_state->assigned_channel; | |
| 275 | + if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED) | |
| 276 | + mux = 3; | |
| 277 | + else | |
| 278 | + mux = vc4_state->assigned_channel; | |
| 279 | + | |
| 280 | + reg = HVS_READ(SCALER_DISPEOLN); | |
| 281 | + HVS_WRITE(SCALER_DISPEOLN, | |
| 282 | + (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) | | |
| 283 | + VC4_SET_FIELD(mux, SCALER_DISPEOLN_DSP4_MUX)); | |
| 284 | + | |
| 241 | 285 | break; |
| 242 | 286 | |
| 243 | 287 | case 5: |
| 244 | − dsp5_mux = vc4_state->assigned_channel; | |
| 288 | + if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED) | |
| 289 | + mux = 3; | |
| 290 | + else | |
| 291 | + mux = vc4_state->assigned_channel; | |
| 292 | + | |
| 293 | + reg = HVS_READ(SCALER_DISPDITHER); | |
| 294 | + HVS_WRITE(SCALER_DISPDITHER, | |
| 295 | + (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) | | |
| 296 | + VC4_SET_FIELD(mux, SCALER_DISPDITHER_DSP5_MUX)); | |
| 245 | 297 | break; |
| 246 | 298 | |
| 247 | 299 | default: |
| 248 | 300 | break; |
| 249 | 301 | } |
| 250 | 302 | } |
| 251 | − | |
| 252 | − reg = HVS_READ(SCALER_DISPECTRL); | |
| 253 | − HVS_WRITE(SCALER_DISPECTRL, | |
| 254 | − (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) | | |
| 255 | − VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX)); | |
| 256 | − | |
| 257 | − reg = HVS_READ(SCALER_DISPCTRL); | |
| 258 | − HVS_WRITE(SCALER_DISPCTRL, | |
| 259 | − (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) | | |
| 260 | − VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX)); | |
| 261 | − | |
| 262 | − reg = HVS_READ(SCALER_DISPEOLN); | |
| 263 | − HVS_WRITE(SCALER_DISPEOLN, | |
| 264 | − (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) | | |
| 265 | − VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX)); | |
| 266 | − | |
| 267 | − reg = HVS_READ(SCALER_DISPDITHER); | |
| 268 | − HVS_WRITE(SCALER_DISPDITHER, | |
| 269 | − (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) | | |
| 270 | − VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX)); | |
| 271 | 303 | } |
| 272 | 304 | |
| 273 | 305 | static void |
| @@ -657,53 +689,123 @@ static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) · 383 unmodified lines | ||
| 657 | 689 | &load_state->base, |
| 658 | 690 | &vc4_load_tracker_state_funcs); |
| 659 | 691 | |
| 660 | − return drmm_add_action(&vc4->base, vc4_load_tracker_obj_fini, NULL); | |
| 692 | + return drmm_add_action_or_reset(&vc4->base, vc4_load_tracker_obj_fini, NULL); | |
| 661 | 693 | } |
| 662 | 694 | |
| 663 | −#define NUM_OUTPUTS 6 | |
| 664 | −#define NUM_CHANNELS 3 | |
| 695 | +static struct drm_private_state * | |
| 696 | +vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) | |
| 697 | +{ | |
| 698 | + struct vc4_hvs_state *old_state = to_vc4_hvs_state(obj->state); | |
| 699 | + struct vc4_hvs_state *state; | |
| 700 | + | |
| 701 | + state = kzalloc(sizeof(*state), GFP_KERNEL); | |
| 702 | + if (!state) | |
| 703 | + return NULL; | |
| 665 | 704 | |
| 666 | −static int | |
| 667 | −vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) | |
| 705 | + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); | |
| 706 | + | |
| 707 | + state->unassigned_channels = old_state->unassigned_channels; | |
| 708 | + | |
| 709 | + return &state->base; | |
| 710 | +} | |
| 711 | + | |
| 712 | +static void vc4_hvs_channels_destroy_state(struct drm_private_obj *obj, | |
| 713 | + struct drm_private_state *state) | |
| 668 | 714 | { |
| 669 | − unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0); | |
| 670 | − struct drm_crtc_state *old_crtc_state, *new_crtc_state; | |
| 671 | − struct drm_crtc *crtc; | |
| 672 | − int i, ret; | |
| 715 | + struct vc4_hvs_state *hvs_state = to_vc4_hvs_state(state); | |
| 673 | 716 | |
| 674 | − /* | |
| 675 | − * Since the HVS FIFOs are shared across all the pixelvalves and | |
| 676 | − * the TXP (and thus all the CRTCs), we need to pull the current | |
| 677 | − * state of all the enabled CRTCs so that an update to a single | |
| 678 | − * CRTC still keeps the previous FIFOs enabled and assigned to | |
| 679 | − * the same CRTCs, instead of evaluating only the CRTC being | |
| 680 | − * modified. | |
| 681 | − */ | |
| 682 | − list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | |
| 683 | − struct drm_crtc_state *crtc_state; | |
| 717 | + kfree(hvs_state); | |
| 718 | +} | |
| 684 | 719 | |
| 685 | − if (!crtc->state->enable) | |
| 686 | − continue; | |
| 720 | +static const struct drm_private_state_funcs vc4_hvs_state_funcs = { | |
| 721 | + .atomic_duplicate_state = vc4_hvs_channels_duplicate_state, | |
| 722 | + .atomic_destroy_state = vc4_hvs_channels_destroy_state, | |
| 723 | +}; | |
| 687 | 724 | |
| 688 | − crtc_state = drm_atomic_get_crtc_state(state, crtc); | |
| 689 | − if (IS_ERR(crtc_state)) | |
| 690 | − return PTR_ERR(crtc_state); | |
| 691 | − } | |
| 725 | +static void vc4_hvs_channels_obj_fini(struct drm_device *dev, void *unused) | |
| 726 | +{ | |
| 727 | + struct vc4_dev *vc4 = to_vc4_dev(dev); | |
| 728 | + | |
| 729 | + drm_atomic_private_obj_fini(&vc4->hvs_channels); | |
| 730 | +} | |
| 731 | + | |
| 732 | +static int vc4_hvs_channels_obj_init(struct vc4_dev *vc4) | |
| 733 | +{ | |
| 734 | + struct vc4_hvs_state *state; | |
| 735 | + | |
| 736 | + state = kzalloc(sizeof(*state), GFP_KERNEL); | |
| 737 | + if (!state) | |
| 738 | + return -ENOMEM; | |
| 739 | + | |
| 740 | + state->unassigned_channels = GENMASK(HVS_NUM_CHANNELS - 1, 0); | |
| 741 | + drm_atomic_private_obj_init(&vc4->base, &vc4->hvs_channels, | |
| 742 | + &state->base, | |
| 743 | + &vc4_hvs_state_funcs); | |
| 744 | + | |
| 745 | + return drmm_add_action_or_reset(&vc4->base, vc4_hvs_channels_obj_fini, NULL); | |
| 746 | +} | |
| 747 | + | |
| 748 | +/* | |
| 749 | + * The BCM2711 HVS has up to 7 outputs connected to the pixelvalves and | |
| 750 | + * the TXP (and therefore all the CRTCs found on that platform). | |
| 751 | + * | |
| 752 | + * The naive (and our initial) implementation would just iterate over | |
| 753 | + * all the active CRTCs, try to find a suitable FIFO, and then remove it | |
| 754 | + * from the pool of available FIFOs. However, there are a few corner | |
| 755 | + * cases that need to be considered: | |
| 756 | + * | |
| 757 | + * - When running in a dual-display setup (so with two CRTCs involved), | |
| 758 | + * we can update the state of a single CRTC (for example by changing | |
| 759 | + * its mode using xrandr under X11) without affecting the other. In | |
| 760 | + * this case, the other CRTC wouldn't be in the state at all, so we | |
| 761 | + * need to consider all the running CRTCs in the DRM device to assign | |
| 762 | + * a FIFO, not just the one in the state. | |
| 763 | + * | |
| 764 | + * - To fix the above, we can't use drm_atomic_get_crtc_state on all | |
| 765 | + * enabled CRTCs to pull their CRTC state into the global state, since | |
| 766 | + * a page flip would start considering their vblank to complete. Since | |
| 767 | + * we don't have a guarantee that they are actually active, that | |
| 768 | + * vblank might never happen, and shouldn't even be considered if we | |
| 769 | + * want to do a page flip on a single CRTC. That can be tested by | |
| 770 | + * doing a modetest -v first on HDMI1 and then on HDMI0. | |
| 771 | + * | |
| 772 | + * - Since we need the pixelvalve to be disabled and enabled back when | |
| 773 | + * the FIFO is changed, we should keep the FIFO assigned for as long | |
| 774 | + * as the CRTC is enabled, only considering it free again once that | |
| 775 | + * CRTC has been disabled. This can be tested by booting X11 on a | |
| 776 | + * single display, and changing the resolution down and then back up. | |
| 777 | + */ | |
| 778 | +static int vc4_pv_muxing_atomic_check(struct drm_device *dev, | |
| 779 | + struct drm_atomic_state *state) | |
| 780 | +{ | |
| 781 | + struct vc4_hvs_state *hvs_new_state; | |
| 782 | + struct drm_crtc_state *old_crtc_state, *new_crtc_state; | |
| 783 | + struct drm_crtc *crtc; | |
| 784 | + unsigned int i; | |
| 785 | + | |
| 786 | + hvs_new_state = vc4_hvs_get_global_state(state); | |
| 787 | + if (!hvs_new_state) | |
| 788 | + return -EINVAL; | |
| 692 | 789 | |
| 693 | 790 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
| 791 | + struct vc4_crtc_state *old_vc4_crtc_state = | |
| 792 | + to_vc4_crtc_state(old_crtc_state); | |
| 694 | 793 | struct vc4_crtc_state *new_vc4_crtc_state = |
| 695 | 794 | to_vc4_crtc_state(new_crtc_state); |
| 696 | 795 | struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); |
| 697 | 796 | unsigned int matching_channels; |
| 698 | 797 | |
| 699 | − if (old_crtc_state->enable && !new_crtc_state->enable) | |
| 700 | − new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; | |
| 701 | − | |
| 702 | − if (!new_crtc_state->enable) | |
| 798 | + /* Nothing to do here, let's skip it */ | |
| 799 | + if (old_crtc_state->enable == new_crtc_state->enable) | |
| 703 | 800 | continue; |
| 704 | 801 | |
| 705 | − if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) { | |
| 706 | − unassigned_channels &= ~BIT(new_vc4_crtc_state->assigned_channel); | |
| 802 | + /* Muxing will need to be modified, mark it as such */ | |
| 803 | + new_vc4_crtc_state->update_muxing = true; | |
| 804 | + | |
| 805 | + /* If we're disabling our CRTC, we put back our channel */ | |
| 806 | + if (!new_crtc_state->enable) { | |
| 807 | + hvs_new_state->unassigned_channels |= BIT(old_vc4_crtc_state->assigned_channel); | |
| 808 | + new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; | |
| 707 | 809 | continue; |
| 708 | 810 | } |
| 709 | 811 | |
| @@ -731,17 +833,29 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) · 21 unmodified lines | ||
| 731 | 833 | * the future, we will need to have something smarter, |
| 732 | 834 | * but it works so far. |
| 733 | 835 | */ |
| 734 | − matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels; | |
| 836 | + matching_channels = hvs_new_state->unassigned_channels & vc4_crtc->data->hvs_available_channels; | |
| 735 | 837 | if (matching_channels) { |
| 736 | 838 | unsigned int channel = ffs(matching_channels) - 1; |
| 737 | 839 | |
| 738 | 840 | new_vc4_crtc_state->assigned_channel = channel; |
| 739 | − unassigned_channels &= ~BIT(channel); | |
| 841 | + hvs_new_state->unassigned_channels &= ~BIT(channel); | |
| 740 | 842 | } else { |
| 741 | 843 | return -EINVAL; |
| 742 | 844 | } |
| 743 | 845 | } |
| 744 | 846 | |
| 847 | + return 0; | |
| 848 | +} | |
| 849 | + | |
| 850 | +static int | |
| 851 | +vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) | |
| 852 | +{ | |
| 853 | + int ret; | |
| 854 | + | |
| 855 | + ret = vc4_pv_muxing_atomic_check(dev, state); | |
| 856 | + if (ret) | |
| 857 | + return ret; | |
| 858 | + | |
| 745 | 859 | ret = vc4_ctm_atomic_check(dev, state); |
| 746 | 860 | if (ret < 0) |
| 747 | 861 | return ret; |
| @@ -808,6 +922,10 @@ int vc4_kms_load(struct drm_device *dev) · 60 unmodified lines | ||
| 808 | 922 | if (ret) |
| 809 | 923 | return ret; |
| 810 | 924 | |
| 925 | + ret = vc4_hvs_channels_obj_init(vc4); | |
| 926 | + if (ret) | |
| 927 | + return ret; | |
| 928 | + | |
| 811 | 929 | drm_mode_config_reset(dev); |
| 812 | 930 | |
| 813 | 931 | drm_kms_helper_poll_init(dev); |
| @@ -23,19 +23,17 @@ · 22 unmodified lines | ||
| 23 | 23 | #define CP_2WHEEL_MOUSE_HACK 0x02 |
| 24 | 24 | #define CP_2WHEEL_MOUSE_HACK_ON 0x04 |
| 25 | 25 | |
| 26 | +#define VA_INVAL_LOGICAL_BOUNDARY 0x08 | |
| 27 | + | |
| 26 | 28 | /* |
| 27 | 29 | * Some USB barcode readers from cypress have usage min and usage max in |
| 28 | 30 | * the wrong order |
| 29 | 31 | */ |
| 30 | −static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |
| 32 | +static __u8 *cp_rdesc_fixup(struct hid_device *hdev, __u8 *rdesc, | |
| 31 | 33 | unsigned int *rsize) |
| 32 | 34 | { |
| 33 | − unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | |
| 34 | 35 | unsigned int i; |
| 35 | 36 | |
| 36 | − if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) | |
| 37 | − return rdesc; | |
| 38 | − | |
| 39 | 37 | if (*rsize < 4) |
| 40 | 38 | return rdesc; |
| 41 | 39 | |
| @@ -48,6 +46,40 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 6 unmodified lines | ||
| 48 | 46 | return rdesc; |
| 49 | 47 | } |
| 50 | 48 | |
| 49 | +static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc, | |
| 50 | + unsigned int *rsize) | |
| 51 | +{ | |
| 52 | + /* | |
| 53 | + * Varmilo VA104M (with VID Cypress and device ID 07B1) incorrectly | |
| 54 | + * reports Logical Minimum of its Consumer Control device as 572 | |
| 55 | + * (0x02 0x3c). Fix this by setting its Logical Minimum to zero. | |
| 56 | + */ | |
| 57 | + if (*rsize == 25 && | |
| 58 | + rdesc[0] == 0x05 && rdesc[1] == 0x0c && | |
| 59 | + rdesc[2] == 0x09 && rdesc[3] == 0x01 && | |
| 60 | + rdesc[6] == 0x19 && rdesc[7] == 0x00 && | |
| 61 | + rdesc[11] == 0x16 && rdesc[12] == 0x3c && rdesc[13] == 0x02) { | |
| 62 | + hid_info(hdev, | |
| 63 | + "fixing up varmilo VA104M consumer control report descriptor\n"); | |
| 64 | + rdesc[12] = 0x00; | |
| 65 | + rdesc[13] = 0x00; | |
| 66 | + } | |
| 67 | + return rdesc; | |
| 68 | +} | |
| 69 | + | |
| 70 | +static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |
| 71 | + unsigned int *rsize) | |
| 72 | +{ | |
| 73 | + unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | |
| 74 | + | |
| 75 | + if (quirks & CP_RDESC_SWAPPED_MIN_MAX) | |
| 76 | + rdesc = cp_rdesc_fixup(hdev, rdesc, rsize); | |
| 77 | + if (quirks & VA_INVAL_LOGICAL_BOUNDARY) | |
| 78 | + rdesc = va_logical_boundary_fixup(hdev, rdesc, rsize); | |
| 79 | + | |
| 80 | + return rdesc; | |
| 81 | +} | |
| 82 | + | |
| 51 | 83 | static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, |
| 52 | 84 | struct hid_field *field, struct hid_usage *usage, |
| 53 | 85 | unsigned long **bit, int *max) |
| @@ -128,6 +160,8 @@ static const struct hid_device_id cp_devices[] = { · 74 unmodified lines | ||
| 128 | 160 | .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, |
| 129 | 161 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), |
| 130 | 162 | .driver_data = CP_2WHEEL_MOUSE_HACK }, |
| 163 | + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1), | |
| 164 | + .driver_data = VA_INVAL_LOGICAL_BOUNDARY }, | |
| 131 | 165 | { } |
| 132 | 166 | }; |
| 133 | 167 | MODULE_DEVICE_TABLE(hid, cp_devices); |
| @@ -331,6 +331,8 @@ · 330 unmodified lines | ||
| 331 | 331 | #define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81 |
| 332 | 332 | #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 |
| 333 | 333 | |
| 334 | +#define USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1 0X07b1 | |
| 335 | + | |
| 334 | 336 | #define USB_VENDOR_ID_DATA_MODUL 0x7374 |
| 335 | 337 | #define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH 0x1201 |
| 336 | 338 | |
| @@ -443,6 +445,10 @@ · 106 unmodified lines | ||
| 443 | 445 | #define USB_VENDOR_ID_FRUCTEL 0x25B6 |
| 444 | 446 | #define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002 |
| 445 | 447 | |
| 448 | +#define USB_VENDOR_ID_GAMEVICE 0x27F8 | |
| 449 | +#define USB_DEVICE_ID_GAMEVICE_GV186 0x0BBE | |
| 450 | +#define USB_DEVICE_ID_GAMEVICE_KISHI 0x0BBF | |
| 451 | + | |
| 446 | 452 | #define USB_VENDOR_ID_GAMERON 0x0810 |
| 447 | 453 | #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001 |
| 448 | 454 | #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 |
| @@ -485,6 +491,7 @@ · 36 unmodified lines | ||
| 485 | 491 | #define USB_DEVICE_ID_PENPOWER 0x00f4 |
| 486 | 492 | |
| 487 | 493 | #define USB_VENDOR_ID_GREENASIA 0x0e8f |
| 494 | +#define USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR 0x3010 | |
| 488 | 495 | #define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD 0x3013 |
| 489 | 496 | |
| 490 | 497 | #define USB_VENDOR_ID_GRETAGMACBETH 0x0971 |
| @@ -743,6 +750,7 @@ · 252 unmodified lines | ||
| 743 | 750 | #define USB_VENDOR_ID_LOGITECH 0x046d |
| 744 | 751 | #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e |
| 745 | 752 | #define USB_DEVICE_ID_LOGITECH_T651 0xb00c |
| 753 | +#define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD 0xb309 | |
| 746 | 754 | #define USB_DEVICE_ID_LOGITECH_C007 0xc007 |
| 747 | 755 | #define USB_DEVICE_ID_LOGITECH_C077 0xc077 |
| 748 | 756 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 |
| @@ -1298,6 +1306,7 @@ · 549 unmodified lines | ||
| 1298 | 1306 | |
| 1299 | 1307 | #define USB_VENDOR_ID_UGTIZER 0x2179 |
| 1300 | 1308 | #define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053 |
| 1309 | +#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040 0x0077 | |
| 1301 | 1310 | |
| 1302 | 1311 | #define USB_VENDOR_ID_VIEWSONIC 0x0543 |
| 1303 | 1312 | #define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621 |
| @@ -319,6 +319,9 @@ static const struct hid_device_id hid_battery_quirks[] = { · 318 unmodified lines | ||
| 319 | 319 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 320 | 320 | USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), |
| 321 | 321 | HID_BATTERY_QUIRK_IGNORE }, |
| 322 | + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, | |
| 323 | + USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), | |
| 324 | + HID_BATTERY_QUIRK_IGNORE }, | |
| 322 | 325 | {} |
| 323 | 326 | }; |
| 324 | 327 | |
| @@ -11,6 +11,48 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | #include "hid-ids.h" |
| 13 | 13 | |
| 14 | +#define QUIRK_TOUCHPAD_ON_OFF_REPORT BIT(0) | |
| 15 | + | |
| 16 | +static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) | |
| 17 | +{ | |
| 18 | + unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | |
| 19 | + | |
| 20 | + if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) { | |
| 21 | + if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) { | |
| 22 | + hid_info(hdev, "Fixing up ITE keyboard report descriptor\n"); | |
| 23 | + rdesc[163] = HID_MAIN_ITEM_RELATIVE; | |
| 24 | + } | |
| 25 | + } | |
| 26 | + | |
| 27 | + return rdesc; | |
| 28 | +} | |
| 29 | + | |
| 30 | +static int ite_input_mapping(struct hid_device *hdev, | |
| 31 | + struct hid_input *hi, struct hid_field *field, | |
| 32 | + struct hid_usage *usage, unsigned long **bit, | |
| 33 | + int *max) | |
| 34 | +{ | |
| 35 | + | |
| 36 | + unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | |
| 37 | + | |
| 38 | + if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) && | |
| 39 | + (usage->hid & HID_USAGE_PAGE) == 0x00880000) { | |
| 40 | + if (usage->hid == 0x00880078) { | |
| 41 | + /* Touchpad on, userspace expects F22 for this */ | |
| 42 | + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F22); | |
| 43 | + return 1; | |
| 44 | + } | |
| 45 | + if (usage->hid == 0x00880079) { | |
| 46 | + /* Touchpad off, userspace expects F23 for this */ | |
| 47 | + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F23); | |
| 48 | + return 1; | |
| 49 | + } | |
| 50 | + return -1; | |
| 51 | + } | |
| 52 | + | |
| 53 | + return 0; | |
| 54 | +} | |
| 55 | + | |
| 14 | 56 | static int ite_event(struct hid_device *hdev, struct hid_field *field, |
| 15 | 57 | struct hid_usage *usage, __s32 value) |
| 16 | 58 | { |
| @@ -37,13 +79,27 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field, · 20 unmodified lines | ||
| 37 | 79 | return 0; |
| 38 | 80 | } |
| 39 | 81 | |
| 82 | +static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id) | |
| 83 | +{ | |
| 84 | + int ret; | |
| 85 | + | |
| 86 | + hid_set_drvdata(hdev, (void *)id->driver_data); | |
| 87 | + | |
| 88 | + ret = hid_open_report(hdev); | |
| 89 | + if (ret) | |
| 90 | + return ret; | |
| 91 | + | |
| 92 | + return hid_hw_start(hdev, HID_CONNECT_DEFAULT); | |
| 93 | +} | |
| 94 | + | |
| 40 | 95 | static const struct hid_device_id ite_devices[] = { |
| 41 | 96 | { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) }, |
| 42 | 97 | { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) }, |
| 43 | 98 | /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */ |
| 44 | 99 | { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, |
| 45 | 100 | USB_VENDOR_ID_SYNAPTICS, |
| 46 | − USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) }, | |
| 101 | + USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012), | |
| 102 | + .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT }, | |
| 47 | 103 | /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */ |
| 48 | 104 | { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, |
| 49 | 105 | USB_VENDOR_ID_SYNAPTICS, |
| @@ -55,6 +111,9 @@ MODULE_DEVICE_TABLE(hid, ite_devices); · 5 unmodified lines | ||
| 55 | 111 | static struct hid_driver ite_driver = { |
| 56 | 112 | .name = "itetech", |
| 57 | 113 | .id_table = ite_devices, |
| 114 | + .probe = ite_probe, | |
| 115 | + .report_fixup = ite_report_fixup, | |
| 116 | + .input_mapping = ite_input_mapping, | |
| 58 | 117 | .event = ite_event, |
| 59 | 118 | }; |
| 60 | 119 | module_hid_driver(ite_driver); |
| @@ -328,7 +328,7 @@ static const char mse_bluetooth_descriptor[] = { · 327 unmodified lines | ||
| 328 | 328 | 0x25, 0x01, /* LOGICAL_MAX (1) */ |
| 329 | 329 | 0x75, 0x01, /* REPORT_SIZE (1) */ |
| 330 | 330 | 0x95, 0x04, /* REPORT_COUNT (4) */ |
| 331 | − 0x81, 0x06, /* INPUT */ | |
| 331 | + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ | |
| 332 | 332 | 0xC0, /* END_COLLECTION */ |
| 333 | 333 | 0xC0, /* END_COLLECTION */ |
| 334 | 334 | }; |
| @@ -866,11 +866,24 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, · 531 unmodified lines | ||
| 866 | 866 | schedule_work(&djrcv_dev->work); |
| 867 | 867 | } |
| 868 | 868 | |
| 869 | +/* | |
| 870 | + * Some quad/bluetooth keyboards have a builtin touchpad in this case we see | |
| 871 | + * only 1 paired device with a device_type of REPORT_TYPE_KEYBOARD. For the | |
| 872 | + * touchpad to work we must also forward mouse input reports to the dj_hiddev | |
| 873 | + * created for the keyboard (instead of forwarding them to a second paired | |
| 874 | + * device with a device_type of REPORT_TYPE_MOUSE as we normally would). | |
| 875 | + */ | |
| 876 | +static const u16 kbd_builtin_touchpad_ids[] = { | |
| 877 | + 0xb309, /* Dinovo Edge */ | |
| 878 | + 0xb30c, /* Dinovo Mini */ | |
| 879 | +}; | |
| 880 | + | |
| 869 | 881 | static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev, |
| 870 | 882 | struct hidpp_event *hidpp_report, |
| 871 | 883 | struct dj_workitem *workitem) |
| 872 | 884 | { |
| 873 | 885 | struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); |
| 886 | + int i, id; | |
| 874 | 887 | |
| 875 | 888 | workitem->type = WORKITEM_TYPE_PAIRED; |
| 876 | 889 | workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] & |
| @@ -882,6 +895,13 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev, · 5 unmodified lines | ||
| 882 | 895 | workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA | |
| 883 | 896 | POWER_KEYS | MEDIA_CENTER | |
| 884 | 897 | HIDPP; |
| 898 | + id = (workitem->quad_id_msb << 8) | workitem->quad_id_lsb; | |
| 899 | + for (i = 0; i < ARRAY_SIZE(kbd_builtin_touchpad_ids); i++) { | |
| 900 | + if (id == kbd_builtin_touchpad_ids[i]) { | |
| 901 | + workitem->reports_supported |= STD_MOUSE; | |
| 902 | + break; | |
| 903 | + } | |
| 904 | + } | |
| 885 | 905 | break; |
| 886 | 906 | case REPORT_TYPE_MOUSE: |
| 887 | 907 | workitem->reports_supported |= STD_MOUSE | HIDPP; |
| @@ -93,6 +93,8 @@ MODULE_PARM_DESC(disable_tap_to_click, · 92 unmodified lines | ||
| 93 | 93 | #define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS BIT(3) |
| 94 | 94 | #define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4) |
| 95 | 95 | |
| 96 | +#define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) | |
| 97 | + | |
| 96 | 98 | /* |
| 97 | 99 | * There are two hidpp protocols in use, the first version hidpp10 is known |
| 98 | 100 | * as register access protocol or RAP, the second version hidpp20 is known as |
| @@ -2950,6 +2952,26 @@ static int g920_get_config(struct hidpp_device *hidpp, · 2851 unmodified lines | ||
| 2950 | 2952 | return g920_ff_set_autocenter(hidpp, data); |
| 2951 | 2953 | } |
| 2952 | 2954 | |
| 2955 | +/* -------------------------------------------------------------------------- */ | |
| 2956 | +/* Logitech Dinovo Mini keyboard with builtin touchpad */ | |
| 2957 | +/* -------------------------------------------------------------------------- */ | |
| 2958 | +#define DINOVO_MINI_PRODUCT_ID 0xb30c | |
| 2959 | + | |
| 2960 | +static int lg_dinovo_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 2961 | + struct hid_field *field, struct hid_usage *usage, | |
| 2962 | + unsigned long **bit, int *max) | |
| 2963 | +{ | |
| 2964 | + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) | |
| 2965 | + return 0; | |
| 2966 | + | |
| 2967 | + switch (usage->hid & HID_USAGE) { | |
| 2968 | + case 0x00d: lg_map_key_clear(KEY_MEDIA); break; | |
| 2969 | + default: | |
| 2970 | + return 0; | |
| 2971 | + } | |
| 2972 | + return 1; | |
| 2973 | +} | |
| 2974 | + | |
| 2953 | 2975 | /* -------------------------------------------------------------------------- */ |
| 2954 | 2976 | /* HID++1.0 devices which use HID++ reports for their wheels */ |
| 2955 | 2977 | /* -------------------------------------------------------------------------- */ |
| @@ -3185,6 +3207,9 @@ static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi, · 229 unmodified lines | ||
| 3185 | 3207 | field->application != HID_GD_MOUSE) |
| 3186 | 3208 | return m560_input_mapping(hdev, hi, field, usage, bit, max); |
| 3187 | 3209 | |
| 3210 | + if (hdev->product == DINOVO_MINI_PRODUCT_ID) | |
| 3211 | + return lg_dinovo_input_mapping(hdev, hi, field, usage, bit, max); | |
| 3212 | + | |
| 3188 | 3213 | return 0; |
| 3189 | 3214 | } |
| 3190 | 3215 | |
| @@ -3947,6 +3972,7 @@ static const struct hid_device_id hidpp_devices[] = { · 756 unmodified lines | ||
| 3947 | 3972 | LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, |
| 3948 | 3973 | { /* Mouse Logitech MX Anywhere 2 */ |
| 3949 | 3974 | LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, |
| 3975 | + { LDJ_DEVICE(0x4072), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, | |
| 3950 | 3976 | { LDJ_DEVICE(0xb013), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, |
| 3951 | 3977 | { LDJ_DEVICE(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, |
| 3952 | 3978 | { LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, |
| @@ -3971,6 +3997,9 @@ static const struct hid_device_id hidpp_devices[] = { · 18 unmodified lines | ||
| 3971 | 3997 | { /* Keyboard MX5000 (Bluetooth-receiver in HID proxy mode) */ |
| 3972 | 3998 | LDJ_DEVICE(0xb305), |
| 3973 | 3999 | .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, |
| 4000 | + { /* Dinovo Edge (Bluetooth-receiver in HID proxy mode) */ | |
| 4001 | + LDJ_DEVICE(0xb309), | |
| 4002 | + .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, | |
| 3974 | 4003 | { /* Keyboard MX5500 (Bluetooth-receiver in HID proxy mode) */ |
| 3975 | 4004 | LDJ_DEVICE(0xb30b), |
| 3976 | 4005 | .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, |
| @@ -4013,6 +4042,9 @@ static const struct hid_device_id hidpp_devices[] = { · 36 unmodified lines | ||
| 4013 | 4042 | { /* MX5000 keyboard over Bluetooth */ |
| 4014 | 4043 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305), |
| 4015 | 4044 | .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, |
| 4045 | + { /* Dinovo Edge keyboard over Bluetooth */ | |
| 4046 | + HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb309), | |
| 4047 | + .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, | |
| 4016 | 4048 | { /* MX5500 keyboard over Bluetooth */ |
| 4017 | 4049 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), |
| 4018 | 4050 | .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, |
| @@ -49,6 +49,36 @@ enum { · 48 unmodified lines | ||
| 49 | 49 | MCP2221_ALT_F_NOT_GPIOD = 0xEF, |
| 50 | 50 | }; |
| 51 | 51 | |
| 52 | +/* MCP GPIO direction encoding */ | |
| 53 | +enum { | |
| 54 | + MCP2221_DIR_OUT = 0x00, | |
| 55 | + MCP2221_DIR_IN = 0x01, | |
| 56 | +}; | |
| 57 | + | |
| 58 | +#define MCP_NGPIO 4 | |
| 59 | + | |
| 60 | +/* MCP GPIO set command layout */ | |
| 61 | +struct mcp_set_gpio { | |
| 62 | + u8 cmd; | |
| 63 | + u8 dummy; | |
| 64 | + struct { | |
| 65 | + u8 change_value; | |
| 66 | + u8 value; | |
| 67 | + u8 change_direction; | |
| 68 | + u8 direction; | |
| 69 | + } gpio[MCP_NGPIO]; | |
| 70 | +} __packed; | |
| 71 | + | |
| 72 | +/* MCP GPIO get command layout */ | |
| 73 | +struct mcp_get_gpio { | |
| 74 | + u8 cmd; | |
| 75 | + u8 dummy; | |
| 76 | + struct { | |
| 77 | + u8 direction; | |
| 78 | + u8 value; | |
| 79 | + } gpio[MCP_NGPIO]; | |
| 80 | +} __packed; | |
| 81 | + | |
| 52 | 82 | /* |
| 53 | 83 | * There is no way to distinguish responses. Therefore next command |
| 54 | 84 | * is sent only after response to previous has been received. Mutex |
| @@ -542,7 +572,7 @@ static int mcp_gpio_get(struct gpio_chip *gc, · 487 unmodified lines | ||
| 542 | 572 | |
| 543 | 573 | mcp->txbuf[0] = MCP2221_GPIO_GET; |
| 544 | 574 | |
| 545 | − mcp->gp_idx = (offset + 1) * 2; | |
| 575 | + mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].value); | |
| 546 | 576 | |
| 547 | 577 | mutex_lock(&mcp->lock); |
| 548 | 578 | ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); |
| @@ -559,7 +589,7 @@ static void mcp_gpio_set(struct gpio_chip *gc, · 10 unmodified lines | ||
| 559 | 589 | memset(mcp->txbuf, 0, 18); |
| 560 | 590 | mcp->txbuf[0] = MCP2221_GPIO_SET; |
| 561 | 591 | |
| 562 | − mcp->gp_idx = ((offset + 1) * 4) - 1; | |
| 592 | + mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].value); | |
| 563 | 593 | |
| 564 | 594 | mcp->txbuf[mcp->gp_idx - 1] = 1; |
| 565 | 595 | mcp->txbuf[mcp->gp_idx] = !!value; |
| @@ -575,7 +605,7 @@ static int mcp_gpio_dir_set(struct mcp2221 *mcp, · 9 unmodified lines | ||
| 575 | 605 | memset(mcp->txbuf, 0, 18); |
| 576 | 606 | mcp->txbuf[0] = MCP2221_GPIO_SET; |
| 577 | 607 | |
| 578 | − mcp->gp_idx = (offset + 1) * 5; | |
| 608 | + mcp->gp_idx = offsetof(struct mcp_set_gpio, gpio[offset].direction); | |
| 579 | 609 | |
| 580 | 610 | mcp->txbuf[mcp->gp_idx - 1] = 1; |
| 581 | 611 | mcp->txbuf[mcp->gp_idx] = val; |
| @@ -590,7 +620,7 @@ static int mcp_gpio_direction_input(struct gpio_chip *gc, · 8 unmodified lines | ||
| 590 | 620 | struct mcp2221 *mcp = gpiochip_get_data(gc); |
| 591 | 621 | |
| 592 | 622 | mutex_lock(&mcp->lock); |
| 593 | − ret = mcp_gpio_dir_set(mcp, offset, 0); | |
| 623 | + ret = mcp_gpio_dir_set(mcp, offset, MCP2221_DIR_IN); | |
| 594 | 624 | mutex_unlock(&mcp->lock); |
| 595 | 625 | |
| 596 | 626 | return ret; |
| @@ -603,7 +633,7 @@ static int mcp_gpio_direction_output(struct gpio_chip *gc, · 6 unmodified lines | ||
| 603 | 633 | struct mcp2221 *mcp = gpiochip_get_data(gc); |
| 604 | 634 | |
| 605 | 635 | mutex_lock(&mcp->lock); |
| 606 | − ret = mcp_gpio_dir_set(mcp, offset, 1); | |
| 636 | + ret = mcp_gpio_dir_set(mcp, offset, MCP2221_DIR_OUT); | |
| 607 | 637 | mutex_unlock(&mcp->lock); |
| 608 | 638 | |
| 609 | 639 | /* Can't configure as output, bailout early */ |
| @@ -623,7 +653,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc, · 13 unmodified lines | ||
| 623 | 653 | |
| 624 | 654 | mcp->txbuf[0] = MCP2221_GPIO_GET; |
| 625 | 655 | |
| 626 | − mcp->gp_idx = (offset + 1) * 2; | |
| 656 | + mcp->gp_idx = offsetof(struct mcp_get_gpio, gpio[offset].direction); | |
| 627 | 657 | |
| 628 | 658 | mutex_lock(&mcp->lock); |
| 629 | 659 | ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1); |
| @@ -632,7 +662,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc, · 2 unmodified lines | ||
| 632 | 662 | if (ret) |
| 633 | 663 | return ret; |
| 634 | 664 | |
| 635 | − if (mcp->gpio_dir) | |
| 665 | + if (mcp->gpio_dir == MCP2221_DIR_IN) | |
| 636 | 666 | return GPIO_LINE_DIRECTION_IN; |
| 637 | 667 | |
| 638 | 668 | return GPIO_LINE_DIRECTION_OUT; |
| @@ -758,7 +788,7 @@ static int mcp2221_raw_event(struct hid_device *hdev, · 119 unmodified lines | ||
| 758 | 788 | mcp->status = -ENOENT; |
| 759 | 789 | } else { |
| 760 | 790 | mcp->status = !!data[mcp->gp_idx]; |
| 761 | − mcp->gpio_dir = !!data[mcp->gp_idx + 1]; | |
| 791 | + mcp->gpio_dir = data[mcp->gp_idx + 1]; | |
| 762 | 792 | } |
| 763 | 793 | break; |
| 764 | 794 | default: |
| @@ -860,7 +890,7 @@ static int mcp2221_probe(struct hid_device *hdev, · 95 unmodified lines | ||
| 860 | 890 | mcp->gc->get_direction = mcp_gpio_get_direction; |
| 861 | 891 | mcp->gc->set = mcp_gpio_set; |
| 862 | 892 | mcp->gc->get = mcp_gpio_get; |
| 863 | − mcp->gc->ngpio = 4; | |
| 893 | + mcp->gc->ngpio = MCP_NGPIO; | |
| 864 | 894 | mcp->gc->base = -1; |
| 865 | 895 | mcp->gc->can_sleep = 1; |
| 866 | 896 | mcp->gc->parent = &hdev->dev; |
| @@ -83,7 +83,12 @@ static const struct hid_device_id hid_quirks[] = { · 82 unmodified lines | ||
| 83 | 83 | { HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS }, |
| 84 | 84 | { HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET }, |
| 85 | 85 | { HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS }, |
| 86 | + { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR), HID_QUIRK_MULTI_INPUT }, | |
| 86 | 87 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT }, |
| 88 | + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_GV186), | |
| 89 | + HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, | |
| 90 | + { HID_USB_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_KISHI), | |
| 91 | + HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, | |
| 87 | 92 | { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
| 88 | 93 | { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
| 89 | 94 | { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
| @@ -483,7 +483,8 @@ static int sensor_hub_raw_event(struct hid_device *hdev, · 482 unmodified lines | ||
| 483 | 483 | return 1; |
| 484 | 484 | |
| 485 | 485 | ptr = raw_data; |
| 486 | − ptr++; /* Skip report id */ | |
| 486 | + if (report->id) | |
| 487 | + ptr++; /* Skip report id */ | |
| 487 | 488 | |
| 488 | 489 | spin_lock_irqsave(&pdata->lock, flags); |
| 489 | 490 | |
| @@ -385,6 +385,8 @@ static const struct hid_device_id uclogic_devices[] = { · 384 unmodified lines | ||
| 385 | 385 | USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) }, |
| 386 | 386 | { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, |
| 387 | 387 | USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, |
| 388 | + { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, | |
| 389 | + USB_DEVICE_ID_UGTIZER_TABLET_GT5040) }, | |
| 388 | 390 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, |
| 389 | 391 | USB_DEVICE_ID_UGEE_TABLET_G5) }, |
| 390 | 392 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, |
| @@ -997,6 +997,8 @@ int uclogic_params_init(struct uclogic_params *params, · 996 unmodified lines | ||
| 997 | 997 | break; |
| 998 | 998 | case VID_PID(USB_VENDOR_ID_UGTIZER, |
| 999 | 999 | USB_DEVICE_ID_UGTIZER_TABLET_GP0610): |
| 1000 | + case VID_PID(USB_VENDOR_ID_UGTIZER, | |
| 1001 | + USB_DEVICE_ID_UGTIZER_TABLET_GT5040): | |
| 1000 | 1002 | case VID_PID(USB_VENDOR_ID_UGEE, |
| 1001 | 1003 | USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540): |
| 1002 | 1004 | case VID_PID(USB_VENDOR_ID_UGEE, |
| @@ -943,6 +943,11 @@ static void i2c_hid_acpi_enable_wakeup(struct device *dev) · 942 unmodified lines | ||
| 943 | 943 | } |
| 944 | 944 | } |
| 945 | 945 | |
| 946 | +static void i2c_hid_acpi_shutdown(struct device *dev) | |
| 947 | +{ | |
| 948 | + acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D3_COLD); | |
| 949 | +} | |
| 950 | + | |
| 946 | 951 | static const struct acpi_device_id i2c_hid_acpi_match[] = { |
| 947 | 952 | {"ACPI0C50", 0 }, |
| 948 | 953 | {"PNP0C50", 0 }, |
| @@ -959,6 +964,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client, · 10 unmodified lines | ||
| 959 | 964 | static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {} |
| 960 | 965 | |
| 961 | 966 | static inline void i2c_hid_acpi_enable_wakeup(struct device *dev) {} |
| 967 | + | |
| 968 | +static inline void i2c_hid_acpi_shutdown(struct device *dev) {} | |
| 962 | 969 | #endif |
| 963 | 970 | |
| 964 | 971 | #ifdef CONFIG_OF |
| @@ -1175,6 +1182,8 @@ static void i2c_hid_shutdown(struct i2c_client *client) · 210 unmodified lines | ||
| 1175 | 1182 | |
| 1176 | 1183 | i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); |
| 1177 | 1184 | free_irq(client->irq, ihid); |
| 1185 | + | |
| 1186 | + i2c_hid_acpi_shutdown(&client->dev); | |
| 1178 | 1187 | } |
| 1179 | 1188 | |
| 1180 | 1189 | #ifdef CONFIG_PM_SLEEP |
| @@ -126,6 +126,12 @@ enum kx_chipset { · 125 unmodified lines | ||
| 126 | 126 | KX_MAX_CHIPS /* this must be last */ |
| 127 | 127 | }; |
| 128 | 128 | |
| 129 | +enum kx_acpi_type { | |
| 130 | + ACPI_GENERIC, | |
| 131 | + ACPI_SMO8500, | |
| 132 | + ACPI_KIOX010A, | |
| 133 | +}; | |
| 134 | + | |
| 129 | 135 | struct kxcjk1013_data { |
| 130 | 136 | struct i2c_client *client; |
| 131 | 137 | struct iio_trigger *dready_trig; |
| @@ -143,7 +149,7 @@ struct kxcjk1013_data { · 11 unmodified lines | ||
| 143 | 149 | bool motion_trigger_on; |
| 144 | 150 | int64_t timestamp; |
| 145 | 151 | enum kx_chipset chipset; |
| 146 | − bool is_smo8500_device; | |
| 152 | + enum kx_acpi_type acpi_type; | |
| 147 | 153 | }; |
| 148 | 154 | |
| 149 | 155 | enum kxcjk1013_axis { |
| @@ -270,6 +276,32 @@ static const struct { · 120 unmodified lines | ||
| 270 | 276 | {19163, 1, 0}, |
| 271 | 277 | {38326, 0, 1} }; |
| 272 | 278 | |
| 279 | +#ifdef CONFIG_ACPI | |
| 280 | +enum kiox010a_fn_index { | |
| 281 | + KIOX010A_SET_LAPTOP_MODE = 1, | |
| 282 | + KIOX010A_SET_TABLET_MODE = 2, | |
| 283 | +}; | |
| 284 | + | |
| 285 | +static int kiox010a_dsm(struct device *dev, int fn_index) | |
| 286 | +{ | |
| 287 | + acpi_handle handle = ACPI_HANDLE(dev); | |
| 288 | + guid_t kiox010a_dsm_guid; | |
| 289 | + union acpi_object *obj; | |
| 290 | + | |
| 291 | + if (!handle) | |
| 292 | + return -ENODEV; | |
| 293 | + | |
| 294 | + guid_parse("1f339696-d475-4e26-8cad-2e9f8e6d7a91", &kiox010a_dsm_guid); | |
| 295 | + | |
| 296 | + obj = acpi_evaluate_dsm(handle, &kiox010a_dsm_guid, 1, fn_index, NULL); | |
| 297 | + if (!obj) | |
| 298 | + return -EIO; | |
| 299 | + | |
| 300 | + ACPI_FREE(obj); | |
| 301 | + return 0; | |
| 302 | +} | |
| 303 | +#endif | |
| 304 | + | |
| 273 | 305 | static int kxcjk1013_set_mode(struct kxcjk1013_data *data, |
| 274 | 306 | enum kxcjk1013_mode mode) |
| 275 | 307 | { |
| @@ -347,6 +379,13 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 71 unmodified lines | ||
| 347 | 379 | { |
| 348 | 380 | int ret; |
| 349 | 381 | |
| 382 | +#ifdef CONFIG_ACPI | |
| 383 | + if (data->acpi_type == ACPI_KIOX010A) { | |
| 384 | + /* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */ | |
| 385 | + kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE); | |
| 386 | + } | |
| 387 | +#endif | |
| 388 | + | |
| 350 | 389 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I); |
| 351 | 390 | if (ret < 0) { |
| 352 | 391 | dev_err(&data->client->dev, "Error reading who_am_i\n"); |
| @@ -1247,7 +1286,7 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private) · 894 unmodified lines | ||
| 1247 | 1286 | |
| 1248 | 1287 | static const char *kxcjk1013_match_acpi_device(struct device *dev, |
| 1249 | 1288 | enum kx_chipset *chipset, |
| 1250 | − bool *is_smo8500_device) | |
| 1289 | + enum kx_acpi_type *acpi_type) | |
| 1251 | 1290 | { |
| 1252 | 1291 | const struct acpi_device_id *id; |
| 1253 | 1292 | |
| @@ -1256,7 +1295,9 @@ static const char *kxcjk1013_match_acpi_device(struct device *dev, · 2 unmodified lines | ||
| 1256 | 1295 | return NULL; |
| 1257 | 1296 | |
| 1258 | 1297 | if (strcmp(id->id, "SMO8500") == 0) |
| 1259 | − *is_smo8500_device = true; | |
| 1298 | + *acpi_type = ACPI_SMO8500; | |
| 1299 | + else if (strcmp(id->id, "KIOX010A") == 0) | |
| 1300 | + *acpi_type = ACPI_KIOX010A; | |
| 1260 | 1301 | |
| 1261 | 1302 | *chipset = (enum kx_chipset)id->driver_data; |
| 1262 | 1303 | |
| @@ -1299,7 +1340,7 @@ static int kxcjk1013_probe(struct i2c_client *client, · 36 unmodified lines | ||
| 1299 | 1340 | } else if (ACPI_HANDLE(&client->dev)) { |
| 1300 | 1341 | name = kxcjk1013_match_acpi_device(&client->dev, |
| 1301 | 1342 | &data->chipset, |
| 1302 | − &data->is_smo8500_device); | |
| 1343 | + &data->acpi_type); | |
| 1303 | 1344 | } else |
| 1304 | 1345 | return -ENODEV; |
| 1305 | 1346 | |
| @@ -1316,7 +1357,7 @@ static int kxcjk1013_probe(struct i2c_client *client, · 10 unmodified lines | ||
| 1316 | 1357 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1317 | 1358 | indio_dev->info = &kxcjk1013_info; |
| 1318 | 1359 | |
| 1319 | − if (client->irq > 0 && !data->is_smo8500_device) { | |
| 1360 | + if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) { | |
| 1320 | 1361 | ret = devm_request_threaded_irq(&client->dev, client->irq, |
| 1321 | 1362 | kxcjk1013_data_rdy_trig_poll, |
| 1322 | 1363 | kxcjk1013_event_handler, |
| @@ -71,7 +71,7 @@ · 70 unmodified lines | ||
| 71 | 71 | #define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS 10 |
| 72 | 72 | #define JZ4740_ADC_BATTERY_HIGH_VREF (7500 * 0.986) |
| 73 | 73 | #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12 |
| 74 | −#define JZ4770_ADC_BATTERY_VREF 6600 | |
| 74 | +#define JZ4770_ADC_BATTERY_VREF 1200 | |
| 75 | 75 | #define JZ4770_ADC_BATTERY_VREF_BITS 12 |
| 76 | 76 | |
| 77 | 77 | #define JZ_ADC_IRQ_AUX BIT(0) |
| @@ -177,13 +177,12 @@ static void ingenic_adc_set_config(struct ingenic_adc *adc, · 99 unmodified lines | ||
| 177 | 177 | mutex_unlock(&adc->lock); |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | −static void ingenic_adc_enable(struct ingenic_adc *adc, | |
| 181 | − int engine, | |
| 182 | − bool enabled) | |
| 180 | +static void ingenic_adc_enable_unlocked(struct ingenic_adc *adc, | |
| 181 | + int engine, | |
| 182 | + bool enabled) | |
| 183 | 183 | { |
| 184 | 184 | u8 val; |
| 185 | 185 | |
| 186 | − mutex_lock(&adc->lock); | |
| 187 | 186 | val = readb(adc->base + JZ_ADC_REG_ENABLE); |
| 188 | 187 | |
| 189 | 188 | if (enabled) |
| @@ -192,20 +191,41 @@ static void ingenic_adc_enable(struct ingenic_adc *adc, · 2 unmodified lines | ||
| 192 | 191 | val &= ~BIT(engine); |
| 193 | 192 | |
| 194 | 193 | writeb(val, adc->base + JZ_ADC_REG_ENABLE); |
| 194 | +} | |
| 195 | + | |
| 196 | +static void ingenic_adc_enable(struct ingenic_adc *adc, | |
| 197 | + int engine, | |
| 198 | + bool enabled) | |
| 199 | +{ | |
| 200 | + mutex_lock(&adc->lock); | |
| 201 | + ingenic_adc_enable_unlocked(adc, engine, enabled); | |
| 195 | 202 | mutex_unlock(&adc->lock); |
| 196 | 203 | } |
| 197 | 204 | |
| 198 | 205 | static int ingenic_adc_capture(struct ingenic_adc *adc, |
| 199 | 206 | int engine) |
| 200 | 207 | { |
| 208 | + u32 cfg; | |
| 201 | 209 | u8 val; |
| 202 | 210 | int ret; |
| 203 | 211 | |
| 204 | − ingenic_adc_enable(adc, engine, true); | |
| 212 | + /* | |
| 213 | + * Disable CMD_SEL temporarily, because it causes wrong VBAT readings, | |
| 214 | + * probably due to the switch of VREF. We must keep the lock here to | |
| 215 | + * avoid races with the buffer enable/disable functions. | |
| 216 | + */ | |
| 217 | + mutex_lock(&adc->lock); | |
| 218 | + cfg = readl(adc->base + JZ_ADC_REG_CFG); | |
| 219 | + writel(cfg & ~JZ_ADC_REG_CFG_CMD_SEL, adc->base + JZ_ADC_REG_CFG); | |
| 220 | + | |
| 221 | + ingenic_adc_enable_unlocked(adc, engine, true); | |
| 205 | 222 | ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val, |
| 206 | 223 | !(val & BIT(engine)), 250, 1000); |
| 207 | 224 | if (ret) |
| 208 | − ingenic_adc_enable(adc, engine, false); | |
| 225 | + ingenic_adc_enable_unlocked(adc, engine, false); | |
| 226 | + | |
| 227 | + writel(cfg, adc->base + JZ_ADC_REG_CFG); | |
| 228 | + mutex_unlock(&adc->lock); | |
| 209 | 229 | |
| 210 | 230 | return ret; |
| 211 | 231 | } |
| @@ -9,9 +9,9 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/err.h> |
| 10 | 10 | #include <linux/kernel.h> |
| 11 | 11 | #include <linux/module.h> |
| 12 | −#include <linux/of.h> | |
| 13 | −#include <linux/of_device.h> | |
| 12 | +#include <linux/mod_devicetable.h> | |
| 14 | 13 | #include <linux/platform_device.h> |
| 14 | +#include <linux/property.h> | |
| 15 | 15 | #include <linux/iopoll.h> |
| 16 | 16 | #include <linux/io.h> |
| 17 | 17 | #include <linux/iio/iio.h> |
| @@ -276,6 +276,8 @@ static int mt6577_auxadc_probe(struct platform_device *pdev) · 258 unmodified lines | ||
| 276 | 276 | goto err_disable_clk; |
| 277 | 277 | } |
| 278 | 278 | |
| 279 | + adc_dev->dev_comp = device_get_match_data(&pdev->dev); | |
| 280 | + | |
| 279 | 281 | mutex_init(&adc_dev->lock); |
| 280 | 282 | |
| 281 | 283 | mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC, |
| @@ -41,18 +41,16 @@ · 40 unmodified lines | ||
| 41 | 41 | * struct stm32_adc_common_regs - stm32 common registers |
| 42 | 42 | * @csr: common status register offset |
| 43 | 43 | * @ccr: common control register offset |
| 44 | − * @eoc1_msk: adc1 end of conversion flag in @csr | |
| 45 | − * @eoc2_msk: adc2 end of conversion flag in @csr | |
| 46 | − * @eoc3_msk: adc3 end of conversion flag in @csr | |
| 44 | + * @eoc_msk: array of eoc (end of conversion flag) masks in csr for adc1..n | |
| 45 | + * @ovr_msk: array of ovr (overrun flag) masks in csr for adc1..n | |
| 47 | 46 | * @ier: interrupt enable register offset for each adc |
| 48 | 47 | * @eocie_msk: end of conversion interrupt enable mask in @ier |
| 49 | 48 | */ |
| 50 | 49 | struct stm32_adc_common_regs { |
| 51 | 50 | u32 csr; |
| 52 | 51 | u32 ccr; |
| 53 | − u32 eoc1_msk; | |
| 54 | − u32 eoc2_msk; | |
| 55 | − u32 eoc3_msk; | |
| 52 | + u32 eoc_msk[STM32_ADC_MAX_ADCS]; | |
| 53 | + u32 ovr_msk[STM32_ADC_MAX_ADCS]; | |
| 56 | 54 | u32 ier; |
| 57 | 55 | u32 eocie_msk; |
| 58 | 56 | }; |
| @@ -282,21 +280,20 @@ out: · 223 unmodified lines | ||
| 282 | 280 | static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { |
| 283 | 281 | .csr = STM32F4_ADC_CSR, |
| 284 | 282 | .ccr = STM32F4_ADC_CCR, |
| 285 | − .eoc1_msk = STM32F4_EOC1 | STM32F4_OVR1, | |
| 286 | − .eoc2_msk = STM32F4_EOC2 | STM32F4_OVR2, | |
| 287 | − .eoc3_msk = STM32F4_EOC3 | STM32F4_OVR3, | |
| 283 | + .eoc_msk = { STM32F4_EOC1, STM32F4_EOC2, STM32F4_EOC3}, | |
| 284 | + .ovr_msk = { STM32F4_OVR1, STM32F4_OVR2, STM32F4_OVR3}, | |
| 288 | 285 | .ier = STM32F4_ADC_CR1, |
| 289 | − .eocie_msk = STM32F4_EOCIE | STM32F4_OVRIE, | |
| 286 | + .eocie_msk = STM32F4_EOCIE, | |
| 290 | 287 | }; |
| 291 | 288 | |
| 292 | 289 | /* STM32H7 common registers definitions */ |
| 293 | 290 | static const struct stm32_adc_common_regs stm32h7_adc_common_regs = { |
| 294 | 291 | .csr = STM32H7_ADC_CSR, |
| 295 | 292 | .ccr = STM32H7_ADC_CCR, |
| 296 | − .eoc1_msk = STM32H7_EOC_MST | STM32H7_OVR_MST, | |
| 297 | − .eoc2_msk = STM32H7_EOC_SLV | STM32H7_OVR_SLV, | |
| 293 | + .eoc_msk = { STM32H7_EOC_MST, STM32H7_EOC_SLV}, | |
| 294 | + .ovr_msk = { STM32H7_OVR_MST, STM32H7_OVR_SLV}, | |
| 298 | 295 | .ier = STM32H7_ADC_IER, |
| 299 | − .eocie_msk = STM32H7_EOCIE | STM32H7_OVRIE, | |
| 296 | + .eocie_msk = STM32H7_EOCIE, | |
| 300 | 297 | }; |
| 301 | 298 | |
| 302 | 299 | static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = { |
| @@ -318,6 +315,7 @@ static void stm32_adc_irq_handler(struct irq_desc *desc) · 15 unmodified lines | ||
| 318 | 315 | { |
| 319 | 316 | struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc); |
| 320 | 317 | struct irq_chip *chip = irq_desc_get_chip(desc); |
| 318 | + int i; | |
| 321 | 319 | u32 status; |
| 322 | 320 | |
| 323 | 321 | chained_irq_enter(chip, desc); |
| @@ -335,17 +333,12 @@ static void stm32_adc_irq_handler(struct irq_desc *desc) · 11 unmodified lines | ||
| 335 | 333 | * before invoking the interrupt handler (e.g. call ISR only for |
| 336 | 334 | * IRQ-enabled ADCs). |
| 337 | 335 | */ |
| 338 | − if (status & priv->cfg->regs->eoc1_msk && | |
| 339 | − stm32_adc_eoc_enabled(priv, 0)) | |
| 340 | − generic_handle_irq(irq_find_mapping(priv->domain, 0)); | |
| 341 | − | |
| 342 | − if (status & priv->cfg->regs->eoc2_msk && | |
| 343 | − stm32_adc_eoc_enabled(priv, 1)) | |
| 344 | − generic_handle_irq(irq_find_mapping(priv->domain, 1)); | |
| 345 | − | |
| 346 | − if (status & priv->cfg->regs->eoc3_msk && | |
| 347 | − stm32_adc_eoc_enabled(priv, 2)) | |
| 348 | − generic_handle_irq(irq_find_mapping(priv->domain, 2)); | |
| 336 | + for (i = 0; i < priv->cfg->num_irqs; i++) { | |
| 337 | + if ((status & priv->cfg->regs->eoc_msk[i] && | |
| 338 | + stm32_adc_eoc_enabled(priv, i)) || | |
| 339 | + (status & priv->cfg->regs->ovr_msk[i])) | |
| 340 | + generic_handle_irq(irq_find_mapping(priv->domain, i)); | |
| 341 | + } | |
| 349 | 342 | |
| 350 | 343 | chained_irq_exit(chip, desc); |
| 351 | 344 | }; |
| @@ -154,6 +154,7 @@ struct stm32_adc; · 153 unmodified lines | ||
| 154 | 154 | * @start_conv: routine to start conversions |
| 155 | 155 | * @stop_conv: routine to stop conversions |
| 156 | 156 | * @unprepare: optional unprepare routine (disable, power-down) |
| 157 | + * @irq_clear: routine to clear irqs | |
| 157 | 158 | * @smp_cycles: programmable sampling time (ADC clock cycles) |
| 158 | 159 | */ |
| 159 | 160 | struct stm32_adc_cfg { |
| @@ -166,6 +167,7 @@ struct stm32_adc_cfg { · 6 unmodified lines | ||
| 166 | 167 | void (*start_conv)(struct iio_dev *, bool dma); |
| 167 | 168 | void (*stop_conv)(struct iio_dev *); |
| 168 | 169 | void (*unprepare)(struct iio_dev *); |
| 170 | + void (*irq_clear)(struct iio_dev *indio_dev, u32 msk); | |
| 169 | 171 | const unsigned int *smp_cycles; |
| 170 | 172 | }; |
| 171 | 173 | |
| @@ -621,6 +623,13 @@ static void stm32f4_adc_stop_conv(struct iio_dev *indio_dev) · 449 unmodified lines | ||
| 621 | 623 | STM32F4_ADON | STM32F4_DMA | STM32F4_DDS); |
| 622 | 624 | } |
| 623 | 625 | |
| 626 | +static void stm32f4_adc_irq_clear(struct iio_dev *indio_dev, u32 msk) | |
| 627 | +{ | |
| 628 | + struct stm32_adc *adc = iio_priv(indio_dev); | |
| 629 | + | |
| 630 | + stm32_adc_clr_bits(adc, adc->cfg->regs->isr_eoc.reg, msk); | |
| 631 | +} | |
| 632 | + | |
| 624 | 633 | static void stm32h7_adc_start_conv(struct iio_dev *indio_dev, bool dma) |
| 625 | 634 | { |
| 626 | 635 | struct stm32_adc *adc = iio_priv(indio_dev); |
| @@ -659,6 +668,13 @@ static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev) · 32 unmodified lines | ||
| 659 | 668 | stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK); |
| 660 | 669 | } |
| 661 | 670 | |
| 671 | +static void stm32h7_adc_irq_clear(struct iio_dev *indio_dev, u32 msk) | |
| 672 | +{ | |
| 673 | + struct stm32_adc *adc = iio_priv(indio_dev); | |
| 674 | + /* On STM32H7 IRQs are cleared by writing 1 into ISR register */ | |
| 675 | + stm32_adc_set_bits(adc, adc->cfg->regs->isr_eoc.reg, msk); | |
| 676 | +} | |
| 677 | + | |
| 662 | 678 | static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev) |
| 663 | 679 | { |
| 664 | 680 | struct stm32_adc *adc = iio_priv(indio_dev); |
| @@ -1235,17 +1251,40 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, · 570 unmodified lines | ||
| 1235 | 1251 | } |
| 1236 | 1252 | } |
| 1237 | 1253 | |
| 1254 | +static void stm32_adc_irq_clear(struct iio_dev *indio_dev, u32 msk) | |
| 1255 | +{ | |
| 1256 | + struct stm32_adc *adc = iio_priv(indio_dev); | |
| 1257 | + | |
| 1258 | + adc->cfg->irq_clear(indio_dev, msk); | |
| 1259 | +} | |
| 1260 | + | |
| 1238 | 1261 | static irqreturn_t stm32_adc_threaded_isr(int irq, void *data) |
| 1239 | 1262 | { |
| 1240 | 1263 | struct iio_dev *indio_dev = data; |
| 1241 | 1264 | struct stm32_adc *adc = iio_priv(indio_dev); |
| 1242 | 1265 | const struct stm32_adc_regspec *regs = adc->cfg->regs; |
| 1243 | 1266 | u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); |
| 1267 | + u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg); | |
| 1244 | 1268 | |
| 1245 | − if (status & regs->isr_ovr.mask) | |
| 1269 | + /* Check ovr status right now, as ovr mask should be already disabled */ | |
| 1270 | + if (status & regs->isr_ovr.mask) { | |
| 1271 | + /* | |
| 1272 | + * Clear ovr bit to avoid subsequent calls to IRQ handler. | |
| 1273 | + * This requires to stop ADC first. OVR bit state in ISR, | |
| 1274 | + * is propaged to CSR register by hardware. | |
| 1275 | + */ | |
| 1276 | + adc->cfg->stop_conv(indio_dev); | |
| 1277 | + stm32_adc_irq_clear(indio_dev, regs->isr_ovr.mask); | |
| 1246 | 1278 | dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n"); |
| 1279 | + return IRQ_HANDLED; | |
| 1280 | + } | |
| 1247 | 1281 | |
| 1248 | − return IRQ_HANDLED; | |
| 1282 | + if (!(status & mask)) | |
| 1283 | + dev_err_ratelimited(&indio_dev->dev, | |
| 1284 | + "Unexpected IRQ: IER=0x%08x, ISR=0x%08x\n", | |
| 1285 | + mask, status); | |
| 1286 | + | |
| 1287 | + return IRQ_NONE; | |
| 1249 | 1288 | } |
| 1250 | 1289 | |
| 1251 | 1290 | static irqreturn_t stm32_adc_isr(int irq, void *data) |
| @@ -1254,6 +1293,10 @@ static irqreturn_t stm32_adc_isr(int irq, void *data) · 2 unmodified lines | ||
| 1254 | 1293 | struct stm32_adc *adc = iio_priv(indio_dev); |
| 1255 | 1294 | const struct stm32_adc_regspec *regs = adc->cfg->regs; |
| 1256 | 1295 | u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); |
| 1296 | + u32 mask = stm32_adc_readl(adc, regs->ier_eoc.reg); | |
| 1297 | + | |
| 1298 | + if (!(status & mask)) | |
| 1299 | + return IRQ_WAKE_THREAD; | |
| 1257 | 1300 | |
| 1258 | 1301 | if (status & regs->isr_ovr.mask) { |
| 1259 | 1302 | /* |
| @@ -2046,6 +2089,7 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = { · 786 unmodified lines | ||
| 2046 | 2089 | .start_conv = stm32f4_adc_start_conv, |
| 2047 | 2090 | .stop_conv = stm32f4_adc_stop_conv, |
| 2048 | 2091 | .smp_cycles = stm32f4_adc_smp_cycles, |
| 2092 | + .irq_clear = stm32f4_adc_irq_clear, | |
| 2049 | 2093 | }; |
| 2050 | 2094 | |
| 2051 | 2095 | static const struct stm32_adc_cfg stm32h7_adc_cfg = { |
| @@ -2057,6 +2101,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { · 5 unmodified lines | ||
| 2057 | 2101 | .prepare = stm32h7_adc_prepare, |
| 2058 | 2102 | .unprepare = stm32h7_adc_unprepare, |
| 2059 | 2103 | .smp_cycles = stm32h7_adc_smp_cycles, |
| 2104 | + .irq_clear = stm32h7_adc_irq_clear, | |
| 2060 | 2105 | }; |
| 2061 | 2106 | |
| 2062 | 2107 | static const struct stm32_adc_cfg stm32mp1_adc_cfg = { |
| @@ -2069,6 +2114,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { · 6 unmodified lines | ||
| 2069 | 2114 | .prepare = stm32h7_adc_prepare, |
| 2070 | 2115 | .unprepare = stm32h7_adc_unprepare, |
| 2071 | 2116 | .smp_cycles = stm32h7_adc_smp_cycles, |
| 2117 | + .irq_clear = stm32h7_adc_irq_clear, | |
| 2072 | 2118 | }; |
| 2073 | 2119 | |
| 2074 | 2120 | static const struct of_device_id stm32_adc_of_match[] = { |
| @@ -256,7 +256,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, · 255 unmodified lines | ||
| 256 | 256 | struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent); |
| 257 | 257 | struct cros_ec_dev *ec = sensor_hub->ec; |
| 258 | 258 | struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); |
| 259 | − u32 ver_mask; | |
| 259 | + u32 ver_mask, temp; | |
| 260 | 260 | int frequencies[ARRAY_SIZE(state->frequencies) / 2] = { 0 }; |
| 261 | 261 | int ret, i; |
| 262 | 262 | |
| @@ -311,10 +311,16 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, · 48 unmodified lines | ||
| 311 | 311 | &frequencies[2], |
| 312 | 312 | &state->fifo_max_event_count); |
| 313 | 313 | } else { |
| 314 | − frequencies[1] = state->resp->info_3.min_frequency; | |
| 315 | − frequencies[2] = state->resp->info_3.max_frequency; | |
| 316 | − state->fifo_max_event_count = | |
| 317 | − state->resp->info_3.fifo_max_event_count; | |
| 314 | + if (state->resp->info_3.max_frequency == 0) { | |
| 315 | + get_default_min_max_freq(state->resp->info.type, | |
| 316 | + &frequencies[1], | |
| 317 | + &frequencies[2], | |
| 318 | + &temp); | |
| 319 | + } else { | |
| 320 | + frequencies[1] = state->resp->info_3.min_frequency; | |
| 321 | + frequencies[2] = state->resp->info_3.max_frequency; | |
| 322 | + } | |
| 323 | + state->fifo_max_event_count = state->resp->info_3.fifo_max_event_count; | |
| 318 | 324 | } |
| 319 | 325 | for (i = 0; i < ARRAY_SIZE(frequencies); i++) { |
| 320 | 326 | state->frequencies[2 * i] = frequencies[i] / 1000; |
| @@ -156,11 +156,13 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = { · 155 unmodified lines | ||
| 156 | 156 | static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw) |
| 157 | 157 | { |
| 158 | 158 | struct st_lsm6dsx_sensor *sensor; |
| 159 | − u32 odr; | |
| 159 | + u32 odr, timeout; | |
| 160 | 160 | |
| 161 | 161 | sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); |
| 162 | 162 | odr = (hw->enable_mask & BIT(ST_LSM6DSX_ID_ACC)) ? sensor->odr : 12500; |
| 163 | − msleep((2000000U / odr) + 1); | |
| 163 | + /* set 10ms as minimum timeout for i2c slave configuration */ | |
| 164 | + timeout = max_t(u32, 2000000U / odr + 1, 10); | |
| 165 | + msleep(timeout); | |
| 164 | 166 | } |
| 165 | 167 | |
| 166 | 168 | /* |
| @@ -544,6 +544,7 @@ config VCNL4000 · 543 unmodified lines | ||
| 544 | 544 | |
| 545 | 545 | config VCNL4035 |
| 546 | 546 | tristate "VCNL4035 combined ALS and proximity sensor" |
| 547 | + select IIO_BUFFER | |
| 547 | 548 | select IIO_TRIGGERED_BUFFER |
| 548 | 549 | select REGMAP_I2C |
| 549 | 550 | depends on I2C |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | + * Copyright(c) 2020 Cornelis Networks, Inc. | |
| 2 | 3 | * Copyright(c) 2015-2020 Intel Corporation. |
| 3 | 4 | * |
| 4 | 5 | * This file is provided under a dual BSD/GPLv2 license. When using or |
| @@ -206,8 +207,6 @@ static int hfi1_file_open(struct inode *inode, struct file *fp) · 201 unmodified lines | ||
| 206 | 207 | spin_lock_init(&fd->tid_lock); |
| 207 | 208 | spin_lock_init(&fd->invalid_lock); |
| 208 | 209 | fd->rec_cpu_num = -1; /* no cpu affinity by default */ |
| 209 | − fd->mm = current->mm; | |
| 210 | − mmgrab(fd->mm); | |
| 211 | 210 | fd->dd = dd; |
| 212 | 211 | fp->private_data = fd; |
| 213 | 212 | return 0; |
| @@ -711,7 +710,6 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) · 497 unmodified lines | ||
| 711 | 710 | |
| 712 | 711 | deallocate_ctxt(uctxt); |
| 713 | 712 | done: |
| 714 | − mmdrop(fdata->mm); | |
| 715 | 713 | |
| 716 | 714 | if (atomic_dec_and_test(&dd->user_refcount)) |
| 717 | 715 | complete(&dd->user_comp); |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | #ifndef _HFI1_KERNEL_H |
| 2 | 2 | #define _HFI1_KERNEL_H |
| 3 | 3 | /* |
| 4 | + * Copyright(c) 2020 Cornelis Networks, Inc. | |
| 4 | 5 | * Copyright(c) 2015-2020 Intel Corporation. |
| 5 | 6 | * |
| 6 | 7 | * This file is provided under a dual BSD/GPLv2 license. When using or |
| @@ -1451,7 +1452,6 @@ struct hfi1_filedata { · 1444 unmodified lines | ||
| 1451 | 1452 | u32 invalid_tid_idx; |
| 1452 | 1453 | /* protect invalid_tids array and invalid_tid_idx */ |
| 1453 | 1454 | spinlock_t invalid_lock; |
| 1454 | − struct mm_struct *mm; | |
| 1455 | 1455 | }; |
| 1456 | 1456 | |
| 1457 | 1457 | extern struct xarray hfi1_dev_table; |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | + * Copyright(c) 2020 Cornelis Networks, Inc. | |
| 2 | 3 | * Copyright(c) 2016 - 2017 Intel Corporation. |
| 3 | 4 | * |
| 4 | 5 | * This file is provided under a dual BSD/GPLv2 license. When using or |
| @@ -48,23 +49,11 @@ · 43 unmodified lines | ||
| 48 | 49 | #include <linux/rculist.h> |
| 49 | 50 | #include <linux/mmu_notifier.h> |
| 50 | 51 | #include <linux/interval_tree_generic.h> |
| 52 | +#include <linux/sched/mm.h> | |
| 51 | 53 | |
| 52 | 54 | #include "mmu_rb.h" |
| 53 | 55 | #include "trace.h" |
| 54 | 56 | |
| 55 | −struct mmu_rb_handler { | |
| 56 | − struct mmu_notifier mn; | |
| 57 | − struct rb_root_cached root; | |
| 58 | − void *ops_arg; | |
| 59 | − spinlock_t lock; /* protect the RB tree */ | |
| 60 | − struct mmu_rb_ops *ops; | |
| 61 | − struct mm_struct *mm; | |
| 62 | − struct list_head lru_list; | |
| 63 | − struct work_struct del_work; | |
| 64 | − struct list_head del_list; | |
| 65 | − struct workqueue_struct *wq; | |
| 66 | −}; | |
| 67 | − | |
| 68 | 57 | static unsigned long mmu_node_start(struct mmu_rb_node *); |
| 69 | 58 | static unsigned long mmu_node_last(struct mmu_rb_node *); |
| 70 | 59 | static int mmu_notifier_range_start(struct mmu_notifier *, |
| @@ -92,37 +81,36 @@ static unsigned long mmu_node_last(struct mmu_rb_node *node) · 21 unmodified lines | ||
| 92 | 81 | return PAGE_ALIGN(node->addr + node->len) - 1; |
| 93 | 82 | } |
| 94 | 83 | |
| 95 | −int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm, | |
| 84 | +int hfi1_mmu_rb_register(void *ops_arg, | |
| 96 | 85 | struct mmu_rb_ops *ops, |
| 97 | 86 | struct workqueue_struct *wq, |
| 98 | 87 | struct mmu_rb_handler **handler) |
| 99 | 88 | { |
| 100 | − struct mmu_rb_handler *handlr; | |
| 89 | + struct mmu_rb_handler *h; | |
| 101 | 90 | int ret; |
| 102 | 91 | |
| 103 | − handlr = kmalloc(sizeof(*handlr), GFP_KERNEL); | |
| 104 | − if (!handlr) | |
| 92 | + h = kmalloc(sizeof(*h), GFP_KERNEL); | |
| 93 | + if (!h) | |
| 105 | 94 | return -ENOMEM; |
| 106 | 95 | |
| 107 | − handlr->root = RB_ROOT_CACHED; | |
| 108 | − handlr->ops = ops; | |
| 109 | − handlr->ops_arg = ops_arg; | |
| 110 | − INIT_HLIST_NODE(&handlr->mn.hlist); | |
| 111 | − spin_lock_init(&handlr->lock); | |
| 112 | − handlr->mn.ops = &mn_opts; | |
| 113 | − handlr->mm = mm; | |
| 114 | − INIT_WORK(&handlr->del_work, handle_remove); | |
| 115 | − INIT_LIST_HEAD(&handlr->del_list); | |
| 116 | − INIT_LIST_HEAD(&handlr->lru_list); | |
| 117 | − handlr->wq = wq; | |
| 118 | − | |
| 119 | − ret = mmu_notifier_register(&handlr->mn, handlr->mm); | |
| 96 | + h->root = RB_ROOT_CACHED; | |
| 97 | + h->ops = ops; | |
| 98 | + h->ops_arg = ops_arg; | |
| 99 | + INIT_HLIST_NODE(&h->mn.hlist); | |
| 100 | + spin_lock_init(&h->lock); | |
| 101 | + h->mn.ops = &mn_opts; | |
| 102 | + INIT_WORK(&h->del_work, handle_remove); | |
| 103 | + INIT_LIST_HEAD(&h->del_list); | |
| 104 | + INIT_LIST_HEAD(&h->lru_list); | |
| 105 | + h->wq = wq; | |
| 106 | + | |
| 107 | + ret = mmu_notifier_register(&h->mn, current->mm); | |
| 120 | 108 | if (ret) { |
| 121 | − kfree(handlr); | |
| 109 | + kfree(h); | |
| 122 | 110 | return ret; |
| 123 | 111 | } |
| 124 | 112 | |
| 125 | − *handler = handlr; | |
| 113 | + *handler = h; | |
| 126 | 114 | return 0; |
| 127 | 115 | } |
| 128 | 116 | |
| @@ -134,7 +122,7 @@ void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler) · 5 unmodified lines | ||
| 134 | 122 | struct list_head del_list; |
| 135 | 123 | |
| 136 | 124 | /* Unregister first so we don't get any more notifications. */ |
| 137 | − mmu_notifier_unregister(&handler->mn, handler->mm); | |
| 125 | + mmu_notifier_unregister(&handler->mn, handler->mn.mm); | |
| 138 | 126 | |
| 139 | 127 | /* |
| 140 | 128 | * Make sure the wq delete handler is finished running. It will not |
| @@ -166,6 +154,10 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler, · 25 unmodified lines | ||
| 166 | 154 | int ret = 0; |
| 167 | 155 | |
| 168 | 156 | trace_hfi1_mmu_rb_insert(mnode->addr, mnode->len); |
| 157 | + | |
| 158 | + if (current->mm != handler->mn.mm) | |
| 159 | + return -EPERM; | |
| 160 | + | |
| 169 | 161 | spin_lock_irqsave(&handler->lock, flags); |
| 170 | 162 | node = __mmu_rb_search(handler, mnode->addr, mnode->len); |
| 171 | 163 | if (node) { |
| @@ -180,6 +172,7 @@ int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler, · 8 unmodified lines | ||
| 180 | 172 | __mmu_int_rb_remove(mnode, &handler->root); |
| 181 | 173 | list_del(&mnode->list); /* remove from LRU list */ |
| 182 | 174 | } |
| 175 | + mnode->handler = handler; | |
| 183 | 176 | unlock: |
| 184 | 177 | spin_unlock_irqrestore(&handler->lock, flags); |
| 185 | 178 | return ret; |
| @@ -217,6 +210,9 @@ bool hfi1_mmu_rb_remove_unless_exact(struct mmu_rb_handler *handler, · 31 unmodified lines | ||
| 217 | 210 | unsigned long flags; |
| 218 | 211 | bool ret = false; |
| 219 | 212 | |
| 213 | + if (current->mm != handler->mn.mm) | |
| 214 | + return ret; | |
| 215 | + | |
| 220 | 216 | spin_lock_irqsave(&handler->lock, flags); |
| 221 | 217 | node = __mmu_rb_search(handler, addr, len); |
| 222 | 218 | if (node) { |
| @@ -239,6 +235,9 @@ void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg) · 16 unmodified lines | ||
| 239 | 235 | unsigned long flags; |
| 240 | 236 | bool stop = false; |
| 241 | 237 | |
| 238 | + if (current->mm != handler->mn.mm) | |
| 239 | + return; | |
| 240 | + | |
| 242 | 241 | INIT_LIST_HEAD(&del_list); |
| 243 | 242 | |
| 244 | 243 | spin_lock_irqsave(&handler->lock, flags); |
| @@ -272,6 +271,9 @@ void hfi1_mmu_rb_remove(struct mmu_rb_handler *handler, · 27 unmodified lines | ||
| 272 | 271 | { |
| 273 | 272 | unsigned long flags; |
| 274 | 273 | |
| 274 | + if (current->mm != handler->mn.mm) | |
| 275 | + return; | |
| 276 | + | |
| 275 | 277 | /* Validity of handler and node pointers has been checked by caller. */ |
| 276 | 278 | trace_hfi1_mmu_rb_remove(node->addr, node->len); |
| 277 | 279 | spin_lock_irqsave(&handler->lock, flags); |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | + * Copyright(c) 2020 Cornelis Networks, Inc. | |
| 2 | 3 | * Copyright(c) 2016 Intel Corporation. |
| 3 | 4 | * |
| 4 | 5 | * This file is provided under a dual BSD/GPLv2 license. When using or |
| @@ -54,6 +55,7 @@ struct mmu_rb_node { · 49 unmodified lines | ||
| 54 | 55 | unsigned long len; |
| 55 | 56 | unsigned long __last; |
| 56 | 57 | struct rb_node node; |
| 58 | + struct mmu_rb_handler *handler; | |
| 57 | 59 | struct list_head list; |
| 58 | 60 | }; |
| 59 | 61 | |
| @@ -71,7 +73,19 @@ struct mmu_rb_ops { · 11 unmodified lines | ||
| 71 | 73 | void *evict_arg, bool *stop); |
| 72 | 74 | }; |
| 73 | 75 | |
| 74 | −int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm, | |
| 76 | +struct mmu_rb_handler { | |
| 77 | + struct mmu_notifier mn; | |
| 78 | + struct rb_root_cached root; | |
| 79 | + void *ops_arg; | |
| 80 | + spinlock_t lock; /* protect the RB tree */ | |
| 81 | + struct mmu_rb_ops *ops; | |
| 82 | + struct list_head lru_list; | |
| 83 | + struct work_struct del_work; | |
| 84 | + struct list_head del_list; | |
| 85 | + struct workqueue_struct *wq; | |
| 86 | +}; | |
| 87 | + | |
| 88 | +int hfi1_mmu_rb_register(void *ops_arg, | |
| 75 | 89 | struct mmu_rb_ops *ops, |
| 76 | 90 | struct workqueue_struct *wq, |
| 77 | 91 | struct mmu_rb_handler **handler); |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | + * Copyright(c) 2020 Cornelis Networks, Inc. | |
| 2 | 3 | * Copyright(c) 2015-2018 Intel Corporation. |
| 3 | 4 | * |
| 4 | 5 | * This file is provided under a dual BSD/GPLv2 license. When using or |
| @@ -173,15 +174,18 @@ static void unpin_rcv_pages(struct hfi1_filedata *fd, · 168 unmodified lines | ||
| 173 | 174 | { |
| 174 | 175 | struct page **pages; |
| 175 | 176 | struct hfi1_devdata *dd = fd->uctxt->dd; |
| 177 | + struct mm_struct *mm; | |
| 176 | 178 | |
| 177 | 179 | if (mapped) { |
| 178 | 180 | pci_unmap_single(dd->pcidev, node->dma_addr, |
| 179 | 181 | node->npages * PAGE_SIZE, PCI_DMA_FROMDEVICE); |
| 180 | 182 | pages = &node->pages[idx]; |
| 183 | + mm = mm_from_tid_node(node); | |
| 181 | 184 | } else { |
| 182 | 185 | pages = &tidbuf->pages[idx]; |
| 186 | + mm = current->mm; | |
| 183 | 187 | } |
| 184 | − hfi1_release_user_pages(fd->mm, pages, npages, mapped); | |
| 188 | + hfi1_release_user_pages(mm, pages, npages, mapped); | |
| 185 | 189 | fd->tid_n_pinned -= npages; |
| 186 | 190 | } |
| 187 | 191 | |
| @@ -216,12 +220,12 @@ static int pin_rcv_pages(struct hfi1_filedata *fd, struct tid_user_buf *tidbuf) · 28 unmodified lines | ||
| 216 | 220 | * pages, accept the amount pinned so far and program only that. |
| 217 | 221 | * User space knows how to deal with partially programmed buffers. |
| 218 | 222 | */ |
| 219 | − if (!hfi1_can_pin_pages(dd, fd->mm, fd->tid_n_pinned, npages)) { | |
| 223 | + if (!hfi1_can_pin_pages(dd, current->mm, fd->tid_n_pinned, npages)) { | |
| 220 | 224 | kfree(pages); |
| 221 | 225 | return -ENOMEM; |
| 222 | 226 | } |
| 223 | 227 | |
| 224 | − pinned = hfi1_acquire_user_pages(fd->mm, vaddr, npages, true, pages); | |
| 228 | + pinned = hfi1_acquire_user_pages(current->mm, vaddr, npages, true, pages); | |
| 225 | 229 | if (pinned <= 0) { |
| 226 | 230 | kfree(pages); |
| 227 | 231 | return pinned; |
| @@ -756,7 +760,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd, · 528 unmodified lines | ||
| 756 | 760 | |
| 757 | 761 | if (fd->use_mn) { |
| 758 | 762 | ret = mmu_interval_notifier_insert( |
| 759 | − &node->notifier, fd->mm, | |
| 763 | + &node->notifier, current->mm, | |
| 760 | 764 | tbuf->vaddr + (pageidx * PAGE_SIZE), npages * PAGE_SIZE, |
| 761 | 765 | &tid_mn_ops); |
| 762 | 766 | if (ret) |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | #ifndef _HFI1_USER_EXP_RCV_H |
| 2 | 2 | #define _HFI1_USER_EXP_RCV_H |
| 3 | 3 | /* |
| 4 | + * Copyright(c) 2020 - Cornelis Networks, Inc. | |
| 4 | 5 | * Copyright(c) 2015 - 2017 Intel Corporation. |
| 5 | 6 | * |
| 6 | 7 | * This file is provided under a dual BSD/GPLv2 license. When using or |
| @@ -95,4 +96,9 @@ int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd, · 88 unmodified lines | ||
| 95 | 96 | int hfi1_user_exp_rcv_invalid(struct hfi1_filedata *fd, |
| 96 | 97 | struct hfi1_tid_info *tinfo); |
| 97 | 98 | |
| 99 | +static inline struct mm_struct *mm_from_tid_node(struct tid_rb_node *node) | |
| 100 | +{ | |
| 101 | + return node->notifier.mm; | |
| 102 | +} | |
| 103 | + | |
| 98 | 104 | #endif /* _HFI1_USER_EXP_RCV_H */ |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | + * Copyright(c) 2020 - Cornelis Networks, Inc. | |
| 2 | 3 | * Copyright(c) 2015 - 2018 Intel Corporation. |
| 3 | 4 | * |
| 4 | 5 | * This file is provided under a dual BSD/GPLv2 license. When using or |
| @@ -188,7 +189,6 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, · 183 unmodified lines | ||
| 188 | 189 | atomic_set(&pq->n_reqs, 0); |
| 189 | 190 | init_waitqueue_head(&pq->wait); |
| 190 | 191 | atomic_set(&pq->n_locked, 0); |
| 191 | − pq->mm = fd->mm; | |
| 192 | 192 | |
| 193 | 193 | iowait_init(&pq->busy, 0, NULL, NULL, defer_packet_queue, |
| 194 | 194 | activate_packet_queue, NULL, NULL); |
| @@ -230,7 +230,7 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, · 35 unmodified lines | ||
| 230 | 230 | |
| 231 | 231 | cq->nentries = hfi1_sdma_comp_ring_size; |
| 232 | 232 | |
| 233 | − ret = hfi1_mmu_rb_register(pq, pq->mm, &sdma_rb_ops, dd->pport->hfi1_wq, | |
| 233 | + ret = hfi1_mmu_rb_register(pq, &sdma_rb_ops, dd->pport->hfi1_wq, | |
| 234 | 234 | &pq->handler); |
| 235 | 235 | if (ret) { |
| 236 | 236 | dd_dev_err(dd, "Failed to register with MMU %d", ret); |
| @@ -980,13 +980,13 @@ static int pin_sdma_pages(struct user_sdma_request *req, · 743 unmodified lines | ||
| 980 | 980 | |
| 981 | 981 | npages -= node->npages; |
| 982 | 982 | retry: |
| 983 | − if (!hfi1_can_pin_pages(pq->dd, pq->mm, | |
| 983 | + if (!hfi1_can_pin_pages(pq->dd, current->mm, | |
| 984 | 984 | atomic_read(&pq->n_locked), npages)) { |
| 985 | 985 | cleared = sdma_cache_evict(pq, npages); |
| 986 | 986 | if (cleared >= npages) |
| 987 | 987 | goto retry; |
| 988 | 988 | } |
| 989 | − pinned = hfi1_acquire_user_pages(pq->mm, | |
| 989 | + pinned = hfi1_acquire_user_pages(current->mm, | |
| 990 | 990 | ((unsigned long)iovec->iov.iov_base + |
| 991 | 991 | (node->npages * PAGE_SIZE)), npages, 0, |
| 992 | 992 | pages + node->npages); |
| @@ -995,7 +995,7 @@ retry: · 2 unmodified lines | ||
| 995 | 995 | return pinned; |
| 996 | 996 | } |
| 997 | 997 | if (pinned != npages) { |
| 998 | − unpin_vector_pages(pq->mm, pages, node->npages, pinned); | |
| 998 | + unpin_vector_pages(current->mm, pages, node->npages, pinned); | |
| 999 | 999 | return -EFAULT; |
| 1000 | 1000 | } |
| 1001 | 1001 | kfree(node->pages); |
| @@ -1008,7 +1008,8 @@ retry: · 6 unmodified lines | ||
| 1008 | 1008 | static void unpin_sdma_pages(struct sdma_mmu_node *node) |
| 1009 | 1009 | { |
| 1010 | 1010 | if (node->npages) { |
| 1011 | − unpin_vector_pages(node->pq->mm, node->pages, 0, node->npages); | |
| 1011 | + unpin_vector_pages(mm_from_sdma_node(node), node->pages, 0, | |
| 1012 | + node->npages); | |
| 1012 | 1013 | atomic_sub(node->npages, &node->pq->n_locked); |
| 1013 | 1014 | } |
| 1014 | 1015 | } |
| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | #ifndef _HFI1_USER_SDMA_H |
| 2 | 2 | #define _HFI1_USER_SDMA_H |
| 3 | 3 | /* |
| 4 | + * Copyright(c) 2020 - Cornelis Networks, Inc. | |
| 4 | 5 | * Copyright(c) 2015 - 2018 Intel Corporation. |
| 5 | 6 | * |
| 6 | 7 | * This file is provided under a dual BSD/GPLv2 license. When using or |
| @@ -133,7 +134,6 @@ struct hfi1_user_sdma_pkt_q { · 126 unmodified lines | ||
| 133 | 134 | unsigned long unpinned; |
| 134 | 135 | struct mmu_rb_handler *handler; |
| 135 | 136 | atomic_t n_locked; |
| 136 | − struct mm_struct *mm; | |
| 137 | 137 | }; |
| 138 | 138 | |
| 139 | 139 | struct hfi1_user_sdma_comp_q { |
| @@ -250,4 +250,9 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd, · 110 unmodified lines | ||
| 250 | 250 | struct iovec *iovec, unsigned long dim, |
| 251 | 251 | unsigned long *count); |
| 252 | 252 | |
| 253 | +static inline struct mm_struct *mm_from_sdma_node(struct sdma_mmu_node *node) | |
| 254 | +{ | |
| 255 | + return node->rb.handler->mn.mm; | |
| 256 | +} | |
| 257 | + | |
| 253 | 258 | #endif /* _HFI1_USER_SDMA_H */ |
| @@ -2936,6 +2936,7 @@ static int hns_roce_v2_mw_write_mtpt(void *mb_buf, struct hns_roce_mw *mw) · 2935 unmodified lines | ||
| 2936 | 2936 | |
| 2937 | 2937 | roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_R_INV_EN_S, 1); |
| 2938 | 2938 | roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_L_INV_EN_S, 1); |
| 2939 | + roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S, 1); | |
| 2939 | 2940 | |
| 2940 | 2941 | roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_PA_S, 0); |
| 2941 | 2942 | roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_MR_MW_S, 1); |
| @@ -4989,11 +4990,11 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, · 2047 unmodified lines | ||
| 4989 | 4990 | V2_QPC_BYTE_28_AT_M, |
| 4990 | 4991 | V2_QPC_BYTE_28_AT_S); |
| 4991 | 4992 | qp_attr->retry_cnt = roce_get_field(context.byte_212_lsn, |
| 4992 | − V2_QPC_BYTE_212_RETRY_CNT_M, | |
| 4993 | − V2_QPC_BYTE_212_RETRY_CNT_S); | |
| 4993 | + V2_QPC_BYTE_212_RETRY_NUM_INIT_M, | |
| 4994 | + V2_QPC_BYTE_212_RETRY_NUM_INIT_S); | |
| 4994 | 4995 | qp_attr->rnr_retry = roce_get_field(context.byte_244_rnr_rxack, |
| 4995 | − V2_QPC_BYTE_244_RNR_CNT_M, | |
| 4996 | − V2_QPC_BYTE_244_RNR_CNT_S); | |
| 4996 | + V2_QPC_BYTE_244_RNR_NUM_INIT_M, | |
| 4997 | + V2_QPC_BYTE_244_RNR_NUM_INIT_S); | |
| 4997 | 4998 | |
| 4998 | 4999 | done: |
| 4999 | 5000 | qp_attr->cur_qp_state = qp_attr->qp_state; |
| @@ -1661,7 +1661,7 @@ struct hns_roce_query_pf_caps_d { · 1660 unmodified lines | ||
| 1661 | 1661 | __le32 rsv_uars_rsv_qps; |
| 1662 | 1662 | }; |
| 1663 | 1663 | #define V2_QUERY_PF_CAPS_D_NUM_SRQS_S 0 |
| 1664 | −#define V2_QUERY_PF_CAPS_D_NUM_SRQS_M GENMASK(20, 0) | |
| 1664 | +#define V2_QUERY_PF_CAPS_D_NUM_SRQS_M GENMASK(19, 0) | |
| 1665 | 1665 | |
| 1666 | 1666 | #define V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_S 20 |
| 1667 | 1667 | #define V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_M GENMASK(21, 20) |
| @@ -54,10 +54,6 @@ · 53 unmodified lines | ||
| 54 | 54 | #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ |
| 55 | 55 | __stringify(DRV_VERSION_MINOR) "." __stringify(DRV_VERSION_BUILD) |
| 56 | 56 | |
| 57 | −static int push_mode; | |
| 58 | −module_param(push_mode, int, 0644); | |
| 59 | −MODULE_PARM_DESC(push_mode, "Low latency mode: 0=disabled (default), 1=enabled)"); | |
| 60 | − | |
| 61 | 57 | static int debug; |
| 62 | 58 | module_param(debug, int, 0644); |
| 63 | 59 | MODULE_PARM_DESC(debug, "debug flags: 0=disabled (default), 0x7fffffff=all"); |
| @@ -1580,7 +1576,6 @@ static enum i40iw_status_code i40iw_setup_init_state(struct i40iw_handler *hdl, · 1516 unmodified lines | ||
| 1580 | 1576 | if (status) |
| 1581 | 1577 | goto exit; |
| 1582 | 1578 | iwdev->obj_next = iwdev->obj_mem; |
| 1583 | − iwdev->push_mode = push_mode; | |
| 1584 | 1579 | |
| 1585 | 1580 | init_waitqueue_head(&iwdev->vchnl_waitq); |
| 1586 | 1581 | init_waitqueue_head(&dev->vf_reqs); |
| @@ -167,39 +167,16 @@ static void i40iw_dealloc_ucontext(struct ib_ucontext *context) · 166 unmodified lines | ||
| 167 | 167 | */ |
| 168 | 168 | static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) |
| 169 | 169 | { |
| 170 | − struct i40iw_ucontext *ucontext; | |
| 171 | − u64 db_addr_offset, push_offset, pfn; | |
| 172 | − | |
| 173 | − ucontext = to_ucontext(context); | |
| 174 | − if (ucontext->iwdev->sc_dev.is_pf) { | |
| 175 | − db_addr_offset = I40IW_DB_ADDR_OFFSET; | |
| 176 | − push_offset = I40IW_PUSH_OFFSET; | |
| 177 | − if (vma->vm_pgoff) | |
| 178 | − vma->vm_pgoff += I40IW_PF_FIRST_PUSH_PAGE_INDEX - 1; | |
| 179 | − } else { | |
| 180 | − db_addr_offset = I40IW_VF_DB_ADDR_OFFSET; | |
| 181 | − push_offset = I40IW_VF_PUSH_OFFSET; | |
| 182 | − if (vma->vm_pgoff) | |
| 183 | − vma->vm_pgoff += I40IW_VF_FIRST_PUSH_PAGE_INDEX - 1; | |
| 184 | − } | |
| 170 | + struct i40iw_ucontext *ucontext = to_ucontext(context); | |
| 171 | + u64 dbaddr; | |
| 185 | 172 | |
| 186 | − vma->vm_pgoff += db_addr_offset >> PAGE_SHIFT; | |
| 187 | − | |
| 188 | − if (vma->vm_pgoff == (db_addr_offset >> PAGE_SHIFT)) { | |
| 189 | − vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | |
| 190 | − } else { | |
| 191 | − if ((vma->vm_pgoff - (push_offset >> PAGE_SHIFT)) % 2) | |
| 192 | − vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | |
| 193 | − else | |
| 194 | − vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | |
| 195 | − } | |
| 173 | + if (vma->vm_pgoff || vma->vm_end - vma->vm_start != PAGE_SIZE) | |
| 174 | + return -EINVAL; | |
| 196 | 175 | |
| 197 | − pfn = vma->vm_pgoff + | |
| 198 | − (pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >> | |
| 199 | − PAGE_SHIFT); | |
| 176 | + dbaddr = I40IW_DB_ADDR_OFFSET + pci_resource_start(ucontext->iwdev->ldev->pcidev, 0); | |
| 200 | 177 | |
| 201 | − return rdma_user_mmap_io(context, vma, pfn, PAGE_SIZE, | |
| 202 | − vma->vm_page_prot, NULL); | |
| 178 | + return rdma_user_mmap_io(context, vma, dbaddr >> PAGE_SHIFT, PAGE_SIZE, | |
| 179 | + pgprot_noncached(vma->vm_page_prot), NULL); | |
| 203 | 180 | } |
| 204 | 181 | |
| 205 | 182 | /** |
| @@ -803,8 +803,10 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, · 802 unmodified lines | ||
| 803 | 803 | } |
| 804 | 804 | |
| 805 | 805 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
| 806 | − if (IS_ERR(mailbox)) | |
| 806 | + if (IS_ERR(mailbox)) { | |
| 807 | + err = PTR_ERR(mailbox); | |
| 807 | 808 | goto err_out_arm; |
| 809 | + } | |
| 808 | 810 | |
| 809 | 811 | cq_context = mailbox->buf; |
| 810 | 812 | |
| @@ -846,9 +848,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, · 35 unmodified lines | ||
| 846 | 848 | } |
| 847 | 849 | |
| 848 | 850 | spin_lock_irq(&dev->cq_table.lock); |
| 849 | − if (mthca_array_set(&dev->cq_table.cq, | |
| 850 | − cq->cqn & (dev->limits.num_cqs - 1), | |
| 851 | − cq)) { | |
| 851 | + err = mthca_array_set(&dev->cq_table.cq, | |
| 852 | + cq->cqn & (dev->limits.num_cqs - 1), cq); | |
| 853 | + if (err) { | |
| 852 | 854 | spin_unlock_irq(&dev->cq_table.lock); |
| 853 | 855 | goto err_out_free_mr; |
| 854 | 856 | } |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <asm/iommu_table.h> |
| 30 | 30 | #include <asm/io_apic.h> |
| 31 | 31 | #include <asm/irq_remapping.h> |
| 32 | +#include <asm/set_memory.h> | |
| 32 | 33 | |
| 33 | 34 | #include <linux/crash_dump.h> |
| 34 | 35 | |
| @@ -672,11 +673,27 @@ static void __init free_command_buffer(struct amd_iommu *iommu) · 637 unmodified lines | ||
| 672 | 673 | free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE)); |
| 673 | 674 | } |
| 674 | 675 | |
| 676 | +static void *__init iommu_alloc_4k_pages(struct amd_iommu *iommu, | |
| 677 | + gfp_t gfp, size_t size) | |
| 678 | +{ | |
| 679 | + int order = get_order(size); | |
| 680 | + void *buf = (void *)__get_free_pages(gfp, order); | |
| 681 | + | |
| 682 | + if (buf && | |
| 683 | + iommu_feature(iommu, FEATURE_SNP) && | |
| 684 | + set_memory_4k((unsigned long)buf, (1 << order))) { | |
| 685 | + free_pages((unsigned long)buf, order); | |
| 686 | + buf = NULL; | |
| 687 | + } | |
| 688 | + | |
| 689 | + return buf; | |
| 690 | +} | |
| 691 | + | |
| 675 | 692 | /* allocates the memory where the IOMMU will log its events to */ |
| 676 | 693 | static int __init alloc_event_buffer(struct amd_iommu *iommu) |
| 677 | 694 | { |
| 678 | − iommu->evt_buf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | |
| 679 | − get_order(EVT_BUFFER_SIZE)); | |
| 695 | + iommu->evt_buf = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO, | |
| 696 | + EVT_BUFFER_SIZE); | |
| 680 | 697 | |
| 681 | 698 | return iommu->evt_buf ? 0 : -ENOMEM; |
| 682 | 699 | } |
| @@ -715,8 +732,8 @@ static void __init free_event_buffer(struct amd_iommu *iommu) · 32 unmodified lines | ||
| 715 | 732 | /* allocates the memory where the IOMMU will log its events to */ |
| 716 | 733 | static int __init alloc_ppr_log(struct amd_iommu *iommu) |
| 717 | 734 | { |
| 718 | − iommu->ppr_log = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | |
| 719 | − get_order(PPR_LOG_SIZE)); | |
| 735 | + iommu->ppr_log = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO, | |
| 736 | + PPR_LOG_SIZE); | |
| 720 | 737 | |
| 721 | 738 | return iommu->ppr_log ? 0 : -ENOMEM; |
| 722 | 739 | } |
| @@ -838,7 +855,7 @@ static int iommu_init_ga(struct amd_iommu *iommu) · 115 unmodified lines | ||
| 838 | 855 | |
| 839 | 856 | static int __init alloc_cwwb_sem(struct amd_iommu *iommu) |
| 840 | 857 | { |
| 841 | − iommu->cmd_sem = (void *)get_zeroed_page(GFP_KERNEL); | |
| 858 | + iommu->cmd_sem = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO, 1); | |
| 842 | 859 | |
| 843 | 860 | return iommu->cmd_sem ? 0 : -ENOMEM; |
| 844 | 861 | } |
| @@ -69,6 +69,10 @@ struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu) · 68 unmodified lines | ||
| 69 | 69 | { |
| 70 | 70 | struct qcom_smmu *qsmmu; |
| 71 | 71 | |
| 72 | + /* Check to make sure qcom_scm has finished probing */ | |
| 73 | + if (!qcom_scm_is_available()) | |
| 74 | + return ERR_PTR(-EPROBE_DEFER); | |
| 75 | + | |
| 72 | 76 | qsmmu = devm_kzalloc(smmu->dev, sizeof(*qsmmu), GFP_KERNEL); |
| 73 | 77 | if (!qsmmu) |
| 74 | 78 | return ERR_PTR(-ENOMEM); |
| @@ -335,7 +335,9 @@ static void dmar_pci_bus_del_dev(struct dmar_pci_notify_info *info) · 334 unmodified lines | ||
| 335 | 335 | |
| 336 | 336 | static inline void vf_inherit_msi_domain(struct pci_dev *pdev) |
| 337 | 337 | { |
| 338 | − dev_set_msi_domain(&pdev->dev, dev_get_msi_domain(&pdev->physfn->dev)); | |
| 338 | + struct pci_dev *physfn = pci_physfn(pdev); | |
| 339 | + | |
| 340 | + dev_set_msi_domain(&pdev->dev, dev_get_msi_domain(&physfn->dev)); | |
| 339 | 341 | } |
| 340 | 342 | |
| 341 | 343 | static int dmar_pci_bus_notifier(struct notifier_block *nb, |
| @@ -984,7 +986,8 @@ static int map_iommu(struct intel_iommu *iommu, u64 phys_addr) · 642 unmodified lines | ||
| 984 | 986 | warn_invalid_dmar(phys_addr, " returns all ones"); |
| 985 | 987 | goto unmap; |
| 986 | 988 | } |
| 987 | − iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG); | |
| 989 | + if (ecap_vcs(iommu->ecap)) | |
| 990 | + iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG); | |
| 988 | 991 | |
| 989 | 992 | /* the registers might be more than one page */ |
| 990 | 993 | map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), |
| @@ -179,7 +179,7 @@ static int rwbf_quirk; · 178 unmodified lines | ||
| 179 | 179 | * (used when kernel is launched w/ TXT) |
| 180 | 180 | */ |
| 181 | 181 | static int force_on = 0; |
| 182 | −int intel_iommu_tboot_noforce; | |
| 182 | +static int intel_iommu_tboot_noforce; | |
| 183 | 183 | static int no_platform_optin; |
| 184 | 184 | |
| 185 | 185 | #define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry)) |
| @@ -1833,7 +1833,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu) · 1647 unmodified lines | ||
| 1833 | 1833 | if (ecap_prs(iommu->ecap)) |
| 1834 | 1834 | intel_svm_finish_prq(iommu); |
| 1835 | 1835 | } |
| 1836 | − if (ecap_vcs(iommu->ecap) && vccap_pasid(iommu->vccap)) | |
| 1836 | + if (vccap_pasid(iommu->vccap)) | |
| 1837 | 1837 | ioasid_unregister_allocator(&iommu->pasid_allocator); |
| 1838 | 1838 | |
| 1839 | 1839 | #endif |
| @@ -3212,7 +3212,7 @@ static void register_pasid_allocator(struct intel_iommu *iommu) · 1372 unmodified lines | ||
| 3212 | 3212 | * is active. All vIOMMU allocators will eventually be calling the same |
| 3213 | 3213 | * host allocator. |
| 3214 | 3214 | */ |
| 3215 | − if (!ecap_vcs(iommu->ecap) || !vccap_pasid(iommu->vccap)) | |
| 3215 | + if (!vccap_pasid(iommu->vccap)) | |
| 3216 | 3216 | return; |
| 3217 | 3217 | |
| 3218 | 3218 | pr_info("Register custom PASID allocator\n"); |
| @@ -4884,7 +4884,8 @@ int __init intel_iommu_init(void) · 1665 unmodified lines | ||
| 4884 | 4884 | * Intel IOMMU is required for a TXT/tboot launch or platform |
| 4885 | 4885 | * opt in, so enforce that. |
| 4886 | 4886 | */ |
| 4887 | − force_on = tboot_force_iommu() || platform_optin_force_iommu(); | |
| 4887 | + force_on = (!intel_iommu_tboot_noforce && tboot_force_iommu()) || | |
| 4888 | + platform_optin_force_iommu(); | |
| 4888 | 4889 | |
| 4889 | 4890 | if (iommu_init_mempool()) { |
| 4890 | 4891 | if (force_on) |
| @@ -264,16 +264,18 @@ int iommu_probe_device(struct device *dev) · 263 unmodified lines | ||
| 264 | 264 | */ |
| 265 | 265 | iommu_alloc_default_domain(group, dev); |
| 266 | 266 | |
| 267 | − if (group->default_domain) | |
| 267 | + if (group->default_domain) { | |
| 268 | 268 | ret = __iommu_attach_device(group->default_domain, dev); |
| 269 | + if (ret) { | |
| 270 | + iommu_group_put(group); | |
| 271 | + goto err_release; | |
| 272 | + } | |
| 273 | + } | |
| 269 | 274 | |
| 270 | 275 | iommu_create_device_direct_mappings(group, dev); |
| 271 | 276 | |
| 272 | 277 | iommu_group_put(group); |
| 273 | 278 | |
| 274 | − if (ret) | |
| 275 | − goto err_release; | |
| 276 | − | |
| 277 | 279 | if (ops->probe_finalize) |
| 278 | 280 | ops->probe_finalize(dev); |
| 279 | 281 | |
| @@ -253,17 +253,31 @@ config VIDEO_MEDIATEK_VCODEC · 252 unmodified lines | ||
| 253 | 253 | depends on MTK_IOMMU || COMPILE_TEST |
| 254 | 254 | depends on VIDEO_DEV && VIDEO_V4L2 |
| 255 | 255 | depends on ARCH_MEDIATEK || COMPILE_TEST |
| 256 | + depends on VIDEO_MEDIATEK_VPU || MTK_SCP | |
| 257 | + # The two following lines ensure we have the same state ("m" or "y") as | |
| 258 | + # our dependencies, to avoid missing symbols during link. | |
| 259 | + depends on VIDEO_MEDIATEK_VPU || !VIDEO_MEDIATEK_VPU | |
| 260 | + depends on MTK_SCP || !MTK_SCP | |
| 256 | 261 | select VIDEOBUF2_DMA_CONTIG |
| 257 | 262 | select V4L2_MEM2MEM_DEV |
| 258 | − select VIDEO_MEDIATEK_VPU | |
| 259 | − select MTK_SCP | |
| 263 | + select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU | |
| 264 | + select VIDEO_MEDIATEK_VCODEC_SCP if MTK_SCP | |
| 260 | 265 | help |
| 261 | − Mediatek video codec driver provides HW capability to | |
| 262 | − encode and decode in a range of video formats | |
| 263 | − This driver rely on VPU driver to communicate with VPU. | |
| 266 | + Mediatek video codec driver provides HW capability to | |
| 267 | + encode and decode in a range of video formats on MT8173 | |
| 268 | + and MT8183. | |
| 269 | + | |
| 270 | + Note that support for MT8173 requires VIDEO_MEDIATEK_VPU to | |
| 271 | + also be selected. Support for MT8183 depends on MTK_SCP. | |
| 272 | + | |
| 273 | + To compile this driver as modules, choose M here: the | |
| 274 | + modules will be called mtk-vcodec-dec and mtk-vcodec-enc. | |
| 275 | + | |
| 276 | +config VIDEO_MEDIATEK_VCODEC_VPU | |
| 277 | + bool | |
| 264 | 278 | |
| 265 | − To compile this driver as modules, choose M here: the | |
| 266 | − modules will be called mtk-vcodec-dec and mtk-vcodec-enc. | |
| 279 | +config VIDEO_MEDIATEK_VCODEC_SCP | |
| 280 | + bool | |
| 267 | 281 | |
| 268 | 282 | config VIDEO_MEM2MEM_DEINTERLACE |
| 269 | 283 | tristate "Deinterlace support" |
| @@ -307,6 +307,7 @@ static int mmpcam_platform_remove(struct platform_device *pdev) · 306 unmodified lines | ||
| 307 | 307 | * Suspend/resume support. |
| 308 | 308 | */ |
| 309 | 309 | |
| 310 | +#ifdef CONFIG_PM | |
| 310 | 311 | static int mmpcam_runtime_resume(struct device *dev) |
| 311 | 312 | { |
| 312 | 313 | struct mmp_camera *cam = dev_get_drvdata(dev); |
| @@ -352,6 +353,7 @@ static int __maybe_unused mmpcam_resume(struct device *dev) · 39 unmodified lines | ||
| 352 | 353 | return mccic_resume(&cam->mcam); |
| 353 | 354 | return 0; |
| 354 | 355 | } |
| 356 | +#endif | |
| 355 | 357 | |
| 356 | 358 | static const struct dev_pm_ops mmpcam_pm_ops = { |
| 357 | 359 | SET_RUNTIME_PM_OPS(mmpcam_runtime_suspend, mmpcam_runtime_resume, NULL) |
| @@ -24,4 +24,12 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | mtk-vcodec-common-y := mtk_vcodec_intr.o \ |
| 26 | 26 | mtk_vcodec_util.o \ |
| 27 | − mtk_vcodec_fw.o | |
| 27 | + mtk_vcodec_fw.o \ | |
| 28 | + | |
| 29 | +ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_VPU),) | |
| 30 | +mtk-vcodec-common-y += mtk_vcodec_fw_vpu.o | |
| 31 | +endif | |
| 32 | + | |
| 33 | +ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP),) | |
| 34 | +mtk-vcodec-common-y += mtk_vcodec_fw_scp.o | |
| 35 | +endif | |
| @@ -241,7 +241,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) · 240 unmodified lines | ||
| 241 | 241 | } |
| 242 | 242 | dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); |
| 243 | 243 | |
| 244 | − dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_DEC); | |
| 244 | + dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, DECODER); | |
| 245 | 245 | if (IS_ERR(dev->fw_handler)) |
| 246 | 246 | return PTR_ERR(dev->fw_handler); |
| 247 | 247 | |
| @@ -293,7 +293,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) · 292 unmodified lines | ||
| 293 | 293 | } |
| 294 | 294 | dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); |
| 295 | 295 | |
| 296 | − dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_ENC); | |
| 296 | + dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, ENCODER); | |
| 297 | 297 | if (IS_ERR(dev->fw_handler)) |
| 298 | 298 | return PTR_ERR(dev->fw_handler); |
| 299 | 299 | |
| @@ -1,193 +1,29 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | |
| 3 | 3 | #include "mtk_vcodec_fw.h" |
| 4 | +#include "mtk_vcodec_fw_priv.h" | |
| 4 | 5 | #include "mtk_vcodec_util.h" |
| 5 | 6 | #include "mtk_vcodec_drv.h" |
| 6 | 7 | |
| 7 | −struct mtk_vcodec_fw_ops { | |
| 8 | − int (*load_firmware)(struct mtk_vcodec_fw *fw); | |
| 9 | − unsigned int (*get_vdec_capa)(struct mtk_vcodec_fw *fw); | |
| 10 | − unsigned int (*get_venc_capa)(struct mtk_vcodec_fw *fw); | |
| 11 | − void * (*map_dm_addr)(struct mtk_vcodec_fw *fw, u32 dtcm_dmem_addr); | |
| 12 | − int (*ipi_register)(struct mtk_vcodec_fw *fw, int id, | |
| 13 | − mtk_vcodec_ipi_handler handler, const char *name, void *priv); | |
| 14 | − int (*ipi_send)(struct mtk_vcodec_fw *fw, int id, void *buf, | |
| 15 | − unsigned int len, unsigned int wait); | |
| 16 | −}; | |
| 17 | − | |
| 18 | −struct mtk_vcodec_fw { | |
| 19 | − enum mtk_vcodec_fw_type type; | |
| 20 | − const struct mtk_vcodec_fw_ops *ops; | |
| 21 | − struct platform_device *pdev; | |
| 22 | − struct mtk_scp *scp; | |
| 23 | −}; | |
| 24 | − | |
| 25 | −static int mtk_vcodec_vpu_load_firmware(struct mtk_vcodec_fw *fw) | |
| 26 | −{ | |
| 27 | − return vpu_load_firmware(fw->pdev); | |
| 28 | −} | |
| 29 | − | |
| 30 | −static unsigned int mtk_vcodec_vpu_get_vdec_capa(struct mtk_vcodec_fw *fw) | |
| 31 | −{ | |
| 32 | − return vpu_get_vdec_hw_capa(fw->pdev); | |
| 33 | −} | |
| 34 | − | |
| 35 | −static unsigned int mtk_vcodec_vpu_get_venc_capa(struct mtk_vcodec_fw *fw) | |
| 36 | −{ | |
| 37 | − return vpu_get_venc_hw_capa(fw->pdev); | |
| 38 | −} | |
| 39 | − | |
| 40 | −static void *mtk_vcodec_vpu_map_dm_addr(struct mtk_vcodec_fw *fw, | |
| 41 | − u32 dtcm_dmem_addr) | |
| 42 | −{ | |
| 43 | − return vpu_mapping_dm_addr(fw->pdev, dtcm_dmem_addr); | |
| 44 | −} | |
| 45 | − | |
| 46 | −static int mtk_vcodec_vpu_set_ipi_register(struct mtk_vcodec_fw *fw, int id, | |
| 47 | − mtk_vcodec_ipi_handler handler, | |
| 48 | − const char *name, void *priv) | |
| 49 | −{ | |
| 50 | − /* | |
| 51 | − * The handler we receive takes a void * as its first argument. We | |
| 52 | − * cannot change this because it needs to be passed down to the rproc | |
| 53 | − * subsystem when SCP is used. VPU takes a const argument, which is | |
| 54 | − * more constrained, so the conversion below is safe. | |
| 55 | − */ | |
| 56 | − ipi_handler_t handler_const = (ipi_handler_t)handler; | |
| 57 | − | |
| 58 | − return vpu_ipi_register(fw->pdev, id, handler_const, name, priv); | |
| 59 | −} | |
| 60 | − | |
| 61 | −static int mtk_vcodec_vpu_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf, | |
| 62 | − unsigned int len, unsigned int wait) | |
| 63 | −{ | |
| 64 | − return vpu_ipi_send(fw->pdev, id, buf, len); | |
| 65 | −} | |
| 66 | − | |
| 67 | −static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = { | |
| 68 | − .load_firmware = mtk_vcodec_vpu_load_firmware, | |
| 69 | − .get_vdec_capa = mtk_vcodec_vpu_get_vdec_capa, | |
| 70 | − .get_venc_capa = mtk_vcodec_vpu_get_venc_capa, | |
| 71 | − .map_dm_addr = mtk_vcodec_vpu_map_dm_addr, | |
| 72 | − .ipi_register = mtk_vcodec_vpu_set_ipi_register, | |
| 73 | − .ipi_send = mtk_vcodec_vpu_ipi_send, | |
| 74 | −}; | |
| 75 | − | |
| 76 | −static int mtk_vcodec_scp_load_firmware(struct mtk_vcodec_fw *fw) | |
| 77 | −{ | |
| 78 | − return rproc_boot(scp_get_rproc(fw->scp)); | |
| 79 | −} | |
| 80 | − | |
| 81 | −static unsigned int mtk_vcodec_scp_get_vdec_capa(struct mtk_vcodec_fw *fw) | |
| 82 | −{ | |
| 83 | − return scp_get_vdec_hw_capa(fw->scp); | |
| 84 | −} | |
| 85 | − | |
| 86 | −static unsigned int mtk_vcodec_scp_get_venc_capa(struct mtk_vcodec_fw *fw) | |
| 87 | −{ | |
| 88 | − return scp_get_venc_hw_capa(fw->scp); | |
| 89 | −} | |
| 90 | − | |
| 91 | −static void *mtk_vcodec_vpu_scp_dm_addr(struct mtk_vcodec_fw *fw, | |
| 92 | − u32 dtcm_dmem_addr) | |
| 93 | −{ | |
| 94 | − return scp_mapping_dm_addr(fw->scp, dtcm_dmem_addr); | |
| 95 | −} | |
| 96 | − | |
| 97 | −static int mtk_vcodec_scp_set_ipi_register(struct mtk_vcodec_fw *fw, int id, | |
| 98 | − mtk_vcodec_ipi_handler handler, | |
| 99 | − const char *name, void *priv) | |
| 100 | −{ | |
| 101 | − return scp_ipi_register(fw->scp, id, handler, priv); | |
| 102 | −} | |
| 103 | − | |
| 104 | −static int mtk_vcodec_scp_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf, | |
| 105 | − unsigned int len, unsigned int wait) | |
| 106 | −{ | |
| 107 | − return scp_ipi_send(fw->scp, id, buf, len, wait); | |
| 108 | −} | |
| 109 | − | |
| 110 | −static const struct mtk_vcodec_fw_ops mtk_vcodec_rproc_msg = { | |
| 111 | − .load_firmware = mtk_vcodec_scp_load_firmware, | |
| 112 | − .get_vdec_capa = mtk_vcodec_scp_get_vdec_capa, | |
| 113 | − .get_venc_capa = mtk_vcodec_scp_get_venc_capa, | |
| 114 | − .map_dm_addr = mtk_vcodec_vpu_scp_dm_addr, | |
| 115 | − .ipi_register = mtk_vcodec_scp_set_ipi_register, | |
| 116 | − .ipi_send = mtk_vcodec_scp_ipi_send, | |
| 117 | −}; | |
| 118 | − | |
| 119 | −static void mtk_vcodec_reset_handler(void *priv) | |
| 120 | −{ | |
| 121 | − struct mtk_vcodec_dev *dev = priv; | |
| 122 | − struct mtk_vcodec_ctx *ctx; | |
| 123 | − | |
| 124 | − mtk_v4l2_err("Watchdog timeout!!"); | |
| 125 | − | |
| 126 | − mutex_lock(&dev->dev_mutex); | |
| 127 | − list_for_each_entry(ctx, &dev->ctx_list, list) { | |
| 128 | − ctx->state = MTK_STATE_ABORT; | |
| 129 | − mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT", | |
| 130 | − ctx->id); | |
| 131 | − } | |
| 132 | − mutex_unlock(&dev->dev_mutex); | |
| 133 | −} | |
| 134 | − | |
| 135 | 8 | struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev, |
| 136 | 9 | enum mtk_vcodec_fw_type type, |
| 137 | − enum rst_id rst_id) | |
| 10 | + enum mtk_vcodec_fw_use fw_use) | |
| 138 | 11 | { |
| 139 | − const struct mtk_vcodec_fw_ops *ops; | |
| 140 | − struct mtk_vcodec_fw *fw; | |
| 141 | − struct platform_device *fw_pdev = NULL; | |
| 142 | − struct mtk_scp *scp = NULL; | |
| 143 | − | |
| 144 | 12 | switch (type) { |
| 145 | 13 | case VPU: |
| 146 | − ops = &mtk_vcodec_vpu_msg; | |
| 147 | − fw_pdev = vpu_get_plat_device(dev->plat_dev); | |
| 148 | − if (!fw_pdev) { | |
| 149 | − mtk_v4l2_err("firmware device is not ready"); | |
| 150 | − return ERR_PTR(-EINVAL); | |
| 151 | − } | |
| 152 | − vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_reset_handler, | |
| 153 | − dev, rst_id); | |
| 154 | − break; | |
| 14 | + return mtk_vcodec_fw_vpu_init(dev, fw_use); | |
| 155 | 15 | case SCP: |
| 156 | − ops = &mtk_vcodec_rproc_msg; | |
| 157 | − scp = scp_get(dev->plat_dev); | |
| 158 | − if (!scp) { | |
| 159 | − mtk_v4l2_err("could not get vdec scp handle"); | |
| 160 | − return ERR_PTR(-EPROBE_DEFER); | |
| 161 | − } | |
| 162 | − break; | |
| 16 | + return mtk_vcodec_fw_scp_init(dev); | |
| 163 | 17 | default: |
| 164 | 18 | mtk_v4l2_err("invalid vcodec fw type"); |
| 165 | 19 | return ERR_PTR(-EINVAL); |
| 166 | 20 | } |
| 167 | − | |
| 168 | − fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL); | |
| 169 | − if (!fw) | |
| 170 | − return ERR_PTR(-EINVAL); | |
| 171 | − | |
| 172 | − fw->type = type; | |
| 173 | − fw->ops = ops; | |
| 174 | − fw->pdev = fw_pdev; | |
| 175 | − fw->scp = scp; | |
| 176 | − | |
| 177 | − return fw; | |
| 178 | 21 | } |
| 179 | 22 | EXPORT_SYMBOL_GPL(mtk_vcodec_fw_select); |
| 180 | 23 | |
| 181 | 24 | void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw) |
| 182 | 25 | { |
| 183 | − switch (fw->type) { | |
| 184 | − case VPU: | |
| 185 | − put_device(&fw->pdev->dev); | |
| 186 | − break; | |
| 187 | − case SCP: | |
| 188 | − scp_put(fw->scp); | |
| 189 | − break; | |
| 190 | − } | |
| 26 | + fw->ops->release(fw); | |
| 191 | 27 | } |
| 192 | 28 | EXPORT_SYMBOL_GPL(mtk_vcodec_fw_release); |
| 193 | 29 | |
| @@ -15,6 +15,11 @@ enum mtk_vcodec_fw_type { · 14 unmodified lines | ||
| 15 | 15 | SCP, |
| 16 | 16 | }; |
| 17 | 17 | |
| 18 | +enum mtk_vcodec_fw_use { | |
| 19 | + DECODER, | |
| 20 | + ENCODER, | |
| 21 | +}; | |
| 22 | + | |
| 18 | 23 | struct mtk_vcodec_fw; |
| 19 | 24 | |
| 20 | 25 | typedef void (*mtk_vcodec_ipi_handler) (void *data, |
| @@ -22,7 +27,7 @@ typedef void (*mtk_vcodec_ipi_handler) (void *data, · 1 unmodified line | ||
| 22 | 27 | |
| 23 | 28 | struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev, |
| 24 | 29 | enum mtk_vcodec_fw_type type, |
| 25 | − enum rst_id rst_id); | |
| 30 | + enum mtk_vcodec_fw_use fw_use); | |
| 26 | 31 | void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw); |
| 27 | 32 | |
| 28 | 33 | int mtk_vcodec_fw_load_firmware(struct mtk_vcodec_fw *fw); |
| @@ -0,0 +1,52 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | + | |
| 3 | +#ifndef _MTK_VCODEC_FW_PRIV_H_ | |
| 4 | +#define _MTK_VCODEC_FW_PRIV_H_ | |
| 5 | + | |
| 6 | +#include "mtk_vcodec_fw.h" | |
| 7 | + | |
| 8 | +struct mtk_vcodec_dev; | |
| 9 | + | |
| 10 | +struct mtk_vcodec_fw { | |
| 11 | + enum mtk_vcodec_fw_type type; | |
| 12 | + const struct mtk_vcodec_fw_ops *ops; | |
| 13 | + struct platform_device *pdev; | |
| 14 | + struct mtk_scp *scp; | |
| 15 | +}; | |
| 16 | + | |
| 17 | +struct mtk_vcodec_fw_ops { | |
| 18 | + int (*load_firmware)(struct mtk_vcodec_fw *fw); | |
| 19 | + unsigned int (*get_vdec_capa)(struct mtk_vcodec_fw *fw); | |
| 20 | + unsigned int (*get_venc_capa)(struct mtk_vcodec_fw *fw); | |
| 21 | + void *(*map_dm_addr)(struct mtk_vcodec_fw *fw, u32 dtcm_dmem_addr); | |
| 22 | + int (*ipi_register)(struct mtk_vcodec_fw *fw, int id, | |
| 23 | + mtk_vcodec_ipi_handler handler, const char *name, | |
| 24 | + void *priv); | |
| 25 | + int (*ipi_send)(struct mtk_vcodec_fw *fw, int id, void *buf, | |
| 26 | + unsigned int len, unsigned int wait); | |
| 27 | + void (*release)(struct mtk_vcodec_fw *fw); | |
| 28 | +}; | |
| 29 | + | |
| 30 | +#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCODEC_VPU) | |
| 31 | +struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev, | |
| 32 | + enum mtk_vcodec_fw_use fw_use); | |
| 33 | +#else | |
| 34 | +static inline struct mtk_vcodec_fw * | |
| 35 | +mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev, | |
| 36 | + enum mtk_vcodec_fw_use fw_use) | |
| 37 | +{ | |
| 38 | + return ERR_PTR(-ENODEV); | |
| 39 | +} | |
| 40 | +#endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_VPU */ | |
| 41 | + | |
| 42 | +#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP) | |
| 43 | +struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev); | |
| 44 | +#else | |
| 45 | +static inline struct mtk_vcodec_fw * | |
| 46 | +mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev) | |
| 47 | +{ | |
| 48 | + return ERR_PTR(-ENODEV); | |
| 49 | +} | |
| 50 | +#endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_SCP */ | |
| 51 | + | |
| 52 | +#endif /* _MTK_VCODEC_FW_PRIV_H_ */ | |
| @@ -0,0 +1,73 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +#include "mtk_vcodec_fw_priv.h" | |
| 4 | +#include "mtk_vcodec_util.h" | |
| 5 | +#include "mtk_vcodec_drv.h" | |
| 6 | + | |
| 7 | +static int mtk_vcodec_scp_load_firmware(struct mtk_vcodec_fw *fw) | |
| 8 | +{ | |
| 9 | + return rproc_boot(scp_get_rproc(fw->scp)); | |
| 10 | +} | |
| 11 | + | |
| 12 | +static unsigned int mtk_vcodec_scp_get_vdec_capa(struct mtk_vcodec_fw *fw) | |
| 13 | +{ | |
| 14 | + return scp_get_vdec_hw_capa(fw->scp); | |
| 15 | +} | |
| 16 | + | |
| 17 | +static unsigned int mtk_vcodec_scp_get_venc_capa(struct mtk_vcodec_fw *fw) | |
| 18 | +{ | |
| 19 | + return scp_get_venc_hw_capa(fw->scp); | |
| 20 | +} | |
| 21 | + | |
| 22 | +static void *mtk_vcodec_vpu_scp_dm_addr(struct mtk_vcodec_fw *fw, | |
| 23 | + u32 dtcm_dmem_addr) | |
| 24 | +{ | |
| 25 | + return scp_mapping_dm_addr(fw->scp, dtcm_dmem_addr); | |
| 26 | +} | |
| 27 | + | |
| 28 | +static int mtk_vcodec_scp_set_ipi_register(struct mtk_vcodec_fw *fw, int id, | |
| 29 | + mtk_vcodec_ipi_handler handler, | |
| 30 | + const char *name, void *priv) | |
| 31 | +{ | |
| 32 | + return scp_ipi_register(fw->scp, id, handler, priv); | |
| 33 | +} | |
| 34 | + | |
| 35 | +static int mtk_vcodec_scp_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf, | |
| 36 | + unsigned int len, unsigned int wait) | |
| 37 | +{ | |
| 38 | + return scp_ipi_send(fw->scp, id, buf, len, wait); | |
| 39 | +} | |
| 40 | + | |
| 41 | +static void mtk_vcodec_scp_release(struct mtk_vcodec_fw *fw) | |
| 42 | +{ | |
| 43 | + scp_put(fw->scp); | |
| 44 | +} | |
| 45 | + | |
| 46 | +static const struct mtk_vcodec_fw_ops mtk_vcodec_rproc_msg = { | |
| 47 | + .load_firmware = mtk_vcodec_scp_load_firmware, | |
| 48 | + .get_vdec_capa = mtk_vcodec_scp_get_vdec_capa, | |
| 49 | + .get_venc_capa = mtk_vcodec_scp_get_venc_capa, | |
| 50 | + .map_dm_addr = mtk_vcodec_vpu_scp_dm_addr, | |
| 51 | + .ipi_register = mtk_vcodec_scp_set_ipi_register, | |
| 52 | + .ipi_send = mtk_vcodec_scp_ipi_send, | |
| 53 | + .release = mtk_vcodec_scp_release, | |
| 54 | +}; | |
| 55 | + | |
| 56 | +struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev) | |
| 57 | +{ | |
| 58 | + struct mtk_vcodec_fw *fw; | |
| 59 | + struct mtk_scp *scp; | |
| 60 | + | |
| 61 | + scp = scp_get(dev->plat_dev); | |
| 62 | + if (!scp) { | |
| 63 | + mtk_v4l2_err("could not get vdec scp handle"); | |
| 64 | + return ERR_PTR(-EPROBE_DEFER); | |
| 65 | + } | |
| 66 | + | |
| 67 | + fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL); | |
| 68 | + fw->type = SCP; | |
| 69 | + fw->ops = &mtk_vcodec_rproc_msg; | |
| 70 | + fw->scp = scp; | |
| 71 | + | |
| 72 | + return fw; | |
| 73 | +} | |
| @@ -0,0 +1,110 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +#include "mtk_vcodec_fw_priv.h" | |
| 4 | +#include "mtk_vcodec_util.h" | |
| 5 | +#include "mtk_vcodec_drv.h" | |
| 6 | + | |
| 7 | +static int mtk_vcodec_vpu_load_firmware(struct mtk_vcodec_fw *fw) | |
| 8 | +{ | |
| 9 | + return vpu_load_firmware(fw->pdev); | |
| 10 | +} | |
| 11 | + | |
| 12 | +static unsigned int mtk_vcodec_vpu_get_vdec_capa(struct mtk_vcodec_fw *fw) | |
| 13 | +{ | |
| 14 | + return vpu_get_vdec_hw_capa(fw->pdev); | |
| 15 | +} | |
| 16 | + | |
| 17 | +static unsigned int mtk_vcodec_vpu_get_venc_capa(struct mtk_vcodec_fw *fw) | |
| 18 | +{ | |
| 19 | + return vpu_get_venc_hw_capa(fw->pdev); | |
| 20 | +} | |
| 21 | + | |
| 22 | +static void *mtk_vcodec_vpu_map_dm_addr(struct mtk_vcodec_fw *fw, | |
| 23 | + u32 dtcm_dmem_addr) | |
| 24 | +{ | |
| 25 | + return vpu_mapping_dm_addr(fw->pdev, dtcm_dmem_addr); | |
| 26 | +} | |
| 27 | + | |
| 28 | +static int mtk_vcodec_vpu_set_ipi_register(struct mtk_vcodec_fw *fw, int id, | |
| 29 | + mtk_vcodec_ipi_handler handler, | |
| 30 | + const char *name, void *priv) | |
| 31 | +{ | |
| 32 | + /* | |
| 33 | + * The handler we receive takes a void * as its first argument. We | |
| 34 | + * cannot change this because it needs to be passed down to the rproc | |
| 35 | + * subsystem when SCP is used. VPU takes a const argument, which is | |
| 36 | + * more constrained, so the conversion below is safe. | |
| 37 | + */ | |
| 38 | + ipi_handler_t handler_const = (ipi_handler_t)handler; | |
| 39 | + | |
| 40 | + return vpu_ipi_register(fw->pdev, id, handler_const, name, priv); | |
| 41 | +} | |
| 42 | + | |
| 43 | +static int mtk_vcodec_vpu_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf, | |
| 44 | + unsigned int len, unsigned int wait) | |
| 45 | +{ | |
| 46 | + return vpu_ipi_send(fw->pdev, id, buf, len); | |
| 47 | +} | |
| 48 | + | |
| 49 | +static void mtk_vcodec_vpu_release(struct mtk_vcodec_fw *fw) | |
| 50 | +{ | |
| 51 | + put_device(&fw->pdev->dev); | |
| 52 | +} | |
| 53 | + | |
| 54 | +static void mtk_vcodec_vpu_reset_handler(void *priv) | |
| 55 | +{ | |
| 56 | + struct mtk_vcodec_dev *dev = priv; | |
| 57 | + struct mtk_vcodec_ctx *ctx; | |
| 58 | + | |
| 59 | + mtk_v4l2_err("Watchdog timeout!!"); | |
| 60 | + | |
| 61 | + mutex_lock(&dev->dev_mutex); | |
| 62 | + list_for_each_entry(ctx, &dev->ctx_list, list) { | |
| 63 | + ctx->state = MTK_STATE_ABORT; | |
| 64 | + mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT", | |
| 65 | + ctx->id); | |
| 66 | + } | |
| 67 | + mutex_unlock(&dev->dev_mutex); | |
| 68 | +} | |
| 69 | + | |
| 70 | +static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = { | |
| 71 | + .load_firmware = mtk_vcodec_vpu_load_firmware, | |
| 72 | + .get_vdec_capa = mtk_vcodec_vpu_get_vdec_capa, | |
| 73 | + .get_venc_capa = mtk_vcodec_vpu_get_venc_capa, | |
| 74 | + .map_dm_addr = mtk_vcodec_vpu_map_dm_addr, | |
| 75 | + .ipi_register = mtk_vcodec_vpu_set_ipi_register, | |
| 76 | + .ipi_send = mtk_vcodec_vpu_ipi_send, | |
| 77 | + .release = mtk_vcodec_vpu_release, | |
| 78 | +}; | |
| 79 | + | |
| 80 | +struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev, | |
| 81 | + enum mtk_vcodec_fw_use fw_use) | |
| 82 | +{ | |
| 83 | + struct platform_device *fw_pdev; | |
| 84 | + struct mtk_vcodec_fw *fw; | |
| 85 | + enum rst_id rst_id; | |
| 86 | + | |
| 87 | + switch (fw_use) { | |
| 88 | + case ENCODER: | |
| 89 | + rst_id = VPU_RST_ENC; | |
| 90 | + break; | |
| 91 | + case DECODER: | |
| 92 | + default: | |
| 93 | + rst_id = VPU_RST_DEC; | |
| 94 | + break; | |
| 95 | + } | |
| 96 | + | |
| 97 | + fw_pdev = vpu_get_plat_device(dev->plat_dev); | |
| 98 | + if (!fw_pdev) { | |
| 99 | + mtk_v4l2_err("firmware device is not ready"); | |
| 100 | + return ERR_PTR(-EINVAL); | |
| 101 | + } | |
| 102 | + vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_vpu_reset_handler, dev, rst_id); | |
| 103 | + | |
| 104 | + fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL); | |
| 105 | + fw->type = VPU; | |
| 106 | + fw->ops = &mtk_vcodec_vpu_msg; | |
| 107 | + fw->pdev = fw_pdev; | |
| 108 | + | |
| 109 | + return fw; | |
| 110 | +} | |
| @@ -243,8 +243,19 @@ struct venc_controls { · 242 unmodified lines | ||
| 243 | 243 | |
| 244 | 244 | u32 header_mode; |
| 245 | 245 | |
| 246 | − u32 profile; | |
| 247 | − u32 level; | |
| 246 | + struct { | |
| 247 | + u32 h264; | |
| 248 | + u32 mpeg4; | |
| 249 | + u32 hevc; | |
| 250 | + u32 vp8; | |
| 251 | + u32 vp9; | |
| 252 | + } profile; | |
| 253 | + struct { | |
| 254 | + u32 h264; | |
| 255 | + u32 mpeg4; | |
| 256 | + u32 hevc; | |
| 257 | + u32 vp9; | |
| 258 | + } level; | |
| 248 | 259 | }; |
| 249 | 260 | |
| 250 | 261 | struct venus_buffer { |
| @@ -794,7 +794,7 @@ skip_pmdomains: · 793 unmodified lines | ||
| 794 | 794 | return 0; |
| 795 | 795 | |
| 796 | 796 | opp_dl_add_err: |
| 797 | − dev_pm_domain_detach(core->opp_pmdomain, true); | |
| 797 | + dev_pm_opp_detach_genpd(core->opp_table); | |
| 798 | 798 | opp_attach_err: |
| 799 | 799 | if (core->pd_dl_venus) { |
| 800 | 800 | device_link_del(core->pd_dl_venus); |
| @@ -832,7 +832,7 @@ skip_pmdomains: · 31 unmodified lines | ||
| 832 | 832 | if (core->opp_dl_venus) |
| 833 | 833 | device_link_del(core->opp_dl_venus); |
| 834 | 834 | |
| 835 | − dev_pm_domain_detach(core->opp_pmdomain, true); | |
| 835 | + dev_pm_opp_detach_genpd(core->opp_table); | |
| 836 | 836 | } |
| 837 | 837 | |
| 838 | 838 | static int core_get_v4(struct device *dev) |
| @@ -537,6 +537,7 @@ static int venc_set_properties(struct venus_inst *inst) · 536 unmodified lines | ||
| 537 | 537 | struct hfi_quantization quant; |
| 538 | 538 | struct hfi_quantization_range quant_range; |
| 539 | 539 | u32 ptype, rate_control, bitrate; |
| 540 | + u32 profile, level; | |
| 540 | 541 | int ret; |
| 541 | 542 | |
| 542 | 543 | ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2); |
| @@ -684,7 +685,35 @@ static int venc_set_properties(struct venus_inst *inst) · 141 unmodified lines | ||
| 684 | 685 | if (ret) |
| 685 | 686 | return ret; |
| 686 | 687 | |
| 687 | − ret = venus_helper_set_profile_level(inst, ctr->profile, ctr->level); | |
| 688 | + switch (inst->hfi_codec) { | |
| 689 | + case HFI_VIDEO_CODEC_H264: | |
| 690 | + profile = ctr->profile.h264; | |
| 691 | + level = ctr->level.h264; | |
| 692 | + break; | |
| 693 | + case HFI_VIDEO_CODEC_MPEG4: | |
| 694 | + profile = ctr->profile.mpeg4; | |
| 695 | + level = ctr->level.mpeg4; | |
| 696 | + break; | |
| 697 | + case HFI_VIDEO_CODEC_VP8: | |
| 698 | + profile = ctr->profile.vp8; | |
| 699 | + level = 0; | |
| 700 | + break; | |
| 701 | + case HFI_VIDEO_CODEC_VP9: | |
| 702 | + profile = ctr->profile.vp9; | |
| 703 | + level = ctr->level.vp9; | |
| 704 | + break; | |
| 705 | + case HFI_VIDEO_CODEC_HEVC: | |
| 706 | + profile = ctr->profile.hevc; | |
| 707 | + level = ctr->level.hevc; | |
| 708 | + break; | |
| 709 | + case HFI_VIDEO_CODEC_MPEG2: | |
| 710 | + default: | |
| 711 | + profile = 0; | |
| 712 | + level = 0; | |
| 713 | + break; | |
| 714 | + } | |
| 715 | + | |
| 716 | + ret = venus_helper_set_profile_level(inst, profile, level); | |
| 688 | 717 | if (ret) |
| 689 | 718 | return ret; |
| 690 | 719 | |
| @@ -103,15 +103,25 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) · 102 unmodified lines | ||
| 103 | 103 | ctr->h264_entropy_mode = ctrl->val; |
| 104 | 104 | break; |
| 105 | 105 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
| 106 | + ctr->profile.mpeg4 = ctrl->val; | |
| 107 | + break; | |
| 106 | 108 | case V4L2_CID_MPEG_VIDEO_H264_PROFILE: |
| 109 | + ctr->profile.h264 = ctrl->val; | |
| 110 | + break; | |
| 107 | 111 | case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: |
| 112 | + ctr->profile.hevc = ctrl->val; | |
| 113 | + break; | |
| 108 | 114 | case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: |
| 109 | − ctr->profile = ctrl->val; | |
| 115 | + ctr->profile.vp8 = ctrl->val; | |
| 110 | 116 | break; |
| 111 | 117 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: |
| 118 | + ctr->level.mpeg4 = ctrl->val; | |
| 119 | + break; | |
| 112 | 120 | case V4L2_CID_MPEG_VIDEO_H264_LEVEL: |
| 121 | + ctr->level.h264 = ctrl->val; | |
| 122 | + break; | |
| 113 | 123 | case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: |
| 114 | − ctr->level = ctrl->val; | |
| 124 | + ctr->level.hevc = ctrl->val; | |
| 115 | 125 | break; |
| 116 | 126 | case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: |
| 117 | 127 | ctr->h264_i_qp = ctrl->val; |
| @@ -4,36 +4,43 @@ · 3 unmodified lines | ||
| 4 | 4 | * validate the existing APIs in the media subsystem. It can also aid |
| 5 | 5 | * developers working on userspace applications. |
| 6 | 6 | * |
| 7 | − * When this module is loaded, it will attempt to modprobe 'dvb_vidtv_tuner' and 'dvb_vidtv_demod'. | |
| 7 | + * When this module is loaded, it will attempt to modprobe 'dvb_vidtv_tuner' | |
| 8 | + * and 'dvb_vidtv_demod'. | |
| 8 | 9 | * |
| 9 | 10 | * Copyright (C) 2020 Daniel W. S. Almeida |
| 10 | 11 | */ |
| 11 | 12 | |
| 13 | +#include <linux/dev_printk.h> | |
| 12 | 14 | #include <linux/moduleparam.h> |
| 13 | 15 | #include <linux/mutex.h> |
| 14 | 16 | #include <linux/platform_device.h> |
| 15 | −#include <linux/dev_printk.h> | |
| 16 | 17 | #include <linux/time.h> |
| 17 | 18 | #include <linux/types.h> |
| 18 | 19 | #include <linux/workqueue.h> |
| 19 | 20 | |
| 20 | 21 | #include "vidtv_bridge.h" |
| 22 | +#include "vidtv_common.h" | |
| 21 | 23 | #include "vidtv_demod.h" |
| 22 | −#include "vidtv_tuner.h" | |
| 23 | −#include "vidtv_ts.h" | |
| 24 | 24 | #include "vidtv_mux.h" |
| 25 | −#include "vidtv_common.h" | |
| 25 | +#include "vidtv_ts.h" | |
| 26 | +#include "vidtv_tuner.h" | |
| 26 | 27 | |
| 27 | −//#define MUX_BUF_MAX_SZ | |
| 28 | −//#define MUX_BUF_MIN_SZ | |
| 28 | +#define MUX_BUF_MIN_SZ 90164 | |
| 29 | +#define MUX_BUF_MAX_SZ (MUX_BUF_MIN_SZ * 10) | |
| 29 | 30 | #define TUNER_DEFAULT_ADDR 0x68 |
| 30 | 31 | #define DEMOD_DEFAULT_ADDR 0x60 |
| 32 | +#define VIDTV_DEFAULT_NETWORK_ID 0xff44 | |
| 33 | +#define VIDTV_DEFAULT_NETWORK_NAME "LinuxTV.org" | |
| 34 | +#define VIDTV_DEFAULT_TS_ID 0x4081 | |
| 31 | 35 | |
| 32 | −/* LNBf fake parameters: ranges used by an Universal (extended) European LNBf */ | |
| 33 | −#define LNB_CUT_FREQUENCY 11700000 | |
| 34 | −#define LNB_LOW_FREQ 9750000 | |
| 35 | −#define LNB_HIGH_FREQ 10600000 | |
| 36 | − | |
| 36 | +/* | |
| 37 | + * The LNBf fake parameters here are the ranges used by an | |
| 38 | + * Universal (extended) European LNBf, which is likely the most common LNBf | |
| 39 | + * found on Satellite digital TV system nowadays. | |
| 40 | + */ | |
| 41 | +#define LNB_CUT_FREQUENCY 11700000 /* high IF frequency */ | |
| 42 | +#define LNB_LOW_FREQ 9750000 /* low IF frequency */ | |
| 43 | +#define LNB_HIGH_FREQ 10600000 /* transition frequency */ | |
| 37 | 44 | |
| 38 | 45 | static unsigned int drop_tslock_prob_on_low_snr; |
| 39 | 46 | module_param(drop_tslock_prob_on_low_snr, uint, 0); |
| @@ -92,7 +99,8 @@ MODULE_PARM_DESC(si_period_msec, "How often to send SI packets. Default: 40ms"); · 52 unmodified lines | ||
| 92 | 99 | |
| 93 | 100 | static unsigned int pcr_period_msec = 40; |
| 94 | 101 | module_param(pcr_period_msec, uint, 0); |
| 95 | −MODULE_PARM_DESC(pcr_period_msec, "How often to send PCR packets. Default: 40ms"); | |
| 102 | +MODULE_PARM_DESC(pcr_period_msec, | |
| 103 | + "How often to send PCR packets. Default: 40ms"); | |
| 96 | 104 | |
| 97 | 105 | static unsigned int mux_rate_kbytes_sec = 4096; |
| 98 | 106 | module_param(mux_rate_kbytes_sec, uint, 0); |
| @@ -104,16 +112,14 @@ MODULE_PARM_DESC(pcr_pid, "PCR PID for all channels: defaults to 0x200"); · 5 unmodified lines | ||
| 104 | 112 | |
| 105 | 113 | static unsigned int mux_buf_sz_pkts; |
| 106 | 114 | module_param(mux_buf_sz_pkts, uint, 0); |
| 107 | −MODULE_PARM_DESC(mux_buf_sz_pkts, "Size for the internal mux buffer in multiples of 188 bytes"); | |
| 108 | − | |
| 109 | −#define MUX_BUF_MIN_SZ 90164 | |
| 110 | −#define MUX_BUF_MAX_SZ (MUX_BUF_MIN_SZ * 10) | |
| 115 | +MODULE_PARM_DESC(mux_buf_sz_pkts, | |
| 116 | + "Size for the internal mux buffer in multiples of 188 bytes"); | |
| 111 | 117 | |
| 112 | 118 | static u32 vidtv_bridge_mux_buf_sz_for_mux_rate(void) |
| 113 | 119 | { |
| 114 | 120 | u32 max_elapsed_time_msecs = VIDTV_MAX_SLEEP_USECS / USEC_PER_MSEC; |
| 115 | − u32 nbytes_expected; | |
| 116 | 121 | u32 mux_buf_sz = mux_buf_sz_pkts * TS_PACKET_LEN; |
| 122 | + u32 nbytes_expected; | |
| 117 | 123 | |
| 118 | 124 | nbytes_expected = mux_rate_kbytes_sec; |
| 119 | 125 | nbytes_expected *= max_elapsed_time_msecs; |
| @@ -143,14 +149,12 @@ static bool vidtv_bridge_check_demod_lock(struct vidtv_dvb *dvb, u32 n) · 23 unmodified lines | ||
| 143 | 149 | FE_HAS_LOCK); |
| 144 | 150 | } |
| 145 | 151 | |
| 146 | −static void | |
| 147 | −vidtv_bridge_on_new_pkts_avail(void *priv, u8 *buf, u32 npkts) | |
| 152 | +/* | |
| 153 | + * called on a separate thread by the mux when new packets become available | |
| 154 | + */ | |
| 155 | +static void vidtv_bridge_on_new_pkts_avail(void *priv, u8 *buf, u32 npkts) | |
| 148 | 156 | { |
| 149 | − /* | |
| 150 | − * called on a separate thread by the mux when new packets become | |
| 151 | − * available | |
| 152 | − */ | |
| 153 | − struct vidtv_dvb *dvb = (struct vidtv_dvb *)priv; | |
| 157 | + struct vidtv_dvb *dvb = priv; | |
| 154 | 158 | |
| 155 | 159 | /* drop packets if we lose the lock */ |
| 156 | 160 | if (vidtv_bridge_check_demod_lock(dvb, 0)) |
| @@ -159,7 +163,17 @@ vidtv_bridge_on_new_pkts_avail(void *priv, u8 *buf, u32 npkts) · 2 unmodified lines | ||
| 159 | 163 | |
| 160 | 164 | static int vidtv_start_streaming(struct vidtv_dvb *dvb) |
| 161 | 165 | { |
| 162 | − struct vidtv_mux_init_args mux_args = {0}; | |
| 166 | + struct vidtv_mux_init_args mux_args = { | |
| 167 | + .mux_rate_kbytes_sec = mux_rate_kbytes_sec, | |
| 168 | + .on_new_packets_available_cb = vidtv_bridge_on_new_pkts_avail, | |
| 169 | + .pcr_period_usecs = pcr_period_msec * USEC_PER_MSEC, | |
| 170 | + .si_period_usecs = si_period_msec * USEC_PER_MSEC, | |
| 171 | + .pcr_pid = pcr_pid, | |
| 172 | + .transport_stream_id = VIDTV_DEFAULT_TS_ID, | |
| 173 | + .network_id = VIDTV_DEFAULT_NETWORK_ID, | |
| 174 | + .network_name = VIDTV_DEFAULT_NETWORK_NAME, | |
| 175 | + .priv = dvb, | |
| 176 | + }; | |
| 163 | 177 | struct device *dev = &dvb->pdev->dev; |
| 164 | 178 | u32 mux_buf_sz; |
| 165 | 179 | |
| @@ -168,19 +182,17 @@ static int vidtv_start_streaming(struct vidtv_dvb *dvb) · 2 unmodified lines | ||
| 168 | 182 | return 0; |
| 169 | 183 | } |
| 170 | 184 | |
| 171 | − mux_buf_sz = (mux_buf_sz_pkts) ? mux_buf_sz_pkts : vidtv_bridge_mux_buf_sz_for_mux_rate(); | |
| 185 | + if (mux_buf_sz_pkts) | |
| 186 | + mux_buf_sz = mux_buf_sz_pkts; | |
| 187 | + else | |
| 188 | + mux_buf_sz = vidtv_bridge_mux_buf_sz_for_mux_rate(); | |
| 172 | 189 | |
| 173 | − mux_args.mux_rate_kbytes_sec = mux_rate_kbytes_sec; | |
| 174 | − mux_args.on_new_packets_available_cb = vidtv_bridge_on_new_pkts_avail; | |
| 175 | − mux_args.mux_buf_sz = mux_buf_sz; | |
| 176 | − mux_args.pcr_period_usecs = pcr_period_msec * 1000; | |
| 177 | − mux_args.si_period_usecs = si_period_msec * 1000; | |
| 178 | − mux_args.pcr_pid = pcr_pid; | |
| 179 | − mux_args.transport_stream_id = VIDTV_DEFAULT_TS_ID; | |
| 180 | − mux_args.priv = dvb; | |
| 190 | + mux_args.mux_buf_sz = mux_buf_sz; | |
| 181 | 191 | |
| 182 | 192 | dvb->streaming = true; |
| 183 | − dvb->mux = vidtv_mux_init(dvb->fe[0], dev, mux_args); | |
| 193 | + dvb->mux = vidtv_mux_init(dvb->fe[0], dev, &mux_args); | |
| 194 | + if (!dvb->mux) | |
| 195 | + return -ENOMEM; | |
| 184 | 196 | vidtv_mux_start_thread(dvb->mux); |
| 185 | 197 | |
| 186 | 198 | dev_dbg_ratelimited(dev, "Started streaming\n"); |
| @@ -204,8 +216,8 @@ static int vidtv_start_feed(struct dvb_demux_feed *feed) · 17 unmodified lines | ||
| 204 | 216 | { |
| 205 | 217 | struct dvb_demux *demux = feed->demux; |
| 206 | 218 | struct vidtv_dvb *dvb = demux->priv; |
| 207 | − int rc; | |
| 208 | 219 | int ret; |
| 220 | + int rc; | |
| 209 | 221 | |
| 210 | 222 | if (!demux->dmx.frontend) |
| 211 | 223 | return -EINVAL; |
| @@ -243,9 +255,9 @@ static int vidtv_stop_feed(struct dvb_demux_feed *feed) · 31 unmodified lines | ||
| 243 | 255 | |
| 244 | 256 | static struct dvb_frontend *vidtv_get_frontend_ptr(struct i2c_client *c) |
| 245 | 257 | { |
| 246 | − /* the demod will set this when its probe function runs */ | |
| 247 | 258 | struct vidtv_demod_state *state = i2c_get_clientdata(c); |
| 248 | 259 | |
| 260 | + /* the demod will set this when its probe function runs */ | |
| 249 | 261 | return &state->frontend; |
| 250 | 262 | } |
| 251 | 263 | |
| @@ -253,6 +265,11 @@ static int vidtv_master_xfer(struct i2c_adapter *i2c_adap, · 1 unmodified line | ||
| 253 | 265 | struct i2c_msg msgs[], |
| 254 | 266 | int num) |
| 255 | 267 | { |
| 268 | + /* | |
| 269 | + * Right now, this virtual driver doesn't really send or receive | |
| 270 | + * messages from I2C. A real driver will require an implementation | |
| 271 | + * here. | |
| 272 | + */ | |
| 256 | 273 | return 0; |
| 257 | 274 | } |
| 258 | 275 | |
| @@ -320,11 +337,10 @@ static int vidtv_bridge_dmxdev_init(struct vidtv_dvb *dvb) · 61 unmodified lines | ||
| 320 | 337 | |
| 321 | 338 | static int vidtv_bridge_probe_demod(struct vidtv_dvb *dvb, u32 n) |
| 322 | 339 | { |
| 323 | − struct vidtv_demod_config cfg = {}; | |
| 324 | − | |
| 325 | − cfg.drop_tslock_prob_on_low_snr = drop_tslock_prob_on_low_snr; | |
| 326 | − cfg.recover_tslock_prob_on_good_snr = recover_tslock_prob_on_good_snr; | |
| 327 | − | |
| 340 | + struct vidtv_demod_config cfg = { | |
| 341 | + .drop_tslock_prob_on_low_snr = drop_tslock_prob_on_low_snr, | |
| 342 | + .recover_tslock_prob_on_good_snr = recover_tslock_prob_on_good_snr, | |
| 343 | + }; | |
| 328 | 344 | dvb->i2c_client_demod[n] = dvb_module_probe("dvb_vidtv_demod", |
| 329 | 345 | NULL, |
| 330 | 346 | &dvb->i2c_adapter, |
| @@ -343,14 +359,14 @@ static int vidtv_bridge_probe_demod(struct vidtv_dvb *dvb, u32 n) · 12 unmodified lines | ||
| 343 | 359 | |
| 344 | 360 | static int vidtv_bridge_probe_tuner(struct vidtv_dvb *dvb, u32 n) |
| 345 | 361 | { |
| 346 | − struct vidtv_tuner_config cfg = {}; | |
| 362 | + struct vidtv_tuner_config cfg = { | |
| 363 | + .fe = dvb->fe[n], | |
| 364 | + .mock_power_up_delay_msec = mock_power_up_delay_msec, | |
| 365 | + .mock_tune_delay_msec = mock_tune_delay_msec, | |
| 366 | + }; | |
| 347 | 367 | u32 freq; |
| 348 | 368 | int i; |
| 349 | 369 | |
| 350 | − cfg.fe = dvb->fe[n]; | |
| 351 | − cfg.mock_power_up_delay_msec = mock_power_up_delay_msec; | |
| 352 | − cfg.mock_tune_delay_msec = mock_tune_delay_msec; | |
| 353 | − | |
| 354 | 370 | /* TODO: check if the frequencies are at a valid range */ |
| 355 | 371 | |
| 356 | 372 | memcpy(cfg.vidtv_valid_dvb_t_freqs, |
| @@ -389,9 +405,7 @@ static int vidtv_bridge_probe_tuner(struct vidtv_dvb *dvb, u32 n) · 32 unmodified lines | ||
| 389 | 405 | |
| 390 | 406 | static int vidtv_bridge_dvb_init(struct vidtv_dvb *dvb) |
| 391 | 407 | { |
| 392 | − int ret; | |
| 393 | − int i; | |
| 394 | − int j; | |
| 408 | + int ret, i, j; | |
| 395 | 409 | |
| 396 | 410 | ret = vidtv_bridge_i2c_register_adap(dvb); |
| 397 | 411 | if (ret < 0) |
| @@ -20,9 +20,11 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/i2c.h> |
| 21 | 21 | #include <linux/platform_device.h> |
| 22 | 22 | #include <linux/types.h> |
| 23 | + | |
| 23 | 24 | #include <media/dmxdev.h> |
| 24 | 25 | #include <media/dvb_demux.h> |
| 25 | 26 | #include <media/dvb_frontend.h> |
| 27 | + | |
| 26 | 28 | #include "vidtv_mux.h" |
| 27 | 29 | |
| 28 | 30 | /** |
| @@ -32,7 +34,7 @@ · 3 unmodified lines | ||
| 32 | 34 | * @adapter: Represents a DTV adapter. See 'dvb_register_adapter'. |
| 33 | 35 | * @demux: The demux used by the dvb_dmx_swfilter_packets() call. |
| 34 | 36 | * @dmx_dev: Represents a demux device. |
| 35 | − * @dmx_frontend: The frontends associated with the demux. | |
| 37 | + * @dmx_fe: The frontends associated with the demux. | |
| 36 | 38 | * @i2c_adapter: The i2c_adapter associated with the bridge driver. |
| 37 | 39 | * @i2c_client_demod: The i2c_clients associated with the demodulator modules. |
| 38 | 40 | * @i2c_client_tuner: The i2c_clients associated with the tuner modules. |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | * When vidtv boots, it will create some hardcoded channels. |
| 10 | 10 | * Their services will be concatenated to populate the SDT. |
| 11 | 11 | * Their programs will be concatenated to populate the PAT |
| 12 | + * Their events will be concatenated to populate the EIT | |
| 12 | 13 | * For each program in the PAT, a PMT section will be created |
| 13 | 14 | * The PMT section for a channel will be assigned its streams. |
| 14 | 15 | * Every stream will have its corresponding encoder polled to produce TS packets |
| @@ -18,22 +19,22 @@ · 3 unmodified lines | ||
| 18 | 19 | * Copyright (C) 2020 Daniel W. S. Almeida |
| 19 | 20 | */ |
| 20 | 21 | |
| 21 | −#include <linux/types.h> | |
| 22 | −#include <linux/slab.h> | |
| 23 | 22 | #include <linux/dev_printk.h> |
| 24 | 23 | #include <linux/ratelimit.h> |
| 24 | +#include <linux/slab.h> | |
| 25 | +#include <linux/types.h> | |
| 25 | 26 | |
| 26 | 27 | #include "vidtv_channel.h" |
| 27 | −#include "vidtv_psi.h" | |
| 28 | +#include "vidtv_common.h" | |
| 28 | 29 | #include "vidtv_encoder.h" |
| 29 | 30 | #include "vidtv_mux.h" |
| 30 | −#include "vidtv_common.h" | |
| 31 | +#include "vidtv_psi.h" | |
| 31 | 32 | #include "vidtv_s302m.h" |
| 32 | 33 | |
| 33 | 34 | static void vidtv_channel_encoder_destroy(struct vidtv_encoder *e) |
| 34 | 35 | { |
| 35 | − struct vidtv_encoder *curr = e; | |
| 36 | 36 | struct vidtv_encoder *tmp = NULL; |
| 37 | + struct vidtv_encoder *curr = e; | |
| 37 | 38 | |
| 38 | 39 | while (curr) { |
| 39 | 40 | /* forward the call to the derived type */ |
| @@ -44,55 +45,88 @@ static void vidtv_channel_encoder_destroy(struct vidtv_encoder *e) · 4 unmodified lines | ||
| 44 | 45 | } |
| 45 | 46 | |
| 46 | 47 | #define ENCODING_ISO8859_15 "\x0b" |
| 48 | +#define TS_NIT_PID 0x10 | |
| 47 | 49 | |
| 50 | +/* | |
| 51 | + * init an audio only channel with a s302m encoder | |
| 52 | + */ | |
| 48 | 53 | struct vidtv_channel |
| 49 | 54 | *vidtv_channel_s302m_init(struct vidtv_channel *head, u16 transport_stream_id) |
| 50 | 55 | { |
| 51 | − /* | |
| 52 | − * init an audio only channel with a s302m encoder | |
| 53 | − */ | |
| 54 | − const u16 s302m_service_id = 0x880; | |
| 55 | − const u16 s302m_program_num = 0x880; | |
| 56 | − const u16 s302m_program_pid = 0x101; /* packet id for PMT*/ | |
| 57 | − const u16 s302m_es_pid = 0x111; /* packet id for the ES */ | |
| 58 | 56 | const __be32 s302m_fid = cpu_to_be32(VIDTV_S302M_FORMAT_IDENTIFIER); |
| 59 | − | |
| 60 | − char *name = ENCODING_ISO8859_15 "Beethoven"; | |
| 57 | + char *event_text = ENCODING_ISO8859_15 "Bagatelle No. 25 in A minor for solo piano, also known as F\xfcr Elise, composed by Ludwig van Beethoven"; | |
| 58 | + char *event_name = ENCODING_ISO8859_15 "Ludwig van Beethoven: F\xfcr Elise"; | |
| 59 | + struct vidtv_s302m_encoder_init_args encoder_args = {}; | |
| 60 | + char *iso_language_code = ENCODING_ISO8859_15 "eng"; | |
| 61 | 61 | char *provider = ENCODING_ISO8859_15 "LinuxTV.org"; |
| 62 | + char *name = ENCODING_ISO8859_15 "Beethoven"; | |
| 63 | + const u16 s302m_es_pid = 0x111; /* packet id for the ES */ | |
| 64 | + const u16 s302m_program_pid = 0x101; /* packet id for PMT*/ | |
| 65 | + const u16 s302m_service_id = 0x880; | |
| 66 | + const u16 s302m_program_num = 0x880; | |
| 67 | + const u16 s302m_beethoven_event_id = 1; | |
| 68 | + struct vidtv_channel *s302m; | |
| 62 | 69 | |
| 63 | − struct vidtv_channel *s302m = kzalloc(sizeof(*s302m), GFP_KERNEL); | |
| 64 | − struct vidtv_s302m_encoder_init_args encoder_args = {}; | |
| 70 | + s302m = kzalloc(sizeof(*s302m), GFP_KERNEL); | |
| 71 | + if (!s302m) | |
| 72 | + return NULL; | |
| 65 | 73 | |
| 66 | 74 | s302m->name = kstrdup(name, GFP_KERNEL); |
| 75 | + if (!s302m->name) | |
| 76 | + goto free_s302m; | |
| 67 | 77 | |
| 68 | − s302m->service = vidtv_psi_sdt_service_init(NULL, s302m_service_id); | |
| 78 | + s302m->service = vidtv_psi_sdt_service_init(NULL, s302m_service_id, false, true); | |
| 79 | + if (!s302m->service) | |
| 80 | + goto free_name; | |
| 69 | 81 | |
| 70 | 82 | s302m->service->descriptor = (struct vidtv_psi_desc *) |
| 71 | 83 | vidtv_psi_service_desc_init(NULL, |
| 72 | − DIGITAL_TELEVISION_SERVICE, | |
| 84 | + DIGITAL_RADIO_SOUND_SERVICE, | |
| 73 | 85 | name, |
| 74 | 86 | provider); |
| 87 | + if (!s302m->service->descriptor) | |
| 88 | + goto free_service; | |
| 75 | 89 | |
| 76 | 90 | s302m->transport_stream_id = transport_stream_id; |
| 77 | 91 | |
| 78 | 92 | s302m->program = vidtv_psi_pat_program_init(NULL, |
| 79 | 93 | s302m_service_id, |
| 80 | 94 | s302m_program_pid); |
| 95 | + if (!s302m->program) | |
| 96 | + goto free_service; | |
| 81 | 97 | |
| 82 | 98 | s302m->program_num = s302m_program_num; |
| 83 | 99 | |
| 84 | 100 | s302m->streams = vidtv_psi_pmt_stream_init(NULL, |
| 85 | 101 | STREAM_PRIVATE_DATA, |
| 86 | 102 | s302m_es_pid); |
| 103 | + if (!s302m->streams) | |
| 104 | + goto free_program; | |
| 87 | 105 | |
| 88 | 106 | s302m->streams->descriptor = (struct vidtv_psi_desc *) |
| 89 | 107 | vidtv_psi_registration_desc_init(NULL, |
| 90 | 108 | s302m_fid, |
| 91 | 109 | NULL, |
| 92 | 110 | 0); |
| 111 | + if (!s302m->streams->descriptor) | |
| 112 | + goto free_streams; | |
| 113 | + | |
| 93 | 114 | encoder_args.es_pid = s302m_es_pid; |
| 94 | 115 | |
| 95 | 116 | s302m->encoders = vidtv_s302m_encoder_init(encoder_args); |
| 117 | + if (!s302m->encoders) | |
| 118 | + goto free_streams; | |
| 119 | + | |
| 120 | + s302m->events = vidtv_psi_eit_event_init(NULL, s302m_beethoven_event_id); | |
| 121 | + if (!s302m->events) | |
| 122 | + goto free_encoders; | |
| 123 | + s302m->events->descriptor = (struct vidtv_psi_desc *) | |
| 124 | + vidtv_psi_short_event_desc_init(NULL, | |
| 125 | + iso_language_code, | |
| 126 | + event_name, | |
| 127 | + event_text); | |
| 128 | + if (!s302m->events->descriptor) | |
| 129 | + goto free_events; | |
| 96 | 130 | |
| 97 | 131 | if (head) { |
| 98 | 132 | while (head->next) |
| @@ -102,6 +136,68 @@ struct vidtv_channel · 3 unmodified lines | ||
| 102 | 136 | } |
| 103 | 137 | |
| 104 | 138 | return s302m; |
| 139 | + | |
| 140 | +free_events: | |
| 141 | + vidtv_psi_eit_event_destroy(s302m->events); | |
| 142 | +free_encoders: | |
| 143 | + vidtv_s302m_encoder_destroy(s302m->encoders); | |
| 144 | +free_streams: | |
| 145 | + vidtv_psi_pmt_stream_destroy(s302m->streams); | |
| 146 | +free_program: | |
| 147 | + vidtv_psi_pat_program_destroy(s302m->program); | |
| 148 | +free_service: | |
| 149 | + vidtv_psi_sdt_service_destroy(s302m->service); | |
| 150 | +free_name: | |
| 151 | + kfree(s302m->name); | |
| 152 | +free_s302m: | |
| 153 | + kfree(s302m); | |
| 154 | + | |
| 155 | + return NULL; | |
| 156 | +} | |
| 157 | + | |
| 158 | +static struct vidtv_psi_table_eit_event | |
| 159 | +*vidtv_channel_eit_event_cat_into_new(struct vidtv_mux *m) | |
| 160 | +{ | |
| 161 | + /* Concatenate the events */ | |
| 162 | + const struct vidtv_channel *cur_chnl = m->channels; | |
| 163 | + struct vidtv_psi_table_eit_event *curr = NULL; | |
| 164 | + struct vidtv_psi_table_eit_event *head = NULL; | |
| 165 | + struct vidtv_psi_table_eit_event *tail = NULL; | |
| 166 | + struct vidtv_psi_desc *desc = NULL; | |
| 167 | + u16 event_id; | |
| 168 | + | |
| 169 | + if (!cur_chnl) | |
| 170 | + return NULL; | |
| 171 | + | |
| 172 | + while (cur_chnl) { | |
| 173 | + curr = cur_chnl->events; | |
| 174 | + | |
| 175 | + if (!curr) | |
| 176 | + dev_warn_ratelimited(m->dev, | |
| 177 | + "No events found for channel %s\n", | |
| 178 | + cur_chnl->name); | |
| 179 | + | |
| 180 | + while (curr) { | |
| 181 | + event_id = be16_to_cpu(curr->event_id); | |
| 182 | + tail = vidtv_psi_eit_event_init(tail, event_id); | |
| 183 | + if (!tail) { | |
| 184 | + vidtv_psi_eit_event_destroy(head); | |
| 185 | + return NULL; | |
| 186 | + } | |
| 187 | + | |
| 188 | + desc = vidtv_psi_desc_clone(curr->descriptor); | |
| 189 | + vidtv_psi_desc_assign(&tail->descriptor, desc); | |
| 190 | + | |
| 191 | + if (!head) | |
| 192 | + head = tail; | |
| 193 | + | |
| 194 | + curr = curr->next; | |
| 195 | + } | |
| 196 | + | |
| 197 | + cur_chnl = cur_chnl->next; | |
| 198 | + } | |
| 199 | + | |
| 200 | + return head; | |
| 105 | 201 | } |
| 106 | 202 | |
| 107 | 203 | static struct vidtv_psi_table_sdt_service |
| @@ -125,13 +221,21 @@ static struct vidtv_psi_table_sdt_service · 17 unmodified lines | ||
| 125 | 221 | |
| 126 | 222 | if (!curr) |
| 127 | 223 | dev_warn_ratelimited(m->dev, |
| 128 | − "No services found for channel %s\n", cur_chnl->name); | |
| 224 | + "No services found for channel %s\n", | |
| 225 | + cur_chnl->name); | |
| 129 | 226 | |
| 130 | 227 | while (curr) { |
| 131 | 228 | service_id = be16_to_cpu(curr->service_id); |
| 132 | − tail = vidtv_psi_sdt_service_init(tail, service_id); | |
| 229 | + tail = vidtv_psi_sdt_service_init(tail, | |
| 230 | + service_id, | |
| 231 | + curr->EIT_schedule, | |
| 232 | + curr->EIT_present_following); | |
| 233 | + if (!tail) | |
| 234 | + goto free; | |
| 133 | 235 | |
| 134 | 236 | desc = vidtv_psi_desc_clone(curr->descriptor); |
| 237 | + if (!desc) | |
| 238 | + goto free_tail; | |
| 135 | 239 | vidtv_psi_desc_assign(&tail->descriptor, desc); |
| 136 | 240 | |
| 137 | 241 | if (!head) |
| @@ -144,6 +248,12 @@ static struct vidtv_psi_table_sdt_service · 6 unmodified lines | ||
| 144 | 248 | } |
| 145 | 249 | |
| 146 | 250 | return head; |
| 251 | + | |
| 252 | +free_tail: | |
| 253 | + vidtv_psi_sdt_service_destroy(tail); | |
| 254 | +free: | |
| 255 | + vidtv_psi_sdt_service_destroy(head); | |
| 256 | + return NULL; | |
| 147 | 257 | } |
| 148 | 258 | |
| 149 | 259 | static struct vidtv_psi_table_pat_program* |
| @@ -174,6 +284,10 @@ vidtv_channel_pat_prog_cat_into_new(struct vidtv_mux *m) · 24 unmodified lines | ||
| 174 | 284 | tail = vidtv_psi_pat_program_init(tail, |
| 175 | 285 | serv_id, |
| 176 | 286 | pid); |
| 287 | + if (!tail) { | |
| 288 | + vidtv_psi_pat_program_destroy(head); | |
| 289 | + return NULL; | |
| 290 | + } | |
| 177 | 291 | |
| 178 | 292 | if (!head) |
| 179 | 293 | head = tail; |
| @@ -183,30 +297,30 @@ vidtv_channel_pat_prog_cat_into_new(struct vidtv_mux *m) · 3 unmodified lines | ||
| 183 | 297 | |
| 184 | 298 | cur_chnl = cur_chnl->next; |
| 185 | 299 | } |
| 300 | + /* Add the NIT table */ | |
| 301 | + vidtv_psi_pat_program_init(tail, 0, TS_NIT_PID); | |
| 186 | 302 | |
| 187 | 303 | return head; |
| 188 | 304 | } |
| 189 | 305 | |
| 306 | +/* | |
| 307 | + * Match channels to their respective PMT sections, then assign the | |
| 308 | + * streams | |
| 309 | + */ | |
| 190 | 310 | static void |
| 191 | 311 | vidtv_channel_pmt_match_sections(struct vidtv_channel *channels, |
| 192 | 312 | struct vidtv_psi_table_pmt **sections, |
| 193 | 313 | u32 nsections) |
| 194 | 314 | { |
| 195 | − /* | |
| 196 | − * Match channels to their respective PMT sections, then assign the | |
| 197 | − * streams | |
| 198 | − */ | |
| 199 | 315 | struct vidtv_psi_table_pmt *curr_section = NULL; |
| 200 | − struct vidtv_channel *cur_chnl = channels; | |
| 201 | − | |
| 202 | − struct vidtv_psi_table_pmt_stream *s = NULL; | |
| 203 | 316 | struct vidtv_psi_table_pmt_stream *head = NULL; |
| 204 | 317 | struct vidtv_psi_table_pmt_stream *tail = NULL; |
| 205 | − | |
| 318 | + struct vidtv_psi_table_pmt_stream *s = NULL; | |
| 319 | + struct vidtv_channel *cur_chnl = channels; | |
| 206 | 320 | struct vidtv_psi_desc *desc = NULL; |
| 207 | − u32 j; | |
| 208 | − u16 curr_id; | |
| 209 | 321 | u16 e_pid; /* elementary stream pid */ |
| 322 | + u16 curr_id; | |
| 323 | + u32 j; | |
| 210 | 324 | |
| 211 | 325 | while (cur_chnl) { |
| 212 | 326 | for (j = 0; j < nsections; ++j) { |
| @@ -232,7 +346,8 @@ vidtv_channel_pmt_match_sections(struct vidtv_channel *channels, · 19 unmodified lines | ||
| 232 | 346 | head = tail; |
| 233 | 347 | |
| 234 | 348 | desc = vidtv_psi_desc_clone(s->descriptor); |
| 235 | − vidtv_psi_desc_assign(&tail->descriptor, desc); | |
| 349 | + vidtv_psi_desc_assign(&tail->descriptor, | |
| 350 | + desc); | |
| 236 | 351 | |
| 237 | 352 | s = s->next; |
| 238 | 353 | } |
| @@ -246,17 +361,103 @@ vidtv_channel_pmt_match_sections(struct vidtv_channel *channels, · 7 unmodified lines | ||
| 246 | 361 | } |
| 247 | 362 | } |
| 248 | 363 | |
| 249 | −void vidtv_channel_si_init(struct vidtv_mux *m) | |
| 364 | +static void | |
| 365 | +vidtv_channel_destroy_service_list(struct vidtv_psi_desc_service_list_entry *e) | |
| 366 | +{ | |
| 367 | + struct vidtv_psi_desc_service_list_entry *tmp; | |
| 368 | + | |
| 369 | + while (e) { | |
| 370 | + tmp = e; | |
| 371 | + e = e->next; | |
| 372 | + kfree(tmp); | |
| 373 | + } | |
| 374 | +} | |
| 375 | + | |
| 376 | +static struct vidtv_psi_desc_service_list_entry | |
| 377 | +*vidtv_channel_build_service_list(struct vidtv_psi_table_sdt_service *s) | |
| 378 | +{ | |
| 379 | + struct vidtv_psi_desc_service_list_entry *curr_e = NULL; | |
| 380 | + struct vidtv_psi_desc_service_list_entry *head_e = NULL; | |
| 381 | + struct vidtv_psi_desc_service_list_entry *prev_e = NULL; | |
| 382 | + struct vidtv_psi_desc *desc = s->descriptor; | |
| 383 | + struct vidtv_psi_desc_service *s_desc; | |
| 384 | + | |
| 385 | + while (s) { | |
| 386 | + while (desc) { | |
| 387 | + if (s->descriptor->type != SERVICE_DESCRIPTOR) | |
| 388 | + goto next_desc; | |
| 389 | + | |
| 390 | + s_desc = (struct vidtv_psi_desc_service *)desc; | |
| 391 | + | |
| 392 | + curr_e = kzalloc(sizeof(*curr_e), GFP_KERNEL); | |
| 393 | + if (!curr_e) { | |
| 394 | + vidtv_channel_destroy_service_list(head_e); | |
| 395 | + return NULL; | |
| 396 | + } | |
| 397 | + | |
| 398 | + curr_e->service_id = s->service_id; | |
| 399 | + curr_e->service_type = s_desc->service_type; | |
| 400 | + | |
| 401 | + if (!head_e) | |
| 402 | + head_e = curr_e; | |
| 403 | + if (prev_e) | |
| 404 | + prev_e->next = curr_e; | |
| 405 | + | |
| 406 | + prev_e = curr_e; | |
| 407 | + | |
| 408 | +next_desc: | |
| 409 | + desc = desc->next; | |
| 410 | + } | |
| 411 | + s = s->next; | |
| 412 | + } | |
| 413 | + return head_e; | |
| 414 | +} | |
| 415 | + | |
| 416 | +int vidtv_channel_si_init(struct vidtv_mux *m) | |
| 250 | 417 | { |
| 418 | + struct vidtv_psi_desc_service_list_entry *service_list = NULL; | |
| 251 | 419 | struct vidtv_psi_table_pat_program *programs = NULL; |
| 252 | 420 | struct vidtv_psi_table_sdt_service *services = NULL; |
| 421 | + struct vidtv_psi_table_eit_event *events = NULL; | |
| 253 | 422 | |
| 254 | 423 | m->si.pat = vidtv_psi_pat_table_init(m->transport_stream_id); |
| 424 | + if (!m->si.pat) | |
| 425 | + return -ENOMEM; | |
| 255 | 426 | |
| 256 | − m->si.sdt = vidtv_psi_sdt_table_init(m->transport_stream_id); | |
| 427 | + m->si.sdt = vidtv_psi_sdt_table_init(m->network_id, | |
| 428 | + m->transport_stream_id); | |
| 429 | + if (!m->si.sdt) | |
| 430 | + goto free_pat; | |
| 257 | 431 | |
| 258 | 432 | programs = vidtv_channel_pat_prog_cat_into_new(m); |
| 433 | + if (!programs) | |
| 434 | + goto free_sdt; | |
| 259 | 435 | services = vidtv_channel_sdt_serv_cat_into_new(m); |
| 436 | + if (!services) | |
| 437 | + goto free_programs; | |
| 438 | + | |
| 439 | + events = vidtv_channel_eit_event_cat_into_new(m); | |
| 440 | + if (!events) | |
| 441 | + goto free_services; | |
| 442 | + | |
| 443 | + /* look for a service descriptor for every service */ | |
| 444 | + service_list = vidtv_channel_build_service_list(services); | |
| 445 | + if (!service_list) | |
| 446 | + goto free_events; | |
| 447 | + | |
| 448 | + /* use these descriptors to build the NIT */ | |
| 449 | + m->si.nit = vidtv_psi_nit_table_init(m->network_id, | |
| 450 | + m->transport_stream_id, | |
| 451 | + m->network_name, | |
| 452 | + service_list); | |
| 453 | + if (!m->si.nit) | |
| 454 | + goto free_service_list; | |
| 455 | + | |
| 456 | + m->si.eit = vidtv_psi_eit_table_init(m->network_id, | |
| 457 | + m->transport_stream_id, | |
| 458 | + programs->service_id); | |
| 459 | + if (!m->si.eit) | |
| 460 | + goto free_nit; | |
| 260 | 461 | |
| 261 | 462 | /* assemble all programs and assign to PAT */ |
| 262 | 463 | vidtv_psi_pat_program_assign(m->si.pat, programs); |
| @@ -264,31 +465,65 @@ void vidtv_channel_si_init(struct vidtv_mux *m) · 1 unmodified line | ||
| 264 | 465 | /* assemble all services and assign to SDT */ |
| 265 | 466 | vidtv_psi_sdt_service_assign(m->si.sdt, services); |
| 266 | 467 | |
| 267 | − m->si.pmt_secs = vidtv_psi_pmt_create_sec_for_each_pat_entry(m->si.pat, m->pcr_pid); | |
| 468 | + /* assemble all events and assign to EIT */ | |
| 469 | + vidtv_psi_eit_event_assign(m->si.eit, events); | |
| 470 | + | |
| 471 | + m->si.pmt_secs = vidtv_psi_pmt_create_sec_for_each_pat_entry(m->si.pat, | |
| 472 | + m->pcr_pid); | |
| 473 | + if (!m->si.pmt_secs) | |
| 474 | + goto free_eit; | |
| 268 | 475 | |
| 269 | 476 | vidtv_channel_pmt_match_sections(m->channels, |
| 270 | 477 | m->si.pmt_secs, |
| 271 | − m->si.pat->programs); | |
| 478 | + m->si.pat->num_pmt); | |
| 479 | + | |
| 480 | + vidtv_channel_destroy_service_list(service_list); | |
| 481 | + | |
| 482 | + return 0; | |
| 483 | + | |
| 484 | +free_eit: | |
| 485 | + vidtv_psi_eit_table_destroy(m->si.eit); | |
| 486 | +free_nit: | |
| 487 | + vidtv_psi_nit_table_destroy(m->si.nit); | |
| 488 | +free_service_list: | |
| 489 | + vidtv_channel_destroy_service_list(service_list); | |
| 490 | +free_events: | |
| 491 | + vidtv_psi_eit_event_destroy(events); | |
| 492 | +free_services: | |
| 493 | + vidtv_psi_sdt_service_destroy(services); | |
| 494 | +free_programs: | |
| 495 | + vidtv_psi_pat_program_destroy(programs); | |
| 496 | +free_sdt: | |
| 497 | + vidtv_psi_sdt_table_destroy(m->si.sdt); | |
| 498 | +free_pat: | |
| 499 | + vidtv_psi_pat_table_destroy(m->si.pat); | |
| 500 | + return 0; | |
| 272 | 501 | } |
| 273 | 502 | |
| 274 | 503 | void vidtv_channel_si_destroy(struct vidtv_mux *m) |
| 275 | 504 | { |
| 276 | 505 | u32 i; |
| 277 | − u16 num_programs = m->si.pat->programs; | |
| 278 | 506 | |
| 279 | 507 | vidtv_psi_pat_table_destroy(m->si.pat); |
| 280 | 508 | |
| 281 | − for (i = 0; i < num_programs; ++i) | |
| 509 | + for (i = 0; i < m->si.pat->num_pmt; ++i) | |
| 282 | 510 | vidtv_psi_pmt_table_destroy(m->si.pmt_secs[i]); |
| 283 | 511 | |
| 284 | 512 | kfree(m->si.pmt_secs); |
| 285 | 513 | vidtv_psi_sdt_table_destroy(m->si.sdt); |
| 514 | + vidtv_psi_nit_table_destroy(m->si.nit); | |
| 515 | + vidtv_psi_eit_table_destroy(m->si.eit); | |
| 286 | 516 | } |
| 287 | 517 | |
| 288 | −void vidtv_channels_init(struct vidtv_mux *m) | |
| 518 | +int vidtv_channels_init(struct vidtv_mux *m) | |
| 289 | 519 | { |
| 290 | 520 | /* this is the place to add new 'channels' for vidtv */ |
| 291 | 521 | m->channels = vidtv_channel_s302m_init(NULL, m->transport_stream_id); |
| 522 | + | |
| 523 | + if (!m->channels) | |
| 524 | + return -ENOMEM; | |
| 525 | + | |
| 526 | + return 0; | |
| 292 | 527 | } |
| 293 | 528 | |
| 294 | 529 | void vidtv_channels_destroy(struct vidtv_mux *m) |
| @@ -302,6 +537,7 @@ void vidtv_channels_destroy(struct vidtv_mux *m) · 7 unmodified lines | ||
| 302 | 537 | vidtv_psi_pat_program_destroy(curr->program); |
| 303 | 538 | vidtv_psi_pmt_stream_destroy(curr->streams); |
| 304 | 539 | vidtv_channel_encoder_destroy(curr->encoders); |
| 540 | + vidtv_psi_eit_event_destroy(curr->events); | |
| 305 | 541 | |
| 306 | 542 | tmp = curr; |
| 307 | 543 | curr = curr->next; |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | * When vidtv boots, it will create some hardcoded channels. |
| 10 | 10 | * Their services will be concatenated to populate the SDT. |
| 11 | 11 | * Their programs will be concatenated to populate the PAT |
| 12 | + * Their events will be concatenated to populate the EIT | |
| 12 | 13 | * For each program in the PAT, a PMT section will be created |
| 13 | 14 | * The PMT section for a channel will be assigned its streams. |
| 14 | 15 | * Every stream will have its corresponding encoder polled to produce TS packets |
| @@ -22,9 +23,10 @@ · 7 unmodified lines | ||
| 22 | 23 | #define VIDTV_CHANNEL_H |
| 23 | 24 | |
| 24 | 25 | #include <linux/types.h> |
| 25 | −#include "vidtv_psi.h" | |
| 26 | + | |
| 26 | 27 | #include "vidtv_encoder.h" |
| 27 | 28 | #include "vidtv_mux.h" |
| 29 | +#include "vidtv_psi.h" | |
| 28 | 30 | |
| 29 | 31 | /** |
| 30 | 32 | * struct vidtv_channel - A 'channel' abstraction |
| @@ -37,6 +39,7 @@ · 6 unmodified lines | ||
| 37 | 39 | * Every stream will have its corresponding encoder polled to produce TS packets |
| 38 | 40 | * These packets may be interleaved by the mux and then delivered to the bridge |
| 39 | 41 | * |
| 42 | + * @name: name of the channel | |
| 40 | 43 | * @transport_stream_id: a number to identify the TS, chosen at will. |
| 41 | 44 | * @service: A _single_ service. Will be concatenated into the SDT. |
| 42 | 45 | * @program_num: The link between PAT, PMT and SDT. |
| @@ -44,6 +47,7 @@ · 1 unmodified line | ||
| 44 | 47 | * Will be concatenated into the PAT. |
| 45 | 48 | * @streams: A stream loop used to populate the PMT section for 'program' |
| 46 | 49 | * @encoders: A encoder loop. There must be one encoder for each stream. |
| 50 | + * @events: Optional event information. This will feed into the EIT. | |
| 47 | 51 | * @next: Optionally chain this channel. |
| 48 | 52 | */ |
| 49 | 53 | struct vidtv_channel { |
| @@ -54,6 +58,7 @@ struct vidtv_channel { · 4 unmodified lines | ||
| 54 | 58 | struct vidtv_psi_table_pat_program *program; |
| 55 | 59 | struct vidtv_psi_table_pmt_stream *streams; |
| 56 | 60 | struct vidtv_encoder *encoders; |
| 61 | + struct vidtv_psi_table_eit_event *events; | |
| 57 | 62 | struct vidtv_channel *next; |
| 58 | 63 | }; |
| 59 | 64 | |
| @@ -61,14 +66,14 @@ struct vidtv_channel { · 1 unmodified line | ||
| 61 | 66 | * vidtv_channel_si_init - Init the PSI tables from the channels in the mux |
| 62 | 67 | * @m: The mux containing the channels. |
| 63 | 68 | */ |
| 64 | −void vidtv_channel_si_init(struct vidtv_mux *m); | |
| 69 | +int vidtv_channel_si_init(struct vidtv_mux *m); | |
| 65 | 70 | void vidtv_channel_si_destroy(struct vidtv_mux *m); |
| 66 | 71 | |
| 67 | 72 | /** |
| 68 | 73 | * vidtv_channels_init - Init hardcoded, fake 'channels'. |
| 69 | 74 | * @m: The mux to store the channels into. |
| 70 | 75 | */ |
| 71 | −void vidtv_channels_init(struct vidtv_mux *m); | |
| 76 | +int vidtv_channels_init(struct vidtv_mux *m); | |
| 72 | 77 | struct vidtv_channel |
| 73 | 78 | *vidtv_channel_s302m_init(struct vidtv_channel *head, u16 transport_stream_id); |
| 74 | 79 | void vidtv_channels_destroy(struct vidtv_mux *m); |
| @@ -16,7 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | #define CLOCK_UNIT_27MHZ 27000000 |
| 17 | 17 | #define VIDTV_SLEEP_USECS 10000 |
| 18 | 18 | #define VIDTV_MAX_SLEEP_USECS (2 * VIDTV_SLEEP_USECS) |
| 19 | −#define VIDTV_DEFAULT_TS_ID 0x744 | |
| 20 | 19 | |
| 21 | 20 | u32 vidtv_memcpy(void *to, |
| 22 | 21 | size_t to_offset, |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/slab.h> |
| 20 | 20 | #include <linux/string.h> |
| 21 | 21 | #include <linux/workqueue.h> |
| 22 | + | |
| 22 | 23 | #include <media/dvb_frontend.h> |
| 23 | 24 | |
| 24 | 25 | #include "vidtv_demod.h" |
| @@ -192,7 +193,6 @@ static void vidtv_demod_update_stats(struct dvb_frontend *fe) · 167 unmodified lines | ||
| 192 | 193 | |
| 193 | 194 | c->cnr.stat[0].svalue = state->tuner_cnr; |
| 194 | 195 | c->cnr.stat[0].svalue -= prandom_u32_max(state->tuner_cnr / 50); |
| 195 | − | |
| 196 | 196 | } |
| 197 | 197 | |
| 198 | 198 | static int vidtv_demod_read_status(struct dvb_frontend *fe, |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #define VIDTV_DEMOD_H |
| 13 | 13 | |
| 14 | 14 | #include <linux/dvb/frontend.h> |
| 15 | + | |
| 15 | 16 | #include <media/dvb_frontend.h> |
| 16 | 17 | |
| 17 | 18 | /** |
| @@ -19,6 +20,9 @@ · 1 unmodified line | ||
| 19 | 20 | * modulation and fec_inner |
| 20 | 21 | * @modulation: see enum fe_modulation |
| 21 | 22 | * @fec: see enum fe_fec_rate |
| 23 | + * @cnr_ok: S/N threshold to consider the signal as OK. Below that, there's | |
| 24 | + * a chance of losing sync. | |
| 25 | + * @cnr_good: S/N threshold to consider the signal strong. | |
| 22 | 26 | * |
| 23 | 27 | * This struct matches values for 'good' and 'ok' CNRs given the combination |
| 24 | 28 | * of modulation and fec_inner in use. We might simulate some noise if the |
| @@ -52,13 +56,8 @@ struct vidtv_demod_config { · 27 unmodified lines | ||
| 52 | 56 | * struct vidtv_demod_state - The demodulator state |
| 53 | 57 | * @frontend: The frontend structure allocated by the demod. |
| 54 | 58 | * @config: The config used to init the demod. |
| 55 | − * @poll_snr: The task responsible for periodically checking the simulated | |
| 56 | − * signal quality, eventually dropping or reacquiring the TS lock. | |
| 57 | 59 | * @status: the demod status. |
| 58 | − * @cold_start: Whether the demod has not been init yet. | |
| 59 | − * @poll_snr_thread_running: Whether the task responsible for periodically | |
| 60 | − * checking the simulated signal quality is running. | |
| 61 | − * @poll_snr_thread_restart: Whether we should restart the poll_snr task. | |
| 60 | + * @tuner_cnr: current S/N ratio for the signal carrier | |
| 62 | 61 | */ |
| 63 | 62 | struct vidtv_demod_state { |
| 64 | 63 | struct dvb_frontend frontend; |
| @@ -28,7 +28,7 @@ struct vidtv_access_unit { · 27 unmodified lines | ||
| 28 | 28 | struct vidtv_access_unit *next; |
| 29 | 29 | }; |
| 30 | 30 | |
| 31 | −/* Some musical notes, used by a tone generator */ | |
| 31 | +/* Some musical notes, used by a tone generator. Values are in Hz */ | |
| 32 | 32 | enum musical_notes { |
| 33 | 33 | NOTE_SILENT = 0, |
| 34 | 34 | |
| @@ -103,14 +103,16 @@ enum musical_notes { · 68 unmodified lines | ||
| 103 | 103 | * @encoder_buf_sz: The encoder buffer size, in bytes |
| 104 | 104 | * @encoder_buf_offset: Our byte position in the encoder buffer. |
| 105 | 105 | * @sample_count: How many samples we have encoded in total. |
| 106 | + * @access_units: encoder payload units, used for clock references | |
| 106 | 107 | * @src_buf: The source of raw data to be encoded, encoder might set a |
| 107 | 108 | * default if null. |
| 109 | + * @src_buf_sz: size of @src_buf. | |
| 108 | 110 | * @src_buf_offset: Our position in the source buffer. |
| 109 | 111 | * @is_video_encoder: Whether this a video encoder (as opposed to audio) |
| 110 | 112 | * @ctx: Encoder-specific state. |
| 111 | 113 | * @stream_id: Examples: Audio streams (0xc0-0xdf), Video streams |
| 112 | 114 | * (0xe0-0xef). |
| 113 | − * @es_id: The TS PID to use for the elementary stream in this encoder. | |
| 115 | + * @es_pid: The TS PID to use for the elementary stream in this encoder. | |
| 114 | 116 | * @encode: Prepare enough AUs for the given amount of time. |
| 115 | 117 | * @clear: Clear the encoder output. |
| 116 | 118 | * @sync: Attempt to synchronize with this encoder. |
| @@ -131,9 +133,6 @@ struct vidtv_encoder { · 14 unmodified lines | ||
| 131 | 133 | u32 encoder_buf_offset; |
| 132 | 134 | |
| 133 | 135 | u64 sample_count; |
| 134 | − int last_duration; | |
| 135 | − int note_offset; | |
| 136 | − enum musical_notes last_tone; | |
| 137 | 136 | |
| 138 | 137 | struct vidtv_access_unit *access_units; |
| 139 | 138 | |
| @@ -12,23 +12,23 @@ · 11 unmodified lines | ||
| 12 | 12 | * Copyright (C) 2020 Daniel W. S. Almeida |
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | −#include <linux/types.h> | |
| 16 | −#include <linux/slab.h> | |
| 15 | +#include <linux/delay.h> | |
| 16 | +#include <linux/dev_printk.h> | |
| 17 | 17 | #include <linux/jiffies.h> |
| 18 | 18 | #include <linux/kernel.h> |
| 19 | −#include <linux/dev_printk.h> | |
| 19 | +#include <linux/math64.h> | |
| 20 | 20 | #include <linux/ratelimit.h> |
| 21 | −#include <linux/delay.h> | |
| 21 | +#include <linux/slab.h> | |
| 22 | +#include <linux/types.h> | |
| 22 | 23 | #include <linux/vmalloc.h> |
| 23 | −#include <linux/math64.h> | |
| 24 | 24 | |
| 25 | −#include "vidtv_mux.h" | |
| 26 | −#include "vidtv_ts.h" | |
| 27 | −#include "vidtv_pes.h" | |
| 28 | −#include "vidtv_encoder.h" | |
| 29 | 25 | #include "vidtv_channel.h" |
| 30 | 26 | #include "vidtv_common.h" |
| 27 | +#include "vidtv_encoder.h" | |
| 28 | +#include "vidtv_mux.h" | |
| 29 | +#include "vidtv_pes.h" | |
| 31 | 30 | #include "vidtv_psi.h" |
| 31 | +#include "vidtv_ts.h" | |
| 32 | 32 | |
| 33 | 33 | static struct vidtv_mux_pid_ctx |
| 34 | 34 | *vidtv_mux_get_pid_ctx(struct vidtv_mux *m, u16 pid) |
| @@ -47,33 +47,56 @@ static struct vidtv_mux_pid_ctx · 12 unmodified lines | ||
| 47 | 47 | struct vidtv_mux_pid_ctx *ctx; |
| 48 | 48 | |
| 49 | 49 | ctx = vidtv_mux_get_pid_ctx(m, pid); |
| 50 | − | |
| 51 | 50 | if (ctx) |
| 52 | − goto end; | |
| 51 | + return ctx; | |
| 52 | + | |
| 53 | + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | |
| 54 | + if (!ctx) | |
| 55 | + return NULL; | |
| 53 | 56 | |
| 54 | − ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | |
| 55 | 57 | ctx->pid = pid; |
| 56 | 58 | ctx->cc = 0; |
| 57 | 59 | hash_add(m->pid_ctx, &ctx->h, pid); |
| 58 | 60 | |
| 59 | −end: | |
| 60 | 61 | return ctx; |
| 61 | 62 | } |
| 62 | 63 | |
| 63 | −static void vidtv_mux_pid_ctx_init(struct vidtv_mux *m) | |
| 64 | +static void vidtv_mux_pid_ctx_destroy(struct vidtv_mux *m) | |
| 65 | +{ | |
| 66 | + struct vidtv_mux_pid_ctx *ctx; | |
| 67 | + struct hlist_node *tmp; | |
| 68 | + int bkt; | |
| 69 | + | |
| 70 | + hash_for_each_safe(m->pid_ctx, bkt, tmp, ctx, h) { | |
| 71 | + hash_del(&ctx->h); | |
| 72 | + kfree(ctx); | |
| 73 | + } | |
| 74 | +} | |
| 75 | + | |
| 76 | +static int vidtv_mux_pid_ctx_init(struct vidtv_mux *m) | |
| 64 | 77 | { |
| 65 | 78 | struct vidtv_psi_table_pat_program *p = m->si.pat->program; |
| 66 | 79 | u16 pid; |
| 67 | 80 | |
| 68 | 81 | hash_init(m->pid_ctx); |
| 69 | 82 | /* push the pcr pid ctx */ |
| 70 | − vidtv_mux_create_pid_ctx_once(m, m->pcr_pid); | |
| 71 | − /* push the null packet pid ctx */ | |
| 72 | − vidtv_mux_create_pid_ctx_once(m, TS_NULL_PACKET_PID); | |
| 83 | + if (!vidtv_mux_create_pid_ctx_once(m, m->pcr_pid)) | |
| 84 | + return -ENOMEM; | |
| 85 | + /* push the NULL packet pid ctx */ | |
| 86 | + if (!vidtv_mux_create_pid_ctx_once(m, TS_NULL_PACKET_PID)) | |
| 87 | + goto free; | |
| 73 | 88 | /* push the PAT pid ctx */ |
| 74 | − vidtv_mux_create_pid_ctx_once(m, VIDTV_PAT_PID); | |
| 89 | + if (!vidtv_mux_create_pid_ctx_once(m, VIDTV_PAT_PID)) | |
| 90 | + goto free; | |
| 75 | 91 | /* push the SDT pid ctx */ |
| 76 | − vidtv_mux_create_pid_ctx_once(m, VIDTV_SDT_PID); | |
| 92 | + if (!vidtv_mux_create_pid_ctx_once(m, VIDTV_SDT_PID)) | |
| 93 | + goto free; | |
| 94 | + /* push the NIT pid ctx */ | |
| 95 | + if (!vidtv_mux_create_pid_ctx_once(m, VIDTV_NIT_PID)) | |
| 96 | + goto free; | |
| 97 | + /* push the EIT pid ctx */ | |
| 98 | + if (!vidtv_mux_create_pid_ctx_once(m, VIDTV_EIT_PID)) | |
| 99 | + goto free; | |
| 77 | 100 | |
| 78 | 101 | /* add a ctx for all PMT sections */ |
| 79 | 102 | while (p) { |
| @@ -81,18 +104,12 @@ static void vidtv_mux_pid_ctx_init(struct vidtv_mux *m) · 1 unmodified line | ||
| 81 | 104 | vidtv_mux_create_pid_ctx_once(m, pid); |
| 82 | 105 | p = p->next; |
| 83 | 106 | } |
| 84 | −} | |
| 85 | 107 | |
| 86 | −static void vidtv_mux_pid_ctx_destroy(struct vidtv_mux *m) | |
| 87 | −{ | |
| 88 | − int bkt; | |
| 89 | − struct vidtv_mux_pid_ctx *ctx; | |
| 90 | − struct hlist_node *tmp; | |
| 108 | + return 0; | |
| 91 | 109 | |
| 92 | − hash_for_each_safe(m->pid_ctx, bkt, tmp, ctx, h) { | |
| 93 | − hash_del(&ctx->h); | |
| 94 | − kfree(ctx); | |
| 95 | − } | |
| 110 | +free: | |
| 111 | + vidtv_mux_pid_ctx_destroy(m); | |
| 112 | + return -ENOMEM; | |
| 96 | 113 | } |
| 97 | 114 | |
| 98 | 115 | static void vidtv_mux_update_clk(struct vidtv_mux *m) |
| @@ -112,32 +129,53 @@ static void vidtv_mux_update_clk(struct vidtv_mux *m) · 13 unmodified lines | ||
| 112 | 129 | |
| 113 | 130 | static u32 vidtv_mux_push_si(struct vidtv_mux *m) |
| 114 | 131 | { |
| 132 | + struct vidtv_psi_pat_write_args pat_args = { | |
| 133 | + .buf = m->mux_buf, | |
| 134 | + .buf_sz = m->mux_buf_sz, | |
| 135 | + .pat = m->si.pat, | |
| 136 | + }; | |
| 137 | + struct vidtv_psi_pmt_write_args pmt_args = { | |
| 138 | + .buf = m->mux_buf, | |
| 139 | + .buf_sz = m->mux_buf_sz, | |
| 140 | + .pcr_pid = m->pcr_pid, | |
| 141 | + }; | |
| 142 | + struct vidtv_psi_sdt_write_args sdt_args = { | |
| 143 | + .buf = m->mux_buf, | |
| 144 | + .buf_sz = m->mux_buf_sz, | |
| 145 | + .sdt = m->si.sdt, | |
| 146 | + }; | |
| 147 | + struct vidtv_psi_nit_write_args nit_args = { | |
| 148 | + .buf = m->mux_buf, | |
| 149 | + .buf_sz = m->mux_buf_sz, | |
| 150 | + .nit = m->si.nit, | |
| 151 | + | |
| 152 | + }; | |
| 153 | + struct vidtv_psi_eit_write_args eit_args = { | |
| 154 | + .buf = m->mux_buf, | |
| 155 | + .buf_sz = m->mux_buf_sz, | |
| 156 | + .eit = m->si.eit, | |
| 157 | + }; | |
| 115 | 158 | u32 initial_offset = m->mux_buf_offset; |
| 116 | − | |
| 117 | 159 | struct vidtv_mux_pid_ctx *pat_ctx; |
| 118 | 160 | struct vidtv_mux_pid_ctx *pmt_ctx; |
| 119 | 161 | struct vidtv_mux_pid_ctx *sdt_ctx; |
| 120 | − | |
| 121 | − struct vidtv_psi_pat_write_args pat_args = {}; | |
| 122 | − struct vidtv_psi_pmt_write_args pmt_args = {}; | |
| 123 | − struct vidtv_psi_sdt_write_args sdt_args = {}; | |
| 124 | − | |
| 125 | − u32 nbytes; /* the number of bytes written by this function */ | |
| 162 | + struct vidtv_mux_pid_ctx *nit_ctx; | |
| 163 | + struct vidtv_mux_pid_ctx *eit_ctx; | |
| 164 | + u32 nbytes; | |
| 126 | 165 | u16 pmt_pid; |
| 127 | 166 | u32 i; |
| 128 | 167 | |
| 129 | 168 | pat_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_PAT_PID); |
| 130 | 169 | sdt_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_SDT_PID); |
| 170 | + nit_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_NIT_PID); | |
| 171 | + eit_ctx = vidtv_mux_get_pid_ctx(m, VIDTV_EIT_PID); | |
| 131 | 172 | |
| 132 | − pat_args.buf = m->mux_buf; | |
| 133 | 173 | pat_args.offset = m->mux_buf_offset; |
| 134 | − pat_args.pat = m->si.pat; | |
| 135 | − pat_args.buf_sz = m->mux_buf_sz; | |
| 136 | 174 | pat_args.continuity_counter = &pat_ctx->cc; |
| 137 | 175 | |
| 138 | − m->mux_buf_offset += vidtv_psi_pat_write_into(pat_args); | |
| 176 | + m->mux_buf_offset += vidtv_psi_pat_write_into(&pat_args); | |
| 139 | 177 | |
| 140 | − for (i = 0; i < m->si.pat->programs; ++i) { | |
| 178 | + for (i = 0; i < m->si.pat->num_pmt; ++i) { | |
| 141 | 179 | pmt_pid = vidtv_psi_pmt_get_pid(m->si.pmt_secs[i], |
| 142 | 180 | m->si.pat); |
| 143 | 181 | |
| @@ -149,25 +187,29 @@ static u32 vidtv_mux_push_si(struct vidtv_mux *m) · 5 unmodified lines | ||
| 149 | 187 | |
| 150 | 188 | pmt_ctx = vidtv_mux_get_pid_ctx(m, pmt_pid); |
| 151 | 189 | |
| 152 | − pmt_args.buf = m->mux_buf; | |
| 153 | 190 | pmt_args.offset = m->mux_buf_offset; |
| 154 | 191 | pmt_args.pmt = m->si.pmt_secs[i]; |
| 155 | 192 | pmt_args.pid = pmt_pid; |
| 156 | − pmt_args.buf_sz = m->mux_buf_sz; | |
| 157 | 193 | pmt_args.continuity_counter = &pmt_ctx->cc; |
| 158 | − pmt_args.pcr_pid = m->pcr_pid; | |
| 159 | 194 | |
| 160 | 195 | /* write each section into buffer */ |
| 161 | − m->mux_buf_offset += vidtv_psi_pmt_write_into(pmt_args); | |
| 196 | + m->mux_buf_offset += vidtv_psi_pmt_write_into(&pmt_args); | |
| 162 | 197 | } |
| 163 | 198 | |
| 164 | − sdt_args.buf = m->mux_buf; | |
| 165 | 199 | sdt_args.offset = m->mux_buf_offset; |
| 166 | − sdt_args.sdt = m->si.sdt; | |
| 167 | − sdt_args.buf_sz = m->mux_buf_sz; | |
| 168 | 200 | sdt_args.continuity_counter = &sdt_ctx->cc; |
| 169 | 201 | |
| 170 | − m->mux_buf_offset += vidtv_psi_sdt_write_into(sdt_args); | |
| 202 | + m->mux_buf_offset += vidtv_psi_sdt_write_into(&sdt_args); | |
| 203 | + | |
| 204 | + nit_args.offset = m->mux_buf_offset; | |
| 205 | + nit_args.continuity_counter = &nit_ctx->cc; | |
| 206 | + | |
| 207 | + m->mux_buf_offset += vidtv_psi_nit_write_into(&nit_args); | |
| 208 | + | |
| 209 | + eit_args.offset = m->mux_buf_offset; | |
| 210 | + eit_args.continuity_counter = &eit_ctx->cc; | |
| 211 | + | |
| 212 | + m->mux_buf_offset += vidtv_psi_eit_write_into(&eit_args); | |
| 171 | 213 | |
| 172 | 214 | nbytes = m->mux_buf_offset - initial_offset; |
| 173 | 215 | |
| @@ -230,23 +272,29 @@ static bool vidtv_mux_should_push_si(struct vidtv_mux *m) · 56 unmodified lines | ||
| 230 | 272 | static u32 vidtv_mux_packetize_access_units(struct vidtv_mux *m, |
| 231 | 273 | struct vidtv_encoder *e) |
| 232 | 274 | { |
| 233 | − u32 nbytes = 0; | |
| 234 | − | |
| 235 | − struct pes_write_args args = {}; | |
| 236 | − u32 initial_offset = m->mux_buf_offset; | |
| 275 | + struct pes_write_args args = { | |
| 276 | + .dest_buf = m->mux_buf, | |
| 277 | + .dest_buf_sz = m->mux_buf_sz, | |
| 278 | + .pid = be16_to_cpu(e->es_pid), | |
| 279 | + .encoder_id = e->id, | |
| 280 | + .stream_id = be16_to_cpu(e->stream_id), | |
| 281 | + .send_pts = true, /* forbidden value '01'... */ | |
| 282 | + .send_dts = false, /* ...for PTS_DTS flags */ | |
| 283 | + }; | |
| 237 | 284 | struct vidtv_access_unit *au = e->access_units; |
| 238 | − | |
| 285 | + u32 initial_offset = m->mux_buf_offset; | |
| 286 | + struct vidtv_mux_pid_ctx *pid_ctx; | |
| 287 | + u32 nbytes = 0; | |
| 239 | 288 | u8 *buf = NULL; |
| 240 | − struct vidtv_mux_pid_ctx *pid_ctx = vidtv_mux_create_pid_ctx_once(m, | |
| 241 | − be16_to_cpu(e->es_pid)); | |
| 242 | 289 | |
| 243 | − args.dest_buf = m->mux_buf; | |
| 244 | − args.dest_buf_sz = m->mux_buf_sz; | |
| 245 | − args.pid = be16_to_cpu(e->es_pid); | |
| 246 | − args.encoder_id = e->id; | |
| 290 | + /* see SMPTE 302M clause 6.4 */ | |
| 291 | + if (args.encoder_id == S302M) { | |
| 292 | + args.send_dts = false; | |
| 293 | + args.send_pts = true; | |
| 294 | + } | |
| 295 | + | |
| 296 | + pid_ctx = vidtv_mux_create_pid_ctx_once(m, be16_to_cpu(e->es_pid)); | |
| 247 | 297 | args.continuity_counter = &pid_ctx->cc; |
| 248 | − args.stream_id = be16_to_cpu(e->stream_id); | |
| 249 | − args.send_pts = true; | |
| 250 | 298 | |
| 251 | 299 | while (au) { |
| 252 | 300 | buf = e->encoder_buf + au->offset; |
| @@ -256,7 +304,7 @@ static u32 vidtv_mux_packetize_access_units(struct vidtv_mux *m, · 3 unmodified lines | ||
| 256 | 304 | args.pts = au->pts; |
| 257 | 305 | args.pcr = m->timing.clk; |
| 258 | 306 | |
| 259 | − m->mux_buf_offset += vidtv_pes_write_into(args); | |
| 307 | + m->mux_buf_offset += vidtv_pes_write_into(&args); | |
| 260 | 308 | |
| 261 | 309 | au = au->next; |
| 262 | 310 | } |
| @@ -273,10 +321,10 @@ static u32 vidtv_mux_packetize_access_units(struct vidtv_mux *m, · 10 unmodified lines | ||
| 273 | 321 | |
| 274 | 322 | static u32 vidtv_mux_poll_encoders(struct vidtv_mux *m) |
| 275 | 323 | { |
| 276 | − u32 nbytes = 0; | |
| 277 | − u32 au_nbytes; | |
| 278 | 324 | struct vidtv_channel *cur_chnl = m->channels; |
| 279 | 325 | struct vidtv_encoder *e = NULL; |
| 326 | + u32 nbytes = 0; | |
| 327 | + u32 au_nbytes; | |
| 280 | 328 | |
| 281 | 329 | while (cur_chnl) { |
| 282 | 330 | e = cur_chnl->encoders; |
| @@ -300,18 +348,19 @@ static u32 vidtv_mux_poll_encoders(struct vidtv_mux *m) · 17 unmodified lines | ||
| 300 | 348 | |
| 301 | 349 | static u32 vidtv_mux_pad_with_nulls(struct vidtv_mux *m, u32 npkts) |
| 302 | 350 | { |
| 303 | − struct null_packet_write_args args = {}; | |
| 351 | + struct null_packet_write_args args = { | |
| 352 | + .dest_buf = m->mux_buf, | |
| 353 | + .buf_sz = m->mux_buf_sz, | |
| 354 | + .dest_offset = m->mux_buf_offset, | |
| 355 | + }; | |
| 304 | 356 | u32 initial_offset = m->mux_buf_offset; |
| 305 | − u32 nbytes; /* the number of bytes written by this function */ | |
| 306 | − u32 i; | |
| 307 | 357 | struct vidtv_mux_pid_ctx *ctx; |
| 358 | + u32 nbytes; | |
| 359 | + u32 i; | |
| 308 | 360 | |
| 309 | 361 | ctx = vidtv_mux_get_pid_ctx(m, TS_NULL_PACKET_PID); |
| 310 | 362 | |
| 311 | − args.dest_buf = m->mux_buf; | |
| 312 | − args.buf_sz = m->mux_buf_sz; | |
| 313 | 363 | args.continuity_counter = &ctx->cc; |
| 314 | − args.dest_offset = m->mux_buf_offset; | |
| 315 | 364 | |
| 316 | 365 | for (i = 0; i < npkts; ++i) { |
| 317 | 366 | m->mux_buf_offset += vidtv_ts_null_write_into(args); |
| @@ -343,9 +392,9 @@ static void vidtv_mux_tick(struct work_struct *work) · 25 unmodified lines | ||
| 343 | 392 | struct vidtv_mux, |
| 344 | 393 | mpeg_thread); |
| 345 | 394 | struct dtv_frontend_properties *c = &m->fe->dtv_property_cache; |
| 395 | + u32 tot_bits = 0; | |
| 346 | 396 | u32 nbytes; |
| 347 | 397 | u32 npkts; |
| 348 | − u32 tot_bits = 0; | |
| 349 | 398 | |
| 350 | 399 | while (m->streaming) { |
| 351 | 400 | nbytes = 0; |
| @@ -427,40 +476,62 @@ void vidtv_mux_stop_thread(struct vidtv_mux *m) · 75 unmodified lines | ||
| 427 | 476 | |
| 428 | 477 | struct vidtv_mux *vidtv_mux_init(struct dvb_frontend *fe, |
| 429 | 478 | struct device *dev, |
| 430 | − struct vidtv_mux_init_args args) | |
| 479 | + struct vidtv_mux_init_args *args) | |
| 431 | 480 | { |
| 432 | − struct vidtv_mux *m = kzalloc(sizeof(*m), GFP_KERNEL); | |
| 481 | + struct vidtv_mux *m; | |
| 482 | + | |
| 483 | + m = kzalloc(sizeof(*m), GFP_KERNEL); | |
| 484 | + if (!m) | |
| 485 | + return NULL; | |
| 433 | 486 | |
| 434 | 487 | m->dev = dev; |
| 435 | 488 | m->fe = fe; |
| 436 | − m->timing.pcr_period_usecs = args.pcr_period_usecs; | |
| 437 | − m->timing.si_period_usecs = args.si_period_usecs; | |
| 489 | + m->timing.pcr_period_usecs = args->pcr_period_usecs; | |
| 490 | + m->timing.si_period_usecs = args->si_period_usecs; | |
| 491 | + | |
| 492 | + m->mux_rate_kbytes_sec = args->mux_rate_kbytes_sec; | |
| 438 | 493 | |
| 439 | − m->mux_rate_kbytes_sec = args.mux_rate_kbytes_sec; | |
| 494 | + m->on_new_packets_available_cb = args->on_new_packets_available_cb; | |
| 440 | 495 | |
| 441 | − m->on_new_packets_available_cb = args.on_new_packets_available_cb; | |
| 496 | + m->mux_buf = vzalloc(args->mux_buf_sz); | |
| 497 | + if (!m->mux_buf) | |
| 498 | + goto free_mux; | |
| 442 | 499 | |
| 443 | − m->mux_buf = vzalloc(args.mux_buf_sz); | |
| 444 | − m->mux_buf_sz = args.mux_buf_sz; | |
| 500 | + m->mux_buf_sz = args->mux_buf_sz; | |
| 445 | 501 | |
| 446 | − m->pcr_pid = args.pcr_pid; | |
| 447 | − m->transport_stream_id = args.transport_stream_id; | |
| 448 | − m->priv = args.priv; | |
| 502 | + m->pcr_pid = args->pcr_pid; | |
| 503 | + m->transport_stream_id = args->transport_stream_id; | |
| 504 | + m->priv = args->priv; | |
| 505 | + m->network_id = args->network_id; | |
| 506 | + m->network_name = kstrdup(args->network_name, GFP_KERNEL); | |
| 449 | 507 | m->timing.current_jiffies = get_jiffies_64(); |
| 450 | 508 | |
| 451 | − if (args.channels) | |
| 452 | − m->channels = args.channels; | |
| 509 | + if (args->channels) | |
| 510 | + m->channels = args->channels; | |
| 453 | 511 | else |
| 454 | − vidtv_channels_init(m); | |
| 512 | + if (vidtv_channels_init(m) < 0) | |
| 513 | + goto free_mux_buf; | |
| 455 | 514 | |
| 456 | 515 | /* will alloc data for pmt_sections after initializing pat */ |
| 457 | − vidtv_channel_si_init(m); | |
| 516 | + if (vidtv_channel_si_init(m) < 0) | |
| 517 | + goto free_channels; | |
| 458 | 518 | |
| 459 | 519 | INIT_WORK(&m->mpeg_thread, vidtv_mux_tick); |
| 460 | 520 | |
| 461 | − vidtv_mux_pid_ctx_init(m); | |
| 521 | + if (vidtv_mux_pid_ctx_init(m) < 0) | |
| 522 | + goto free_channel_si; | |
| 462 | 523 | |
| 463 | 524 | return m; |
| 525 | + | |
| 526 | +free_channel_si: | |
| 527 | + vidtv_channel_si_destroy(m); | |
| 528 | +free_channels: | |
| 529 | + vidtv_channels_destroy(m); | |
| 530 | +free_mux_buf: | |
| 531 | + vfree(m->mux_buf); | |
| 532 | +free_mux: | |
| 533 | + kfree(m); | |
| 534 | + return NULL; | |
| 464 | 535 | } |
| 465 | 536 | |
| 466 | 537 | void vidtv_mux_destroy(struct vidtv_mux *m) |
| @@ -469,6 +540,7 @@ void vidtv_mux_destroy(struct vidtv_mux *m) · 2 unmodified lines | ||
| 469 | 540 | vidtv_mux_pid_ctx_destroy(m); |
| 470 | 541 | vidtv_channel_si_destroy(m); |
| 471 | 542 | vidtv_channels_destroy(m); |
| 543 | + kfree(m->network_name); | |
| 472 | 544 | vfree(m->mux_buf); |
| 473 | 545 | kfree(m); |
| 474 | 546 | } |
| @@ -15,9 +15,10 @@ · 14 unmodified lines | ||
| 15 | 15 | #ifndef VIDTV_MUX_H |
| 16 | 16 | #define VIDTV_MUX_H |
| 17 | 17 | |
| 18 | −#include <linux/types.h> | |
| 19 | 18 | #include <linux/hashtable.h> |
| 19 | +#include <linux/types.h> | |
| 20 | 20 | #include <linux/workqueue.h> |
| 21 | + | |
| 21 | 22 | #include <media/dvb_frontend.h> |
| 22 | 23 | |
| 23 | 24 | #include "vidtv_psi.h" |
| @@ -58,12 +59,16 @@ struct vidtv_mux_timing { · 34 unmodified lines | ||
| 58 | 59 | * @pat: The PAT in use by the muxer. |
| 59 | 60 | * @pmt_secs: The PMT sections in use by the muxer. One for each program in the PAT. |
| 60 | 61 | * @sdt: The SDT in use by the muxer. |
| 62 | + * @nit: The NIT in use by the muxer. | |
| 63 | + * @eit: the EIT in use by the muxer. | |
| 61 | 64 | */ |
| 62 | 65 | struct vidtv_mux_si { |
| 63 | 66 | /* the SI tables */ |
| 64 | 67 | struct vidtv_psi_table_pat *pat; |
| 65 | 68 | struct vidtv_psi_table_pmt **pmt_secs; /* the PMT sections */ |
| 66 | 69 | struct vidtv_psi_table_sdt *sdt; |
| 70 | + struct vidtv_psi_table_nit *nit; | |
| 71 | + struct vidtv_psi_table_eit *eit; | |
| 67 | 72 | }; |
| 68 | 73 | |
| 69 | 74 | /** |
| @@ -82,8 +87,10 @@ struct vidtv_mux_pid_ctx { · 12 unmodified lines | ||
| 82 | 87 | |
| 83 | 88 | /** |
| 84 | 89 | * struct vidtv_mux - A muxer abstraction loosely based in libavcodec/mpegtsenc.c |
| 85 | − * @mux_rate_kbytes_sec: The bit rate for the TS, in kbytes. | |
| 90 | + * @fe: The frontend structure allocated by the muxer. | |
| 91 | + * @dev: pointer to struct device. | |
| 86 | 92 | * @timing: Keeps track of timing related information. |
| 93 | + * @mux_rate_kbytes_sec: The bit rate for the TS, in kbytes. | |
| 87 | 94 | * @pid_ctx: A hash table to keep track of per-PID metadata. |
| 88 | 95 | * @on_new_packets_available_cb: A callback to inform of new TS packets ready. |
| 89 | 96 | * @mux_buf: A pointer to a buffer for this muxer. TS packets are stored there |
| @@ -99,6 +106,8 @@ struct vidtv_mux_pid_ctx { · 9 unmodified lines | ||
| 99 | 106 | * @pcr_pid: The TS PID used for the PSI packets. All channels will share the |
| 100 | 107 | * same PCR. |
| 101 | 108 | * @transport_stream_id: The transport stream ID |
| 109 | + * @network_id: The network ID | |
| 110 | + * @network_name: The network name | |
| 102 | 111 | * @priv: Private data. |
| 103 | 112 | */ |
| 104 | 113 | struct vidtv_mux { |
| @@ -128,6 +137,8 @@ struct vidtv_mux { · 23 unmodified lines | ||
| 128 | 137 | |
| 129 | 138 | u16 pcr_pid; |
| 130 | 139 | u16 transport_stream_id; |
| 140 | + u16 network_id; | |
| 141 | + char *network_name; | |
| 131 | 142 | void *priv; |
| 132 | 143 | }; |
| 133 | 144 | |
| @@ -142,6 +153,8 @@ struct vidtv_mux { · 8 unmodified lines | ||
| 142 | 153 | * same PCR. |
| 143 | 154 | * @transport_stream_id: The transport stream ID |
| 144 | 155 | * @channels: an optional list of channels to use |
| 156 | + * @network_id: The network ID | |
| 157 | + * @network_name: The network name | |
| 145 | 158 | * @priv: Private data. |
| 146 | 159 | */ |
| 147 | 160 | struct vidtv_mux_init_args { |
| @@ -153,12 +166,14 @@ struct vidtv_mux_init_args { · 5 unmodified lines | ||
| 153 | 166 | u16 pcr_pid; |
| 154 | 167 | u16 transport_stream_id; |
| 155 | 168 | struct vidtv_channel *channels; |
| 169 | + u16 network_id; | |
| 170 | + char *network_name; | |
| 156 | 171 | void *priv; |
| 157 | 172 | }; |
| 158 | 173 | |
| 159 | 174 | struct vidtv_mux *vidtv_mux_init(struct dvb_frontend *fe, |
| 160 | 175 | struct device *dev, |
| 161 | − struct vidtv_mux_init_args args); | |
| 176 | + struct vidtv_mux_init_args *args); | |
| 162 | 177 | void vidtv_mux_destroy(struct vidtv_mux *m); |
| 163 | 178 | |
| 164 | 179 | void vidtv_mux_start_thread(struct vidtv_mux *m); |
| @@ -16,7 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/types.h> |
| 17 | 17 | #include <linux/printk.h> |
| 18 | 18 | #include <linux/ratelimit.h> |
| 19 | −#include <asm/byteorder.h> | |
| 20 | 19 | |
| 21 | 20 | #include "vidtv_pes.h" |
| 22 | 21 | #include "vidtv_common.h" |
| @@ -57,7 +56,7 @@ static u32 vidtv_pes_h_get_len(bool send_pts, bool send_dts) · 34 unmodified lines | ||
| 57 | 56 | return len; |
| 58 | 57 | } |
| 59 | 58 | |
| 60 | −static u32 vidtv_pes_write_header_stuffing(struct pes_header_write_args args) | |
| 59 | +static u32 vidtv_pes_write_header_stuffing(struct pes_header_write_args *args) | |
| 61 | 60 | { |
| 62 | 61 | /* |
| 63 | 62 | * This is a fixed 8-bit value equal to '0xFF' that can be inserted |
| @@ -65,20 +64,20 @@ static u32 vidtv_pes_write_header_stuffing(struct pes_header_write_args args) · 1 unmodified line | ||
| 65 | 64 | * It is discarded by the decoder. No more than 32 stuffing bytes shall |
| 66 | 65 | * be present in one PES packet header. |
| 67 | 66 | */ |
| 68 | − if (args.n_pes_h_s_bytes > PES_HEADER_MAX_STUFFING_BYTES) { | |
| 67 | + if (args->n_pes_h_s_bytes > PES_HEADER_MAX_STUFFING_BYTES) { | |
| 69 | 68 | pr_warn_ratelimited("More than %d stuffing bytes in PES packet header\n", |
| 70 | 69 | PES_HEADER_MAX_STUFFING_BYTES); |
| 71 | − args.n_pes_h_s_bytes = PES_HEADER_MAX_STUFFING_BYTES; | |
| 70 | + args->n_pes_h_s_bytes = PES_HEADER_MAX_STUFFING_BYTES; | |
| 72 | 71 | } |
| 73 | 72 | |
| 74 | − return vidtv_memset(args.dest_buf, | |
| 75 | − args.dest_offset, | |
| 76 | − args.dest_buf_sz, | |
| 73 | + return vidtv_memset(args->dest_buf, | |
| 74 | + args->dest_offset, | |
| 75 | + args->dest_buf_sz, | |
| 77 | 76 | TS_FILL_BYTE, |
| 78 | − args.n_pes_h_s_bytes); | |
| 77 | + args->n_pes_h_s_bytes); | |
| 79 | 78 | } |
| 80 | 79 | |
| 81 | −static u32 vidtv_pes_write_pts_dts(struct pes_header_write_args args) | |
| 80 | +static u32 vidtv_pes_write_pts_dts(struct pes_header_write_args *args) | |
| 82 | 81 | { |
| 83 | 82 | u32 nbytes = 0; /* the number of bytes written by this function */ |
| 84 | 83 | |
| @@ -90,7 +89,7 @@ static u32 vidtv_pes_write_pts_dts(struct pes_header_write_args args) · 5 unmodified lines | ||
| 90 | 89 | u64 mask2; |
| 91 | 90 | u64 mask3; |
| 92 | 91 | |
| 93 | − if (!args.send_pts && args.send_dts) | |
| 92 | + if (!args->send_pts && args->send_dts) | |
| 94 | 93 | return 0; |
| 95 | 94 | |
| 96 | 95 | mask1 = GENMASK_ULL(32, 30); |
| @@ -98,80 +97,81 @@ static u32 vidtv_pes_write_pts_dts(struct pes_header_write_args args) · 1 unmodified line | ||
| 98 | 97 | mask3 = GENMASK_ULL(14, 0); |
| 99 | 98 | |
| 100 | 99 | /* see ISO/IEC 13818-1 : 2000 p. 32 */ |
| 101 | − if (args.send_pts && args.send_dts) { | |
| 102 | − pts_dts.pts1 = (0x3 << 4) | ((args.pts & mask1) >> 29) | 0x1; | |
| 103 | − pts_dts.pts2 = cpu_to_be16(((args.pts & mask2) >> 14) | 0x1); | |
| 104 | − pts_dts.pts3 = cpu_to_be16(((args.pts & mask3) << 1) | 0x1); | |
| 100 | + if (args->send_pts && args->send_dts) { | |
| 101 | + pts_dts.pts1 = (0x3 << 4) | ((args->pts & mask1) >> 29) | 0x1; | |
| 102 | + pts_dts.pts2 = cpu_to_be16(((args->pts & mask2) >> 14) | 0x1); | |
| 103 | + pts_dts.pts3 = cpu_to_be16(((args->pts & mask3) << 1) | 0x1); | |
| 105 | 104 | |
| 106 | − pts_dts.dts1 = (0x1 << 4) | ((args.dts & mask1) >> 29) | 0x1; | |
| 107 | − pts_dts.dts2 = cpu_to_be16(((args.dts & mask2) >> 14) | 0x1); | |
| 108 | − pts_dts.dts3 = cpu_to_be16(((args.dts & mask3) << 1) | 0x1); | |
| 105 | + pts_dts.dts1 = (0x1 << 4) | ((args->dts & mask1) >> 29) | 0x1; | |
| 106 | + pts_dts.dts2 = cpu_to_be16(((args->dts & mask2) >> 14) | 0x1); | |
| 107 | + pts_dts.dts3 = cpu_to_be16(((args->dts & mask3) << 1) | 0x1); | |
| 109 | 108 | |
| 110 | 109 | op = &pts_dts; |
| 111 | 110 | op_sz = sizeof(pts_dts); |
| 112 | 111 | |
| 113 | − } else if (args.send_pts) { | |
| 114 | − pts.pts1 = (0x1 << 5) | ((args.pts & mask1) >> 29) | 0x1; | |
| 115 | − pts.pts2 = cpu_to_be16(((args.pts & mask2) >> 14) | 0x1); | |
| 116 | − pts.pts3 = cpu_to_be16(((args.pts & mask3) << 1) | 0x1); | |
| 112 | + } else if (args->send_pts) { | |
| 113 | + pts.pts1 = (0x1 << 5) | ((args->pts & mask1) >> 29) | 0x1; | |
| 114 | + pts.pts2 = cpu_to_be16(((args->pts & mask2) >> 14) | 0x1); | |
| 115 | + pts.pts3 = cpu_to_be16(((args->pts & mask3) << 1) | 0x1); | |
| 117 | 116 | |
| 118 | 117 | op = &pts; |
| 119 | 118 | op_sz = sizeof(pts); |
| 120 | 119 | } |
| 121 | 120 | |
| 122 | 121 | /* copy PTS/DTS optional */ |
| 123 | − nbytes += vidtv_memcpy(args.dest_buf, | |
| 124 | − args.dest_offset + nbytes, | |
| 125 | − args.dest_buf_sz, | |
| 122 | + nbytes += vidtv_memcpy(args->dest_buf, | |
| 123 | + args->dest_offset + nbytes, | |
| 124 | + args->dest_buf_sz, | |
| 126 | 125 | op, |
| 127 | 126 | op_sz); |
| 128 | 127 | |
| 129 | 128 | return nbytes; |
| 130 | 129 | } |
| 131 | 130 | |
| 132 | −static u32 vidtv_pes_write_h(struct pes_header_write_args args) | |
| 131 | +static u32 vidtv_pes_write_h(struct pes_header_write_args *args) | |
| 133 | 132 | { |
| 134 | 133 | u32 nbytes = 0; /* the number of bytes written by this function */ |
| 135 | 134 | |
| 136 | 135 | struct vidtv_mpeg_pes pes_header = {}; |
| 137 | 136 | struct vidtv_pes_optional pes_optional = {}; |
| 138 | − struct pes_header_write_args pts_dts_args = args; | |
| 139 | − u32 stream_id = (args.encoder_id == S302M) ? PRIVATE_STREAM_1_ID : args.stream_id; | |
| 137 | + struct pes_header_write_args pts_dts_args; | |
| 138 | + u32 stream_id = (args->encoder_id == S302M) ? PRIVATE_STREAM_1_ID : args->stream_id; | |
| 140 | 139 | u16 pes_opt_bitfield = 0x01 << 15; |
| 141 | 140 | |
| 142 | 141 | pes_header.bitfield = cpu_to_be32((PES_START_CODE_PREFIX << 8) | stream_id); |
| 143 | 142 | |
| 144 | − pes_header.length = cpu_to_be16(vidtv_pes_op_get_len(args.send_pts, | |
| 145 | − args.send_dts) + | |
| 146 | − args.access_unit_len); | |
| 143 | + pes_header.length = cpu_to_be16(vidtv_pes_op_get_len(args->send_pts, | |
| 144 | + args->send_dts) + | |
| 145 | + args->access_unit_len); | |
| 147 | 146 | |
| 148 | − if (args.send_pts && args.send_dts) | |
| 147 | + if (args->send_pts && args->send_dts) | |
| 149 | 148 | pes_opt_bitfield |= (0x3 << 6); |
| 150 | − else if (args.send_pts) | |
| 149 | + else if (args->send_pts) | |
| 151 | 150 | pes_opt_bitfield |= (0x1 << 7); |
| 152 | 151 | |
| 153 | 152 | pes_optional.bitfield = cpu_to_be16(pes_opt_bitfield); |
| 154 | − pes_optional.length = vidtv_pes_op_get_len(args.send_pts, args.send_dts) + | |
| 155 | − args.n_pes_h_s_bytes - | |
| 153 | + pes_optional.length = vidtv_pes_op_get_len(args->send_pts, args->send_dts) + | |
| 154 | + args->n_pes_h_s_bytes - | |
| 156 | 155 | sizeof(struct vidtv_pes_optional); |
| 157 | 156 | |
| 158 | 157 | /* copy header */ |
| 159 | − nbytes += vidtv_memcpy(args.dest_buf, | |
| 160 | − args.dest_offset + nbytes, | |
| 161 | − args.dest_buf_sz, | |
| 158 | + nbytes += vidtv_memcpy(args->dest_buf, | |
| 159 | + args->dest_offset + nbytes, | |
| 160 | + args->dest_buf_sz, | |
| 162 | 161 | &pes_header, |
| 163 | 162 | sizeof(pes_header)); |
| 164 | 163 | |
| 165 | 164 | /* copy optional header bits */ |
| 166 | − nbytes += vidtv_memcpy(args.dest_buf, | |
| 167 | − args.dest_offset + nbytes, | |
| 168 | − args.dest_buf_sz, | |
| 165 | + nbytes += vidtv_memcpy(args->dest_buf, | |
| 166 | + args->dest_offset + nbytes, | |
| 167 | + args->dest_buf_sz, | |
| 169 | 168 | &pes_optional, |
| 170 | 169 | sizeof(pes_optional)); |
| 171 | 170 | |
| 172 | 171 | /* copy the timing information */ |
| 173 | − pts_dts_args.dest_offset = args.dest_offset + nbytes; | |
| 174 | − nbytes += vidtv_pes_write_pts_dts(pts_dts_args); | |
| 172 | + pts_dts_args = *args; | |
| 173 | + pts_dts_args.dest_offset = args->dest_offset + nbytes; | |
| 174 | + nbytes += vidtv_pes_write_pts_dts(&pts_dts_args); | |
| 175 | 175 | |
| 176 | 176 | /* write any PES header stuffing */ |
| 177 | 177 | nbytes += vidtv_pes_write_header_stuffing(args); |
| @@ -300,14 +300,31 @@ static u32 vidtv_pes_write_ts_h(struct pes_ts_header_write_args args, · 122 unmodified lines | ||
| 300 | 300 | return nbytes; |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | −u32 vidtv_pes_write_into(struct pes_write_args args) | |
| 303 | +u32 vidtv_pes_write_into(struct pes_write_args *args) | |
| 304 | 304 | { |
| 305 | − u32 unaligned_bytes = (args.dest_offset % TS_PACKET_LEN); | |
| 306 | − struct pes_ts_header_write_args ts_header_args = {}; | |
| 307 | − struct pes_header_write_args pes_header_args = {}; | |
| 308 | − u32 remaining_len = args.access_unit_len; | |
| 305 | + u32 unaligned_bytes = (args->dest_offset % TS_PACKET_LEN); | |
| 306 | + struct pes_ts_header_write_args ts_header_args = { | |
| 307 | + .dest_buf = args->dest_buf, | |
| 308 | + .dest_buf_sz = args->dest_buf_sz, | |
| 309 | + .pid = args->pid, | |
| 310 | + .pcr = args->pcr, | |
| 311 | + .continuity_counter = args->continuity_counter, | |
| 312 | + }; | |
| 313 | + struct pes_header_write_args pes_header_args = { | |
| 314 | + .dest_buf = args->dest_buf, | |
| 315 | + .dest_buf_sz = args->dest_buf_sz, | |
| 316 | + .encoder_id = args->encoder_id, | |
| 317 | + .send_pts = args->send_pts, | |
| 318 | + .pts = args->pts, | |
| 319 | + .send_dts = args->send_dts, | |
| 320 | + .dts = args->dts, | |
| 321 | + .stream_id = args->stream_id, | |
| 322 | + .n_pes_h_s_bytes = args->n_pes_h_s_bytes, | |
| 323 | + .access_unit_len = args->access_unit_len, | |
| 324 | + }; | |
| 325 | + u32 remaining_len = args->access_unit_len; | |
| 309 | 326 | bool wrote_pes_header = false; |
| 310 | − u64 last_pcr = args.pcr; | |
| 327 | + u64 last_pcr = args->pcr; | |
| 311 | 328 | bool need_pcr = true; |
| 312 | 329 | u32 available_space; |
| 313 | 330 | u32 payload_size; |
| @@ -318,25 +335,13 @@ u32 vidtv_pes_write_into(struct pes_write_args args) · 4 unmodified lines | ||
| 318 | 335 | pr_warn_ratelimited("buffer is misaligned, while starting PES\n"); |
| 319 | 336 | |
| 320 | 337 | /* forcibly align and hope for the best */ |
| 321 | − nbytes += vidtv_memset(args.dest_buf, | |
| 322 | − args.dest_offset + nbytes, | |
| 323 | − args.dest_buf_sz, | |
| 338 | + nbytes += vidtv_memset(args->dest_buf, | |
| 339 | + args->dest_offset + nbytes, | |
| 340 | + args->dest_buf_sz, | |
| 324 | 341 | TS_FILL_BYTE, |
| 325 | 342 | TS_PACKET_LEN - unaligned_bytes); |
| 326 | 343 | } |
| 327 | 344 | |
| 328 | − if (args.send_dts && !args.send_pts) { | |
| 329 | − pr_warn_ratelimited("forbidden value '01' for PTS_DTS flags\n"); | |
| 330 | − args.send_pts = true; | |
| 331 | − args.pts = args.dts; | |
| 332 | − } | |
| 333 | − | |
| 334 | − /* see SMPTE 302M clause 6.4 */ | |
| 335 | − if (args.encoder_id == S302M) { | |
| 336 | − args.send_dts = false; | |
| 337 | − args.send_pts = true; | |
| 338 | − } | |
| 339 | − | |
| 340 | 345 | while (remaining_len) { |
| 341 | 346 | available_space = TS_PAYLOAD_LEN; |
| 342 | 347 | /* |
| @@ -345,14 +350,14 @@ u32 vidtv_pes_write_into(struct pes_write_args args) · 2 unmodified lines | ||
| 345 | 350 | * the space needed for the TS header _and_ for the PES header |
| 346 | 351 | */ |
| 347 | 352 | if (!wrote_pes_header) |
| 348 | − available_space -= vidtv_pes_h_get_len(args.send_pts, | |
| 349 | − args.send_dts); | |
| 353 | + available_space -= vidtv_pes_h_get_len(args->send_pts, | |
| 354 | + args->send_dts); | |
| 350 | 355 | |
| 351 | 356 | /* |
| 352 | 357 | * if the encoder has inserted stuffing bytes in the PES |
| 353 | 358 | * header, account for them. |
| 354 | 359 | */ |
| 355 | − available_space -= args.n_pes_h_s_bytes; | |
| 360 | + available_space -= args->n_pes_h_s_bytes; | |
| 356 | 361 | |
| 357 | 362 | /* Take the extra adaptation into account if need to send PCR */ |
| 358 | 363 | if (need_pcr) { |
| @@ -387,14 +392,9 @@ u32 vidtv_pes_write_into(struct pes_write_args args) · 28 unmodified lines | ||
| 387 | 392 | } |
| 388 | 393 | |
| 389 | 394 | /* write ts header */ |
| 390 | − ts_header_args.dest_buf = args.dest_buf; | |
| 391 | − ts_header_args.dest_offset = args.dest_offset + nbytes; | |
| 392 | − ts_header_args.dest_buf_sz = args.dest_buf_sz; | |
| 393 | − ts_header_args.pid = args.pid; | |
| 394 | − ts_header_args.pcr = args.pcr; | |
| 395 | − ts_header_args.continuity_counter = args.continuity_counter; | |
| 396 | − ts_header_args.wrote_pes_header = wrote_pes_header; | |
| 397 | − ts_header_args.n_stuffing_bytes = stuff_bytes; | |
| 395 | + ts_header_args.dest_offset = args->dest_offset + nbytes; | |
| 396 | + ts_header_args.wrote_pes_header = wrote_pes_header; | |
| 397 | + ts_header_args.n_stuffing_bytes = stuff_bytes; | |
| 398 | 398 | |
| 399 | 399 | nbytes += vidtv_pes_write_ts_h(ts_header_args, need_pcr, |
| 400 | 400 | &last_pcr); |
| @@ -403,33 +403,20 @@ u32 vidtv_pes_write_into(struct pes_write_args args) · 2 unmodified lines | ||
| 403 | 403 | |
| 404 | 404 | if (!wrote_pes_header) { |
| 405 | 405 | /* write the PES header only once */ |
| 406 | − pes_header_args.dest_buf = args.dest_buf; | |
| 407 | − | |
| 408 | − pes_header_args.dest_offset = args.dest_offset + | |
| 409 | − nbytes; | |
| 410 | − | |
| 411 | − pes_header_args.dest_buf_sz = args.dest_buf_sz; | |
| 412 | − pes_header_args.encoder_id = args.encoder_id; | |
| 413 | − pes_header_args.send_pts = args.send_pts; | |
| 414 | − pes_header_args.pts = args.pts; | |
| 415 | − pes_header_args.send_dts = args.send_dts; | |
| 416 | − pes_header_args.dts = args.dts; | |
| 417 | − pes_header_args.stream_id = args.stream_id; | |
| 418 | − pes_header_args.n_pes_h_s_bytes = args.n_pes_h_s_bytes; | |
| 419 | − pes_header_args.access_unit_len = args.access_unit_len; | |
| 420 | − | |
| 421 | − nbytes += vidtv_pes_write_h(pes_header_args); | |
| 422 | − wrote_pes_header = true; | |
| 406 | + pes_header_args.dest_offset = args->dest_offset + | |
| 407 | + nbytes; | |
| 408 | + nbytes += vidtv_pes_write_h(&pes_header_args); | |
| 409 | + wrote_pes_header = true; | |
| 423 | 410 | } |
| 424 | 411 | |
| 425 | 412 | /* write as much of the payload as we possibly can */ |
| 426 | − nbytes += vidtv_memcpy(args.dest_buf, | |
| 427 | − args.dest_offset + nbytes, | |
| 428 | − args.dest_buf_sz, | |
| 429 | − args.from, | |
| 413 | + nbytes += vidtv_memcpy(args->dest_buf, | |
| 414 | + args->dest_offset + nbytes, | |
| 415 | + args->dest_buf_sz, | |
| 416 | + args->from, | |
| 430 | 417 | payload_size); |
| 431 | 418 | |
| 432 | − args.from += payload_size; | |
| 419 | + args->from += payload_size; | |
| 433 | 420 | |
| 434 | 421 | remaining_len -= payload_size; |
| 435 | 422 | } |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #ifndef VIDTV_PES_H |
| 15 | 15 | #define VIDTV_PES_H |
| 16 | 16 | |
| 17 | −#include <asm/byteorder.h> | |
| 18 | 17 | #include <linux/types.h> |
| 19 | 18 | |
| 20 | 19 | #include "vidtv_common.h" |
| @@ -114,8 +113,10 @@ struct pes_header_write_args { · 93 unmodified lines | ||
| 114 | 113 | * @dest_buf_sz: The size of the dest_buffer |
| 115 | 114 | * @pid: The PID to use for the TS packets. |
| 116 | 115 | * @continuity_counter: Incremented on every new TS packet. |
| 117 | − * @n_pes_h_s_bytes: Padding bytes. Might be used by an encoder if needed, gets | |
| 116 | + * @wrote_pes_header: Flag to indicate that the PES header was written | |
| 117 | + * @n_stuffing_bytes: Padding bytes. Might be used by an encoder if needed, gets | |
| 118 | 118 | * discarded by the decoder. |
| 119 | + * @pcr: counter driven by a 27Mhz clock. | |
| 119 | 120 | */ |
| 120 | 121 | struct pes_ts_header_write_args { |
| 121 | 122 | void *dest_buf; |
| @@ -146,6 +147,7 @@ struct pes_ts_header_write_args { · 24 unmodified lines | ||
| 146 | 147 | * @dts: DTS value to send. |
| 147 | 148 | * @n_pes_h_s_bytes: Padding bytes. Might be used by an encoder if needed, gets |
| 148 | 149 | * discarded by the decoder. |
| 150 | + * @pcr: counter driven by a 27Mhz clock. | |
| 149 | 151 | */ |
| 150 | 152 | struct pes_write_args { |
| 151 | 153 | void *dest_buf; |
| @@ -186,6 +188,6 @@ struct pes_write_args { · 34 unmodified lines | ||
| 186 | 188 | * equal to the size of the access unit, since we need space for PES headers, TS headers |
| 187 | 189 | * and padding bytes, if any. |
| 188 | 190 | */ |
| 189 | −u32 vidtv_pes_write_into(struct pes_write_args args); | |
| 191 | +u32 vidtv_pes_write_into(struct pes_write_args *args); | |
| 190 | 192 | |
| 191 | 193 | #endif // VIDTV_PES_H |
| @@ -6,31 +6,31 @@ · 5 unmodified lines | ||
| 6 | 6 | * technically be broken into one or more sections, we do not do this here, |
| 7 | 7 | * hence 'table' and 'section' are interchangeable for vidtv. |
| 8 | 8 | * |
| 9 | − * This code currently supports three tables: PAT, PMT and SDT. These are the | |
| 10 | − * bare minimum to get userspace to recognize our MPEG transport stream. It can | |
| 11 | − * be extended to support more PSI tables in the future. | |
| 12 | − * | |
| 13 | 9 | * Copyright (C) 2020 Daniel W. S. Almeida |
| 14 | 10 | */ |
| 15 | 11 | |
| 16 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s, %d: " fmt, __func__, __LINE__ |
| 17 | 13 | |
| 18 | −#include <linux/kernel.h> | |
| 19 | −#include <linux/types.h> | |
| 20 | −#include <linux/slab.h> | |
| 14 | +#include <linux/bcd.h> | |
| 21 | 15 | #include <linux/crc32.h> |
| 22 | −#include <linux/string.h> | |
| 16 | +#include <linux/kernel.h> | |
| 17 | +#include <linux/ktime.h> | |
| 23 | 18 | #include <linux/printk.h> |
| 24 | 19 | #include <linux/ratelimit.h> |
| 20 | +#include <linux/slab.h> | |
| 25 | 21 | #include <linux/string.h> |
| 26 | −#include <asm/byteorder.h> | |
| 22 | +#include <linux/string.h> | |
| 23 | +#include <linux/time.h> | |
| 24 | +#include <linux/types.h> | |
| 27 | 25 | |
| 28 | −#include "vidtv_psi.h" | |
| 29 | 26 | #include "vidtv_common.h" |
| 27 | +#include "vidtv_psi.h" | |
| 30 | 28 | #include "vidtv_ts.h" |
| 31 | 29 | |
| 32 | 30 | #define CRC_SIZE_IN_BYTES 4 |
| 33 | 31 | #define MAX_VERSION_NUM 32 |
| 32 | +#define INITIAL_CRC 0xffffffff | |
| 33 | +#define ISO_LANGUAGE_CODE_LEN 3 | |
| 34 | 34 | |
| 35 | 35 | static const u32 CRC_LUT[256] = { |
| 36 | 36 | /* from libdvbv5 */ |
| @@ -79,7 +79,7 @@ static const u32 CRC_LUT[256] = { · 42 unmodified lines | ||
| 79 | 79 | 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 |
| 80 | 80 | }; |
| 81 | 81 | |
| 82 | −static inline u32 dvb_crc32(u32 crc, u8 *data, u32 len) | |
| 82 | +static u32 dvb_crc32(u32 crc, u8 *data, u32 len) | |
| 83 | 83 | { |
| 84 | 84 | /* from libdvbv5 */ |
| 85 | 85 | while (len--) |
| @@ -92,40 +92,7 @@ static void vidtv_psi_update_version_num(struct vidtv_psi_table_header *h) · 6 unmodified lines | ||
| 92 | 92 | h->version++; |
| 93 | 93 | } |
| 94 | 94 | |
| 95 | −static inline u16 vidtv_psi_sdt_serv_get_desc_loop_len(struct vidtv_psi_table_sdt_service *s) | |
| 96 | −{ | |
| 97 | − u16 mask; | |
| 98 | − u16 ret; | |
| 99 | − | |
| 100 | − mask = GENMASK(11, 0); | |
| 101 | − | |
| 102 | − ret = be16_to_cpu(s->bitfield) & mask; | |
| 103 | − return ret; | |
| 104 | −} | |
| 105 | − | |
| 106 | −static inline u16 vidtv_psi_pmt_stream_get_desc_loop_len(struct vidtv_psi_table_pmt_stream *s) | |
| 107 | −{ | |
| 108 | − u16 mask; | |
| 109 | − u16 ret; | |
| 110 | − | |
| 111 | − mask = GENMASK(9, 0); | |
| 112 | − | |
| 113 | − ret = be16_to_cpu(s->bitfield2) & mask; | |
| 114 | − return ret; | |
| 115 | −} | |
| 116 | − | |
| 117 | −static inline u16 vidtv_psi_pmt_get_desc_loop_len(struct vidtv_psi_table_pmt *p) | |
| 118 | −{ | |
| 119 | − u16 mask; | |
| 120 | − u16 ret; | |
| 121 | − | |
| 122 | − mask = GENMASK(9, 0); | |
| 123 | − | |
| 124 | − ret = be16_to_cpu(p->bitfield2) & mask; | |
| 125 | − return ret; | |
| 126 | −} | |
| 127 | − | |
| 128 | −static inline u16 vidtv_psi_get_sec_len(struct vidtv_psi_table_header *h) | |
| 95 | +static u16 vidtv_psi_get_sec_len(struct vidtv_psi_table_header *h) | |
| 129 | 96 | { |
| 130 | 97 | u16 mask; |
| 131 | 98 | u16 ret; |
| @@ -136,7 +103,7 @@ static inline u16 vidtv_psi_get_sec_len(struct vidtv_psi_table_header *h) · 4 unmodified lines | ||
| 136 | 103 | return ret; |
| 137 | 104 | } |
| 138 | 105 | |
| 139 | −inline u16 vidtv_psi_get_pat_program_pid(struct vidtv_psi_table_pat_program *p) | |
| 106 | +u16 vidtv_psi_get_pat_program_pid(struct vidtv_psi_table_pat_program *p) | |
| 140 | 107 | { |
| 141 | 108 | u16 mask; |
| 142 | 109 | u16 ret; |
| @@ -147,7 +114,7 @@ inline u16 vidtv_psi_get_pat_program_pid(struct vidtv_psi_table_pat_program *p) · 4 unmodified lines | ||
| 147 | 114 | return ret; |
| 148 | 115 | } |
| 149 | 116 | |
| 150 | −inline u16 vidtv_psi_pmt_stream_get_elem_pid(struct vidtv_psi_table_pmt_stream *s) | |
| 117 | +u16 vidtv_psi_pmt_stream_get_elem_pid(struct vidtv_psi_table_pmt_stream *s) | |
| 151 | 118 | { |
| 152 | 119 | u16 mask; |
| 153 | 120 | u16 ret; |
| @@ -158,10 +125,11 @@ inline u16 vidtv_psi_pmt_stream_get_elem_pid(struct vidtv_psi_table_pmt_stream * · 4 unmodified lines | ||
| 158 | 125 | return ret; |
| 159 | 126 | } |
| 160 | 127 | |
| 161 | −static inline void vidtv_psi_set_desc_loop_len(__be16 *bitfield, u16 new_len, u8 desc_len_nbits) | |
| 128 | +static void vidtv_psi_set_desc_loop_len(__be16 *bitfield, u16 new_len, | |
| 129 | + u8 desc_len_nbits) | |
| 162 | 130 | { |
| 163 | − u16 mask; | |
| 164 | 131 | __be16 new; |
| 132 | + u16 mask; | |
| 165 | 133 | |
| 166 | 134 | mask = GENMASK(15, desc_len_nbits); |
| 167 | 135 | |
| @@ -188,90 +156,81 @@ static void vidtv_psi_set_sec_len(struct vidtv_psi_table_header *h, u16 new_len) · 20 unmodified lines | ||
| 188 | 156 | h->bitfield = new; |
| 189 | 157 | } |
| 190 | 158 | |
| 191 | −static u32 vidtv_psi_ts_psi_write_into(struct psi_write_args args) | |
| 159 | +/* | |
| 160 | + * Packetize PSI sections into TS packets: | |
| 161 | + * push a TS header (4bytes) every 184 bytes | |
| 162 | + * manage the continuity_counter | |
| 163 | + * add stuffing (i.e. padding bytes) after the CRC | |
| 164 | + */ | |
| 165 | +static u32 vidtv_psi_ts_psi_write_into(struct psi_write_args *args) | |
| 192 | 166 | { |
| 193 | − /* | |
| 194 | − * Packetize PSI sections into TS packets: | |
| 195 | − * push a TS header (4bytes) every 184 bytes | |
| 196 | − * manage the continuity_counter | |
| 197 | − * add stuffing (i.e. padding bytes) after the CRC | |
| 198 | − */ | |
| 199 | − | |
| 200 | − u32 nbytes_past_boundary = (args.dest_offset % TS_PACKET_LEN); | |
| 167 | + struct vidtv_mpeg_ts ts_header = { | |
| 168 | + .sync_byte = TS_SYNC_BYTE, | |
| 169 | + .bitfield = cpu_to_be16((args->new_psi_section << 14) | args->pid), | |
| 170 | + .scrambling = 0, | |
| 171 | + .payload = 1, | |
| 172 | + .adaptation_field = 0, /* no adaptation field */ | |
| 173 | + }; | |
| 174 | + u32 nbytes_past_boundary = (args->dest_offset % TS_PACKET_LEN); | |
| 201 | 175 | bool aligned = (nbytes_past_boundary == 0); |
| 202 | − struct vidtv_mpeg_ts ts_header = {}; | |
| 203 | − | |
| 204 | − /* number of bytes written by this function */ | |
| 205 | − u32 nbytes = 0; | |
| 206 | − /* how much there is left to write */ | |
| 207 | − u32 remaining_len = args.len; | |
| 208 | − /* how much we can be written in this packet */ | |
| 176 | + u32 remaining_len = args->len; | |
| 209 | 177 | u32 payload_write_len = 0; |
| 210 | − /* where we are in the source */ | |
| 211 | 178 | u32 payload_offset = 0; |
| 179 | + u32 nbytes = 0; | |
| 212 | 180 | |
| 213 | − const u16 PAYLOAD_START = args.new_psi_section; | |
| 214 | − | |
| 215 | − if (!args.crc && !args.is_crc) | |
| 181 | + if (!args->crc && !args->is_crc) | |
| 216 | 182 | pr_warn_ratelimited("Missing CRC for chunk\n"); |
| 217 | 183 | |
| 218 | − if (args.crc) | |
| 219 | − *args.crc = dvb_crc32(*args.crc, args.from, args.len); | |
| 184 | + if (args->crc) | |
| 185 | + *args->crc = dvb_crc32(*args->crc, args->from, args->len); | |
| 220 | 186 | |
| 221 | − if (args.new_psi_section && !aligned) { | |
| 187 | + if (args->new_psi_section && !aligned) { | |
| 222 | 188 | pr_warn_ratelimited("Cannot write a new PSI section in a misaligned buffer\n"); |
| 223 | 189 | |
| 224 | 190 | /* forcibly align and hope for the best */ |
| 225 | − nbytes += vidtv_memset(args.dest_buf, | |
| 226 | − args.dest_offset + nbytes, | |
| 227 | − args.dest_buf_sz, | |
| 191 | + nbytes += vidtv_memset(args->dest_buf, | |
| 192 | + args->dest_offset + nbytes, | |
| 193 | + args->dest_buf_sz, | |
| 228 | 194 | TS_FILL_BYTE, |
| 229 | 195 | TS_PACKET_LEN - nbytes_past_boundary); |
| 230 | 196 | } |
| 231 | 197 | |
| 232 | 198 | while (remaining_len) { |
| 233 | − nbytes_past_boundary = (args.dest_offset + nbytes) % TS_PACKET_LEN; | |
| 199 | + nbytes_past_boundary = (args->dest_offset + nbytes) % TS_PACKET_LEN; | |
| 234 | 200 | aligned = (nbytes_past_boundary == 0); |
| 235 | 201 | |
| 236 | 202 | if (aligned) { |
| 237 | 203 | /* if at a packet boundary, write a new TS header */ |
| 238 | − ts_header.sync_byte = TS_SYNC_BYTE; | |
| 239 | − ts_header.bitfield = cpu_to_be16((PAYLOAD_START << 14) | args.pid); | |
| 240 | − ts_header.scrambling = 0; | |
| 241 | − ts_header.continuity_counter = *args.continuity_counter; | |
| 242 | − ts_header.payload = 1; | |
| 243 | − /* no adaptation field */ | |
| 244 | − ts_header.adaptation_field = 0; | |
| 245 | − | |
| 246 | − /* copy the header */ | |
| 247 | − nbytes += vidtv_memcpy(args.dest_buf, | |
| 248 | − args.dest_offset + nbytes, | |
| 249 | − args.dest_buf_sz, | |
| 204 | + ts_header.continuity_counter = *args->continuity_counter; | |
| 205 | + | |
| 206 | + nbytes += vidtv_memcpy(args->dest_buf, | |
| 207 | + args->dest_offset + nbytes, | |
| 208 | + args->dest_buf_sz, | |
| 250 | 209 | &ts_header, |
| 251 | 210 | sizeof(ts_header)); |
| 252 | 211 | /* |
| 253 | 212 | * This will trigger a discontinuity if the buffer is full, |
| 254 | 213 | * effectively dropping the packet. |
| 255 | 214 | */ |
| 256 | − vidtv_ts_inc_cc(args.continuity_counter); | |
| 215 | + vidtv_ts_inc_cc(args->continuity_counter); | |
| 257 | 216 | } |
| 258 | 217 | |
| 259 | 218 | /* write the pointer_field in the first byte of the payload */ |
| 260 | − if (args.new_psi_section) | |
| 261 | − nbytes += vidtv_memset(args.dest_buf, | |
| 262 | − args.dest_offset + nbytes, | |
| 263 | − args.dest_buf_sz, | |
| 219 | + if (args->new_psi_section) | |
| 220 | + nbytes += vidtv_memset(args->dest_buf, | |
| 221 | + args->dest_offset + nbytes, | |
| 222 | + args->dest_buf_sz, | |
| 264 | 223 | 0x0, |
| 265 | 224 | 1); |
| 266 | 225 | |
| 267 | 226 | /* write as much of the payload as possible */ |
| 268 | − nbytes_past_boundary = (args.dest_offset + nbytes) % TS_PACKET_LEN; | |
| 227 | + nbytes_past_boundary = (args->dest_offset + nbytes) % TS_PACKET_LEN; | |
| 269 | 228 | payload_write_len = min(TS_PACKET_LEN - nbytes_past_boundary, remaining_len); |
| 270 | 229 | |
| 271 | − nbytes += vidtv_memcpy(args.dest_buf, | |
| 272 | − args.dest_offset + nbytes, | |
| 273 | − args.dest_buf_sz, | |
| 274 | − args.from + payload_offset, | |
| 230 | + nbytes += vidtv_memcpy(args->dest_buf, | |
| 231 | + args->dest_offset + nbytes, | |
| 232 | + args->dest_buf_sz, | |
| 233 | + args->from + payload_offset, | |
| 275 | 234 | payload_write_len); |
| 276 | 235 | |
| 277 | 236 | /* 'payload_write_len' written from a total of 'len' requested*/ |
| @@ -283,37 +242,45 @@ static u32 vidtv_psi_ts_psi_write_into(struct psi_write_args args) · 5 unmodified lines | ||
| 283 | 242 | * fill the rest of the packet if there is any remaining space unused |
| 284 | 243 | */ |
| 285 | 244 | |
| 286 | − nbytes_past_boundary = (args.dest_offset + nbytes) % TS_PACKET_LEN; | |
| 245 | + nbytes_past_boundary = (args->dest_offset + nbytes) % TS_PACKET_LEN; | |
| 287 | 246 | |
| 288 | − if (args.is_crc) | |
| 289 | − nbytes += vidtv_memset(args.dest_buf, | |
| 290 | − args.dest_offset + nbytes, | |
| 291 | − args.dest_buf_sz, | |
| 247 | + if (args->is_crc) | |
| 248 | + nbytes += vidtv_memset(args->dest_buf, | |
| 249 | + args->dest_offset + nbytes, | |
| 250 | + args->dest_buf_sz, | |
| 292 | 251 | TS_FILL_BYTE, |
| 293 | 252 | TS_PACKET_LEN - nbytes_past_boundary); |
| 294 | 253 | |
| 295 | 254 | return nbytes; |
| 296 | 255 | } |
| 297 | 256 | |
| 298 | −static u32 table_section_crc32_write_into(struct crc32_write_args args) | |
| 257 | +static u32 table_section_crc32_write_into(struct crc32_write_args *args) | |
| 299 | 258 | { |
| 259 | + struct psi_write_args psi_args = { | |
| 260 | + .dest_buf = args->dest_buf, | |
| 261 | + .from = &args->crc, | |
| 262 | + .len = CRC_SIZE_IN_BYTES, | |
| 263 | + .dest_offset = args->dest_offset, | |
| 264 | + .pid = args->pid, | |
| 265 | + .new_psi_section = false, | |
| 266 | + .continuity_counter = args->continuity_counter, | |
| 267 | + .is_crc = true, | |
| 268 | + .dest_buf_sz = args->dest_buf_sz, | |
| 269 | + }; | |
| 270 | + | |
| 300 | 271 | /* the CRC is the last entry in the section */ |
| 301 | − u32 nbytes = 0; | |
| 302 | − struct psi_write_args psi_args = {}; | |
| 303 | 272 | |
| 304 | − psi_args.dest_buf = args.dest_buf; | |
| 305 | − psi_args.from = &args.crc; | |
| 306 | − psi_args.len = CRC_SIZE_IN_BYTES; | |
| 307 | − psi_args.dest_offset = args.dest_offset; | |
| 308 | − psi_args.pid = args.pid; | |
| 309 | − psi_args.new_psi_section = false; | |
| 310 | − psi_args.continuity_counter = args.continuity_counter; | |
| 311 | − psi_args.is_crc = true; | |
| 312 | − psi_args.dest_buf_sz = args.dest_buf_sz; | |
| 273 | + return vidtv_psi_ts_psi_write_into(&psi_args); | |
| 274 | +} | |
| 313 | 275 | |
| 314 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 276 | +static void vidtv_psi_desc_chain(struct vidtv_psi_desc *head, struct vidtv_psi_desc *desc) | |
| 277 | +{ | |
| 278 | + if (head) { | |
| 279 | + while (head->next) | |
| 280 | + head = head->next; | |
| 315 | 281 | |
| 316 | − return nbytes; | |
| 282 | + head->next = desc; | |
| 283 | + } | |
| 317 | 284 | } |
| 318 | 285 | |
| 319 | 286 | struct vidtv_psi_desc_service *vidtv_psi_service_desc_init(struct vidtv_psi_desc *head, |
| @@ -326,6 +293,8 @@ struct vidtv_psi_desc_service *vidtv_psi_service_desc_init(struct vidtv_psi_desc · 6 unmodified lines | ||
| 326 | 293 | u32 provider_name_len = provider_name ? strlen(provider_name) : 0; |
| 327 | 294 | |
| 328 | 295 | desc = kzalloc(sizeof(*desc), GFP_KERNEL); |
| 296 | + if (!desc) | |
| 297 | + return NULL; | |
| 329 | 298 | |
| 330 | 299 | desc->type = SERVICE_DESCRIPTOR; |
| 331 | 300 | |
| @@ -347,12 +316,7 @@ struct vidtv_psi_desc_service *vidtv_psi_service_desc_init(struct vidtv_psi_desc · 15 unmodified lines | ||
| 347 | 316 | if (provider_name && provider_name_len) |
| 348 | 317 | desc->provider_name = kstrdup(provider_name, GFP_KERNEL); |
| 349 | 318 | |
| 350 | − if (head) { | |
| 351 | − while (head->next) | |
| 352 | − head = head->next; | |
| 353 | − | |
| 354 | − head->next = (struct vidtv_psi_desc *)desc; | |
| 355 | − } | |
| 319 | + vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc); | |
| 356 | 320 | return desc; |
| 357 | 321 | } |
| 358 | 322 | |
| @@ -365,6 +329,8 @@ struct vidtv_psi_desc_registration · 6 unmodified lines | ||
| 365 | 329 | struct vidtv_psi_desc_registration *desc; |
| 366 | 330 | |
| 367 | 331 | desc = kzalloc(sizeof(*desc) + sizeof(format_id) + additional_info_len, GFP_KERNEL); |
| 332 | + if (!desc) | |
| 333 | + return NULL; | |
| 368 | 334 | |
| 369 | 335 | desc->type = REGISTRATION_DESCRIPTOR; |
| 370 | 336 | |
| @@ -378,44 +344,178 @@ struct vidtv_psi_desc_registration · 7 unmodified lines | ||
| 378 | 344 | additional_ident_info, |
| 379 | 345 | additional_info_len); |
| 380 | 346 | |
| 381 | − if (head) { | |
| 382 | − while (head->next) | |
| 383 | − head = head->next; | |
| 347 | + vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc); | |
| 348 | + return desc; | |
| 349 | +} | |
| 384 | 350 | |
| 385 | − head->next = (struct vidtv_psi_desc *)desc; | |
| 351 | +struct vidtv_psi_desc_network_name | |
| 352 | +*vidtv_psi_network_name_desc_init(struct vidtv_psi_desc *head, char *network_name) | |
| 353 | +{ | |
| 354 | + u32 network_name_len = network_name ? strlen(network_name) : 0; | |
| 355 | + struct vidtv_psi_desc_network_name *desc; | |
| 356 | + | |
| 357 | + desc = kzalloc(sizeof(*desc), GFP_KERNEL); | |
| 358 | + if (!desc) | |
| 359 | + return NULL; | |
| 360 | + | |
| 361 | + desc->type = NETWORK_NAME_DESCRIPTOR; | |
| 362 | + | |
| 363 | + desc->length = network_name_len; | |
| 364 | + | |
| 365 | + if (network_name && network_name_len) | |
| 366 | + desc->network_name = kstrdup(network_name, GFP_KERNEL); | |
| 367 | + | |
| 368 | + vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc); | |
| 369 | + return desc; | |
| 370 | +} | |
| 371 | + | |
| 372 | +struct vidtv_psi_desc_service_list | |
| 373 | +*vidtv_psi_service_list_desc_init(struct vidtv_psi_desc *head, | |
| 374 | + struct vidtv_psi_desc_service_list_entry *entry) | |
| 375 | +{ | |
| 376 | + struct vidtv_psi_desc_service_list_entry *curr_e = NULL; | |
| 377 | + struct vidtv_psi_desc_service_list_entry *head_e = NULL; | |
| 378 | + struct vidtv_psi_desc_service_list_entry *prev_e = NULL; | |
| 379 | + struct vidtv_psi_desc_service_list *desc; | |
| 380 | + u16 length = 0; | |
| 381 | + | |
| 382 | + desc = kzalloc(sizeof(*desc), GFP_KERNEL); | |
| 383 | + if (!desc) | |
| 384 | + return NULL; | |
| 385 | + | |
| 386 | + desc->type = SERVICE_LIST_DESCRIPTOR; | |
| 387 | + | |
| 388 | + while (entry) { | |
| 389 | + curr_e = kzalloc(sizeof(*curr_e), GFP_KERNEL); | |
| 390 | + if (!curr_e) { | |
| 391 | + while (head_e) { | |
| 392 | + curr_e = head_e; | |
| 393 | + head_e = head_e->next; | |
| 394 | + kfree(curr_e); | |
| 395 | + } | |
| 396 | + kfree(desc); | |
| 397 | + return NULL; | |
| 398 | + } | |
| 399 | + | |
| 400 | + curr_e->service_id = entry->service_id; | |
| 401 | + curr_e->service_type = entry->service_type; | |
| 402 | + | |
| 403 | + length += sizeof(struct vidtv_psi_desc_service_list_entry) - | |
| 404 | + sizeof(struct vidtv_psi_desc_service_list_entry *); | |
| 405 | + | |
| 406 | + if (!head_e) | |
| 407 | + head_e = curr_e; | |
| 408 | + if (prev_e) | |
| 409 | + prev_e->next = curr_e; | |
| 410 | + | |
| 411 | + prev_e = curr_e; | |
| 412 | + entry = entry->next; | |
| 386 | 413 | } |
| 387 | 414 | |
| 415 | + desc->length = length; | |
| 416 | + desc->service_list = head_e; | |
| 417 | + | |
| 418 | + vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc); | |
| 419 | + return desc; | |
| 420 | +} | |
| 421 | + | |
| 422 | +struct vidtv_psi_desc_short_event | |
| 423 | +*vidtv_psi_short_event_desc_init(struct vidtv_psi_desc *head, | |
| 424 | + char *iso_language_code, | |
| 425 | + char *event_name, | |
| 426 | + char *text) | |
| 427 | +{ | |
| 428 | + u32 iso_len = iso_language_code ? strlen(iso_language_code) : 0; | |
| 429 | + u32 event_name_len = event_name ? strlen(event_name) : 0; | |
| 430 | + struct vidtv_psi_desc_short_event *desc; | |
| 431 | + u32 text_len = text ? strlen(text) : 0; | |
| 432 | + | |
| 433 | + desc = kzalloc(sizeof(*desc), GFP_KERNEL); | |
| 434 | + if (!desc) | |
| 435 | + return NULL; | |
| 436 | + | |
| 437 | + desc->type = SHORT_EVENT_DESCRIPTOR; | |
| 438 | + | |
| 439 | + desc->length = ISO_LANGUAGE_CODE_LEN + | |
| 440 | + sizeof_field(struct vidtv_psi_desc_short_event, event_name_len) + | |
| 441 | + event_name_len + | |
| 442 | + sizeof_field(struct vidtv_psi_desc_short_event, text_len) + | |
| 443 | + text_len; | |
| 444 | + | |
| 445 | + desc->event_name_len = event_name_len; | |
| 446 | + desc->text_len = text_len; | |
| 447 | + | |
| 448 | + if (iso_len != ISO_LANGUAGE_CODE_LEN) | |
| 449 | + iso_language_code = "eng"; | |
| 450 | + | |
| 451 | + desc->iso_language_code = kstrdup(iso_language_code, GFP_KERNEL); | |
| 452 | + | |
| 453 | + if (event_name && event_name_len) | |
| 454 | + desc->event_name = kstrdup(event_name, GFP_KERNEL); | |
| 455 | + | |
| 456 | + if (text && text_len) | |
| 457 | + desc->text = kstrdup(text, GFP_KERNEL); | |
| 458 | + | |
| 459 | + vidtv_psi_desc_chain(head, (struct vidtv_psi_desc *)desc); | |
| 388 | 460 | return desc; |
| 389 | 461 | } |
| 390 | 462 | |
| 391 | 463 | struct vidtv_psi_desc *vidtv_psi_desc_clone(struct vidtv_psi_desc *desc) |
| 392 | 464 | { |
| 465 | + struct vidtv_psi_desc_network_name *desc_network_name; | |
| 466 | + struct vidtv_psi_desc_service_list *desc_service_list; | |
| 467 | + struct vidtv_psi_desc_short_event *desc_short_event; | |
| 468 | + struct vidtv_psi_desc_service *service; | |
| 393 | 469 | struct vidtv_psi_desc *head = NULL; |
| 394 | 470 | struct vidtv_psi_desc *prev = NULL; |
| 395 | 471 | struct vidtv_psi_desc *curr = NULL; |
| 396 | 472 | |
| 397 | − struct vidtv_psi_desc_service *service; | |
| 398 | − | |
| 399 | 473 | while (desc) { |
| 400 | 474 | switch (desc->type) { |
| 401 | 475 | case SERVICE_DESCRIPTOR: |
| 402 | 476 | service = (struct vidtv_psi_desc_service *)desc; |
| 403 | 477 | curr = (struct vidtv_psi_desc *) |
| 404 | − vidtv_psi_service_desc_init(head, | |
| 405 | − service->service_type, | |
| 406 | − service->service_name, | |
| 407 | − service->provider_name); | |
| 478 | + vidtv_psi_service_desc_init(head, | |
| 479 | + service->service_type, | |
| 480 | + service->service_name, | |
| 481 | + service->provider_name); | |
| 482 | + break; | |
| 483 | + | |
| 484 | + case NETWORK_NAME_DESCRIPTOR: | |
| 485 | + desc_network_name = (struct vidtv_psi_desc_network_name *)desc; | |
| 486 | + curr = (struct vidtv_psi_desc *) | |
| 487 | + vidtv_psi_network_name_desc_init(head, | |
| 488 | + desc_network_name->network_name); | |
| 489 | + break; | |
| 490 | + | |
| 491 | + case SERVICE_LIST_DESCRIPTOR: | |
| 492 | + desc_service_list = (struct vidtv_psi_desc_service_list *)desc; | |
| 493 | + curr = (struct vidtv_psi_desc *) | |
| 494 | + vidtv_psi_service_list_desc_init(head, | |
| 495 | + desc_service_list->service_list); | |
| 496 | + break; | |
| 497 | + | |
| 498 | + case SHORT_EVENT_DESCRIPTOR: | |
| 499 | + desc_short_event = (struct vidtv_psi_desc_short_event *)desc; | |
| 500 | + curr = (struct vidtv_psi_desc *) | |
| 501 | + vidtv_psi_short_event_desc_init(head, | |
| 502 | + desc_short_event->iso_language_code, | |
| 503 | + desc_short_event->event_name, | |
| 504 | + desc_short_event->text); | |
| 408 | 505 | break; |
| 409 | 506 | |
| 410 | 507 | case REGISTRATION_DESCRIPTOR: |
| 411 | 508 | default: |
| 412 | 509 | curr = kzalloc(sizeof(*desc) + desc->length, GFP_KERNEL); |
| 510 | + if (!curr) | |
| 511 | + return NULL; | |
| 413 | 512 | memcpy(curr, desc, sizeof(*desc) + desc->length); |
| 414 | − break; | |
| 415 | − } | |
| 513 | + } | |
| 416 | 514 | |
| 417 | − if (curr) | |
| 418 | − curr->next = NULL; | |
| 515 | + if (!curr) | |
| 516 | + return NULL; | |
| 517 | + | |
| 518 | + curr->next = NULL; | |
| 419 | 519 | if (!head) |
| 420 | 520 | head = curr; |
| 421 | 521 | if (prev) |
| @@ -430,6 +530,8 @@ struct vidtv_psi_desc *vidtv_psi_desc_clone(struct vidtv_psi_desc *desc) · 8 unmodified lines | ||
| 430 | 530 | |
| 431 | 531 | void vidtv_psi_desc_destroy(struct vidtv_psi_desc *desc) |
| 432 | 532 | { |
| 533 | + struct vidtv_psi_desc_service_list_entry *sl_entry_tmp = NULL; | |
| 534 | + struct vidtv_psi_desc_service_list_entry *sl_entry = NULL; | |
| 433 | 535 | struct vidtv_psi_desc *curr = desc; |
| 434 | 536 | struct vidtv_psi_desc *tmp = NULL; |
| 435 | 537 | |
| @@ -447,6 +549,25 @@ void vidtv_psi_desc_destroy(struct vidtv_psi_desc *desc) · 11 unmodified lines | ||
| 447 | 549 | /* nothing to do */ |
| 448 | 550 | break; |
| 449 | 551 | |
| 552 | + case NETWORK_NAME_DESCRIPTOR: | |
| 553 | + kfree(((struct vidtv_psi_desc_network_name *)tmp)->network_name); | |
| 554 | + break; | |
| 555 | + | |
| 556 | + case SERVICE_LIST_DESCRIPTOR: | |
| 557 | + sl_entry = ((struct vidtv_psi_desc_service_list *)tmp)->service_list; | |
| 558 | + while (sl_entry) { | |
| 559 | + sl_entry_tmp = sl_entry; | |
| 560 | + sl_entry = sl_entry->next; | |
| 561 | + kfree(sl_entry_tmp); | |
| 562 | + } | |
| 563 | + break; | |
| 564 | + | |
| 565 | + case SHORT_EVENT_DESCRIPTOR: | |
| 566 | + kfree(((struct vidtv_psi_desc_short_event *)tmp)->iso_language_code); | |
| 567 | + kfree(((struct vidtv_psi_desc_short_event *)tmp)->event_name); | |
| 568 | + kfree(((struct vidtv_psi_desc_short_event *)tmp)->text); | |
| 569 | + break; | |
| 570 | + | |
| 450 | 571 | default: |
| 451 | 572 | pr_warn_ratelimited("Possible leak: not handling descriptor type %d\n", |
| 452 | 573 | tmp->type); |
| @@ -513,63 +634,119 @@ void vidtv_sdt_desc_assign(struct vidtv_psi_table_sdt *sdt, · 60 unmodified lines | ||
| 513 | 634 | vidtv_psi_update_version_num(&sdt->header); |
| 514 | 635 | } |
| 515 | 636 | |
| 516 | −static u32 vidtv_psi_desc_write_into(struct desc_write_args args) | |
| 637 | +static u32 vidtv_psi_desc_write_into(struct desc_write_args *args) | |
| 517 | 638 | { |
| 518 | − /* the number of bytes written by this function */ | |
| 639 | + struct psi_write_args psi_args = { | |
| 640 | + .dest_buf = args->dest_buf, | |
| 641 | + .from = &args->desc->type, | |
| 642 | + .pid = args->pid, | |
| 643 | + .new_psi_section = false, | |
| 644 | + .continuity_counter = args->continuity_counter, | |
| 645 | + .is_crc = false, | |
| 646 | + .dest_buf_sz = args->dest_buf_sz, | |
| 647 | + .crc = args->crc, | |
| 648 | + .len = sizeof_field(struct vidtv_psi_desc, type) + | |
| 649 | + sizeof_field(struct vidtv_psi_desc, length), | |
| 650 | + }; | |
| 651 | + struct vidtv_psi_desc_service_list_entry *serv_list_entry = NULL; | |
| 519 | 652 | u32 nbytes = 0; |
| 520 | − struct psi_write_args psi_args = {}; | |
| 521 | − | |
| 522 | − psi_args.dest_buf = args.dest_buf; | |
| 523 | − psi_args.from = &args.desc->type; | |
| 524 | 653 | |
| 525 | − psi_args.len = sizeof_field(struct vidtv_psi_desc, type) + | |
| 526 | − sizeof_field(struct vidtv_psi_desc, length); | |
| 654 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 527 | 655 | |
| 528 | − psi_args.dest_offset = args.dest_offset + nbytes; | |
| 529 | − psi_args.pid = args.pid; | |
| 530 | − psi_args.new_psi_section = false; | |
| 531 | − psi_args.continuity_counter = args.continuity_counter; | |
| 532 | − psi_args.is_crc = false; | |
| 533 | − psi_args.dest_buf_sz = args.dest_buf_sz; | |
| 534 | − psi_args.crc = args.crc; | |
| 656 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 535 | 657 | |
| 536 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 537 | − | |
| 538 | − switch (args.desc->type) { | |
| 658 | + switch (args->desc->type) { | |
| 539 | 659 | case SERVICE_DESCRIPTOR: |
| 540 | − psi_args.dest_offset = args.dest_offset + nbytes; | |
| 660 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 541 | 661 | psi_args.len = sizeof_field(struct vidtv_psi_desc_service, service_type) + |
| 542 | 662 | sizeof_field(struct vidtv_psi_desc_service, provider_name_len); |
| 543 | − psi_args.from = &((struct vidtv_psi_desc_service *)args.desc)->service_type; | |
| 663 | + psi_args.from = &((struct vidtv_psi_desc_service *)args->desc)->service_type; | |
| 544 | 664 | |
| 545 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 665 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 546 | 666 | |
| 547 | − psi_args.dest_offset = args.dest_offset + nbytes; | |
| 548 | − psi_args.len = ((struct vidtv_psi_desc_service *)args.desc)->provider_name_len; | |
| 549 | − psi_args.from = ((struct vidtv_psi_desc_service *)args.desc)->provider_name; | |
| 667 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 668 | + psi_args.len = ((struct vidtv_psi_desc_service *)args->desc)->provider_name_len; | |
| 669 | + psi_args.from = ((struct vidtv_psi_desc_service *)args->desc)->provider_name; | |
| 550 | 670 | |
| 551 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 671 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 552 | 672 | |
| 553 | − psi_args.dest_offset = args.dest_offset + nbytes; | |
| 673 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 554 | 674 | psi_args.len = sizeof_field(struct vidtv_psi_desc_service, service_name_len); |
| 555 | − psi_args.from = &((struct vidtv_psi_desc_service *)args.desc)->service_name_len; | |
| 675 | + psi_args.from = &((struct vidtv_psi_desc_service *)args->desc)->service_name_len; | |
| 556 | 676 | |
| 557 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 677 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 558 | 678 | |
| 559 | − psi_args.dest_offset = args.dest_offset + nbytes; | |
| 560 | − psi_args.len = ((struct vidtv_psi_desc_service *)args.desc)->service_name_len; | |
| 561 | − psi_args.from = ((struct vidtv_psi_desc_service *)args.desc)->service_name; | |
| 679 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 680 | + psi_args.len = ((struct vidtv_psi_desc_service *)args->desc)->service_name_len; | |
| 681 | + psi_args.from = ((struct vidtv_psi_desc_service *)args->desc)->service_name; | |
| 682 | + | |
| 683 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 684 | + break; | |
| 685 | + | |
| 686 | + case NETWORK_NAME_DESCRIPTOR: | |
| 687 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 688 | + psi_args.len = args->desc->length; | |
| 689 | + psi_args.from = ((struct vidtv_psi_desc_network_name *)args->desc)->network_name; | |
| 690 | + | |
| 691 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 692 | + break; | |
| 693 | + | |
| 694 | + case SERVICE_LIST_DESCRIPTOR: | |
| 695 | + serv_list_entry = ((struct vidtv_psi_desc_service_list *)args->desc)->service_list; | |
| 696 | + while (serv_list_entry) { | |
| 697 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 698 | + psi_args.len = sizeof(struct vidtv_psi_desc_service_list_entry) - | |
| 699 | + sizeof(struct vidtv_psi_desc_service_list_entry *); | |
| 700 | + psi_args.from = serv_list_entry; | |
| 701 | + | |
| 702 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 703 | + | |
| 704 | + serv_list_entry = serv_list_entry->next; | |
| 705 | + } | |
| 706 | + break; | |
| 707 | + | |
| 708 | + case SHORT_EVENT_DESCRIPTOR: | |
| 709 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 710 | + psi_args.len = ISO_LANGUAGE_CODE_LEN; | |
| 711 | + psi_args.from = ((struct vidtv_psi_desc_short_event *) | |
| 712 | + args->desc)->iso_language_code; | |
| 713 | + | |
| 714 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 715 | + | |
| 716 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 717 | + psi_args.len = sizeof_field(struct vidtv_psi_desc_short_event, event_name_len); | |
| 718 | + psi_args.from = &((struct vidtv_psi_desc_short_event *) | |
| 719 | + args->desc)->event_name_len; | |
| 720 | + | |
| 721 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 722 | + | |
| 723 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 724 | + psi_args.len = ((struct vidtv_psi_desc_short_event *)args->desc)->event_name_len; | |
| 725 | + psi_args.from = ((struct vidtv_psi_desc_short_event *)args->desc)->event_name; | |
| 726 | + | |
| 727 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 728 | + | |
| 729 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 730 | + psi_args.len = sizeof_field(struct vidtv_psi_desc_short_event, text_len); | |
| 731 | + psi_args.from = &((struct vidtv_psi_desc_short_event *)args->desc)->text_len; | |
| 732 | + | |
| 733 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 734 | + | |
| 735 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 736 | + psi_args.len = ((struct vidtv_psi_desc_short_event *)args->desc)->text_len; | |
| 737 | + psi_args.from = ((struct vidtv_psi_desc_short_event *)args->desc)->text; | |
| 738 | + | |
| 739 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 562 | 740 | |
| 563 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 564 | 741 | break; |
| 565 | 742 | |
| 566 | 743 | case REGISTRATION_DESCRIPTOR: |
| 567 | 744 | default: |
| 568 | − psi_args.dest_offset = args.dest_offset + nbytes; | |
| 569 | − psi_args.len = args.desc->length; | |
| 570 | − psi_args.from = &args.desc->data; | |
| 745 | + psi_args.dest_offset = args->dest_offset + nbytes; | |
| 746 | + psi_args.len = args->desc->length; | |
| 747 | + psi_args.from = &args->desc->data; | |
| 571 | 748 | |
| 572 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 749 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 573 | 750 | break; |
| 574 | 751 | } |
| 575 | 752 | |
| @@ -577,40 +754,37 @@ static u32 vidtv_psi_desc_write_into(struct desc_write_args args) · 1 unmodified line | ||
| 577 | 754 | } |
| 578 | 755 | |
| 579 | 756 | static u32 |
| 580 | −vidtv_psi_table_header_write_into(struct header_write_args args) | |
| 757 | +vidtv_psi_table_header_write_into(struct header_write_args *args) | |
| 581 | 758 | { |
| 582 | − /* the number of bytes written by this function */ | |
| 583 | − u32 nbytes = 0; | |
| 584 | − struct psi_write_args psi_args = {}; | |
| 585 | − | |
| 586 | − psi_args.dest_buf = args.dest_buf; | |
| 587 | − psi_args.from = args.h; | |
| 588 | − psi_args.len = sizeof(struct vidtv_psi_table_header); | |
| 589 | − psi_args.dest_offset = args.dest_offset; | |
| 590 | − psi_args.pid = args.pid; | |
| 591 | − psi_args.new_psi_section = true; | |
| 592 | − psi_args.continuity_counter = args.continuity_counter; | |
| 593 | − psi_args.is_crc = false; | |
| 594 | − psi_args.dest_buf_sz = args.dest_buf_sz; | |
| 595 | − psi_args.crc = args.crc; | |
| 596 | − | |
| 597 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 598 | − | |
| 599 | − return nbytes; | |
| 759 | + struct psi_write_args psi_args = { | |
| 760 | + .dest_buf = args->dest_buf, | |
| 761 | + .from = args->h, | |
| 762 | + .len = sizeof(struct vidtv_psi_table_header), | |
| 763 | + .dest_offset = args->dest_offset, | |
| 764 | + .pid = args->pid, | |
| 765 | + .new_psi_section = true, | |
| 766 | + .continuity_counter = args->continuity_counter, | |
| 767 | + .is_crc = false, | |
| 768 | + .dest_buf_sz = args->dest_buf_sz, | |
| 769 | + .crc = args->crc, | |
| 770 | + }; | |
| 771 | + | |
| 772 | + return vidtv_psi_ts_psi_write_into(&psi_args); | |
| 600 | 773 | } |
| 601 | 774 | |
| 602 | 775 | void |
| 603 | 776 | vidtv_psi_pat_table_update_sec_len(struct vidtv_psi_table_pat *pat) |
| 604 | 777 | { |
| 605 | − /* see ISO/IEC 13818-1 : 2000 p.43 */ | |
| 606 | 778 | u16 length = 0; |
| 607 | 779 | u32 i; |
| 608 | 780 | |
| 781 | + /* see ISO/IEC 13818-1 : 2000 p.43 */ | |
| 782 | + | |
| 609 | 783 | /* from immediately after 'section_length' until 'last_section_number'*/ |
| 610 | 784 | length += PAT_LEN_UNTIL_LAST_SECTION_NUMBER; |
| 611 | 785 | |
| 612 | 786 | /* do not count the pointer */ |
| 613 | − for (i = 0; i < pat->programs; ++i) | |
| 787 | + for (i = 0; i < pat->num_pat; ++i) | |
| 614 | 788 | length += sizeof(struct vidtv_psi_table_pat_program) - |
| 615 | 789 | sizeof(struct vidtv_psi_table_pat_program *); |
| 616 | 790 | |
| @@ -621,10 +795,11 @@ vidtv_psi_pat_table_update_sec_len(struct vidtv_psi_table_pat *pat) · 4 unmodified lines | ||
| 621 | 795 | |
| 622 | 796 | void vidtv_psi_pmt_table_update_sec_len(struct vidtv_psi_table_pmt *pmt) |
| 623 | 797 | { |
| 624 | − /* see ISO/IEC 13818-1 : 2000 p.46 */ | |
| 625 | − u16 length = 0; | |
| 626 | 798 | struct vidtv_psi_table_pmt_stream *s = pmt->stream; |
| 627 | 799 | u16 desc_loop_len; |
| 800 | + u16 length = 0; | |
| 801 | + | |
| 802 | + /* see ISO/IEC 13818-1 : 2000 p.46 */ | |
| 628 | 803 | |
| 629 | 804 | /* from immediately after 'section_length' until 'program_info_length'*/ |
| 630 | 805 | length += PMT_LEN_UNTIL_PROGRAM_INFO_LENGTH; |
| @@ -655,10 +830,11 @@ void vidtv_psi_pmt_table_update_sec_len(struct vidtv_psi_table_pmt *pmt) · 24 unmodified lines | ||
| 655 | 830 | |
| 656 | 831 | void vidtv_psi_sdt_table_update_sec_len(struct vidtv_psi_table_sdt *sdt) |
| 657 | 832 | { |
| 658 | − /* see ETSI EN 300 468 V 1.10.1 p.24 */ | |
| 659 | − u16 length = 0; | |
| 660 | 833 | struct vidtv_psi_table_sdt_service *s = sdt->service; |
| 661 | 834 | u16 desc_loop_len; |
| 835 | + u16 length = 0; | |
| 836 | + | |
| 837 | + /* see ETSI EN 300 468 V 1.10.1 p.24 */ | |
| 662 | 838 | |
| 663 | 839 | /* |
| 664 | 840 | * from immediately after 'section_length' until |
| @@ -681,7 +857,6 @@ void vidtv_psi_sdt_table_update_sec_len(struct vidtv_psi_table_sdt *sdt) · 16 unmodified lines | ||
| 681 | 857 | } |
| 682 | 858 | |
| 683 | 859 | length += CRC_SIZE_IN_BYTES; |
| 684 | − | |
| 685 | 860 | vidtv_psi_set_sec_len(&sdt->header, length); |
| 686 | 861 | } |
| 687 | 862 | |
| @@ -694,6 +869,8 @@ vidtv_psi_pat_program_init(struct vidtv_psi_table_pat_program *head, · 6 unmodified lines | ||
| 694 | 869 | const u16 RESERVED = 0x07; |
| 695 | 870 | |
| 696 | 871 | program = kzalloc(sizeof(*program), GFP_KERNEL); |
| 872 | + if (!program) | |
| 873 | + return NULL; | |
| 697 | 874 | |
| 698 | 875 | program->service_id = cpu_to_be16(service_id); |
| 699 | 876 | |
| @@ -714,8 +891,8 @@ vidtv_psi_pat_program_init(struct vidtv_psi_table_pat_program *head, · 14 unmodified lines | ||
| 714 | 891 | void |
| 715 | 892 | vidtv_psi_pat_program_destroy(struct vidtv_psi_table_pat_program *p) |
| 716 | 893 | { |
| 717 | − struct vidtv_psi_table_pat_program *curr = p; | |
| 718 | 894 | struct vidtv_psi_table_pat_program *tmp = NULL; |
| 895 | + struct vidtv_psi_table_pat_program *curr = p; | |
| 719 | 896 | |
| 720 | 897 | while (curr) { |
| 721 | 898 | tmp = curr; |
| @@ -724,42 +901,49 @@ vidtv_psi_pat_program_destroy(struct vidtv_psi_table_pat_program *p) · 2 unmodified lines | ||
| 724 | 901 | } |
| 725 | 902 | } |
| 726 | 903 | |
| 904 | +/* This function transfers ownership of p to the table */ | |
| 727 | 905 | void |
| 728 | 906 | vidtv_psi_pat_program_assign(struct vidtv_psi_table_pat *pat, |
| 729 | 907 | struct vidtv_psi_table_pat_program *p) |
| 730 | 908 | { |
| 731 | − /* This function transfers ownership of p to the table */ | |
| 909 | + struct vidtv_psi_table_pat_program *program; | |
| 910 | + u16 program_count; | |
| 732 | 911 | |
| 733 | − u16 program_count = 0; | |
| 734 | − struct vidtv_psi_table_pat_program *program = p; | |
| 912 | + do { | |
| 913 | + program_count = 0; | |
| 914 | + program = p; | |
| 735 | 915 | |
| 736 | − if (p == pat->program) | |
| 737 | − return; | |
| 916 | + if (p == pat->program) | |
| 917 | + return; | |
| 738 | 918 | |
| 739 | − while (program) { | |
| 740 | − ++program_count; | |
| 741 | − program = program->next; | |
| 742 | − } | |
| 919 | + while (program) { | |
| 920 | + ++program_count; | |
| 921 | + program = program->next; | |
| 922 | + } | |
| 743 | 923 | |
| 744 | − pat->programs = program_count; | |
| 745 | − pat->program = p; | |
| 924 | + pat->num_pat = program_count; | |
| 925 | + pat->program = p; | |
| 746 | 926 | |
| 747 | − /* Recompute section length */ | |
| 748 | − vidtv_psi_pat_table_update_sec_len(pat); | |
| 927 | + /* Recompute section length */ | |
| 928 | + vidtv_psi_pat_table_update_sec_len(pat); | |
| 749 | 929 | |
| 750 | − if (vidtv_psi_get_sec_len(&pat->header) > MAX_SECTION_LEN) | |
| 751 | − vidtv_psi_pat_program_assign(pat, NULL); | |
| 930 | + p = NULL; | |
| 931 | + } while (vidtv_psi_get_sec_len(&pat->header) > MAX_SECTION_LEN); | |
| 752 | 932 | |
| 753 | 933 | vidtv_psi_update_version_num(&pat->header); |
| 754 | 934 | } |
| 755 | 935 | |
| 756 | 936 | struct vidtv_psi_table_pat *vidtv_psi_pat_table_init(u16 transport_stream_id) |
| 757 | 937 | { |
| 758 | − struct vidtv_psi_table_pat *pat = kzalloc(sizeof(*pat), GFP_KERNEL); | |
| 938 | + struct vidtv_psi_table_pat *pat; | |
| 759 | 939 | const u16 SYNTAX = 0x1; |
| 760 | 940 | const u16 ZERO = 0x0; |
| 761 | 941 | const u16 ONES = 0x03; |
| 762 | 942 | |
| 943 | + pat = kzalloc(sizeof(*pat), GFP_KERNEL); | |
| 944 | + if (!pat) | |
| 945 | + return NULL; | |
| 946 | + | |
| 763 | 947 | pat->header.table_id = 0x0; |
| 764 | 948 | |
| 765 | 949 | pat->header.bitfield = cpu_to_be16((SYNTAX << 15) | (ZERO << 14) | (ONES << 12)); |
| @@ -772,70 +956,68 @@ struct vidtv_psi_table_pat *vidtv_psi_pat_table_init(u16 transport_stream_id) · 6 unmodified lines | ||
| 772 | 956 | pat->header.section_id = 0x0; |
| 773 | 957 | pat->header.last_section = 0x0; |
| 774 | 958 | |
| 775 | − pat->programs = 0; | |
| 776 | − | |
| 777 | 959 | vidtv_psi_pat_table_update_sec_len(pat); |
| 778 | 960 | |
| 779 | 961 | return pat; |
| 780 | 962 | } |
| 781 | 963 | |
| 782 | −u32 vidtv_psi_pat_write_into(struct vidtv_psi_pat_write_args args) | |
| 964 | +u32 vidtv_psi_pat_write_into(struct vidtv_psi_pat_write_args *args) | |
| 783 | 965 | { |
| 784 | − /* the number of bytes written by this function */ | |
| 966 | + struct vidtv_psi_table_pat_program *p = args->pat->program; | |
| 967 | + struct header_write_args h_args = { | |
| 968 | + .dest_buf = args->buf, | |
| 969 | + .dest_offset = args->offset, | |
| 970 | + .pid = VIDTV_PAT_PID, | |
| 971 | + .h = &args->pat->header, | |
| 972 | + .continuity_counter = args->continuity_counter, | |
| 973 | + .dest_buf_sz = args->buf_sz, | |
| 974 | + }; | |
| 975 | + struct psi_write_args psi_args = { | |
| 976 | + .dest_buf = args->buf, | |
| 977 | + .pid = VIDTV_PAT_PID, | |
| 978 | + .new_psi_section = false, | |
| 979 | + .continuity_counter = args->continuity_counter, | |
| 980 | + .is_crc = false, | |
| 981 | + .dest_buf_sz = args->buf_sz, | |
| 982 | + }; | |
| 983 | + struct crc32_write_args c_args = { | |
| 984 | + .dest_buf = args->buf, | |
| 985 | + .pid = VIDTV_PAT_PID, | |
| 986 | + .dest_buf_sz = args->buf_sz, | |
| 987 | + }; | |
| 988 | + u32 crc = INITIAL_CRC; | |
| 785 | 989 | u32 nbytes = 0; |
| 786 | − const u16 pat_pid = VIDTV_PAT_PID; | |
| 787 | − u32 crc = 0xffffffff; | |
| 788 | − | |
| 789 | − struct vidtv_psi_table_pat_program *p = args.pat->program; | |
| 790 | 990 | |
| 791 | − struct header_write_args h_args = {}; | |
| 792 | − struct psi_write_args psi_args = {}; | |
| 793 | − struct crc32_write_args c_args = {}; | |
| 991 | + vidtv_psi_pat_table_update_sec_len(args->pat); | |
| 794 | 992 | |
| 795 | − vidtv_psi_pat_table_update_sec_len(args.pat); | |
| 796 | − | |
| 797 | − h_args.dest_buf = args.buf; | |
| 798 | − h_args.dest_offset = args.offset; | |
| 799 | − h_args.h = &args.pat->header; | |
| 800 | − h_args.pid = pat_pid; | |
| 801 | − h_args.continuity_counter = args.continuity_counter; | |
| 802 | − h_args.dest_buf_sz = args.buf_sz; | |
| 803 | 993 | h_args.crc = &crc; |
| 804 | 994 | |
| 805 | − nbytes += vidtv_psi_table_header_write_into(h_args); | |
| 995 | + nbytes += vidtv_psi_table_header_write_into(&h_args); | |
| 806 | 996 | |
| 807 | 997 | /* note that the field 'u16 programs' is not really part of the PAT */ |
| 808 | 998 | |
| 809 | − psi_args.dest_buf = args.buf; | |
| 810 | − psi_args.pid = pat_pid; | |
| 811 | − psi_args.new_psi_section = false; | |
| 812 | − psi_args.continuity_counter = args.continuity_counter; | |
| 813 | − psi_args.is_crc = false; | |
| 814 | − psi_args.dest_buf_sz = args.buf_sz; | |
| 815 | − psi_args.crc = &crc; | |
| 999 | + psi_args.crc = &crc; | |
| 816 | 1000 | |
| 817 | 1001 | while (p) { |
| 818 | 1002 | /* copy the PAT programs */ |
| 819 | 1003 | psi_args.from = p; |
| 820 | 1004 | /* skip the pointer */ |
| 821 | 1005 | psi_args.len = sizeof(*p) - |
| 822 | − sizeof(struct vidtv_psi_table_pat_program *); | |
| 823 | − psi_args.dest_offset = args.offset + nbytes; | |
| 1006 | + sizeof(struct vidtv_psi_table_pat_program *); | |
| 1007 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1008 | + psi_args.continuity_counter = args->continuity_counter; | |
| 824 | 1009 | |
| 825 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 1010 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 826 | 1011 | |
| 827 | 1012 | p = p->next; |
| 828 | 1013 | } |
| 829 | 1014 | |
| 830 | − c_args.dest_buf = args.buf; | |
| 831 | − c_args.dest_offset = args.offset + nbytes; | |
| 1015 | + c_args.dest_offset = args->offset + nbytes; | |
| 1016 | + c_args.continuity_counter = args->continuity_counter; | |
| 832 | 1017 | c_args.crc = cpu_to_be32(crc); |
| 833 | − c_args.pid = pat_pid; | |
| 834 | − c_args.continuity_counter = args.continuity_counter; | |
| 835 | − c_args.dest_buf_sz = args.buf_sz; | |
| 836 | 1018 | |
| 837 | 1019 | /* Write the CRC32 at the end */ |
| 838 | − nbytes += table_section_crc32_write_into(c_args); | |
| 1020 | + nbytes += table_section_crc32_write_into(&c_args); | |
| 839 | 1021 | |
| 840 | 1022 | return nbytes; |
| 841 | 1023 | } |
| @@ -859,6 +1041,8 @@ vidtv_psi_pmt_stream_init(struct vidtv_psi_table_pmt_stream *head, · 17 unmodified lines | ||
| 859 | 1041 | u16 desc_loop_len; |
| 860 | 1042 | |
| 861 | 1043 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); |
| 1044 | + if (!stream) | |
| 1045 | + return NULL; | |
| 862 | 1046 | |
| 863 | 1047 | stream->type = stream_type; |
| 864 | 1048 | |
| @@ -883,8 +1067,8 @@ vidtv_psi_pmt_stream_init(struct vidtv_psi_table_pmt_stream *head, · 18 unmodified lines | ||
| 883 | 1067 | |
| 884 | 1068 | void vidtv_psi_pmt_stream_destroy(struct vidtv_psi_table_pmt_stream *s) |
| 885 | 1069 | { |
| 886 | − struct vidtv_psi_table_pmt_stream *curr_stream = s; | |
| 887 | 1070 | struct vidtv_psi_table_pmt_stream *tmp_stream = NULL; |
| 1071 | + struct vidtv_psi_table_pmt_stream *curr_stream = s; | |
| 888 | 1072 | |
| 889 | 1073 | while (curr_stream) { |
| 890 | 1074 | tmp_stream = curr_stream; |
| @@ -897,15 +1081,16 @@ void vidtv_psi_pmt_stream_destroy(struct vidtv_psi_table_pmt_stream *s) · 6 unmodified lines | ||
| 897 | 1081 | void vidtv_psi_pmt_stream_assign(struct vidtv_psi_table_pmt *pmt, |
| 898 | 1082 | struct vidtv_psi_table_pmt_stream *s) |
| 899 | 1083 | { |
| 900 | − /* This function transfers ownership of s to the table */ | |
| 901 | − if (s == pmt->stream) | |
| 902 | − return; | |
| 1084 | + do { | |
| 1085 | + /* This function transfers ownership of s to the table */ | |
| 1086 | + if (s == pmt->stream) | |
| 1087 | + return; | |
| 903 | 1088 | |
| 904 | − pmt->stream = s; | |
| 905 | − vidtv_psi_pmt_table_update_sec_len(pmt); | |
| 1089 | + pmt->stream = s; | |
| 1090 | + vidtv_psi_pmt_table_update_sec_len(pmt); | |
| 906 | 1091 | |
| 907 | − if (vidtv_psi_get_sec_len(&pmt->header) > MAX_SECTION_LEN) | |
| 908 | − vidtv_psi_pmt_stream_assign(pmt, NULL); | |
| 1092 | + s = NULL; | |
| 1093 | + } while (vidtv_psi_get_sec_len(&pmt->header) > MAX_SECTION_LEN); | |
| 909 | 1094 | |
| 910 | 1095 | vidtv_psi_update_version_num(&pmt->header); |
| 911 | 1096 | } |
| @@ -933,14 +1118,18 @@ u16 vidtv_psi_pmt_get_pid(struct vidtv_psi_table_pmt *section, · 21 unmodified lines | ||
| 933 | 1118 | struct vidtv_psi_table_pmt *vidtv_psi_pmt_table_init(u16 program_number, |
| 934 | 1119 | u16 pcr_pid) |
| 935 | 1120 | { |
| 936 | − struct vidtv_psi_table_pmt *pmt = kzalloc(sizeof(*pmt), GFP_KERNEL); | |
| 937 | − const u16 SYNTAX = 0x1; | |
| 938 | − const u16 ZERO = 0x0; | |
| 939 | − const u16 ONES = 0x03; | |
| 1121 | + struct vidtv_psi_table_pmt *pmt; | |
| 940 | 1122 | const u16 RESERVED1 = 0x07; |
| 941 | 1123 | const u16 RESERVED2 = 0x0f; |
| 1124 | + const u16 SYNTAX = 0x1; | |
| 1125 | + const u16 ONES = 0x03; | |
| 1126 | + const u16 ZERO = 0x0; | |
| 942 | 1127 | u16 desc_loop_len; |
| 943 | 1128 | |
| 1129 | + pmt = kzalloc(sizeof(*pmt), GFP_KERNEL); | |
| 1130 | + if (!pmt) | |
| 1131 | + return NULL; | |
| 1132 | + | |
| 944 | 1133 | if (!pcr_pid) |
| 945 | 1134 | pcr_pid = 0x1fff; |
| 946 | 1135 | |
| @@ -970,87 +1159,84 @@ struct vidtv_psi_table_pmt *vidtv_psi_pmt_table_init(u16 program_number, · 23 unmodified lines | ||
| 970 | 1159 | return pmt; |
| 971 | 1160 | } |
| 972 | 1161 | |
| 973 | −u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args args) | |
| 1162 | +u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args *args) | |
| 974 | 1163 | { |
| 975 | − /* the number of bytes written by this function */ | |
| 1164 | + struct vidtv_psi_desc *table_descriptor = args->pmt->descriptor; | |
| 1165 | + struct vidtv_psi_table_pmt_stream *stream = args->pmt->stream; | |
| 1166 | + struct vidtv_psi_desc *stream_descriptor; | |
| 1167 | + struct header_write_args h_args = { | |
| 1168 | + .dest_buf = args->buf, | |
| 1169 | + .dest_offset = args->offset, | |
| 1170 | + .h = &args->pmt->header, | |
| 1171 | + .pid = args->pid, | |
| 1172 | + .continuity_counter = args->continuity_counter, | |
| 1173 | + .dest_buf_sz = args->buf_sz, | |
| 1174 | + }; | |
| 1175 | + struct psi_write_args psi_args = { | |
| 1176 | + .dest_buf = args->buf, | |
| 1177 | + .from = &args->pmt->bitfield, | |
| 1178 | + .len = sizeof_field(struct vidtv_psi_table_pmt, bitfield) + | |
| 1179 | + sizeof_field(struct vidtv_psi_table_pmt, bitfield2), | |
| 1180 | + .pid = args->pid, | |
| 1181 | + .new_psi_section = false, | |
| 1182 | + .is_crc = false, | |
| 1183 | + .dest_buf_sz = args->buf_sz, | |
| 1184 | + }; | |
| 1185 | + struct desc_write_args d_args = { | |
| 1186 | + .dest_buf = args->buf, | |
| 1187 | + .desc = table_descriptor, | |
| 1188 | + .pid = args->pid, | |
| 1189 | + .dest_buf_sz = args->buf_sz, | |
| 1190 | + }; | |
| 1191 | + struct crc32_write_args c_args = { | |
| 1192 | + .dest_buf = args->buf, | |
| 1193 | + .pid = args->pid, | |
| 1194 | + .dest_buf_sz = args->buf_sz, | |
| 1195 | + }; | |
| 1196 | + u32 crc = INITIAL_CRC; | |
| 976 | 1197 | u32 nbytes = 0; |
| 977 | − u32 crc = 0xffffffff; | |
| 978 | − | |
| 979 | − struct vidtv_psi_desc *table_descriptor = args.pmt->descriptor; | |
| 980 | − struct vidtv_psi_table_pmt_stream *stream = args.pmt->stream; | |
| 981 | − struct vidtv_psi_desc *stream_descriptor = (stream) ? | |
| 982 | − args.pmt->stream->descriptor : | |
| 983 | − NULL; | |
| 984 | − | |
| 985 | − struct header_write_args h_args = {}; | |
| 986 | − struct psi_write_args psi_args = {}; | |
| 987 | − struct desc_write_args d_args = {}; | |
| 988 | − struct crc32_write_args c_args = {}; | |
| 989 | − | |
| 990 | − vidtv_psi_pmt_table_update_sec_len(args.pmt); | |
| 991 | − | |
| 992 | − h_args.dest_buf = args.buf; | |
| 993 | − h_args.dest_offset = args.offset; | |
| 994 | − h_args.h = &args.pmt->header; | |
| 995 | − h_args.pid = args.pid; | |
| 996 | − h_args.continuity_counter = args.continuity_counter; | |
| 997 | − h_args.dest_buf_sz = args.buf_sz; | |
| 1198 | + | |
| 1199 | + vidtv_psi_pmt_table_update_sec_len(args->pmt); | |
| 1200 | + | |
| 998 | 1201 | h_args.crc = &crc; |
| 999 | 1202 | |
| 1000 | − nbytes += vidtv_psi_table_header_write_into(h_args); | |
| 1203 | + nbytes += vidtv_psi_table_header_write_into(&h_args); | |
| 1001 | 1204 | |
| 1002 | 1205 | /* write the two bitfields */ |
| 1003 | − psi_args.dest_buf = args.buf; | |
| 1004 | − psi_args.from = &args.pmt->bitfield; | |
| 1005 | − psi_args.len = sizeof_field(struct vidtv_psi_table_pmt, bitfield) + | |
| 1006 | − sizeof_field(struct vidtv_psi_table_pmt, bitfield2); | |
| 1007 | − | |
| 1008 | − psi_args.dest_offset = args.offset + nbytes; | |
| 1009 | − psi_args.pid = args.pid; | |
| 1010 | − psi_args.new_psi_section = false; | |
| 1011 | − psi_args.continuity_counter = args.continuity_counter; | |
| 1012 | − psi_args.is_crc = false; | |
| 1013 | − psi_args.dest_buf_sz = args.buf_sz; | |
| 1014 | − psi_args.crc = &crc; | |
| 1015 | − | |
| 1016 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 1206 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1207 | + psi_args.continuity_counter = args->continuity_counter; | |
| 1208 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 1017 | 1209 | |
| 1018 | 1210 | while (table_descriptor) { |
| 1019 | 1211 | /* write the descriptors, if any */ |
| 1020 | − d_args.dest_buf = args.buf; | |
| 1021 | − d_args.dest_offset = args.offset + nbytes; | |
| 1022 | − d_args.desc = table_descriptor; | |
| 1023 | − d_args.pid = args.pid; | |
| 1024 | − d_args.continuity_counter = args.continuity_counter; | |
| 1025 | − d_args.dest_buf_sz = args.buf_sz; | |
| 1212 | + d_args.dest_offset = args->offset + nbytes; | |
| 1213 | + d_args.continuity_counter = args->continuity_counter; | |
| 1026 | 1214 | d_args.crc = &crc; |
| 1027 | 1215 | |
| 1028 | − nbytes += vidtv_psi_desc_write_into(d_args); | |
| 1216 | + nbytes += vidtv_psi_desc_write_into(&d_args); | |
| 1029 | 1217 | |
| 1030 | 1218 | table_descriptor = table_descriptor->next; |
| 1031 | 1219 | } |
| 1032 | 1220 | |
| 1221 | + psi_args.len += sizeof_field(struct vidtv_psi_table_pmt_stream, type); | |
| 1033 | 1222 | while (stream) { |
| 1034 | 1223 | /* write the streams, if any */ |
| 1035 | 1224 | psi_args.from = stream; |
| 1036 | − psi_args.len = sizeof_field(struct vidtv_psi_table_pmt_stream, type) + | |
| 1037 | − sizeof_field(struct vidtv_psi_table_pmt_stream, bitfield) + | |
| 1038 | − sizeof_field(struct vidtv_psi_table_pmt_stream, bitfield2); | |
| 1039 | − psi_args.dest_offset = args.offset + nbytes; | |
| 1225 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1226 | + psi_args.continuity_counter = args->continuity_counter; | |
| 1227 | + | |
| 1228 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 1040 | 1229 | |
| 1041 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 1230 | + stream_descriptor = stream->descriptor; | |
| 1042 | 1231 | |
| 1043 | 1232 | while (stream_descriptor) { |
| 1044 | 1233 | /* write the stream descriptors, if any */ |
| 1045 | − d_args.dest_buf = args.buf; | |
| 1046 | − d_args.dest_offset = args.offset + nbytes; | |
| 1234 | + d_args.dest_offset = args->offset + nbytes; | |
| 1047 | 1235 | d_args.desc = stream_descriptor; |
| 1048 | − d_args.pid = args.pid; | |
| 1049 | − d_args.continuity_counter = args.continuity_counter; | |
| 1050 | − d_args.dest_buf_sz = args.buf_sz; | |
| 1236 | + d_args.continuity_counter = args->continuity_counter; | |
| 1051 | 1237 | d_args.crc = &crc; |
| 1052 | 1238 | |
| 1053 | − nbytes += vidtv_psi_desc_write_into(d_args); | |
| 1239 | + nbytes += vidtv_psi_desc_write_into(&d_args); | |
| 1054 | 1240 | |
| 1055 | 1241 | stream_descriptor = stream_descriptor->next; |
| 1056 | 1242 | } |
| @@ -1058,15 +1244,12 @@ u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args args) · 1 unmodified line | ||
| 1058 | 1244 | stream = stream->next; |
| 1059 | 1245 | } |
| 1060 | 1246 | |
| 1061 | − c_args.dest_buf = args.buf; | |
| 1062 | − c_args.dest_offset = args.offset + nbytes; | |
| 1247 | + c_args.dest_offset = args->offset + nbytes; | |
| 1063 | 1248 | c_args.crc = cpu_to_be32(crc); |
| 1064 | − c_args.pid = args.pid; | |
| 1065 | − c_args.continuity_counter = args.continuity_counter; | |
| 1066 | − c_args.dest_buf_sz = args.buf_sz; | |
| 1249 | + c_args.continuity_counter = args->continuity_counter; | |
| 1067 | 1250 | |
| 1068 | 1251 | /* Write the CRC32 at the end */ |
| 1069 | − nbytes += table_section_crc32_write_into(c_args); | |
| 1252 | + nbytes += table_section_crc32_write_into(&c_args); | |
| 1070 | 1253 | |
| 1071 | 1254 | return nbytes; |
| 1072 | 1255 | } |
| @@ -1078,16 +1261,20 @@ void vidtv_psi_pmt_table_destroy(struct vidtv_psi_table_pmt *pmt) · 5 unmodified lines | ||
| 1078 | 1261 | kfree(pmt); |
| 1079 | 1262 | } |
| 1080 | 1263 | |
| 1081 | −struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 transport_stream_id) | |
| 1264 | +struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 network_id, | |
| 1265 | + u16 transport_stream_id) | |
| 1082 | 1266 | { |
| 1083 | − struct vidtv_psi_table_sdt *sdt = kzalloc(sizeof(*sdt), GFP_KERNEL); | |
| 1267 | + struct vidtv_psi_table_sdt *sdt; | |
| 1268 | + const u16 RESERVED = 0xff; | |
| 1084 | 1269 | const u16 SYNTAX = 0x1; |
| 1085 | − const u16 ONE = 0x1; | |
| 1086 | 1270 | const u16 ONES = 0x03; |
| 1087 | − const u16 RESERVED = 0xff; | |
| 1271 | + const u16 ONE = 0x1; | |
| 1088 | 1272 | |
| 1089 | − sdt->header.table_id = 0x42; | |
| 1273 | + sdt = kzalloc(sizeof(*sdt), GFP_KERNEL); | |
| 1274 | + if (!sdt) | |
| 1275 | + return NULL; | |
| 1090 | 1276 | |
| 1277 | + sdt->header.table_id = 0x42; | |
| 1091 | 1278 | sdt->header.bitfield = cpu_to_be16((SYNTAX << 15) | (ONE << 14) | (ONES << 12)); |
| 1092 | 1279 | |
| 1093 | 1280 | /* |
| @@ -1111,7 +1298,7 @@ struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 transport_stream_id) · 17 unmodified lines | ||
| 1111 | 1298 | * This can be changed to something more useful, when support for |
| 1112 | 1299 | * NIT gets added |
| 1113 | 1300 | */ |
| 1114 | − sdt->network_id = cpu_to_be16(0xff01); | |
| 1301 | + sdt->network_id = cpu_to_be16(network_id); | |
| 1115 | 1302 | sdt->reserved = RESERVED; |
| 1116 | 1303 | |
| 1117 | 1304 | vidtv_psi_sdt_table_update_sec_len(sdt); |
| @@ -1119,74 +1306,79 @@ struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 transport_stream_id) · 1 unmodified line | ||
| 1119 | 1306 | return sdt; |
| 1120 | 1307 | } |
| 1121 | 1308 | |
| 1122 | −u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args args) | |
| 1309 | +u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args *args) | |
| 1123 | 1310 | { |
| 1311 | + struct header_write_args h_args = { | |
| 1312 | + .dest_buf = args->buf, | |
| 1313 | + .dest_offset = args->offset, | |
| 1314 | + .h = &args->sdt->header, | |
| 1315 | + .pid = VIDTV_SDT_PID, | |
| 1316 | + .dest_buf_sz = args->buf_sz, | |
| 1317 | + }; | |
| 1318 | + struct psi_write_args psi_args = { | |
| 1319 | + .dest_buf = args->buf, | |
| 1320 | + .len = sizeof_field(struct vidtv_psi_table_sdt, network_id) + | |
| 1321 | + sizeof_field(struct vidtv_psi_table_sdt, reserved), | |
| 1322 | + .pid = VIDTV_SDT_PID, | |
| 1323 | + .new_psi_section = false, | |
| 1324 | + .is_crc = false, | |
| 1325 | + .dest_buf_sz = args->buf_sz, | |
| 1326 | + }; | |
| 1327 | + struct desc_write_args d_args = { | |
| 1328 | + .dest_buf = args->buf, | |
| 1329 | + .pid = VIDTV_SDT_PID, | |
| 1330 | + .dest_buf_sz = args->buf_sz, | |
| 1331 | + }; | |
| 1332 | + struct crc32_write_args c_args = { | |
| 1333 | + .dest_buf = args->buf, | |
| 1334 | + .pid = VIDTV_SDT_PID, | |
| 1335 | + .dest_buf_sz = args->buf_sz, | |
| 1336 | + }; | |
| 1337 | + struct vidtv_psi_table_sdt_service *service = args->sdt->service; | |
| 1338 | + struct vidtv_psi_desc *service_desc; | |
| 1124 | 1339 | u32 nbytes = 0; |
| 1125 | − u16 sdt_pid = VIDTV_SDT_PID; /* see ETSI EN 300 468 v1.15.1 p. 11 */ | |
| 1340 | + u32 crc = INITIAL_CRC; | |
| 1126 | 1341 | |
| 1127 | − u32 crc = 0xffffffff; | |
| 1342 | + /* see ETSI EN 300 468 v1.15.1 p. 11 */ | |
| 1128 | 1343 | |
| 1129 | − struct vidtv_psi_table_sdt_service *service = args.sdt->service; | |
| 1130 | − struct vidtv_psi_desc *service_desc = (args.sdt->service) ? | |
| 1131 | − args.sdt->service->descriptor : | |
| 1132 | − NULL; | |
| 1344 | + vidtv_psi_sdt_table_update_sec_len(args->sdt); | |
| 1133 | 1345 | |
| 1134 | − struct header_write_args h_args = {}; | |
| 1135 | − struct psi_write_args psi_args = {}; | |
| 1136 | − struct desc_write_args d_args = {}; | |
| 1137 | − struct crc32_write_args c_args = {}; | |
| 1138 | − | |
| 1139 | − vidtv_psi_sdt_table_update_sec_len(args.sdt); | |
| 1140 | − | |
| 1141 | − h_args.dest_buf = args.buf; | |
| 1142 | − h_args.dest_offset = args.offset; | |
| 1143 | − h_args.h = &args.sdt->header; | |
| 1144 | − h_args.pid = sdt_pid; | |
| 1145 | − h_args.continuity_counter = args.continuity_counter; | |
| 1146 | − h_args.dest_buf_sz = args.buf_sz; | |
| 1346 | + h_args.continuity_counter = args->continuity_counter; | |
| 1147 | 1347 | h_args.crc = &crc; |
| 1148 | 1348 | |
| 1149 | − nbytes += vidtv_psi_table_header_write_into(h_args); | |
| 1150 | − | |
| 1151 | − psi_args.dest_buf = args.buf; | |
| 1152 | − psi_args.from = &args.sdt->network_id; | |
| 1349 | + nbytes += vidtv_psi_table_header_write_into(&h_args); | |
| 1153 | 1350 | |
| 1154 | − psi_args.len = sizeof_field(struct vidtv_psi_table_sdt, network_id) + | |
| 1155 | − sizeof_field(struct vidtv_psi_table_sdt, reserved); | |
| 1156 | − | |
| 1157 | − psi_args.dest_offset = args.offset + nbytes; | |
| 1158 | − psi_args.pid = sdt_pid; | |
| 1159 | − psi_args.new_psi_section = false; | |
| 1160 | − psi_args.continuity_counter = args.continuity_counter; | |
| 1161 | − psi_args.is_crc = false; | |
| 1162 | − psi_args.dest_buf_sz = args.buf_sz; | |
| 1351 | + psi_args.from = &args->sdt->network_id; | |
| 1352 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1353 | + psi_args.continuity_counter = args->continuity_counter; | |
| 1163 | 1354 | psi_args.crc = &crc; |
| 1164 | 1355 | |
| 1165 | 1356 | /* copy u16 network_id + u8 reserved)*/ |
| 1166 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 1357 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 1358 | + | |
| 1359 | + /* skip both pointers at the end */ | |
| 1360 | + psi_args.len = sizeof(struct vidtv_psi_table_sdt_service) - | |
| 1361 | + sizeof(struct vidtv_psi_desc *) - | |
| 1362 | + sizeof(struct vidtv_psi_table_sdt_service *); | |
| 1167 | 1363 | |
| 1168 | 1364 | while (service) { |
| 1169 | 1365 | /* copy the services, if any */ |
| 1170 | 1366 | psi_args.from = service; |
| 1171 | − /* skip both pointers at the end */ | |
| 1172 | − psi_args.len = sizeof(struct vidtv_psi_table_sdt_service) - | |
| 1173 | − sizeof(struct vidtv_psi_desc *) - | |
| 1174 | − sizeof(struct vidtv_psi_table_sdt_service *); | |
| 1175 | − psi_args.dest_offset = args.offset + nbytes; | |
| 1367 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1368 | + psi_args.continuity_counter = args->continuity_counter; | |
| 1369 | + | |
| 1370 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 1176 | 1371 | |
| 1177 | − nbytes += vidtv_psi_ts_psi_write_into(psi_args); | |
| 1372 | + service_desc = service->descriptor; | |
| 1178 | 1373 | |
| 1179 | 1374 | while (service_desc) { |
| 1180 | 1375 | /* copy the service descriptors, if any */ |
| 1181 | − d_args.dest_buf = args.buf; | |
| 1182 | − d_args.dest_offset = args.offset + nbytes; | |
| 1376 | + d_args.dest_offset = args->offset + nbytes; | |
| 1183 | 1377 | d_args.desc = service_desc; |
| 1184 | − d_args.pid = sdt_pid; | |
| 1185 | − d_args.continuity_counter = args.continuity_counter; | |
| 1186 | − d_args.dest_buf_sz = args.buf_sz; | |
| 1378 | + d_args.continuity_counter = args->continuity_counter; | |
| 1187 | 1379 | d_args.crc = &crc; |
| 1188 | 1380 | |
| 1189 | − nbytes += vidtv_psi_desc_write_into(d_args); | |
| 1381 | + nbytes += vidtv_psi_desc_write_into(&d_args); | |
| 1190 | 1382 | |
| 1191 | 1383 | service_desc = service_desc->next; |
| 1192 | 1384 | } |
| @@ -1194,15 +1386,12 @@ u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args args) · 1 unmodified line | ||
| 1194 | 1386 | service = service->next; |
| 1195 | 1387 | } |
| 1196 | 1388 | |
| 1197 | − c_args.dest_buf = args.buf; | |
| 1198 | − c_args.dest_offset = args.offset + nbytes; | |
| 1389 | + c_args.dest_offset = args->offset + nbytes; | |
| 1199 | 1390 | c_args.crc = cpu_to_be32(crc); |
| 1200 | − c_args.pid = sdt_pid; | |
| 1201 | − c_args.continuity_counter = args.continuity_counter; | |
| 1202 | − c_args.dest_buf_sz = args.buf_sz; | |
| 1391 | + c_args.continuity_counter = args->continuity_counter; | |
| 1203 | 1392 | |
| 1204 | 1393 | /* Write the CRC at the end */ |
| 1205 | − nbytes += table_section_crc32_write_into(c_args); | |
| 1394 | + nbytes += table_section_crc32_write_into(&c_args); | |
| 1206 | 1395 | |
| 1207 | 1396 | return nbytes; |
| 1208 | 1397 | } |
| @@ -1215,11 +1404,15 @@ void vidtv_psi_sdt_table_destroy(struct vidtv_psi_table_sdt *sdt) · 6 unmodified lines | ||
| 1215 | 1404 | |
| 1216 | 1405 | struct vidtv_psi_table_sdt_service |
| 1217 | 1406 | *vidtv_psi_sdt_service_init(struct vidtv_psi_table_sdt_service *head, |
| 1218 | − u16 service_id) | |
| 1407 | + u16 service_id, | |
| 1408 | + bool eit_schedule, | |
| 1409 | + bool eit_present_following) | |
| 1219 | 1410 | { |
| 1220 | 1411 | struct vidtv_psi_table_sdt_service *service; |
| 1221 | 1412 | |
| 1222 | 1413 | service = kzalloc(sizeof(*service), GFP_KERNEL); |
| 1414 | + if (!service) | |
| 1415 | + return NULL; | |
| 1223 | 1416 | |
| 1224 | 1417 | /* |
| 1225 | 1418 | * ETSI 300 468: this is a 16bit field which serves as a label to |
| @@ -1228,8 +1421,8 @@ struct vidtv_psi_table_sdt_service · 2 unmodified lines | ||
| 1228 | 1421 | * corresponding program_map_section |
| 1229 | 1422 | */ |
| 1230 | 1423 | service->service_id = cpu_to_be16(service_id); |
| 1231 | − service->EIT_schedule = 0x0; | |
| 1232 | − service->EIT_present_following = 0x0; | |
| 1424 | + service->EIT_schedule = eit_schedule; | |
| 1425 | + service->EIT_present_following = eit_present_following; | |
| 1233 | 1426 | service->reserved = 0x3f; |
| 1234 | 1427 | |
| 1235 | 1428 | service->bitfield = cpu_to_be16(RUNNING << 13); |
| @@ -1262,53 +1455,78 @@ void · 26 unmodified lines | ||
| 1262 | 1455 | vidtv_psi_sdt_service_assign(struct vidtv_psi_table_sdt *sdt, |
| 1263 | 1456 | struct vidtv_psi_table_sdt_service *service) |
| 1264 | 1457 | { |
| 1265 | − if (service == sdt->service) | |
| 1266 | − return; | |
| 1458 | + do { | |
| 1459 | + if (service == sdt->service) | |
| 1460 | + return; | |
| 1267 | 1461 | |
| 1268 | − sdt->service = service; | |
| 1462 | + sdt->service = service; | |
| 1269 | 1463 | |
| 1270 | − /* recompute section length */ | |
| 1271 | − vidtv_psi_sdt_table_update_sec_len(sdt); | |
| 1464 | + /* recompute section length */ | |
| 1465 | + vidtv_psi_sdt_table_update_sec_len(sdt); | |
| 1272 | 1466 | |
| 1273 | − if (vidtv_psi_get_sec_len(&sdt->header) > MAX_SECTION_LEN) | |
| 1274 | − vidtv_psi_sdt_service_assign(sdt, NULL); | |
| 1467 | + service = NULL; | |
| 1468 | + } while (vidtv_psi_get_sec_len(&sdt->header) > MAX_SECTION_LEN); | |
| 1275 | 1469 | |
| 1276 | 1470 | vidtv_psi_update_version_num(&sdt->header); |
| 1277 | 1471 | } |
| 1278 | 1472 | |
| 1473 | +/* | |
| 1474 | + * PMTs contain information about programs. For each program, | |
| 1475 | + * there is one PMT section. This function will create a section | |
| 1476 | + * for each program found in the PAT | |
| 1477 | + */ | |
| 1279 | 1478 | struct vidtv_psi_table_pmt** |
| 1280 | −vidtv_psi_pmt_create_sec_for_each_pat_entry(struct vidtv_psi_table_pat *pat, u16 pcr_pid) | |
| 1479 | +vidtv_psi_pmt_create_sec_for_each_pat_entry(struct vidtv_psi_table_pat *pat, | |
| 1480 | + u16 pcr_pid) | |
| 1281 | 1481 | |
| 1282 | 1482 | { |
| 1483 | + struct vidtv_psi_table_pat_program *program; | |
| 1484 | + struct vidtv_psi_table_pmt **pmt_secs; | |
| 1485 | + u32 i = 0, num_pmt = 0; | |
| 1486 | + | |
| 1283 | 1487 | /* |
| 1284 | − * PMTs contain information about programs. For each program, | |
| 1285 | − * there is one PMT section. This function will create a section | |
| 1286 | − * for each program found in the PAT | |
| 1488 | + * The number of PMT entries is the number of PAT entries | |
| 1489 | + * that contain service_id. That exclude special tables, like NIT | |
| 1287 | 1490 | */ |
| 1288 | − struct vidtv_psi_table_pat_program *program = pat->program; | |
| 1289 | − struct vidtv_psi_table_pmt **pmt_secs; | |
| 1290 | − u32 i = 0; | |
| 1491 | + program = pat->program; | |
| 1492 | + while (program) { | |
| 1493 | + if (program->service_id) | |
| 1494 | + num_pmt++; | |
| 1495 | + program = program->next; | |
| 1496 | + } | |
| 1291 | 1497 | |
| 1292 | − /* a section for each program_id */ | |
| 1293 | − pmt_secs = kcalloc(pat->programs, | |
| 1498 | + pmt_secs = kcalloc(num_pmt, | |
| 1294 | 1499 | sizeof(struct vidtv_psi_table_pmt *), |
| 1295 | 1500 | GFP_KERNEL); |
| 1296 | − | |
| 1297 | − while (program) { | |
| 1298 | − pmt_secs[i] = vidtv_psi_pmt_table_init(be16_to_cpu(program->service_id), pcr_pid); | |
| 1299 | − ++i; | |
| 1300 | − program = program->next; | |
| 1501 | + if (!pmt_secs) | |
| 1502 | + return NULL; | |
| 1503 | + | |
| 1504 | + for (program = pat->program; program; program = program->next) { | |
| 1505 | + if (!program->service_id) | |
| 1506 | + continue; | |
| 1507 | + pmt_secs[i] = vidtv_psi_pmt_table_init(be16_to_cpu(program->service_id), | |
| 1508 | + pcr_pid); | |
| 1509 | + | |
| 1510 | + if (!pmt_secs[i]) { | |
| 1511 | + while (i > 0) { | |
| 1512 | + i--; | |
| 1513 | + vidtv_psi_pmt_table_destroy(pmt_secs[i]); | |
| 1514 | + } | |
| 1515 | + return NULL; | |
| 1516 | + } | |
| 1517 | + i++; | |
| 1301 | 1518 | } |
| 1519 | + pat->num_pmt = num_pmt; | |
| 1302 | 1520 | |
| 1303 | 1521 | return pmt_secs; |
| 1304 | 1522 | } |
| 1305 | 1523 | |
| 1524 | +/* find the PMT section associated with 'program_num' */ | |
| 1306 | 1525 | struct vidtv_psi_table_pmt |
| 1307 | 1526 | *vidtv_psi_find_pmt_sec(struct vidtv_psi_table_pmt **pmt_sections, |
| 1308 | 1527 | u16 nsections, |
| 1309 | 1528 | u16 program_num) |
| 1310 | 1529 | { |
| 1311 | − /* find the PMT section associated with 'program_num' */ | |
| 1312 | 1530 | struct vidtv_psi_table_pmt *sec = NULL; |
| 1313 | 1531 | u32 i; |
| 1314 | 1532 | |
| @@ -1320,3 +1538,488 @@ struct vidtv_psi_table_pmt · 5 unmodified lines | ||
| 1320 | 1538 | |
| 1321 | 1539 | return NULL; /* not found */ |
| 1322 | 1540 | } |
| 1541 | + | |
| 1542 | +static void vidtv_psi_nit_table_update_sec_len(struct vidtv_psi_table_nit *nit) | |
| 1543 | +{ | |
| 1544 | + u16 length = 0; | |
| 1545 | + struct vidtv_psi_table_transport *t = nit->transport; | |
| 1546 | + u16 desc_loop_len; | |
| 1547 | + u16 transport_loop_len = 0; | |
| 1548 | + | |
| 1549 | + /* | |
| 1550 | + * from immediately after 'section_length' until | |
| 1551 | + * 'network_descriptor_length' | |
| 1552 | + */ | |
| 1553 | + length += NIT_LEN_UNTIL_NETWORK_DESCRIPTOR_LEN; | |
| 1554 | + | |
| 1555 | + desc_loop_len = vidtv_psi_desc_comp_loop_len(nit->descriptor); | |
| 1556 | + vidtv_psi_set_desc_loop_len(&nit->bitfield, desc_loop_len, 12); | |
| 1557 | + | |
| 1558 | + length += desc_loop_len; | |
| 1559 | + | |
| 1560 | + length += sizeof_field(struct vidtv_psi_table_nit, bitfield2); | |
| 1561 | + | |
| 1562 | + while (t) { | |
| 1563 | + /* skip both pointers at the end */ | |
| 1564 | + transport_loop_len += sizeof(struct vidtv_psi_table_transport) - | |
| 1565 | + sizeof(struct vidtv_psi_desc *) - | |
| 1566 | + sizeof(struct vidtv_psi_table_transport *); | |
| 1567 | + | |
| 1568 | + length += transport_loop_len; | |
| 1569 | + | |
| 1570 | + desc_loop_len = vidtv_psi_desc_comp_loop_len(t->descriptor); | |
| 1571 | + vidtv_psi_set_desc_loop_len(&t->bitfield, desc_loop_len, 12); | |
| 1572 | + | |
| 1573 | + length += desc_loop_len; | |
| 1574 | + | |
| 1575 | + t = t->next; | |
| 1576 | + } | |
| 1577 | + | |
| 1578 | + // Actually sets the transport stream loop len, maybe rename this function later | |
| 1579 | + vidtv_psi_set_desc_loop_len(&nit->bitfield2, transport_loop_len, 12); | |
| 1580 | + length += CRC_SIZE_IN_BYTES; | |
| 1581 | + | |
| 1582 | + vidtv_psi_set_sec_len(&nit->header, length); | |
| 1583 | +} | |
| 1584 | + | |
| 1585 | +struct vidtv_psi_table_nit | |
| 1586 | +*vidtv_psi_nit_table_init(u16 network_id, | |
| 1587 | + u16 transport_stream_id, | |
| 1588 | + char *network_name, | |
| 1589 | + struct vidtv_psi_desc_service_list_entry *service_list) | |
| 1590 | +{ | |
| 1591 | + struct vidtv_psi_table_transport *transport; | |
| 1592 | + struct vidtv_psi_table_nit *nit; | |
| 1593 | + const u16 SYNTAX = 0x1; | |
| 1594 | + const u16 ONES = 0x03; | |
| 1595 | + const u16 ONE = 0x1; | |
| 1596 | + | |
| 1597 | + nit = kzalloc(sizeof(*nit), GFP_KERNEL); | |
| 1598 | + if (!nit) | |
| 1599 | + return NULL; | |
| 1600 | + | |
| 1601 | + transport = kzalloc(sizeof(*transport), GFP_KERNEL); | |
| 1602 | + if (!transport) | |
| 1603 | + goto free_nit; | |
| 1604 | + | |
| 1605 | + nit->header.table_id = 0x40; // ACTUAL_NETWORK | |
| 1606 | + | |
| 1607 | + nit->header.bitfield = cpu_to_be16((SYNTAX << 15) | (ONE << 14) | (ONES << 12)); | |
| 1608 | + | |
| 1609 | + nit->header.id = cpu_to_be16(network_id); | |
| 1610 | + nit->header.current_next = ONE; | |
| 1611 | + | |
| 1612 | + nit->header.version = 0x1f; | |
| 1613 | + | |
| 1614 | + nit->header.one2 = ONES; | |
| 1615 | + nit->header.section_id = 0; | |
| 1616 | + nit->header.last_section = 0; | |
| 1617 | + | |
| 1618 | + nit->bitfield = cpu_to_be16(0xf); | |
| 1619 | + nit->bitfield2 = cpu_to_be16(0xf); | |
| 1620 | + | |
| 1621 | + nit->descriptor = (struct vidtv_psi_desc *) | |
| 1622 | + vidtv_psi_network_name_desc_init(NULL, network_name); | |
| 1623 | + if (!nit->descriptor) | |
| 1624 | + goto free_transport; | |
| 1625 | + | |
| 1626 | + transport->transport_id = cpu_to_be16(transport_stream_id); | |
| 1627 | + transport->network_id = cpu_to_be16(network_id); | |
| 1628 | + transport->bitfield = cpu_to_be16(0xf); | |
| 1629 | + transport->descriptor = (struct vidtv_psi_desc *) | |
| 1630 | + vidtv_psi_service_list_desc_init(NULL, service_list); | |
| 1631 | + if (!transport->descriptor) | |
| 1632 | + goto free_nit_desc; | |
| 1633 | + | |
| 1634 | + nit->transport = transport; | |
| 1635 | + | |
| 1636 | + vidtv_psi_nit_table_update_sec_len(nit); | |
| 1637 | + | |
| 1638 | + return nit; | |
| 1639 | + | |
| 1640 | +free_nit_desc: | |
| 1641 | + vidtv_psi_desc_destroy((struct vidtv_psi_desc *)nit->descriptor); | |
| 1642 | + | |
| 1643 | +free_transport: | |
| 1644 | + kfree(transport); | |
| 1645 | +free_nit: | |
| 1646 | + kfree(nit); | |
| 1647 | + return NULL; | |
| 1648 | +} | |
| 1649 | + | |
| 1650 | +u32 vidtv_psi_nit_write_into(struct vidtv_psi_nit_write_args *args) | |
| 1651 | +{ | |
| 1652 | + struct header_write_args h_args = { | |
| 1653 | + .dest_buf = args->buf, | |
| 1654 | + .dest_offset = args->offset, | |
| 1655 | + .h = &args->nit->header, | |
| 1656 | + .pid = VIDTV_NIT_PID, | |
| 1657 | + .dest_buf_sz = args->buf_sz, | |
| 1658 | + }; | |
| 1659 | + struct psi_write_args psi_args = { | |
| 1660 | + .dest_buf = args->buf, | |
| 1661 | + .from = &args->nit->bitfield, | |
| 1662 | + .len = sizeof_field(struct vidtv_psi_table_nit, bitfield), | |
| 1663 | + .pid = VIDTV_NIT_PID, | |
| 1664 | + .new_psi_section = false, | |
| 1665 | + .is_crc = false, | |
| 1666 | + .dest_buf_sz = args->buf_sz, | |
| 1667 | + }; | |
| 1668 | + struct desc_write_args d_args = { | |
| 1669 | + .dest_buf = args->buf, | |
| 1670 | + .pid = VIDTV_NIT_PID, | |
| 1671 | + .dest_buf_sz = args->buf_sz, | |
| 1672 | + }; | |
| 1673 | + struct crc32_write_args c_args = { | |
| 1674 | + .dest_buf = args->buf, | |
| 1675 | + .pid = VIDTV_NIT_PID, | |
| 1676 | + .dest_buf_sz = args->buf_sz, | |
| 1677 | + }; | |
| 1678 | + struct vidtv_psi_desc *table_descriptor = args->nit->descriptor; | |
| 1679 | + struct vidtv_psi_table_transport *transport = args->nit->transport; | |
| 1680 | + struct vidtv_psi_desc *transport_descriptor; | |
| 1681 | + u32 crc = INITIAL_CRC; | |
| 1682 | + u32 nbytes = 0; | |
| 1683 | + | |
| 1684 | + vidtv_psi_nit_table_update_sec_len(args->nit); | |
| 1685 | + | |
| 1686 | + h_args.continuity_counter = args->continuity_counter; | |
| 1687 | + h_args.crc = &crc; | |
| 1688 | + | |
| 1689 | + nbytes += vidtv_psi_table_header_write_into(&h_args); | |
| 1690 | + | |
| 1691 | + /* write the bitfield */ | |
| 1692 | + | |
| 1693 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1694 | + psi_args.continuity_counter = args->continuity_counter; | |
| 1695 | + psi_args.crc = &crc; | |
| 1696 | + | |
| 1697 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 1698 | + | |
| 1699 | + while (table_descriptor) { | |
| 1700 | + /* write the descriptors, if any */ | |
| 1701 | + d_args.dest_offset = args->offset + nbytes; | |
| 1702 | + d_args.desc = table_descriptor; | |
| 1703 | + d_args.continuity_counter = args->continuity_counter; | |
| 1704 | + d_args.crc = &crc; | |
| 1705 | + | |
| 1706 | + nbytes += vidtv_psi_desc_write_into(&d_args); | |
| 1707 | + | |
| 1708 | + table_descriptor = table_descriptor->next; | |
| 1709 | + } | |
| 1710 | + | |
| 1711 | + /* write the second bitfield */ | |
| 1712 | + psi_args.from = &args->nit->bitfield2; | |
| 1713 | + psi_args.len = sizeof_field(struct vidtv_psi_table_nit, bitfield2); | |
| 1714 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1715 | + | |
| 1716 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 1717 | + | |
| 1718 | + psi_args.len = sizeof_field(struct vidtv_psi_table_transport, transport_id) + | |
| 1719 | + sizeof_field(struct vidtv_psi_table_transport, network_id) + | |
| 1720 | + sizeof_field(struct vidtv_psi_table_transport, bitfield); | |
| 1721 | + while (transport) { | |
| 1722 | + /* write the transport sections, if any */ | |
| 1723 | + psi_args.from = transport; | |
| 1724 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1725 | + | |
| 1726 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 1727 | + | |
| 1728 | + transport_descriptor = transport->descriptor; | |
| 1729 | + | |
| 1730 | + while (transport_descriptor) { | |
| 1731 | + /* write the transport descriptors, if any */ | |
| 1732 | + d_args.dest_offset = args->offset + nbytes; | |
| 1733 | + d_args.desc = transport_descriptor; | |
| 1734 | + d_args.continuity_counter = args->continuity_counter; | |
| 1735 | + d_args.crc = &crc; | |
| 1736 | + | |
| 1737 | + nbytes += vidtv_psi_desc_write_into(&d_args); | |
| 1738 | + | |
| 1739 | + transport_descriptor = transport_descriptor->next; | |
| 1740 | + } | |
| 1741 | + | |
| 1742 | + transport = transport->next; | |
| 1743 | + } | |
| 1744 | + | |
| 1745 | + c_args.dest_offset = args->offset + nbytes; | |
| 1746 | + c_args.crc = cpu_to_be32(crc); | |
| 1747 | + c_args.continuity_counter = args->continuity_counter; | |
| 1748 | + | |
| 1749 | + /* Write the CRC32 at the end */ | |
| 1750 | + nbytes += table_section_crc32_write_into(&c_args); | |
| 1751 | + | |
| 1752 | + return nbytes; | |
| 1753 | +} | |
| 1754 | + | |
| 1755 | +static void vidtv_psi_transport_destroy(struct vidtv_psi_table_transport *t) | |
| 1756 | +{ | |
| 1757 | + struct vidtv_psi_table_transport *tmp_t = NULL; | |
| 1758 | + struct vidtv_psi_table_transport *curr_t = t; | |
| 1759 | + | |
| 1760 | + while (curr_t) { | |
| 1761 | + tmp_t = curr_t; | |
| 1762 | + curr_t = curr_t->next; | |
| 1763 | + vidtv_psi_desc_destroy(tmp_t->descriptor); | |
| 1764 | + kfree(tmp_t); | |
| 1765 | + } | |
| 1766 | +} | |
| 1767 | + | |
| 1768 | +void vidtv_psi_nit_table_destroy(struct vidtv_psi_table_nit *nit) | |
| 1769 | +{ | |
| 1770 | + vidtv_psi_desc_destroy(nit->descriptor); | |
| 1771 | + vidtv_psi_transport_destroy(nit->transport); | |
| 1772 | + kfree(nit); | |
| 1773 | +} | |
| 1774 | + | |
| 1775 | +void vidtv_psi_eit_table_update_sec_len(struct vidtv_psi_table_eit *eit) | |
| 1776 | +{ | |
| 1777 | + struct vidtv_psi_table_eit_event *e = eit->event; | |
| 1778 | + u16 desc_loop_len; | |
| 1779 | + u16 length = 0; | |
| 1780 | + | |
| 1781 | + /* | |
| 1782 | + * from immediately after 'section_length' until | |
| 1783 | + * 'last_table_id' | |
| 1784 | + */ | |
| 1785 | + length += EIT_LEN_UNTIL_LAST_TABLE_ID; | |
| 1786 | + | |
| 1787 | + while (e) { | |
| 1788 | + /* skip both pointers at the end */ | |
| 1789 | + length += sizeof(struct vidtv_psi_table_eit_event) - | |
| 1790 | + sizeof(struct vidtv_psi_desc *) - | |
| 1791 | + sizeof(struct vidtv_psi_table_eit_event *); | |
| 1792 | + | |
| 1793 | + desc_loop_len = vidtv_psi_desc_comp_loop_len(e->descriptor); | |
| 1794 | + vidtv_psi_set_desc_loop_len(&e->bitfield, desc_loop_len, 12); | |
| 1795 | + | |
| 1796 | + length += desc_loop_len; | |
| 1797 | + | |
| 1798 | + e = e->next; | |
| 1799 | + } | |
| 1800 | + | |
| 1801 | + length += CRC_SIZE_IN_BYTES; | |
| 1802 | + | |
| 1803 | + vidtv_psi_set_sec_len(&eit->header, length); | |
| 1804 | +} | |
| 1805 | + | |
| 1806 | +void vidtv_psi_eit_event_assign(struct vidtv_psi_table_eit *eit, | |
| 1807 | + struct vidtv_psi_table_eit_event *e) | |
| 1808 | +{ | |
| 1809 | + do { | |
| 1810 | + if (e == eit->event) | |
| 1811 | + return; | |
| 1812 | + | |
| 1813 | + eit->event = e; | |
| 1814 | + vidtv_psi_eit_table_update_sec_len(eit); | |
| 1815 | + | |
| 1816 | + e = NULL; | |
| 1817 | + } while (vidtv_psi_get_sec_len(&eit->header) > EIT_MAX_SECTION_LEN); | |
| 1818 | + | |
| 1819 | + vidtv_psi_update_version_num(&eit->header); | |
| 1820 | +} | |
| 1821 | + | |
| 1822 | +struct vidtv_psi_table_eit | |
| 1823 | +*vidtv_psi_eit_table_init(u16 network_id, | |
| 1824 | + u16 transport_stream_id, | |
| 1825 | + __be16 service_id) | |
| 1826 | +{ | |
| 1827 | + struct vidtv_psi_table_eit *eit; | |
| 1828 | + const u16 SYNTAX = 0x1; | |
| 1829 | + const u16 ONE = 0x1; | |
| 1830 | + const u16 ONES = 0x03; | |
| 1831 | + | |
| 1832 | + eit = kzalloc(sizeof(*eit), GFP_KERNEL); | |
| 1833 | + if (!eit) | |
| 1834 | + return NULL; | |
| 1835 | + | |
| 1836 | + eit->header.table_id = 0x4e; //actual_transport_stream: present/following | |
| 1837 | + | |
| 1838 | + eit->header.bitfield = cpu_to_be16((SYNTAX << 15) | (ONE << 14) | (ONES << 12)); | |
| 1839 | + | |
| 1840 | + eit->header.id = service_id; | |
| 1841 | + eit->header.current_next = ONE; | |
| 1842 | + | |
| 1843 | + eit->header.version = 0x1f; | |
| 1844 | + | |
| 1845 | + eit->header.one2 = ONES; | |
| 1846 | + eit->header.section_id = 0; | |
| 1847 | + eit->header.last_section = 0; | |
| 1848 | + | |
| 1849 | + eit->transport_id = cpu_to_be16(transport_stream_id); | |
| 1850 | + eit->network_id = cpu_to_be16(network_id); | |
| 1851 | + | |
| 1852 | + eit->last_segment = eit->header.last_section; /* not implemented */ | |
| 1853 | + eit->last_table_id = eit->header.table_id; /* not implemented */ | |
| 1854 | + | |
| 1855 | + vidtv_psi_eit_table_update_sec_len(eit); | |
| 1856 | + | |
| 1857 | + return eit; | |
| 1858 | +} | |
| 1859 | + | |
| 1860 | +u32 vidtv_psi_eit_write_into(struct vidtv_psi_eit_write_args *args) | |
| 1861 | +{ | |
| 1862 | + struct header_write_args h_args = { | |
| 1863 | + .dest_buf = args->buf, | |
| 1864 | + .dest_offset = args->offset, | |
| 1865 | + .h = &args->eit->header, | |
| 1866 | + .pid = VIDTV_EIT_PID, | |
| 1867 | + .dest_buf_sz = args->buf_sz, | |
| 1868 | + }; | |
| 1869 | + struct psi_write_args psi_args = { | |
| 1870 | + .dest_buf = args->buf, | |
| 1871 | + .len = sizeof_field(struct vidtv_psi_table_eit, transport_id) + | |
| 1872 | + sizeof_field(struct vidtv_psi_table_eit, network_id) + | |
| 1873 | + sizeof_field(struct vidtv_psi_table_eit, last_segment) + | |
| 1874 | + sizeof_field(struct vidtv_psi_table_eit, last_table_id), | |
| 1875 | + .pid = VIDTV_EIT_PID, | |
| 1876 | + .new_psi_section = false, | |
| 1877 | + .is_crc = false, | |
| 1878 | + .dest_buf_sz = args->buf_sz, | |
| 1879 | + }; | |
| 1880 | + struct desc_write_args d_args = { | |
| 1881 | + .dest_buf = args->buf, | |
| 1882 | + .pid = VIDTV_EIT_PID, | |
| 1883 | + .dest_buf_sz = args->buf_sz, | |
| 1884 | + }; | |
| 1885 | + struct crc32_write_args c_args = { | |
| 1886 | + .dest_buf = args->buf, | |
| 1887 | + .pid = VIDTV_EIT_PID, | |
| 1888 | + .dest_buf_sz = args->buf_sz, | |
| 1889 | + }; | |
| 1890 | + struct vidtv_psi_table_eit_event *event = args->eit->event; | |
| 1891 | + struct vidtv_psi_desc *event_descriptor; | |
| 1892 | + u32 crc = INITIAL_CRC; | |
| 1893 | + u32 nbytes = 0; | |
| 1894 | + | |
| 1895 | + vidtv_psi_eit_table_update_sec_len(args->eit); | |
| 1896 | + | |
| 1897 | + h_args.continuity_counter = args->continuity_counter; | |
| 1898 | + h_args.crc = &crc; | |
| 1899 | + | |
| 1900 | + nbytes += vidtv_psi_table_header_write_into(&h_args); | |
| 1901 | + | |
| 1902 | + psi_args.from = &args->eit->transport_id; | |
| 1903 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1904 | + psi_args.continuity_counter = args->continuity_counter; | |
| 1905 | + psi_args.crc = &crc; | |
| 1906 | + | |
| 1907 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 1908 | + | |
| 1909 | + /* skip both pointers at the end */ | |
| 1910 | + psi_args.len = sizeof(struct vidtv_psi_table_eit_event) - | |
| 1911 | + sizeof(struct vidtv_psi_desc *) - | |
| 1912 | + sizeof(struct vidtv_psi_table_eit_event *); | |
| 1913 | + while (event) { | |
| 1914 | + /* copy the events, if any */ | |
| 1915 | + psi_args.from = event; | |
| 1916 | + psi_args.dest_offset = args->offset + nbytes; | |
| 1917 | + | |
| 1918 | + nbytes += vidtv_psi_ts_psi_write_into(&psi_args); | |
| 1919 | + | |
| 1920 | + event_descriptor = event->descriptor; | |
| 1921 | + | |
| 1922 | + while (event_descriptor) { | |
| 1923 | + /* copy the event descriptors, if any */ | |
| 1924 | + d_args.dest_offset = args->offset + nbytes; | |
| 1925 | + d_args.desc = event_descriptor; | |
| 1926 | + d_args.continuity_counter = args->continuity_counter; | |
| 1927 | + d_args.crc = &crc; | |
| 1928 | + | |
| 1929 | + nbytes += vidtv_psi_desc_write_into(&d_args); | |
| 1930 | + | |
| 1931 | + event_descriptor = event_descriptor->next; | |
| 1932 | + } | |
| 1933 | + | |
| 1934 | + event = event->next; | |
| 1935 | + } | |
| 1936 | + | |
| 1937 | + c_args.dest_offset = args->offset + nbytes; | |
| 1938 | + c_args.crc = cpu_to_be32(crc); | |
| 1939 | + c_args.continuity_counter = args->continuity_counter; | |
| 1940 | + | |
| 1941 | + /* Write the CRC at the end */ | |
| 1942 | + nbytes += table_section_crc32_write_into(&c_args); | |
| 1943 | + | |
| 1944 | + return nbytes; | |
| 1945 | +} | |
| 1946 | + | |
| 1947 | +struct vidtv_psi_table_eit_event | |
| 1948 | +*vidtv_psi_eit_event_init(struct vidtv_psi_table_eit_event *head, u16 event_id) | |
| 1949 | +{ | |
| 1950 | + const u8 DURATION[] = {0x23, 0x59, 0x59}; /* BCD encoded */ | |
| 1951 | + struct vidtv_psi_table_eit_event *e; | |
| 1952 | + struct timespec64 ts; | |
| 1953 | + struct tm time; | |
| 1954 | + int mjd, l; | |
| 1955 | + __be16 mjd_be; | |
| 1956 | + | |
| 1957 | + e = kzalloc(sizeof(*e), GFP_KERNEL); | |
| 1958 | + if (!e) | |
| 1959 | + return NULL; | |
| 1960 | + | |
| 1961 | + e->event_id = cpu_to_be16(event_id); | |
| 1962 | + | |
| 1963 | + ts = ktime_to_timespec64(ktime_get_real()); | |
| 1964 | + time64_to_tm(ts.tv_sec, 0, &time); | |
| 1965 | + | |
| 1966 | + /* Convert date to Modified Julian Date - per EN 300 468 Annex C */ | |
| 1967 | + if (time.tm_mon < 2) | |
| 1968 | + l = 1; | |
| 1969 | + else | |
| 1970 | + l = 0; | |
| 1971 | + | |
| 1972 | + mjd = 14956 + time.tm_mday; | |
| 1973 | + mjd += (time.tm_year - l) * 36525 / 100; | |
| 1974 | + mjd += (time.tm_mon + 2 + l * 12) * 306001 / 10000; | |
| 1975 | + mjd_be = cpu_to_be16(mjd); | |
| 1976 | + | |
| 1977 | + /* | |
| 1978 | + * Store MJD and hour/min/sec to the event. | |
| 1979 | + * | |
| 1980 | + * Let's make the event to start on a full hour | |
| 1981 | + */ | |
| 1982 | + memcpy(e->start_time, &mjd_be, sizeof(mjd_be)); | |
| 1983 | + e->start_time[2] = bin2bcd(time.tm_hour); | |
| 1984 | + e->start_time[3] = 0; | |
| 1985 | + e->start_time[4] = 0; | |
| 1986 | + | |
| 1987 | + /* | |
| 1988 | + * TODO: for now, the event will last for a day. Should be | |
| 1989 | + * enough for testing purposes, but if one runs the driver | |
| 1990 | + * for more than that, the current event will become invalid. | |
| 1991 | + * So, we need a better code here in order to change the start | |
| 1992 | + * time once the event expires. | |
| 1993 | + */ | |
| 1994 | + memcpy(e->duration, DURATION, sizeof(e->duration)); | |
| 1995 | + | |
| 1996 | + e->bitfield = cpu_to_be16(RUNNING << 13); | |
| 1997 | + | |
| 1998 | + if (head) { | |
| 1999 | + while (head->next) | |
| 2000 | + head = head->next; | |
| 2001 | + | |
| 2002 | + head->next = e; | |
| 2003 | + } | |
| 2004 | + | |
| 2005 | + return e; | |
| 2006 | +} | |
| 2007 | + | |
| 2008 | +void vidtv_psi_eit_event_destroy(struct vidtv_psi_table_eit_event *e) | |
| 2009 | +{ | |
| 2010 | + struct vidtv_psi_table_eit_event *tmp_e = NULL; | |
| 2011 | + struct vidtv_psi_table_eit_event *curr_e = e; | |
| 2012 | + | |
| 2013 | + while (curr_e) { | |
| 2014 | + tmp_e = curr_e; | |
| 2015 | + curr_e = curr_e->next; | |
| 2016 | + vidtv_psi_desc_destroy(tmp_e->descriptor); | |
| 2017 | + kfree(tmp_e); | |
| 2018 | + } | |
| 2019 | +} | |
| 2020 | + | |
| 2021 | +void vidtv_psi_eit_table_destroy(struct vidtv_psi_table_eit *eit) | |
| 2022 | +{ | |
| 2023 | + vidtv_psi_eit_event_destroy(eit->event); | |
| 2024 | + kfree(eit); | |
| 2025 | +} | |
| @@ -6,10 +6,6 @@ · 5 unmodified lines | ||
| 6 | 6 | * technically be broken into one or more sections, we do not do this here, |
| 7 | 7 | * hence 'table' and 'section' are interchangeable for vidtv. |
| 8 | 8 | * |
| 9 | − * This code currently supports three tables: PAT, PMT and SDT. These are the | |
| 10 | − * bare minimum to get userspace to recognize our MPEG transport stream. It can | |
| 11 | − * be extended to support more PSI tables in the future. | |
| 12 | − * | |
| 13 | 9 | * Copyright (C) 2020 Daniel W. S. Almeida |
| 14 | 10 | */ |
| 15 | 11 | |
| @@ -17,7 +13,6 @@ · 1 unmodified line | ||
| 17 | 13 | #define VIDTV_PSI_H |
| 18 | 14 | |
| 19 | 15 | #include <linux/types.h> |
| 20 | −#include <asm/byteorder.h> | |
| 21 | 16 | |
| 22 | 17 | /* |
| 23 | 18 | * all section lengths start immediately after the 'section_length' field |
| @@ -27,20 +22,28 @@ · 3 unmodified lines | ||
| 27 | 22 | #define PAT_LEN_UNTIL_LAST_SECTION_NUMBER 5 |
| 28 | 23 | #define PMT_LEN_UNTIL_PROGRAM_INFO_LENGTH 9 |
| 29 | 24 | #define SDT_LEN_UNTIL_RESERVED_FOR_FUTURE_USE 8 |
| 25 | +#define NIT_LEN_UNTIL_NETWORK_DESCRIPTOR_LEN 7 | |
| 26 | +#define EIT_LEN_UNTIL_LAST_TABLE_ID 11 | |
| 30 | 27 | #define MAX_SECTION_LEN 1021 |
| 28 | +#define EIT_MAX_SECTION_LEN 4093 /* see ETSI 300 468 v.1.10.1 p. 26 */ | |
| 31 | 29 | #define VIDTV_PAT_PID 0 /* mandated by the specs */ |
| 32 | 30 | #define VIDTV_SDT_PID 0x0011 /* mandated by the specs */ |
| 31 | +#define VIDTV_NIT_PID 0x0010 /* mandated by the specs */ | |
| 32 | +#define VIDTV_EIT_PID 0x0012 /*mandated by the specs */ | |
| 33 | 33 | |
| 34 | 34 | enum vidtv_psi_descriptors { |
| 35 | 35 | REGISTRATION_DESCRIPTOR = 0x05, /* See ISO/IEC 13818-1 section 2.6.8 */ |
| 36 | + NETWORK_NAME_DESCRIPTOR = 0x40, /* See ETSI EN 300 468 section 6.2.27 */ | |
| 37 | + SERVICE_LIST_DESCRIPTOR = 0x41, /* See ETSI EN 300 468 section 6.2.35 */ | |
| 36 | 38 | SERVICE_DESCRIPTOR = 0x48, /* See ETSI EN 300 468 section 6.2.33 */ |
| 39 | + SHORT_EVENT_DESCRIPTOR = 0x4d, /* See ETSI EN 300 468 section 6.2.37 */ | |
| 37 | 40 | }; |
| 38 | 41 | |
| 39 | 42 | enum vidtv_psi_stream_types { |
| 40 | 43 | STREAM_PRIVATE_DATA = 0x06, /* see ISO/IEC 13818-1 2000 p. 48 */ |
| 41 | 44 | }; |
| 42 | 45 | |
| 43 | −/** | |
| 46 | +/* | |
| 44 | 47 | * struct vidtv_psi_desc - A generic PSI descriptor type. |
| 45 | 48 | * The descriptor length is an 8-bit field specifying the total number of bytes of the data portion |
| 46 | 49 | * of the descriptor following the byte defining the value of this field. |
| @@ -52,7 +55,7 @@ struct vidtv_psi_desc { · 5 unmodified lines | ||
| 52 | 55 | u8 data[]; |
| 53 | 56 | } __packed; |
| 54 | 57 | |
| 55 | −/** | |
| 58 | +/* | |
| 56 | 59 | * struct vidtv_psi_desc_service - Service descriptor. |
| 57 | 60 | * See ETSI EN 300 468 section 6.2.33. |
| 58 | 61 | */ |
| @@ -68,7 +71,7 @@ struct vidtv_psi_desc_service { · 9 unmodified lines | ||
| 68 | 71 | char *service_name; |
| 69 | 72 | } __packed; |
| 70 | 73 | |
| 71 | −/** | |
| 74 | +/* | |
| 72 | 75 | * struct vidtv_psi_desc_registration - A registration descriptor. |
| 73 | 76 | * See ISO/IEC 13818-1 section 2.6.8 |
| 74 | 77 | */ |
| @@ -90,7 +93,56 @@ struct vidtv_psi_desc_registration { · 15 unmodified lines | ||
| 90 | 93 | u8 additional_identification_info[]; |
| 91 | 94 | } __packed; |
| 92 | 95 | |
| 93 | −/** | |
| 96 | +/* | |
| 97 | + * struct vidtv_psi_desc_network_name - A network name descriptor | |
| 98 | + * see ETSI EN 300 468 v1.15.1 section 6.2.27 | |
| 99 | + */ | |
| 100 | +struct vidtv_psi_desc_network_name { | |
| 101 | + struct vidtv_psi_desc *next; | |
| 102 | + u8 type; | |
| 103 | + u8 length; | |
| 104 | + char *network_name; | |
| 105 | +} __packed; | |
| 106 | + | |
| 107 | +struct vidtv_psi_desc_service_list_entry { | |
| 108 | + __be16 service_id; | |
| 109 | + u8 service_type; | |
| 110 | + struct vidtv_psi_desc_service_list_entry *next; | |
| 111 | +} __packed; | |
| 112 | + | |
| 113 | +/* | |
| 114 | + * struct vidtv_psi_desc_service_list - A service list descriptor | |
| 115 | + * see ETSI EN 300 468 v1.15.1 section 6.2.35 | |
| 116 | + */ | |
| 117 | +struct vidtv_psi_desc_service_list { | |
| 118 | + struct vidtv_psi_desc *next; | |
| 119 | + u8 type; | |
| 120 | + u8 length; | |
| 121 | + struct vidtv_psi_desc_service_list_entry *service_list; | |
| 122 | +} __packed; | |
| 123 | + | |
| 124 | +/* | |
| 125 | + * struct vidtv_psi_desc_short_event - A short event descriptor | |
| 126 | + * see ETSI EN 300 468 v1.15.1 section 6.2.37 | |
| 127 | + */ | |
| 128 | +struct vidtv_psi_desc_short_event { | |
| 129 | + struct vidtv_psi_desc *next; | |
| 130 | + u8 type; | |
| 131 | + u8 length; | |
| 132 | + char *iso_language_code; | |
| 133 | + u8 event_name_len; | |
| 134 | + char *event_name; | |
| 135 | + u8 text_len; | |
| 136 | + char *text; | |
| 137 | +} __packed; | |
| 138 | + | |
| 139 | +struct vidtv_psi_desc_short_event | |
| 140 | +*vidtv_psi_short_event_desc_init(struct vidtv_psi_desc *head, | |
| 141 | + char *iso_language_code, | |
| 142 | + char *event_name, | |
| 143 | + char *text); | |
| 144 | + | |
| 145 | +/* | |
| 94 | 146 | * struct vidtv_psi_table_header - A header that is present for all PSI tables. |
| 95 | 147 | */ |
| 96 | 148 | struct vidtv_psi_table_header { |
| @@ -106,7 +158,7 @@ struct vidtv_psi_table_header { · 9 unmodified lines | ||
| 106 | 158 | u8 last_section; /* last_section_number */ |
| 107 | 159 | } __packed; |
| 108 | 160 | |
| 109 | −/** | |
| 161 | +/* | |
| 110 | 162 | * struct vidtv_psi_table_pat_program - A single program in the PAT |
| 111 | 163 | * See ISO/IEC 13818-1 : 2000 p.43 |
| 112 | 164 | */ |
| @@ -116,17 +168,18 @@ struct vidtv_psi_table_pat_program { · 3 unmodified lines | ||
| 116 | 168 | struct vidtv_psi_table_pat_program *next; |
| 117 | 169 | } __packed; |
| 118 | 170 | |
| 119 | −/** | |
| 171 | +/* | |
| 120 | 172 | * struct vidtv_psi_table_pat - The Program Allocation Table (PAT) |
| 121 | 173 | * See ISO/IEC 13818-1 : 2000 p.43 |
| 122 | 174 | */ |
| 123 | 175 | struct vidtv_psi_table_pat { |
| 124 | 176 | struct vidtv_psi_table_header header; |
| 125 | − u16 programs; /* Included by libdvbv5, not part of the table and not actually serialized */ | |
| 177 | + u16 num_pat; | |
| 178 | + u16 num_pmt; | |
| 126 | 179 | struct vidtv_psi_table_pat_program *program; |
| 127 | 180 | } __packed; |
| 128 | 181 | |
| 129 | −/** | |
| 182 | +/* | |
| 130 | 183 | * struct vidtv_psi_table_sdt_service - Represents a service in the SDT. |
| 131 | 184 | * see ETSI EN 300 468 v1.15.1 section 5.2.3. |
| 132 | 185 | */ |
| @@ -140,7 +193,7 @@ struct vidtv_psi_table_sdt_service { · 7 unmodified lines | ||
| 140 | 193 | struct vidtv_psi_table_sdt_service *next; |
| 141 | 194 | } __packed; |
| 142 | 195 | |
| 143 | −/** | |
| 196 | +/* | |
| 144 | 197 | * struct vidtv_psi_table_sdt - Represents the Service Description Table |
| 145 | 198 | * see ETSI EN 300 468 v1.15.1 section 5.2.3. |
| 146 | 199 | */ |
| @@ -152,7 +205,7 @@ struct vidtv_psi_table_sdt { · 5 unmodified lines | ||
| 152 | 205 | struct vidtv_psi_table_sdt_service *service; |
| 153 | 206 | } __packed; |
| 154 | 207 | |
| 155 | −/** | |
| 208 | +/* | |
| 156 | 209 | * enum service_running_status - Status of a SDT service. |
| 157 | 210 | * see ETSI EN 300 468 v1.15.1 section 5.2.3 table 6. |
| 158 | 211 | */ |
| @@ -160,16 +213,17 @@ enum service_running_status { · 1 unmodified line | ||
| 160 | 213 | RUNNING = 0x4, |
| 161 | 214 | }; |
| 162 | 215 | |
| 163 | −/** | |
| 216 | +/* | |
| 164 | 217 | * enum service_type - The type of a SDT service. |
| 165 | 218 | * see ETSI EN 300 468 v1.15.1 section 6.2.33, table 81. |
| 166 | 219 | */ |
| 167 | 220 | enum service_type { |
| 168 | 221 | /* see ETSI EN 300 468 v1.15.1 p. 77 */ |
| 169 | 222 | DIGITAL_TELEVISION_SERVICE = 0x1, |
| 223 | + DIGITAL_RADIO_SOUND_SERVICE = 0X2, | |
| 170 | 224 | }; |
| 171 | 225 | |
| 172 | −/** | |
| 226 | +/* | |
| 173 | 227 | * struct vidtv_psi_table_pmt_stream - A single stream in the PMT. |
| 174 | 228 | * See ISO/IEC 13818-1 : 2000 p.46. |
| 175 | 229 | */ |
| @@ -181,7 +235,7 @@ struct vidtv_psi_table_pmt_stream { · 5 unmodified lines | ||
| 181 | 235 | struct vidtv_psi_table_pmt_stream *next; |
| 182 | 236 | } __packed; |
| 183 | 237 | |
| 184 | −/** | |
| 238 | +/* | |
| 185 | 239 | * struct vidtv_psi_table_pmt - The Program Map Table (PMT). |
| 186 | 240 | * See ISO/IEC 13818-1 : 2000 p.46. |
| 187 | 241 | */ |
| @@ -290,6 +344,13 @@ struct vidtv_psi_desc_registration · 102 unmodified lines | ||
| 290 | 344 | u8 *additional_ident_info, |
| 291 | 345 | u32 additional_info_len); |
| 292 | 346 | |
| 347 | +struct vidtv_psi_desc_network_name | |
| 348 | +*vidtv_psi_network_name_desc_init(struct vidtv_psi_desc *head, char *network_name); | |
| 349 | + | |
| 350 | +struct vidtv_psi_desc_service_list | |
| 351 | +*vidtv_psi_service_list_desc_init(struct vidtv_psi_desc *head, | |
| 352 | + struct vidtv_psi_desc_service_list_entry *entry); | |
| 353 | + | |
| 293 | 354 | struct vidtv_psi_table_pat_program |
| 294 | 355 | *vidtv_psi_pat_program_init(struct vidtv_psi_table_pat_program *head, |
| 295 | 356 | u16 service_id, |
| @@ -305,11 +366,14 @@ struct vidtv_psi_table_pat *vidtv_psi_pat_table_init(u16 transport_stream_id); · 9 unmodified lines | ||
| 305 | 366 | struct vidtv_psi_table_pmt *vidtv_psi_pmt_table_init(u16 program_number, |
| 306 | 367 | u16 pcr_pid); |
| 307 | 368 | |
| 308 | −struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 transport_stream_id); | |
| 369 | +struct vidtv_psi_table_sdt *vidtv_psi_sdt_table_init(u16 network_id, | |
| 370 | + u16 transport_stream_id); | |
| 309 | 371 | |
| 310 | 372 | struct vidtv_psi_table_sdt_service* |
| 311 | 373 | vidtv_psi_sdt_service_init(struct vidtv_psi_table_sdt_service *head, |
| 312 | − u16 service_id); | |
| 374 | + u16 service_id, | |
| 375 | + bool eit_schedule, | |
| 376 | + bool eit_present_following); | |
| 313 | 377 | |
| 314 | 378 | void |
| 315 | 379 | vidtv_psi_desc_destroy(struct vidtv_psi_desc *desc); |
| @@ -413,7 +477,6 @@ struct vidtv_psi_desc *vidtv_psi_desc_clone(struct vidtv_psi_desc *desc); · 97 unmodified lines | ||
| 413 | 477 | * vidtv_psi_create_sec_for_each_pat_entry - Create a PMT section for each |
| 414 | 478 | * program found in the PAT |
| 415 | 479 | * @pat: The PAT to look for programs. |
| 416 | − * @s: The stream loop (one or more streams) | |
| 417 | 480 | * @pcr_pid: packet ID for the PCR to be used for the program described in this |
| 418 | 481 | * PMT section |
| 419 | 482 | */ |
| @@ -492,7 +555,7 @@ struct vidtv_psi_pat_write_args { · 72 unmodified lines | ||
| 492 | 555 | * equal to the size of the PAT, since more space is needed for TS headers during TS |
| 493 | 556 | * encapsulation. |
| 494 | 557 | */ |
| 495 | −u32 vidtv_psi_pat_write_into(struct vidtv_psi_pat_write_args args); | |
| 558 | +u32 vidtv_psi_pat_write_into(struct vidtv_psi_pat_write_args *args); | |
| 496 | 559 | |
| 497 | 560 | /** |
| 498 | 561 | * struct vidtv_psi_sdt_write_args - Arguments for writing a SDT table |
| @@ -524,16 +587,18 @@ struct vidtv_psi_sdt_write_args { · 25 unmodified lines | ||
| 524 | 587 | * equal to the size of the SDT, since more space is needed for TS headers during TS |
| 525 | 588 | * encapsulation. |
| 526 | 589 | */ |
| 527 | −u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args args); | |
| 590 | +u32 vidtv_psi_sdt_write_into(struct vidtv_psi_sdt_write_args *args); | |
| 528 | 591 | |
| 529 | 592 | /** |
| 530 | 593 | * struct vidtv_psi_pmt_write_args - Arguments for writing a PMT section |
| 531 | 594 | * @buf: The destination buffer. |
| 532 | 595 | * @offset: The offset into the destination buffer. |
| 533 | 596 | * @pmt: A pointer to the PMT. |
| 597 | + * @pid: Program ID | |
| 534 | 598 | * @buf_sz: The size of the destination buffer. |
| 535 | 599 | * @continuity_counter: A pointer to the CC. Incremented on every new packet. |
| 536 | − * | |
| 600 | + * @pcr_pid: The TS PID used for the PSI packets. All channels will share the | |
| 601 | + * same PCR. | |
| 537 | 602 | */ |
| 538 | 603 | struct vidtv_psi_pmt_write_args { |
| 539 | 604 | char *buf; |
| @@ -557,7 +622,7 @@ struct vidtv_psi_pmt_write_args { · 17 unmodified lines | ||
| 557 | 622 | * equal to the size of the PMT section, since more space is needed for TS headers |
| 558 | 623 | * during TS encapsulation. |
| 559 | 624 | */ |
| 560 | −u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args args); | |
| 625 | +u32 vidtv_psi_pmt_write_into(struct vidtv_psi_pmt_write_args *args); | |
| 561 | 626 | |
| 562 | 627 | /** |
| 563 | 628 | * vidtv_psi_find_pmt_sec - Finds the PMT section for 'program_num' |
| @@ -574,4 +639,171 @@ struct vidtv_psi_table_pmt *vidtv_psi_find_pmt_sec(struct vidtv_psi_table_pmt ** · 10 unmodified lines | ||
| 574 | 639 | u16 vidtv_psi_get_pat_program_pid(struct vidtv_psi_table_pat_program *p); |
| 575 | 640 | u16 vidtv_psi_pmt_stream_get_elem_pid(struct vidtv_psi_table_pmt_stream *s); |
| 576 | 641 | |
| 642 | +/** | |
| 643 | + * struct vidtv_psi_table_transport - A entry in the TS loop for the NIT and/or other tables. | |
| 644 | + * See ETSI 300 468 section 5.2.1 | |
| 645 | + * @transport_id: The TS ID being described | |
| 646 | + * @network_id: The network_id that contains the TS ID | |
| 647 | + * @bitfield: Contains the descriptor loop length | |
| 648 | + * @descriptor: A descriptor loop | |
| 649 | + * @next: Pointer to the next entry | |
| 650 | + * | |
| 651 | + */ | |
| 652 | +struct vidtv_psi_table_transport { | |
| 653 | + __be16 transport_id; | |
| 654 | + __be16 network_id; | |
| 655 | + __be16 bitfield; /* desc_len: 12, reserved: 4 */ | |
| 656 | + struct vidtv_psi_desc *descriptor; | |
| 657 | + struct vidtv_psi_table_transport *next; | |
| 658 | +} __packed; | |
| 659 | + | |
| 660 | +/** | |
| 661 | + * struct vidtv_psi_table_nit - A Network Information Table (NIT). See ETSI 300 | |
| 662 | + * 468 section 5.2.1 | |
| 663 | + * @header: A PSI table header | |
| 664 | + * @bitfield: Contains the network descriptor length | |
| 665 | + * @descriptor: A descriptor loop describing the network | |
| 666 | + * @bitfield2: Contains the transport stream loop length | |
| 667 | + * @transport: The transport stream loop | |
| 668 | + * | |
| 669 | + */ | |
| 670 | +struct vidtv_psi_table_nit { | |
| 671 | + struct vidtv_psi_table_header header; | |
| 672 | + __be16 bitfield; /* network_desc_len: 12, reserved:4 */ | |
| 673 | + struct vidtv_psi_desc *descriptor; | |
| 674 | + __be16 bitfield2; /* ts_loop_len: 12, reserved: 4 */ | |
| 675 | + struct vidtv_psi_table_transport *transport; | |
| 676 | +} __packed; | |
| 677 | + | |
| 678 | +struct vidtv_psi_table_nit | |
| 679 | +*vidtv_psi_nit_table_init(u16 network_id, | |
| 680 | + u16 transport_stream_id, | |
| 681 | + char *network_name, | |
| 682 | + struct vidtv_psi_desc_service_list_entry *service_list); | |
| 683 | + | |
| 684 | +/** | |
| 685 | + * struct vidtv_psi_nit_write_args - Arguments for writing a NIT section | |
| 686 | + * @buf: The destination buffer. | |
| 687 | + * @offset: The offset into the destination buffer. | |
| 688 | + * @nit: A pointer to the NIT | |
| 689 | + * @buf_sz: The size of the destination buffer. | |
| 690 | + * @continuity_counter: A pointer to the CC. Incremented on every new packet. | |
| 691 | + * | |
| 692 | + */ | |
| 693 | +struct vidtv_psi_nit_write_args { | |
| 694 | + char *buf; | |
| 695 | + u32 offset; | |
| 696 | + struct vidtv_psi_table_nit *nit; | |
| 697 | + u32 buf_sz; | |
| 698 | + u8 *continuity_counter; | |
| 699 | +}; | |
| 700 | + | |
| 701 | +/** | |
| 702 | + * vidtv_psi_nit_write_into - Write NIT as MPEG-TS packets into a buffer. | |
| 703 | + * @args: an instance of struct vidtv_psi_nit_write_args | |
| 704 | + * | |
| 705 | + * This function writes the MPEG TS packets for a NIT table into a buffer. | |
| 706 | + * Calling code will usually generate the NIT via a call to its init function | |
| 707 | + * and thus is responsible for freeing it. | |
| 708 | + * | |
| 709 | + * Return: The number of bytes written into the buffer. This is NOT | |
| 710 | + * equal to the size of the NIT, since more space is needed for TS headers during TS | |
| 711 | + * encapsulation. | |
| 712 | + */ | |
| 713 | +u32 vidtv_psi_nit_write_into(struct vidtv_psi_nit_write_args *args); | |
| 714 | + | |
| 715 | +void vidtv_psi_nit_table_destroy(struct vidtv_psi_table_nit *nit); | |
| 716 | + | |
| 717 | +/* | |
| 718 | + * struct vidtv_psi_desc_short_event - A short event descriptor | |
| 719 | + * see ETSI EN 300 468 v1.15.1 section 6.2.37 | |
| 720 | + */ | |
| 721 | +struct vidtv_psi_table_eit_event { | |
| 722 | + __be16 event_id; | |
| 723 | + u8 start_time[5]; | |
| 724 | + u8 duration[3]; | |
| 725 | + __be16 bitfield; /* desc_length: 12, free_CA_mode: 1, running_status: 1 */ | |
| 726 | + struct vidtv_psi_desc *descriptor; | |
| 727 | + struct vidtv_psi_table_eit_event *next; | |
| 728 | +} __packed; | |
| 729 | + | |
| 730 | +/* | |
| 731 | + * struct vidtv_psi_table_eit - A Event Information Table (EIT) | |
| 732 | + * See ETSI 300 468 section 5.2.4 | |
| 733 | + */ | |
| 734 | +struct vidtv_psi_table_eit { | |
| 735 | + struct vidtv_psi_table_header header; | |
| 736 | + __be16 transport_id; | |
| 737 | + __be16 network_id; | |
| 738 | + u8 last_segment; | |
| 739 | + u8 last_table_id; | |
| 740 | + struct vidtv_psi_table_eit_event *event; | |
| 741 | +} __packed; | |
| 742 | + | |
| 743 | +struct vidtv_psi_table_eit | |
| 744 | +*vidtv_psi_eit_table_init(u16 network_id, | |
| 745 | + u16 transport_stream_id, | |
| 746 | + u16 service_id); | |
| 747 | + | |
| 748 | +/** | |
| 749 | + * struct vidtv_psi_eit_write_args - Arguments for writing an EIT section | |
| 750 | + * @buf: The destination buffer. | |
| 751 | + * @offset: The offset into the destination buffer. | |
| 752 | + * @eit: A pointer to the EIT | |
| 753 | + * @buf_sz: The size of the destination buffer. | |
| 754 | + * @continuity_counter: A pointer to the CC. Incremented on every new packet. | |
| 755 | + * | |
| 756 | + */ | |
| 757 | +struct vidtv_psi_eit_write_args { | |
| 758 | + char *buf; | |
| 759 | + u32 offset; | |
| 760 | + struct vidtv_psi_table_eit *eit; | |
| 761 | + u32 buf_sz; | |
| 762 | + u8 *continuity_counter; | |
| 763 | +}; | |
| 764 | + | |
| 765 | +/** | |
| 766 | + * vidtv_psi_eit_write_into - Write EIT as MPEG-TS packets into a buffer. | |
| 767 | + * @args: an instance of struct vidtv_psi_nit_write_args | |
| 768 | + * | |
| 769 | + * This function writes the MPEG TS packets for a EIT table into a buffer. | |
| 770 | + * Calling code will usually generate the EIT via a call to its init function | |
| 771 | + * and thus is responsible for freeing it. | |
| 772 | + * | |
| 773 | + * Return: The number of bytes written into the buffer. This is NOT | |
| 774 | + * equal to the size of the EIT, since more space is needed for TS headers during TS | |
| 775 | + * encapsulation. | |
| 776 | + */ | |
| 777 | +u32 vidtv_psi_eit_write_into(struct vidtv_psi_eit_write_args *args); | |
| 778 | + | |
| 779 | +void vidtv_psi_eit_table_destroy(struct vidtv_psi_table_eit *eit); | |
| 780 | + | |
| 781 | +/** | |
| 782 | + * vidtv_psi_eit_table_update_sec_len - Recompute and update the EIT section length. | |
| 783 | + * @eit: The EIT whose length is to be updated. | |
| 784 | + * | |
| 785 | + * This will traverse the table and accumulate the length of its components, | |
| 786 | + * which is then used to replace the 'section_length' field. | |
| 787 | + * | |
| 788 | + * If section_length > EIT_MAX_SECTION_LEN, the operation fails. | |
| 789 | + */ | |
| 790 | +void vidtv_psi_eit_table_update_sec_len(struct vidtv_psi_table_eit *eit); | |
| 791 | + | |
| 792 | +/** | |
| 793 | + * vidtv_psi_eit_event_assign - Assigns the event loop to the EIT. | |
| 794 | + * @eit: The EIT to assign to. | |
| 795 | + * @e: The event loop | |
| 796 | + * | |
| 797 | + * This will free the previous event loop in the table. | |
| 798 | + * This will assign ownership of the stream loop to the table, i.e. the table | |
| 799 | + * will free this stream loop when a call to its destroy function is made. | |
| 800 | + */ | |
| 801 | +void vidtv_psi_eit_event_assign(struct vidtv_psi_table_eit *eit, | |
| 802 | + struct vidtv_psi_table_eit_event *e); | |
| 803 | + | |
| 804 | +struct vidtv_psi_table_eit_event | |
| 805 | +*vidtv_psi_eit_event_init(struct vidtv_psi_table_eit_event *head, u16 event_id); | |
| 806 | + | |
| 807 | +void vidtv_psi_eit_event_destroy(struct vidtv_psi_table_eit_event *e); | |
| 808 | + | |
| 577 | 809 | #endif // VIDTV_PSI_H |
| @@ -17,23 +17,22 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s, %d: " fmt, __func__, __LINE__ |
| 19 | 19 | |
| 20 | −#include <linux/types.h> | |
| 21 | −#include <linux/slab.h> | |
| 20 | +#include <linux/bug.h> | |
| 22 | 21 | #include <linux/crc32.h> |
| 23 | −#include <linux/vmalloc.h> | |
| 24 | −#include <linux/string.h> | |
| 25 | −#include <linux/kernel.h> | |
| 22 | +#include <linux/fixp-arith.h> | |
| 26 | 23 | #include <linux/jiffies.h> |
| 24 | +#include <linux/kernel.h> | |
| 25 | +#include <linux/math64.h> | |
| 27 | 26 | #include <linux/printk.h> |
| 28 | 27 | #include <linux/ratelimit.h> |
| 29 | −#include <linux/fixp-arith.h> | |
| 30 | − | |
| 31 | −#include <linux/math64.h> | |
| 32 | −#include <asm/byteorder.h> | |
| 28 | +#include <linux/slab.h> | |
| 29 | +#include <linux/string.h> | |
| 30 | +#include <linux/types.h> | |
| 31 | +#include <linux/vmalloc.h> | |
| 33 | 32 | |
| 34 | −#include "vidtv_s302m.h" | |
| 35 | −#include "vidtv_encoder.h" | |
| 36 | 33 | #include "vidtv_common.h" |
| 34 | +#include "vidtv_encoder.h" | |
| 35 | +#include "vidtv_s302m.h" | |
| 37 | 36 | |
| 38 | 37 | #define S302M_SAMPLING_RATE_HZ 48000 |
| 39 | 38 | #define PES_PRIVATE_STREAM_1 0xbd /* PES: private_stream_1 */ |
| @@ -79,8 +78,9 @@ struct tone_duration { · 39 unmodified lines | ||
| 79 | 78 | int duration; |
| 80 | 79 | }; |
| 81 | 80 | |
| 82 | −#define COMPASS 120 /* beats per minute (Allegro) */ | |
| 83 | −static const struct tone_duration beethoven_5th_symphony[] = { | |
| 81 | +#define COMPASS 100 /* beats per minute */ | |
| 82 | +static const struct tone_duration beethoven_fur_elise[] = { | |
| 83 | + { NOTE_SILENT, 512}, | |
| 84 | 84 | { NOTE_E_6, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, |
| 85 | 85 | { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_B_5, 128}, |
| 86 | 86 | { NOTE_D_6, 128}, { NOTE_C_6, 128}, { NOTE_A_3, 128}, |
| @@ -121,31 +121,36 @@ static const struct tone_duration beethoven_5th_symphony[] = { · 34 unmodified lines | ||
| 121 | 121 | { NOTE_E_5, 128}, { NOTE_D_5, 128}, { NOTE_A_3, 128}, |
| 122 | 122 | { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_E_4, 128}, |
| 123 | 123 | { NOTE_D_5, 128}, { NOTE_C_5, 128}, { NOTE_E_3, 128}, |
| 124 | − { NOTE_E_4, 128}, { NOTE_E_5, 255}, { NOTE_E_6, 128}, | |
| 125 | − { NOTE_E_5, 128}, { NOTE_E_6, 128}, { NOTE_E_5, 255}, | |
| 124 | + { NOTE_E_4, 128}, { NOTE_E_5, 128}, { NOTE_E_5, 128}, | |
| 125 | + { NOTE_E_6, 128}, { NOTE_E_5, 128}, { NOTE_E_6, 128}, | |
| 126 | + { NOTE_E_5, 128}, { NOTE_E_5, 128}, { NOTE_DS_5, 128}, | |
| 127 | + { NOTE_E_5, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, | |
| 126 | 128 | { NOTE_DS_5, 128}, { NOTE_E_5, 128}, { NOTE_DS_6, 128}, |
| 127 | − { NOTE_E_6, 128}, { NOTE_DS_5, 128}, { NOTE_E_5, 128}, | |
| 128 | − { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_DS_6, 128}, | |
| 129 | 129 | { NOTE_E_6, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, |
| 130 | − { NOTE_B_5, 128}, { NOTE_D_6, 128}, { NOTE_C_6, 128}, | |
| 131 | − { NOTE_A_3, 128}, { NOTE_E_4, 128}, { NOTE_A_4, 128}, | |
| 132 | − { NOTE_C_5, 128}, { NOTE_E_5, 128}, { NOTE_A_5, 128}, | |
| 133 | − { NOTE_E_3, 128}, { NOTE_E_4, 128}, { NOTE_GS_4, 128}, | |
| 134 | − { NOTE_E_5, 128}, { NOTE_GS_5, 128}, { NOTE_B_5, 128}, | |
| 135 | − { NOTE_A_3, 128}, { NOTE_E_4, 128}, { NOTE_A_4, 128}, | |
| 136 | − { NOTE_E_5, 128}, { NOTE_E_6, 128}, { NOTE_DS_6, 128}, | |
| 130 | + { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_B_5, 128}, | |
| 131 | + { NOTE_D_6, 128}, { NOTE_C_6, 128}, { NOTE_A_3, 128}, | |
| 132 | + { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_C_5, 128}, | |
| 133 | + { NOTE_E_5, 128}, { NOTE_A_5, 128}, { NOTE_E_3, 128}, | |
| 134 | + { NOTE_E_4, 128}, { NOTE_GS_4, 128}, { NOTE_E_5, 128}, | |
| 135 | + { NOTE_GS_5, 128}, { NOTE_B_5, 128}, { NOTE_A_3, 128}, | |
| 136 | + { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_E_5, 128}, | |
| 137 | 137 | { NOTE_E_6, 128}, { NOTE_DS_6, 128}, { NOTE_E_6, 128}, |
| 138 | − { NOTE_B_5, 128}, { NOTE_D_6, 128}, { NOTE_C_6, 128}, | |
| 139 | − { NOTE_A_3, 128}, { NOTE_E_4, 128}, { NOTE_A_4, 128}, | |
| 140 | − { NOTE_C_5, 128}, { NOTE_E_5, 128}, { NOTE_A_5, 128}, | |
| 141 | − { NOTE_E_3, 128}, { NOTE_E_4, 128}, { NOTE_GS_4, 128}, | |
| 142 | − { NOTE_E_5, 128}, { NOTE_C_6, 128}, { NOTE_B_5, 128}, | |
| 143 | − { NOTE_C_5, 255}, { NOTE_C_5, 255}, { NOTE_SILENT, 512}, | |
| 138 | + { NOTE_DS_6, 128}, { NOTE_E_6, 128}, { NOTE_B_5, 128}, | |
| 139 | + { NOTE_D_6, 128}, { NOTE_C_6, 128}, { NOTE_A_3, 128}, | |
| 140 | + { NOTE_E_4, 128}, { NOTE_A_4, 128}, { NOTE_C_5, 128}, | |
| 141 | + { NOTE_E_5, 128}, { NOTE_A_5, 128}, { NOTE_E_3, 128}, | |
| 142 | + { NOTE_E_4, 128}, { NOTE_GS_4, 128}, { NOTE_E_5, 128}, | |
| 143 | + { NOTE_C_6, 128}, { NOTE_B_5, 128}, { NOTE_A_5, 512}, | |
| 144 | + { NOTE_SILENT, 256}, | |
| 144 | 145 | }; |
| 145 | 146 | |
| 146 | 147 | static struct vidtv_access_unit *vidtv_s302m_access_unit_init(struct vidtv_access_unit *head) |
| 147 | 148 | { |
| 148 | − struct vidtv_access_unit *au = kzalloc(sizeof(*au), GFP_KERNEL); | |
| 149 | + struct vidtv_access_unit *au; | |
| 150 | + | |
| 151 | + au = kzalloc(sizeof(*au), GFP_KERNEL); | |
| 152 | + if (!au) | |
| 153 | + return NULL; | |
| 149 | 154 | |
| 150 | 155 | if (head) { |
| 151 | 156 | while (head->next) |
| @@ -196,10 +201,10 @@ static void vidtv_s302m_alloc_au(struct vidtv_encoder *e) · 44 unmodified lines | ||
| 196 | 201 | static void |
| 197 | 202 | vidtv_s302m_compute_sample_count_from_video(struct vidtv_encoder *e) |
| 198 | 203 | { |
| 199 | − struct vidtv_access_unit *au = e->access_units; | |
| 200 | 204 | struct vidtv_access_unit *sync_au = e->sync->access_units; |
| 201 | − u32 vau_duration_usecs; | |
| 205 | + struct vidtv_access_unit *au = e->access_units; | |
| 202 | 206 | u32 sample_duration_usecs; |
| 207 | + u32 vau_duration_usecs; | |
| 203 | 208 | u32 s; |
| 204 | 209 | |
| 205 | 210 | vau_duration_usecs = USEC_PER_SEC / e->sync->sampling_rate_hz; |
| @@ -230,36 +235,32 @@ static u16 vidtv_s302m_get_sample(struct vidtv_encoder *e) · 24 unmodified lines | ||
| 230 | 235 | { |
| 231 | 236 | u16 sample; |
| 232 | 237 | int pos; |
| 238 | + struct vidtv_s302m_ctx *ctx = e->ctx; | |
| 233 | 239 | |
| 234 | 240 | if (!e->src_buf) { |
| 235 | 241 | /* |
| 236 | 242 | * Simple tone generator: play the tones at the |
| 237 | − * beethoven_5th_symphony array. | |
| 243 | + * beethoven_fur_elise array. | |
| 238 | 244 | */ |
| 239 | − if (e->last_duration <= 0) { | |
| 240 | − if (e->src_buf_offset >= ARRAY_SIZE(beethoven_5th_symphony)) | |
| 245 | + if (ctx->last_duration <= 0) { | |
| 246 | + if (e->src_buf_offset >= ARRAY_SIZE(beethoven_fur_elise)) | |
| 241 | 247 | e->src_buf_offset = 0; |
| 242 | 248 | |
| 243 | − e->last_tone = beethoven_5th_symphony[e->src_buf_offset].note; | |
| 244 | − e->last_duration = beethoven_5th_symphony[e->src_buf_offset].duration * S302M_SAMPLING_RATE_HZ / COMPASS / 5; | |
| 249 | + ctx->last_tone = beethoven_fur_elise[e->src_buf_offset].note; | |
| 250 | + ctx->last_duration = beethoven_fur_elise[e->src_buf_offset].duration * | |
| 251 | + S302M_SAMPLING_RATE_HZ / COMPASS / 5; | |
| 245 | 252 | e->src_buf_offset++; |
| 246 | − e->note_offset = 0; | |
| 253 | + ctx->note_offset = 0; | |
| 247 | 254 | } else { |
| 248 | − e->last_duration--; | |
| 255 | + ctx->last_duration--; | |
| 249 | 256 | } |
| 250 | 257 | |
| 251 | − /* Handle silent */ | |
| 252 | − if (!e->last_tone) { | |
| 253 | − e->src_buf_offset = 0; | |
| 258 | + /* Handle pause notes */ | |
| 259 | + if (!ctx->last_tone) | |
| 254 | 260 | return 0x8000; |
| 255 | − } | |
| 256 | 261 | |
| 257 | − pos = (2 * PI * e->note_offset * e->last_tone / S302M_SAMPLING_RATE_HZ); | |
| 258 | − | |
| 259 | − if (pos == 360) | |
| 260 | − e->note_offset = 0; | |
| 261 | − else | |
| 262 | − e->note_offset++; | |
| 262 | + pos = (2 * PI * ctx->note_offset * ctx->last_tone) / S302M_SAMPLING_RATE_HZ; | |
| 263 | + ctx->note_offset++; | |
| 263 | 264 | |
| 264 | 265 | return (fixp_sin32(pos % (2 * PI)) >> 16) + 0x8000; |
| 265 | 266 | } |
| @@ -289,9 +290,9 @@ static u16 vidtv_s302m_get_sample(struct vidtv_encoder *e) · 23 unmodified lines | ||
| 289 | 290 | static u32 vidtv_s302m_write_frame(struct vidtv_encoder *e, |
| 290 | 291 | u16 sample) |
| 291 | 292 | { |
| 292 | − u32 nbytes = 0; | |
| 293 | − struct vidtv_s302m_frame_16 f = {}; | |
| 294 | 293 | struct vidtv_s302m_ctx *ctx = e->ctx; |
| 294 | + struct vidtv_s302m_frame_16 f = {}; | |
| 295 | + u32 nbytes = 0; | |
| 295 | 296 | |
| 296 | 297 | /* from ffmpeg: see s302enc.c */ |
| 297 | 298 | |
| @@ -388,6 +389,8 @@ static void vidtv_s302m_write_frames(struct vidtv_encoder *e) · 90 unmodified lines | ||
| 388 | 389 | |
| 389 | 390 | static void *vidtv_s302m_encode(struct vidtv_encoder *e) |
| 390 | 391 | { |
| 392 | + struct vidtv_s302m_ctx *ctx = e->ctx; | |
| 393 | + | |
| 391 | 394 | /* |
| 392 | 395 | * According to SMPTE 302M, an audio access unit is specified as those |
| 393 | 396 | * AES3 words that are associated with a corresponding video frame. |
| @@ -401,8 +404,6 @@ static void *vidtv_s302m_encode(struct vidtv_encoder *e) · 7 unmodified lines | ||
| 401 | 404 | * ffmpeg |
| 402 | 405 | */ |
| 403 | 406 | |
| 404 | − struct vidtv_s302m_ctx *ctx = e->ctx; | |
| 405 | − | |
| 406 | 407 | vidtv_s302m_access_unit_destroy(e); |
| 407 | 408 | vidtv_s302m_alloc_au(e); |
| 408 | 409 | |
| @@ -440,8 +441,13 @@ static u32 vidtv_s302m_clear(struct vidtv_encoder *e) · 31 unmodified lines | ||
| 440 | 441 | struct vidtv_encoder |
| 441 | 442 | *vidtv_s302m_encoder_init(struct vidtv_s302m_encoder_init_args args) |
| 442 | 443 | { |
| 443 | − struct vidtv_encoder *e = kzalloc(sizeof(*e), GFP_KERNEL); | |
| 444 | 444 | u32 priv_sz = sizeof(struct vidtv_s302m_ctx); |
| 445 | + struct vidtv_s302m_ctx *ctx; | |
| 446 | + struct vidtv_encoder *e; | |
| 447 | + | |
| 448 | + e = kzalloc(sizeof(*e), GFP_KERNEL); | |
| 449 | + if (!e) | |
| 450 | + return NULL; | |
| 445 | 451 | |
| 446 | 452 | e->id = S302M; |
| 447 | 453 | |
| @@ -453,14 +459,19 @@ struct vidtv_encoder · 5 unmodified lines | ||
| 453 | 459 | e->encoder_buf_offset = 0; |
| 454 | 460 | |
| 455 | 461 | e->sample_count = 0; |
| 456 | − e->last_duration = 0; | |
| 457 | 462 | |
| 458 | 463 | e->src_buf = (args.src_buf) ? args.src_buf : NULL; |
| 459 | 464 | e->src_buf_sz = (args.src_buf) ? args.src_buf_sz : 0; |
| 460 | 465 | e->src_buf_offset = 0; |
| 461 | 466 | |
| 462 | 467 | e->is_video_encoder = false; |
| 463 | − e->ctx = kzalloc(priv_sz, GFP_KERNEL); | |
| 468 | + | |
| 469 | + ctx = kzalloc(priv_sz, GFP_KERNEL); | |
| 470 | + if (!ctx) | |
| 471 | + return NULL; | |
| 472 | + | |
| 473 | + e->ctx = ctx; | |
| 474 | + ctx->last_duration = 0; | |
| 464 | 475 | |
| 465 | 476 | e->encode = vidtv_s302m_encode; |
| 466 | 477 | e->clear = vidtv_s302m_clear; |
| @@ -19,7 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | #define VIDTV_S302M_H |
| 20 | 20 | |
| 21 | 21 | #include <linux/types.h> |
| 22 | −#include <asm/byteorder.h> | |
| 23 | 22 | |
| 24 | 23 | #include "vidtv_encoder.h" |
| 25 | 24 | |
| @@ -34,14 +33,20 @@ · 8 unmodified lines | ||
| 34 | 33 | * @enc: A pointer to the containing encoder structure. |
| 35 | 34 | * @frame_index: The current frame in a block |
| 36 | 35 | * @au_count: The total number of access units encoded up to now |
| 36 | + * @last_duration: Duration of the tone currently being played | |
| 37 | + * @note_offset: Position at the music tone array | |
| 38 | + * @last_tone: Tone currently being played | |
| 37 | 39 | */ |
| 38 | 40 | struct vidtv_s302m_ctx { |
| 39 | 41 | struct vidtv_encoder *enc; |
| 40 | 42 | u32 frame_index; |
| 41 | 43 | u32 au_count; |
| 44 | + int last_duration; | |
| 45 | + unsigned int note_offset; | |
| 46 | + enum musical_notes last_tone; | |
| 42 | 47 | }; |
| 43 | 48 | |
| 44 | −/** | |
| 49 | +/* | |
| 45 | 50 | * struct vidtv_smpte_s302m_es - s302m MPEG Elementary Stream header. |
| 46 | 51 | * |
| 47 | 52 | * See SMPTE 302M 2007 table 1. |
| @@ -9,14 +9,13 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s, %d: " fmt, __func__, __LINE__ |
| 11 | 11 | |
| 12 | +#include <linux/math64.h> | |
| 12 | 13 | #include <linux/printk.h> |
| 13 | 14 | #include <linux/ratelimit.h> |
| 14 | 15 | #include <linux/types.h> |
| 15 | −#include <linux/math64.h> | |
| 16 | −#include <asm/byteorder.h> | |
| 17 | 16 | |
| 18 | −#include "vidtv_ts.h" | |
| 19 | 17 | #include "vidtv_common.h" |
| 18 | +#include "vidtv_ts.h" | |
| 20 | 19 | |
| 21 | 20 | static u32 vidtv_ts_write_pcr_bits(u8 *to, u32 to_offset, u64 pcr) |
| 22 | 21 | { |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | #define VIDTV_TS_H |
| 12 | 12 | |
| 13 | 13 | #include <linux/types.h> |
| 14 | −#include <asm/byteorder.h> | |
| 15 | 14 | |
| 16 | 15 | #define TS_SYNC_BYTE 0x47 |
| 17 | 16 | #define TS_PACKET_LEN 188 |
| @@ -54,7 +53,7 @@ struct vidtv_mpeg_ts { · 36 unmodified lines | ||
| 54 | 53 | * @dest_offset: The byte offset into the buffer. |
| 55 | 54 | * @pid: The TS PID for the PCR packets. |
| 56 | 55 | * @buf_sz: The size of the buffer in bytes. |
| 57 | − * @countinuity_counter: The TS continuity_counter. | |
| 56 | + * @continuity_counter: The TS continuity_counter. | |
| 58 | 57 | * @pcr: A sample from the system clock. |
| 59 | 58 | */ |
| 60 | 59 | struct pcr_write_args { |
| @@ -71,7 +70,7 @@ struct pcr_write_args { · 10 unmodified lines | ||
| 71 | 70 | * @dest_buf: The buffer to write into. |
| 72 | 71 | * @dest_offset: The byte offset into the buffer. |
| 73 | 72 | * @buf_sz: The size of the buffer in bytes. |
| 74 | − * @countinuity_counter: The TS continuity_counter. | |
| 73 | + * @continuity_counter: The TS continuity_counter. | |
| 75 | 74 | */ |
| 76 | 75 | struct null_packet_write_args { |
| 77 | 76 | void *dest_buf; |
| @@ -13,11 +13,12 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/errno.h> |
| 14 | 14 | #include <linux/i2c.h> |
| 15 | 15 | #include <linux/module.h> |
| 16 | +#include <linux/printk.h> | |
| 17 | +#include <linux/ratelimit.h> | |
| 16 | 18 | #include <linux/slab.h> |
| 17 | 19 | #include <linux/types.h> |
| 20 | + | |
| 18 | 21 | #include <media/dvb_frontend.h> |
| 19 | −#include <linux/printk.h> | |
| 20 | −#include <linux/ratelimit.h> | |
| 21 | 22 | |
| 22 | 23 | #include "vidtv_tuner.h" |
| 23 | 24 | |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #define VIDTV_TUNER_H |
| 12 | 12 | |
| 13 | 13 | #include <linux/types.h> |
| 14 | + | |
| 14 | 15 | #include <media/dvb_frontend.h> |
| 15 | 16 | |
| 16 | 17 | #define NUM_VALID_TUNER_FREQS 8 |
| @@ -30,7 +30,10 @@ · 29 unmodified lines | ||
| 30 | 30 | #define SDHCI_ARASAN_VENDOR_REGISTER 0x78 |
| 31 | 31 | |
| 32 | 32 | #define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8 |
| 33 | +#define SDHCI_ARASAN_ITAPDLY_SEL_MASK 0xFF | |
| 34 | + | |
| 33 | 35 | #define SDHCI_ARASAN_OTAPDLY_REGISTER 0xF0FC |
| 36 | +#define SDHCI_ARASAN_OTAPDLY_SEL_MASK 0x3F | |
| 34 | 37 | |
| 35 | 38 | #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200 |
| 36 | 39 | #define VENDOR_ENHANCED_STROBE BIT(0) |
| @@ -600,14 +603,8 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees) · 563 unmodified lines | ||
| 600 | 603 | u8 tap_delay, tap_max = 0; |
| 601 | 604 | int ret; |
| 602 | 605 | |
| 603 | − /* | |
| 604 | − * This is applicable for SDHCI_SPEC_300 and above | |
| 605 | − * ZynqMP does not set phase for <=25MHz clock. | |
| 606 | − * If degrees is zero, no need to do anything. | |
| 607 | − */ | |
| 608 | − if (host->version < SDHCI_SPEC_300 || | |
| 609 | − host->timing == MMC_TIMING_LEGACY || | |
| 610 | − host->timing == MMC_TIMING_UHS_SDR12 || !degrees) | |
| 606 | + /* This is applicable for SDHCI_SPEC_300 and above */ | |
| 607 | + if (host->version < SDHCI_SPEC_300) | |
| 611 | 608 | return 0; |
| 612 | 609 | |
| 613 | 610 | switch (host->timing) { |
| @@ -638,6 +635,9 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees) · 24 unmodified lines | ||
| 638 | 635 | if (ret) |
| 639 | 636 | pr_err("Error setting Output Tap Delay\n"); |
| 640 | 637 | |
| 638 | + /* Release DLL Reset */ | |
| 639 | + zynqmp_pm_sd_dll_reset(node_id, PM_DLL_RESET_RELEASE); | |
| 640 | + | |
| 641 | 641 | return ret; |
| 642 | 642 | } |
| 643 | 643 | |
| @@ -668,16 +668,13 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct clk_hw *hw, int degrees) · 24 unmodified lines | ||
| 668 | 668 | u8 tap_delay, tap_max = 0; |
| 669 | 669 | int ret; |
| 670 | 670 | |
| 671 | − /* | |
| 672 | − * This is applicable for SDHCI_SPEC_300 and above | |
| 673 | − * ZynqMP does not set phase for <=25MHz clock. | |
| 674 | − * If degrees is zero, no need to do anything. | |
| 675 | − */ | |
| 676 | − if (host->version < SDHCI_SPEC_300 || | |
| 677 | − host->timing == MMC_TIMING_LEGACY || | |
| 678 | − host->timing == MMC_TIMING_UHS_SDR12 || !degrees) | |
| 671 | + /* This is applicable for SDHCI_SPEC_300 and above */ | |
| 672 | + if (host->version < SDHCI_SPEC_300) | |
| 679 | 673 | return 0; |
| 680 | 674 | |
| 675 | + /* Assert DLL Reset */ | |
| 676 | + zynqmp_pm_sd_dll_reset(node_id, PM_DLL_RESET_ASSERT); | |
| 677 | + | |
| 681 | 678 | switch (host->timing) { |
| 682 | 679 | case MMC_TIMING_MMC_HS: |
| 683 | 680 | case MMC_TIMING_SD_HS: |
| @@ -733,14 +730,8 @@ static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees) · 49 unmodified lines | ||
| 733 | 730 | struct sdhci_host *host = sdhci_arasan->host; |
| 734 | 731 | u8 tap_delay, tap_max = 0; |
| 735 | 732 | |
| 736 | − /* | |
| 737 | − * This is applicable for SDHCI_SPEC_300 and above | |
| 738 | − * Versal does not set phase for <=25MHz clock. | |
| 739 | − * If degrees is zero, no need to do anything. | |
| 740 | − */ | |
| 741 | − if (host->version < SDHCI_SPEC_300 || | |
| 742 | − host->timing == MMC_TIMING_LEGACY || | |
| 743 | − host->timing == MMC_TIMING_UHS_SDR12 || !degrees) | |
| 733 | + /* This is applicable for SDHCI_SPEC_300 and above */ | |
| 734 | + if (host->version < SDHCI_SPEC_300) | |
| 744 | 735 | return 0; |
| 745 | 736 | |
| 746 | 737 | switch (host->timing) { |
| @@ -773,6 +764,7 @@ static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees) · 26 unmodified lines | ||
| 773 | 764 | regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER); |
| 774 | 765 | regval |= SDHCI_OTAPDLY_ENABLE; |
| 775 | 766 | sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); |
| 767 | + regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK; | |
| 776 | 768 | regval |= tap_delay; |
| 777 | 769 | sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); |
| 778 | 770 | } |
| @@ -804,14 +796,8 @@ static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees) · 25 unmodified lines | ||
| 804 | 796 | struct sdhci_host *host = sdhci_arasan->host; |
| 805 | 797 | u8 tap_delay, tap_max = 0; |
| 806 | 798 | |
| 807 | − /* | |
| 808 | − * This is applicable for SDHCI_SPEC_300 and above | |
| 809 | − * Versal does not set phase for <=25MHz clock. | |
| 810 | − * If degrees is zero, no need to do anything. | |
| 811 | − */ | |
| 812 | − if (host->version < SDHCI_SPEC_300 || | |
| 813 | − host->timing == MMC_TIMING_LEGACY || | |
| 814 | − host->timing == MMC_TIMING_UHS_SDR12 || !degrees) | |
| 799 | + /* This is applicable for SDHCI_SPEC_300 and above */ | |
| 800 | + if (host->version < SDHCI_SPEC_300) | |
| 815 | 801 | return 0; |
| 816 | 802 | |
| 817 | 803 | switch (host->timing) { |
| @@ -846,6 +832,7 @@ static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees) · 28 unmodified lines | ||
| 846 | 832 | sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); |
| 847 | 833 | regval |= SDHCI_ITAPDLY_ENABLE; |
| 848 | 834 | sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); |
| 835 | + regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK; | |
| 849 | 836 | regval |= tap_delay; |
| 850 | 837 | sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); |
| 851 | 838 | regval &= ~SDHCI_ITAPDLY_CHGWIN; |
| @@ -665,6 +665,15 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode, · 664 unmodified lines | ||
| 665 | 665 | } |
| 666 | 666 | } |
| 667 | 667 | |
| 668 | +static void sdhci_intel_set_uhs_signaling(struct sdhci_host *host, | |
| 669 | + unsigned int timing) | |
| 670 | +{ | |
| 671 | + /* Set UHS timing to SDR25 for High Speed mode */ | |
| 672 | + if (timing == MMC_TIMING_MMC_HS || timing == MMC_TIMING_SD_HS) | |
| 673 | + timing = MMC_TIMING_UHS_SDR25; | |
| 674 | + sdhci_set_uhs_signaling(host, timing); | |
| 675 | +} | |
| 676 | + | |
| 668 | 677 | #define INTEL_HS400_ES_REG 0x78 |
| 669 | 678 | #define INTEL_HS400_ES_BIT BIT(0) |
| 670 | 679 | |
| @@ -721,7 +730,7 @@ static const struct sdhci_ops sdhci_intel_byt_ops = { · 50 unmodified lines | ||
| 721 | 730 | .enable_dma = sdhci_pci_enable_dma, |
| 722 | 731 | .set_bus_width = sdhci_set_bus_width, |
| 723 | 732 | .reset = sdhci_reset, |
| 724 | − .set_uhs_signaling = sdhci_set_uhs_signaling, | |
| 733 | + .set_uhs_signaling = sdhci_intel_set_uhs_signaling, | |
| 725 | 734 | .hw_reset = sdhci_pci_hw_reset, |
| 726 | 735 | }; |
| 727 | 736 | |
| @@ -731,7 +740,7 @@ static const struct sdhci_ops sdhci_intel_glk_ops = { · 3 unmodified lines | ||
| 731 | 740 | .enable_dma = sdhci_pci_enable_dma, |
| 732 | 741 | .set_bus_width = sdhci_set_bus_width, |
| 733 | 742 | .reset = sdhci_cqhci_reset, |
| 734 | − .set_uhs_signaling = sdhci_set_uhs_signaling, | |
| 743 | + .set_uhs_signaling = sdhci_intel_set_uhs_signaling, | |
| 735 | 744 | .hw_reset = sdhci_pci_hw_reset, |
| 736 | 745 | .irq = sdhci_cqhci_irq, |
| 737 | 746 | }; |
| @@ -215,8 +215,17 @@ static int gpio_nand_setup_interface(struct nand_chip *this, int csline, · 214 unmodified lines | ||
| 215 | 215 | return 0; |
| 216 | 216 | } |
| 217 | 217 | |
| 218 | +static int gpio_nand_attach_chip(struct nand_chip *chip) | |
| 219 | +{ | |
| 220 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 221 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 222 | + | |
| 223 | + return 0; | |
| 224 | +} | |
| 225 | + | |
| 218 | 226 | static const struct nand_controller_ops gpio_nand_ops = { |
| 219 | 227 | .exec_op = gpio_nand_exec_op, |
| 228 | + .attach_chip = gpio_nand_attach_chip, | |
| 220 | 229 | .setup_interface = gpio_nand_setup_interface, |
| 221 | 230 | }; |
| 222 | 231 | |
| @@ -260,9 +269,6 @@ static int gpio_nand_probe(struct platform_device *pdev) · 37 unmodified lines | ||
| 260 | 269 | return err; |
| 261 | 270 | } |
| 262 | 271 | |
| 263 | − this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 264 | − this->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 265 | − | |
| 266 | 272 | platform_set_drvdata(pdev, priv); |
| 267 | 273 | |
| 268 | 274 | /* Set chip enabled but write protected */ |
| @@ -236,8 +236,17 @@ static int au1550nd_exec_op(struct nand_chip *this, · 235 unmodified lines | ||
| 236 | 236 | return ret; |
| 237 | 237 | } |
| 238 | 238 | |
| 239 | +static int au1550nd_attach_chip(struct nand_chip *chip) | |
| 240 | +{ | |
| 241 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 242 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 243 | + | |
| 244 | + return 0; | |
| 245 | +} | |
| 246 | + | |
| 239 | 247 | static const struct nand_controller_ops au1550nd_ops = { |
| 240 | 248 | .exec_op = au1550nd_exec_op, |
| 249 | + .attach_chip = au1550nd_attach_chip, | |
| 241 | 250 | }; |
| 242 | 251 | |
| 243 | 252 | static int au1550nd_probe(struct platform_device *pdev) |
| @@ -294,8 +303,6 @@ static int au1550nd_probe(struct platform_device *pdev) · 50 unmodified lines | ||
| 294 | 303 | nand_controller_init(&ctx->controller); |
| 295 | 304 | ctx->controller.ops = &au1550nd_ops; |
| 296 | 305 | this->controller = &ctx->controller; |
| 297 | − this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 298 | − this->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 299 | 306 | |
| 300 | 307 | if (pd->devwidth) |
| 301 | 308 | this->options |= NAND_BUSWIDTH_16; |
| @@ -243,8 +243,24 @@ static int cs_calculate_ecc(struct nand_chip *this, const u_char *dat, · 242 unmodified lines | ||
| 243 | 243 | |
| 244 | 244 | static struct cs553x_nand_controller *controllers[4]; |
| 245 | 245 | |
| 246 | +static int cs553x_attach_chip(struct nand_chip *chip) | |
| 247 | +{ | |
| 248 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) | |
| 249 | + return 0; | |
| 250 | + | |
| 251 | + chip->ecc.size = 256; | |
| 252 | + chip->ecc.bytes = 3; | |
| 253 | + chip->ecc.hwctl = cs_enable_hwecc; | |
| 254 | + chip->ecc.calculate = cs_calculate_ecc; | |
| 255 | + chip->ecc.correct = nand_correct_data; | |
| 256 | + chip->ecc.strength = 1; | |
| 257 | + | |
| 258 | + return 0; | |
| 259 | +} | |
| 260 | + | |
| 246 | 261 | static const struct nand_controller_ops cs553x_nand_controller_ops = { |
| 247 | 262 | .exec_op = cs553x_exec_op, |
| 263 | + .attach_chip = cs553x_attach_chip, | |
| 248 | 264 | }; |
| 249 | 265 | |
| 250 | 266 | static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) |
| @@ -286,14 +302,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) · 35 unmodified lines | ||
| 286 | 302 | goto out_mtd; |
| 287 | 303 | } |
| 288 | 304 | |
| 289 | − this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 290 | − this->ecc.size = 256; | |
| 291 | − this->ecc.bytes = 3; | |
| 292 | − this->ecc.hwctl = cs_enable_hwecc; | |
| 293 | − this->ecc.calculate = cs_calculate_ecc; | |
| 294 | − this->ecc.correct = nand_correct_data; | |
| 295 | − this->ecc.strength = 1; | |
| 296 | − | |
| 297 | 305 | /* Enable the following for a flash based bad block table */ |
| 298 | 306 | this->bbt_options = NAND_BBT_USE_FLASH; |
| 299 | 307 | |
| @@ -585,6 +585,10 @@ static int davinci_nand_attach_chip(struct nand_chip *chip) · 584 unmodified lines | ||
| 585 | 585 | if (IS_ERR(pdata)) |
| 586 | 586 | return PTR_ERR(pdata); |
| 587 | 587 | |
| 588 | + /* Use board-specific ECC config */ | |
| 589 | + info->chip.ecc.engine_type = pdata->engine_type; | |
| 590 | + info->chip.ecc.placement = pdata->ecc_placement; | |
| 591 | + | |
| 588 | 592 | switch (info->chip.ecc.engine_type) { |
| 589 | 593 | case NAND_ECC_ENGINE_TYPE_NONE: |
| 590 | 594 | pdata->ecc_bits = 0; |
| @@ -850,10 +854,6 @@ static int nand_davinci_probe(struct platform_device *pdev) · 259 unmodified lines | ||
| 850 | 854 | info->mask_ale = pdata->mask_ale ? : MASK_ALE; |
| 851 | 855 | info->mask_cle = pdata->mask_cle ? : MASK_CLE; |
| 852 | 856 | |
| 853 | − /* Use board-specific ECC config */ | |
| 854 | − info->chip.ecc.engine_type = pdata->engine_type; | |
| 855 | − info->chip.ecc.placement = pdata->ecc_placement; | |
| 856 | − | |
| 857 | 857 | spin_lock_irq(&davinci_nand_lock); |
| 858 | 858 | |
| 859 | 859 | /* put CSxNAND into NAND mode */ |
| @@ -1269,12 +1269,31 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) · 1268 unmodified lines | ||
| 1269 | 1269 | return 1; |
| 1270 | 1270 | } |
| 1271 | 1271 | |
| 1272 | +static int doc200x_attach_chip(struct nand_chip *chip) | |
| 1273 | +{ | |
| 1274 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) | |
| 1275 | + return 0; | |
| 1276 | + | |
| 1277 | + chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED; | |
| 1278 | + chip->ecc.size = 512; | |
| 1279 | + chip->ecc.bytes = 6; | |
| 1280 | + chip->ecc.strength = 2; | |
| 1281 | + chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; | |
| 1282 | + chip->ecc.hwctl = doc200x_enable_hwecc; | |
| 1283 | + chip->ecc.calculate = doc200x_calculate_ecc; | |
| 1284 | + chip->ecc.correct = doc200x_correct_data; | |
| 1285 | + | |
| 1286 | + return 0; | |
| 1287 | +} | |
| 1288 | + | |
| 1272 | 1289 | static const struct nand_controller_ops doc200x_ops = { |
| 1273 | 1290 | .exec_op = doc200x_exec_op, |
| 1291 | + .attach_chip = doc200x_attach_chip, | |
| 1274 | 1292 | }; |
| 1275 | 1293 | |
| 1276 | 1294 | static const struct nand_controller_ops doc2001plus_ops = { |
| 1277 | 1295 | .exec_op = doc2001plus_exec_op, |
| 1296 | + .attach_chip = doc200x_attach_chip, | |
| 1278 | 1297 | }; |
| 1279 | 1298 | |
| 1280 | 1299 | static int __init doc_probe(unsigned long physadr) |
| @@ -1452,16 +1471,6 @@ static int __init doc_probe(unsigned long physadr) · 171 unmodified lines | ||
| 1452 | 1471 | |
| 1453 | 1472 | nand->controller = &doc->base; |
| 1454 | 1473 | nand_set_controller_data(nand, doc); |
| 1455 | − nand->ecc.hwctl = doc200x_enable_hwecc; | |
| 1456 | − nand->ecc.calculate = doc200x_calculate_ecc; | |
| 1457 | − nand->ecc.correct = doc200x_correct_data; | |
| 1458 | − | |
| 1459 | − nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 1460 | − nand->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED; | |
| 1461 | − nand->ecc.size = 512; | |
| 1462 | − nand->ecc.bytes = 6; | |
| 1463 | − nand->ecc.strength = 2; | |
| 1464 | − nand->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; | |
| 1465 | 1474 | nand->bbt_options = NAND_BBT_USE_FLASH; |
| 1466 | 1475 | /* Skip the automatic BBT scan so we can run it manually */ |
| 1467 | 1476 | nand->options |= NAND_SKIP_BBTSCAN | NAND_NO_BBM_QUIRK; |
| @@ -880,6 +880,20 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand) · 879 unmodified lines | ||
| 880 | 880 | struct mtd_info *mtd = nand_to_mtd(nand); |
| 881 | 881 | struct fsmc_nand_data *host = nand_to_fsmc(nand); |
| 882 | 882 | |
| 883 | + if (nand->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID) | |
| 884 | + nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 885 | + | |
| 886 | + if (!nand->ecc.size) | |
| 887 | + nand->ecc.size = 512; | |
| 888 | + | |
| 889 | + if (AMBA_REV_BITS(host->pid) >= 8) { | |
| 890 | + nand->ecc.read_page = fsmc_read_page_hwecc; | |
| 891 | + nand->ecc.calculate = fsmc_read_hwecc_ecc4; | |
| 892 | + nand->ecc.correct = fsmc_bch8_correct_data; | |
| 893 | + nand->ecc.bytes = 13; | |
| 894 | + nand->ecc.strength = 8; | |
| 895 | + } | |
| 896 | + | |
| 883 | 897 | if (AMBA_REV_BITS(host->pid) >= 8) { |
| 884 | 898 | switch (mtd->oobsize) { |
| 885 | 899 | case 16: |
| @@ -905,6 +919,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand) · 19 unmodified lines | ||
| 905 | 919 | dev_info(host->dev, "Using 1-bit HW ECC scheme\n"); |
| 906 | 920 | nand->ecc.calculate = fsmc_read_hwecc_ecc1; |
| 907 | 921 | nand->ecc.correct = nand_correct_data; |
| 922 | + nand->ecc.hwctl = fsmc_enable_hwecc; | |
| 908 | 923 | nand->ecc.bytes = 3; |
| 909 | 924 | nand->ecc.strength = 1; |
| 910 | 925 | nand->ecc.options |= NAND_ECC_SOFT_HAMMING_SM_ORDER; |
| @@ -1055,13 +1070,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) · 144 unmodified lines | ||
| 1055 | 1070 | |
| 1056 | 1071 | mtd->dev.parent = &pdev->dev; |
| 1057 | 1072 | |
| 1058 | − /* | |
| 1059 | − * Setup default ECC mode. nand_dt_init() called from nand_scan_ident() | |
| 1060 | − * can overwrite this value if the DT provides a different value. | |
| 1061 | − */ | |
| 1062 | − nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 1063 | − nand->ecc.hwctl = fsmc_enable_hwecc; | |
| 1064 | − nand->ecc.size = 512; | |
| 1065 | 1073 | nand->badblockbits = 7; |
| 1066 | 1074 | |
| 1067 | 1075 | if (host->mode == USE_DMA_ACCESS) { |
| @@ -1084,14 +1092,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 1084 | 1092 | nand->options |= NAND_KEEP_TIMINGS; |
| 1085 | 1093 | } |
| 1086 | 1094 | |
| 1087 | − if (AMBA_REV_BITS(host->pid) >= 8) { | |
| 1088 | − nand->ecc.read_page = fsmc_read_page_hwecc; | |
| 1089 | − nand->ecc.calculate = fsmc_read_hwecc_ecc4; | |
| 1090 | − nand->ecc.correct = fsmc_bch8_correct_data; | |
| 1091 | − nand->ecc.bytes = 13; | |
| 1092 | − nand->ecc.strength = 8; | |
| 1093 | − } | |
| 1094 | − | |
| 1095 | 1095 | nand_controller_init(&host->base); |
| 1096 | 1096 | host->base.ops = &fsmc_nand_controller_ops; |
| 1097 | 1097 | nand->controller = &host->base; |
| @@ -161,8 +161,17 @@ static int gpio_nand_exec_op(struct nand_chip *chip, · 160 unmodified lines | ||
| 161 | 161 | return ret; |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | +static int gpio_nand_attach_chip(struct nand_chip *chip) | |
| 165 | +{ | |
| 166 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 167 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 168 | + | |
| 169 | + return 0; | |
| 170 | +} | |
| 171 | + | |
| 164 | 172 | static const struct nand_controller_ops gpio_nand_ops = { |
| 165 | 173 | .exec_op = gpio_nand_exec_op, |
| 174 | + .attach_chip = gpio_nand_attach_chip, | |
| 166 | 175 | }; |
| 167 | 176 | |
| 168 | 177 | #ifdef CONFIG_OF |
| @@ -342,8 +351,6 @@ static int gpio_nand_probe(struct platform_device *pdev) · 173 unmodified lines | ||
| 342 | 351 | gpiomtd->base.ops = &gpio_nand_ops; |
| 343 | 352 | |
| 344 | 353 | nand_set_flash_node(chip, pdev->dev.of_node); |
| 345 | − chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 346 | − chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 347 | 354 | chip->options = gpiomtd->plat.options; |
| 348 | 355 | chip->controller = &gpiomtd->base; |
| 349 | 356 | |
| @@ -648,6 +648,9 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip) · 647 unmodified lines | ||
| 648 | 648 | struct lpc32xx_nand_host *host = nand_get_controller_data(chip); |
| 649 | 649 | struct device *dev = &host->pdev->dev; |
| 650 | 650 | |
| 651 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) | |
| 652 | + return 0; | |
| 653 | + | |
| 651 | 654 | host->dma_buf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL); |
| 652 | 655 | if (!host->dma_buf) |
| 653 | 656 | return -ENOMEM; |
| @@ -656,8 +659,17 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip) · 2 unmodified lines | ||
| 656 | 659 | if (!host->dummy_buf) |
| 657 | 660 | return -ENOMEM; |
| 658 | 661 | |
| 659 | − chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 660 | 662 | chip->ecc.size = 512; |
| 663 | + chip->ecc.hwctl = lpc32xx_ecc_enable; | |
| 664 | + chip->ecc.read_page_raw = lpc32xx_read_page; | |
| 665 | + chip->ecc.read_page = lpc32xx_read_page; | |
| 666 | + chip->ecc.write_page_raw = lpc32xx_write_page_lowlevel; | |
| 667 | + chip->ecc.write_page = lpc32xx_write_page_lowlevel; | |
| 668 | + chip->ecc.write_oob = lpc32xx_write_oob; | |
| 669 | + chip->ecc.read_oob = lpc32xx_read_oob; | |
| 670 | + chip->ecc.strength = 4; | |
| 671 | + chip->ecc.bytes = 10; | |
| 672 | + | |
| 661 | 673 | mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops); |
| 662 | 674 | host->mlcsubpages = mtd->writesize / 512; |
| 663 | 675 | |
| @@ -741,15 +753,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) · 77 unmodified lines | ||
| 741 | 753 | platform_set_drvdata(pdev, host); |
| 742 | 754 | |
| 743 | 755 | /* Initialize function pointers */ |
| 744 | − nand_chip->ecc.hwctl = lpc32xx_ecc_enable; | |
| 745 | − nand_chip->ecc.read_page_raw = lpc32xx_read_page; | |
| 746 | − nand_chip->ecc.read_page = lpc32xx_read_page; | |
| 747 | − nand_chip->ecc.write_page_raw = lpc32xx_write_page_lowlevel; | |
| 748 | − nand_chip->ecc.write_page = lpc32xx_write_page_lowlevel; | |
| 749 | − nand_chip->ecc.write_oob = lpc32xx_write_oob; | |
| 750 | − nand_chip->ecc.read_oob = lpc32xx_read_oob; | |
| 751 | − nand_chip->ecc.strength = 4; | |
| 752 | − nand_chip->ecc.bytes = 10; | |
| 753 | 756 | nand_chip->legacy.waitfunc = lpc32xx_waitfunc; |
| 754 | 757 | |
| 755 | 758 | nand_chip->options = NAND_NO_SUBPAGE_WRITE; |
| @@ -775,6 +775,9 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip) · 774 unmodified lines | ||
| 775 | 775 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 776 | 776 | struct lpc32xx_nand_host *host = nand_get_controller_data(chip); |
| 777 | 777 | |
| 778 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) | |
| 779 | + return 0; | |
| 780 | + | |
| 778 | 781 | /* OOB and ECC CPU and DMA work areas */ |
| 779 | 782 | host->ecc_buf = (uint32_t *)(host->data_buf + LPC32XX_DMA_DATA_SIZE); |
| 780 | 783 | |
| @@ -786,11 +789,22 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip) · 5 unmodified lines | ||
| 786 | 789 | if (mtd->writesize <= 512) |
| 787 | 790 | mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops); |
| 788 | 791 | |
| 792 | + chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED; | |
| 789 | 793 | /* These sizes remain the same regardless of page size */ |
| 790 | 794 | chip->ecc.size = 256; |
| 795 | + chip->ecc.strength = 1; | |
| 791 | 796 | chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES; |
| 792 | 797 | chip->ecc.prepad = 0; |
| 793 | 798 | chip->ecc.postpad = 0; |
| 799 | + chip->ecc.read_page_raw = lpc32xx_nand_read_page_raw_syndrome; | |
| 800 | + chip->ecc.read_page = lpc32xx_nand_read_page_syndrome; | |
| 801 | + chip->ecc.write_page_raw = lpc32xx_nand_write_page_raw_syndrome; | |
| 802 | + chip->ecc.write_page = lpc32xx_nand_write_page_syndrome; | |
| 803 | + chip->ecc.write_oob = lpc32xx_nand_write_oob_syndrome; | |
| 804 | + chip->ecc.read_oob = lpc32xx_nand_read_oob_syndrome; | |
| 805 | + chip->ecc.calculate = lpc32xx_nand_ecc_calculate; | |
| 806 | + chip->ecc.correct = nand_correct_data; | |
| 807 | + chip->ecc.hwctl = lpc32xx_nand_ecc_enable; | |
| 794 | 808 | |
| 795 | 809 | /* |
| 796 | 810 | * Use a custom BBT marker setup for small page FLASH that |
| @@ -881,21 +895,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) · 84 unmodified lines | ||
| 881 | 895 | platform_set_drvdata(pdev, host); |
| 882 | 896 | |
| 883 | 897 | /* NAND callbacks for LPC32xx SLC hardware */ |
| 884 | − chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 885 | − chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED; | |
| 886 | 898 | chip->legacy.read_byte = lpc32xx_nand_read_byte; |
| 887 | 899 | chip->legacy.read_buf = lpc32xx_nand_read_buf; |
| 888 | 900 | chip->legacy.write_buf = lpc32xx_nand_write_buf; |
| 889 | − chip->ecc.read_page_raw = lpc32xx_nand_read_page_raw_syndrome; | |
| 890 | − chip->ecc.read_page = lpc32xx_nand_read_page_syndrome; | |
| 891 | − chip->ecc.write_page_raw = lpc32xx_nand_write_page_raw_syndrome; | |
| 892 | − chip->ecc.write_page = lpc32xx_nand_write_page_syndrome; | |
| 893 | − chip->ecc.write_oob = lpc32xx_nand_write_oob_syndrome; | |
| 894 | − chip->ecc.read_oob = lpc32xx_nand_read_oob_syndrome; | |
| 895 | − chip->ecc.calculate = lpc32xx_nand_ecc_calculate; | |
| 896 | − chip->ecc.correct = nand_correct_data; | |
| 897 | − chip->ecc.strength = 1; | |
| 898 | − chip->ecc.hwctl = lpc32xx_nand_ecc_enable; | |
| 899 | 901 | |
| 900 | 902 | /* |
| 901 | 903 | * Allocate a large enough buffer for a single huge page plus |
| @@ -104,6 +104,7 @@ · 103 unmodified lines | ||
| 104 | 104 | #define NFC_TIMEOUT (HZ / 10) /* 1/10 s */ |
| 105 | 105 | |
| 106 | 106 | struct mpc5121_nfc_prv { |
| 107 | + struct nand_controller controller; | |
| 107 | 108 | struct nand_chip chip; |
| 108 | 109 | int irq; |
| 109 | 110 | void __iomem *regs; |
| @@ -602,6 +603,18 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) · 492 unmodified lines | ||
| 602 | 603 | iounmap(prv->csreg); |
| 603 | 604 | } |
| 604 | 605 | |
| 606 | +static int mpc5121_nfc_attach_chip(struct nand_chip *chip) | |
| 607 | +{ | |
| 608 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 609 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 610 | + | |
| 611 | + return 0; | |
| 612 | +} | |
| 613 | + | |
| 614 | +static const struct nand_controller_ops mpc5121_nfc_ops = { | |
| 615 | + .attach_chip = mpc5121_nfc_attach_chip, | |
| 616 | +}; | |
| 617 | + | |
| 605 | 618 | static int mpc5121_nfc_probe(struct platform_device *op) |
| 606 | 619 | { |
| 607 | 620 | struct device_node *dn = op->dev.of_node; |
| @@ -634,6 +647,10 @@ static int mpc5121_nfc_probe(struct platform_device *op) · 26 unmodified lines | ||
| 634 | 647 | chip = &prv->chip; |
| 635 | 648 | mtd = nand_to_mtd(chip); |
| 636 | 649 | |
| 650 | + nand_controller_init(&prv->controller); | |
| 651 | + prv->controller.ops = &mpc5121_nfc_ops; | |
| 652 | + chip->controller = &prv->controller; | |
| 653 | + | |
| 637 | 654 | mtd->dev.parent = dev; |
| 638 | 655 | nand_set_controller_data(chip, prv); |
| 639 | 656 | nand_set_flash_node(chip, dn); |
| @@ -688,8 +705,6 @@ static int mpc5121_nfc_probe(struct platform_device *op) · 48 unmodified lines | ||
| 688 | 705 | chip->legacy.set_features = nand_get_set_features_notsupp; |
| 689 | 706 | chip->legacy.get_features = nand_get_set_features_notsupp; |
| 690 | 707 | chip->bbt_options = NAND_BBT_USE_FLASH; |
| 691 | − chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 692 | − chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 693 | 708 | |
| 694 | 709 | /* Support external chip-select logic on ADS5121 board */ |
| 695 | 710 | if (of_machine_is_compatible("fsl,mpc5121ads")) { |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <linux/platform_data/mtd-orion_nand.h> |
| 23 | 23 | |
| 24 | 24 | struct orion_nand_info { |
| 25 | + struct nand_controller controller; | |
| 25 | 26 | struct nand_chip chip; |
| 26 | 27 | struct clk *clk; |
| 27 | 28 | }; |
| @@ -82,6 +83,18 @@ static void orion_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) · 54 unmodified lines | ||
| 82 | 83 | buf[i++] = readb(io_base); |
| 83 | 84 | } |
| 84 | 85 | |
| 86 | +static int orion_nand_attach_chip(struct nand_chip *chip) | |
| 87 | +{ | |
| 88 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 89 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 90 | + | |
| 91 | + return 0; | |
| 92 | +} | |
| 93 | + | |
| 94 | +static const struct nand_controller_ops orion_nand_ops = { | |
| 95 | + .attach_chip = orion_nand_attach_chip, | |
| 96 | +}; | |
| 97 | + | |
| 85 | 98 | static int __init orion_nand_probe(struct platform_device *pdev) |
| 86 | 99 | { |
| 87 | 100 | struct orion_nand_info *info; |
| @@ -101,6 +114,10 @@ static int __init orion_nand_probe(struct platform_device *pdev) · 13 unmodified lines | ||
| 101 | 114 | nc = &info->chip; |
| 102 | 115 | mtd = nand_to_mtd(nc); |
| 103 | 116 | |
| 117 | + nand_controller_init(&info->controller); | |
| 118 | + info->controller.ops = &orion_nand_ops; | |
| 119 | + nc->controller = &info->controller; | |
| 120 | + | |
| 104 | 121 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 105 | 122 | io_base = devm_ioremap_resource(&pdev->dev, res); |
| 106 | 123 | |
| @@ -139,8 +156,6 @@ static int __init orion_nand_probe(struct platform_device *pdev) · 32 unmodified lines | ||
| 139 | 156 | nc->legacy.IO_ADDR_R = nc->legacy.IO_ADDR_W = io_base; |
| 140 | 157 | nc->legacy.cmd_ctrl = orion_nand_cmd_ctrl; |
| 141 | 158 | nc->legacy.read_buf = orion_nand_read_buf; |
| 142 | − nc->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 143 | − nc->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 144 | 159 | |
| 145 | 160 | if (board->chip_delay) |
| 146 | 161 | nc->legacy.chip_delay = board->chip_delay; |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | static unsigned int lpcctl; |
| 31 | 31 | static struct mtd_info *pasemi_nand_mtd; |
| 32 | +static struct nand_controller controller; | |
| 32 | 33 | static const char driver_name[] = "pasemi-nand"; |
| 33 | 34 | |
| 34 | 35 | static void pasemi_read_buf(struct nand_chip *chip, u_char *buf, int len) |
| @@ -73,6 +74,18 @@ static int pasemi_device_ready(struct nand_chip *chip) · 38 unmodified lines | ||
| 73 | 74 | return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); |
| 74 | 75 | } |
| 75 | 76 | |
| 77 | +static int pasemi_attach_chip(struct nand_chip *chip) | |
| 78 | +{ | |
| 79 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 80 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 81 | + | |
| 82 | + return 0; | |
| 83 | +} | |
| 84 | + | |
| 85 | +static const struct nand_controller_ops pasemi_ops = { | |
| 86 | + .attach_chip = pasemi_attach_chip, | |
| 87 | +}; | |
| 88 | + | |
| 76 | 89 | static int pasemi_nand_probe(struct platform_device *ofdev) |
| 77 | 90 | { |
| 78 | 91 | struct device *dev = &ofdev->dev; |
| @@ -100,6 +113,10 @@ static int pasemi_nand_probe(struct platform_device *ofdev) · 21 unmodified lines | ||
| 100 | 113 | goto out; |
| 101 | 114 | } |
| 102 | 115 | |
| 116 | + controller.ops = &pasemi_ops; | |
| 117 | + nand_controller_init(&controller); | |
| 118 | + chip->controller = &controller; | |
| 119 | + | |
| 103 | 120 | pasemi_nand_mtd = nand_to_mtd(chip); |
| 104 | 121 | |
| 105 | 122 | /* Link the private data with the MTD structure */ |
| @@ -132,8 +149,6 @@ static int pasemi_nand_probe(struct platform_device *ofdev) · 26 unmodified lines | ||
| 132 | 149 | chip->legacy.read_buf = pasemi_read_buf; |
| 133 | 150 | chip->legacy.write_buf = pasemi_write_buf; |
| 134 | 151 | chip->legacy.chip_delay = 0; |
| 135 | − chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 136 | − chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 137 | 152 | |
| 138 | 153 | /* Enable the following for a flash based bad block table */ |
| 139 | 154 | chip->bbt_options = NAND_BBT_USE_FLASH; |
| @@ -14,10 +14,23 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/mtd/platnand.h> |
| 15 | 15 | |
| 16 | 16 | struct plat_nand_data { |
| 17 | + struct nand_controller controller; | |
| 17 | 18 | struct nand_chip chip; |
| 18 | 19 | void __iomem *io_base; |
| 19 | 20 | }; |
| 20 | 21 | |
| 22 | +static int plat_nand_attach_chip(struct nand_chip *chip) | |
| 23 | +{ | |
| 24 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 25 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 26 | + | |
| 27 | + return 0; | |
| 28 | +} | |
| 29 | + | |
| 30 | +static const struct nand_controller_ops plat_nand_ops = { | |
| 31 | + .attach_chip = plat_nand_attach_chip, | |
| 32 | +}; | |
| 33 | + | |
| 21 | 34 | /* |
| 22 | 35 | * Probe for the NAND device. |
| 23 | 36 | */ |
| @@ -46,6 +59,10 @@ static int plat_nand_probe(struct platform_device *pdev) · 22 unmodified lines | ||
| 46 | 59 | if (!data) |
| 47 | 60 | return -ENOMEM; |
| 48 | 61 | |
| 62 | + data->controller.ops = &plat_nand_ops; | |
| 63 | + nand_controller_init(&data->controller); | |
| 64 | + data->chip.controller = &data->controller; | |
| 65 | + | |
| 49 | 66 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 50 | 67 | data->io_base = devm_ioremap_resource(&pdev->dev, res); |
| 51 | 68 | if (IS_ERR(data->io_base)) |
| @@ -66,9 +83,6 @@ static int plat_nand_probe(struct platform_device *pdev) · 14 unmodified lines | ||
| 66 | 83 | data->chip.options |= pdata->chip.options; |
| 67 | 84 | data->chip.bbt_options |= pdata->chip.bbt_options; |
| 68 | 85 | |
| 69 | − data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 70 | − data->chip.ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 71 | − | |
| 72 | 86 | platform_set_drvdata(pdev, data); |
| 73 | 87 | |
| 74 | 88 | /* Handle any platform specific setup */ |
| @@ -817,6 +817,29 @@ out: · 816 unmodified lines | ||
| 817 | 817 | return ret; |
| 818 | 818 | } |
| 819 | 819 | |
| 820 | +static int r852_attach_chip(struct nand_chip *chip) | |
| 821 | +{ | |
| 822 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) | |
| 823 | + return 0; | |
| 824 | + | |
| 825 | + chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED; | |
| 826 | + chip->ecc.size = R852_DMA_LEN; | |
| 827 | + chip->ecc.bytes = SM_OOB_SIZE; | |
| 828 | + chip->ecc.strength = 2; | |
| 829 | + chip->ecc.hwctl = r852_ecc_hwctl; | |
| 830 | + chip->ecc.calculate = r852_ecc_calculate; | |
| 831 | + chip->ecc.correct = r852_ecc_correct; | |
| 832 | + | |
| 833 | + /* TODO: hack */ | |
| 834 | + chip->ecc.read_oob = r852_read_oob; | |
| 835 | + | |
| 836 | + return 0; | |
| 837 | +} | |
| 838 | + | |
| 839 | +static const struct nand_controller_ops r852_ops = { | |
| 840 | + .attach_chip = r852_attach_chip, | |
| 841 | +}; | |
| 842 | + | |
| 820 | 843 | static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) |
| 821 | 844 | { |
| 822 | 845 | int error; |
| @@ -858,19 +881,6 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) · 35 unmodified lines | ||
| 858 | 881 | chip->legacy.read_buf = r852_read_buf; |
| 859 | 882 | chip->legacy.write_buf = r852_write_buf; |
| 860 | 883 | |
| 861 | − /* ecc */ | |
| 862 | − chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 863 | − chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED; | |
| 864 | − chip->ecc.size = R852_DMA_LEN; | |
| 865 | − chip->ecc.bytes = SM_OOB_SIZE; | |
| 866 | − chip->ecc.strength = 2; | |
| 867 | − chip->ecc.hwctl = r852_ecc_hwctl; | |
| 868 | − chip->ecc.calculate = r852_ecc_calculate; | |
| 869 | − chip->ecc.correct = r852_ecc_correct; | |
| 870 | − | |
| 871 | − /* TODO: hack */ | |
| 872 | − chip->ecc.read_oob = r852_read_oob; | |
| 873 | − | |
| 874 | 884 | /* init our device structure */ |
| 875 | 885 | dev = kzalloc(sizeof(struct r852_device), GFP_KERNEL); |
| 876 | 886 | |
| @@ -882,6 +892,10 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) · 5 unmodified lines | ||
| 882 | 892 | dev->pci_dev = pci_dev; |
| 883 | 893 | pci_set_drvdata(pci_dev, dev); |
| 884 | 894 | |
| 895 | + nand_controller_init(&dev->controller); | |
| 896 | + dev->controller.ops = &r852_ops; | |
| 897 | + chip->controller = &dev->controller; | |
| 898 | + | |
| 885 | 899 | dev->bounce_buffer = dma_alloc_coherent(&pci_dev->dev, R852_DMA_LEN, |
| 886 | 900 | &dev->phys_bounce_buffer, GFP_KERNEL); |
| 887 | 901 | |
| @@ -104,6 +104,7 @@ · 103 unmodified lines | ||
| 104 | 104 | #define DMA_MEMORY 1 |
| 105 | 105 | |
| 106 | 106 | struct r852_device { |
| 107 | + struct nand_controller controller; | |
| 107 | 108 | void __iomem *mmio; /* mmio */ |
| 108 | 109 | struct nand_chip *chip; /* nand chip backpointer */ |
| 109 | 110 | struct pci_dev *pci_dev; /* pci backpointer */ |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/io.h> |
| 21 | 21 | |
| 22 | 22 | struct sharpsl_nand { |
| 23 | + struct nand_controller controller; | |
| 23 | 24 | struct nand_chip chip; |
| 24 | 25 | |
| 25 | 26 | void __iomem *io; |
| @@ -96,6 +97,25 @@ static int sharpsl_nand_calculate_ecc(struct nand_chip *chip, · 70 unmodified lines | ||
| 96 | 97 | return readb(sharpsl->io + ECCCNTR) != 0; |
| 97 | 98 | } |
| 98 | 99 | |
| 100 | +static int sharpsl_attach_chip(struct nand_chip *chip) | |
| 101 | +{ | |
| 102 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) | |
| 103 | + return 0; | |
| 104 | + | |
| 105 | + chip->ecc.size = 256; | |
| 106 | + chip->ecc.bytes = 3; | |
| 107 | + chip->ecc.strength = 1; | |
| 108 | + chip->ecc.hwctl = sharpsl_nand_enable_hwecc; | |
| 109 | + chip->ecc.calculate = sharpsl_nand_calculate_ecc; | |
| 110 | + chip->ecc.correct = nand_correct_data; | |
| 111 | + | |
| 112 | + return 0; | |
| 113 | +} | |
| 114 | + | |
| 115 | +static const struct nand_controller_ops sharpsl_ops = { | |
| 116 | + .attach_chip = sharpsl_attach_chip, | |
| 117 | +}; | |
| 118 | + | |
| 99 | 119 | /* |
| 100 | 120 | * Main initialization routine |
| 101 | 121 | */ |
| @@ -136,6 +156,10 @@ static int sharpsl_nand_probe(struct platform_device *pdev) · 34 unmodified lines | ||
| 136 | 156 | /* Get pointer to private data */ |
| 137 | 157 | this = (struct nand_chip *)(&sharpsl->chip); |
| 138 | 158 | |
| 159 | + nand_controller_init(&sharpsl->controller); | |
| 160 | + sharpsl->controller.ops = &sharpsl_ops; | |
| 161 | + this->controller = &sharpsl->controller; | |
| 162 | + | |
| 139 | 163 | /* Link the private data with the MTD structure */ |
| 140 | 164 | mtd = nand_to_mtd(this); |
| 141 | 165 | mtd->dev.parent = &pdev->dev; |
| @@ -156,15 +180,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) · 14 unmodified lines | ||
| 156 | 180 | this->legacy.dev_ready = sharpsl_nand_dev_ready; |
| 157 | 181 | /* 15 us command delay time */ |
| 158 | 182 | this->legacy.chip_delay = 15; |
| 159 | − /* set eccmode using hardware ECC */ | |
| 160 | − this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 161 | − this->ecc.size = 256; | |
| 162 | − this->ecc.bytes = 3; | |
| 163 | − this->ecc.strength = 1; | |
| 164 | 183 | this->badblock_pattern = data->badblock_pattern; |
| 165 | − this->ecc.hwctl = sharpsl_nand_enable_hwecc; | |
| 166 | − this->ecc.calculate = sharpsl_nand_calculate_ecc; | |
| 167 | − this->ecc.correct = nand_correct_data; | |
| 168 | 184 | |
| 169 | 185 | /* Scan to find existence of the device */ |
| 170 | 186 | err = nand_scan(this, 1); |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #define FPGA_NAND_DATA_SHIFT 16 |
| 23 | 23 | |
| 24 | 24 | struct socrates_nand_host { |
| 25 | + struct nand_controller controller; | |
| 25 | 26 | struct nand_chip nand_chip; |
| 26 | 27 | void __iomem *io_base; |
| 27 | 28 | struct device *dev; |
| @@ -116,6 +117,18 @@ static int socrates_nand_device_ready(struct nand_chip *nand_chip) · 88 unmodified lines | ||
| 116 | 117 | return 1; |
| 117 | 118 | } |
| 118 | 119 | |
| 120 | +static int socrates_attach_chip(struct nand_chip *chip) | |
| 121 | +{ | |
| 122 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 123 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 124 | + | |
| 125 | + return 0; | |
| 126 | +} | |
| 127 | + | |
| 128 | +static const struct nand_controller_ops socrates_ops = { | |
| 129 | + .attach_chip = socrates_attach_chip, | |
| 130 | +}; | |
| 131 | + | |
| 119 | 132 | /* |
| 120 | 133 | * Probe for the NAND device. |
| 121 | 134 | */ |
| @@ -141,6 +154,10 @@ static int socrates_nand_probe(struct platform_device *ofdev) · 19 unmodified lines | ||
| 141 | 154 | mtd = nand_to_mtd(nand_chip); |
| 142 | 155 | host->dev = &ofdev->dev; |
| 143 | 156 | |
| 157 | + nand_controller_init(&host->controller); | |
| 158 | + host->controller.ops = &socrates_ops; | |
| 159 | + nand_chip->controller = &host->controller; | |
| 160 | + | |
| 144 | 161 | /* link the private data structures */ |
| 145 | 162 | nand_set_controller_data(nand_chip, host); |
| 146 | 163 | nand_set_flash_node(nand_chip, ofdev->dev.of_node); |
| @@ -153,10 +170,6 @@ static int socrates_nand_probe(struct platform_device *ofdev) · 6 unmodified lines | ||
| 153 | 170 | nand_chip->legacy.read_buf = socrates_nand_read_buf; |
| 154 | 171 | nand_chip->legacy.dev_ready = socrates_nand_device_ready; |
| 155 | 172 | |
| 156 | − /* enable ECC */ | |
| 157 | − nand_chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 158 | − nand_chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 159 | − | |
| 160 | 173 | /* TODO: I have no idea what real delay is. */ |
| 161 | 174 | nand_chip->legacy.chip_delay = 20; /* 20us command delay time */ |
| 162 | 175 | |
| @@ -103,6 +103,7 @@ · 102 unmodified lines | ||
| 103 | 103 | /*--------------------------------------------------------------------------*/ |
| 104 | 104 | |
| 105 | 105 | struct tmio_nand { |
| 106 | + struct nand_controller controller; | |
| 106 | 107 | struct nand_chip chip; |
| 107 | 108 | struct completion comp; |
| 108 | 109 | |
| @@ -355,6 +356,25 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio) · 246 unmodified lines | ||
| 355 | 356 | cell->disable(dev); |
| 356 | 357 | } |
| 357 | 358 | |
| 359 | +static int tmio_attach_chip(struct nand_chip *chip) | |
| 360 | +{ | |
| 361 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) | |
| 362 | + return 0; | |
| 363 | + | |
| 364 | + chip->ecc.size = 512; | |
| 365 | + chip->ecc.bytes = 6; | |
| 366 | + chip->ecc.strength = 2; | |
| 367 | + chip->ecc.hwctl = tmio_nand_enable_hwecc; | |
| 368 | + chip->ecc.calculate = tmio_nand_calculate_ecc; | |
| 369 | + chip->ecc.correct = tmio_nand_correct_data; | |
| 370 | + | |
| 371 | + return 0; | |
| 372 | +} | |
| 373 | + | |
| 374 | +static const struct nand_controller_ops tmio_ops = { | |
| 375 | + .attach_chip = tmio_attach_chip, | |
| 376 | +}; | |
| 377 | + | |
| 358 | 378 | static int tmio_probe(struct platform_device *dev) |
| 359 | 379 | { |
| 360 | 380 | struct tmio_nand_data *data = dev_get_platdata(&dev->dev); |
| @@ -385,6 +405,10 @@ static int tmio_probe(struct platform_device *dev) · 24 unmodified lines | ||
| 385 | 405 | mtd->name = "tmio-nand"; |
| 386 | 406 | mtd->dev.parent = &dev->dev; |
| 387 | 407 | |
| 408 | + nand_controller_init(&tmio->controller); | |
| 409 | + tmio->controller.ops = &tmio_ops; | |
| 410 | + nand_chip->controller = &tmio->controller; | |
| 411 | + | |
| 388 | 412 | tmio->ccr = devm_ioremap(&dev->dev, ccr->start, resource_size(ccr)); |
| 389 | 413 | if (!tmio->ccr) |
| 390 | 414 | return -EIO; |
| @@ -409,15 +433,6 @@ static int tmio_probe(struct platform_device *dev) · 18 unmodified lines | ||
| 409 | 433 | nand_chip->legacy.write_buf = tmio_nand_write_buf; |
| 410 | 434 | nand_chip->legacy.read_buf = tmio_nand_read_buf; |
| 411 | 435 | |
| 412 | − /* set eccmode using hardware ECC */ | |
| 413 | − nand_chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 414 | − nand_chip->ecc.size = 512; | |
| 415 | − nand_chip->ecc.bytes = 6; | |
| 416 | − nand_chip->ecc.strength = 2; | |
| 417 | − nand_chip->ecc.hwctl = tmio_nand_enable_hwecc; | |
| 418 | − nand_chip->ecc.calculate = tmio_nand_calculate_ecc; | |
| 419 | − nand_chip->ecc.correct = tmio_nand_correct_data; | |
| 420 | − | |
| 421 | 436 | if (data) |
| 422 | 437 | nand_chip->badblock_pattern = data->badblock_pattern; |
| 423 | 438 | |
| @@ -253,6 +253,11 @@ static int txx9ndfmc_attach_chip(struct nand_chip *chip) · 252 unmodified lines | ||
| 253 | 253 | { |
| 254 | 254 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 255 | 255 | |
| 256 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) | |
| 257 | + return 0; | |
| 258 | + | |
| 259 | + chip->ecc.strength = 1; | |
| 260 | + | |
| 256 | 261 | if (mtd->writesize >= 512) { |
| 257 | 262 | chip->ecc.size = 512; |
| 258 | 263 | chip->ecc.bytes = 6; |
| @@ -261,6 +266,10 @@ static int txx9ndfmc_attach_chip(struct nand_chip *chip) · 2 unmodified lines | ||
| 261 | 266 | chip->ecc.bytes = 3; |
| 262 | 267 | } |
| 263 | 268 | |
| 269 | + chip->ecc.calculate = txx9ndfmc_calculate_ecc; | |
| 270 | + chip->ecc.correct = txx9ndfmc_correct_data; | |
| 271 | + chip->ecc.hwctl = txx9ndfmc_enable_hwecc; | |
| 272 | + | |
| 264 | 273 | return 0; |
| 265 | 274 | } |
| 266 | 275 | |
| @@ -326,11 +335,6 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) · 59 unmodified lines | ||
| 326 | 335 | chip->legacy.write_buf = txx9ndfmc_write_buf; |
| 327 | 336 | chip->legacy.cmd_ctrl = txx9ndfmc_cmd_ctrl; |
| 328 | 337 | chip->legacy.dev_ready = txx9ndfmc_dev_ready; |
| 329 | − chip->ecc.calculate = txx9ndfmc_calculate_ecc; | |
| 330 | − chip->ecc.correct = txx9ndfmc_correct_data; | |
| 331 | − chip->ecc.hwctl = txx9ndfmc_enable_hwecc; | |
| 332 | − chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; | |
| 333 | − chip->ecc.strength = 1; | |
| 334 | 338 | chip->legacy.chip_delay = 100; |
| 335 | 339 | chip->controller = &drvdata->controller; |
| 336 | 340 | |
| @@ -62,6 +62,7 @@ · 61 unmodified lines | ||
| 62 | 62 | #define NAND_CON_NANDM 1 |
| 63 | 63 | |
| 64 | 64 | struct xway_nand_data { |
| 65 | + struct nand_controller controller; | |
| 65 | 66 | struct nand_chip chip; |
| 66 | 67 | unsigned long csflags; |
| 67 | 68 | void __iomem *nandaddr; |
| @@ -145,6 +146,18 @@ static void xway_write_buf(struct nand_chip *chip, const u_char *buf, int len) · 77 unmodified lines | ||
| 145 | 146 | xway_writeb(nand_to_mtd(chip), NAND_WRITE_DATA, buf[i]); |
| 146 | 147 | } |
| 147 | 148 | |
| 149 | +static int xway_attach_chip(struct nand_chip *chip) | |
| 150 | +{ | |
| 151 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 152 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 153 | + | |
| 154 | + return 0; | |
| 155 | +} | |
| 156 | + | |
| 157 | +static const struct nand_controller_ops xway_nand_ops = { | |
| 158 | + .attach_chip = xway_attach_chip, | |
| 159 | +}; | |
| 160 | + | |
| 148 | 161 | /* |
| 149 | 162 | * Probe for the NAND device. |
| 150 | 163 | */ |
| @@ -180,8 +193,9 @@ static int xway_nand_probe(struct platform_device *pdev) · 29 unmodified lines | ||
| 180 | 193 | data->chip.legacy.read_byte = xway_read_byte; |
| 181 | 194 | data->chip.legacy.chip_delay = 30; |
| 182 | 195 | |
| 183 | − data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; | |
| 184 | − data->chip.ecc.algo = NAND_ECC_ALGO_HAMMING; | |
| 196 | + nand_controller_init(&data->controller); | |
| 197 | + data->controller.ops = &xway_nand_ops; | |
| 198 | + data->chip.controller = &data->controller; | |
| 185 | 199 | |
| 186 | 200 | platform_set_drvdata(pdev, data); |
| 187 | 201 | nand_set_controller_data(&data->chip, data); |
| @@ -1459,7 +1459,39 @@ static void bond_upper_dev_unlink(struct bonding *bond, struct slave *slave) · 1458 unmodified lines | ||
| 1459 | 1459 | slave->dev->flags &= ~IFF_SLAVE; |
| 1460 | 1460 | } |
| 1461 | 1461 | |
| 1462 | −static struct slave *bond_alloc_slave(struct bonding *bond) | |
| 1462 | +static void slave_kobj_release(struct kobject *kobj) | |
| 1463 | +{ | |
| 1464 | + struct slave *slave = to_slave(kobj); | |
| 1465 | + struct bonding *bond = bond_get_bond_by_slave(slave); | |
| 1466 | + | |
| 1467 | + cancel_delayed_work_sync(&slave->notify_work); | |
| 1468 | + if (BOND_MODE(bond) == BOND_MODE_8023AD) | |
| 1469 | + kfree(SLAVE_AD_INFO(slave)); | |
| 1470 | + | |
| 1471 | + kfree(slave); | |
| 1472 | +} | |
| 1473 | + | |
| 1474 | +static struct kobj_type slave_ktype = { | |
| 1475 | + .release = slave_kobj_release, | |
| 1476 | +#ifdef CONFIG_SYSFS | |
| 1477 | + .sysfs_ops = &slave_sysfs_ops, | |
| 1478 | +#endif | |
| 1479 | +}; | |
| 1480 | + | |
| 1481 | +static int bond_kobj_init(struct slave *slave) | |
| 1482 | +{ | |
| 1483 | + int err; | |
| 1484 | + | |
| 1485 | + err = kobject_init_and_add(&slave->kobj, &slave_ktype, | |
| 1486 | + &(slave->dev->dev.kobj), "bonding_slave"); | |
| 1487 | + if (err) | |
| 1488 | + kobject_put(&slave->kobj); | |
| 1489 | + | |
| 1490 | + return err; | |
| 1491 | +} | |
| 1492 | + | |
| 1493 | +static struct slave *bond_alloc_slave(struct bonding *bond, | |
| 1494 | + struct net_device *slave_dev) | |
| 1463 | 1495 | { |
| 1464 | 1496 | struct slave *slave = NULL; |
| 1465 | 1497 | |
| @@ -1467,11 +1499,17 @@ static struct slave *bond_alloc_slave(struct bonding *bond) · 1 unmodified line | ||
| 1467 | 1499 | if (!slave) |
| 1468 | 1500 | return NULL; |
| 1469 | 1501 | |
| 1502 | + slave->bond = bond; | |
| 1503 | + slave->dev = slave_dev; | |
| 1504 | + | |
| 1505 | + if (bond_kobj_init(slave)) | |
| 1506 | + return NULL; | |
| 1507 | + | |
| 1470 | 1508 | if (BOND_MODE(bond) == BOND_MODE_8023AD) { |
| 1471 | 1509 | SLAVE_AD_INFO(slave) = kzalloc(sizeof(struct ad_slave_info), |
| 1472 | 1510 | GFP_KERNEL); |
| 1473 | 1511 | if (!SLAVE_AD_INFO(slave)) { |
| 1474 | − kfree(slave); | |
| 1512 | + kobject_put(&slave->kobj); | |
| 1475 | 1513 | return NULL; |
| 1476 | 1514 | } |
| 1477 | 1515 | } |
| @@ -1480,17 +1518,6 @@ static struct slave *bond_alloc_slave(struct bonding *bond) · 2 unmodified lines | ||
| 1480 | 1518 | return slave; |
| 1481 | 1519 | } |
| 1482 | 1520 | |
| 1483 | −static void bond_free_slave(struct slave *slave) | |
| 1484 | −{ | |
| 1485 | − struct bonding *bond = bond_get_bond_by_slave(slave); | |
| 1486 | − | |
| 1487 | − cancel_delayed_work_sync(&slave->notify_work); | |
| 1488 | − if (BOND_MODE(bond) == BOND_MODE_8023AD) | |
| 1489 | − kfree(SLAVE_AD_INFO(slave)); | |
| 1490 | − | |
| 1491 | − kfree(slave); | |
| 1492 | −} | |
| 1493 | − | |
| 1494 | 1521 | static void bond_fill_ifbond(struct bonding *bond, struct ifbond *info) |
| 1495 | 1522 | { |
| 1496 | 1523 | info->bond_mode = BOND_MODE(bond); |
| @@ -1677,14 +1704,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, · 180 unmodified lines | ||
| 1677 | 1704 | goto err_undo_flags; |
| 1678 | 1705 | } |
| 1679 | 1706 | |
| 1680 | − new_slave = bond_alloc_slave(bond); | |
| 1707 | + new_slave = bond_alloc_slave(bond, slave_dev); | |
| 1681 | 1708 | if (!new_slave) { |
| 1682 | 1709 | res = -ENOMEM; |
| 1683 | 1710 | goto err_undo_flags; |
| 1684 | 1711 | } |
| 1685 | 1712 | |
| 1686 | − new_slave->bond = bond; | |
| 1687 | − new_slave->dev = slave_dev; | |
| 1688 | 1713 | /* Set the new_slave's queue_id to be zero. Queue ID mapping |
| 1689 | 1714 | * is set via sysfs or module option if desired. |
| 1690 | 1715 | */ |
| @@ -2006,7 +2031,7 @@ err_restore_mtu: · 315 unmodified lines | ||
| 2006 | 2031 | dev_set_mtu(slave_dev, new_slave->original_mtu); |
| 2007 | 2032 | |
| 2008 | 2033 | err_free: |
| 2009 | − bond_free_slave(new_slave); | |
| 2034 | + kobject_put(&new_slave->kobj); | |
| 2010 | 2035 | |
| 2011 | 2036 | err_undo_flags: |
| 2012 | 2037 | /* Enslave of first slave has failed and we need to fix master's mac */ |
| @@ -2186,7 +2211,7 @@ static int __bond_release_one(struct net_device *bond_dev, · 173 unmodified lines | ||
| 2186 | 2211 | if (!netif_is_bond_master(slave_dev)) |
| 2187 | 2212 | slave_dev->priv_flags &= ~IFF_BONDING; |
| 2188 | 2213 | |
| 2189 | − bond_free_slave(slave); | |
| 2214 | + kobject_put(&slave->kobj); | |
| 2190 | 2215 | |
| 2191 | 2216 | return 0; |
| 2192 | 2217 | } |
| @@ -121,7 +121,6 @@ static const struct slave_attribute *slave_attrs[] = { · 120 unmodified lines | ||
| 121 | 121 | }; |
| 122 | 122 | |
| 123 | 123 | #define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr) |
| 124 | −#define to_slave(obj) container_of(obj, struct slave, kobj) | |
| 125 | 124 | |
| 126 | 125 | static ssize_t slave_show(struct kobject *kobj, |
| 127 | 126 | struct attribute *attr, char *buf) |
| @@ -132,28 +131,15 @@ static ssize_t slave_show(struct kobject *kobj, · 4 unmodified lines | ||
| 132 | 131 | return slave_attr->show(slave, buf); |
| 133 | 132 | } |
| 134 | 133 | |
| 135 | −static const struct sysfs_ops slave_sysfs_ops = { | |
| 134 | +const struct sysfs_ops slave_sysfs_ops = { | |
| 136 | 135 | .show = slave_show, |
| 137 | 136 | }; |
| 138 | 137 | |
| 139 | −static struct kobj_type slave_ktype = { | |
| 140 | −#ifdef CONFIG_SYSFS | |
| 141 | − .sysfs_ops = &slave_sysfs_ops, | |
| 142 | −#endif | |
| 143 | −}; | |
| 144 | − | |
| 145 | 138 | int bond_sysfs_slave_add(struct slave *slave) |
| 146 | 139 | { |
| 147 | 140 | const struct slave_attribute **a; |
| 148 | 141 | int err; |
| 149 | 142 | |
| 150 | − err = kobject_init_and_add(&slave->kobj, &slave_ktype, | |
| 151 | − &(slave->dev->dev.kobj), "bonding_slave"); | |
| 152 | − if (err) { | |
| 153 | − kobject_put(&slave->kobj); | |
| 154 | − return err; | |
| 155 | − } | |
| 156 | − | |
| 157 | 143 | for (a = slave_attrs; *a; ++a) { |
| 158 | 144 | err = sysfs_create_file(&slave->kobj, &((*a)->attr)); |
| 159 | 145 | if (err) { |
| @@ -171,6 +157,4 @@ void bond_sysfs_slave_del(struct slave *slave) · 11 unmodified lines | ||
| 171 | 157 | |
| 172 | 158 | for (a = slave_attrs; *a; ++a) |
| 173 | 159 | sysfs_remove_file(&slave->kobj, &((*a)->attr)); |
| 174 | − | |
| 175 | − kobject_put(&slave->kobj); | |
| 176 | 160 | } |
| @@ -1033,7 +1033,7 @@ static const struct can_bittiming_const m_can_bittiming_const_31X = { · 1032 unmodified lines | ||
| 1033 | 1033 | .name = KBUILD_MODNAME, |
| 1034 | 1034 | .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ |
| 1035 | 1035 | .tseg1_max = 256, |
| 1036 | − .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ | |
| 1036 | + .tseg2_min = 2, /* Time segment 2 = phase_seg2 */ | |
| 1037 | 1037 | .tseg2_max = 128, |
| 1038 | 1038 | .sjw_max = 128, |
| 1039 | 1039 | .brp_min = 1, |
| @@ -1385,6 +1385,8 @@ static int m_can_dev_setup(struct m_can_classdev *m_can_dev) · 345 unmodified lines | ||
| 1385 | 1385 | &m_can_data_bittiming_const_31X; |
| 1386 | 1386 | break; |
| 1387 | 1387 | case 32: |
| 1388 | + case 33: | |
| 1389 | + /* Support both MCAN version v3.2.x and v3.3.0 */ | |
| 1388 | 1390 | m_can_dev->can.bittiming_const = m_can_dev->bit_timing ? |
| 1389 | 1391 | m_can_dev->bit_timing : &m_can_bittiming_const_31X; |
| 1390 | 1392 | |
| @@ -1653,7 +1655,7 @@ static int m_can_open(struct net_device *dev) · 262 unmodified lines | ||
| 1653 | 1655 | INIT_WORK(&cdev->tx_work, m_can_tx_work_queue); |
| 1654 | 1656 | |
| 1655 | 1657 | err = request_threaded_irq(dev->irq, NULL, m_can_isr, |
| 1656 | − IRQF_ONESHOT | IRQF_TRIGGER_FALLING, | |
| 1658 | + IRQF_ONESHOT, | |
| 1657 | 1659 | dev->name, dev); |
| 1658 | 1660 | } else { |
| 1659 | 1661 | err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name, |
| @@ -2735,6 +2735,10 @@ static int mcp251xfd_probe(struct spi_device *spi) · 2734 unmodified lines | ||
| 2735 | 2735 | u32 freq; |
| 2736 | 2736 | int err; |
| 2737 | 2737 | |
| 2738 | + if (!spi->irq) | |
| 2739 | + return dev_err_probe(&spi->dev, -ENXIO, | |
| 2740 | + "No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n"); | |
| 2741 | + | |
| 2738 | 2742 | rx_int = devm_gpiod_get_optional(&spi->dev, "microchip,rx-int", |
| 2739 | 2743 | GPIOD_IN); |
| 2740 | 2744 | if (PTR_ERR(rx_int) == -EPROBE_DEFER) |
| @@ -64,21 +64,27 @@ enum gs_can_identify_mode { · 63 unmodified lines | ||
| 64 | 64 | }; |
| 65 | 65 | |
| 66 | 66 | /* data types passed between host and device */ |
| 67 | + | |
| 68 | +/* The firmware on the original USB2CAN by Geschwister Schneider | |
| 69 | + * Technologie Entwicklungs- und Vertriebs UG exchanges all data | |
| 70 | + * between the host and the device in host byte order. This is done | |
| 71 | + * with the struct gs_host_config::byte_order member, which is sent | |
| 72 | + * first to indicate the desired byte order. | |
| 73 | + * | |
| 74 | + * The widely used open source firmware candleLight doesn't support | |
| 75 | + * this feature and exchanges the data in little endian byte order. | |
| 76 | + */ | |
| 67 | 77 | struct gs_host_config { |
| 68 | − u32 byte_order; | |
| 78 | + __le32 byte_order; | |
| 69 | 79 | } __packed; |
| 70 | −/* All data exchanged between host and device is exchanged in host byte order, | |
| 71 | − * thanks to the struct gs_host_config byte_order member, which is sent first | |
| 72 | − * to indicate the desired byte order. | |
| 73 | − */ | |
| 74 | 80 | |
| 75 | 81 | struct gs_device_config { |
| 76 | 82 | u8 reserved1; |
| 77 | 83 | u8 reserved2; |
| 78 | 84 | u8 reserved3; |
| 79 | 85 | u8 icount; |
| 80 | − u32 sw_version; | |
| 81 | − u32 hw_version; | |
| 86 | + __le32 sw_version; | |
| 87 | + __le32 hw_version; | |
| 82 | 88 | } __packed; |
| 83 | 89 | |
| 84 | 90 | #define GS_CAN_MODE_NORMAL 0 |
| @@ -88,26 +94,26 @@ struct gs_device_config { · 3 unmodified lines | ||
| 88 | 94 | #define GS_CAN_MODE_ONE_SHOT BIT(3) |
| 89 | 95 | |
| 90 | 96 | struct gs_device_mode { |
| 91 | − u32 mode; | |
| 92 | − u32 flags; | |
| 97 | + __le32 mode; | |
| 98 | + __le32 flags; | |
| 93 | 99 | } __packed; |
| 94 | 100 | |
| 95 | 101 | struct gs_device_state { |
| 96 | − u32 state; | |
| 97 | − u32 rxerr; | |
| 98 | − u32 txerr; | |
| 102 | + __le32 state; | |
| 103 | + __le32 rxerr; | |
| 104 | + __le32 txerr; | |
| 99 | 105 | } __packed; |
| 100 | 106 | |
| 101 | 107 | struct gs_device_bittiming { |
| 102 | − u32 prop_seg; | |
| 103 | − u32 phase_seg1; | |
| 104 | − u32 phase_seg2; | |
| 105 | − u32 sjw; | |
| 106 | − u32 brp; | |
| 108 | + __le32 prop_seg; | |
| 109 | + __le32 phase_seg1; | |
| 110 | + __le32 phase_seg2; | |
| 111 | + __le32 sjw; | |
| 112 | + __le32 brp; | |
| 107 | 113 | } __packed; |
| 108 | 114 | |
| 109 | 115 | struct gs_identify_mode { |
| 110 | − u32 mode; | |
| 116 | + __le32 mode; | |
| 111 | 117 | } __packed; |
| 112 | 118 | |
| 113 | 119 | #define GS_CAN_FEATURE_LISTEN_ONLY BIT(0) |
| @@ -118,23 +124,23 @@ struct gs_identify_mode { · 4 unmodified lines | ||
| 118 | 124 | #define GS_CAN_FEATURE_IDENTIFY BIT(5) |
| 119 | 125 | |
| 120 | 126 | struct gs_device_bt_const { |
| 121 | − u32 feature; | |
| 122 | − u32 fclk_can; | |
| 123 | − u32 tseg1_min; | |
| 124 | − u32 tseg1_max; | |
| 125 | − u32 tseg2_min; | |
| 126 | − u32 tseg2_max; | |
| 127 | − u32 sjw_max; | |
| 128 | − u32 brp_min; | |
| 129 | − u32 brp_max; | |
| 130 | − u32 brp_inc; | |
| 127 | + __le32 feature; | |
| 128 | + __le32 fclk_can; | |
| 129 | + __le32 tseg1_min; | |
| 130 | + __le32 tseg1_max; | |
| 131 | + __le32 tseg2_min; | |
| 132 | + __le32 tseg2_max; | |
| 133 | + __le32 sjw_max; | |
| 134 | + __le32 brp_min; | |
| 135 | + __le32 brp_max; | |
| 136 | + __le32 brp_inc; | |
| 131 | 137 | } __packed; |
| 132 | 138 | |
| 133 | 139 | #define GS_CAN_FLAG_OVERFLOW 1 |
| 134 | 140 | |
| 135 | 141 | struct gs_host_frame { |
| 136 | 142 | u32 echo_id; |
| 137 | − u32 can_id; | |
| 143 | + __le32 can_id; | |
| 138 | 144 | |
| 139 | 145 | u8 can_dlc; |
| 140 | 146 | u8 channel; |
| @@ -330,13 +336,13 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) · 189 unmodified lines | ||
| 330 | 336 | if (!skb) |
| 331 | 337 | return; |
| 332 | 338 | |
| 333 | − cf->can_id = hf->can_id; | |
| 339 | + cf->can_id = le32_to_cpu(hf->can_id); | |
| 334 | 340 | |
| 335 | 341 | can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); |
| 336 | 342 | memcpy(cf->data, hf->data, 8); |
| 337 | 343 | |
| 338 | 344 | /* ERROR frames tell us information about the controller */ |
| 339 | − if (hf->can_id & CAN_ERR_FLAG) | |
| 345 | + if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) | |
| 340 | 346 | gs_update_state(dev, cf); |
| 341 | 347 | |
| 342 | 348 | netdev->stats.rx_packets++; |
| @@ -419,11 +425,11 @@ static int gs_usb_set_bittiming(struct net_device *netdev) · 76 unmodified lines | ||
| 419 | 425 | if (!dbt) |
| 420 | 426 | return -ENOMEM; |
| 421 | 427 | |
| 422 | − dbt->prop_seg = bt->prop_seg; | |
| 423 | − dbt->phase_seg1 = bt->phase_seg1; | |
| 424 | − dbt->phase_seg2 = bt->phase_seg2; | |
| 425 | − dbt->sjw = bt->sjw; | |
| 426 | − dbt->brp = bt->brp; | |
| 428 | + dbt->prop_seg = cpu_to_le32(bt->prop_seg); | |
| 429 | + dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1); | |
| 430 | + dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2); | |
| 431 | + dbt->sjw = cpu_to_le32(bt->sjw); | |
| 432 | + dbt->brp = cpu_to_le32(bt->brp); | |
| 427 | 433 | |
| 428 | 434 | /* request bit timings */ |
| 429 | 435 | rc = usb_control_msg(interface_to_usbdev(intf), |
| @@ -504,7 +510,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, · 74 unmodified lines | ||
| 504 | 510 | |
| 505 | 511 | cf = (struct can_frame *)skb->data; |
| 506 | 512 | |
| 507 | − hf->can_id = cf->can_id; | |
| 513 | + hf->can_id = cpu_to_le32(cf->can_id); | |
| 508 | 514 | hf->can_dlc = can_get_cc_dlc(cf, dev->can.ctrlmode); |
| 509 | 515 | |
| 510 | 516 | memcpy(hf->data, cf->data, cf->len); |
| @@ -575,6 +581,7 @@ static int gs_can_open(struct net_device *netdev) · 64 unmodified lines | ||
| 575 | 581 | int rc, i; |
| 576 | 582 | struct gs_device_mode *dm; |
| 577 | 583 | u32 ctrlmode; |
| 584 | + u32 flags = 0; | |
| 578 | 585 | |
| 579 | 586 | rc = open_candev(netdev); |
| 580 | 587 | if (rc) |
| @@ -642,24 +649,24 @@ static int gs_can_open(struct net_device *netdev) · 61 unmodified lines | ||
| 642 | 649 | |
| 643 | 650 | /* flags */ |
| 644 | 651 | ctrlmode = dev->can.ctrlmode; |
| 645 | − dm->flags = 0; | |
| 646 | 652 | |
| 647 | 653 | if (ctrlmode & CAN_CTRLMODE_LOOPBACK) |
| 648 | − dm->flags |= GS_CAN_MODE_LOOP_BACK; | |
| 654 | + flags |= GS_CAN_MODE_LOOP_BACK; | |
| 649 | 655 | else if (ctrlmode & CAN_CTRLMODE_LISTENONLY) |
| 650 | − dm->flags |= GS_CAN_MODE_LISTEN_ONLY; | |
| 656 | + flags |= GS_CAN_MODE_LISTEN_ONLY; | |
| 651 | 657 | |
| 652 | 658 | /* Controller is not allowed to retry TX |
| 653 | 659 | * this mode is unavailable on atmels uc3c hardware |
| 654 | 660 | */ |
| 655 | 661 | if (ctrlmode & CAN_CTRLMODE_ONE_SHOT) |
| 656 | − dm->flags |= GS_CAN_MODE_ONE_SHOT; | |
| 662 | + flags |= GS_CAN_MODE_ONE_SHOT; | |
| 657 | 663 | |
| 658 | 664 | if (ctrlmode & CAN_CTRLMODE_3_SAMPLES) |
| 659 | − dm->flags |= GS_CAN_MODE_TRIPLE_SAMPLE; | |
| 665 | + flags |= GS_CAN_MODE_TRIPLE_SAMPLE; | |
| 660 | 666 | |
| 661 | 667 | /* finally start device */ |
| 662 | − dm->mode = GS_CAN_MODE_START; | |
| 668 | + dm->mode = cpu_to_le32(GS_CAN_MODE_START); | |
| 669 | + dm->flags = cpu_to_le32(flags); | |
| 663 | 670 | rc = usb_control_msg(interface_to_usbdev(dev->iface), |
| 664 | 671 | usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0), |
| 665 | 672 | GS_USB_BREQ_MODE, |
| @@ -739,9 +746,9 @@ static int gs_usb_set_identify(struct net_device *netdev, bool do_identify) · 73 unmodified lines | ||
| 739 | 746 | return -ENOMEM; |
| 740 | 747 | |
| 741 | 748 | if (do_identify) |
| 742 | − imode->mode = GS_CAN_IDENTIFY_ON; | |
| 749 | + imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_ON); | |
| 743 | 750 | else |
| 744 | − imode->mode = GS_CAN_IDENTIFY_OFF; | |
| 751 | + imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF); | |
| 745 | 752 | |
| 746 | 753 | rc = usb_control_msg(interface_to_usbdev(dev->iface), |
| 747 | 754 | usb_sndctrlpipe(interface_to_usbdev(dev->iface), |
| @@ -792,6 +799,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, · 44 unmodified lines | ||
| 792 | 799 | struct net_device *netdev; |
| 793 | 800 | int rc; |
| 794 | 801 | struct gs_device_bt_const *bt_const; |
| 802 | + u32 feature; | |
| 795 | 803 | |
| 796 | 804 | bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL); |
| 797 | 805 | if (!bt_const) |
| @@ -832,14 +840,14 @@ static struct gs_can *gs_make_candev(unsigned int channel, · 34 unmodified lines | ||
| 832 | 840 | |
| 833 | 841 | /* dev setup */ |
| 834 | 842 | strcpy(dev->bt_const.name, "gs_usb"); |
| 835 | − dev->bt_const.tseg1_min = bt_const->tseg1_min; | |
| 836 | − dev->bt_const.tseg1_max = bt_const->tseg1_max; | |
| 837 | − dev->bt_const.tseg2_min = bt_const->tseg2_min; | |
| 838 | − dev->bt_const.tseg2_max = bt_const->tseg2_max; | |
| 839 | − dev->bt_const.sjw_max = bt_const->sjw_max; | |
| 840 | − dev->bt_const.brp_min = bt_const->brp_min; | |
| 841 | − dev->bt_const.brp_max = bt_const->brp_max; | |
| 842 | − dev->bt_const.brp_inc = bt_const->brp_inc; | |
| 843 | + dev->bt_const.tseg1_min = le32_to_cpu(bt_const->tseg1_min); | |
| 844 | + dev->bt_const.tseg1_max = le32_to_cpu(bt_const->tseg1_max); | |
| 845 | + dev->bt_const.tseg2_min = le32_to_cpu(bt_const->tseg2_min); | |
| 846 | + dev->bt_const.tseg2_max = le32_to_cpu(bt_const->tseg2_max); | |
| 847 | + dev->bt_const.sjw_max = le32_to_cpu(bt_const->sjw_max); | |
| 848 | + dev->bt_const.brp_min = le32_to_cpu(bt_const->brp_min); | |
| 849 | + dev->bt_const.brp_max = le32_to_cpu(bt_const->brp_max); | |
| 850 | + dev->bt_const.brp_inc = le32_to_cpu(bt_const->brp_inc); | |
| 843 | 851 | |
| 844 | 852 | dev->udev = interface_to_usbdev(intf); |
| 845 | 853 | dev->iface = intf; |
| @@ -856,28 +864,29 @@ static struct gs_can *gs_make_candev(unsigned int channel, · 10 unmodified lines | ||
| 856 | 864 | |
| 857 | 865 | /* can setup */ |
| 858 | 866 | dev->can.state = CAN_STATE_STOPPED; |
| 859 | − dev->can.clock.freq = bt_const->fclk_can; | |
| 867 | + dev->can.clock.freq = le32_to_cpu(bt_const->fclk_can); | |
| 860 | 868 | dev->can.bittiming_const = &dev->bt_const; |
| 861 | 869 | dev->can.do_set_bittiming = gs_usb_set_bittiming; |
| 862 | 870 | |
| 863 | 871 | dev->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC; |
| 864 | 872 | |
| 865 | − if (bt_const->feature & GS_CAN_FEATURE_LISTEN_ONLY) | |
| 873 | + feature = le32_to_cpu(bt_const->feature); | |
| 874 | + if (feature & GS_CAN_FEATURE_LISTEN_ONLY) | |
| 866 | 875 | dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY; |
| 867 | 876 | |
| 868 | − if (bt_const->feature & GS_CAN_FEATURE_LOOP_BACK) | |
| 877 | + if (feature & GS_CAN_FEATURE_LOOP_BACK) | |
| 869 | 878 | dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK; |
| 870 | 879 | |
| 871 | − if (bt_const->feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) | |
| 880 | + if (feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) | |
| 872 | 881 | dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; |
| 873 | 882 | |
| 874 | − if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT) | |
| 883 | + if (feature & GS_CAN_FEATURE_ONE_SHOT) | |
| 875 | 884 | dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; |
| 876 | 885 | |
| 877 | 886 | SET_NETDEV_DEV(netdev, &intf->dev); |
| 878 | 887 | |
| 879 | − if (dconf->sw_version > 1) | |
| 880 | − if (bt_const->feature & GS_CAN_FEATURE_IDENTIFY) | |
| 888 | + if (le32_to_cpu(dconf->sw_version) > 1) | |
| 889 | + if (feature & GS_CAN_FEATURE_IDENTIFY) | |
| 881 | 890 | netdev->ethtool_ops = &gs_usb_ethtool_ops; |
| 882 | 891 | |
| 883 | 892 | kfree(bt_const); |
| @@ -912,7 +921,7 @@ static int gs_usb_probe(struct usb_interface *intf, · 28 unmodified lines | ||
| 912 | 921 | if (!hconf) |
| 913 | 922 | return -ENOMEM; |
| 914 | 923 | |
| 915 | − hconf->byte_order = 0x0000beef; | |
| 924 | + hconf->byte_order = cpu_to_le32(0x0000beef); | |
| 916 | 925 | |
| 917 | 926 | /* send host config */ |
| 918 | 927 | rc = usb_control_msg(interface_to_usbdev(intf), |
| @@ -516,6 +516,7 @@ int ena_com_rx_pkt(struct ena_com_io_cq *io_cq, · 515 unmodified lines | ||
| 516 | 516 | { |
| 517 | 517 | struct ena_com_rx_buf_info *ena_buf = &ena_rx_ctx->ena_bufs[0]; |
| 518 | 518 | struct ena_eth_io_rx_cdesc_base *cdesc = NULL; |
| 519 | + u16 q_depth = io_cq->q_depth; | |
| 519 | 520 | u16 cdesc_idx = 0; |
| 520 | 521 | u16 nb_hw_desc; |
| 521 | 522 | u16 i = 0; |
| @@ -543,6 +544,8 @@ int ena_com_rx_pkt(struct ena_com_io_cq *io_cq, · 21 unmodified lines | ||
| 543 | 544 | do { |
| 544 | 545 | ena_buf[i].len = cdesc->length; |
| 545 | 546 | ena_buf[i].req_id = cdesc->req_id; |
| 547 | + if (unlikely(ena_buf[i].req_id >= q_depth)) | |
| 548 | + return -EIO; | |
| 546 | 549 | |
| 547 | 550 | if (++i >= nb_hw_desc) |
| 548 | 551 | break; |
| @@ -789,24 +789,6 @@ static void ena_free_all_io_tx_resources(struct ena_adapter *adapter) · 788 unmodified lines | ||
| 789 | 789 | adapter->num_io_queues); |
| 790 | 790 | } |
| 791 | 791 | |
| 792 | −static int validate_rx_req_id(struct ena_ring *rx_ring, u16 req_id) | |
| 793 | −{ | |
| 794 | − if (likely(req_id < rx_ring->ring_size)) | |
| 795 | − return 0; | |
| 796 | − | |
| 797 | − netif_err(rx_ring->adapter, rx_err, rx_ring->netdev, | |
| 798 | − "Invalid rx req_id: %hu\n", req_id); | |
| 799 | − | |
| 800 | − u64_stats_update_begin(&rx_ring->syncp); | |
| 801 | − rx_ring->rx_stats.bad_req_id++; | |
| 802 | − u64_stats_update_end(&rx_ring->syncp); | |
| 803 | − | |
| 804 | − /* Trigger device reset */ | |
| 805 | − rx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID; | |
| 806 | − set_bit(ENA_FLAG_TRIGGER_RESET, &rx_ring->adapter->flags); | |
| 807 | − return -EFAULT; | |
| 808 | −} | |
| 809 | − | |
| 810 | 792 | /* ena_setup_rx_resources - allocate I/O Rx resources (Descriptors) |
| 811 | 793 | * @adapter: network interface device structure |
| 812 | 794 | * @qid: queue index |
| @@ -926,10 +908,14 @@ static void ena_free_all_io_rx_resources(struct ena_adapter *adapter) · 113 unmodified lines | ||
| 926 | 908 | static int ena_alloc_rx_page(struct ena_ring *rx_ring, |
| 927 | 909 | struct ena_rx_buffer *rx_info, gfp_t gfp) |
| 928 | 910 | { |
| 911 | + int headroom = rx_ring->rx_headroom; | |
| 929 | 912 | struct ena_com_buf *ena_buf; |
| 930 | 913 | struct page *page; |
| 931 | 914 | dma_addr_t dma; |
| 932 | 915 | |
| 916 | + /* restore page offset value in case it has been changed by device */ | |
| 917 | + rx_info->page_offset = headroom; | |
| 918 | + | |
| 933 | 919 | /* if previous allocated page is not used */ |
| 934 | 920 | if (unlikely(rx_info->page)) |
| 935 | 921 | return 0; |
| @@ -959,10 +945,9 @@ static int ena_alloc_rx_page(struct ena_ring *rx_ring, · 23 unmodified lines | ||
| 959 | 945 | "Allocate page %p, rx_info %p\n", page, rx_info); |
| 960 | 946 | |
| 961 | 947 | rx_info->page = page; |
| 962 | − rx_info->page_offset = 0; | |
| 963 | 948 | ena_buf = &rx_info->ena_buf; |
| 964 | − ena_buf->paddr = dma + rx_ring->rx_headroom; | |
| 965 | − ena_buf->len = ENA_PAGE_SIZE - rx_ring->rx_headroom; | |
| 949 | + ena_buf->paddr = dma + headroom; | |
| 950 | + ena_buf->len = ENA_PAGE_SIZE - headroom; | |
| 966 | 951 | |
| 967 | 952 | return 0; |
| 968 | 953 | } |
| @@ -1356,15 +1341,10 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, · 387 unmodified lines | ||
| 1356 | 1341 | struct ena_rx_buffer *rx_info; |
| 1357 | 1342 | u16 len, req_id, buf = 0; |
| 1358 | 1343 | void *va; |
| 1359 | − int rc; | |
| 1360 | 1344 | |
| 1361 | 1345 | len = ena_bufs[buf].len; |
| 1362 | 1346 | req_id = ena_bufs[buf].req_id; |
| 1363 | 1347 | |
| 1364 | − rc = validate_rx_req_id(rx_ring, req_id); | |
| 1365 | − if (unlikely(rc < 0)) | |
| 1366 | − return NULL; | |
| 1367 | − | |
| 1368 | 1348 | rx_info = &rx_ring->rx_buffer_info[req_id]; |
| 1369 | 1349 | |
| 1370 | 1350 | if (unlikely(!rx_info->page)) { |
| @@ -1379,7 +1359,8 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, · 8 unmodified lines | ||
| 1379 | 1359 | |
| 1380 | 1360 | /* save virt address of first buffer */ |
| 1381 | 1361 | va = page_address(rx_info->page) + rx_info->page_offset; |
| 1382 | − prefetch(va + NET_IP_ALIGN); | |
| 1362 | + | |
| 1363 | + prefetch(va); | |
| 1383 | 1364 | |
| 1384 | 1365 | if (len <= rx_ring->rx_copybreak) { |
| 1385 | 1366 | skb = ena_alloc_skb(rx_ring, false); |
| @@ -1420,8 +1401,6 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, · 34 unmodified lines | ||
| 1420 | 1401 | |
| 1421 | 1402 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_info->page, |
| 1422 | 1403 | rx_info->page_offset, len, ENA_PAGE_SIZE); |
| 1423 | − /* The offset is non zero only for the first buffer */ | |
| 1424 | − rx_info->page_offset = 0; | |
| 1425 | 1404 | |
| 1426 | 1405 | netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev, |
| 1427 | 1406 | "RX skb updated. len %d. data_len %d\n", |
| @@ -1440,10 +1419,6 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, · 12 unmodified lines | ||
| 1440 | 1419 | len = ena_bufs[buf].len; |
| 1441 | 1420 | req_id = ena_bufs[buf].req_id; |
| 1442 | 1421 | |
| 1443 | − rc = validate_rx_req_id(rx_ring, req_id); | |
| 1444 | − if (unlikely(rc < 0)) | |
| 1445 | − return NULL; | |
| 1446 | − | |
| 1447 | 1422 | rx_info = &rx_ring->rx_buffer_info[req_id]; |
| 1448 | 1423 | } while (1); |
| 1449 | 1424 | |
| @@ -1544,8 +1519,7 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp) · 94 unmodified lines | ||
| 1544 | 1519 | int ret; |
| 1545 | 1520 | |
| 1546 | 1521 | rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id]; |
| 1547 | − xdp->data = page_address(rx_info->page) + | |
| 1548 | − rx_info->page_offset + rx_ring->rx_headroom; | |
| 1522 | + xdp->data = page_address(rx_info->page) + rx_info->page_offset; | |
| 1549 | 1523 | xdp_set_data_meta_invalid(xdp); |
| 1550 | 1524 | xdp->data_hard_start = page_address(rx_info->page); |
| 1551 | 1525 | xdp->data_end = xdp->data + rx_ring->ena_bufs[0].len; |
| @@ -1612,8 +1586,9 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, · 60 unmodified lines | ||
| 1612 | 1586 | if (unlikely(ena_rx_ctx.descs == 0)) |
| 1613 | 1587 | break; |
| 1614 | 1588 | |
| 1589 | + /* First descriptor might have an offset set by the device */ | |
| 1615 | 1590 | rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id]; |
| 1616 | − rx_info->page_offset = ena_rx_ctx.pkt_offset; | |
| 1591 | + rx_info->page_offset += ena_rx_ctx.pkt_offset; | |
| 1617 | 1592 | |
| 1618 | 1593 | netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev, |
| 1619 | 1594 | "rx_poll: q %d got packet from ena. descs #: %d l3 proto %d l4 proto %d hash: %x\n", |
| @@ -1697,12 +1672,18 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, · 77 unmodified lines | ||
| 1697 | 1672 | error: |
| 1698 | 1673 | adapter = netdev_priv(rx_ring->netdev); |
| 1699 | 1674 | |
| 1700 | − u64_stats_update_begin(&rx_ring->syncp); | |
| 1701 | − rx_ring->rx_stats.bad_desc_num++; | |
| 1702 | − u64_stats_update_end(&rx_ring->syncp); | |
| 1675 | + if (rc == -ENOSPC) { | |
| 1676 | + u64_stats_update_begin(&rx_ring->syncp); | |
| 1677 | + rx_ring->rx_stats.bad_desc_num++; | |
| 1678 | + u64_stats_update_end(&rx_ring->syncp); | |
| 1679 | + adapter->reset_reason = ENA_REGS_RESET_TOO_MANY_RX_DESCS; | |
| 1680 | + } else { | |
| 1681 | + u64_stats_update_begin(&rx_ring->syncp); | |
| 1682 | + rx_ring->rx_stats.bad_req_id++; | |
| 1683 | + u64_stats_update_end(&rx_ring->syncp); | |
| 1684 | + adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID; | |
| 1685 | + } | |
| 1703 | 1686 | |
| 1704 | − /* Too many desc from the device. Trigger reset */ | |
| 1705 | − adapter->reset_reason = ENA_REGS_RESET_TOO_MANY_RX_DESCS; | |
| 1706 | 1687 | set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags); |
| 1707 | 1688 | |
| 1708 | 1689 | return 0; |
| @@ -3388,16 +3369,9 @@ static int ena_device_init(struct ena_com_dev *ena_dev, struct pci_dev *pdev, · 1679 unmodified lines | ||
| 3388 | 3369 | goto err_mmio_read_less; |
| 3389 | 3370 | } |
| 3390 | 3371 | |
| 3391 | − rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(dma_width)); | |
| 3372 | + rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_width)); | |
| 3392 | 3373 | if (rc) { |
| 3393 | − dev_err(dev, "pci_set_dma_mask failed 0x%x\n", rc); | |
| 3394 | − goto err_mmio_read_less; | |
| 3395 | − } | |
| 3396 | − | |
| 3397 | − rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(dma_width)); | |
| 3398 | − if (rc) { | |
| 3399 | − dev_err(dev, "err_pci_set_consistent_dma_mask failed 0x%x\n", | |
| 3400 | − rc); | |
| 3374 | + dev_err(dev, "dma_set_mask_and_coherent failed %d\n", rc); | |
| 3401 | 3375 | goto err_mmio_read_less; |
| 3402 | 3376 | } |
| 3403 | 3377 | |
| @@ -4167,6 +4141,12 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 763 unmodified lines | ||
| 4167 | 4141 | return rc; |
| 4168 | 4142 | } |
| 4169 | 4143 | |
| 4144 | + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(ENA_MAX_PHYS_ADDR_SIZE_BITS)); | |
| 4145 | + if (rc) { | |
| 4146 | + dev_err(&pdev->dev, "dma_set_mask_and_coherent failed %d\n", rc); | |
| 4147 | + goto err_disable_device; | |
| 4148 | + } | |
| 4149 | + | |
| 4170 | 4150 | pci_set_master(pdev); |
| 4171 | 4151 | |
| 4172 | 4152 | ena_dev = vzalloc(sizeof(*ena_dev)); |
| @@ -413,85 +413,63 @@ int aq_ring_rx_clean(struct aq_ring_s *self, · 412 unmodified lines | ||
| 413 | 413 | buff->rxdata.pg_off, |
| 414 | 414 | buff->len, DMA_FROM_DEVICE); |
| 415 | 415 | |
| 416 | − /* for single fragment packets use build_skb() */ | |
| 417 | − if (buff->is_eop && | |
| 418 | − buff->len <= AQ_CFG_RX_FRAME_MAX - AQ_SKB_ALIGN) { | |
| 419 | − skb = build_skb(aq_buf_vaddr(&buff->rxdata), | |
| 416 | + skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE); | |
| 417 | + if (unlikely(!skb)) { | |
| 418 | + u64_stats_update_begin(&self->stats.rx.syncp); | |
| 419 | + self->stats.rx.skb_alloc_fails++; | |
| 420 | + u64_stats_update_end(&self->stats.rx.syncp); | |
| 421 | + err = -ENOMEM; | |
| 422 | + goto err_exit; | |
| 423 | + } | |
| 424 | + if (is_ptp_ring) | |
| 425 | + buff->len -= | |
| 426 | + aq_ptp_extract_ts(self->aq_nic, skb, | |
| 427 | + aq_buf_vaddr(&buff->rxdata), | |
| 428 | + buff->len); | |
| 429 | + | |
| 430 | + hdr_len = buff->len; | |
| 431 | + if (hdr_len > AQ_CFG_RX_HDR_SIZE) | |
| 432 | + hdr_len = eth_get_headlen(skb->dev, | |
| 433 | + aq_buf_vaddr(&buff->rxdata), | |
| 434 | + AQ_CFG_RX_HDR_SIZE); | |
| 435 | + | |
| 436 | + memcpy(__skb_put(skb, hdr_len), aq_buf_vaddr(&buff->rxdata), | |
| 437 | + ALIGN(hdr_len, sizeof(long))); | |
| 438 | + | |
| 439 | + if (buff->len - hdr_len > 0) { | |
| 440 | + skb_add_rx_frag(skb, 0, buff->rxdata.page, | |
| 441 | + buff->rxdata.pg_off + hdr_len, | |
| 442 | + buff->len - hdr_len, | |
| 420 | 443 | AQ_CFG_RX_FRAME_MAX); |
| 421 | − if (unlikely(!skb)) { | |
| 422 | − u64_stats_update_begin(&self->stats.rx.syncp); | |
| 423 | − self->stats.rx.skb_alloc_fails++; | |
| 424 | − u64_stats_update_end(&self->stats.rx.syncp); | |
| 425 | − err = -ENOMEM; | |
| 426 | − goto err_exit; | |
| 427 | − } | |
| 428 | − if (is_ptp_ring) | |
| 429 | − buff->len -= | |
| 430 | − aq_ptp_extract_ts(self->aq_nic, skb, | |
| 431 | − aq_buf_vaddr(&buff->rxdata), | |
| 432 | − buff->len); | |
| 433 | − skb_put(skb, buff->len); | |
| 434 | 444 | page_ref_inc(buff->rxdata.page); |
| 435 | − } else { | |
| 436 | − skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE); | |
| 437 | − if (unlikely(!skb)) { | |
| 438 | − u64_stats_update_begin(&self->stats.rx.syncp); | |
| 439 | − self->stats.rx.skb_alloc_fails++; | |
| 440 | − u64_stats_update_end(&self->stats.rx.syncp); | |
| 441 | − err = -ENOMEM; | |
| 442 | − goto err_exit; | |
| 443 | − } | |
| 444 | − if (is_ptp_ring) | |
| 445 | − buff->len -= | |
| 446 | − aq_ptp_extract_ts(self->aq_nic, skb, | |
| 447 | − aq_buf_vaddr(&buff->rxdata), | |
| 448 | − buff->len); | |
| 449 | − | |
| 450 | − hdr_len = buff->len; | |
| 451 | − if (hdr_len > AQ_CFG_RX_HDR_SIZE) | |
| 452 | − hdr_len = eth_get_headlen(skb->dev, | |
| 453 | − aq_buf_vaddr(&buff->rxdata), | |
| 454 | − AQ_CFG_RX_HDR_SIZE); | |
| 455 | − | |
| 456 | − memcpy(__skb_put(skb, hdr_len), aq_buf_vaddr(&buff->rxdata), | |
| 457 | − ALIGN(hdr_len, sizeof(long))); | |
| 458 | − | |
| 459 | − if (buff->len - hdr_len > 0) { | |
| 460 | − skb_add_rx_frag(skb, 0, buff->rxdata.page, | |
| 461 | − buff->rxdata.pg_off + hdr_len, | |
| 462 | − buff->len - hdr_len, | |
| 463 | − AQ_CFG_RX_FRAME_MAX); | |
| 464 | − page_ref_inc(buff->rxdata.page); | |
| 465 | − } | |
| 445 | + } | |
| 466 | 446 | |
| 467 | − if (!buff->is_eop) { | |
| 468 | − buff_ = buff; | |
| 469 | − i = 1U; | |
| 470 | − do { | |
| 471 | − next_ = buff_->next, | |
| 472 | − buff_ = &self->buff_ring[next_]; | |
| 447 | + if (!buff->is_eop) { | |
| 448 | + buff_ = buff; | |
| 449 | + i = 1U; | |
| 450 | + do { | |
| 451 | + next_ = buff_->next; | |
| 452 | + buff_ = &self->buff_ring[next_]; | |
| 473 | 453 | |
| 474 | − dma_sync_single_range_for_cpu( | |
| 475 | − aq_nic_get_dev(self->aq_nic), | |
| 476 | − buff_->rxdata.daddr, | |
| 477 | − buff_->rxdata.pg_off, | |
| 478 | − buff_->len, | |
| 479 | − DMA_FROM_DEVICE); | |
| 480 | − skb_add_rx_frag(skb, i++, | |
| 481 | − buff_->rxdata.page, | |
| 482 | − buff_->rxdata.pg_off, | |
| 483 | − buff_->len, | |
| 484 | − AQ_CFG_RX_FRAME_MAX); | |
| 485 | − page_ref_inc(buff_->rxdata.page); | |
| 486 | − buff_->is_cleaned = 1; | |
| 487 | − | |
| 488 | − buff->is_ip_cso &= buff_->is_ip_cso; | |
| 489 | − buff->is_udp_cso &= buff_->is_udp_cso; | |
| 490 | − buff->is_tcp_cso &= buff_->is_tcp_cso; | |
| 491 | − buff->is_cso_err |= buff_->is_cso_err; | |
| 454 | + dma_sync_single_range_for_cpu(aq_nic_get_dev(self->aq_nic), | |
| 455 | + buff_->rxdata.daddr, | |
| 456 | + buff_->rxdata.pg_off, | |
| 457 | + buff_->len, | |
| 458 | + DMA_FROM_DEVICE); | |
| 459 | + skb_add_rx_frag(skb, i++, | |
| 460 | + buff_->rxdata.page, | |
| 461 | + buff_->rxdata.pg_off, | |
| 462 | + buff_->len, | |
| 463 | + AQ_CFG_RX_FRAME_MAX); | |
| 464 | + page_ref_inc(buff_->rxdata.page); | |
| 465 | + buff_->is_cleaned = 1; | |
| 492 | 466 | |
| 493 | − } while (!buff_->is_eop); | |
| 494 | − } | |
| 467 | + buff->is_ip_cso &= buff_->is_ip_cso; | |
| 468 | + buff->is_udp_cso &= buff_->is_udp_cso; | |
| 469 | + buff->is_tcp_cso &= buff_->is_tcp_cso; | |
| 470 | + buff->is_cso_err |= buff_->is_cso_err; | |
| 471 | + | |
| 472 | + } while (!buff_->is_eop); | |
| 495 | 473 | } |
| 496 | 474 | |
| 497 | 475 | if (buff->is_vlan) |
| @@ -11590,7 +11590,8 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) · 11589 unmodified lines | ||
| 11590 | 11590 | if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0 && |
| 11591 | 11591 | dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) { |
| 11592 | 11592 | dev_err(&pdev->dev, "System does not support DMA, aborting\n"); |
| 11593 | − goto init_err_disable; | |
| 11593 | + rc = -EIO; | |
| 11594 | + goto init_err_release; | |
| 11594 | 11595 | } |
| 11595 | 11596 | |
| 11596 | 11597 | pci_set_master(pdev); |
| @@ -12674,6 +12675,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) · 1077 unmodified lines | ||
| 12674 | 12675 | create_singlethread_workqueue("bnxt_pf_wq"); |
| 12675 | 12676 | if (!bnxt_pf_wq) { |
| 12676 | 12677 | dev_err(&pdev->dev, "Unable to create workqueue.\n"); |
| 12678 | + rc = -ENOMEM; | |
| 12677 | 12679 | goto init_err_pci_clean; |
| 12678 | 12680 | } |
| 12679 | 12681 | } |
| @@ -68,7 +68,7 @@ config CHELSIO_T3 · 67 unmodified lines | ||
| 68 | 68 | |
| 69 | 69 | config CHELSIO_T4 |
| 70 | 70 | tristate "Chelsio Communications T4/T5/T6 Ethernet support" |
| 71 | − depends on PCI && (IPV6 || IPV6=n) | |
| 71 | + depends on PCI && (IPV6 || IPV6=n) && (TLS || TLS=n) | |
| 72 | 72 | select FW_LOADER |
| 73 | 73 | select MDIO |
| 74 | 74 | select ZLIB_DEFLATE |
| @@ -880,7 +880,8 @@ int set_filter_wr(struct adapter *adapter, int fidx) · 879 unmodified lines | ||
| 880 | 880 | FW_FILTER_WR_OVLAN_VLD_V(f->fs.val.ovlan_vld) | |
| 881 | 881 | FW_FILTER_WR_IVLAN_VLDM_V(f->fs.mask.ivlan_vld) | |
| 882 | 882 | FW_FILTER_WR_OVLAN_VLDM_V(f->fs.mask.ovlan_vld)); |
| 883 | − fwr->smac_sel = f->smt->idx; | |
| 883 | + if (f->fs.newsmac) | |
| 884 | + fwr->smac_sel = f->smt->idx; | |
| 884 | 885 | fwr->rx_chan_rx_rpl_iq = |
| 885 | 886 | htons(FW_FILTER_WR_RX_CHAN_V(0) | |
| 886 | 887 | FW_FILTER_WR_RX_RPL_IQ_V(adapter->sge.fw_evtq.abs_id)); |
| @@ -544,7 +544,9 @@ static int chcr_ktls_dev_add(struct net_device *netdev, struct sock *sk, · 543 unmodified lines | ||
| 544 | 544 | /* need to wait for hw response, can't free tx_info yet. */ |
| 545 | 545 | if (tx_info->open_state == CH_KTLS_OPEN_PENDING) |
| 546 | 546 | tx_info->pending_close = true; |
| 547 | − /* free the lock after the cleanup */ | |
| 547 | + else | |
| 548 | + spin_unlock_bh(&tx_info->lock); | |
| 549 | + /* if in pending close, free the lock after the cleanup */ | |
| 548 | 550 | goto put_module; |
| 549 | 551 | } |
| 550 | 552 | spin_unlock_bh(&tx_info->lock); |
| @@ -4,6 +4,8 @@ config FSL_DPAA2_ETH · 3 unmodified lines | ||
| 4 | 4 | depends on FSL_MC_BUS && FSL_MC_DPIO |
| 5 | 5 | select PHYLINK |
| 6 | 6 | select PCS_LYNX |
| 7 | + select FSL_XGMAC_MDIO | |
| 8 | + select NET_DEVLINK | |
| 7 | 9 | help |
| 8 | 10 | This is the DPAA2 Ethernet driver supporting Freescale SoCs |
| 9 | 11 | with DPAA2 (DataPath Acceleration Architecture v2). |
| @@ -92,18 +92,8 @@ static int enetc_setup_taprio(struct net_device *ndev, · 91 unmodified lines | ||
| 92 | 92 | gcl_config->atc = 0xff; |
| 93 | 93 | gcl_config->acl_len = cpu_to_le16(gcl_len); |
| 94 | 94 | |
| 95 | − if (!admin_conf->base_time) { | |
| 96 | − gcl_data->btl = | |
| 97 | − cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR0)); | |
| 98 | − gcl_data->bth = | |
| 99 | − cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR1)); | |
| 100 | − } else { | |
| 101 | − gcl_data->btl = | |
| 102 | − cpu_to_le32(lower_32_bits(admin_conf->base_time)); | |
| 103 | − gcl_data->bth = | |
| 104 | − cpu_to_le32(upper_32_bits(admin_conf->base_time)); | |
| 105 | − } | |
| 106 | − | |
| 95 | + gcl_data->btl = cpu_to_le32(lower_32_bits(admin_conf->base_time)); | |
| 96 | + gcl_data->bth = cpu_to_le32(upper_32_bits(admin_conf->base_time)); | |
| 107 | 97 | gcl_data->ct = cpu_to_le32(admin_conf->cycle_time); |
| 108 | 98 | gcl_data->cte = cpu_to_le32(admin_conf->cycle_time_extension); |
| 109 | 99 | |
| @@ -2156,8 +2156,11 @@ static int do_reset(struct ibmvnic_adapter *adapter, · 2155 unmodified lines | ||
| 2156 | 2156 | for (i = 0; i < adapter->req_rx_queues; i++) |
| 2157 | 2157 | napi_schedule(&adapter->napi[i]); |
| 2158 | 2158 | |
| 2159 | − if (adapter->reset_reason != VNIC_RESET_FAILOVER) | |
| 2159 | + if (adapter->reset_reason == VNIC_RESET_FAILOVER || | |
| 2160 | + adapter->reset_reason == VNIC_RESET_MOBILITY) { | |
| 2160 | 2161 | call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); |
| 2162 | + call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev); | |
| 2163 | + } | |
| 2161 | 2164 | |
| 2162 | 2165 | rc = 0; |
| 2163 | 2166 | |
| @@ -2227,6 +2230,9 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter, · 63 unmodified lines | ||
| 2227 | 2230 | if (rc) |
| 2228 | 2231 | return IBMVNIC_OPEN_FAILED; |
| 2229 | 2232 | |
| 2233 | + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); | |
| 2234 | + call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev); | |
| 2235 | + | |
| 2230 | 2236 | return 0; |
| 2231 | 2237 | } |
| 2232 | 2238 | |
| @@ -2291,7 +2297,6 @@ static void __ibmvnic_reset(struct work_struct *work) · 58 unmodified lines | ||
| 2291 | 2297 | |
| 2292 | 2298 | if (!saved_state) { |
| 2293 | 2299 | reset_state = adapter->state; |
| 2294 | − adapter->state = VNIC_RESETTING; | |
| 2295 | 2300 | saved_state = true; |
| 2296 | 2301 | } |
| 2297 | 2302 | spin_unlock_irqrestore(&adapter->state_lock, flags); |
| @@ -2432,6 +2437,12 @@ static void ibmvnic_tx_timeout(struct net_device *dev, unsigned int txqueue) · 134 unmodified lines | ||
| 2432 | 2437 | { |
| 2433 | 2438 | struct ibmvnic_adapter *adapter = netdev_priv(dev); |
| 2434 | 2439 | |
| 2440 | + if (test_bit(0, &adapter->resetting)) { | |
| 2441 | + netdev_err(adapter->netdev, | |
| 2442 | + "Adapter is resetting, skip timeout reset\n"); | |
| 2443 | + return; | |
| 2444 | + } | |
| 2445 | + | |
| 2435 | 2446 | ibmvnic_reset(adapter, VNIC_RESET_TIMEOUT); |
| 2436 | 2447 | } |
| 2437 | 2448 | |
| @@ -2963,6 +2974,9 @@ static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter) · 525 unmodified lines | ||
| 2963 | 2974 | { |
| 2964 | 2975 | int i, rc; |
| 2965 | 2976 | |
| 2977 | + if (!adapter->tx_scrq || !adapter->rx_scrq) | |
| 2978 | + return -EINVAL; | |
| 2979 | + | |
| 2966 | 2980 | for (i = 0; i < adapter->req_tx_queues; i++) { |
| 2967 | 2981 | netdev_dbg(adapter->netdev, "Re-setting tx_scrq[%d]\n", i); |
| 2968 | 2982 | rc = reset_one_sub_crq_queue(adapter, adapter->tx_scrq[i]); |
| @@ -5044,6 +5058,9 @@ static int ibmvnic_reset_crq(struct ibmvnic_adapter *adapter) · 2075 unmodified lines | ||
| 5044 | 5058 | } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); |
| 5045 | 5059 | |
| 5046 | 5060 | /* Clean out the queue */ |
| 5061 | + if (!crq->msgs) | |
| 5062 | + return -EINVAL; | |
| 5063 | + | |
| 5047 | 5064 | memset(crq->msgs, 0, PAGE_SIZE); |
| 5048 | 5065 | crq->cur = 0; |
| 5049 | 5066 | crq->active = false; |
| @@ -5348,7 +5365,7 @@ static int ibmvnic_remove(struct vio_dev *dev) · 298 unmodified lines | ||
| 5348 | 5365 | unsigned long flags; |
| 5349 | 5366 | |
| 5350 | 5367 | spin_lock_irqsave(&adapter->state_lock, flags); |
| 5351 | − if (adapter->state == VNIC_RESETTING) { | |
| 5368 | + if (test_bit(0, &adapter->resetting)) { | |
| 5352 | 5369 | spin_unlock_irqrestore(&adapter->state_lock, flags); |
| 5353 | 5370 | return -EBUSY; |
| 5354 | 5371 | } |
| @@ -943,8 +943,7 @@ enum vnic_state {VNIC_PROBING = 1, · 942 unmodified lines | ||
| 943 | 943 | VNIC_CLOSING, |
| 944 | 944 | VNIC_CLOSED, |
| 945 | 945 | VNIC_REMOVING, |
| 946 | − VNIC_REMOVED, | |
| 947 | − VNIC_RESETTING}; | |
| 946 | + VNIC_REMOVED}; | |
| 948 | 947 | |
| 949 | 948 | enum ibmvnic_reset_reason {VNIC_RESET_FAILOVER = 1, |
| 950 | 949 | VNIC_RESET_MOBILITY, |
| @@ -140,6 +140,7 @@ enum i40e_state_t { · 139 unmodified lines | ||
| 140 | 140 | __I40E_CLIENT_RESET, |
| 141 | 141 | __I40E_VIRTCHNL_OP_PENDING, |
| 142 | 142 | __I40E_RECOVERY_MODE, |
| 143 | + __I40E_VF_RESETS_DISABLED, /* disable resets during i40e_remove */ | |
| 143 | 144 | /* This must be last as it determines the size of the BITMAP */ |
| 144 | 145 | __I40E_STATE_SIZE__, |
| 145 | 146 | }; |
| @@ -4010,8 +4010,16 @@ static irqreturn_t i40e_intr(int irq, void *data) · 4009 unmodified lines | ||
| 4010 | 4010 | } |
| 4011 | 4011 | |
| 4012 | 4012 | if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) { |
| 4013 | − ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK; | |
| 4014 | − set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); | |
| 4013 | + /* disable any further VFLR event notifications */ | |
| 4014 | + if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) { | |
| 4015 | + u32 reg = rd32(hw, I40E_PFINT_ICR0_ENA); | |
| 4016 | + | |
| 4017 | + reg &= ~I40E_PFINT_ICR0_VFLR_MASK; | |
| 4018 | + wr32(hw, I40E_PFINT_ICR0_ENA, reg); | |
| 4019 | + } else { | |
| 4020 | + ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK; | |
| 4021 | + set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); | |
| 4022 | + } | |
| 4015 | 4023 | } |
| 4016 | 4024 | |
| 4017 | 4025 | if (icr0 & I40E_PFINT_ICR0_GRST_MASK) { |
| @@ -15311,6 +15319,11 @@ static void i40e_remove(struct pci_dev *pdev) · 11293 unmodified lines | ||
| 15311 | 15319 | while (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) |
| 15312 | 15320 | usleep_range(1000, 2000); |
| 15313 | 15321 | |
| 15322 | + if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { | |
| 15323 | + set_bit(__I40E_VF_RESETS_DISABLED, pf->state); | |
| 15324 | + i40e_free_vfs(pf); | |
| 15325 | + pf->flags &= ~I40E_FLAG_SRIOV_ENABLED; | |
| 15326 | + } | |
| 15314 | 15327 | /* no more scheduling of any task */ |
| 15315 | 15328 | set_bit(__I40E_SUSPENDED, pf->state); |
| 15316 | 15329 | set_bit(__I40E_DOWN, pf->state); |
| @@ -15337,11 +15350,6 @@ static void i40e_remove(struct pci_dev *pdev) · 20 unmodified lines | ||
| 15337 | 15350 | */ |
| 15338 | 15351 | i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], false); |
| 15339 | 15352 | |
| 15340 | − if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { | |
| 15341 | − i40e_free_vfs(pf); | |
| 15342 | − pf->flags &= ~I40E_FLAG_SRIOV_ENABLED; | |
| 15343 | − } | |
| 15344 | − | |
| 15345 | 15353 | i40e_fdir_teardown(pf); |
| 15346 | 15354 | |
| 15347 | 15355 | /* If there is a switch structure or any orphans, remove them. |
| @@ -1403,7 +1403,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf) · 1402 unmodified lines | ||
| 1403 | 1403 | * @vf: pointer to the VF structure |
| 1404 | 1404 | * @flr: VFLR was issued or not |
| 1405 | 1405 | * |
| 1406 | − * Returns true if the VF is reset, false otherwise. | |
| 1406 | + * Returns true if the VF is in reset, resets successfully, or resets | |
| 1407 | + * are disabled and false otherwise. | |
| 1407 | 1408 | **/ |
| 1408 | 1409 | bool i40e_reset_vf(struct i40e_vf *vf, bool flr) |
| 1409 | 1410 | { |
| @@ -1413,11 +1414,14 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) · 3 unmodified lines | ||
| 1413 | 1414 | u32 reg; |
| 1414 | 1415 | int i; |
| 1415 | 1416 | |
| 1417 | + if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) | |
| 1418 | + return true; | |
| 1419 | + | |
| 1416 | 1420 | /* If the VFs have been disabled, this means something else is |
| 1417 | 1421 | * resetting the VF, so we shouldn't continue. |
| 1418 | 1422 | */ |
| 1419 | 1423 | if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) |
| 1420 | − return false; | |
| 1424 | + return true; | |
| 1421 | 1425 | |
| 1422 | 1426 | i40e_trigger_vf_reset(vf, flr); |
| 1423 | 1427 | |
| @@ -1581,6 +1585,15 @@ void i40e_free_vfs(struct i40e_pf *pf) · 157 unmodified lines | ||
| 1581 | 1585 | |
| 1582 | 1586 | i40e_notify_client_of_vf_enable(pf, 0); |
| 1583 | 1587 | |
| 1588 | + /* Disable IOV before freeing resources. This lets any VF drivers | |
| 1589 | + * running in the host get themselves cleaned up before we yank | |
| 1590 | + * the carpet out from underneath their feet. | |
| 1591 | + */ | |
| 1592 | + if (!pci_vfs_assigned(pf->pdev)) | |
| 1593 | + pci_disable_sriov(pf->pdev); | |
| 1594 | + else | |
| 1595 | + dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n"); | |
| 1596 | + | |
| 1584 | 1597 | /* Amortize wait time by stopping all VFs at the same time */ |
| 1585 | 1598 | for (i = 0; i < pf->num_alloc_vfs; i++) { |
| 1586 | 1599 | if (test_bit(I40E_VF_STATE_INIT, &pf->vf[i].vf_states)) |
| @@ -1596,15 +1609,6 @@ void i40e_free_vfs(struct i40e_pf *pf) · 9 unmodified lines | ||
| 1596 | 1609 | i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[i].lan_vsi_idx]); |
| 1597 | 1610 | } |
| 1598 | 1611 | |
| 1599 | − /* Disable IOV before freeing resources. This lets any VF drivers | |
| 1600 | − * running in the host get themselves cleaned up before we yank | |
| 1601 | − * the carpet out from underneath their feet. | |
| 1602 | − */ | |
| 1603 | − if (!pci_vfs_assigned(pf->pdev)) | |
| 1604 | − pci_disable_sriov(pf->pdev); | |
| 1605 | − else | |
| 1606 | − dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n"); | |
| 1607 | − | |
| 1608 | 1612 | /* free up VF resources */ |
| 1609 | 1613 | tmp = pf->num_alloc_vfs; |
| 1610 | 1614 | pf->num_alloc_vfs = 0; |
| @@ -1193,7 +1193,6 @@ const struct stmmac_ops dwmac4_ops = { · 1192 unmodified lines | ||
| 1193 | 1193 | .pcs_get_adv_lp = dwmac4_get_adv_lp, |
| 1194 | 1194 | .debug = dwmac4_debug, |
| 1195 | 1195 | .set_filter = dwmac4_set_filter, |
| 1196 | − .flex_pps_config = dwmac5_flex_pps_config, | |
| 1197 | 1196 | .set_mac_loopback = dwmac4_set_mac_loopback, |
| 1198 | 1197 | .update_vlan_hash = dwmac4_update_vlan_hash, |
| 1199 | 1198 | .sarc_configure = dwmac4_sarc_configure, |
| @@ -1236,6 +1235,7 @@ const struct stmmac_ops dwmac410_ops = { · 36 unmodified lines | ||
| 1236 | 1235 | .pcs_get_adv_lp = dwmac4_get_adv_lp, |
| 1237 | 1236 | .debug = dwmac4_debug, |
| 1238 | 1237 | .set_filter = dwmac4_set_filter, |
| 1238 | + .flex_pps_config = dwmac5_flex_pps_config, | |
| 1239 | 1239 | .set_mac_loopback = dwmac4_set_mac_loopback, |
| 1240 | 1240 | .update_vlan_hash = dwmac4_update_vlan_hash, |
| 1241 | 1241 | .sarc_configure = dwmac4_sarc_configure, |
| @@ -1921,12 +1921,15 @@ static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from) · 1920 unmodified lines | ||
| 1921 | 1921 | struct tun_file *tfile = file->private_data; |
| 1922 | 1922 | struct tun_struct *tun = tun_get(tfile); |
| 1923 | 1923 | ssize_t result; |
| 1924 | + int noblock = 0; | |
| 1924 | 1925 | |
| 1925 | 1926 | if (!tun) |
| 1926 | 1927 | return -EBADFD; |
| 1927 | 1928 | |
| 1928 | − result = tun_get_user(tun, tfile, NULL, from, | |
| 1929 | − file->f_flags & O_NONBLOCK, false); | |
| 1929 | + if ((file->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NOWAIT)) | |
| 1930 | + noblock = 1; | |
| 1931 | + | |
| 1932 | + result = tun_get_user(tun, tfile, NULL, from, noblock, false); | |
| 1930 | 1933 | |
| 1931 | 1934 | tun_put(tun); |
| 1932 | 1935 | return result; |
| @@ -2137,10 +2140,15 @@ static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to) · 204 unmodified lines | ||
| 2137 | 2140 | struct tun_file *tfile = file->private_data; |
| 2138 | 2141 | struct tun_struct *tun = tun_get(tfile); |
| 2139 | 2142 | ssize_t len = iov_iter_count(to), ret; |
| 2143 | + int noblock = 0; | |
| 2140 | 2144 | |
| 2141 | 2145 | if (!tun) |
| 2142 | 2146 | return -EBADFD; |
| 2143 | − ret = tun_do_read(tun, tfile, to, file->f_flags & O_NONBLOCK, NULL); | |
| 2147 | + | |
| 2148 | + if ((file->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NOWAIT)) | |
| 2149 | + noblock = 1; | |
| 2150 | + | |
| 2151 | + ret = tun_do_read(tun, tfile, to, noblock, NULL); | |
| 2144 | 2152 | ret = min_t(ssize_t, ret, len); |
| 2145 | 2153 | if (ret > 0) |
| 2146 | 2154 | iocb->ki_pos = ret; |
| @@ -59,7 +59,7 @@ · 58 unmodified lines | ||
| 59 | 59 | #define IPHETH_USBINTF_SUBCLASS 253 |
| 60 | 60 | #define IPHETH_USBINTF_PROTO 1 |
| 61 | 61 | |
| 62 | −#define IPHETH_BUF_SIZE 1516 | |
| 62 | +#define IPHETH_BUF_SIZE 1514 | |
| 63 | 63 | #define IPHETH_IP_ALIGN 2 /* padding at front of URB */ |
| 64 | 64 | #define IPHETH_TX_TIMEOUT (5 * HZ) |
| 65 | 65 | |
| @@ -5,10 +5,9 @@ · 4 unmodified lines | ||
| 5 | 5 | * |
| 6 | 6 | * GPL LICENSE SUMMARY |
| 7 | 7 | * |
| 8 | − * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | |
| 9 | 8 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
| 10 | 9 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | − * Copyright(c) 2018 - 2019 Intel Corporation | |
| 10 | + * Copyright(c) 2012-2014, 2018 - 2020 Intel Corporation | |
| 12 | 11 | * |
| 13 | 12 | * This program is free software; you can redistribute it and/or modify |
| 14 | 13 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -28,10 +27,9 @@ · 13 unmodified lines | ||
| 28 | 27 | * |
| 29 | 28 | * BSD LICENSE |
| 30 | 29 | * |
| 31 | − * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | |
| 32 | 30 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
| 33 | 31 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | − * Copyright(c) 2018 - 2019 Intel Corporation | |
| 32 | + * Copyright(c) 2012-2014, 2018 - 2020 Intel Corporation | |
| 35 | 33 | * All rights reserved. |
| 36 | 34 | * |
| 37 | 35 | * Redistribution and use in source and binary forms, with or without |
| @@ -128,7 +126,9 @@ enum iwl_sta_flags { · 90 unmodified lines | ||
| 128 | 126 | STA_FLG_MAX_AGG_SIZE_256K = (5 << STA_FLG_MAX_AGG_SIZE_SHIFT), |
| 129 | 127 | STA_FLG_MAX_AGG_SIZE_512K = (6 << STA_FLG_MAX_AGG_SIZE_SHIFT), |
| 130 | 128 | STA_FLG_MAX_AGG_SIZE_1024K = (7 << STA_FLG_MAX_AGG_SIZE_SHIFT), |
| 131 | − STA_FLG_MAX_AGG_SIZE_MSK = (7 << STA_FLG_MAX_AGG_SIZE_SHIFT), | |
| 129 | + STA_FLG_MAX_AGG_SIZE_2M = (8 << STA_FLG_MAX_AGG_SIZE_SHIFT), | |
| 130 | + STA_FLG_MAX_AGG_SIZE_4M = (9 << STA_FLG_MAX_AGG_SIZE_SHIFT), | |
| 131 | + STA_FLG_MAX_AGG_SIZE_MSK = (0xf << STA_FLG_MAX_AGG_SIZE_SHIFT), | |
| 132 | 132 | |
| 133 | 133 | STA_FLG_AGG_MPDU_DENS_SHIFT = 23, |
| 134 | 134 | STA_FLG_AGG_MPDU_DENS_2US = (4 << STA_FLG_AGG_MPDU_DENS_SHIFT), |
| @@ -8,7 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 9 | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 10 | 10 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 11 | − * Copyright(c) 2018 - 2019 Intel Corporation | |
| 11 | + * Copyright(c) 2018 - 2020 Intel Corporation | |
| 12 | 12 | * |
| 13 | 13 | * This program is free software; you can redistribute it and/or modify |
| 14 | 14 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -31,7 +31,7 @@ · 16 unmodified lines | ||
| 31 | 31 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
| 32 | 32 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
| 33 | 33 | * Copyright(c) 2016 - 2017 Intel Deutschland GmbH |
| 34 | − * Copyright(c) 2018 - 2019 Intel Corporation | |
| 34 | + * Copyright(c) 2018 - 2020 Intel Corporation | |
| 35 | 35 | * All rights reserved. |
| 36 | 36 | * |
| 37 | 37 | * Redistribution and use in source and binary forms, with or without |
| @@ -421,12 +421,14 @@ struct iwl_hs20_roc_res { · 383 unmodified lines | ||
| 421 | 421 | * able to run the GO Negotiation. Will not be fragmented and not |
| 422 | 422 | * repetitive. Valid only on the P2P Device MAC. Only the duration will |
| 423 | 423 | * be taken into account. |
| 424 | + * @SESSION_PROTECT_CONF_MAX_ID: not used | |
| 424 | 425 | */ |
| 425 | 426 | enum iwl_mvm_session_prot_conf_id { |
| 426 | 427 | SESSION_PROTECT_CONF_ASSOC, |
| 427 | 428 | SESSION_PROTECT_CONF_GO_CLIENT_ASSOC, |
| 428 | 429 | SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV, |
| 429 | 430 | SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION, |
| 431 | + SESSION_PROTECT_CONF_MAX_ID, | |
| 430 | 432 | }; /* SESSION_PROTECTION_CONF_ID_E_VER_1 */ |
| 431 | 433 | |
| 432 | 434 | /** |
| @@ -459,7 +461,7 @@ struct iwl_mvm_session_prot_cmd { · 26 unmodified lines | ||
| 459 | 461 | * @mac_id: the mac id for which the session protection started / ended |
| 460 | 462 | * @status: 1 means success, 0 means failure |
| 461 | 463 | * @start: 1 means the session protection started, 0 means it ended |
| 462 | − * @conf_id: the configuration id of the session that started / eneded | |
| 464 | + * @conf_id: see &enum iwl_mvm_session_prot_conf_id | |
| 463 | 465 | * |
| 464 | 466 | * Note that any session protection will always get two notifications: start |
| 465 | 467 | * and end even the firmware could not schedule it. |
| @@ -147,6 +147,16 @@ · 146 unmodified lines | ||
| 147 | 147 | #define CSR_MAC_SHADOW_REG_CTL2 (CSR_BASE + 0x0AC) |
| 148 | 148 | #define CSR_MAC_SHADOW_REG_CTL2_RX_WAKE 0xFFFF |
| 149 | 149 | |
| 150 | +/* LTR control (since IWL_DEVICE_FAMILY_22000) */ | |
| 151 | +#define CSR_LTR_LONG_VAL_AD (CSR_BASE + 0x0D4) | |
| 152 | +#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ 0x80000000 | |
| 153 | +#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE 0x1c000000 | |
| 154 | +#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL 0x03ff0000 | |
| 155 | +#define CSR_LTR_LONG_VAL_AD_SNOOP_REQ 0x00008000 | |
| 156 | +#define CSR_LTR_LONG_VAL_AD_SNOOP_SCALE 0x00001c00 | |
| 157 | +#define CSR_LTR_LONG_VAL_AD_SNOOP_VAL 0x000003ff | |
| 158 | +#define CSR_LTR_LONG_VAL_AD_SCALE_USEC 2 | |
| 159 | + | |
| 150 | 160 | /* GIO Chicken Bits (PCI Express bus link power management) */ |
| 151 | 161 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) |
| 152 | 162 | |
| @@ -3080,7 +3080,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, · 3079 unmodified lines | ||
| 3080 | 3080 | |
| 3081 | 3081 | /* this would be a mac80211 bug ... but don't crash */ |
| 3082 | 3082 | if (WARN_ON_ONCE(!mvmvif->phy_ctxt)) |
| 3083 | − return -EINVAL; | |
| 3083 | + return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) ? 0 : -EINVAL; | |
| 3084 | 3084 | |
| 3085 | 3085 | /* |
| 3086 | 3086 | * If we are in a STA removal flow and in DQA mode: |
| @@ -3127,6 +3127,9 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, · 40 unmodified lines | ||
| 3127 | 3127 | goto out_unlock; |
| 3128 | 3128 | } |
| 3129 | 3129 | |
| 3130 | + if (vif->type == NL80211_IFTYPE_STATION) | |
| 3131 | + vif->bss_conf.he_support = sta->he_cap.has_he; | |
| 3132 | + | |
| 3130 | 3133 | if (sta->tdls && |
| 3131 | 3134 | (vif->p2p || |
| 3132 | 3135 | iwl_mvm_tdls_sta_count(mvm, NULL) == |
| @@ -196,6 +196,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, · 195 unmodified lines | ||
| 196 | 196 | mpdu_dens = sta->ht_cap.ampdu_density; |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | + | |
| 199 | 200 | if (sta->vht_cap.vht_supported) { |
| 200 | 201 | agg_size = sta->vht_cap.cap & |
| 201 | 202 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; |
| @@ -205,6 +206,23 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, · 3 unmodified lines | ||
| 205 | 206 | agg_size = sta->ht_cap.ampdu_factor; |
| 206 | 207 | } |
| 207 | 208 | |
| 209 | + /* D6.0 10.12.2 A-MPDU length limit rules | |
| 210 | + * A STA indicates the maximum length of the A-MPDU preEOF padding | |
| 211 | + * that it can receive in an HE PPDU in the Maximum A-MPDU Length | |
| 212 | + * Exponent field in its HT Capabilities, VHT Capabilities, | |
| 213 | + * and HE 6 GHz Band Capabilities elements (if present) and the | |
| 214 | + * Maximum AMPDU Length Exponent Extension field in its HE | |
| 215 | + * Capabilities element | |
| 216 | + */ | |
| 217 | + if (sta->he_cap.has_he) | |
| 218 | + agg_size += u8_get_bits(sta->he_cap.he_cap_elem.mac_cap_info[3], | |
| 219 | + IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK); | |
| 220 | + | |
| 221 | + /* Limit to max A-MPDU supported by FW */ | |
| 222 | + if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT)) | |
| 223 | + agg_size = (STA_FLG_MAX_AGG_SIZE_4M >> | |
| 224 | + STA_FLG_MAX_AGG_SIZE_SHIFT); | |
| 225 | + | |
| 208 | 226 | add_sta_cmd.station_flags |= |
| 209 | 227 | cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT); |
| 210 | 228 | add_sta_cmd.station_flags |= |
| @@ -641,11 +641,32 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, · 640 unmodified lines | ||
| 641 | 641 | } |
| 642 | 642 | } |
| 643 | 643 | |
| 644 | +static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm, | |
| 645 | + struct iwl_mvm_vif *mvmvif) | |
| 646 | +{ | |
| 647 | + struct iwl_mvm_session_prot_cmd cmd = { | |
| 648 | + .id_and_color = | |
| 649 | + cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | |
| 650 | + mvmvif->color)), | |
| 651 | + .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), | |
| 652 | + .conf_id = cpu_to_le32(mvmvif->time_event_data.id), | |
| 653 | + }; | |
| 654 | + int ret; | |
| 655 | + | |
| 656 | + ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD, | |
| 657 | + MAC_CONF_GROUP, 0), | |
| 658 | + 0, sizeof(cmd), &cmd); | |
| 659 | + if (ret) | |
| 660 | + IWL_ERR(mvm, | |
| 661 | + "Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret); | |
| 662 | +} | |
| 663 | + | |
| 644 | 664 | static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm, |
| 645 | 665 | struct iwl_mvm_time_event_data *te_data, |
| 646 | 666 | u32 *uid) |
| 647 | 667 | { |
| 648 | 668 | u32 id; |
| 669 | + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif); | |
| 649 | 670 | |
| 650 | 671 | /* |
| 651 | 672 | * It is possible that by the time we got to this point the time |
| @@ -663,14 +684,29 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm, · 11 unmodified lines | ||
| 663 | 684 | iwl_mvm_te_clear_data(mvm, te_data); |
| 664 | 685 | spin_unlock_bh(&mvm->time_event_lock); |
| 665 | 686 | |
| 666 | − /* | |
| 667 | − * It is possible that by the time we try to remove it, the time event | |
| 668 | − * has already ended and removed. In such a case there is no need to | |
| 669 | − * send a removal command. | |
| 687 | + /* When session protection is supported, the te_data->id field | |
| 688 | + * is reused to save session protection's configuration. | |
| 670 | 689 | */ |
| 671 | − if (id == TE_MAX) { | |
| 672 | − IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid); | |
| 690 | + if (fw_has_capa(&mvm->fw->ucode_capa, | |
| 691 | + IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) { | |
| 692 | + if (mvmvif && id < SESSION_PROTECT_CONF_MAX_ID) { | |
| 693 | + /* Session protection is still ongoing. Cancel it */ | |
| 694 | + iwl_mvm_cancel_session_protection(mvm, mvmvif); | |
| 695 | + if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { | |
| 696 | + set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); | |
| 697 | + iwl_mvm_roc_finished(mvm); | |
| 698 | + } | |
| 699 | + } | |
| 673 | 700 | return false; |
| 701 | + } else { | |
| 702 | + /* It is possible that by the time we try to remove it, the | |
| 703 | + * time event has already ended and removed. In such a case | |
| 704 | + * there is no need to send a removal command. | |
| 705 | + */ | |
| 706 | + if (id == TE_MAX) { | |
| 707 | + IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid); | |
| 708 | + return false; | |
| 709 | + } | |
| 674 | 710 | } |
| 675 | 711 | |
| 676 | 712 | return true; |
| @@ -771,6 +807,7 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, · 94 unmodified lines | ||
| 771 | 807 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
| 772 | 808 | struct iwl_mvm_session_prot_notif *notif = (void *)pkt->data; |
| 773 | 809 | struct ieee80211_vif *vif; |
| 810 | + struct iwl_mvm_vif *mvmvif; | |
| 774 | 811 | |
| 775 | 812 | rcu_read_lock(); |
| 776 | 813 | vif = iwl_mvm_rcu_dereference_vif_id(mvm, le32_to_cpu(notif->mac_id), |
| @@ -779,9 +816,10 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, · 2 unmodified lines | ||
| 779 | 816 | if (!vif) |
| 780 | 817 | goto out_unlock; |
| 781 | 818 | |
| 819 | + mvmvif = iwl_mvm_vif_from_mac80211(vif); | |
| 820 | + | |
| 782 | 821 | /* The vif is not a P2P_DEVICE, maintain its time_event_data */ |
| 783 | 822 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { |
| 784 | − struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | |
| 785 | 823 | struct iwl_mvm_time_event_data *te_data = |
| 786 | 824 | &mvmvif->time_event_data; |
| 787 | 825 | |
| @@ -816,10 +854,14 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, · 28 unmodified lines | ||
| 816 | 854 | |
| 817 | 855 | if (!le32_to_cpu(notif->status) || !le32_to_cpu(notif->start)) { |
| 818 | 856 | /* End TE, notify mac80211 */ |
| 857 | + mvmvif->time_event_data.id = SESSION_PROTECT_CONF_MAX_ID; | |
| 819 | 858 | ieee80211_remain_on_channel_expired(mvm->hw); |
| 820 | 859 | set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); |
| 821 | 860 | iwl_mvm_roc_finished(mvm); |
| 822 | 861 | } else if (le32_to_cpu(notif->start)) { |
| 862 | + if (WARN_ON(mvmvif->time_event_data.id != | |
| 863 | + le32_to_cpu(notif->conf_id))) | |
| 864 | + goto out_unlock; | |
| 823 | 865 | set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); |
| 824 | 866 | ieee80211_ready_on_channel(mvm->hw); /* Start TE */ |
| 825 | 867 | } |
| @@ -845,20 +887,24 @@ iwl_mvm_start_p2p_roc_session_protection(struct iwl_mvm *mvm, · 19 unmodified lines | ||
| 845 | 887 | |
| 846 | 888 | lockdep_assert_held(&mvm->mutex); |
| 847 | 889 | |
| 890 | + /* The time_event_data.id field is reused to save session | |
| 891 | + * protection's configuration. | |
| 892 | + */ | |
| 848 | 893 | switch (type) { |
| 849 | 894 | case IEEE80211_ROC_TYPE_NORMAL: |
| 850 | − cmd.conf_id = | |
| 851 | − cpu_to_le32(SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV); | |
| 895 | + mvmvif->time_event_data.id = | |
| 896 | + SESSION_PROTECT_CONF_P2P_DEVICE_DISCOV; | |
| 852 | 897 | break; |
| 853 | 898 | case IEEE80211_ROC_TYPE_MGMT_TX: |
| 854 | − cmd.conf_id = | |
| 855 | − cpu_to_le32(SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION); | |
| 899 | + mvmvif->time_event_data.id = | |
| 900 | + SESSION_PROTECT_CONF_P2P_GO_NEGOTIATION; | |
| 856 | 901 | break; |
| 857 | 902 | default: |
| 858 | 903 | WARN_ONCE(1, "Got an invalid ROC type\n"); |
| 859 | 904 | return -EINVAL; |
| 860 | 905 | } |
| 861 | 906 | |
| 907 | + cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id); | |
| 862 | 908 | return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD, |
| 863 | 909 | MAC_CONF_GROUP, 0), |
| 864 | 910 | 0, sizeof(cmd), &cmd); |
| @@ -960,25 +1006,6 @@ void iwl_mvm_cleanup_roc_te(struct iwl_mvm *mvm) · 95 unmodified lines | ||
| 960 | 1006 | __iwl_mvm_remove_time_event(mvm, te_data, &uid); |
| 961 | 1007 | } |
| 962 | 1008 | |
| 963 | −static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm, | |
| 964 | − struct iwl_mvm_vif *mvmvif) | |
| 965 | −{ | |
| 966 | − struct iwl_mvm_session_prot_cmd cmd = { | |
| 967 | − .id_and_color = | |
| 968 | − cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | |
| 969 | − mvmvif->color)), | |
| 970 | − .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), | |
| 971 | − }; | |
| 972 | − int ret; | |
| 973 | − | |
| 974 | − ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SESSION_PROTECTION_CMD, | |
| 975 | − MAC_CONF_GROUP, 0), | |
| 976 | − 0, sizeof(cmd), &cmd); | |
| 977 | − if (ret) | |
| 978 | − IWL_ERR(mvm, | |
| 979 | − "Couldn't send the SESSION_PROTECTION_CMD: %d\n", ret); | |
| 980 | −} | |
| 981 | − | |
| 982 | 1009 | void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
| 983 | 1010 | { |
| 984 | 1011 | struct iwl_mvm_vif *mvmvif; |
| @@ -988,10 +1015,13 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) · 3 unmodified lines | ||
| 988 | 1015 | IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) { |
| 989 | 1016 | mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 990 | 1017 | |
| 991 | − iwl_mvm_cancel_session_protection(mvm, mvmvif); | |
| 992 | − | |
| 993 | − if (vif->type == NL80211_IFTYPE_P2P_DEVICE) | |
| 1018 | + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { | |
| 1019 | + iwl_mvm_cancel_session_protection(mvm, mvmvif); | |
| 994 | 1020 | set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); |
| 1021 | + } else { | |
| 1022 | + iwl_mvm_remove_aux_roc_te(mvm, mvmvif, | |
| 1023 | + &mvmvif->time_event_data); | |
| 1024 | + } | |
| 995 | 1025 | |
| 996 | 1026 | iwl_mvm_roc_finished(mvm); |
| 997 | 1027 | |
| @@ -1126,10 +1156,15 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm, · 128 unmodified lines | ||
| 1126 | 1156 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, |
| 1127 | 1157 | mvmvif->color)), |
| 1128 | 1158 | .action = cpu_to_le32(FW_CTXT_ACTION_ADD), |
| 1129 | − .conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC), | |
| 1130 | 1159 | .duration_tu = cpu_to_le32(MSEC_TO_TU(duration)), |
| 1131 | 1160 | }; |
| 1132 | 1161 | |
| 1162 | + /* The time_event_data.id field is reused to save session | |
| 1163 | + * protection's configuration. | |
| 1164 | + */ | |
| 1165 | + mvmvif->time_event_data.id = SESSION_PROTECT_CONF_ASSOC; | |
| 1166 | + cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id); | |
| 1167 | + | |
| 1133 | 1168 | lockdep_assert_held(&mvm->mutex); |
| 1134 | 1169 | |
| 1135 | 1170 | spin_lock_bh(&mvm->time_event_lock); |
| @@ -252,6 +252,26 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, · 251 unmodified lines | ||
| 252 | 252 | |
| 253 | 253 | iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, |
| 254 | 254 | CSR_AUTO_FUNC_BOOT_ENA); |
| 255 | + | |
| 256 | + if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) { | |
| 257 | + /* | |
| 258 | + * The firmware initializes this again later (to a smaller | |
| 259 | + * value), but for the boot process initialize the LTR to | |
| 260 | + * ~250 usec. | |
| 261 | + */ | |
| 262 | + u32 val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ | | |
| 263 | + u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, | |
| 264 | + CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) | | |
| 265 | + u32_encode_bits(250, | |
| 266 | + CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) | | |
| 267 | + CSR_LTR_LONG_VAL_AD_SNOOP_REQ | | |
| 268 | + u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, | |
| 269 | + CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) | | |
| 270 | + u32_encode_bits(250, CSR_LTR_LONG_VAL_AD_SNOOP_VAL); | |
| 271 | + | |
| 272 | + iwl_write32(trans, CSR_LTR_LONG_VAL_AD, val); | |
| 273 | + } | |
| 274 | + | |
| 255 | 275 | if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) |
| 256 | 276 | iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); |
| 257 | 277 | else |
| @@ -2156,18 +2156,36 @@ static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, · 2155 unmodified lines | ||
| 2156 | 2156 | void *buf, int dwords) |
| 2157 | 2157 | { |
| 2158 | 2158 | unsigned long flags; |
| 2159 | − int offs, ret = 0; | |
| 2159 | + int offs = 0; | |
| 2160 | 2160 | u32 *vals = buf; |
| 2161 | 2161 | |
| 2162 | − if (iwl_trans_grab_nic_access(trans, &flags)) { | |
| 2163 | − iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); | |
| 2164 | − for (offs = 0; offs < dwords; offs++) | |
| 2165 | − vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | |
| 2166 | − iwl_trans_release_nic_access(trans, &flags); | |
| 2167 | − } else { | |
| 2168 | − ret = -EBUSY; | |
| 2162 | + while (offs < dwords) { | |
| 2163 | + /* limit the time we spin here under lock to 1/2s */ | |
| 2164 | + ktime_t timeout = ktime_add_us(ktime_get(), 500 * USEC_PER_MSEC); | |
| 2165 | + | |
| 2166 | + if (iwl_trans_grab_nic_access(trans, &flags)) { | |
| 2167 | + iwl_write32(trans, HBUS_TARG_MEM_RADDR, | |
| 2168 | + addr + 4 * offs); | |
| 2169 | + | |
| 2170 | + while (offs < dwords) { | |
| 2171 | + vals[offs] = iwl_read32(trans, | |
| 2172 | + HBUS_TARG_MEM_RDAT); | |
| 2173 | + offs++; | |
| 2174 | + | |
| 2175 | + /* calling ktime_get is expensive so | |
| 2176 | + * do it once in 128 reads | |
| 2177 | + */ | |
| 2178 | + if (offs % 128 == 0 && ktime_after(ktime_get(), | |
| 2179 | + timeout)) | |
| 2180 | + break; | |
| 2181 | + } | |
| 2182 | + iwl_trans_release_nic_access(trans, &flags); | |
| 2183 | + } else { | |
| 2184 | + return -EBUSY; | |
| 2185 | + } | |
| 2169 | 2186 | } |
| 2170 | − return ret; | |
| 2187 | + | |
| 2188 | + return 0; | |
| 2171 | 2189 | } |
| 2172 | 2190 | |
| 2173 | 2191 | static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, |
| @@ -1482,7 +1482,7 @@ static bool rtw_fw_dump_check_size(struct rtw_dev *rtwdev, · 1481 unmodified lines | ||
| 1482 | 1482 | int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size, |
| 1483 | 1483 | u32 *buffer) |
| 1484 | 1484 | { |
| 1485 | − if (!rtwdev->chip->fw_fifo_addr) { | |
| 1485 | + if (!rtwdev->chip->fw_fifo_addr[0]) { | |
| 1486 | 1486 | rtw_dbg(rtwdev, RTW_DBG_FW, "chip not support dump fw fifo\n"); |
| 1487 | 1487 | return -ENOTSUPP; |
| 1488 | 1488 | } |
| @@ -25,8 +25,8 @@ struct s3fwrn5_i2c_phy { · 24 unmodified lines | ||
| 25 | 25 | struct i2c_client *i2c_dev; |
| 26 | 26 | struct nci_dev *ndev; |
| 27 | 27 | |
| 28 | − unsigned int gpio_en; | |
| 29 | − unsigned int gpio_fw_wake; | |
| 28 | + int gpio_en; | |
| 29 | + int gpio_fw_wake; | |
| 30 | 30 | |
| 31 | 31 | struct mutex mutex; |
| 32 | 32 | |
| @@ -2929,7 +2929,7 @@ int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi, · 2928 unmodified lines | ||
| 2929 | 2929 | static int nvme_get_effects_log(struct nvme_ctrl *ctrl, u8 csi, |
| 2930 | 2930 | struct nvme_effects_log **log) |
| 2931 | 2931 | { |
| 2932 | − struct nvme_cel *cel = xa_load(&ctrl->cels, csi); | |
| 2932 | + struct nvme_effects_log *cel = xa_load(&ctrl->cels, csi); | |
| 2933 | 2933 | int ret; |
| 2934 | 2934 | |
| 2935 | 2935 | if (cel) |
| @@ -2940,16 +2940,15 @@ static int nvme_get_effects_log(struct nvme_ctrl *ctrl, u8 csi, · 4 unmodified lines | ||
| 2940 | 2940 | return -ENOMEM; |
| 2941 | 2941 | |
| 2942 | 2942 | ret = nvme_get_log(ctrl, 0x00, NVME_LOG_CMD_EFFECTS, 0, csi, |
| 2943 | − &cel->log, sizeof(cel->log), 0); | |
| 2943 | + cel, sizeof(*cel), 0); | |
| 2944 | 2944 | if (ret) { |
| 2945 | 2945 | kfree(cel); |
| 2946 | 2946 | return ret; |
| 2947 | 2947 | } |
| 2948 | 2948 | |
| 2949 | − cel->csi = csi; | |
| 2950 | − xa_store(&ctrl->cels, cel->csi, cel, GFP_KERNEL); | |
| 2949 | + xa_store(&ctrl->cels, csi, cel, GFP_KERNEL); | |
| 2951 | 2950 | out: |
| 2952 | − *log = &cel->log; | |
| 2951 | + *log = cel; | |
| 2953 | 2952 | return 0; |
| 2954 | 2953 | } |
| 2955 | 2954 | |
| @@ -4374,6 +4373,19 @@ void nvme_uninit_ctrl(struct nvme_ctrl *ctrl) · 1418 unmodified lines | ||
| 4374 | 4373 | } |
| 4375 | 4374 | EXPORT_SYMBOL_GPL(nvme_uninit_ctrl); |
| 4376 | 4375 | |
| 4376 | +static void nvme_free_cels(struct nvme_ctrl *ctrl) | |
| 4377 | +{ | |
| 4378 | + struct nvme_effects_log *cel; | |
| 4379 | + unsigned long i; | |
| 4380 | + | |
| 4381 | + xa_for_each (&ctrl->cels, i, cel) { | |
| 4382 | + xa_erase(&ctrl->cels, i); | |
| 4383 | + kfree(cel); | |
| 4384 | + } | |
| 4385 | + | |
| 4386 | + xa_destroy(&ctrl->cels); | |
| 4387 | +} | |
| 4388 | + | |
| 4377 | 4389 | static void nvme_free_ctrl(struct device *dev) |
| 4378 | 4390 | { |
| 4379 | 4391 | struct nvme_ctrl *ctrl = |
| @@ -4383,8 +4395,7 @@ static void nvme_free_ctrl(struct device *dev) · 3 unmodified lines | ||
| 4383 | 4395 | if (!subsys || ctrl->instance != subsys->instance) |
| 4384 | 4396 | ida_simple_remove(&nvme_instance_ida, ctrl->instance); |
| 4385 | 4397 | |
| 4386 | − xa_destroy(&ctrl->cels); | |
| 4387 | − | |
| 4398 | + nvme_free_cels(ctrl); | |
| 4388 | 4399 | nvme_mpath_uninit(ctrl); |
| 4389 | 4400 | __free_page(ctrl->discard_page); |
| 4390 | 4401 | |
| @@ -226,12 +226,6 @@ struct nvme_fault_inject { · 225 unmodified lines | ||
| 226 | 226 | #endif |
| 227 | 227 | }; |
| 228 | 228 | |
| 229 | −struct nvme_cel { | |
| 230 | − struct list_head entry; | |
| 231 | − struct nvme_effects_log log; | |
| 232 | − u8 csi; | |
| 233 | −}; | |
| 234 | − | |
| 235 | 229 | struct nvme_ctrl { |
| 236 | 230 | bool comp_seen; |
| 237 | 231 | enum nvme_ctrl_state state; |
| @@ -292,9 +292,21 @@ static void nvme_dbbuf_init(struct nvme_dev *dev, · 291 unmodified lines | ||
| 292 | 292 | nvmeq->dbbuf_cq_ei = &dev->dbbuf_eis[cq_idx(qid, dev->db_stride)]; |
| 293 | 293 | } |
| 294 | 294 | |
| 295 | +static void nvme_dbbuf_free(struct nvme_queue *nvmeq) | |
| 296 | +{ | |
| 297 | + if (!nvmeq->qid) | |
| 298 | + return; | |
| 299 | + | |
| 300 | + nvmeq->dbbuf_sq_db = NULL; | |
| 301 | + nvmeq->dbbuf_cq_db = NULL; | |
| 302 | + nvmeq->dbbuf_sq_ei = NULL; | |
| 303 | + nvmeq->dbbuf_cq_ei = NULL; | |
| 304 | +} | |
| 305 | + | |
| 295 | 306 | static void nvme_dbbuf_set(struct nvme_dev *dev) |
| 296 | 307 | { |
| 297 | 308 | struct nvme_command c; |
| 309 | + unsigned int i; | |
| 298 | 310 | |
| 299 | 311 | if (!dev->dbbuf_dbs) |
| 300 | 312 | return; |
| @@ -308,6 +320,9 @@ static void nvme_dbbuf_set(struct nvme_dev *dev) · 7 unmodified lines | ||
| 308 | 320 | dev_warn(dev->ctrl.device, "unable to set dbbuf\n"); |
| 309 | 321 | /* Free memory and continue on */ |
| 310 | 322 | nvme_dbbuf_dma_free(dev); |
| 323 | + | |
| 324 | + for (i = 1; i <= dev->online_queues; i++) | |
| 325 | + nvme_dbbuf_free(&dev->queues[i]); | |
| 311 | 326 | } |
| 312 | 327 | } |
| 313 | 328 | |
| @@ -111,6 +111,7 @@ static const struct key_entry acer_wmi_keymap[] __initconst = { · 110 unmodified lines | ||
| 111 | 111 | {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ |
| 112 | 112 | {KE_IGNORE, 0x81, {KEY_SLEEP} }, |
| 113 | 113 | {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad Toggle */ |
| 114 | + {KE_IGNORE, 0x84, {KEY_KBDILLUMTOGGLE} }, /* Automatic Keyboard background light toggle */ | |
| 114 | 115 | {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} }, |
| 115 | 116 | {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} }, |
| 116 | 117 | {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} }, |
| @@ -206,6 +206,12 @@ static const struct dmi_system_id dmi_switches_allow_list[] = { · 205 unmodified lines | ||
| 206 | 206 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Stream x360 Convertible PC 11"), |
| 207 | 207 | }, |
| 208 | 208 | }, |
| 209 | + { | |
| 210 | + .matches = { | |
| 211 | + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | |
| 212 | + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"), | |
| 213 | + }, | |
| 214 | + }, | |
| 209 | 215 | {} /* Array terminator */ |
| 210 | 216 | }; |
| 211 | 217 | |
| @@ -3218,7 +3218,14 @@ static int hotkey_init_tablet_mode(void) · 3217 unmodified lines | ||
| 3218 | 3218 | |
| 3219 | 3219 | in_tablet_mode = hotkey_gmms_get_tablet_mode(res, |
| 3220 | 3220 | &has_tablet_mode); |
| 3221 | − if (has_tablet_mode) | |
| 3221 | + /* | |
| 3222 | + * The Yoga 11e series has 2 accelerometers described by a | |
| 3223 | + * BOSC0200 ACPI node. This setup relies on a Windows service | |
| 3224 | + * which calls special ACPI methods on this node to report | |
| 3225 | + * the laptop/tent/tablet mode to the EC. The bmc150 iio driver | |
| 3226 | + * does not support this, so skip the hotkey on these models. | |
| 3227 | + */ | |
| 3228 | + if (has_tablet_mode && !acpi_dev_present("BOSC0200", "1", -1)) | |
| 3222 | 3229 | tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GMMS; |
| 3223 | 3230 | type = "GMMS"; |
| 3224 | 3231 | } else if (acpi_evalf(hkey_handle, &res, "MHKG", "qd")) { |
| @@ -4228,6 +4235,7 @@ static void hotkey_resume(void) · 1003 unmodified lines | ||
| 4228 | 4235 | pr_err("error while attempting to reset the event firmware interface\n"); |
| 4229 | 4236 | |
| 4230 | 4237 | tpacpi_send_radiosw_update(); |
| 4238 | + tpacpi_input_send_tabletsw(); | |
| 4231 | 4239 | hotkey_tablet_mode_notify_change(); |
| 4232 | 4240 | hotkey_wakeup_reason_notify_change(); |
| 4233 | 4241 | hotkey_wakeup_hotunplug_complete_notify_change(); |
| @@ -8776,6 +8784,8 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = { · 4542 unmodified lines | ||
| 8776 | 8784 | TPACPI_Q_LNV3('N', '2', 'C', TPACPI_FAN_2CTL), /* P52 / P72 */ |
| 8777 | 8785 | TPACPI_Q_LNV3('N', '2', 'E', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (1st gen) */ |
| 8778 | 8786 | TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (2nd gen) */ |
| 8787 | + TPACPI_Q_LNV3('N', '2', 'V', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (3nd gen) */ | |
| 8788 | + TPACPI_Q_LNV3('N', '3', '0', TPACPI_FAN_2CTL), /* P15 (1st gen) / P15v (1st gen) */ | |
| 8779 | 8789 | }; |
| 8780 | 8790 | |
| 8781 | 8791 | static int __init fan_init(struct ibm_init_struct *iibm) |
| @@ -9703,6 +9713,7 @@ static const struct tpacpi_quirk battery_quirk_table[] __initconst = { · 921 unmodified lines | ||
| 9703 | 9713 | TPACPI_Q_LNV3('R', '0', 'B', true), /* Thinkpad 11e gen 3 */ |
| 9704 | 9714 | TPACPI_Q_LNV3('R', '0', 'C', true), /* Thinkpad 13 */ |
| 9705 | 9715 | TPACPI_Q_LNV3('R', '0', 'J', true), /* Thinkpad 13 gen 2 */ |
| 9716 | + TPACPI_Q_LNV3('R', '0', 'K', true), /* Thinkpad 11e gen 4 celeron BIOS */ | |
| 9706 | 9717 | }; |
| 9707 | 9718 | |
| 9708 | 9719 | static int __init tpacpi_battery_init(struct ibm_init_struct *ibm) |
| @@ -1478,7 +1478,7 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, · 1477 unmodified lines | ||
| 1478 | 1478 | struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file)); |
| 1479 | 1479 | char *buffer; |
| 1480 | 1480 | char *cmd; |
| 1481 | − int lcd_out, crt_out, tv_out; | |
| 1481 | + int lcd_out = -1, crt_out = -1, tv_out = -1; | |
| 1482 | 1482 | int remain = count; |
| 1483 | 1483 | int value; |
| 1484 | 1484 | int ret; |
| @@ -1510,7 +1510,6 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, · 25 unmodified lines | ||
| 1510 | 1510 | |
| 1511 | 1511 | kfree(cmd); |
| 1512 | 1512 | |
| 1513 | − lcd_out = crt_out = tv_out = -1; | |
| 1514 | 1513 | ret = get_video_status(dev, &video_out); |
| 1515 | 1514 | if (!ret) { |
| 1516 | 1515 | unsigned int new_video_out = video_out; |
| @@ -295,6 +295,21 @@ static const struct ts_dmi_data irbis_tw90_data = { · 294 unmodified lines | ||
| 295 | 295 | .properties = irbis_tw90_props, |
| 296 | 296 | }; |
| 297 | 297 | |
| 298 | +static const struct property_entry irbis_tw118_props[] = { | |
| 299 | + PROPERTY_ENTRY_U32("touchscreen-min-x", 20), | |
| 300 | + PROPERTY_ENTRY_U32("touchscreen-min-y", 30), | |
| 301 | + PROPERTY_ENTRY_U32("touchscreen-size-x", 1960), | |
| 302 | + PROPERTY_ENTRY_U32("touchscreen-size-y", 1510), | |
| 303 | + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-irbis-tw118.fw"), | |
| 304 | + PROPERTY_ENTRY_U32("silead,max-fingers", 10), | |
| 305 | + { } | |
| 306 | +}; | |
| 307 | + | |
| 308 | +static const struct ts_dmi_data irbis_tw118_data = { | |
| 309 | + .acpi_name = "MSSL1680:00", | |
| 310 | + .properties = irbis_tw118_props, | |
| 311 | +}; | |
| 312 | + | |
| 298 | 313 | static const struct property_entry itworks_tw891_props[] = { |
| 299 | 314 | PROPERTY_ENTRY_U32("touchscreen-min-x", 1), |
| 300 | 315 | PROPERTY_ENTRY_U32("touchscreen-min-y", 5), |
| @@ -623,6 +638,23 @@ static const struct ts_dmi_data pov_mobii_wintab_p1006w_v10_data = { · 322 unmodified lines | ||
| 623 | 638 | .properties = pov_mobii_wintab_p1006w_v10_props, |
| 624 | 639 | }; |
| 625 | 640 | |
| 641 | +static const struct property_entry predia_basic_props[] = { | |
| 642 | + PROPERTY_ENTRY_U32("touchscreen-min-x", 3), | |
| 643 | + PROPERTY_ENTRY_U32("touchscreen-min-y", 10), | |
| 644 | + PROPERTY_ENTRY_U32("touchscreen-size-x", 1728), | |
| 645 | + PROPERTY_ENTRY_U32("touchscreen-size-y", 1144), | |
| 646 | + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), | |
| 647 | + PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-predia-basic.fw"), | |
| 648 | + PROPERTY_ENTRY_U32("silead,max-fingers", 10), | |
| 649 | + PROPERTY_ENTRY_BOOL("silead,home-button"), | |
| 650 | + { } | |
| 651 | +}; | |
| 652 | + | |
| 653 | +static const struct ts_dmi_data predia_basic_data = { | |
| 654 | + .acpi_name = "MSSL1680:00", | |
| 655 | + .properties = predia_basic_props, | |
| 656 | +}; | |
| 657 | + | |
| 626 | 658 | static const struct property_entry schneider_sct101ctm_props[] = { |
| 627 | 659 | PROPERTY_ENTRY_U32("touchscreen-size-x", 1715), |
| 628 | 660 | PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), |
| @@ -936,6 +968,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 307 unmodified lines | ||
| 936 | 968 | DMI_MATCH(DMI_PRODUCT_NAME, "TW90"), |
| 937 | 969 | }, |
| 938 | 970 | }, |
| 971 | + { | |
| 972 | + /* Irbis TW118 */ | |
| 973 | + .driver_data = (void *)&irbis_tw118_data, | |
| 974 | + .matches = { | |
| 975 | + DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"), | |
| 976 | + DMI_MATCH(DMI_PRODUCT_NAME, "TW118"), | |
| 977 | + }, | |
| 978 | + }, | |
| 939 | 979 | { |
| 940 | 980 | /* I.T.Works TW891 */ |
| 941 | 981 | .driver_data = (void *)&itworks_tw891_data, |
| @@ -1109,6 +1149,16 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 167 unmodified lines | ||
| 1109 | 1149 | DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"), |
| 1110 | 1150 | }, |
| 1111 | 1151 | }, |
| 1152 | + { | |
| 1153 | + /* Predia Basic tablet) */ | |
| 1154 | + .driver_data = (void *)&predia_basic_data, | |
| 1155 | + .matches = { | |
| 1156 | + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), | |
| 1157 | + DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"), | |
| 1158 | + /* Above matches are too generic, add bios-version match */ | |
| 1159 | + DMI_MATCH(DMI_BIOS_VERSION, "Mx.WT107.KUBNGEA"), | |
| 1160 | + }, | |
| 1161 | + }, | |
| 1112 | 1162 | { |
| 1113 | 1163 | /* Point of View mobii wintab p800w (v2.1) */ |
| 1114 | 1164 | .driver_data = (void *)&pov_mobii_wintab_p800w_v21_data, |
| @@ -103,43 +103,26 @@ static int timespec_to_char_array(struct timespec64 const *ts, · 102 unmodified lines | ||
| 103 | 103 | return 0; |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | −static int idtcm_strverscmp(const char *ver1, const char *ver2) | |
| 106 | +static int idtcm_strverscmp(const char *version1, const char *version2) | |
| 107 | 107 | { |
| 108 | − u8 num1; | |
| 109 | − u8 num2; | |
| 110 | − int result = 0; | |
| 111 | − | |
| 112 | − /* loop through each level of the version string */ | |
| 113 | − while (result == 0) { | |
| 114 | − /* extract leading version numbers */ | |
| 115 | − if (kstrtou8(ver1, 10, &num1) < 0) | |
| 116 | − return -1; | |
| 108 | + u8 ver1[3], ver2[3]; | |
| 109 | + int i; | |
| 117 | 110 | |
| 118 | − if (kstrtou8(ver2, 10, &num2) < 0) | |
| 119 | − return -1; | |
| 111 | + if (sscanf(version1, "%hhu.%hhu.%hhu", | |
| 112 | + &ver1[0], &ver1[1], &ver1[2]) != 3) | |
| 113 | + return -1; | |
| 114 | + if (sscanf(version2, "%hhu.%hhu.%hhu", | |
| 115 | + &ver2[0], &ver2[1], &ver2[2]) != 3) | |
| 116 | + return -1; | |
| 120 | 117 | |
| 121 | − /* if numbers differ, then set the result */ | |
| 122 | − if (num1 < num2) | |
| 123 | − result = -1; | |
| 124 | − else if (num1 > num2) | |
| 125 | − result = 1; | |
| 126 | − else { | |
| 127 | − /* if numbers are the same, go to next level */ | |
| 128 | − ver1 = strchr(ver1, '.'); | |
| 129 | − ver2 = strchr(ver2, '.'); | |
| 130 | − if (!ver1 && !ver2) | |
| 131 | − break; | |
| 132 | − else if (!ver1) | |
| 133 | − result = -1; | |
| 134 | − else if (!ver2) | |
| 135 | − result = 1; | |
| 136 | − else { | |
| 137 | − ver1++; | |
| 138 | − ver2++; | |
| 139 | − } | |
| 140 | − } | |
| 118 | + for (i = 0; i < 3; i++) { | |
| 119 | + if (ver1[i] > ver2[i]) | |
| 120 | + return 1; | |
| 121 | + if (ver1[i] < ver2[i]) | |
| 122 | + return -1; | |
| 141 | 123 | } |
| 142 | − return result; | |
| 124 | + | |
| 125 | + return 0; | |
| 143 | 126 | } |
| 144 | 127 | |
| 145 | 128 | static int idtcm_xfer_read(struct idtcm *idtcm, |
| @@ -2980,6 +2980,12 @@ static int _dasd_requeue_request(struct dasd_ccw_req *cqr) · 2979 unmodified lines | ||
| 2980 | 2980 | |
| 2981 | 2981 | if (!block) |
| 2982 | 2982 | return -EINVAL; |
| 2983 | + /* | |
| 2984 | + * If the request is an ERP request there is nothing to requeue. | |
| 2985 | + * This will be done with the remaining original request. | |
| 2986 | + */ | |
| 2987 | + if (cqr->refers) | |
| 2988 | + return 0; | |
| 2983 | 2989 | spin_lock_irq(&cqr->dq->lock); |
| 2984 | 2990 | req = (struct request *) cqr->callback_data; |
| 2985 | 2991 | blk_mq_requeue_request(req, false); |
| @@ -417,10 +417,13 @@ enum qeth_qdio_out_buffer_state { · 416 unmodified lines | ||
| 417 | 417 | QETH_QDIO_BUF_EMPTY, |
| 418 | 418 | /* Filled by driver; owned by hardware in order to be sent. */ |
| 419 | 419 | QETH_QDIO_BUF_PRIMED, |
| 420 | − /* Identified to be pending in TPQ. */ | |
| 420 | + /* Discovered by the TX completion code: */ | |
| 421 | 421 | QETH_QDIO_BUF_PENDING, |
| 422 | − /* Found in completion queue. */ | |
| 423 | − QETH_QDIO_BUF_IN_CQ, | |
| 422 | + /* Finished by the TX completion code: */ | |
| 423 | + QETH_QDIO_BUF_NEED_QAOB, | |
| 424 | + /* Received QAOB notification on CQ: */ | |
| 425 | + QETH_QDIO_BUF_QAOB_OK, | |
| 426 | + QETH_QDIO_BUF_QAOB_ERROR, | |
| 424 | 427 | /* Handled via transfer pending / completion queue. */ |
| 425 | 428 | QETH_QDIO_BUF_HANDLED_DELAYED, |
| 426 | 429 | }; |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | #include <net/iucv/af_iucv.h> |
| 35 | 35 | #include <net/dsfield.h> |
| 36 | +#include <net/sock.h> | |
| 36 | 37 | |
| 37 | 38 | #include <asm/ebcdic.h> |
| 38 | 39 | #include <asm/chpid.h> |
| @@ -499,17 +500,12 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx, · 460 unmodified lines | ||
| 499 | 500 | |
| 500 | 501 | } |
| 501 | 502 | } |
| 502 | − if (forced_cleanup && (atomic_read(&(q->bufs[bidx]->state)) == | |
| 503 | − QETH_QDIO_BUF_HANDLED_DELAYED)) { | |
| 504 | − /* for recovery situations */ | |
| 505 | − qeth_init_qdio_out_buf(q, bidx); | |
| 506 | − QETH_CARD_TEXT(q->card, 2, "clprecov"); | |
| 507 | − } | |
| 508 | 503 | } |
| 509 | 504 | |
| 510 | 505 | static void qeth_qdio_handle_aob(struct qeth_card *card, |
| 511 | 506 | unsigned long phys_aob_addr) |
| 512 | 507 | { |
| 508 | + enum qeth_qdio_out_buffer_state new_state = QETH_QDIO_BUF_QAOB_OK; | |
| 513 | 509 | struct qaob *aob; |
| 514 | 510 | struct qeth_qdio_out_buffer *buffer; |
| 515 | 511 | enum iucv_tx_notify notification; |
| @@ -521,22 +517,6 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, · 5 unmodified lines | ||
| 521 | 517 | buffer = (struct qeth_qdio_out_buffer *) aob->user1; |
| 522 | 518 | QETH_CARD_TEXT_(card, 5, "%lx", aob->user1); |
| 523 | 519 | |
| 524 | − if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED, | |
| 525 | − QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) { | |
| 526 | − notification = TX_NOTIFY_OK; | |
| 527 | − } else { | |
| 528 | − WARN_ON_ONCE(atomic_read(&buffer->state) != | |
| 529 | − QETH_QDIO_BUF_PENDING); | |
| 530 | − atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ); | |
| 531 | − notification = TX_NOTIFY_DELAYED_OK; | |
| 532 | − } | |
| 533 | − | |
| 534 | − if (aob->aorc != 0) { | |
| 535 | − QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc); | |
| 536 | − notification = qeth_compute_cq_notification(aob->aorc, 1); | |
| 537 | − } | |
| 538 | − qeth_notify_skbs(buffer->q, buffer, notification); | |
| 539 | − | |
| 540 | 520 | /* Free dangling allocations. The attached skbs are handled by |
| 541 | 521 | * qeth_cleanup_handled_pending(). |
| 542 | 522 | */ |
| @@ -548,7 +528,33 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, · 5 unmodified lines | ||
| 548 | 528 | if (data && buffer->is_header[i]) |
| 549 | 529 | kmem_cache_free(qeth_core_header_cache, data); |
| 550 | 530 | } |
| 551 | − atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); | |
| 531 | + | |
| 532 | + if (aob->aorc) { | |
| 533 | + QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc); | |
| 534 | + new_state = QETH_QDIO_BUF_QAOB_ERROR; | |
| 535 | + } | |
| 536 | + | |
| 537 | + switch (atomic_xchg(&buffer->state, new_state)) { | |
| 538 | + case QETH_QDIO_BUF_PRIMED: | |
| 539 | + /* Faster than TX completion code. */ | |
| 540 | + notification = qeth_compute_cq_notification(aob->aorc, 0); | |
| 541 | + qeth_notify_skbs(buffer->q, buffer, notification); | |
| 542 | + atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); | |
| 543 | + break; | |
| 544 | + case QETH_QDIO_BUF_PENDING: | |
| 545 | + /* TX completion code is active and will handle the async | |
| 546 | + * completion for us. | |
| 547 | + */ | |
| 548 | + break; | |
| 549 | + case QETH_QDIO_BUF_NEED_QAOB: | |
| 550 | + /* TX completion code is already finished. */ | |
| 551 | + notification = qeth_compute_cq_notification(aob->aorc, 1); | |
| 552 | + qeth_notify_skbs(buffer->q, buffer, notification); | |
| 553 | + atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); | |
| 554 | + break; | |
| 555 | + default: | |
| 556 | + WARN_ON_ONCE(1); | |
| 557 | + } | |
| 552 | 558 | |
| 553 | 559 | qdio_release_aob(aob); |
| 554 | 560 | } |
| @@ -1405,7 +1411,7 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *q, · 850 unmodified lines | ||
| 1405 | 1411 | skb_queue_walk(&buf->skb_list, skb) { |
| 1406 | 1412 | QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification); |
| 1407 | 1413 | QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb); |
| 1408 | − if (skb->protocol == htons(ETH_P_AF_IUCV) && skb->sk) | |
| 1414 | + if (skb->sk && skb->sk->sk_family == PF_IUCV) | |
| 1409 | 1415 | iucv_sk(skb->sk)->sk_txnotify(skb, notification); |
| 1410 | 1416 | } |
| 1411 | 1417 | } |
| @@ -1416,9 +1422,6 @@ static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error, · 4 unmodified lines | ||
| 1416 | 1422 | struct qeth_qdio_out_q *queue = buf->q; |
| 1417 | 1423 | struct sk_buff *skb; |
| 1418 | 1424 | |
| 1419 | − /* release may never happen from within CQ tasklet scope */ | |
| 1420 | − WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ); | |
| 1421 | − | |
| 1422 | 1425 | if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) |
| 1423 | 1426 | qeth_notify_skbs(queue, buf, TX_NOTIFY_GENERALERROR); |
| 1424 | 1427 | |
| @@ -6078,9 +6081,32 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue, · 4653 unmodified lines | ||
| 6078 | 6081 | |
| 6079 | 6082 | if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED, |
| 6080 | 6083 | QETH_QDIO_BUF_PENDING) == |
| 6081 | − QETH_QDIO_BUF_PRIMED) | |
| 6084 | + QETH_QDIO_BUF_PRIMED) { | |
| 6082 | 6085 | qeth_notify_skbs(queue, buffer, TX_NOTIFY_PENDING); |
| 6083 | 6086 | |
| 6087 | + /* Handle race with qeth_qdio_handle_aob(): */ | |
| 6088 | + switch (atomic_xchg(&buffer->state, | |
| 6089 | + QETH_QDIO_BUF_NEED_QAOB)) { | |
| 6090 | + case QETH_QDIO_BUF_PENDING: | |
| 6091 | + /* No concurrent QAOB notification. */ | |
| 6092 | + break; | |
| 6093 | + case QETH_QDIO_BUF_QAOB_OK: | |
| 6094 | + qeth_notify_skbs(queue, buffer, | |
| 6095 | + TX_NOTIFY_DELAYED_OK); | |
| 6096 | + atomic_set(&buffer->state, | |
| 6097 | + QETH_QDIO_BUF_HANDLED_DELAYED); | |
| 6098 | + break; | |
| 6099 | + case QETH_QDIO_BUF_QAOB_ERROR: | |
| 6100 | + qeth_notify_skbs(queue, buffer, | |
| 6101 | + TX_NOTIFY_DELAYED_GENERALERROR); | |
| 6102 | + atomic_set(&buffer->state, | |
| 6103 | + QETH_QDIO_BUF_HANDLED_DELAYED); | |
| 6104 | + break; | |
| 6105 | + default: | |
| 6106 | + WARN_ON_ONCE(1); | |
| 6107 | + } | |
| 6108 | + } | |
| 6109 | + | |
| 6084 | 6110 | QETH_CARD_TEXT_(card, 5, "pel%u", bidx); |
| 6085 | 6111 | |
| 6086 | 6112 | /* prepare the queue slot for re-use: */ |
| @@ -983,32 +983,19 @@ static void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card) · 982 unmodified lines | ||
| 983 | 983 | * change notification' and thus can support the learning_sync bridgeport |
| 984 | 984 | * attribute |
| 985 | 985 | * @card: qeth_card structure pointer |
| 986 | − * | |
| 987 | − * This is a destructive test and must be called before dev2br or | |
| 988 | − * bridgeport address notification is enabled! | |
| 989 | 986 | */ |
| 990 | 987 | static void qeth_l2_detect_dev2br_support(struct qeth_card *card) |
| 991 | 988 | { |
| 992 | 989 | struct qeth_priv *priv = netdev_priv(card->dev); |
| 993 | 990 | bool dev2br_supported; |
| 994 | − int rc; | |
| 995 | 991 | |
| 996 | 992 | QETH_CARD_TEXT(card, 2, "d2brsup"); |
| 997 | 993 | if (!IS_IQD(card)) |
| 998 | 994 | return; |
| 999 | 995 | |
| 1000 | 996 | /* dev2br requires valid cssid,iid,chid */ |
| 1001 | − if (!card->info.ids_valid) { | |
| 1002 | − dev2br_supported = false; | |
| 1003 | − } else if (css_general_characteristics.enarf) { | |
| 1004 | − dev2br_supported = true; | |
| 1005 | − } else { | |
| 1006 | − /* Old machines don't have the feature bit: | |
| 1007 | − * Probe by testing whether a disable succeeds | |
| 1008 | − */ | |
| 1009 | − rc = qeth_l2_pnso(card, PNSO_OC_NET_ADDR_INFO, 0, NULL, NULL); | |
| 1010 | − dev2br_supported = !rc; | |
| 1011 | − } | |
| 997 | + dev2br_supported = card->info.ids_valid && | |
| 998 | + css_general_characteristics.enarf; | |
| 1012 | 999 | QETH_CARD_TEXT_(card, 2, "D2Bsup%02x", dev2br_supported); |
| 1013 | 1000 | |
| 1014 | 1001 | if (dev2br_supported) |
| @@ -2233,7 +2220,6 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok) · 1218 unmodified lines | ||
| 2233 | 2220 | struct net_device *dev = card->dev; |
| 2234 | 2221 | int rc = 0; |
| 2235 | 2222 | |
| 2236 | − /* query before bridgeport_notification may be enabled */ | |
| 2237 | 2223 | qeth_l2_detect_dev2br_support(card); |
| 2238 | 2224 | |
| 2239 | 2225 | mutex_lock(&card->sbp_lock); |
| @@ -533,8 +533,8 @@ static void iscsi_complete_task(struct iscsi_task *task, int state) · 532 unmodified lines | ||
| 533 | 533 | if (conn->task == task) |
| 534 | 534 | conn->task = NULL; |
| 535 | 535 | |
| 536 | − if (conn->ping_task == task) | |
| 537 | − conn->ping_task = NULL; | |
| 536 | + if (READ_ONCE(conn->ping_task) == task) | |
| 537 | + WRITE_ONCE(conn->ping_task, NULL); | |
| 538 | 538 | |
| 539 | 539 | /* release get from queueing */ |
| 540 | 540 | __iscsi_put_task(task); |
| @@ -738,6 +738,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, · 197 unmodified lines | ||
| 738 | 738 | task->conn->session->age); |
| 739 | 739 | } |
| 740 | 740 | |
| 741 | + if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK)) | |
| 742 | + WRITE_ONCE(conn->ping_task, task); | |
| 743 | + | |
| 741 | 744 | if (!ihost->workq) { |
| 742 | 745 | if (iscsi_prep_mgmt_task(conn, task)) |
| 743 | 746 | goto free_task; |
| @@ -941,8 +944,11 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) · 197 unmodified lines | ||
| 941 | 944 | struct iscsi_nopout hdr; |
| 942 | 945 | struct iscsi_task *task; |
| 943 | 946 | |
| 944 | − if (!rhdr && conn->ping_task) | |
| 945 | − return -EINVAL; | |
| 947 | + if (!rhdr) { | |
| 948 | + if (READ_ONCE(conn->ping_task)) | |
| 949 | + return -EINVAL; | |
| 950 | + WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK); | |
| 951 | + } | |
| 946 | 952 | |
| 947 | 953 | memset(&hdr, 0, sizeof(struct iscsi_nopout)); |
| 948 | 954 | hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; |
| @@ -957,11 +963,12 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) · 8 unmodified lines | ||
| 957 | 963 | |
| 958 | 964 | task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); |
| 959 | 965 | if (!task) { |
| 966 | + if (!rhdr) | |
| 967 | + WRITE_ONCE(conn->ping_task, NULL); | |
| 960 | 968 | iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); |
| 961 | 969 | return -EIO; |
| 962 | 970 | } else if (!rhdr) { |
| 963 | 971 | /* only track our nops */ |
| 964 | − conn->ping_task = task; | |
| 965 | 972 | conn->last_ping = jiffies; |
| 966 | 973 | } |
| 967 | 974 | |
| @@ -984,7 +991,7 @@ static int iscsi_nop_out_rsp(struct iscsi_task *task, · 16 unmodified lines | ||
| 984 | 991 | struct iscsi_conn *conn = task->conn; |
| 985 | 992 | int rc = 0; |
| 986 | 993 | |
| 987 | − if (conn->ping_task != task) { | |
| 994 | + if (READ_ONCE(conn->ping_task) != task) { | |
| 988 | 995 | /* |
| 989 | 996 | * If this is not in response to one of our |
| 990 | 997 | * nops then it must be from userspace. |
| @@ -1923,7 +1930,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn) · 932 unmodified lines | ||
| 1923 | 1930 | */ |
| 1924 | 1931 | static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) |
| 1925 | 1932 | { |
| 1926 | − if (conn->ping_task && | |
| 1933 | + if (READ_ONCE(conn->ping_task) && | |
| 1927 | 1934 | time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + |
| 1928 | 1935 | (conn->ping_timeout * HZ), jiffies)) |
| 1929 | 1936 | return 1; |
| @@ -2058,7 +2065,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) · 128 unmodified lines | ||
| 2058 | 2065 | * Checking the transport already or nop from a cmd timeout still |
| 2059 | 2066 | * running |
| 2060 | 2067 | */ |
| 2061 | − if (conn->ping_task) { | |
| 2068 | + if (READ_ONCE(conn->ping_task)) { | |
| 2062 | 2069 | task->have_checked_conn = true; |
| 2063 | 2070 | rc = BLK_EH_RESET_TIMER; |
| 2064 | 2071 | goto done; |
| @@ -1294,8 +1294,15 @@ static int ufshcd_devfreq_target(struct device *dev, · 1293 unmodified lines | ||
| 1294 | 1294 | } |
| 1295 | 1295 | spin_unlock_irqrestore(hba->host->host_lock, irq_flags); |
| 1296 | 1296 | |
| 1297 | + pm_runtime_get_noresume(hba->dev); | |
| 1298 | + if (!pm_runtime_active(hba->dev)) { | |
| 1299 | + pm_runtime_put_noidle(hba->dev); | |
| 1300 | + ret = -EAGAIN; | |
| 1301 | + goto out; | |
| 1302 | + } | |
| 1297 | 1303 | start = ktime_get(); |
| 1298 | 1304 | ret = ufshcd_devfreq_scale(hba, scale_up); |
| 1305 | + pm_runtime_put(hba->dev); | |
| 1299 | 1306 | |
| 1300 | 1307 | trace_ufshcd_profile_clk_scaling(dev_name(hba->dev), |
| 1301 | 1308 | (scale_up ? "up" : "down"), |
| @@ -3192,13 +3199,19 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, · 1890 unmodified lines | ||
| 3192 | 3199 | /* Get the length of descriptor */ |
| 3193 | 3200 | ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len); |
| 3194 | 3201 | if (!buff_len) { |
| 3195 | − dev_err(hba->dev, "%s: Failed to get desc length", __func__); | |
| 3202 | + dev_err(hba->dev, "%s: Failed to get desc length\n", __func__); | |
| 3203 | + return -EINVAL; | |
| 3204 | + } | |
| 3205 | + | |
| 3206 | + if (param_offset >= buff_len) { | |
| 3207 | + dev_err(hba->dev, "%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n", | |
| 3208 | + __func__, param_offset, desc_id, buff_len); | |
| 3196 | 3209 | return -EINVAL; |
| 3197 | 3210 | } |
| 3198 | 3211 | |
| 3199 | 3212 | /* Check whether we need temp memory */ |
| 3200 | 3213 | if (param_offset != 0 || param_size < buff_len) { |
| 3201 | − desc_buf = kmalloc(buff_len, GFP_KERNEL); | |
| 3214 | + desc_buf = kzalloc(buff_len, GFP_KERNEL); | |
| 3202 | 3215 | if (!desc_buf) |
| 3203 | 3216 | return -ENOMEM; |
| 3204 | 3217 | } else { |
| @@ -3212,14 +3225,14 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, · 7 unmodified lines | ||
| 3212 | 3225 | desc_buf, &buff_len); |
| 3213 | 3226 | |
| 3214 | 3227 | if (ret) { |
| 3215 | − dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d", | |
| 3228 | + dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n", | |
| 3216 | 3229 | __func__, desc_id, desc_index, param_offset, ret); |
| 3217 | 3230 | goto out; |
| 3218 | 3231 | } |
| 3219 | 3232 | |
| 3220 | 3233 | /* Sanity check */ |
| 3221 | 3234 | if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) { |
| 3222 | − dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header", | |
| 3235 | + dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n", | |
| 3223 | 3236 | __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]); |
| 3224 | 3237 | ret = -EINVAL; |
| 3225 | 3238 | goto out; |
| @@ -3229,12 +3242,12 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, · 3 unmodified lines | ||
| 3229 | 3242 | buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET]; |
| 3230 | 3243 | ufshcd_update_desc_length(hba, desc_id, desc_index, buff_len); |
| 3231 | 3244 | |
| 3232 | − /* Check wherher we will not copy more data, than available */ | |
| 3233 | − if (is_kmalloc && (param_offset + param_size) > buff_len) | |
| 3234 | − param_size = buff_len - param_offset; | |
| 3235 | − | |
| 3236 | − if (is_kmalloc) | |
| 3245 | + if (is_kmalloc) { | |
| 3246 | + /* Make sure we don't copy more data than available */ | |
| 3247 | + if (param_offset + param_size > buff_len) | |
| 3248 | + param_size = buff_len - param_offset; | |
| 3237 | 3249 | memcpy(param_read_buf, &desc_buf[param_offset], param_size); |
| 3250 | + } | |
| 3238 | 3251 | out: |
| 3239 | 3252 | if (is_kmalloc) |
| 3240 | 3253 | kfree(desc_buf); |
| @@ -8900,11 +8913,7 @@ int ufshcd_shutdown(struct ufs_hba *hba) · 5659 unmodified lines | ||
| 8900 | 8913 | if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba)) |
| 8901 | 8914 | goto out; |
| 8902 | 8915 | |
| 8903 | − if (pm_runtime_suspended(hba->dev)) { | |
| 8904 | − ret = ufshcd_runtime_resume(hba); | |
| 8905 | − if (ret) | |
| 8906 | − goto out; | |
| 8907 | − } | |
| 8916 | + pm_runtime_get_sync(hba->dev); | |
| 8908 | 8917 | |
| 8909 | 8918 | ret = ufshcd_suspend(hba, UFS_SHUTDOWN_PM); |
| 8910 | 8919 | out: |
| @@ -95,7 +95,6 @@ static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) · 94 unmodified lines | ||
| 95 | 95 | { |
| 96 | 96 | int error; |
| 97 | 97 | struct fsl_mc_device_irq *irq; |
| 98 | − cpumask_t mask; | |
| 99 | 98 | |
| 100 | 99 | irq = dpio_dev->irqs[0]; |
| 101 | 100 | error = devm_request_irq(&dpio_dev->dev, |
| @@ -112,9 +111,7 @@ static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) · 10 unmodified lines | ||
| 112 | 111 | } |
| 113 | 112 | |
| 114 | 113 | /* set the affinity hint */ |
| 115 | − cpumask_clear(&mask); | |
| 116 | − cpumask_set_cpu(cpu, &mask); | |
| 117 | − if (irq_set_affinity_hint(irq->msi_desc->irq, &mask)) | |
| 114 | + if (irq_set_affinity_hint(irq->msi_desc->irq, cpumask_of(cpu))) | |
| 118 | 115 | dev_err(&dpio_dev->dev, |
| 119 | 116 | "irq_set_affinity failed irq %d cpu %d\n", |
| 120 | 117 | irq->msi_desc->irq, cpu); |
| @@ -875,7 +875,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) · 874 unmodified lines | ||
| 875 | 875 | master->set_cs = dw_spi_set_cs; |
| 876 | 876 | master->transfer_one = dw_spi_transfer_one; |
| 877 | 877 | master->handle_err = dw_spi_handle_err; |
| 878 | − master->mem_ops = &dws->mem_ops; | |
| 878 | + if (dws->mem_ops.exec_op) | |
| 879 | + master->mem_ops = &dws->mem_ops; | |
| 879 | 880 | master->max_speed_hz = dws->max_freq; |
| 880 | 881 | master->dev.of_node = dev->of_node; |
| 881 | 882 | master->dev.fwnode = dev->fwnode; |
| @@ -1686,6 +1686,7 @@ static int spi_imx_probe(struct platform_device *pdev) · 1685 unmodified lines | ||
| 1686 | 1686 | |
| 1687 | 1687 | pm_runtime_set_autosuspend_delay(spi_imx->dev, MXC_RPM_TIMEOUT); |
| 1688 | 1688 | pm_runtime_use_autosuspend(spi_imx->dev); |
| 1689 | + pm_runtime_get_noresume(spi_imx->dev); | |
| 1689 | 1690 | pm_runtime_set_active(spi_imx->dev); |
| 1690 | 1691 | pm_runtime_enable(spi_imx->dev); |
| 1691 | 1692 | |
| @@ -1001,6 +1001,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) · 1000 unmodified lines | ||
| 1001 | 1001 | struct resource *res; |
| 1002 | 1002 | struct nxp_fspi *f; |
| 1003 | 1003 | int ret; |
| 1004 | + u32 reg; | |
| 1004 | 1005 | |
| 1005 | 1006 | ctlr = spi_alloc_master(&pdev->dev, sizeof(*f)); |
| 1006 | 1007 | if (!ctlr) |
| @@ -1032,6 +1033,12 @@ static int nxp_fspi_probe(struct platform_device *pdev) · 25 unmodified lines | ||
| 1032 | 1033 | goto err_put_ctrl; |
| 1033 | 1034 | } |
| 1034 | 1035 | |
| 1036 | + /* Clear potential interrupts */ | |
| 1037 | + reg = fspi_readl(f, f->iobase + FSPI_INTR); | |
| 1038 | + if (reg) | |
| 1039 | + fspi_writel(f, reg, f->iobase + FSPI_INTR); | |
| 1040 | + | |
| 1041 | + | |
| 1035 | 1042 | /* find the resources - controller memory mapped space */ |
| 1036 | 1043 | if (is_acpi_node(f->dev->fwnode)) |
| 1037 | 1044 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
| @@ -3372,12 +3372,15 @@ int spi_setup(struct spi_device *spi) · 3371 unmodified lines | ||
| 3372 | 3372 | if (!spi->max_speed_hz) |
| 3373 | 3373 | spi->max_speed_hz = spi->controller->max_speed_hz; |
| 3374 | 3374 | |
| 3375 | + mutex_lock(&spi->controller->io_mutex); | |
| 3376 | + | |
| 3375 | 3377 | if (spi->controller->setup) |
| 3376 | 3378 | status = spi->controller->setup(spi); |
| 3377 | 3379 | |
| 3378 | 3380 | if (spi->controller->auto_runtime_pm && spi->controller->set_cs) { |
| 3379 | 3381 | status = pm_runtime_get_sync(spi->controller->dev.parent); |
| 3380 | 3382 | if (status < 0) { |
| 3383 | + mutex_unlock(&spi->controller->io_mutex); | |
| 3381 | 3384 | pm_runtime_put_noidle(spi->controller->dev.parent); |
| 3382 | 3385 | dev_err(&spi->controller->dev, "Failed to power device: %d\n", |
| 3383 | 3386 | status); |
| @@ -3399,6 +3402,8 @@ int spi_setup(struct spi_device *spi) · 15 unmodified lines | ||
| 3399 | 3402 | spi_set_cs(spi, false); |
| 3400 | 3403 | } |
| 3401 | 3404 | |
| 3405 | + mutex_unlock(&spi->controller->io_mutex); | |
| 3406 | + | |
| 3402 | 3407 | if (spi->rt && !spi->controller->rt) { |
| 3403 | 3408 | spi->controller->rt = true; |
| 3404 | 3409 | spi_set_thread_rt(spi->controller); |
| @@ -446,7 +446,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx, · 445 unmodified lines | ||
| 446 | 446 | reg |= (pps->second_chroma_qp_index_offset & 0x3f) << 16; |
| 447 | 447 | reg |= (pps->chroma_qp_index_offset & 0x3f) << 8; |
| 448 | 448 | reg |= (pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta) & 0x3f; |
| 449 | − if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT) | |
| 449 | + if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) | |
| 450 | 450 | reg |= VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT; |
| 451 | 451 | cedrus_write(dev, VE_H264_SHS_QP, reg); |
| 452 | 452 | |
| @@ -653,16 +653,11 @@ static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie) · 652 unmodified lines | ||
| 653 | 653 | return 0; |
| 654 | 654 | } |
| 655 | 655 | |
| 656 | −static int mt7621_pcie_request_resources(struct mt7621_pcie *pcie, | |
| 657 | − struct list_head *res) | |
| 656 | +static void mt7621_pcie_add_resources(struct mt7621_pcie *pcie, | |
| 657 | + struct list_head *res) | |
| 658 | 658 | { |
| 659 | − struct device *dev = pcie->dev; | |
| 660 | − | |
| 661 | 659 | pci_add_resource_offset(res, &pcie->io, pcie->offset.io); |
| 662 | 660 | pci_add_resource_offset(res, &pcie->mem, pcie->offset.mem); |
| 663 | − pci_add_resource(res, &pcie->busn); | |
| 664 | − | |
| 665 | − return devm_request_pci_bus_resources(dev, res); | |
| 666 | 661 | } |
| 667 | 662 | |
| 668 | 663 | static int mt7621_pcie_register_host(struct pci_host_bridge *host, |
| @@ -738,11 +733,7 @@ static int mt7621_pci_probe(struct platform_device *pdev) · 69 unmodified lines | ||
| 738 | 733 | |
| 739 | 734 | setup_cm_memory_region(pcie); |
| 740 | 735 | |
| 741 | − err = mt7621_pcie_request_resources(pcie, &res); | |
| 742 | − if (err) { | |
| 743 | − dev_err(dev, "Error requesting resources\n"); | |
| 744 | − return err; | |
| 745 | − } | |
| 736 | + mt7621_pcie_add_resources(pcie, &res); | |
| 746 | 737 | |
| 747 | 738 | err = mt7621_pcie_register_host(bridge, &res); |
| 748 | 739 | if (err) { |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | config DMA_RALINK |
| 3 | 3 | tristate "RALINK DMA support" |
| 4 | 4 | depends on RALINK && !SOC_RT288X |
| 5 | + depends on DMADEVICES | |
| 5 | 6 | select DMA_ENGINE |
| 6 | 7 | select DMA_VIRTUAL_CHANNELS |
| 7 | 8 | |
| @@ -20,6 +20,7 @@ static const struct sdio_device_id sdio_ids[] = { · 19 unmodified lines | ||
| 20 | 20 | { SDIO_DEVICE(0x024c, 0x0525), }, |
| 21 | 21 | { SDIO_DEVICE(0x024c, 0x0623), }, |
| 22 | 22 | { SDIO_DEVICE(0x024c, 0x0626), }, |
| 23 | + { SDIO_DEVICE(0x024c, 0x0627), }, | |
| 23 | 24 | { SDIO_DEVICE(0x024c, 0xb723), }, |
| 24 | 25 | { /* end: all zeroes */ }, |
| 25 | 26 | }; |
| @@ -483,8 +483,7 @@ EXPORT_SYMBOL(iscsit_queue_rsp); · 482 unmodified lines | ||
| 483 | 483 | void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd) |
| 484 | 484 | { |
| 485 | 485 | spin_lock_bh(&conn->cmd_lock); |
| 486 | − if (!list_empty(&cmd->i_conn_node) && | |
| 487 | − !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP)) | |
| 486 | + if (!list_empty(&cmd->i_conn_node)) | |
| 488 | 487 | list_del_init(&cmd->i_conn_node); |
| 489 | 488 | spin_unlock_bh(&conn->cmd_lock); |
| 490 | 489 | |
| @@ -4083,12 +4082,22 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn) · 3592 unmodified lines | ||
| 4083 | 4082 | spin_lock_bh(&conn->cmd_lock); |
| 4084 | 4083 | list_splice_init(&conn->conn_cmd_list, &tmp_list); |
| 4085 | 4084 | |
| 4086 | − list_for_each_entry(cmd, &tmp_list, i_conn_node) { | |
| 4085 | + list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) { | |
| 4087 | 4086 | struct se_cmd *se_cmd = &cmd->se_cmd; |
| 4088 | 4087 | |
| 4089 | 4088 | if (se_cmd->se_tfo != NULL) { |
| 4090 | 4089 | spin_lock_irq(&se_cmd->t_state_lock); |
| 4091 | − se_cmd->transport_state |= CMD_T_FABRIC_STOP; | |
| 4090 | + if (se_cmd->transport_state & CMD_T_ABORTED) { | |
| 4091 | + /* | |
| 4092 | + * LIO's abort path owns the cleanup for this, | |
| 4093 | + * so put it back on the list and let | |
| 4094 | + * aborted_task handle it. | |
| 4095 | + */ | |
| 4096 | + list_move_tail(&cmd->i_conn_node, | |
| 4097 | + &conn->conn_cmd_list); | |
| 4098 | + } else { | |
| 4099 | + se_cmd->transport_state |= CMD_T_FABRIC_STOP; | |
| 4100 | + } | |
| 4092 | 4101 | spin_unlock_irq(&se_cmd->t_state_lock); |
| 4093 | 4102 | } |
| 4094 | 4103 | } |
| @@ -534,7 +534,8 @@ void optee_free_pages_list(void *list, size_t num_entries) · 533 unmodified lines | ||
| 534 | 534 | static bool is_normal_memory(pgprot_t p) |
| 535 | 535 | { |
| 536 | 536 | #if defined(CONFIG_ARM) |
| 537 | − return (pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC; | |
| 537 | + return (((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC) || | |
| 538 | + ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEBACK)); | |
| 538 | 539 | #elif defined(CONFIG_ARM64) |
| 539 | 540 | return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL); |
| 540 | 541 | #else |
| @@ -789,8 +789,10 @@ static int ar933x_uart_probe(struct platform_device *pdev) · 788 unmodified lines | ||
| 789 | 789 | goto err_disable_clk; |
| 790 | 790 | |
| 791 | 791 | up->gpios = mctrl_gpio_init(port, 0); |
| 792 | − if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS) | |
| 793 | − return PTR_ERR(up->gpios); | |
| 792 | + if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS) { | |
| 793 | + ret = PTR_ERR(up->gpios); | |
| 794 | + goto err_disable_clk; | |
| 795 | + } | |
| 794 | 796 | |
| 795 | 797 | up->rts_gpiod = mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS); |
| 796 | 798 | |
| @@ -942,8 +942,14 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) · 941 unmodified lines | ||
| 942 | 942 | struct imx_port *sport = dev_id; |
| 943 | 943 | unsigned int usr1, usr2, ucr1, ucr2, ucr3, ucr4; |
| 944 | 944 | irqreturn_t ret = IRQ_NONE; |
| 945 | + unsigned long flags = 0; | |
| 945 | 946 | |
| 946 | − spin_lock(&sport->port.lock); | |
| 947 | + /* | |
| 948 | + * IRQs might not be disabled upon entering this interrupt handler, | |
| 949 | + * e.g. when interrupt handlers are forced to be threaded. To support | |
| 950 | + * this scenario as well, disable IRQs when acquiring the spinlock. | |
| 951 | + */ | |
| 952 | + spin_lock_irqsave(&sport->port.lock, flags); | |
| 947 | 953 | |
| 948 | 954 | usr1 = imx_uart_readl(sport, USR1); |
| 949 | 955 | usr2 = imx_uart_readl(sport, USR2); |
| @@ -1013,7 +1019,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) · 63 unmodified lines | ||
| 1013 | 1019 | ret = IRQ_HANDLED; |
| 1014 | 1020 | } |
| 1015 | 1021 | |
| 1016 | − spin_unlock(&sport->port.lock); | |
| 1022 | + spin_unlock_irqrestore(&sport->port.lock, flags); | |
| 1017 | 1023 | |
| 1018 | 1024 | return ret; |
| 1019 | 1025 | } |
| @@ -2002,16 +2008,6 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) · 982 unmodified lines | ||
| 2002 | 2008 | unsigned int ucr1; |
| 2003 | 2009 | unsigned long flags = 0; |
| 2004 | 2010 | int locked = 1; |
| 2005 | − int retval; | |
| 2006 | − | |
| 2007 | − retval = clk_enable(sport->clk_per); | |
| 2008 | − if (retval) | |
| 2009 | − return; | |
| 2010 | − retval = clk_enable(sport->clk_ipg); | |
| 2011 | − if (retval) { | |
| 2012 | − clk_disable(sport->clk_per); | |
| 2013 | − return; | |
| 2014 | − } | |
| 2015 | 2011 | |
| 2016 | 2012 | if (sport->port.sysrq) |
| 2017 | 2013 | locked = 0; |
| @@ -2047,9 +2043,6 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) · 29 unmodified lines | ||
| 2047 | 2043 | |
| 2048 | 2044 | if (locked) |
| 2049 | 2045 | spin_unlock_irqrestore(&sport->port.lock, flags); |
| 2050 | − | |
| 2051 | − clk_disable(sport->clk_ipg); | |
| 2052 | − clk_disable(sport->clk_per); | |
| 2053 | 2046 | } |
| 2054 | 2047 | |
| 2055 | 2048 | /* |
| @@ -2150,15 +2143,14 @@ imx_uart_console_setup(struct console *co, char *options) · 94 unmodified lines | ||
| 2150 | 2143 | |
| 2151 | 2144 | retval = uart_set_options(&sport->port, co, baud, parity, bits, flow); |
| 2152 | 2145 | |
| 2153 | − clk_disable(sport->clk_ipg); | |
| 2154 | 2146 | if (retval) { |
| 2155 | − clk_unprepare(sport->clk_ipg); | |
| 2147 | + clk_disable_unprepare(sport->clk_ipg); | |
| 2156 | 2148 | goto error_console; |
| 2157 | 2149 | } |
| 2158 | 2150 | |
| 2159 | − retval = clk_prepare(sport->clk_per); | |
| 2151 | + retval = clk_prepare_enable(sport->clk_per); | |
| 2160 | 2152 | if (retval) |
| 2161 | − clk_unprepare(sport->clk_ipg); | |
| 2153 | + clk_disable_unprepare(sport->clk_ipg); | |
| 2162 | 2154 | |
| 2163 | 2155 | error_console: |
| 2164 | 2156 | return retval; |
| @@ -1093,7 +1093,12 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) · 1092 unmodified lines | ||
| 1093 | 1093 | goto err1; |
| 1094 | 1094 | } |
| 1095 | 1095 | |
| 1096 | − fb_virt = ioremap(par->mem->start, screen_fb_size); | |
| 1096 | + /* | |
| 1097 | + * Map the VRAM cacheable for performance. This is also required for | |
| 1098 | + * VM Connect to display properly for ARM64 Linux VM, as the host also | |
| 1099 | + * maps the VRAM cacheable. | |
| 1100 | + */ | |
| 1101 | + fb_virt = ioremap_cache(par->mem->start, screen_fb_size); | |
| 1097 | 1102 | if (!fb_virt) |
| 1098 | 1103 | goto err2; |
| 1099 | 1104 | |
| @@ -823,6 +823,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry, · 822 unmodified lines | ||
| 823 | 823 | vp->cb_break_before = afs_calc_vnode_cb_break(vnode); |
| 824 | 824 | vp->vnode = vnode; |
| 825 | 825 | vp->put_vnode = true; |
| 826 | + vp->speculative = true; /* vnode not locked */ | |
| 826 | 827 | } |
| 827 | 828 | } |
| 828 | 829 | } |
| @@ -294,6 +294,13 @@ void afs_vnode_commit_status(struct afs_operation *op, struct afs_vnode_param *v · 293 unmodified lines | ||
| 294 | 294 | op->flags &= ~AFS_OPERATION_DIR_CONFLICT; |
| 295 | 295 | } |
| 296 | 296 | } else if (vp->scb.have_status) { |
| 297 | + if (vp->dv_before + vp->dv_delta != vp->scb.status.data_version && | |
| 298 | + vp->speculative) | |
| 299 | + /* Ignore the result of a speculative bulk status fetch | |
| 300 | + * if it splits around a modification op, thereby | |
| 301 | + * appearing to regress the data version. | |
| 302 | + */ | |
| 303 | + goto out; | |
| 297 | 304 | afs_apply_status(op, vp); |
| 298 | 305 | if (vp->scb.have_cb) |
| 299 | 306 | afs_apply_callback(op, vp); |
| @@ -305,6 +312,7 @@ void afs_vnode_commit_status(struct afs_operation *op, struct afs_vnode_param *v · 5 unmodified lines | ||
| 305 | 312 | } |
| 306 | 313 | } |
| 307 | 314 | |
| 315 | +out: | |
| 308 | 316 | write_sequnlock(&vnode->cb_lock); |
| 309 | 317 | |
| 310 | 318 | if (vp->scb.have_status) |
| @@ -755,6 +755,7 @@ struct afs_vnode_param { · 754 unmodified lines | ||
| 755 | 755 | bool update_ctime:1; /* Need to update the ctime */ |
| 756 | 756 | bool set_size:1; /* Must update i_size */ |
| 757 | 757 | bool op_unlinked:1; /* True if file was unlinked by op */ |
| 758 | + bool speculative:1; /* T if speculative status fetch (no vnode lock) */ | |
| 758 | 759 | }; |
| 759 | 760 | |
| 760 | 761 | /* |
| @@ -878,7 +878,10 @@ struct btrfs_fs_info { · 877 unmodified lines | ||
| 878 | 878 | */ |
| 879 | 879 | struct ulist *qgroup_ulist; |
| 880 | 880 | |
| 881 | − /* protect user change for quota operations */ | |
| 881 | + /* | |
| 882 | + * Protect user change for quota operations. If a transaction is needed, | |
| 883 | + * it must be started before locking this lock. | |
| 884 | + */ | |
| 882 | 885 | struct mutex qgroup_ioctl_lock; |
| 883 | 886 | |
| 884 | 887 | /* list of dirty qgroups to be written at next commit */ |
| @@ -452,46 +452,6 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages) · 451 unmodified lines | ||
| 452 | 452 | } |
| 453 | 453 | } |
| 454 | 454 | |
| 455 | −static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode, | |
| 456 | − const u64 start, | |
| 457 | − const u64 len, | |
| 458 | − struct extent_state **cached_state) | |
| 459 | −{ | |
| 460 | − u64 search_start = start; | |
| 461 | − const u64 end = start + len - 1; | |
| 462 | − | |
| 463 | − while (search_start < end) { | |
| 464 | − const u64 search_len = end - search_start + 1; | |
| 465 | − struct extent_map *em; | |
| 466 | − u64 em_len; | |
| 467 | − int ret = 0; | |
| 468 | − | |
| 469 | − em = btrfs_get_extent(inode, NULL, 0, search_start, search_len); | |
| 470 | − if (IS_ERR(em)) | |
| 471 | − return PTR_ERR(em); | |
| 472 | − | |
| 473 | − if (em->block_start != EXTENT_MAP_HOLE) | |
| 474 | − goto next; | |
| 475 | − | |
| 476 | − em_len = em->len; | |
| 477 | − if (em->start < search_start) | |
| 478 | − em_len -= search_start - em->start; | |
| 479 | − if (em_len > search_len) | |
| 480 | − em_len = search_len; | |
| 481 | − | |
| 482 | − ret = set_extent_bit(&inode->io_tree, search_start, | |
| 483 | − search_start + em_len - 1, | |
| 484 | − EXTENT_DELALLOC_NEW, | |
| 485 | − NULL, cached_state, GFP_NOFS); | |
| 486 | −next: | |
| 487 | − search_start = extent_map_end(em); | |
| 488 | − free_extent_map(em); | |
| 489 | − if (ret) | |
| 490 | − return ret; | |
| 491 | − } | |
| 492 | − return 0; | |
| 493 | −} | |
| 494 | − | |
| 495 | 455 | /* |
| 496 | 456 | * after copy_from_user, pages need to be dirtied and we need to make |
| 497 | 457 | * sure holes are created between the current EOF and the start of |
| @@ -528,23 +488,6 @@ int btrfs_dirty_pages(struct btrfs_inode *inode, struct page **pages, · 30 unmodified lines | ||
| 528 | 488 | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, |
| 529 | 489 | 0, 0, cached); |
| 530 | 490 | |
| 531 | − if (!btrfs_is_free_space_inode(inode)) { | |
| 532 | − if (start_pos >= isize && | |
| 533 | − !(inode->flags & BTRFS_INODE_PREALLOC)) { | |
| 534 | − /* | |
| 535 | − * There can't be any extents following eof in this case | |
| 536 | − * so just set the delalloc new bit for the range | |
| 537 | − * directly. | |
| 538 | − */ | |
| 539 | − extra_bits |= EXTENT_DELALLOC_NEW; | |
| 540 | − } else { | |
| 541 | − err = btrfs_find_new_delalloc_bytes(inode, start_pos, | |
| 542 | − num_bytes, cached); | |
| 543 | − if (err) | |
| 544 | − return err; | |
| 545 | − } | |
| 546 | − } | |
| 547 | − | |
| 548 | 491 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, |
| 549 | 492 | extra_bits, cached); |
| 550 | 493 | if (err) |
| @@ -2253,11 +2253,69 @@ static int add_pending_csums(struct btrfs_trans_handle *trans, · 2252 unmodified lines | ||
| 2253 | 2253 | return 0; |
| 2254 | 2254 | } |
| 2255 | 2255 | |
| 2256 | +static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode, | |
| 2257 | + const u64 start, | |
| 2258 | + const u64 len, | |
| 2259 | + struct extent_state **cached_state) | |
| 2260 | +{ | |
| 2261 | + u64 search_start = start; | |
| 2262 | + const u64 end = start + len - 1; | |
| 2263 | + | |
| 2264 | + while (search_start < end) { | |
| 2265 | + const u64 search_len = end - search_start + 1; | |
| 2266 | + struct extent_map *em; | |
| 2267 | + u64 em_len; | |
| 2268 | + int ret = 0; | |
| 2269 | + | |
| 2270 | + em = btrfs_get_extent(inode, NULL, 0, search_start, search_len); | |
| 2271 | + if (IS_ERR(em)) | |
| 2272 | + return PTR_ERR(em); | |
| 2273 | + | |
| 2274 | + if (em->block_start != EXTENT_MAP_HOLE) | |
| 2275 | + goto next; | |
| 2276 | + | |
| 2277 | + em_len = em->len; | |
| 2278 | + if (em->start < search_start) | |
| 2279 | + em_len -= search_start - em->start; | |
| 2280 | + if (em_len > search_len) | |
| 2281 | + em_len = search_len; | |
| 2282 | + | |
| 2283 | + ret = set_extent_bit(&inode->io_tree, search_start, | |
| 2284 | + search_start + em_len - 1, | |
| 2285 | + EXTENT_DELALLOC_NEW, | |
| 2286 | + NULL, cached_state, GFP_NOFS); | |
| 2287 | +next: | |
| 2288 | + search_start = extent_map_end(em); | |
| 2289 | + free_extent_map(em); | |
| 2290 | + if (ret) | |
| 2291 | + return ret; | |
| 2292 | + } | |
| 2293 | + return 0; | |
| 2294 | +} | |
| 2295 | + | |
| 2256 | 2296 | int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end, |
| 2257 | 2297 | unsigned int extra_bits, |
| 2258 | 2298 | struct extent_state **cached_state) |
| 2259 | 2299 | { |
| 2260 | 2300 | WARN_ON(PAGE_ALIGNED(end)); |
| 2301 | + | |
| 2302 | + if (start >= i_size_read(&inode->vfs_inode) && | |
| 2303 | + !(inode->flags & BTRFS_INODE_PREALLOC)) { | |
| 2304 | + /* | |
| 2305 | + * There can't be any extents following eof in this case so just | |
| 2306 | + * set the delalloc new bit for the range directly. | |
| 2307 | + */ | |
| 2308 | + extra_bits |= EXTENT_DELALLOC_NEW; | |
| 2309 | + } else { | |
| 2310 | + int ret; | |
| 2311 | + | |
| 2312 | + ret = btrfs_find_new_delalloc_bytes(inode, start, | |
| 2313 | + end + 1 - start, | |
| 2314 | + cached_state); | |
| 2315 | + if (ret) | |
| 2316 | + return ret; | |
| 2317 | + } | |
| 2318 | + | |
| 2261 | 2319 | return set_extent_delalloc(&inode->io_tree, start, end, extra_bits, |
| 2262 | 2320 | cached_state); |
| 2263 | 2321 | } |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/slab.h> |
| 12 | 12 | #include <linux/workqueue.h> |
| 13 | 13 | #include <linux/btrfs.h> |
| 14 | +#include <linux/sched/mm.h> | |
| 14 | 15 | |
| 15 | 16 | #include "ctree.h" |
| 16 | 17 | #include "transaction.h" |
| @@ -497,13 +498,13 @@ next2: · 480 unmodified lines | ||
| 497 | 498 | break; |
| 498 | 499 | } |
| 499 | 500 | out: |
| 501 | + btrfs_free_path(path); | |
| 500 | 502 | fs_info->qgroup_flags |= flags; |
| 501 | 503 | if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON)) |
| 502 | 504 | clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); |
| 503 | 505 | else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN && |
| 504 | 506 | ret >= 0) |
| 505 | 507 | ret = qgroup_rescan_init(fs_info, rescan_progress, 0); |
| 506 | − btrfs_free_path(path); | |
| 507 | 508 | |
| 508 | 509 | if (ret < 0) { |
| 509 | 510 | ulist_free(fs_info->qgroup_ulist); |
| @@ -936,6 +937,7 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info) · 426 unmodified lines | ||
| 936 | 937 | struct btrfs_key found_key; |
| 937 | 938 | struct btrfs_qgroup *qgroup = NULL; |
| 938 | 939 | struct btrfs_trans_handle *trans = NULL; |
| 940 | + struct ulist *ulist = NULL; | |
| 939 | 941 | int ret = 0; |
| 940 | 942 | int slot; |
| 941 | 943 | |
| @@ -943,8 +945,8 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info) · 1 unmodified line | ||
| 943 | 945 | if (fs_info->quota_root) |
| 944 | 946 | goto out; |
| 945 | 947 | |
| 946 | − fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL); | |
| 947 | − if (!fs_info->qgroup_ulist) { | |
| 948 | + ulist = ulist_alloc(GFP_KERNEL); | |
| 949 | + if (!ulist) { | |
| 948 | 950 | ret = -ENOMEM; |
| 949 | 951 | goto out; |
| 950 | 952 | } |
| @@ -952,6 +954,22 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info) · 1 unmodified line | ||
| 952 | 954 | ret = btrfs_sysfs_add_qgroups(fs_info); |
| 953 | 955 | if (ret < 0) |
| 954 | 956 | goto out; |
| 957 | + | |
| 958 | + /* | |
| 959 | + * Unlock qgroup_ioctl_lock before starting the transaction. This is to | |
| 960 | + * avoid lock acquisition inversion problems (reported by lockdep) between | |
| 961 | + * qgroup_ioctl_lock and the vfs freeze semaphores, acquired when we | |
| 962 | + * start a transaction. | |
| 963 | + * After we started the transaction lock qgroup_ioctl_lock again and | |
| 964 | + * check if someone else created the quota root in the meanwhile. If so, | |
| 965 | + * just return success and release the transaction handle. | |
| 966 | + * | |
| 967 | + * Also we don't need to worry about someone else calling | |
| 968 | + * btrfs_sysfs_add_qgroups() after we unlock and getting an error because | |
| 969 | + * that function returns 0 (success) when the sysfs entries already exist. | |
| 970 | + */ | |
| 971 | + mutex_unlock(&fs_info->qgroup_ioctl_lock); | |
| 972 | + | |
| 955 | 973 | /* |
| 956 | 974 | * 1 for quota root item |
| 957 | 975 | * 1 for BTRFS_QGROUP_STATUS item |
| @@ -961,12 +979,20 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info) · 3 unmodified lines | ||
| 961 | 979 | * would be a lot of overkill. |
| 962 | 980 | */ |
| 963 | 981 | trans = btrfs_start_transaction(tree_root, 2); |
| 982 | + | |
| 983 | + mutex_lock(&fs_info->qgroup_ioctl_lock); | |
| 964 | 984 | if (IS_ERR(trans)) { |
| 965 | 985 | ret = PTR_ERR(trans); |
| 966 | 986 | trans = NULL; |
| 967 | 987 | goto out; |
| 968 | 988 | } |
| 969 | 989 | |
| 990 | + if (fs_info->quota_root) | |
| 991 | + goto out; | |
| 992 | + | |
| 993 | + fs_info->qgroup_ulist = ulist; | |
| 994 | + ulist = NULL; | |
| 995 | + | |
| 970 | 996 | /* |
| 971 | 997 | * initially create the quota tree |
| 972 | 998 | */ |
| @@ -1124,11 +1150,14 @@ out: · 151 unmodified lines | ||
| 1124 | 1150 | if (ret) { |
| 1125 | 1151 | ulist_free(fs_info->qgroup_ulist); |
| 1126 | 1152 | fs_info->qgroup_ulist = NULL; |
| 1127 | − if (trans) | |
| 1128 | − btrfs_end_transaction(trans); | |
| 1129 | 1153 | btrfs_sysfs_del_qgroups(fs_info); |
| 1130 | 1154 | } |
| 1131 | 1155 | mutex_unlock(&fs_info->qgroup_ioctl_lock); |
| 1156 | + if (ret && trans) | |
| 1157 | + btrfs_end_transaction(trans); | |
| 1158 | + else if (trans) | |
| 1159 | + ret = btrfs_end_transaction(trans); | |
| 1160 | + ulist_free(ulist); | |
| 1132 | 1161 | return ret; |
| 1133 | 1162 | } |
| 1134 | 1163 | |
| @@ -1141,19 +1170,29 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) · 6 unmodified lines | ||
| 1141 | 1170 | mutex_lock(&fs_info->qgroup_ioctl_lock); |
| 1142 | 1171 | if (!fs_info->quota_root) |
| 1143 | 1172 | goto out; |
| 1173 | + mutex_unlock(&fs_info->qgroup_ioctl_lock); | |
| 1144 | 1174 | |
| 1145 | 1175 | /* |
| 1146 | 1176 | * 1 For the root item |
| 1147 | 1177 | * |
| 1148 | 1178 | * We should also reserve enough items for the quota tree deletion in |
| 1149 | 1179 | * btrfs_clean_quota_tree but this is not done. |
| 1180 | + * | |
| 1181 | + * Also, we must always start a transaction without holding the mutex | |
| 1182 | + * qgroup_ioctl_lock, see btrfs_quota_enable(). | |
| 1150 | 1183 | */ |
| 1151 | 1184 | trans = btrfs_start_transaction(fs_info->tree_root, 1); |
| 1185 | + | |
| 1186 | + mutex_lock(&fs_info->qgroup_ioctl_lock); | |
| 1152 | 1187 | if (IS_ERR(trans)) { |
| 1153 | 1188 | ret = PTR_ERR(trans); |
| 1189 | + trans = NULL; | |
| 1154 | 1190 | goto out; |
| 1155 | 1191 | } |
| 1156 | 1192 | |
| 1193 | + if (!fs_info->quota_root) | |
| 1194 | + goto out; | |
| 1195 | + | |
| 1157 | 1196 | clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); |
| 1158 | 1197 | btrfs_qgroup_wait_for_completion(fs_info, false); |
| 1159 | 1198 | spin_lock(&fs_info->qgroup_lock); |
| @@ -1167,13 +1206,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) · 7 unmodified lines | ||
| 1167 | 1206 | ret = btrfs_clean_quota_tree(trans, quota_root); |
| 1168 | 1207 | if (ret) { |
| 1169 | 1208 | btrfs_abort_transaction(trans, ret); |
| 1170 | − goto end_trans; | |
| 1209 | + goto out; | |
| 1171 | 1210 | } |
| 1172 | 1211 | |
| 1173 | 1212 | ret = btrfs_del_root(trans, "a_root->root_key); |
| 1174 | 1213 | if (ret) { |
| 1175 | 1214 | btrfs_abort_transaction(trans, ret); |
| 1176 | − goto end_trans; | |
| 1215 | + goto out; | |
| 1177 | 1216 | } |
| 1178 | 1217 | |
| 1179 | 1218 | list_del("a_root->dirty_list); |
| @@ -1185,10 +1224,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) · 5 unmodified lines | ||
| 1185 | 1224 | |
| 1186 | 1225 | btrfs_put_root(quota_root); |
| 1187 | 1226 | |
| 1188 | −end_trans: | |
| 1189 | − ret = btrfs_end_transaction(trans); | |
| 1190 | 1227 | out: |
| 1191 | 1228 | mutex_unlock(&fs_info->qgroup_ioctl_lock); |
| 1229 | + if (ret && trans) | |
| 1230 | + btrfs_end_transaction(trans); | |
| 1231 | + else if (trans) | |
| 1232 | + ret = btrfs_end_transaction(trans); | |
| 1233 | + | |
| 1192 | 1234 | return ret; |
| 1193 | 1235 | } |
| 1194 | 1236 | |
| @@ -1324,13 +1366,17 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, u64 src, · 129 unmodified lines | ||
| 1324 | 1366 | struct btrfs_qgroup *member; |
| 1325 | 1367 | struct btrfs_qgroup_list *list; |
| 1326 | 1368 | struct ulist *tmp; |
| 1369 | + unsigned int nofs_flag; | |
| 1327 | 1370 | int ret = 0; |
| 1328 | 1371 | |
| 1329 | 1372 | /* Check the level of src and dst first */ |
| 1330 | 1373 | if (btrfs_qgroup_level(src) >= btrfs_qgroup_level(dst)) |
| 1331 | 1374 | return -EINVAL; |
| 1332 | 1375 | |
| 1376 | + /* We hold a transaction handle open, must do a NOFS allocation. */ | |
| 1377 | + nofs_flag = memalloc_nofs_save(); | |
| 1333 | 1378 | tmp = ulist_alloc(GFP_KERNEL); |
| 1379 | + memalloc_nofs_restore(nofs_flag); | |
| 1334 | 1380 | if (!tmp) |
| 1335 | 1381 | return -ENOMEM; |
| 1336 | 1382 | |
| @@ -1387,10 +1433,14 @@ static int __del_qgroup_relation(struct btrfs_trans_handle *trans, u64 src, · 50 unmodified lines | ||
| 1387 | 1433 | struct btrfs_qgroup_list *list; |
| 1388 | 1434 | struct ulist *tmp; |
| 1389 | 1435 | bool found = false; |
| 1436 | + unsigned int nofs_flag; | |
| 1390 | 1437 | int ret = 0; |
| 1391 | 1438 | int ret2; |
| 1392 | 1439 | |
| 1440 | + /* We hold a transaction handle open, must do a NOFS allocation. */ | |
| 1441 | + nofs_flag = memalloc_nofs_save(); | |
| 1393 | 1442 | tmp = ulist_alloc(GFP_KERNEL); |
| 1443 | + memalloc_nofs_restore(nofs_flag); | |
| 1394 | 1444 | if (!tmp) |
| 1395 | 1445 | return -ENOMEM; |
| 1396 | 1446 | |
| @@ -3512,6 +3562,7 @@ static int try_flush_qgroup(struct btrfs_root *root) · 2115 unmodified lines | ||
| 3512 | 3562 | { |
| 3513 | 3563 | struct btrfs_trans_handle *trans; |
| 3514 | 3564 | int ret; |
| 3565 | + bool can_commit = true; | |
| 3515 | 3566 | |
| 3516 | 3567 | /* |
| 3517 | 3568 | * We don't want to run flush again and again, so if there is a running |
| @@ -3523,6 +3574,20 @@ static int try_flush_qgroup(struct btrfs_root *root) · 5 unmodified lines | ||
| 3523 | 3574 | return 0; |
| 3524 | 3575 | } |
| 3525 | 3576 | |
| 3577 | + /* | |
| 3578 | + * If current process holds a transaction, we shouldn't flush, as we | |
| 3579 | + * assume all space reservation happens before a transaction handle is | |
| 3580 | + * held. | |
| 3581 | + * | |
| 3582 | + * But there are cases like btrfs_delayed_item_reserve_metadata() where | |
| 3583 | + * we try to reserve space with one transction handle already held. | |
| 3584 | + * In that case we can't commit transaction, but at least try to end it | |
| 3585 | + * and hope the started data writes can free some space. | |
| 3586 | + */ | |
| 3587 | + if (current->journal_info && | |
| 3588 | + current->journal_info != BTRFS_SEND_TRANS_STUB) | |
| 3589 | + can_commit = false; | |
| 3590 | + | |
| 3526 | 3591 | ret = btrfs_start_delalloc_snapshot(root); |
| 3527 | 3592 | if (ret < 0) |
| 3528 | 3593 | goto out; |
| @@ -3534,7 +3599,10 @@ static int try_flush_qgroup(struct btrfs_root *root) · 5 unmodified lines | ||
| 3534 | 3599 | goto out; |
| 3535 | 3600 | } |
| 3536 | 3601 | |
| 3537 | − ret = btrfs_commit_transaction(trans); | |
| 3602 | + if (can_commit) | |
| 3603 | + ret = btrfs_commit_transaction(trans); | |
| 3604 | + else | |
| 3605 | + ret = btrfs_end_transaction(trans); | |
| 3538 | 3606 | out: |
| 3539 | 3607 | clear_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state); |
| 3540 | 3608 | wake_up(&root->qgroup_flush_wait); |
| @@ -983,7 +983,8 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize) · 982 unmodified lines | ||
| 983 | 983 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, |
| 984 | 984 | BTRFS_MAX_EXTENT_SIZE >> 1, |
| 985 | 985 | (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1, |
| 986 | − EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL); | |
| 986 | + EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | | |
| 987 | + EXTENT_UPTODATE, 0, 0, NULL); | |
| 987 | 988 | if (ret) { |
| 988 | 989 | test_err("clear_extent_bit returned %d", ret); |
| 989 | 990 | goto out; |
| @@ -1050,7 +1051,8 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize) · 60 unmodified lines | ||
| 1050 | 1051 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, |
| 1051 | 1052 | BTRFS_MAX_EXTENT_SIZE + sectorsize, |
| 1052 | 1053 | BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, |
| 1053 | − EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL); | |
| 1054 | + EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | | |
| 1055 | + EXTENT_UPTODATE, 0, 0, NULL); | |
| 1054 | 1056 | if (ret) { |
| 1055 | 1057 | test_err("clear_extent_bit returned %d", ret); |
| 1056 | 1058 | goto out; |
| @@ -1082,7 +1084,8 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize) · 25 unmodified lines | ||
| 1082 | 1084 | |
| 1083 | 1085 | /* Empty */ |
| 1084 | 1086 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, |
| 1085 | − EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL); | |
| 1087 | + EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | | |
| 1088 | + EXTENT_UPTODATE, 0, 0, NULL); | |
| 1086 | 1089 | if (ret) { |
| 1087 | 1090 | test_err("clear_extent_bit returned %d", ret); |
| 1088 | 1091 | goto out; |
| @@ -1097,7 +1100,8 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize) · 8 unmodified lines | ||
| 1097 | 1100 | out: |
| 1098 | 1101 | if (ret) |
| 1099 | 1102 | clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, |
| 1100 | − EXTENT_DELALLOC | EXTENT_UPTODATE, 0, 0, NULL); | |
| 1103 | + EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | | |
| 1104 | + EXTENT_UPTODATE, 0, 0, NULL); | |
| 1101 | 1105 | iput(inode); |
| 1102 | 1106 | btrfs_free_dummy_root(root); |
| 1103 | 1107 | btrfs_free_dummy_fs_info(fs_info); |
| @@ -1068,6 +1068,7 @@ static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key, · 1067 unmodified lines | ||
| 1068 | 1068 | "invalid root item size, have %u expect %zu or %u", |
| 1069 | 1069 | btrfs_item_size_nr(leaf, slot), sizeof(ri), |
| 1070 | 1070 | btrfs_legacy_root_item_size()); |
| 1071 | + return -EUCLEAN; | |
| 1071 | 1072 | } |
| 1072 | 1073 | |
| 1073 | 1074 | /* |
| @@ -1423,6 +1424,7 @@ static int check_extent_data_ref(struct extent_buffer *leaf, · 349 unmodified lines | ||
| 1423 | 1424 | "invalid item size, have %u expect aligned to %zu for key type %u", |
| 1424 | 1425 | btrfs_item_size_nr(leaf, slot), |
| 1425 | 1426 | sizeof(*dref), key->type); |
| 1427 | + return -EUCLEAN; | |
| 1426 | 1428 | } |
| 1427 | 1429 | if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) { |
| 1428 | 1430 | generic_err(leaf, slot, |
| @@ -1451,6 +1453,7 @@ static int check_extent_data_ref(struct extent_buffer *leaf, · 22 unmodified lines | ||
| 1451 | 1453 | extent_err(leaf, slot, |
| 1452 | 1454 | "invalid extent data backref offset, have %llu expect aligned to %u", |
| 1453 | 1455 | offset, leaf->fs_info->sectorsize); |
| 1456 | + return -EUCLEAN; | |
| 1454 | 1457 | } |
| 1455 | 1458 | } |
| 1456 | 1459 | return 0; |
| @@ -940,7 +940,13 @@ static noinline struct btrfs_device *device_list_add(const char *path, · 939 unmodified lines | ||
| 940 | 940 | if (device->bdev != path_bdev) { |
| 941 | 941 | bdput(path_bdev); |
| 942 | 942 | mutex_unlock(&fs_devices->device_list_mutex); |
| 943 | − btrfs_warn_in_rcu(device->fs_info, | |
| 943 | + /* | |
| 944 | + * device->fs_info may not be reliable here, so | |
| 945 | + * pass in a NULL instead. This avoids a | |
| 946 | + * possible use-after-free when the fs_info and | |
| 947 | + * fs_info->sb are already torn down. | |
| 948 | + */ | |
| 949 | + btrfs_warn_in_rcu(NULL, | |
| 944 | 950 | "duplicate device %s devid %llu generation %llu scanned by %s (%d)", |
| 945 | 951 | path, devid, found_transid, |
| 946 | 952 | current->comm, |
| @@ -1266,6 +1266,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, · 1265 unmodified lines | ||
| 1266 | 1266 | cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc); |
| 1267 | 1267 | } else if (mode_from_special_sid) { |
| 1268 | 1268 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true); |
| 1269 | + kfree(pntsd); | |
| 1269 | 1270 | } else { |
| 1270 | 1271 | /* get approximated mode from ACL */ |
| 1271 | 1272 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false); |
| @@ -264,7 +264,7 @@ smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val) · 263 unmodified lines | ||
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | static struct mid_q_entry * |
| 267 | −smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |
| 267 | +__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue) | |
| 268 | 268 | { |
| 269 | 269 | struct mid_q_entry *mid; |
| 270 | 270 | struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; |
| @@ -281,6 +281,10 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) · 10 unmodified lines | ||
| 281 | 281 | (mid->mid_state == MID_REQUEST_SUBMITTED) && |
| 282 | 282 | (mid->command == shdr->Command)) { |
| 283 | 283 | kref_get(&mid->refcount); |
| 284 | + if (dequeue) { | |
| 285 | + list_del_init(&mid->qhead); | |
| 286 | + mid->mid_flags |= MID_DELETED; | |
| 287 | + } | |
| 284 | 288 | spin_unlock(&GlobalMid_Lock); |
| 285 | 289 | return mid; |
| 286 | 290 | } |
| @@ -289,6 +293,18 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) · 2 unmodified lines | ||
| 289 | 293 | return NULL; |
| 290 | 294 | } |
| 291 | 295 | |
| 296 | +static struct mid_q_entry * | |
| 297 | +smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |
| 298 | +{ | |
| 299 | + return __smb2_find_mid(server, buf, false); | |
| 300 | +} | |
| 301 | + | |
| 302 | +static struct mid_q_entry * | |
| 303 | +smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf) | |
| 304 | +{ | |
| 305 | + return __smb2_find_mid(server, buf, true); | |
| 306 | +} | |
| 307 | + | |
| 292 | 308 | static void |
| 293 | 309 | smb2_dump_detail(void *buf, struct TCP_Server_Info *server) |
| 294 | 310 | { |
| @@ -4356,7 +4372,8 @@ init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size, · 4061 unmodified lines | ||
| 4356 | 4372 | static int |
| 4357 | 4373 | handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, |
| 4358 | 4374 | char *buf, unsigned int buf_len, struct page **pages, |
| 4359 | − unsigned int npages, unsigned int page_data_size) | |
| 4375 | + unsigned int npages, unsigned int page_data_size, | |
| 4376 | + bool is_offloaded) | |
| 4360 | 4377 | { |
| 4361 | 4378 | unsigned int data_offset; |
| 4362 | 4379 | unsigned int data_len; |
| @@ -4378,7 +4395,8 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, · 15 unmodified lines | ||
| 4378 | 4395 | |
| 4379 | 4396 | if (server->ops->is_session_expired && |
| 4380 | 4397 | server->ops->is_session_expired(buf)) { |
| 4381 | − cifs_reconnect(server); | |
| 4398 | + if (!is_offloaded) | |
| 4399 | + cifs_reconnect(server); | |
| 4382 | 4400 | return -1; |
| 4383 | 4401 | } |
| 4384 | 4402 | |
| @@ -4402,7 +4420,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, · 17 unmodified lines | ||
| 4402 | 4420 | cifs_dbg(FYI, "%s: server returned error %d\n", |
| 4403 | 4421 | __func__, rdata->result); |
| 4404 | 4422 | /* normal error on read response */ |
| 4405 | − dequeue_mid(mid, false); | |
| 4423 | + if (is_offloaded) | |
| 4424 | + mid->mid_state = MID_RESPONSE_RECEIVED; | |
| 4425 | + else | |
| 4426 | + dequeue_mid(mid, false); | |
| 4406 | 4427 | return 0; |
| 4407 | 4428 | } |
| 4408 | 4429 | |
| @@ -4426,7 +4447,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, · 17 unmodified lines | ||
| 4426 | 4447 | cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n", |
| 4427 | 4448 | __func__, data_offset); |
| 4428 | 4449 | rdata->result = -EIO; |
| 4429 | − dequeue_mid(mid, rdata->result); | |
| 4450 | + if (is_offloaded) | |
| 4451 | + mid->mid_state = MID_RESPONSE_MALFORMED; | |
| 4452 | + else | |
| 4453 | + dequeue_mid(mid, rdata->result); | |
| 4430 | 4454 | return 0; |
| 4431 | 4455 | } |
| 4432 | 4456 | |
| @@ -4442,21 +4466,30 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, · 9 unmodified lines | ||
| 4442 | 4466 | cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n", |
| 4443 | 4467 | __func__, data_offset); |
| 4444 | 4468 | rdata->result = -EIO; |
| 4445 | − dequeue_mid(mid, rdata->result); | |
| 4469 | + if (is_offloaded) | |
| 4470 | + mid->mid_state = MID_RESPONSE_MALFORMED; | |
| 4471 | + else | |
| 4472 | + dequeue_mid(mid, rdata->result); | |
| 4446 | 4473 | return 0; |
| 4447 | 4474 | } |
| 4448 | 4475 | |
| 4449 | 4476 | if (data_len > page_data_size - pad_len) { |
| 4450 | 4477 | /* data_len is corrupt -- discard frame */ |
| 4451 | 4478 | rdata->result = -EIO; |
| 4452 | − dequeue_mid(mid, rdata->result); | |
| 4479 | + if (is_offloaded) | |
| 4480 | + mid->mid_state = MID_RESPONSE_MALFORMED; | |
| 4481 | + else | |
| 4482 | + dequeue_mid(mid, rdata->result); | |
| 4453 | 4483 | return 0; |
| 4454 | 4484 | } |
| 4455 | 4485 | |
| 4456 | 4486 | rdata->result = init_read_bvec(pages, npages, page_data_size, |
| 4457 | 4487 | cur_off, &bvec); |
| 4458 | 4488 | if (rdata->result != 0) { |
| 4459 | − dequeue_mid(mid, rdata->result); | |
| 4489 | + if (is_offloaded) | |
| 4490 | + mid->mid_state = MID_RESPONSE_MALFORMED; | |
| 4491 | + else | |
| 4492 | + dequeue_mid(mid, rdata->result); | |
| 4460 | 4493 | return 0; |
| 4461 | 4494 | } |
| 4462 | 4495 | |
| @@ -4471,7 +4504,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, · 8 unmodified lines | ||
| 4471 | 4504 | /* read response payload cannot be in both buf and pages */ |
| 4472 | 4505 | WARN_ONCE(1, "buf can not contain only a part of read data"); |
| 4473 | 4506 | rdata->result = -EIO; |
| 4474 | − dequeue_mid(mid, rdata->result); | |
| 4507 | + if (is_offloaded) | |
| 4508 | + mid->mid_state = MID_RESPONSE_MALFORMED; | |
| 4509 | + else | |
| 4510 | + dequeue_mid(mid, rdata->result); | |
| 4475 | 4511 | return 0; |
| 4476 | 4512 | } |
| 4477 | 4513 | |
| @@ -4482,7 +4518,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid, · 4 unmodified lines | ||
| 4482 | 4518 | if (length < 0) |
| 4483 | 4519 | return length; |
| 4484 | 4520 | |
| 4485 | − dequeue_mid(mid, false); | |
| 4521 | + if (is_offloaded) | |
| 4522 | + mid->mid_state = MID_RESPONSE_RECEIVED; | |
| 4523 | + else | |
| 4524 | + dequeue_mid(mid, false); | |
| 4486 | 4525 | return length; |
| 4487 | 4526 | } |
| 4488 | 4527 | |
| @@ -4511,15 +4550,34 @@ static void smb2_decrypt_offload(struct work_struct *work) · 22 unmodified lines | ||
| 4511 | 4550 | } |
| 4512 | 4551 | |
| 4513 | 4552 | dw->server->lstrp = jiffies; |
| 4514 | − mid = smb2_find_mid(dw->server, dw->buf); | |
| 4553 | + mid = smb2_find_dequeue_mid(dw->server, dw->buf); | |
| 4515 | 4554 | if (mid == NULL) |
| 4516 | 4555 | cifs_dbg(FYI, "mid not found\n"); |
| 4517 | 4556 | else { |
| 4518 | 4557 | mid->decrypted = true; |
| 4519 | 4558 | rc = handle_read_data(dw->server, mid, dw->buf, |
| 4520 | 4559 | dw->server->vals->read_rsp_size, |
| 4521 | − dw->ppages, dw->npages, dw->len); | |
| 4522 | − mid->callback(mid); | |
| 4560 | + dw->ppages, dw->npages, dw->len, | |
| 4561 | + true); | |
| 4562 | + if (rc >= 0) { | |
| 4563 | +#ifdef CONFIG_CIFS_STATS2 | |
| 4564 | + mid->when_received = jiffies; | |
| 4565 | +#endif | |
| 4566 | + mid->callback(mid); | |
| 4567 | + } else { | |
| 4568 | + spin_lock(&GlobalMid_Lock); | |
| 4569 | + if (dw->server->tcpStatus == CifsNeedReconnect) { | |
| 4570 | + mid->mid_state = MID_RETRY_NEEDED; | |
| 4571 | + spin_unlock(&GlobalMid_Lock); | |
| 4572 | + mid->callback(mid); | |
| 4573 | + } else { | |
| 4574 | + mid->mid_state = MID_REQUEST_SUBMITTED; | |
| 4575 | + mid->mid_flags &= ~(MID_DELETED); | |
| 4576 | + list_add_tail(&mid->qhead, | |
| 4577 | + &dw->server->pending_mid_q); | |
| 4578 | + spin_unlock(&GlobalMid_Lock); | |
| 4579 | + } | |
| 4580 | + } | |
| 4523 | 4581 | cifs_mid_q_entry_release(mid); |
| 4524 | 4582 | } |
| 4525 | 4583 | |
| @@ -4622,7 +4680,7 @@ non_offloaded_decrypt: · 96 unmodified lines | ||
| 4622 | 4680 | (*mid)->decrypted = true; |
| 4623 | 4681 | rc = handle_read_data(server, *mid, buf, |
| 4624 | 4682 | server->vals->read_rsp_size, |
| 4625 | − pages, npages, len); | |
| 4683 | + pages, npages, len, false); | |
| 4626 | 4684 | } |
| 4627 | 4685 | |
| 4628 | 4686 | free_pages: |
| @@ -4765,7 +4823,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid) · 136 unmodified lines | ||
| 4765 | 4823 | char *buf = server->large_buf ? server->bigbuf : server->smallbuf; |
| 4766 | 4824 | |
| 4767 | 4825 | return handle_read_data(server, mid, buf, server->pdu_size, |
| 4768 | − NULL, 0, 0); | |
| 4826 | + NULL, 0, 0, false); | |
| 4769 | 4827 | } |
| 4770 | 4828 | |
| 4771 | 4829 | static int |
| @@ -21,6 +21,7 @@ LIST_HEAD(efivarfs_list); · 20 unmodified lines | ||
| 21 | 21 | static void efivarfs_evict_inode(struct inode *inode) |
| 22 | 22 | { |
| 23 | 23 | clear_inode(inode); |
| 24 | + kfree(inode->i_private); | |
| 24 | 25 | } |
| 25 | 26 | |
| 26 | 27 | static const struct super_operations efivarfs_ops = { |
| @@ -2695,7 +2695,8 @@ void ext4_insert_dentry(struct inode *inode, · 2694 unmodified lines | ||
| 2695 | 2695 | struct ext4_filename *fname); |
| 2696 | 2696 | static inline void ext4_update_dx_flag(struct inode *inode) |
| 2697 | 2697 | { |
| 2698 | − if (!ext4_has_feature_dir_index(inode->i_sb)) { | |
| 2698 | + if (!ext4_has_feature_dir_index(inode->i_sb) && | |
| 2699 | + ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) { | |
| 2699 | 2700 | /* ext4_iget() should have caught this... */ |
| 2700 | 2701 | WARN_ON_ONCE(ext4_has_feature_metadata_csum(inode->i_sb)); |
| 2701 | 2702 | ext4_clear_inode_flag(inode, EXT4_INODE_INDEX); |
| @@ -2638,10 +2638,6 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb, · 2637 unmodified lines | ||
| 2638 | 2638 | } else if (test_opt2(sb, DAX_INODE)) { |
| 2639 | 2639 | SEQ_OPTS_PUTS("dax=inode"); |
| 2640 | 2640 | } |
| 2641 | − | |
| 2642 | − if (test_opt2(sb, JOURNAL_FAST_COMMIT)) | |
| 2643 | − SEQ_OPTS_PUTS("fast_commit"); | |
| 2644 | − | |
| 2645 | 2641 | ext4_show_quota_options(seq, sb); |
| 2646 | 2642 | return 0; |
| 2647 | 2643 | } |
| @@ -205,6 +205,7 @@ struct fixed_file_ref_node { · 204 unmodified lines | ||
| 205 | 205 | struct list_head file_list; |
| 206 | 206 | struct fixed_file_data *file_data; |
| 207 | 207 | struct llist_node llist; |
| 208 | + bool done; | |
| 208 | 209 | }; |
| 209 | 210 | |
| 210 | 211 | struct fixed_file_data { |
| @@ -478,6 +479,7 @@ struct io_sr_msg { · 267 unmodified lines | ||
| 478 | 479 | struct io_open { |
| 479 | 480 | struct file *file; |
| 480 | 481 | int dfd; |
| 482 | + bool ignore_nonblock; | |
| 481 | 483 | struct filename *filename; |
| 482 | 484 | struct open_how how; |
| 483 | 485 | unsigned long nofile; |
| @@ -1311,22 +1313,6 @@ static bool io_grab_identity(struct io_kiocb *req) · 827 unmodified lines | ||
| 1311 | 1313 | return false; |
| 1312 | 1314 | req->work.flags |= IO_WQ_WORK_FSIZE; |
| 1313 | 1315 | } |
| 1314 | − | |
| 1315 | − if (!(req->work.flags & IO_WQ_WORK_FILES) && | |
| 1316 | − (def->work_flags & IO_WQ_WORK_FILES) && | |
| 1317 | − !(req->flags & REQ_F_NO_FILE_TABLE)) { | |
| 1318 | − if (id->files != current->files || | |
| 1319 | − id->nsproxy != current->nsproxy) | |
| 1320 | − return false; | |
| 1321 | − atomic_inc(&id->files->count); | |
| 1322 | − get_nsproxy(id->nsproxy); | |
| 1323 | − req->flags |= REQ_F_INFLIGHT; | |
| 1324 | − | |
| 1325 | − spin_lock_irq(&ctx->inflight_lock); | |
| 1326 | − list_add(&req->inflight_entry, &ctx->inflight_list); | |
| 1327 | − spin_unlock_irq(&ctx->inflight_lock); | |
| 1328 | − req->work.flags |= IO_WQ_WORK_FILES; | |
| 1329 | − } | |
| 1330 | 1316 | #ifdef CONFIG_BLK_CGROUP |
| 1331 | 1317 | if (!(req->work.flags & IO_WQ_WORK_BLKCG) && |
| 1332 | 1318 | (def->work_flags & IO_WQ_WORK_BLKCG)) { |
| @@ -1368,6 +1354,21 @@ static bool io_grab_identity(struct io_kiocb *req) · 35 unmodified lines | ||
| 1368 | 1354 | } |
| 1369 | 1355 | spin_unlock(¤t->fs->lock); |
| 1370 | 1356 | } |
| 1357 | + if (!(req->work.flags & IO_WQ_WORK_FILES) && | |
| 1358 | + (def->work_flags & IO_WQ_WORK_FILES) && | |
| 1359 | + !(req->flags & REQ_F_NO_FILE_TABLE)) { | |
| 1360 | + if (id->files != current->files || | |
| 1361 | + id->nsproxy != current->nsproxy) | |
| 1362 | + return false; | |
| 1363 | + atomic_inc(&id->files->count); | |
| 1364 | + get_nsproxy(id->nsproxy); | |
| 1365 | + req->flags |= REQ_F_INFLIGHT; | |
| 1366 | + | |
| 1367 | + spin_lock_irq(&ctx->inflight_lock); | |
| 1368 | + list_add(&req->inflight_entry, &ctx->inflight_list); | |
| 1369 | + spin_unlock_irq(&ctx->inflight_lock); | |
| 1370 | + req->work.flags |= IO_WQ_WORK_FILES; | |
| 1371 | + } | |
| 1371 | 1372 | |
| 1372 | 1373 | return true; |
| 1373 | 1374 | } |
| @@ -2577,7 +2578,6 @@ static bool io_resubmit_prep(struct io_kiocb *req, int error) · 1203 unmodified lines | ||
| 2577 | 2578 | } |
| 2578 | 2579 | end_req: |
| 2579 | 2580 | req_set_fail_links(req); |
| 2580 | − io_req_complete(req, ret); | |
| 2581 | 2581 | return false; |
| 2582 | 2582 | } |
| 2583 | 2583 | #endif |
| @@ -3192,7 +3192,7 @@ static void io_req_map_rw(struct io_kiocb *req, const struct iovec *iovec, · 608 unmodified lines | ||
| 3192 | 3192 | rw->free_iovec = iovec; |
| 3193 | 3193 | rw->bytes_done = 0; |
| 3194 | 3194 | /* can only be fixed buffers, no need to do anything */ |
| 3195 | − if (iter->type == ITER_BVEC) | |
| 3195 | + if (iov_iter_is_bvec(iter)) | |
| 3196 | 3196 | return; |
| 3197 | 3197 | if (!iovec) { |
| 3198 | 3198 | unsigned iov_off = 0; |
| @@ -3795,6 +3795,7 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe · 596 unmodified lines | ||
| 3795 | 3795 | return ret; |
| 3796 | 3796 | } |
| 3797 | 3797 | req->open.nofile = rlimit(RLIMIT_NOFILE); |
| 3798 | + req->open.ignore_nonblock = false; | |
| 3798 | 3799 | req->flags |= REQ_F_NEED_CLEANUP; |
| 3799 | 3800 | return 0; |
| 3800 | 3801 | } |
| @@ -3838,7 +3839,7 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock) · 37 unmodified lines | ||
| 3838 | 3839 | struct file *file; |
| 3839 | 3840 | int ret; |
| 3840 | 3841 | |
| 3841 | − if (force_nonblock) | |
| 3842 | + if (force_nonblock && !req->open.ignore_nonblock) | |
| 3842 | 3843 | return -EAGAIN; |
| 3843 | 3844 | |
| 3844 | 3845 | ret = build_open_flags(&req->open.how, &op); |
| @@ -3853,6 +3854,21 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock) · 8 unmodified lines | ||
| 3853 | 3854 | if (IS_ERR(file)) { |
| 3854 | 3855 | put_unused_fd(ret); |
| 3855 | 3856 | ret = PTR_ERR(file); |
| 3857 | + /* | |
| 3858 | + * A work-around to ensure that /proc/self works that way | |
| 3859 | + * that it should - if we get -EOPNOTSUPP back, then assume | |
| 3860 | + * that proc_self_get_link() failed us because we're in async | |
| 3861 | + * context. We should be safe to retry this from the task | |
| 3862 | + * itself with force_nonblock == false set, as it should not | |
| 3863 | + * block on lookup. Would be nice to know this upfront and | |
| 3864 | + * avoid the async dance, but doesn't seem feasible. | |
| 3865 | + */ | |
| 3866 | + if (ret == -EOPNOTSUPP && io_wq_current_is_worker()) { | |
| 3867 | + req->open.ignore_nonblock = true; | |
| 3868 | + refcount_inc(&req->refs); | |
| 3869 | + io_req_task_queue(req); | |
| 3870 | + return 0; | |
| 3871 | + } | |
| 3856 | 3872 | } else { |
| 3857 | 3873 | fsnotify_open(file); |
| 3858 | 3874 | fd_install(ret, file); |
| @@ -6957,9 +6973,7 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx) · 3098 unmodified lines | ||
| 6957 | 6973 | return -ENXIO; |
| 6958 | 6974 | |
| 6959 | 6975 | spin_lock(&data->lock); |
| 6960 | − if (!list_empty(&data->ref_list)) | |
| 6961 | − ref_node = list_first_entry(&data->ref_list, | |
| 6962 | − struct fixed_file_ref_node, node); | |
| 6976 | + ref_node = data->node; | |
| 6963 | 6977 | spin_unlock(&data->lock); |
| 6964 | 6978 | if (ref_node) |
| 6965 | 6979 | percpu_ref_kill(&ref_node->refs); |
| @@ -7308,10 +7322,6 @@ static void __io_file_put_work(struct fixed_file_ref_node *ref_node) · 342 unmodified lines | ||
| 7308 | 7322 | kfree(pfile); |
| 7309 | 7323 | } |
| 7310 | 7324 | |
| 7311 | − spin_lock(&file_data->lock); | |
| 7312 | − list_del(&ref_node->node); | |
| 7313 | − spin_unlock(&file_data->lock); | |
| 7314 | − | |
| 7315 | 7325 | percpu_ref_exit(&ref_node->refs); |
| 7316 | 7326 | kfree(ref_node); |
| 7317 | 7327 | percpu_ref_put(&file_data->refs); |
| @@ -7338,17 +7348,32 @@ static void io_file_put_work(struct work_struct *work) · 20 unmodified lines | ||
| 7338 | 7348 | static void io_file_data_ref_zero(struct percpu_ref *ref) |
| 7339 | 7349 | { |
| 7340 | 7350 | struct fixed_file_ref_node *ref_node; |
| 7351 | + struct fixed_file_data *data; | |
| 7341 | 7352 | struct io_ring_ctx *ctx; |
| 7342 | − bool first_add; | |
| 7353 | + bool first_add = false; | |
| 7343 | 7354 | int delay = HZ; |
| 7344 | 7355 | |
| 7345 | 7356 | ref_node = container_of(ref, struct fixed_file_ref_node, refs); |
| 7346 | − ctx = ref_node->file_data->ctx; | |
| 7357 | + data = ref_node->file_data; | |
| 7358 | + ctx = data->ctx; | |
| 7359 | + | |
| 7360 | + spin_lock(&data->lock); | |
| 7361 | + ref_node->done = true; | |
| 7347 | 7362 | |
| 7348 | − if (percpu_ref_is_dying(&ctx->file_data->refs)) | |
| 7363 | + while (!list_empty(&data->ref_list)) { | |
| 7364 | + ref_node = list_first_entry(&data->ref_list, | |
| 7365 | + struct fixed_file_ref_node, node); | |
| 7366 | + /* recycle ref nodes in order */ | |
| 7367 | + if (!ref_node->done) | |
| 7368 | + break; | |
| 7369 | + list_del(&ref_node->node); | |
| 7370 | + first_add |= llist_add(&ref_node->llist, &ctx->file_put_llist); | |
| 7371 | + } | |
| 7372 | + spin_unlock(&data->lock); | |
| 7373 | + | |
| 7374 | + if (percpu_ref_is_dying(&data->refs)) | |
| 7349 | 7375 | delay = 0; |
| 7350 | 7376 | |
| 7351 | − first_add = llist_add(&ref_node->llist, &ctx->file_put_llist); | |
| 7352 | 7377 | if (!delay) |
| 7353 | 7378 | mod_delayed_work(system_wq, &ctx->file_put_work, 0); |
| 7354 | 7379 | else if (first_add) |
| @@ -7372,6 +7397,7 @@ static struct fixed_file_ref_node *alloc_fixed_file_ref_node( · 17 unmodified lines | ||
| 7372 | 7397 | INIT_LIST_HEAD(&ref_node->node); |
| 7373 | 7398 | INIT_LIST_HEAD(&ref_node->file_list); |
| 7374 | 7399 | ref_node->file_data = ctx->file_data; |
| 7400 | + ref_node->done = false; | |
| 7375 | 7401 | return ref_node; |
| 7376 | 7402 | } |
| 7377 | 7403 | |
| @@ -7467,7 +7493,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg, · 89 unmodified lines | ||
| 7467 | 7493 | |
| 7468 | 7494 | file_data->node = ref_node; |
| 7469 | 7495 | spin_lock(&file_data->lock); |
| 7470 | − list_add(&ref_node->node, &file_data->ref_list); | |
| 7496 | + list_add_tail(&ref_node->node, &file_data->ref_list); | |
| 7471 | 7497 | spin_unlock(&file_data->lock); |
| 7472 | 7498 | percpu_ref_get(&file_data->refs); |
| 7473 | 7499 | return ret; |
| @@ -7626,7 +7652,7 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx, · 152 unmodified lines | ||
| 7626 | 7652 | if (needs_switch) { |
| 7627 | 7653 | percpu_ref_kill(&data->node->refs); |
| 7628 | 7654 | spin_lock(&data->lock); |
| 7629 | − list_add(&ref_node->node, &data->ref_list); | |
| 7655 | + list_add_tail(&ref_node->node, &data->ref_list); | |
| 7630 | 7656 | data->node = ref_node; |
| 7631 | 7657 | spin_unlock(&data->lock); |
| 7632 | 7658 | percpu_ref_get(&ctx->file_data->refs); |
| @@ -9225,14 +9251,16 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p, · 1592 unmodified lines | ||
| 9225 | 9251 | * to a power-of-two, if it isn't already. We do NOT impose |
| 9226 | 9252 | * any cq vs sq ring sizing. |
| 9227 | 9253 | */ |
| 9228 | − p->cq_entries = roundup_pow_of_two(p->cq_entries); | |
| 9229 | − if (p->cq_entries < p->sq_entries) | |
| 9254 | + if (!p->cq_entries) | |
| 9230 | 9255 | return -EINVAL; |
| 9231 | 9256 | if (p->cq_entries > IORING_MAX_CQ_ENTRIES) { |
| 9232 | 9257 | if (!(p->flags & IORING_SETUP_CLAMP)) |
| 9233 | 9258 | return -EINVAL; |
| 9234 | 9259 | p->cq_entries = IORING_MAX_CQ_ENTRIES; |
| 9235 | 9260 | } |
| 9261 | + p->cq_entries = roundup_pow_of_two(p->cq_entries); | |
| 9262 | + if (p->cq_entries < p->sq_entries) | |
| 9263 | + return -EINVAL; | |
| 9236 | 9264 | } else { |
| 9237 | 9265 | p->cq_entries = 2 * p->sq_entries; |
| 9238 | 9266 | } |
| @@ -566,12 +566,14 @@ static int __jbd2_journal_force_commit(journal_t *journal) · 565 unmodified lines | ||
| 566 | 566 | } |
| 567 | 567 | |
| 568 | 568 | /** |
| 569 | − * Force and wait upon a commit if the calling process is not within | |
| 570 | − * transaction. This is used for forcing out undo-protected data which contains | |
| 571 | − * bitmaps, when the fs is running out of space. | |
| 569 | + * jbd2_journal_force_commit_nested - Force and wait upon a commit if the | |
| 570 | + * calling process is not within transaction. | |
| 572 | 571 | * |
| 573 | 572 | * @journal: journal to force |
| 574 | 573 | * Returns true if progress was made. |
| 574 | + * | |
| 575 | + * This is used for forcing out undo-protected data which contains | |
| 576 | + * bitmaps, when the fs is running out of space. | |
| 575 | 577 | */ |
| 576 | 578 | int jbd2_journal_force_commit_nested(journal_t *journal) |
| 577 | 579 | { |
| @@ -582,7 +584,7 @@ int jbd2_journal_force_commit_nested(journal_t *journal) · 4 unmodified lines | ||
| 582 | 584 | } |
| 583 | 585 | |
| 584 | 586 | /** |
| 585 | − * int journal_force_commit() - force any uncommitted transactions | |
| 587 | + * jbd2_journal_force_commit() - force any uncommitted transactions | |
| 586 | 588 | * @journal: journal to force |
| 587 | 589 | * |
| 588 | 590 | * Caller want unconditional commit. We can only force the running transaction |
| @@ -1881,7 +1883,7 @@ static int load_superblock(journal_t *journal) · 1292 unmodified lines | ||
| 1881 | 1883 | |
| 1882 | 1884 | |
| 1883 | 1885 | /** |
| 1884 | − * int jbd2_journal_load() - Read journal from disk. | |
| 1886 | + * jbd2_journal_load() - Read journal from disk. | |
| 1885 | 1887 | * @journal: Journal to act on. |
| 1886 | 1888 | * |
| 1887 | 1889 | * Given a journal_t structure which tells us which disk blocks contain |
| @@ -1951,7 +1953,7 @@ recovery_error: · 63 unmodified lines | ||
| 1951 | 1953 | } |
| 1952 | 1954 | |
| 1953 | 1955 | /** |
| 1954 | − * void jbd2_journal_destroy() - Release a journal_t structure. | |
| 1956 | + * jbd2_journal_destroy() - Release a journal_t structure. | |
| 1955 | 1957 | * @journal: Journal to act on. |
| 1956 | 1958 | * |
| 1957 | 1959 | * Release a journal_t structure once it is no longer in use by the |
| @@ -2028,7 +2030,7 @@ int jbd2_journal_destroy(journal_t *journal) · 70 unmodified lines | ||
| 2028 | 2030 | |
| 2029 | 2031 | |
| 2030 | 2032 | /** |
| 2031 | − *int jbd2_journal_check_used_features() - Check if features specified are used. | |
| 2033 | + * jbd2_journal_check_used_features() - Check if features specified are used. | |
| 2032 | 2034 | * @journal: Journal to check. |
| 2033 | 2035 | * @compat: bitmask of compatible features |
| 2034 | 2036 | * @ro: bitmask of features that force read-only mount |
| @@ -2063,7 +2065,7 @@ int jbd2_journal_check_used_features(journal_t *journal, unsigned long compat, · 28 unmodified lines | ||
| 2063 | 2065 | } |
| 2064 | 2066 | |
| 2065 | 2067 | /** |
| 2066 | − * int jbd2_journal_check_available_features() - Check feature set in journalling layer | |
| 2068 | + * jbd2_journal_check_available_features() - Check feature set in journalling layer | |
| 2067 | 2069 | * @journal: Journal to check. |
| 2068 | 2070 | * @compat: bitmask of compatible features |
| 2069 | 2071 | * @ro: bitmask of features that force read-only mount |
| @@ -2126,7 +2128,7 @@ jbd2_journal_initialize_fast_commit(journal_t *journal) · 56 unmodified lines | ||
| 2126 | 2128 | } |
| 2127 | 2129 | |
| 2128 | 2130 | /** |
| 2129 | − * int jbd2_journal_set_features() - Mark a given journal feature in the superblock | |
| 2131 | + * jbd2_journal_set_features() - Mark a given journal feature in the superblock | |
| 2130 | 2132 | * @journal: Journal to act on. |
| 2131 | 2133 | * @compat: bitmask of compatible features |
| 2132 | 2134 | * @ro: bitmask of features that force read-only mount |
| @@ -2217,7 +2219,7 @@ int jbd2_journal_set_features(journal_t *journal, unsigned long compat, · 84 unmodified lines | ||
| 2217 | 2219 | } |
| 2218 | 2220 | |
| 2219 | 2221 | /* |
| 2220 | − * jbd2_journal_clear_features () - Clear a given journal feature in the | |
| 2222 | + * jbd2_journal_clear_features() - Clear a given journal feature in the | |
| 2221 | 2223 | * superblock |
| 2222 | 2224 | * @journal: Journal to act on. |
| 2223 | 2225 | * @compat: bitmask of compatible features |
| @@ -2246,7 +2248,7 @@ void jbd2_journal_clear_features(journal_t *journal, unsigned long compat, · 22 unmodified lines | ||
| 2246 | 2248 | EXPORT_SYMBOL(jbd2_journal_clear_features); |
| 2247 | 2249 | |
| 2248 | 2250 | /** |
| 2249 | − * int jbd2_journal_flush () - Flush journal | |
| 2251 | + * jbd2_journal_flush() - Flush journal | |
| 2250 | 2252 | * @journal: Journal to act on. |
| 2251 | 2253 | * |
| 2252 | 2254 | * Flush all data for a given journal to disk and empty the journal. |
| @@ -2321,7 +2323,7 @@ out: · 68 unmodified lines | ||
| 2321 | 2323 | } |
| 2322 | 2324 | |
| 2323 | 2325 | /** |
| 2324 | − * int jbd2_journal_wipe() - Wipe journal contents | |
| 2326 | + * jbd2_journal_wipe() - Wipe journal contents | |
| 2325 | 2327 | * @journal: Journal to act on. |
| 2326 | 2328 | * @write: flag (see below) |
| 2327 | 2329 | * |
| @@ -2362,7 +2364,7 @@ int jbd2_journal_wipe(journal_t *journal, int write) · 34 unmodified lines | ||
| 2362 | 2364 | } |
| 2363 | 2365 | |
| 2364 | 2366 | /** |
| 2365 | − * void jbd2_journal_abort () - Shutdown the journal immediately. | |
| 2367 | + * jbd2_journal_abort () - Shutdown the journal immediately. | |
| 2366 | 2368 | * @journal: the journal to shutdown. |
| 2367 | 2369 | * @errno: an error number to record in the journal indicating |
| 2368 | 2370 | * the reason for the shutdown. |
| @@ -2453,7 +2455,7 @@ void jbd2_journal_abort(journal_t *journal, int errno) · 84 unmodified lines | ||
| 2453 | 2455 | } |
| 2454 | 2456 | |
| 2455 | 2457 | /** |
| 2456 | − * int jbd2_journal_errno () - returns the journal's error state. | |
| 2458 | + * jbd2_journal_errno() - returns the journal's error state. | |
| 2457 | 2459 | * @journal: journal to examine. |
| 2458 | 2460 | * |
| 2459 | 2461 | * This is the errno number set with jbd2_journal_abort(), the last |
| @@ -2477,7 +2479,7 @@ int jbd2_journal_errno(journal_t *journal) · 17 unmodified lines | ||
| 2477 | 2479 | } |
| 2478 | 2480 | |
| 2479 | 2481 | /** |
| 2480 | − * int jbd2_journal_clear_err () - clears the journal's error state | |
| 2482 | + * jbd2_journal_clear_err() - clears the journal's error state | |
| 2481 | 2483 | * @journal: journal to act on. |
| 2482 | 2484 | * |
| 2483 | 2485 | * An error must be cleared or acked to take a FS out of readonly |
| @@ -2497,7 +2499,7 @@ int jbd2_journal_clear_err(journal_t *journal) · 13 unmodified lines | ||
| 2497 | 2499 | } |
| 2498 | 2500 | |
| 2499 | 2501 | /** |
| 2500 | − * void jbd2_journal_ack_err() - Ack journal err. | |
| 2502 | + * jbd2_journal_ack_err() - Ack journal err. | |
| 2501 | 2503 | * @journal: journal to act on. |
| 2502 | 2504 | * |
| 2503 | 2505 | * An error must be cleared or acked to take a FS out of readonly |
| @@ -519,7 +519,7 @@ EXPORT_SYMBOL(jbd2__journal_start); · 518 unmodified lines | ||
| 519 | 519 | |
| 520 | 520 | |
| 521 | 521 | /** |
| 522 | − * handle_t *jbd2_journal_start() - Obtain a new handle. | |
| 522 | + * jbd2_journal_start() - Obtain a new handle. | |
| 523 | 523 | * @journal: Journal to start transaction on. |
| 524 | 524 | * @nblocks: number of block buffer we might modify |
| 525 | 525 | * |
| @@ -566,7 +566,7 @@ void jbd2_journal_free_reserved(handle_t *handle) · 40 unmodified lines | ||
| 566 | 566 | EXPORT_SYMBOL(jbd2_journal_free_reserved); |
| 567 | 567 | |
| 568 | 568 | /** |
| 569 | − * int jbd2_journal_start_reserved() - start reserved handle | |
| 569 | + * jbd2_journal_start_reserved() - start reserved handle | |
| 570 | 570 | * @handle: handle to start |
| 571 | 571 | * @type: for handle statistics |
| 572 | 572 | * @line_no: for handle statistics |
| @@ -620,7 +620,7 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type, · 47 unmodified lines | ||
| 620 | 620 | EXPORT_SYMBOL(jbd2_journal_start_reserved); |
| 621 | 621 | |
| 622 | 622 | /** |
| 623 | − * int jbd2_journal_extend() - extend buffer credits. | |
| 623 | + * jbd2_journal_extend() - extend buffer credits. | |
| 624 | 624 | * @handle: handle to 'extend' |
| 625 | 625 | * @nblocks: nr blocks to try to extend by. |
| 626 | 626 | * @revoke_records: number of revoke records to try to extend by. |
| @@ -745,7 +745,7 @@ static void stop_this_handle(handle_t *handle) · 118 unmodified lines | ||
| 745 | 745 | } |
| 746 | 746 | |
| 747 | 747 | /** |
| 748 | − * int jbd2_journal_restart() - restart a handle . | |
| 748 | + * jbd2__journal_restart() - restart a handle . | |
| 749 | 749 | * @handle: handle to restart |
| 750 | 750 | * @nblocks: nr credits requested |
| 751 | 751 | * @revoke_records: number of revoke record credits requested |
| @@ -815,7 +815,7 @@ int jbd2_journal_restart(handle_t *handle, int nblocks) · 63 unmodified lines | ||
| 815 | 815 | EXPORT_SYMBOL(jbd2_journal_restart); |
| 816 | 816 | |
| 817 | 817 | /** |
| 818 | − * void jbd2_journal_lock_updates () - establish a transaction barrier. | |
| 818 | + * jbd2_journal_lock_updates () - establish a transaction barrier. | |
| 819 | 819 | * @journal: Journal to establish a barrier on. |
| 820 | 820 | * |
| 821 | 821 | * This locks out any further updates from being started, and blocks |
| @@ -874,7 +874,7 @@ void jbd2_journal_lock_updates(journal_t *journal) · 52 unmodified lines | ||
| 874 | 874 | } |
| 875 | 875 | |
| 876 | 876 | /** |
| 877 | − * void jbd2_journal_unlock_updates (journal_t* journal) - release barrier | |
| 877 | + * jbd2_journal_unlock_updates () - release barrier | |
| 878 | 878 | * @journal: Journal to release the barrier on. |
| 879 | 879 | * |
| 880 | 880 | * Release a transaction barrier obtained with jbd2_journal_lock_updates(). |
| @@ -1182,7 +1182,8 @@ out: · 301 unmodified lines | ||
| 1182 | 1182 | } |
| 1183 | 1183 | |
| 1184 | 1184 | /** |
| 1185 | − * int jbd2_journal_get_write_access() - notify intent to modify a buffer for metadata (not data) update. | |
| 1185 | + * jbd2_journal_get_write_access() - notify intent to modify a buffer | |
| 1186 | + * for metadata (not data) update. | |
| 1186 | 1187 | * @handle: transaction to add buffer modifications to |
| 1187 | 1188 | * @bh: bh to be used for metadata writes |
| 1188 | 1189 | * |
| @@ -1226,7 +1227,7 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh) · 37 unmodified lines | ||
| 1226 | 1227 | * unlocked buffer beforehand. */ |
| 1227 | 1228 | |
| 1228 | 1229 | /** |
| 1229 | − * int jbd2_journal_get_create_access () - notify intent to use newly created bh | |
| 1230 | + * jbd2_journal_get_create_access () - notify intent to use newly created bh | |
| 1230 | 1231 | * @handle: transaction to new buffer to |
| 1231 | 1232 | * @bh: new buffer. |
| 1232 | 1233 | * |
| @@ -1306,7 +1307,7 @@ out: · 73 unmodified lines | ||
| 1306 | 1307 | } |
| 1307 | 1308 | |
| 1308 | 1309 | /** |
| 1309 | − * int jbd2_journal_get_undo_access() - Notify intent to modify metadata with | |
| 1310 | + * jbd2_journal_get_undo_access() - Notify intent to modify metadata with | |
| 1310 | 1311 | * non-rewindable consequences |
| 1311 | 1312 | * @handle: transaction |
| 1312 | 1313 | * @bh: buffer to undo |
| @@ -1383,7 +1384,7 @@ out: · 70 unmodified lines | ||
| 1383 | 1384 | } |
| 1384 | 1385 | |
| 1385 | 1386 | /** |
| 1386 | − * void jbd2_journal_set_triggers() - Add triggers for commit writeout | |
| 1387 | + * jbd2_journal_set_triggers() - Add triggers for commit writeout | |
| 1387 | 1388 | * @bh: buffer to trigger on |
| 1388 | 1389 | * @type: struct jbd2_buffer_trigger_type containing the trigger(s). |
| 1389 | 1390 | * |
| @@ -1425,7 +1426,7 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh, · 35 unmodified lines | ||
| 1425 | 1426 | } |
| 1426 | 1427 | |
| 1427 | 1428 | /** |
| 1428 | − * int jbd2_journal_dirty_metadata() - mark a buffer as containing dirty metadata | |
| 1429 | + * jbd2_journal_dirty_metadata() - mark a buffer as containing dirty metadata | |
| 1429 | 1430 | * @handle: transaction to add buffer to. |
| 1430 | 1431 | * @bh: buffer to mark |
| 1431 | 1432 | * |
| @@ -1593,7 +1594,7 @@ out: · 161 unmodified lines | ||
| 1593 | 1594 | } |
| 1594 | 1595 | |
| 1595 | 1596 | /** |
| 1596 | − * void jbd2_journal_forget() - bforget() for potentially-journaled buffers. | |
| 1597 | + * jbd2_journal_forget() - bforget() for potentially-journaled buffers. | |
| 1597 | 1598 | * @handle: transaction handle |
| 1598 | 1599 | * @bh: bh to 'forget' |
| 1599 | 1600 | * |
| @@ -1762,7 +1763,7 @@ drop: · 162 unmodified lines | ||
| 1762 | 1763 | } |
| 1763 | 1764 | |
| 1764 | 1765 | /** |
| 1765 | − * int jbd2_journal_stop() - complete a transaction | |
| 1766 | + * jbd2_journal_stop() - complete a transaction | |
| 1766 | 1767 | * @handle: transaction to complete. |
| 1767 | 1768 | * |
| 1768 | 1769 | * All done for a particular handle. |
| @@ -2080,7 +2081,7 @@ out: · 311 unmodified lines | ||
| 2080 | 2081 | } |
| 2081 | 2082 | |
| 2082 | 2083 | /** |
| 2083 | − * int jbd2_journal_try_to_free_buffers() - try to free page buffers. | |
| 2084 | + * jbd2_journal_try_to_free_buffers() - try to free page buffers. | |
| 2084 | 2085 | * @journal: journal for operation |
| 2085 | 2086 | * @page: to try and free |
| 2086 | 2087 | * |
| @@ -2411,7 +2412,7 @@ zap_buffer_unlocked: · 324 unmodified lines | ||
| 2411 | 2412 | } |
| 2412 | 2413 | |
| 2413 | 2414 | /** |
| 2414 | − * void jbd2_journal_invalidatepage() | |
| 2415 | + * jbd2_journal_invalidatepage() | |
| 2415 | 2416 | * @journal: journal to use for flush... |
| 2416 | 2417 | * @page: page to flush |
| 2417 | 2418 | * @offset: start of the range to invalidate |
| @@ -959,7 +959,7 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, · 958 unmodified lines | ||
| 959 | 959 | size_t len, loff_t *ppos) |
| 960 | 960 | { |
| 961 | 961 | struct simple_attr *attr; |
| 962 | − u64 val; | |
| 962 | + unsigned long long val; | |
| 963 | 963 | size_t size; |
| 964 | 964 | ssize_t ret; |
| 965 | 965 | |
| @@ -977,7 +977,9 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, · 11 unmodified lines | ||
| 977 | 977 | goto out; |
| 978 | 978 | |
| 979 | 979 | attr->set_buf[size] = '\0'; |
| 980 | − val = simple_strtoll(attr->set_buf, NULL, 0); | |
| 980 | + ret = kstrtoull(attr->set_buf, 0, &val); | |
| 981 | + if (ret) | |
| 982 | + goto out; | |
| 981 | 983 | ret = attr->set(attr->data, val); |
| 982 | 984 | if (ret == 0) |
| 983 | 985 | ret = len; /* on success, claim we got the whole input */ |
| @@ -178,6 +178,7 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, · 177 unmodified lines | ||
| 178 | 178 | struct inode *inode = d_inode(dentry); |
| 179 | 179 | struct dentry *parent; |
| 180 | 180 | bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED; |
| 181 | + bool parent_needed, parent_interested; | |
| 181 | 182 | __u32 p_mask; |
| 182 | 183 | struct inode *p_inode = NULL; |
| 183 | 184 | struct name_snapshot name; |
| @@ -193,7 +194,8 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, · 9 unmodified lines | ||
| 193 | 194 | return 0; |
| 194 | 195 | |
| 195 | 196 | parent = NULL; |
| 196 | − if (!parent_watched && !fsnotify_event_needs_parent(inode, mnt, mask)) | |
| 197 | + parent_needed = fsnotify_event_needs_parent(inode, mnt, mask); | |
| 198 | + if (!parent_watched && !parent_needed) | |
| 197 | 199 | goto notify; |
| 198 | 200 | |
| 199 | 201 | /* Does parent inode care about events on children? */ |
| @@ -205,17 +207,17 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, · 5 unmodified lines | ||
| 205 | 207 | |
| 206 | 208 | /* |
| 207 | 209 | * Include parent/name in notification either if some notification |
| 208 | − * groups require parent info (!parent_watched case) or the parent is | |
| 209 | − * interested in this event. | |
| 210 | + * groups require parent info or the parent is interested in this event. | |
| 210 | 211 | */ |
| 211 | − if (!parent_watched || (mask & p_mask & ALL_FSNOTIFY_EVENTS)) { | |
| 212 | + parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS; | |
| 213 | + if (parent_needed || parent_interested) { | |
| 212 | 214 | /* When notifying parent, child should be passed as data */ |
| 213 | 215 | WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type)); |
| 214 | 216 | |
| 215 | 217 | /* Notify both parent and child with child name info */ |
| 216 | 218 | take_dentry_name_snapshot(&name, dentry); |
| 217 | 219 | file_name = &name.name; |
| 218 | − if (parent_watched) | |
| 220 | + if (parent_interested) | |
| 219 | 221 | mask |= FS_EVENT_ON_CHILD; |
| 220 | 222 | } |
| 221 | 223 | |
| @@ -16,6 +16,13 @@ static const char *proc_self_get_link(struct dentry *dentry, · 15 unmodified lines | ||
| 16 | 16 | pid_t tgid = task_tgid_nr_ns(current, ns); |
| 17 | 17 | char *name; |
| 18 | 18 | |
| 19 | + /* | |
| 20 | + * Not currently supported. Once we can inherit all of struct pid, | |
| 21 | + * we can allow this. | |
| 22 | + */ | |
| 23 | + if (current->flags & PF_KTHREAD) | |
| 24 | + return ERR_PTR(-EOPNOTSUPP); | |
| 25 | + | |
| 19 | 26 | if (!tgid) |
| 20 | 27 | return ERR_PTR(-ENOENT); |
| 21 | 28 | /* max length of unsigned int in decimal + NULL term */ |
| @@ -515,7 +515,7 @@ xfs_attr_copy_value( · 514 unmodified lines | ||
| 515 | 515 | *========================================================================*/ |
| 516 | 516 | |
| 517 | 517 | /* |
| 518 | − * Query whether the requested number of additional bytes of extended | |
| 518 | + * Query whether the total requested number of attr fork bytes of extended | |
| 519 | 519 | * attribute space will be able to fit inline. |
| 520 | 520 | * |
| 521 | 521 | * Returns zero if not, else the di_forkoff fork offset to be used in the |
| @@ -535,6 +535,12 @@ xfs_attr_shortform_bytesfit( · 13 unmodified lines | ||
| 535 | 535 | int maxforkoff; |
| 536 | 536 | int offset; |
| 537 | 537 | |
| 538 | + /* | |
| 539 | + * Check if the new size could fit at all first: | |
| 540 | + */ | |
| 541 | + if (bytes > XFS_LITINO(mp)) | |
| 542 | + return 0; | |
| 543 | + | |
| 538 | 544 | /* rounded down */ |
| 539 | 545 | offset = (XFS_LITINO(mp) - bytes) >> 3; |
| 540 | 546 | |
| @@ -243,8 +243,8 @@ xfs_rmapbt_key_diff( · 242 unmodified lines | ||
| 243 | 243 | else if (y > x) |
| 244 | 244 | return -1; |
| 245 | 245 | |
| 246 | − x = be64_to_cpu(kp->rm_offset); | |
| 247 | − y = xfs_rmap_irec_offset_pack(rec); | |
| 246 | + x = XFS_RMAP_OFF(be64_to_cpu(kp->rm_offset)); | |
| 247 | + y = rec->rm_offset; | |
| 248 | 248 | if (x > y) |
| 249 | 249 | return 1; |
| 250 | 250 | else if (y > x) |
| @@ -275,8 +275,8 @@ xfs_rmapbt_diff_two_keys( · 24 unmodified lines | ||
| 275 | 275 | else if (y > x) |
| 276 | 276 | return -1; |
| 277 | 277 | |
| 278 | − x = be64_to_cpu(kp1->rm_offset); | |
| 279 | − y = be64_to_cpu(kp2->rm_offset); | |
| 278 | + x = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset)); | |
| 279 | + y = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset)); | |
| 280 | 280 | if (x > y) |
| 281 | 281 | return 1; |
| 282 | 282 | else if (y > x) |
| @@ -390,8 +390,8 @@ xfs_rmapbt_keys_inorder( · 107 unmodified lines | ||
| 390 | 390 | return 1; |
| 391 | 391 | else if (a > b) |
| 392 | 392 | return 0; |
| 393 | − a = be64_to_cpu(k1->rmap.rm_offset); | |
| 394 | − b = be64_to_cpu(k2->rmap.rm_offset); | |
| 393 | + a = XFS_RMAP_OFF(be64_to_cpu(k1->rmap.rm_offset)); | |
| 394 | + b = XFS_RMAP_OFF(be64_to_cpu(k2->rmap.rm_offset)); | |
| 395 | 395 | if (a <= b) |
| 396 | 396 | return 1; |
| 397 | 397 | return 0; |
| @@ -420,8 +420,8 @@ xfs_rmapbt_recs_inorder( · 22 unmodified lines | ||
| 420 | 420 | return 1; |
| 421 | 421 | else if (a > b) |
| 422 | 422 | return 0; |
| 423 | − a = be64_to_cpu(r1->rmap.rm_offset); | |
| 424 | − b = be64_to_cpu(r2->rmap.rm_offset); | |
| 423 | + a = XFS_RMAP_OFF(be64_to_cpu(r1->rmap.rm_offset)); | |
| 424 | + b = XFS_RMAP_OFF(be64_to_cpu(r2->rmap.rm_offset)); | |
| 425 | 425 | if (a <= b) |
| 426 | 426 | return 1; |
| 427 | 427 | return 0; |
| @@ -218,13 +218,13 @@ xchk_bmap_xref_rmap( · 217 unmodified lines | ||
| 218 | 218 | * which doesn't track unwritten state. |
| 219 | 219 | */ |
| 220 | 220 | if (owner != XFS_RMAP_OWN_COW && |
| 221 | − irec->br_state == XFS_EXT_UNWRITTEN && | |
| 222 | − !(rmap.rm_flags & XFS_RMAP_UNWRITTEN)) | |
| 221 | + !!(irec->br_state == XFS_EXT_UNWRITTEN) != | |
| 222 | + !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN)) | |
| 223 | 223 | xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, |
| 224 | 224 | irec->br_startoff); |
| 225 | 225 | |
| 226 | − if (info->whichfork == XFS_ATTR_FORK && | |
| 227 | − !(rmap.rm_flags & XFS_RMAP_ATTR_FORK)) | |
| 226 | + if (!!(info->whichfork == XFS_ATTR_FORK) != | |
| 227 | + !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK)) | |
| 228 | 228 | xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, |
| 229 | 229 | irec->br_startoff); |
| 230 | 230 | if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK) |
| @@ -452,32 +452,41 @@ xchk_btree_check_minrecs( · 451 unmodified lines | ||
| 452 | 452 | int level, |
| 453 | 453 | struct xfs_btree_block *block) |
| 454 | 454 | { |
| 455 | − unsigned int numrecs; | |
| 456 | − int ok_level; | |
| 457 | − | |
| 458 | − numrecs = be16_to_cpu(block->bb_numrecs); | |
| 455 | + struct xfs_btree_cur *cur = bs->cur; | |
| 456 | + unsigned int root_level = cur->bc_nlevels - 1; | |
| 457 | + unsigned int numrecs = be16_to_cpu(block->bb_numrecs); | |
| 459 | 458 | |
| 460 | 459 | /* More records than minrecs means the block is ok. */ |
| 461 | − if (numrecs >= bs->cur->bc_ops->get_minrecs(bs->cur, level)) | |
| 460 | + if (numrecs >= cur->bc_ops->get_minrecs(cur, level)) | |
| 462 | 461 | return; |
| 463 | 462 | |
| 464 | 463 | /* |
| 465 | − * Certain btree blocks /can/ have fewer than minrecs records. Any | |
| 466 | − * level greater than or equal to the level of the highest dedicated | |
| 467 | − * btree block are allowed to violate this constraint. | |
| 468 | − * | |
| 469 | − * For a btree rooted in a block, the btree root can have fewer than | |
| 470 | − * minrecs records. If the btree is rooted in an inode and does not | |
| 471 | − * store records in the root, the direct children of the root and the | |
| 472 | − * root itself can have fewer than minrecs records. | |
| 464 | + * For btrees rooted in the inode, it's possible that the root block | |
| 465 | + * contents spilled into a regular ondisk block because there wasn't | |
| 466 | + * enough space in the inode root. The number of records in that | |
| 467 | + * child block might be less than the standard minrecs, but that's ok | |
| 468 | + * provided that there's only one direct child of the root. | |
| 473 | 469 | */ |
| 474 | − ok_level = bs->cur->bc_nlevels - 1; | |
| 475 | − if (bs->cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) | |
| 476 | − ok_level--; | |
| 477 | − if (level >= ok_level) | |
| 470 | + if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && | |
| 471 | + level == cur->bc_nlevels - 2) { | |
| 472 | + struct xfs_btree_block *root_block; | |
| 473 | + struct xfs_buf *root_bp; | |
| 474 | + int root_maxrecs; | |
| 475 | + | |
| 476 | + root_block = xfs_btree_get_block(cur, root_level, &root_bp); | |
| 477 | + root_maxrecs = cur->bc_ops->get_dmaxrecs(cur, root_level); | |
| 478 | + if (be16_to_cpu(root_block->bb_numrecs) != 1 || | |
| 479 | + numrecs <= root_maxrecs) | |
| 480 | + xchk_btree_set_corrupt(bs->sc, cur, level); | |
| 478 | 481 | return; |
| 482 | + } | |
| 479 | 483 | |
| 480 | − xchk_btree_set_corrupt(bs->sc, bs->cur, level); | |
| 484 | + /* | |
| 485 | + * Otherwise, only the root level is allowed to have fewer than minrecs | |
| 486 | + * records or keyptrs. | |
| 487 | + */ | |
| 488 | + if (level < root_level) | |
| 489 | + xchk_btree_set_corrupt(bs->sc, cur, level); | |
| 481 | 490 | } |
| 482 | 491 | |
| 483 | 492 | /* |
| @@ -558,14 +558,27 @@ xchk_directory_leaf1_bestfree( · 557 unmodified lines | ||
| 558 | 558 | /* Check all the bestfree entries. */ |
| 559 | 559 | for (i = 0; i < bestcount; i++, bestp++) { |
| 560 | 560 | best = be16_to_cpu(*bestp); |
| 561 | − if (best == NULLDATAOFF) | |
| 562 | − continue; | |
| 563 | 561 | error = xfs_dir3_data_read(sc->tp, sc->ip, |
| 564 | − i * args->geo->fsbcount, 0, &dbp); | |
| 562 | + xfs_dir2_db_to_da(args->geo, i), | |
| 563 | + XFS_DABUF_MAP_HOLE_OK, | |
| 564 | + &dbp); | |
| 565 | 565 | if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, |
| 566 | 566 | &error)) |
| 567 | 567 | break; |
| 568 | − xchk_directory_check_freesp(sc, lblk, dbp, best); | |
| 568 | + | |
| 569 | + if (!dbp) { | |
| 570 | + if (best != NULLDATAOFF) { | |
| 571 | + xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, | |
| 572 | + lblk); | |
| 573 | + break; | |
| 574 | + } | |
| 575 | + continue; | |
| 576 | + } | |
| 577 | + | |
| 578 | + if (best == NULLDATAOFF) | |
| 579 | + xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); | |
| 580 | + else | |
| 581 | + xchk_directory_check_freesp(sc, lblk, dbp, best); | |
| 569 | 582 | xfs_trans_brelse(sc->tp, dbp); |
| 570 | 583 | if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) |
| 571 | 584 | break; |
| @@ -706,6 +706,23 @@ relock: · 705 unmodified lines | ||
| 706 | 706 | return 0; |
| 707 | 707 | } |
| 708 | 708 | |
| 709 | +/* | |
| 710 | + * Check that the imap we are going to return to the caller spans the entire | |
| 711 | + * range that the caller requested for the IO. | |
| 712 | + */ | |
| 713 | +static bool | |
| 714 | +imap_spans_range( | |
| 715 | + struct xfs_bmbt_irec *imap, | |
| 716 | + xfs_fileoff_t offset_fsb, | |
| 717 | + xfs_fileoff_t end_fsb) | |
| 718 | +{ | |
| 719 | + if (imap->br_startoff > offset_fsb) | |
| 720 | + return false; | |
| 721 | + if (imap->br_startoff + imap->br_blockcount < end_fsb) | |
| 722 | + return false; | |
| 723 | + return true; | |
| 724 | +} | |
| 725 | + | |
| 709 | 726 | static int |
| 710 | 727 | xfs_direct_write_iomap_begin( |
| 711 | 728 | struct inode *inode, |
| @@ -766,6 +783,18 @@ xfs_direct_write_iomap_begin( · 54 unmodified lines | ||
| 766 | 783 | if (imap_needs_alloc(inode, flags, &imap, nimaps)) |
| 767 | 784 | goto allocate_blocks; |
| 768 | 785 | |
| 786 | + /* | |
| 787 | + * NOWAIT IO needs to span the entire requested IO with a single map so | |
| 788 | + * that we avoid partial IO failures due to the rest of the IO range not | |
| 789 | + * covered by this map triggering an EAGAIN condition when it is | |
| 790 | + * subsequently mapped and aborting the IO. | |
| 791 | + */ | |
| 792 | + if ((flags & IOMAP_NOWAIT) && | |
| 793 | + !imap_spans_range(&imap, offset_fsb, end_fsb)) { | |
| 794 | + error = -EAGAIN; | |
| 795 | + goto out_unlock; | |
| 796 | + } | |
| 797 | + | |
| 769 | 798 | xfs_iunlock(ip, lockmode); |
| 770 | 799 | trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap); |
| 771 | 800 | return xfs_bmbt_to_iomap(ip, iomap, &imap, iomap_flags); |
| @@ -55,6 +55,9 @@ struct xfs_iwalk_ag { · 54 unmodified lines | ||
| 55 | 55 | /* Where do we start the traversal? */ |
| 56 | 56 | xfs_ino_t startino; |
| 57 | 57 | |
| 58 | + /* What was the last inode number we saw when iterating the inobt? */ | |
| 59 | + xfs_ino_t lastino; | |
| 60 | + | |
| 58 | 61 | /* Array of inobt records we cache. */ |
| 59 | 62 | struct xfs_inobt_rec_incore *recs; |
| 60 | 63 | |
| @@ -301,6 +304,9 @@ xfs_iwalk_ag_start( · 240 unmodified lines | ||
| 301 | 304 | if (XFS_IS_CORRUPT(mp, *has_more != 1)) |
| 302 | 305 | return -EFSCORRUPTED; |
| 303 | 306 | |
| 307 | + iwag->lastino = XFS_AGINO_TO_INO(mp, agno, | |
| 308 | + irec->ir_startino + XFS_INODES_PER_CHUNK - 1); | |
| 309 | + | |
| 304 | 310 | /* |
| 305 | 311 | * If the LE lookup yielded an inobt record before the cursor position, |
| 306 | 312 | * skip it and see if there's another one after it. |
| @@ -347,15 +353,17 @@ xfs_iwalk_run_callbacks( · 40 unmodified lines | ||
| 347 | 353 | struct xfs_mount *mp = iwag->mp; |
| 348 | 354 | struct xfs_trans *tp = iwag->tp; |
| 349 | 355 | struct xfs_inobt_rec_incore *irec; |
| 350 | − xfs_agino_t restart; | |
| 356 | + xfs_agino_t next_agino; | |
| 351 | 357 | int error; |
| 352 | 358 | |
| 359 | + next_agino = XFS_INO_TO_AGINO(mp, iwag->lastino) + 1; | |
| 360 | + | |
| 353 | 361 | ASSERT(iwag->nr_recs > 0); |
| 354 | 362 | |
| 355 | 363 | /* Delete cursor but remember the last record we cached... */ |
| 356 | 364 | xfs_iwalk_del_inobt(tp, curpp, agi_bpp, 0); |
| 357 | 365 | irec = &iwag->recs[iwag->nr_recs - 1]; |
| 358 | − restart = irec->ir_startino + XFS_INODES_PER_CHUNK - 1; | |
| 366 | + ASSERT(next_agino == irec->ir_startino + XFS_INODES_PER_CHUNK); | |
| 359 | 367 | |
| 360 | 368 | error = xfs_iwalk_ag_recs(iwag); |
| 361 | 369 | if (error) |
| @@ -372,7 +380,7 @@ xfs_iwalk_run_callbacks( · 10 unmodified lines | ||
| 372 | 380 | if (error) |
| 373 | 381 | return error; |
| 374 | 382 | |
| 375 | − return xfs_inobt_lookup(*curpp, restart, XFS_LOOKUP_GE, has_more); | |
| 383 | + return xfs_inobt_lookup(*curpp, next_agino, XFS_LOOKUP_GE, has_more); | |
| 376 | 384 | } |
| 377 | 385 | |
| 378 | 386 | /* Walk all inodes in a single AG, from @iwag->startino to the end of the AG. */ |
| @@ -396,6 +404,7 @@ xfs_iwalk_ag( · 17 unmodified lines | ||
| 396 | 404 | |
| 397 | 405 | while (!error && has_more) { |
| 398 | 406 | struct xfs_inobt_rec_incore *irec; |
| 407 | + xfs_ino_t rec_fsino; | |
| 399 | 408 | |
| 400 | 409 | cond_resched(); |
| 401 | 410 | if (xfs_pwork_want_abort(&iwag->pwork)) |
| @@ -407,6 +416,15 @@ xfs_iwalk_ag( · 5 unmodified lines | ||
| 407 | 416 | if (error || !has_more) |
| 408 | 417 | break; |
| 409 | 418 | |
| 419 | + /* Make sure that we always move forward. */ | |
| 420 | + rec_fsino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino); | |
| 421 | + if (iwag->lastino != NULLFSINO && | |
| 422 | + XFS_IS_CORRUPT(mp, iwag->lastino >= rec_fsino)) { | |
| 423 | + error = -EFSCORRUPTED; | |
| 424 | + goto out; | |
| 425 | + } | |
| 426 | + iwag->lastino = rec_fsino + XFS_INODES_PER_CHUNK - 1; | |
| 427 | + | |
| 410 | 428 | /* No allocated inodes in this chunk; skip it. */ |
| 411 | 429 | if (iwag->skip_empty && irec->ir_freecount == irec->ir_count) { |
| 412 | 430 | error = xfs_btree_increment(cur, 0, &has_more); |
| @@ -535,6 +553,7 @@ xfs_iwalk( · 122 unmodified lines | ||
| 535 | 553 | .trim_start = 1, |
| 536 | 554 | .skip_empty = 1, |
| 537 | 555 | .pwork = XFS_PWORK_SINGLE_THREADED, |
| 556 | + .lastino = NULLFSINO, | |
| 538 | 557 | }; |
| 539 | 558 | xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, startino); |
| 540 | 559 | int error; |
| @@ -623,6 +642,7 @@ xfs_iwalk_threaded( · 82 unmodified lines | ||
| 623 | 642 | iwag->data = data; |
| 624 | 643 | iwag->startino = startino; |
| 625 | 644 | iwag->sz_recs = xfs_iwalk_prefetch(inode_records); |
| 645 | + iwag->lastino = NULLFSINO; | |
| 626 | 646 | xfs_pwork_queue(&pctl, &iwag->pwork); |
| 627 | 647 | startino = XFS_AGINO_TO_INO(mp, agno + 1, 0); |
| 628 | 648 | if (flags & XFS_INOBT_WALK_SAME_AG) |
| @@ -696,6 +716,7 @@ xfs_inobt_walk( · 67 unmodified lines | ||
| 696 | 716 | .startino = startino, |
| 697 | 717 | .sz_recs = xfs_inobt_walk_prefetch(inobt_records), |
| 698 | 718 | .pwork = XFS_PWORK_SINGLE_THREADED, |
| 719 | + .lastino = NULLFSINO, | |
| 699 | 720 | }; |
| 700 | 721 | xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, startino); |
| 701 | 722 | int error; |
| @@ -194,20 +194,25 @@ xfs_initialize_perag( · 193 unmodified lines | ||
| 194 | 194 | } |
| 195 | 195 | |
| 196 | 196 | pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL); |
| 197 | − if (!pag) | |
| 197 | + if (!pag) { | |
| 198 | + error = -ENOMEM; | |
| 198 | 199 | goto out_unwind_new_pags; |
| 200 | + } | |
| 199 | 201 | pag->pag_agno = index; |
| 200 | 202 | pag->pag_mount = mp; |
| 201 | 203 | spin_lock_init(&pag->pag_ici_lock); |
| 202 | 204 | INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); |
| 203 | − if (xfs_buf_hash_init(pag)) | |
| 205 | + | |
| 206 | + error = xfs_buf_hash_init(pag); | |
| 207 | + if (error) | |
| 204 | 208 | goto out_free_pag; |
| 205 | 209 | init_waitqueue_head(&pag->pagb_wait); |
| 206 | 210 | spin_lock_init(&pag->pagb_lock); |
| 207 | 211 | pag->pagb_count = 0; |
| 208 | 212 | pag->pagb_tree = RB_ROOT; |
| 209 | 213 | |
| 210 | − if (radix_tree_preload(GFP_NOFS)) | |
| 214 | + error = radix_tree_preload(GFP_NOFS); | |
| 215 | + if (error) | |
| 211 | 216 | goto out_hash_destroy; |
| 212 | 217 | |
| 213 | 218 | spin_lock(&mp->m_perag_lock); |
| @@ -8,8 +8,10 @@ · 7 unmodified lines | ||
| 8 | 8 | + __clang_patchlevel__) |
| 9 | 9 | |
| 10 | 10 | #if CLANG_VERSION < 100001 |
| 11 | +#ifndef __BPF_TRACING__ | |
| 11 | 12 | # error Sorry, your version of Clang is too old - please use 10.0.1 or newer. |
| 12 | 13 | #endif |
| 14 | +#endif | |
| 13 | 15 | |
| 14 | 16 | /* Compiler specific definitions for Clang compiler */ |
| 15 | 17 | |
| @@ -50,10 +50,6 @@ · 49 unmodified lines | ||
| 50 | 50 | #define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U |
| 51 | 51 | #define ZYNQMP_PM_CAPABILITY_UNUSABLE 0x8U |
| 52 | 52 | |
| 53 | −/* Feature check status */ | |
| 54 | −#define PM_FEATURE_INVALID -1 | |
| 55 | −#define PM_FEATURE_UNCHECKED 0 | |
| 56 | − | |
| 57 | 53 | /* |
| 58 | 54 | * Firmware FPGA Manager flags |
| 59 | 55 | * XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration |
| @@ -798,7 +798,6 @@ extern int iommu_calculate_agaw(struct intel_iommu *iommu); · 797 unmodified lines | ||
| 798 | 798 | extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu); |
| 799 | 799 | extern int dmar_disabled; |
| 800 | 800 | extern int intel_iommu_enabled; |
| 801 | −extern int intel_iommu_tboot_noforce; | |
| 802 | 801 | extern int intel_iommu_gfx_mapped; |
| 803 | 802 | #else |
| 804 | 803 | static inline int iommu_calculate_agaw(struct intel_iommu *iommu) |
| @@ -401,7 +401,7 @@ static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh) · 400 unmodified lines | ||
| 401 | 401 | #define JI_WAIT_DATA (1 << __JI_WAIT_DATA) |
| 402 | 402 | |
| 403 | 403 | /** |
| 404 | − * struct jbd_inode - The jbd_inode type is the structure linking inodes in | |
| 404 | + * struct jbd2_inode - The jbd_inode type is the structure linking inodes in | |
| 405 | 405 | * ordered mode present in a transaction so that we can sync them during commit. |
| 406 | 406 | */ |
| 407 | 407 | struct jbd2_inode { |
| @@ -282,20 +282,6 @@ struct mem_cgroup { · 281 unmodified lines | ||
| 282 | 282 | |
| 283 | 283 | MEMCG_PADDING(_pad1_); |
| 284 | 284 | |
| 285 | − /* | |
| 286 | − * set > 0 if pages under this cgroup are moving to other cgroup. | |
| 287 | − */ | |
| 288 | − atomic_t moving_account; | |
| 289 | − struct task_struct *move_lock_task; | |
| 290 | − | |
| 291 | − /* Legacy local VM stats and events */ | |
| 292 | − struct memcg_vmstats_percpu __percpu *vmstats_local; | |
| 293 | − | |
| 294 | − /* Subtree VM stats and events (batched updates) */ | |
| 295 | − struct memcg_vmstats_percpu __percpu *vmstats_percpu; | |
| 296 | − | |
| 297 | − MEMCG_PADDING(_pad2_); | |
| 298 | − | |
| 299 | 285 | atomic_long_t vmstats[MEMCG_NR_STAT]; |
| 300 | 286 | atomic_long_t vmevents[NR_VM_EVENT_ITEMS]; |
| 301 | 287 | |
| @@ -317,6 +303,20 @@ struct mem_cgroup { · 15 unmodified lines | ||
| 317 | 303 | struct list_head objcg_list; /* list of inherited objcgs */ |
| 318 | 304 | #endif |
| 319 | 305 | |
| 306 | + MEMCG_PADDING(_pad2_); | |
| 307 | + | |
| 308 | + /* | |
| 309 | + * set > 0 if pages under this cgroup are moving to other cgroup. | |
| 310 | + */ | |
| 311 | + atomic_t moving_account; | |
| 312 | + struct task_struct *move_lock_task; | |
| 313 | + | |
| 314 | + /* Legacy local VM stats and events */ | |
| 315 | + struct memcg_vmstats_percpu __percpu *vmstats_local; | |
| 316 | + | |
| 317 | + /* Subtree VM stats and events (batched updates) */ | |
| 318 | + struct memcg_vmstats_percpu __percpu *vmstats_percpu; | |
| 319 | + | |
| 320 | 320 | #ifdef CONFIG_CGROUP_WRITEBACK |
| 321 | 321 | struct list_head cgwb_list; |
| 322 | 322 | struct wb_domain cgwb_domain; |
| @@ -281,20 +281,6 @@ static inline bool movable_node_is_enabled(void) · 280 unmodified lines | ||
| 281 | 281 | } |
| 282 | 282 | #endif /* ! CONFIG_MEMORY_HOTPLUG */ |
| 283 | 283 | |
| 284 | −#ifdef CONFIG_NUMA | |
| 285 | −extern int memory_add_physaddr_to_nid(u64 start); | |
| 286 | −extern int phys_to_target_node(u64 start); | |
| 287 | −#else | |
| 288 | −static inline int memory_add_physaddr_to_nid(u64 start) | |
| 289 | −{ | |
| 290 | − return 0; | |
| 291 | −} | |
| 292 | −static inline int phys_to_target_node(u64 start) | |
| 293 | −{ | |
| 294 | − return 0; | |
| 295 | −} | |
| 296 | −#endif | |
| 297 | − | |
| 298 | 284 | #if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_DEFERRED_STRUCT_PAGE_INIT) |
| 299 | 285 | /* |
| 300 | 286 | * pgdat resizing functions |
| @@ -3163,6 +3163,11 @@ static inline bool dev_validate_header(const struct net_device *dev, · 3162 unmodified lines | ||
| 3163 | 3163 | return false; |
| 3164 | 3164 | } |
| 3165 | 3165 | |
| 3166 | +static inline bool dev_has_header(const struct net_device *dev) | |
| 3167 | +{ | |
| 3168 | + return dev->header_ops && dev->header_ops->create; | |
| 3169 | +} | |
| 3170 | + | |
| 3166 | 3171 | typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, |
| 3167 | 3172 | int len, int size); |
| 3168 | 3173 | int register_gifconf(unsigned int family, gifconf_func_t *gifconf); |
| @@ -21,13 +21,41 @@ · 20 unmodified lines | ||
| 21 | 21 | #endif |
| 22 | 22 | |
| 23 | 23 | #ifdef CONFIG_NUMA |
| 24 | +#include <linux/printk.h> | |
| 25 | +#include <asm/sparsemem.h> | |
| 26 | + | |
| 24 | 27 | /* Generic implementation available */ |
| 25 | 28 | int numa_map_to_online_node(int node); |
| 26 | −#else | |
| 29 | + | |
| 30 | +#ifndef memory_add_physaddr_to_nid | |
| 31 | +static inline int memory_add_physaddr_to_nid(u64 start) | |
| 32 | +{ | |
| 33 | + pr_info_once("Unknown online node for memory at 0x%llx, assuming node 0\n", | |
| 34 | + start); | |
| 35 | + return 0; | |
| 36 | +} | |
| 37 | +#endif | |
| 38 | +#ifndef phys_to_target_node | |
| 39 | +static inline int phys_to_target_node(u64 start) | |
| 40 | +{ | |
| 41 | + pr_info_once("Unknown target node for memory at 0x%llx, assuming node 0\n", | |
| 42 | + start); | |
| 43 | + return 0; | |
| 44 | +} | |
| 45 | +#endif | |
| 46 | +#else /* !CONFIG_NUMA */ | |
| 27 | 47 | static inline int numa_map_to_online_node(int node) |
| 28 | 48 | { |
| 29 | 49 | return NUMA_NO_NODE; |
| 30 | 50 | } |
| 51 | +static inline int memory_add_physaddr_to_nid(u64 start) | |
| 52 | +{ | |
| 53 | + return 0; | |
| 54 | +} | |
| 55 | +static inline int phys_to_target_node(u64 start) | |
| 56 | +{ | |
| 57 | + return 0; | |
| 58 | +} | |
| 31 | 59 | #endif |
| 32 | 60 | |
| 33 | 61 | #endif /* _LINUX_NUMA_H */ |
| @@ -906,6 +906,8 @@ static inline unsigned int __readahead_batch(struct readahead_control *rac, · 905 unmodified lines | ||
| 906 | 906 | xas_set(&xas, rac->_index); |
| 907 | 907 | rcu_read_lock(); |
| 908 | 908 | xas_for_each(&xas, page, rac->_index + rac->_nr_pages - 1) { |
| 909 | + if (xas_retry(&xas, page)) | |
| 910 | + continue; | |
| 909 | 911 | VM_BUG_ON_PAGE(!PageLocked(page), page); |
| 910 | 912 | VM_BUG_ON_PAGE(PageTail(page), page); |
| 911 | 913 | array[i++] = page; |
| @@ -1427,6 +1427,19 @@ typedef unsigned int pgtbl_mod_mask; · 1426 unmodified lines | ||
| 1427 | 1427 | |
| 1428 | 1428 | #endif /* !__ASSEMBLY__ */ |
| 1429 | 1429 | |
| 1430 | +#if !defined(MAX_POSSIBLE_PHYSMEM_BITS) && !defined(CONFIG_64BIT) | |
| 1431 | +#ifdef CONFIG_PHYS_ADDR_T_64BIT | |
| 1432 | +/* | |
| 1433 | + * ZSMALLOC needs to know the highest PFN on 32-bit architectures | |
| 1434 | + * with physical address space extension, but falls back to | |
| 1435 | + * BITS_PER_LONG otherwise. | |
| 1436 | + */ | |
| 1437 | +#error Missing MAX_POSSIBLE_PHYSMEM_BITS definition | |
| 1438 | +#else | |
| 1439 | +#define MAX_POSSIBLE_PHYSMEM_BITS 32 | |
| 1440 | +#endif | |
| 1441 | +#endif | |
| 1442 | + | |
| 1430 | 1443 | #ifndef has_transparent_hugepage |
| 1431 | 1444 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 1432 | 1445 | #define has_transparent_hugepage() 1 |
| @@ -50,6 +50,7 @@ struct sysc_regbits { · 49 unmodified lines | ||
| 50 | 50 | s8 emufree_shift; |
| 51 | 51 | }; |
| 52 | 52 | |
| 53 | +#define SYSC_MODULE_QUIRK_ENA_RESETDONE BIT(25) | |
| 53 | 54 | #define SYSC_MODULE_QUIRK_PRUSS BIT(24) |
| 54 | 55 | #define SYSC_MODULE_QUIRK_DSS_RESET BIT(23) |
| 55 | 56 | #define SYSC_MODULE_QUIRK_RTC_UNLOCK BIT(22) |
| @@ -552,7 +552,6 @@ struct sched_dl_entity { · 551 unmodified lines | ||
| 552 | 552 | * overruns. |
| 553 | 553 | */ |
| 554 | 554 | unsigned int dl_throttled : 1; |
| 555 | − unsigned int dl_boosted : 1; | |
| 556 | 555 | unsigned int dl_yielded : 1; |
| 557 | 556 | unsigned int dl_non_contending : 1; |
| 558 | 557 | unsigned int dl_overrun : 1; |
| @@ -571,6 +570,15 @@ struct sched_dl_entity { · 12 unmodified lines | ||
| 571 | 570 | * time. |
| 572 | 571 | */ |
| 573 | 572 | struct hrtimer inactive_timer; |
| 573 | + | |
| 574 | +#ifdef CONFIG_RT_MUTEXES | |
| 575 | + /* | |
| 576 | + * Priority Inheritance. When a DEADLINE scheduling entity is boosted | |
| 577 | + * pi_se points to the donor, otherwise points to the dl_se it belongs | |
| 578 | + * to (the original one/itself). | |
| 579 | + */ | |
| 580 | + struct sched_dl_entity *pi_se; | |
| 581 | +#endif | |
| 574 | 582 | }; |
| 575 | 583 | |
| 576 | 584 | #ifdef CONFIG_UCLAMP_TASK |
| @@ -770,7 +778,6 @@ struct task_struct { · 193 unmodified lines | ||
| 770 | 778 | unsigned sched_reset_on_fork:1; |
| 771 | 779 | unsigned sched_contributes_to_load:1; |
| 772 | 780 | unsigned sched_migrated:1; |
| 773 | − unsigned sched_remote_wakeup:1; | |
| 774 | 781 | #ifdef CONFIG_PSI |
| 775 | 782 | unsigned sched_psi_wake_requeue:1; |
| 776 | 783 | #endif |
| @@ -780,6 +787,21 @@ struct task_struct { · 3 unmodified lines | ||
| 780 | 787 | |
| 781 | 788 | /* Unserialized, strictly 'current' */ |
| 782 | 789 | |
| 790 | + /* | |
| 791 | + * This field must not be in the scheduler word above due to wakelist | |
| 792 | + * queueing no longer being serialized by p->on_cpu. However: | |
| 793 | + * | |
| 794 | + * p->XXX = X; ttwu() | |
| 795 | + * schedule() if (p->on_rq && ..) // false | |
| 796 | + * smp_mb__after_spinlock(); if (smp_load_acquire(&p->on_cpu) && //true | |
| 797 | + * deactivate_task() ttwu_queue_wakelist()) | |
| 798 | + * p->on_rq = 0; p->sched_remote_wakeup = Y; | |
| 799 | + * | |
| 800 | + * guarantees all stores of 'current' are visible before | |
| 801 | + * ->sched_remote_wakeup gets used, so it can be in this word. | |
| 802 | + */ | |
| 803 | + unsigned sched_remote_wakeup:1; | |
| 804 | + | |
| 783 | 805 | /* Bit to tell LSMs we're in execve(): */ |
| 784 | 806 | unsigned in_execve:1; |
| 785 | 807 | unsigned in_iowait:1; |
| @@ -185,6 +185,11 @@ struct slave { · 184 unmodified lines | ||
| 185 | 185 | struct rtnl_link_stats64 slave_stats; |
| 186 | 186 | }; |
| 187 | 187 | |
| 188 | +static inline struct slave *to_slave(struct kobject *kobj) | |
| 189 | +{ | |
| 190 | + return container_of(kobj, struct slave, kobj); | |
| 191 | +} | |
| 192 | + | |
| 188 | 193 | struct bond_up_slave { |
| 189 | 194 | unsigned int count; |
| 190 | 195 | struct rcu_head rcu; |
| @@ -750,6 +755,9 @@ extern struct bond_parm_tbl ad_select_tbl[]; · 559 unmodified lines | ||
| 750 | 755 | /* exported from bond_netlink.c */ |
| 751 | 756 | extern struct rtnl_link_ops bond_link_ops; |
| 752 | 757 | |
| 758 | +/* exported from bond_sysfs_slave.c */ | |
| 759 | +extern const struct sysfs_ops slave_sysfs_ops; | |
| 760 | + | |
| 753 | 761 | static inline netdev_tx_t bond_tx_drop(struct net_device *dev, struct sk_buff *skb) |
| 754 | 762 | { |
| 755 | 763 | atomic_long_inc(&dev->tx_dropped); |
| @@ -247,8 +247,9 @@ void inet_hashinfo2_init(struct inet_hashinfo *h, const char *name, · 246 unmodified lines | ||
| 247 | 247 | unsigned long high_limit); |
| 248 | 248 | int inet_hashinfo2_init_mod(struct inet_hashinfo *h); |
| 249 | 249 | |
| 250 | −bool inet_ehash_insert(struct sock *sk, struct sock *osk); | |
| 251 | −bool inet_ehash_nolisten(struct sock *sk, struct sock *osk); | |
| 250 | +bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk); | |
| 251 | +bool inet_ehash_nolisten(struct sock *sk, struct sock *osk, | |
| 252 | + bool *found_dup_sk); | |
| 252 | 253 | int __inet_hash(struct sock *sk, struct sock *osk); |
| 253 | 254 | int inet_hash(struct sock *sk); |
| 254 | 255 | void inet_unhash(struct sock *sk); |
| @@ -199,6 +199,12 @@ enum tls_context_flags { · 198 unmodified lines | ||
| 199 | 199 | * to be atomic. |
| 200 | 200 | */ |
| 201 | 201 | TLS_TX_SYNC_SCHED = 1, |
| 202 | + /* tls_dev_del was called for the RX side, device state was released, | |
| 203 | + * but tls_ctx->netdev might still be kept, because TX-side driver | |
| 204 | + * resources might not be released yet. Used to prevent the second | |
| 205 | + * tls_dev_del call in tls_device_down if it happens simultaneously. | |
| 206 | + */ | |
| 207 | + TLS_RX_DEV_CLOSED = 2, | |
| 202 | 208 | }; |
| 203 | 209 | |
| 204 | 210 | struct cipher_context { |
| @@ -132,6 +132,9 @@ struct iscsi_task { · 131 unmodified lines | ||
| 132 | 132 | void *dd_data; /* driver/transport data */ |
| 133 | 133 | }; |
| 134 | 134 | |
| 135 | +/* invalid scsi_task pointer */ | |
| 136 | +#define INVALID_SCSI_TASK (struct iscsi_task *)-1l | |
| 137 | + | |
| 135 | 138 | static inline int iscsi_task_has_unsol_data(struct iscsi_task *task) |
| 136 | 139 | { |
| 137 | 140 | return task->unsol_r2t.data_length > task->unsol_r2t.sent; |
| @@ -0,0 +1,15 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | +/* | |
| 3 | + * linux/sound/rt1015.h -- Platform data for RT1015 | |
| 4 | + * | |
| 5 | + * Copyright 2020 Realtek Microelectronics | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#ifndef __LINUX_SND_RT1015_H | |
| 9 | +#define __LINUX_SND_RT1015_H | |
| 10 | + | |
| 11 | +struct rt1015_platform_data { | |
| 12 | + unsigned int power_up_delay_ms; | |
| 13 | +}; | |
| 14 | + | |
| 15 | +#endif | |
| @@ -190,7 +190,7 @@ TRACE_EVENT(inode_foreign_history, · 189 unmodified lines | ||
| 190 | 190 | ), |
| 191 | 191 | |
| 192 | 192 | TP_fast_assign( |
| 193 | − strncpy(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32); | |
| 193 | + strscpy_pad(__entry->name, bdi_dev_name(inode_to_bdi(inode)), 32); | |
| 194 | 194 | __entry->ino = inode->i_ino; |
| 195 | 195 | __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); |
| 196 | 196 | __entry->history = history; |
| @@ -219,7 +219,7 @@ TRACE_EVENT(inode_switch_wbs, · 22 unmodified lines | ||
| 219 | 219 | ), |
| 220 | 220 | |
| 221 | 221 | TP_fast_assign( |
| 222 | − strncpy(__entry->name, bdi_dev_name(old_wb->bdi), 32); | |
| 222 | + strscpy_pad(__entry->name, bdi_dev_name(old_wb->bdi), 32); | |
| 223 | 223 | __entry->ino = inode->i_ino; |
| 224 | 224 | __entry->old_cgroup_ino = __trace_wb_assign_cgroup(old_wb); |
| 225 | 225 | __entry->new_cgroup_ino = __trace_wb_assign_cgroup(new_wb); |
| @@ -252,7 +252,7 @@ TRACE_EVENT(track_foreign_dirty, · 26 unmodified lines | ||
| 252 | 252 | struct address_space *mapping = page_mapping(page); |
| 253 | 253 | struct inode *inode = mapping ? mapping->host : NULL; |
| 254 | 254 | |
| 255 | − strncpy(__entry->name, bdi_dev_name(wb->bdi), 32); | |
| 255 | + strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); | |
| 256 | 256 | __entry->bdi_id = wb->bdi->id; |
| 257 | 257 | __entry->ino = inode ? inode->i_ino : 0; |
| 258 | 258 | __entry->memcg_id = wb->memcg_css->id; |
| @@ -285,7 +285,7 @@ TRACE_EVENT(flush_foreign, · 26 unmodified lines | ||
| 285 | 285 | ), |
| 286 | 286 | |
| 287 | 287 | TP_fast_assign( |
| 288 | − strncpy(__entry->name, bdi_dev_name(wb->bdi), 32); | |
| 288 | + strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); | |
| 289 | 289 | __entry->cgroup_ino = __trace_wb_assign_cgroup(wb); |
| 290 | 290 | __entry->frn_bdi_id = frn_bdi_id; |
| 291 | 291 | __entry->frn_memcg_id = frn_memcg_id; |
| @@ -526,6 +526,8 @@ enum devlink_attr { · 525 unmodified lines | ||
| 526 | 526 | DEVLINK_ATTR_RELOAD_STATS_LIMIT, /* u8 */ |
| 527 | 527 | DEVLINK_ATTR_RELOAD_STATS_VALUE, /* u32 */ |
| 528 | 528 | DEVLINK_ATTR_REMOTE_RELOAD_STATS, /* nested */ |
| 529 | + DEVLINK_ATTR_RELOAD_ACTION_INFO, /* nested */ | |
| 530 | + DEVLINK_ATTR_RELOAD_ACTION_STATS, /* nested */ | |
| 529 | 531 | |
| 530 | 532 | /* add new attributes above here, update the policy in devlink.c */ |
| 531 | 533 | |
| @@ -1058,4 +1058,6 @@ enum ovs_dec_ttl_attr { · 1057 unmodified lines | ||
| 1058 | 1058 | __OVS_DEC_TTL_ATTR_MAX |
| 1059 | 1059 | }; |
| 1060 | 1060 | |
| 1061 | +#define OVS_DEC_TTL_ATTR_MAX (__OVS_DEC_TTL_ATTR_MAX - 1) | |
| 1062 | + | |
| 1061 | 1063 | #endif /* _LINUX_OPENVSWITCH_H */ |
| @@ -719,7 +719,7 @@ config LOG_CPU_MAX_BUF_SHIFT · 718 unmodified lines | ||
| 719 | 719 | with more CPUs. Therefore this value is used only when the sum of |
| 720 | 720 | contributions is greater than the half of the default kernel ring |
| 721 | 721 | buffer as defined by LOG_BUF_SHIFT. The default values are set |
| 722 | − so that more than 64 CPUs are needed to trigger the allocation. | |
| 722 | + so that more than 16 CPUs are needed to trigger the allocation. | |
| 723 | 723 | |
| 724 | 724 | Also this option is ignored when "log_buf_len" kernel parameter is |
| 725 | 725 | used as it forces an exact (power of two) size of the ring buffer. |
| @@ -108,19 +108,21 @@ static inline void lockdep_lock(void) · 107 unmodified lines | ||
| 108 | 108 | { |
| 109 | 109 | DEBUG_LOCKS_WARN_ON(!irqs_disabled()); |
| 110 | 110 | |
| 111 | + __this_cpu_inc(lockdep_recursion); | |
| 111 | 112 | arch_spin_lock(&__lock); |
| 112 | 113 | __owner = current; |
| 113 | − __this_cpu_inc(lockdep_recursion); | |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | 116 | static inline void lockdep_unlock(void) |
| 117 | 117 | { |
| 118 | + DEBUG_LOCKS_WARN_ON(!irqs_disabled()); | |
| 119 | + | |
| 118 | 120 | if (debug_locks && DEBUG_LOCKS_WARN_ON(__owner != current)) |
| 119 | 121 | return; |
| 120 | 122 | |
| 121 | − __this_cpu_dec(lockdep_recursion); | |
| 122 | 123 | __owner = NULL; |
| 123 | 124 | arch_spin_unlock(&__lock); |
| 125 | + __this_cpu_dec(lockdep_recursion); | |
| 124 | 126 | } |
| 125 | 127 | |
| 126 | 128 | static inline bool lockdep_assert_locked(void) |
| @@ -528,8 +528,8 @@ static int log_store(u32 caller_id, int facility, int level, · 527 unmodified lines | ||
| 528 | 528 | if (dev_info) |
| 529 | 529 | memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info)); |
| 530 | 530 | |
| 531 | − /* insert message */ | |
| 532 | − if ((flags & LOG_CONT) || !(flags & LOG_NEWLINE)) | |
| 531 | + /* A message without a trailing newline can be continued. */ | |
| 532 | + if (!(flags & LOG_NEWLINE)) | |
| 533 | 533 | prb_commit(&e); |
| 534 | 534 | else |
| 535 | 535 | prb_final_commit(&e); |
| @@ -882,8 +882,6 @@ static bool desc_reserve(struct printk_ringbuffer *rb, unsigned long *id_out) · 881 unmodified lines | ||
| 882 | 882 | head_id = atomic_long_read(&desc_ring->head_id); /* LMM(desc_reserve:A) */ |
| 883 | 883 | |
| 884 | 884 | do { |
| 885 | − desc = to_desc(desc_ring, head_id); | |
| 886 | − | |
| 887 | 885 | id = DESC_ID(head_id + 1); |
| 888 | 886 | id_prev_wrap = DESC_ID_PREV_WRAP(desc_ring, id); |
| 889 | 887 | |
| @@ -264,17 +264,11 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state) · 263 unmodified lines | ||
| 264 | 264 | return ret; |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | −static bool ptrace_has_cap(const struct cred *cred, struct user_namespace *ns, | |
| 268 | − unsigned int mode) | |
| 267 | +static bool ptrace_has_cap(struct user_namespace *ns, unsigned int mode) | |
| 269 | 268 | { |
| 270 | − int ret; | |
| 271 | − | |
| 272 | 269 | if (mode & PTRACE_MODE_NOAUDIT) |
| 273 | − ret = security_capable(cred, ns, CAP_SYS_PTRACE, CAP_OPT_NOAUDIT); | |
| 274 | − else | |
| 275 | − ret = security_capable(cred, ns, CAP_SYS_PTRACE, CAP_OPT_NONE); | |
| 276 | − | |
| 277 | − return ret == 0; | |
| 270 | + return ns_capable_noaudit(ns, CAP_SYS_PTRACE); | |
| 271 | + return ns_capable(ns, CAP_SYS_PTRACE); | |
| 278 | 272 | } |
| 279 | 273 | |
| 280 | 274 | /* Returns 0 on success, -errno on denial. */ |
| @@ -326,7 +320,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) · 45 unmodified lines | ||
| 326 | 320 | gid_eq(caller_gid, tcred->sgid) && |
| 327 | 321 | gid_eq(caller_gid, tcred->gid)) |
| 328 | 322 | goto ok; |
| 329 | − if (ptrace_has_cap(cred, tcred->user_ns, mode)) | |
| 323 | + if (ptrace_has_cap(tcred->user_ns, mode)) | |
| 330 | 324 | goto ok; |
| 331 | 325 | rcu_read_unlock(); |
| 332 | 326 | return -EPERM; |
| @@ -345,7 +339,7 @@ ok: · 12 unmodified lines | ||
| 345 | 339 | mm = task->mm; |
| 346 | 340 | if (mm && |
| 347 | 341 | ((get_dumpable(mm) != SUID_DUMP_USER) && |
| 348 | − !ptrace_has_cap(cred, mm->user_ns, mode))) | |
| 342 | + !ptrace_has_cap(mm->user_ns, mode))) | |
| 349 | 343 | return -EPERM; |
| 350 | 344 | |
| 351 | 345 | return security_ptrace_access_check(task, mode); |
| @@ -2501,7 +2501,12 @@ ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags, · 2500 unmodified lines | ||
| 2501 | 2501 | #ifdef CONFIG_SMP |
| 2502 | 2502 | if (wake_flags & WF_MIGRATED) |
| 2503 | 2503 | en_flags |= ENQUEUE_MIGRATED; |
| 2504 | + else | |
| 2504 | 2505 | #endif |
| 2506 | + if (p->in_iowait) { | |
| 2507 | + delayacct_blkio_end(p); | |
| 2508 | + atomic_dec(&task_rq(p)->nr_iowait); | |
| 2509 | + } | |
| 2505 | 2510 | |
| 2506 | 2511 | activate_task(rq, p, en_flags); |
| 2507 | 2512 | ttwu_do_wakeup(rq, p, wake_flags, rf); |
| @@ -2888,11 +2893,6 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) · 380 unmodified lines | ||
| 2888 | 2893 | if (READ_ONCE(p->on_rq) && ttwu_runnable(p, wake_flags)) |
| 2889 | 2894 | goto unlock; |
| 2890 | 2895 | |
| 2891 | − if (p->in_iowait) { | |
| 2892 | − delayacct_blkio_end(p); | |
| 2893 | − atomic_dec(&task_rq(p)->nr_iowait); | |
| 2894 | − } | |
| 2895 | − | |
| 2896 | 2896 | #ifdef CONFIG_SMP |
| 2897 | 2897 | /* |
| 2898 | 2898 | * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be |
| @@ -2963,6 +2963,11 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) · 64 unmodified lines | ||
| 2963 | 2963 | |
| 2964 | 2964 | cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags); |
| 2965 | 2965 | if (task_cpu(p) != cpu) { |
| 2966 | + if (p->in_iowait) { | |
| 2967 | + delayacct_blkio_end(p); | |
| 2968 | + atomic_dec(&task_rq(p)->nr_iowait); | |
| 2969 | + } | |
| 2970 | + | |
| 2966 | 2971 | wake_flags |= WF_MIGRATED; |
| 2967 | 2972 | psi_ttwu_dequeue(p); |
| 2968 | 2973 | set_task_cpu(p, cpu); |
| @@ -4907,20 +4912,21 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task) · 1938 unmodified lines | ||
| 4907 | 4912 | if (!dl_prio(p->normal_prio) || |
| 4908 | 4913 | (pi_task && dl_prio(pi_task->prio) && |
| 4909 | 4914 | dl_entity_preempt(&pi_task->dl, &p->dl))) { |
| 4910 | − p->dl.dl_boosted = 1; | |
| 4915 | + p->dl.pi_se = pi_task->dl.pi_se; | |
| 4911 | 4916 | queue_flag |= ENQUEUE_REPLENISH; |
| 4912 | − } else | |
| 4913 | − p->dl.dl_boosted = 0; | |
| 4917 | + } else { | |
| 4918 | + p->dl.pi_se = &p->dl; | |
| 4919 | + } | |
| 4914 | 4920 | p->sched_class = &dl_sched_class; |
| 4915 | 4921 | } else if (rt_prio(prio)) { |
| 4916 | 4922 | if (dl_prio(oldprio)) |
| 4917 | − p->dl.dl_boosted = 0; | |
| 4923 | + p->dl.pi_se = &p->dl; | |
| 4918 | 4924 | if (oldprio < prio) |
| 4919 | 4925 | queue_flag |= ENQUEUE_HEAD; |
| 4920 | 4926 | p->sched_class = &rt_sched_class; |
| 4921 | 4927 | } else { |
| 4922 | 4928 | if (dl_prio(oldprio)) |
| 4923 | − p->dl.dl_boosted = 0; | |
| 4929 | + p->dl.pi_se = &p->dl; | |
| 4924 | 4930 | if (rt_prio(oldprio)) |
| 4925 | 4931 | p->rt.timeout = 0; |
| 4926 | 4932 | p->sched_class = &fair_sched_class; |
| @@ -43,6 +43,28 @@ static inline int on_dl_rq(struct sched_dl_entity *dl_se) · 42 unmodified lines | ||
| 43 | 43 | return !RB_EMPTY_NODE(&dl_se->rb_node); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | +#ifdef CONFIG_RT_MUTEXES | |
| 47 | +static inline struct sched_dl_entity *pi_of(struct sched_dl_entity *dl_se) | |
| 48 | +{ | |
| 49 | + return dl_se->pi_se; | |
| 50 | +} | |
| 51 | + | |
| 52 | +static inline bool is_dl_boosted(struct sched_dl_entity *dl_se) | |
| 53 | +{ | |
| 54 | + return pi_of(dl_se) != dl_se; | |
| 55 | +} | |
| 56 | +#else | |
| 57 | +static inline struct sched_dl_entity *pi_of(struct sched_dl_entity *dl_se) | |
| 58 | +{ | |
| 59 | + return dl_se; | |
| 60 | +} | |
| 61 | + | |
| 62 | +static inline bool is_dl_boosted(struct sched_dl_entity *dl_se) | |
| 63 | +{ | |
| 64 | + return false; | |
| 65 | +} | |
| 66 | +#endif | |
| 67 | + | |
| 46 | 68 | #ifdef CONFIG_SMP |
| 47 | 69 | static inline struct dl_bw *dl_bw_of(int i) |
| 48 | 70 | { |
| @@ -698,7 +720,7 @@ static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se) · 649 unmodified lines | ||
| 698 | 720 | struct dl_rq *dl_rq = dl_rq_of_se(dl_se); |
| 699 | 721 | struct rq *rq = rq_of_dl_rq(dl_rq); |
| 700 | 722 | |
| 701 | − WARN_ON(dl_se->dl_boosted); | |
| 723 | + WARN_ON(is_dl_boosted(dl_se)); | |
| 702 | 724 | WARN_ON(dl_time_before(rq_clock(rq), dl_se->deadline)); |
| 703 | 725 | |
| 704 | 726 | /* |
| @@ -736,21 +758,20 @@ static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se) · 31 unmodified lines | ||
| 736 | 758 | * could happen are, typically, a entity voluntarily trying to overcome its |
| 737 | 759 | * runtime, or it just underestimated it during sched_setattr(). |
| 738 | 760 | */ |
| 739 | −static void replenish_dl_entity(struct sched_dl_entity *dl_se, | |
| 740 | − struct sched_dl_entity *pi_se) | |
| 761 | +static void replenish_dl_entity(struct sched_dl_entity *dl_se) | |
| 741 | 762 | { |
| 742 | 763 | struct dl_rq *dl_rq = dl_rq_of_se(dl_se); |
| 743 | 764 | struct rq *rq = rq_of_dl_rq(dl_rq); |
| 744 | 765 | |
| 745 | − BUG_ON(pi_se->dl_runtime <= 0); | |
| 766 | + BUG_ON(pi_of(dl_se)->dl_runtime <= 0); | |
| 746 | 767 | |
| 747 | 768 | /* |
| 748 | 769 | * This could be the case for a !-dl task that is boosted. |
| 749 | 770 | * Just go with full inherited parameters. |
| 750 | 771 | */ |
| 751 | 772 | if (dl_se->dl_deadline == 0) { |
| 752 | − dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; | |
| 753 | − dl_se->runtime = pi_se->dl_runtime; | |
| 773 | + dl_se->deadline = rq_clock(rq) + pi_of(dl_se)->dl_deadline; | |
| 774 | + dl_se->runtime = pi_of(dl_se)->dl_runtime; | |
| 754 | 775 | } |
| 755 | 776 | |
| 756 | 777 | if (dl_se->dl_yielded && dl_se->runtime > 0) |
| @@ -763,8 +784,8 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se, · 6 unmodified lines | ||
| 763 | 784 | * arbitrary large. |
| 764 | 785 | */ |
| 765 | 786 | while (dl_se->runtime <= 0) { |
| 766 | − dl_se->deadline += pi_se->dl_period; | |
| 767 | − dl_se->runtime += pi_se->dl_runtime; | |
| 787 | + dl_se->deadline += pi_of(dl_se)->dl_period; | |
| 788 | + dl_se->runtime += pi_of(dl_se)->dl_runtime; | |
| 768 | 789 | } |
| 769 | 790 | |
| 770 | 791 | /* |
| @@ -778,8 +799,8 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se, · 7 unmodified lines | ||
| 778 | 799 | */ |
| 779 | 800 | if (dl_time_before(dl_se->deadline, rq_clock(rq))) { |
| 780 | 801 | printk_deferred_once("sched: DL replenish lagged too much\n"); |
| 781 | − dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; | |
| 782 | − dl_se->runtime = pi_se->dl_runtime; | |
| 802 | + dl_se->deadline = rq_clock(rq) + pi_of(dl_se)->dl_deadline; | |
| 803 | + dl_se->runtime = pi_of(dl_se)->dl_runtime; | |
| 783 | 804 | } |
| 784 | 805 | |
| 785 | 806 | if (dl_se->dl_yielded) |
| @@ -812,8 +833,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se, · 26 unmodified lines | ||
| 812 | 833 | * task with deadline equal to period this is the same of using |
| 813 | 834 | * dl_period instead of dl_deadline in the equation above. |
| 814 | 835 | */ |
| 815 | −static bool dl_entity_overflow(struct sched_dl_entity *dl_se, | |
| 816 | − struct sched_dl_entity *pi_se, u64 t) | |
| 836 | +static bool dl_entity_overflow(struct sched_dl_entity *dl_se, u64 t) | |
| 817 | 837 | { |
| 818 | 838 | u64 left, right; |
| 819 | 839 | |
| @@ -835,9 +855,9 @@ static bool dl_entity_overflow(struct sched_dl_entity *dl_se, · 15 unmodified lines | ||
| 835 | 855 | * of anything below microseconds resolution is actually fiction |
| 836 | 856 | * (but still we want to give the user that illusion >;). |
| 837 | 857 | */ |
| 838 | − left = (pi_se->dl_deadline >> DL_SCALE) * (dl_se->runtime >> DL_SCALE); | |
| 858 | + left = (pi_of(dl_se)->dl_deadline >> DL_SCALE) * (dl_se->runtime >> DL_SCALE); | |
| 839 | 859 | right = ((dl_se->deadline - t) >> DL_SCALE) * |
| 840 | − (pi_se->dl_runtime >> DL_SCALE); | |
| 860 | + (pi_of(dl_se)->dl_runtime >> DL_SCALE); | |
| 841 | 861 | |
| 842 | 862 | return dl_time_before(right, left); |
| 843 | 863 | } |
| @@ -922,24 +942,23 @@ static inline bool dl_is_implicit(struct sched_dl_entity *dl_se) · 78 unmodified lines | ||
| 922 | 942 | * Please refer to the comments update_dl_revised_wakeup() function to find |
| 923 | 943 | * more about the Revised CBS rule. |
| 924 | 944 | */ |
| 925 | −static void update_dl_entity(struct sched_dl_entity *dl_se, | |
| 926 | − struct sched_dl_entity *pi_se) | |
| 945 | +static void update_dl_entity(struct sched_dl_entity *dl_se) | |
| 927 | 946 | { |
| 928 | 947 | struct dl_rq *dl_rq = dl_rq_of_se(dl_se); |
| 929 | 948 | struct rq *rq = rq_of_dl_rq(dl_rq); |
| 930 | 949 | |
| 931 | 950 | if (dl_time_before(dl_se->deadline, rq_clock(rq)) || |
| 932 | − dl_entity_overflow(dl_se, pi_se, rq_clock(rq))) { | |
| 951 | + dl_entity_overflow(dl_se, rq_clock(rq))) { | |
| 933 | 952 | |
| 934 | 953 | if (unlikely(!dl_is_implicit(dl_se) && |
| 935 | 954 | !dl_time_before(dl_se->deadline, rq_clock(rq)) && |
| 936 | − !dl_se->dl_boosted)){ | |
| 955 | + !is_dl_boosted(dl_se))) { | |
| 937 | 956 | update_dl_revised_wakeup(dl_se, rq); |
| 938 | 957 | return; |
| 939 | 958 | } |
| 940 | 959 | |
| 941 | − dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; | |
| 942 | − dl_se->runtime = pi_se->dl_runtime; | |
| 960 | + dl_se->deadline = rq_clock(rq) + pi_of(dl_se)->dl_deadline; | |
| 961 | + dl_se->runtime = pi_of(dl_se)->dl_runtime; | |
| 943 | 962 | } |
| 944 | 963 | } |
| 945 | 964 | |
| @@ -1038,7 +1057,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer) · 92 unmodified lines | ||
| 1038 | 1057 | * The task might have been boosted by someone else and might be in the |
| 1039 | 1058 | * boosting/deboosting path, its not throttled. |
| 1040 | 1059 | */ |
| 1041 | − if (dl_se->dl_boosted) | |
| 1060 | + if (is_dl_boosted(dl_se)) | |
| 1042 | 1061 | goto unlock; |
| 1043 | 1062 | |
| 1044 | 1063 | /* |
| @@ -1066,7 +1085,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer) · 21 unmodified lines | ||
| 1066 | 1085 | * but do not enqueue -- wait for our wakeup to do that. |
| 1067 | 1086 | */ |
| 1068 | 1087 | if (!task_on_rq_queued(p)) { |
| 1069 | − replenish_dl_entity(dl_se, dl_se); | |
| 1088 | + replenish_dl_entity(dl_se); | |
| 1070 | 1089 | goto unlock; |
| 1071 | 1090 | } |
| 1072 | 1091 | |
| @@ -1156,7 +1175,7 @@ static inline void dl_check_constrained_dl(struct sched_dl_entity *dl_se) · 83 unmodified lines | ||
| 1156 | 1175 | |
| 1157 | 1176 | if (dl_time_before(dl_se->deadline, rq_clock(rq)) && |
| 1158 | 1177 | dl_time_before(rq_clock(rq), dl_next_period(dl_se))) { |
| 1159 | − if (unlikely(dl_se->dl_boosted || !start_dl_timer(p))) | |
| 1178 | + if (unlikely(is_dl_boosted(dl_se) || !start_dl_timer(p))) | |
| 1160 | 1179 | return; |
| 1161 | 1180 | dl_se->dl_throttled = 1; |
| 1162 | 1181 | if (dl_se->runtime > 0) |
| @@ -1287,7 +1306,7 @@ throttle: · 124 unmodified lines | ||
| 1287 | 1306 | dl_se->dl_overrun = 1; |
| 1288 | 1307 | |
| 1289 | 1308 | __dequeue_task_dl(rq, curr, 0); |
| 1290 | − if (unlikely(dl_se->dl_boosted || !start_dl_timer(curr))) | |
| 1309 | + if (unlikely(is_dl_boosted(dl_se) || !start_dl_timer(curr))) | |
| 1291 | 1310 | enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH); |
| 1292 | 1311 | |
| 1293 | 1312 | if (!is_leftmost(curr, &rq->dl)) |
| @@ -1481,8 +1500,7 @@ static void __dequeue_dl_entity(struct sched_dl_entity *dl_se) · 187 unmodified lines | ||
| 1481 | 1500 | } |
| 1482 | 1501 | |
| 1483 | 1502 | static void |
| 1484 | −enqueue_dl_entity(struct sched_dl_entity *dl_se, | |
| 1485 | − struct sched_dl_entity *pi_se, int flags) | |
| 1503 | +enqueue_dl_entity(struct sched_dl_entity *dl_se, int flags) | |
| 1486 | 1504 | { |
| 1487 | 1505 | BUG_ON(on_dl_rq(dl_se)); |
| 1488 | 1506 | |
| @@ -1493,9 +1511,9 @@ enqueue_dl_entity(struct sched_dl_entity *dl_se, · 4 unmodified lines | ||
| 1493 | 1511 | */ |
| 1494 | 1512 | if (flags & ENQUEUE_WAKEUP) { |
| 1495 | 1513 | task_contending(dl_se, flags); |
| 1496 | − update_dl_entity(dl_se, pi_se); | |
| 1514 | + update_dl_entity(dl_se); | |
| 1497 | 1515 | } else if (flags & ENQUEUE_REPLENISH) { |
| 1498 | − replenish_dl_entity(dl_se, pi_se); | |
| 1516 | + replenish_dl_entity(dl_se); | |
| 1499 | 1517 | } else if ((flags & ENQUEUE_RESTORE) && |
| 1500 | 1518 | dl_time_before(dl_se->deadline, |
| 1501 | 1519 | rq_clock(rq_of_dl_rq(dl_rq_of_se(dl_se))))) { |
| @@ -1512,19 +1530,7 @@ static void dequeue_dl_entity(struct sched_dl_entity *dl_se) · 10 unmodified lines | ||
| 1512 | 1530 | |
| 1513 | 1531 | static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) |
| 1514 | 1532 | { |
| 1515 | − struct task_struct *pi_task = rt_mutex_get_top_task(p); | |
| 1516 | − struct sched_dl_entity *pi_se = &p->dl; | |
| 1517 | − | |
| 1518 | − /* | |
| 1519 | − * Use the scheduling parameters of the top pi-waiter task if: | |
| 1520 | − * - we have a top pi-waiter which is a SCHED_DEADLINE task AND | |
| 1521 | − * - our dl_boosted is set (i.e. the pi-waiter's (absolute) deadline is | |
| 1522 | − * smaller than our deadline OR we are a !SCHED_DEADLINE task getting | |
| 1523 | − * boosted due to a SCHED_DEADLINE pi-waiter). | |
| 1524 | − * Otherwise we keep our runtime and deadline. | |
| 1525 | − */ | |
| 1526 | − if (pi_task && dl_prio(pi_task->normal_prio) && p->dl.dl_boosted) { | |
| 1527 | − pi_se = &pi_task->dl; | |
| 1533 | + if (is_dl_boosted(&p->dl)) { | |
| 1528 | 1534 | /* |
| 1529 | 1535 | * Because of delays in the detection of the overrun of a |
| 1530 | 1536 | * thread's runtime, it might be the case that a thread |
| @@ -1557,7 +1563,7 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) · 26 unmodified lines | ||
| 1557 | 1563 | * the throttle. |
| 1558 | 1564 | */ |
| 1559 | 1565 | p->dl.dl_throttled = 0; |
| 1560 | − BUG_ON(!p->dl.dl_boosted || flags != ENQUEUE_REPLENISH); | |
| 1566 | + BUG_ON(!is_dl_boosted(&p->dl) || flags != ENQUEUE_REPLENISH); | |
| 1561 | 1567 | return; |
| 1562 | 1568 | } |
| 1563 | 1569 | |
| @@ -1594,7 +1600,7 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) · 30 unmodified lines | ||
| 1594 | 1600 | return; |
| 1595 | 1601 | } |
| 1596 | 1602 | |
| 1597 | − enqueue_dl_entity(&p->dl, pi_se, flags); | |
| 1603 | + enqueue_dl_entity(&p->dl, flags); | |
| 1598 | 1604 | |
| 1599 | 1605 | if (!task_current(rq, p) && p->nr_cpus_allowed > 1) |
| 1600 | 1606 | enqueue_pushable_dl_task(rq, p); |
| @@ -2787,11 +2793,14 @@ void __dl_clear_params(struct task_struct *p) · 1186 unmodified lines | ||
| 2787 | 2793 | dl_se->dl_bw = 0; |
| 2788 | 2794 | dl_se->dl_density = 0; |
| 2789 | 2795 | |
| 2790 | − dl_se->dl_boosted = 0; | |
| 2791 | 2796 | dl_se->dl_throttled = 0; |
| 2792 | 2797 | dl_se->dl_yielded = 0; |
| 2793 | 2798 | dl_se->dl_non_contending = 0; |
| 2794 | 2799 | dl_se->dl_overrun = 0; |
| 2800 | + | |
| 2801 | +#ifdef CONFIG_RT_MUTEXES | |
| 2802 | + dl_se->pi_se = dl_se; | |
| 2803 | +#endif | |
| 2795 | 2804 | } |
| 2796 | 2805 | |
| 2797 | 2806 | bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr) |
| @@ -5477,6 +5477,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags) · 5476 unmodified lines | ||
| 5477 | 5477 | struct cfs_rq *cfs_rq; |
| 5478 | 5478 | struct sched_entity *se = &p->se; |
| 5479 | 5479 | int idle_h_nr_running = task_has_idle_policy(p); |
| 5480 | + int task_new = !(flags & ENQUEUE_WAKEUP); | |
| 5480 | 5481 | |
| 5481 | 5482 | /* |
| 5482 | 5483 | * The code below (indirectly) updates schedutil which looks at |
| @@ -5549,7 +5550,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags) · 66 unmodified lines | ||
| 5549 | 5550 | * into account, but that is not straightforward to implement, |
| 5550 | 5551 | * and the following generally works well enough in practice. |
| 5551 | 5552 | */ |
| 5552 | − if (flags & ENQUEUE_WAKEUP) | |
| 5553 | + if (!task_new) | |
| 5553 | 5554 | update_overutilized_status(rq); |
| 5554 | 5555 | |
| 5555 | 5556 | enqueue_throttle: |
| @@ -38,7 +38,7 @@ · 37 unmodified lines | ||
| 38 | 38 | #include <linux/filter.h> |
| 39 | 39 | #include <linux/pid.h> |
| 40 | 40 | #include <linux/ptrace.h> |
| 41 | −#include <linux/security.h> | |
| 41 | +#include <linux/capability.h> | |
| 42 | 42 | #include <linux/tracehook.h> |
| 43 | 43 | #include <linux/uaccess.h> |
| 44 | 44 | #include <linux/anon_inodes.h> |
| @@ -558,8 +558,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog) · 513 unmodified lines | ||
| 558 | 558 | * behavior of privileged children. |
| 559 | 559 | */ |
| 560 | 560 | if (!task_no_new_privs(current) && |
| 561 | − security_capable(current_cred(), current_user_ns(), | |
| 562 | − CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) != 0) | |
| 561 | + !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN)) | |
| 563 | 562 | return ERR_PTR(-EACCES); |
| 564 | 563 | |
| 565 | 564 | /* Allocate a new seccomp_filter */ |
| @@ -1484,11 +1484,19 @@ void end_page_writeback(struct page *page) · 1483 unmodified lines | ||
| 1484 | 1484 | rotate_reclaimable_page(page); |
| 1485 | 1485 | } |
| 1486 | 1486 | |
| 1487 | + /* | |
| 1488 | + * Writeback does not hold a page reference of its own, relying | |
| 1489 | + * on truncation to wait for the clearing of PG_writeback. | |
| 1490 | + * But here we must make sure that the page is not freed and | |
| 1491 | + * reused before the wake_up_page(). | |
| 1492 | + */ | |
| 1493 | + get_page(page); | |
| 1487 | 1494 | if (!test_clear_page_writeback(page)) |
| 1488 | 1495 | BUG(); |
| 1489 | 1496 | |
| 1490 | 1497 | smp_mb__after_atomic(); |
| 1491 | 1498 | wake_up_page(page, PG_writeback); |
| 1499 | + put_page(page); | |
| 1492 | 1500 | } |
| 1493 | 1501 | EXPORT_SYMBOL(end_page_writeback); |
| 1494 | 1502 | |
| @@ -2347,10 +2355,15 @@ page_ok: · 852 unmodified lines | ||
| 2347 | 2355 | |
| 2348 | 2356 | page_not_up_to_date: |
| 2349 | 2357 | /* Get exclusive access to the page ... */ |
| 2350 | − if (iocb->ki_flags & IOCB_WAITQ) | |
| 2358 | + if (iocb->ki_flags & IOCB_WAITQ) { | |
| 2359 | + if (written) { | |
| 2360 | + put_page(page); | |
| 2361 | + goto out; | |
| 2362 | + } | |
| 2351 | 2363 | error = lock_page_async(page, iocb->ki_waitq); |
| 2352 | − else | |
| 2364 | + } else { | |
| 2353 | 2365 | error = lock_page_killable(page); |
| 2366 | + } | |
| 2354 | 2367 | if (unlikely(error)) |
| 2355 | 2368 | goto readpage_error; |
| 2356 | 2369 | |
| @@ -2393,10 +2406,15 @@ readpage: · 36 unmodified lines | ||
| 2393 | 2406 | } |
| 2394 | 2407 | |
| 2395 | 2408 | if (!PageUptodate(page)) { |
| 2396 | − if (iocb->ki_flags & IOCB_WAITQ) | |
| 2409 | + if (iocb->ki_flags & IOCB_WAITQ) { | |
| 2410 | + if (written) { | |
| 2411 | + put_page(page); | |
| 2412 | + goto out; | |
| 2413 | + } | |
| 2397 | 2414 | error = lock_page_async(page, iocb->ki_waitq); |
| 2398 | − else | |
| 2415 | + } else { | |
| 2399 | 2416 | error = lock_page_killable(page); |
| 2417 | + } | |
| 2400 | 2418 | |
| 2401 | 2419 | if (unlikely(error)) |
| 2402 | 2420 | goto readpage_error; |
| @@ -710,7 +710,6 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf) · 709 unmodified lines | ||
| 710 | 710 | transparent_hugepage_use_zero_page()) { |
| 711 | 711 | pgtable_t pgtable; |
| 712 | 712 | struct page *zero_page; |
| 713 | − bool set; | |
| 714 | 713 | vm_fault_t ret; |
| 715 | 714 | pgtable = pte_alloc_one(vma->vm_mm); |
| 716 | 715 | if (unlikely(!pgtable)) |
| @@ -723,25 +722,25 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf) · 6 unmodified lines | ||
| 723 | 722 | } |
| 724 | 723 | vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); |
| 725 | 724 | ret = 0; |
| 726 | − set = false; | |
| 727 | 725 | if (pmd_none(*vmf->pmd)) { |
| 728 | 726 | ret = check_stable_address_space(vma->vm_mm); |
| 729 | 727 | if (ret) { |
| 730 | 728 | spin_unlock(vmf->ptl); |
| 729 | + pte_free(vma->vm_mm, pgtable); | |
| 731 | 730 | } else if (userfaultfd_missing(vma)) { |
| 732 | 731 | spin_unlock(vmf->ptl); |
| 732 | + pte_free(vma->vm_mm, pgtable); | |
| 733 | 733 | ret = handle_userfault(vmf, VM_UFFD_MISSING); |
| 734 | 734 | VM_BUG_ON(ret & VM_FAULT_FALLBACK); |
| 735 | 735 | } else { |
| 736 | 736 | set_huge_zero_page(pgtable, vma->vm_mm, vma, |
| 737 | 737 | haddr, vmf->pmd, zero_page); |
| 738 | 738 | spin_unlock(vmf->ptl); |
| 739 | − set = true; | |
| 740 | 739 | } |
| 741 | − } else | |
| 740 | + } else { | |
| 742 | 741 | spin_unlock(vmf->ptl); |
| 743 | − if (!set) | |
| 744 | 742 | pte_free(vma->vm_mm, pgtable); |
| 743 | + } | |
| 745 | 744 | return ret; |
| 746 | 745 | } |
| 747 | 746 | gfp = alloc_hugepage_direct_gfpmask(vma); |
| @@ -226,7 +226,7 @@ static void force_shm_swapin_readahead(struct vm_area_struct *vma, · 225 unmodified lines | ||
| 226 | 226 | struct address_space *mapping) |
| 227 | 227 | { |
| 228 | 228 | XA_STATE(xas, &mapping->i_pages, linear_page_index(vma, start)); |
| 229 | − pgoff_t end_index = end / PAGE_SIZE; | |
| 229 | + pgoff_t end_index = linear_page_index(vma, end + PAGE_SIZE - 1); | |
| 230 | 230 | struct page *page; |
| 231 | 231 | |
| 232 | 232 | rcu_read_lock(); |
| @@ -1231,8 +1231,6 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec, · 998 unmodified lines | ||
| 1231 | 1231 | ret = total_len - iov_iter_count(&iter); |
| 1232 | 1232 | |
| 1233 | 1233 | mmput(mm); |
| 1234 | − return ret; | |
| 1235 | − | |
| 1236 | 1234 | release_task: |
| 1237 | 1235 | put_task_struct(task); |
| 1238 | 1236 | put_pid: |
| @@ -867,8 +867,13 @@ void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val) · 866 unmodified lines | ||
| 867 | 867 | rcu_read_lock(); |
| 868 | 868 | memcg = mem_cgroup_from_obj(p); |
| 869 | 869 | |
| 870 | − /* Untracked pages have no memcg, no lruvec. Update only the node */ | |
| 871 | − if (!memcg || memcg == root_mem_cgroup) { | |
| 870 | + /* | |
| 871 | + * Untracked pages have no memcg, no lruvec. Update only the | |
| 872 | + * node. If we reparent the slab objects to the root memcg, | |
| 873 | + * when we free the slab object, we need to update the per-memcg | |
| 874 | + * vmstats to keep it correct for the root memcg. | |
| 875 | + */ | |
| 876 | + if (!memcg) { | |
| 872 | 877 | __mod_node_page_state(pgdat, idx, val); |
| 873 | 878 | } else { |
| 874 | 879 | lruvec = mem_cgroup_lruvec(memcg, pgdat); |
| @@ -350,24 +350,6 @@ int __ref __add_pages(int nid, unsigned long pfn, unsigned long nr_pages, · 349 unmodified lines | ||
| 350 | 350 | return err; |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | −#ifdef CONFIG_NUMA | |
| 354 | −int __weak memory_add_physaddr_to_nid(u64 start) | |
| 355 | −{ | |
| 356 | − pr_info_once("Unknown online node for memory at 0x%llx, assuming node 0\n", | |
| 357 | − start); | |
| 358 | − return 0; | |
| 359 | −} | |
| 360 | −EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); | |
| 361 | − | |
| 362 | −int __weak phys_to_target_node(u64 start) | |
| 363 | −{ | |
| 364 | − pr_info_once("Unknown target node for memory at 0x%llx, assuming node 0\n", | |
| 365 | − start); | |
| 366 | − return 0; | |
| 367 | −} | |
| 368 | −EXPORT_SYMBOL_GPL(phys_to_target_node); | |
| 369 | −#endif | |
| 370 | − | |
| 371 | 353 | /* find the smallest valid pfn in the range [start_pfn, end_pfn) */ |
| 372 | 354 | static unsigned long find_smallest_section_pfn(int nid, struct zone *zone, |
| 373 | 355 | unsigned long start_pfn, |
| @@ -2754,12 +2754,6 @@ int test_clear_page_writeback(struct page *page) · 2753 unmodified lines | ||
| 2754 | 2754 | } else { |
| 2755 | 2755 | ret = TestClearPageWriteback(page); |
| 2756 | 2756 | } |
| 2757 | − /* | |
| 2758 | − * NOTE: Page might be free now! Writeback doesn't hold a page | |
| 2759 | − * reference on its own, it relies on truncation to wait for | |
| 2760 | − * the clearing of PG_writeback. The below can only access | |
| 2761 | − * page state that is static across allocation cycles. | |
| 2762 | − */ | |
| 2763 | 2757 | if (ret) { |
| 2764 | 2758 | dec_lruvec_state(lruvec, NR_WRITEBACK); |
| 2765 | 2759 | dec_zone_page_state(page, NR_ZONE_WRITE_PENDING); |
| @@ -180,6 +180,7 @@ static const struct file_operations batadv_log_fops = { · 179 unmodified lines | ||
| 180 | 180 | .read = batadv_log_read, |
| 181 | 181 | .poll = batadv_log_poll, |
| 182 | 182 | .llseek = no_llseek, |
| 183 | + .owner = THIS_MODULE, | |
| 183 | 184 | }; |
| 184 | 185 | |
| 185 | 186 | /** |
| @@ -541,10 +541,13 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id, · 540 unmodified lines | ||
| 541 | 541 | |
| 542 | 542 | /* Check for bugs in CAN protocol implementations using af_can.c: |
| 543 | 543 | * 'rcv' will be NULL if no matching list item was found for removal. |
| 544 | + * As this case may potentially happen when closing a socket while | |
| 545 | + * the notifier for removing the CAN netdev is running we just print | |
| 546 | + * a warning here. | |
| 544 | 547 | */ |
| 545 | 548 | if (!rcv) { |
| 546 | − WARN(1, "BUG: receive list entry not found for dev %s, id %03X, mask %03X\n", | |
| 547 | − DNAME(dev), can_id, mask); | |
| 549 | + pr_warn("can: receive list entry not found for dev %s, id %03X, mask %03X\n", | |
| 550 | + DNAME(dev), can_id, mask); | |
| 548 | 551 | goto out; |
| 549 | 552 | } |
| 550 | 553 | |
| @@ -517,7 +517,7 @@ devlink_reload_limit_is_supported(struct devlink *devlink, enum devlink_reload_l · 516 unmodified lines | ||
| 517 | 517 | return test_bit(limit, &devlink->ops->reload_limits); |
| 518 | 518 | } |
| 519 | 519 | |
| 520 | −static int devlink_reload_stat_put(struct sk_buff *msg, enum devlink_reload_action action, | |
| 520 | +static int devlink_reload_stat_put(struct sk_buff *msg, | |
| 521 | 521 | enum devlink_reload_limit limit, u32 value) |
| 522 | 522 | { |
| 523 | 523 | struct nlattr *reload_stats_entry; |
| @@ -526,8 +526,7 @@ static int devlink_reload_stat_put(struct sk_buff *msg, enum devlink_reload_acti · 2 unmodified lines | ||
| 526 | 526 | if (!reload_stats_entry) |
| 527 | 527 | return -EMSGSIZE; |
| 528 | 528 | |
| 529 | − if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_ACTION, action) || | |
| 530 | − nla_put_u8(msg, DEVLINK_ATTR_RELOAD_STATS_LIMIT, limit) || | |
| 529 | + if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_STATS_LIMIT, limit) || | |
| 531 | 530 | nla_put_u32(msg, DEVLINK_ATTR_RELOAD_STATS_VALUE, value)) |
| 532 | 531 | goto nla_put_failure; |
| 533 | 532 | nla_nest_end(msg, reload_stats_entry); |
| @@ -540,7 +539,7 @@ nla_put_failure: · 6 unmodified lines | ||
| 540 | 539 | |
| 541 | 540 | static int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink, bool is_remote) |
| 542 | 541 | { |
| 543 | − struct nlattr *reload_stats_attr; | |
| 542 | + struct nlattr *reload_stats_attr, *act_info, *act_stats; | |
| 544 | 543 | int i, j, stat_idx; |
| 545 | 544 | u32 value; |
| 546 | 545 | |
| @@ -552,17 +551,29 @@ static int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink · 5 unmodified lines | ||
| 552 | 551 | if (!reload_stats_attr) |
| 553 | 552 | return -EMSGSIZE; |
| 554 | 553 | |
| 555 | − for (j = 0; j <= DEVLINK_RELOAD_LIMIT_MAX; j++) { | |
| 556 | − /* Remote stats are shown even if not locally supported. Stats | |
| 557 | − * of actions with unspecified limit are shown though drivers | |
| 558 | − * don't need to register unspecified limit. | |
| 559 | − */ | |
| 560 | − if (!is_remote && j != DEVLINK_RELOAD_LIMIT_UNSPEC && | |
| 561 | − !devlink_reload_limit_is_supported(devlink, j)) | |
| 554 | + for (i = 0; i <= DEVLINK_RELOAD_ACTION_MAX; i++) { | |
| 555 | + if ((!is_remote && | |
| 556 | + !devlink_reload_action_is_supported(devlink, i)) || | |
| 557 | + i == DEVLINK_RELOAD_ACTION_UNSPEC) | |
| 562 | 558 | continue; |
| 563 | − for (i = 0; i <= DEVLINK_RELOAD_ACTION_MAX; i++) { | |
| 564 | − if ((!is_remote && !devlink_reload_action_is_supported(devlink, i)) || | |
| 565 | − i == DEVLINK_RELOAD_ACTION_UNSPEC || | |
| 559 | + act_info = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_INFO); | |
| 560 | + if (!act_info) | |
| 561 | + goto nla_put_failure; | |
| 562 | + | |
| 563 | + if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_ACTION, i)) | |
| 564 | + goto action_info_nest_cancel; | |
| 565 | + act_stats = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_STATS); | |
| 566 | + if (!act_stats) | |
| 567 | + goto action_info_nest_cancel; | |
| 568 | + | |
| 569 | + for (j = 0; j <= DEVLINK_RELOAD_LIMIT_MAX; j++) { | |
| 570 | + /* Remote stats are shown even if not locally supported. | |
| 571 | + * Stats of actions with unspecified limit are shown | |
| 572 | + * though drivers don't need to register unspecified | |
| 573 | + * limit. | |
| 574 | + */ | |
| 575 | + if ((!is_remote && j != DEVLINK_RELOAD_LIMIT_UNSPEC && | |
| 576 | + !devlink_reload_limit_is_supported(devlink, j)) || | |
| 566 | 577 | devlink_reload_combination_is_invalid(i, j)) |
| 567 | 578 | continue; |
| 568 | 579 | |
| @@ -571,13 +582,19 @@ static int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink · 2 unmodified lines | ||
| 571 | 582 | value = devlink->stats.reload_stats[stat_idx]; |
| 572 | 583 | else |
| 573 | 584 | value = devlink->stats.remote_reload_stats[stat_idx]; |
| 574 | − if (devlink_reload_stat_put(msg, i, j, value)) | |
| 575 | − goto nla_put_failure; | |
| 585 | + if (devlink_reload_stat_put(msg, j, value)) | |
| 586 | + goto action_stats_nest_cancel; | |
| 576 | 587 | } |
| 588 | + nla_nest_end(msg, act_stats); | |
| 589 | + nla_nest_end(msg, act_info); | |
| 577 | 590 | } |
| 578 | 591 | nla_nest_end(msg, reload_stats_attr); |
| 579 | 592 | return 0; |
| 580 | 593 | |
| 594 | +action_stats_nest_cancel: | |
| 595 | + nla_nest_cancel(msg, act_stats); | |
| 596 | +action_info_nest_cancel: | |
| 597 | + nla_nest_cancel(msg, act_info); | |
| 581 | 598 | nla_put_failure: |
| 582 | 599 | nla_nest_cancel(msg, reload_stats_attr); |
| 583 | 600 | return -EMSGSIZE; |
| @@ -755,6 +772,8 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, · 171 unmodified lines | ||
| 755 | 772 | if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) |
| 756 | 773 | goto nla_put_failure; |
| 757 | 774 | |
| 775 | + /* Hold rtnl lock while accessing port's netdev attributes. */ | |
| 776 | + rtnl_lock(); | |
| 758 | 777 | spin_lock_bh(&devlink_port->type_lock); |
| 759 | 778 | if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type)) |
| 760 | 779 | goto nla_put_failure_type_locked; |
| @@ -763,9 +782,10 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, · 2 unmodified lines | ||
| 763 | 782 | devlink_port->desired_type)) |
| 764 | 783 | goto nla_put_failure_type_locked; |
| 765 | 784 | if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) { |
| 785 | + struct net *net = devlink_net(devlink_port->devlink); | |
| 766 | 786 | struct net_device *netdev = devlink_port->type_dev; |
| 767 | 787 | |
| 768 | − if (netdev && | |
| 788 | + if (netdev && net_eq(net, dev_net(netdev)) && | |
| 769 | 789 | (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX, |
| 770 | 790 | netdev->ifindex) || |
| 771 | 791 | nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME, |
| @@ -781,6 +801,7 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, · 9 unmodified lines | ||
| 781 | 801 | goto nla_put_failure_type_locked; |
| 782 | 802 | } |
| 783 | 803 | spin_unlock_bh(&devlink_port->type_lock); |
| 804 | + rtnl_unlock(); | |
| 784 | 805 | if (devlink_nl_port_attrs_put(msg, devlink_port)) |
| 785 | 806 | goto nla_put_failure; |
| 786 | 807 | if (devlink_nl_port_function_attrs_put(msg, devlink_port, extack)) |
| @@ -791,6 +812,7 @@ static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, · 4 unmodified lines | ||
| 791 | 812 | |
| 792 | 813 | nla_put_failure_type_locked: |
| 793 | 814 | spin_unlock_bh(&devlink_port->type_lock); |
| 815 | + rtnl_unlock(); | |
| 794 | 816 | nla_put_failure: |
| 795 | 817 | genlmsg_cancel(msg, hdr); |
| 796 | 818 | return -EMSGSIZE; |
| @@ -99,9 +99,14 @@ void gro_cells_destroy(struct gro_cells *gcells) · 98 unmodified lines | ||
| 99 | 99 | struct gro_cell *cell = per_cpu_ptr(gcells->cells, i); |
| 100 | 100 | |
| 101 | 101 | napi_disable(&cell->napi); |
| 102 | − netif_napi_del(&cell->napi); | |
| 102 | + __netif_napi_del(&cell->napi); | |
| 103 | 103 | __skb_queue_purge(&cell->napi_skbs); |
| 104 | 104 | } |
| 105 | + /* This barrier is needed because netpoll could access dev->napi_list | |
| 106 | + * under rcu protection. | |
| 107 | + */ | |
| 108 | + synchronize_net(); | |
| 109 | + | |
| 105 | 110 | free_percpu(gcells->cells); |
| 106 | 111 | gcells->cells = NULL; |
| 107 | 112 | } |
| @@ -4562,7 +4562,7 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk) · 4561 unmodified lines | ||
| 4562 | 4562 | if (skb && (skb_next = skb_peek(q))) { |
| 4563 | 4563 | icmp_next = is_icmp_err_skb(skb_next); |
| 4564 | 4564 | if (icmp_next) |
| 4565 | − sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_origin; | |
| 4565 | + sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_errno; | |
| 4566 | 4566 | } |
| 4567 | 4567 | spin_unlock_irqrestore(&q->lock, flags); |
| 4568 | 4568 | |
| @@ -427,7 +427,7 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk, · 426 unmodified lines | ||
| 427 | 427 | |
| 428 | 428 | if (__inet_inherit_port(sk, newsk) < 0) |
| 429 | 429 | goto put_and_exit; |
| 430 | − *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); | |
| 430 | + *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), NULL); | |
| 431 | 431 | if (*own_req) |
| 432 | 432 | ireq->ireq_opt = NULL; |
| 433 | 433 | else |
| @@ -533,7 +533,7 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, · 532 unmodified lines | ||
| 533 | 533 | dccp_done(newsk); |
| 534 | 534 | goto out; |
| 535 | 535 | } |
| 536 | − *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); | |
| 536 | + *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), NULL); | |
| 537 | 537 | /* Clone pktoptions received with SYN, if we own the req */ |
| 538 | 538 | if (*own_req && ireq->pktopts) { |
| 539 | 539 | newnp->pktoptions = skb_clone(ireq->pktopts, GFP_ATOMIC); |
| @@ -787,7 +787,7 @@ static void reqsk_queue_hash_req(struct request_sock *req, · 786 unmodified lines | ||
| 787 | 787 | timer_setup(&req->rsk_timer, reqsk_timer_handler, TIMER_PINNED); |
| 788 | 788 | mod_timer(&req->rsk_timer, jiffies + timeout); |
| 789 | 789 | |
| 790 | − inet_ehash_insert(req_to_sk(req), NULL); | |
| 790 | + inet_ehash_insert(req_to_sk(req), NULL, NULL); | |
| 791 | 791 | /* before letting lookups find us, make sure all req fields |
| 792 | 792 | * are committed to memory and refcnt initialized. |
| 793 | 793 | */ |
| @@ -20,6 +20,9 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <net/addrconf.h> |
| 21 | 21 | #include <net/inet_connection_sock.h> |
| 22 | 22 | #include <net/inet_hashtables.h> |
| 23 | +#if IS_ENABLED(CONFIG_IPV6) | |
| 24 | +#include <net/inet6_hashtables.h> | |
| 25 | +#endif | |
| 23 | 26 | #include <net/secure_seq.h> |
| 24 | 27 | #include <net/ip.h> |
| 25 | 28 | #include <net/tcp.h> |
| @@ -508,10 +511,52 @@ static u32 inet_sk_port_offset(const struct sock *sk) · 482 unmodified lines | ||
| 508 | 511 | inet->inet_dport); |
| 509 | 512 | } |
| 510 | 513 | |
| 511 | −/* insert a socket into ehash, and eventually remove another one | |
| 512 | − * (The another one can be a SYN_RECV or TIMEWAIT | |
| 514 | +/* Searches for an exsiting socket in the ehash bucket list. | |
| 515 | + * Returns true if found, false otherwise. | |
| 513 | 516 | */ |
| 514 | −bool inet_ehash_insert(struct sock *sk, struct sock *osk) | |
| 517 | +static bool inet_ehash_lookup_by_sk(struct sock *sk, | |
| 518 | + struct hlist_nulls_head *list) | |
| 519 | +{ | |
| 520 | + const __portpair ports = INET_COMBINED_PORTS(sk->sk_dport, sk->sk_num); | |
| 521 | + const int sdif = sk->sk_bound_dev_if; | |
| 522 | + const int dif = sk->sk_bound_dev_if; | |
| 523 | + const struct hlist_nulls_node *node; | |
| 524 | + struct net *net = sock_net(sk); | |
| 525 | + struct sock *esk; | |
| 526 | + | |
| 527 | + INET_ADDR_COOKIE(acookie, sk->sk_daddr, sk->sk_rcv_saddr); | |
| 528 | + | |
| 529 | + sk_nulls_for_each_rcu(esk, node, list) { | |
| 530 | + if (esk->sk_hash != sk->sk_hash) | |
| 531 | + continue; | |
| 532 | + if (sk->sk_family == AF_INET) { | |
| 533 | + if (unlikely(INET_MATCH(esk, net, acookie, | |
| 534 | + sk->sk_daddr, | |
| 535 | + sk->sk_rcv_saddr, | |
| 536 | + ports, dif, sdif))) { | |
| 537 | + return true; | |
| 538 | + } | |
| 539 | + } | |
| 540 | +#if IS_ENABLED(CONFIG_IPV6) | |
| 541 | + else if (sk->sk_family == AF_INET6) { | |
| 542 | + if (unlikely(INET6_MATCH(esk, net, | |
| 543 | + &sk->sk_v6_daddr, | |
| 544 | + &sk->sk_v6_rcv_saddr, | |
| 545 | + ports, dif, sdif))) { | |
| 546 | + return true; | |
| 547 | + } | |
| 548 | + } | |
| 549 | +#endif | |
| 550 | + } | |
| 551 | + return false; | |
| 552 | +} | |
| 553 | + | |
| 554 | +/* Insert a socket into ehash, and eventually remove another one | |
| 555 | + * (The another one can be a SYN_RECV or TIMEWAIT) | |
| 556 | + * If an existing socket already exists, socket sk is not inserted, | |
| 557 | + * and sets found_dup_sk parameter to true. | |
| 558 | + */ | |
| 559 | +bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk) | |
| 515 | 560 | { |
| 516 | 561 | struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; |
| 517 | 562 | struct hlist_nulls_head *list; |
| @@ -530,16 +575,23 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk) · 12 unmodified lines | ||
| 530 | 575 | if (osk) { |
| 531 | 576 | WARN_ON_ONCE(sk->sk_hash != osk->sk_hash); |
| 532 | 577 | ret = sk_nulls_del_node_init_rcu(osk); |
| 578 | + } else if (found_dup_sk) { | |
| 579 | + *found_dup_sk = inet_ehash_lookup_by_sk(sk, list); | |
| 580 | + if (*found_dup_sk) | |
| 581 | + ret = false; | |
| 533 | 582 | } |
| 583 | + | |
| 534 | 584 | if (ret) |
| 535 | 585 | __sk_nulls_add_node_rcu(sk, list); |
| 586 | + | |
| 536 | 587 | spin_unlock(lock); |
| 588 | + | |
| 537 | 589 | return ret; |
| 538 | 590 | } |
| 539 | 591 | |
| 540 | −bool inet_ehash_nolisten(struct sock *sk, struct sock *osk) | |
| 592 | +bool inet_ehash_nolisten(struct sock *sk, struct sock *osk, bool *found_dup_sk) | |
| 541 | 593 | { |
| 542 | − bool ok = inet_ehash_insert(sk, osk); | |
| 594 | + bool ok = inet_ehash_insert(sk, osk, found_dup_sk); | |
| 543 | 595 | |
| 544 | 596 | if (ok) { |
| 545 | 597 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
| @@ -583,7 +635,7 @@ int __inet_hash(struct sock *sk, struct sock *osk) · 37 unmodified lines | ||
| 583 | 635 | int err = 0; |
| 584 | 636 | |
| 585 | 637 | if (sk->sk_state != TCP_LISTEN) { |
| 586 | − inet_ehash_nolisten(sk, osk); | |
| 638 | + inet_ehash_nolisten(sk, osk, NULL); | |
| 587 | 639 | return 0; |
| 588 | 640 | } |
| 589 | 641 | WARN_ON(!sk_unhashed(sk)); |
| @@ -679,7 +731,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, · 89 unmodified lines | ||
| 679 | 731 | tb = inet_csk(sk)->icsk_bind_hash; |
| 680 | 732 | spin_lock_bh(&head->lock); |
| 681 | 733 | if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { |
| 682 | − inet_ehash_nolisten(sk, NULL); | |
| 734 | + inet_ehash_nolisten(sk, NULL, NULL); | |
| 683 | 735 | spin_unlock_bh(&head->lock); |
| 684 | 736 | return 0; |
| 685 | 737 | } |
| @@ -758,7 +810,7 @@ ok: · 72 unmodified lines | ||
| 758 | 810 | inet_bind_hash(sk, tb, port); |
| 759 | 811 | if (sk_unhashed(sk)) { |
| 760 | 812 | inet_sk(sk)->inet_sport = htons(port); |
| 761 | − inet_ehash_nolisten(sk, (struct sock *)tw); | |
| 813 | + inet_ehash_nolisten(sk, (struct sock *)tw, NULL); | |
| 762 | 814 | } |
| 763 | 815 | if (tw) |
| 764 | 816 | inet_twsk_bind_unhash(tw, hinfo); |
| @@ -198,6 +198,11 @@ static void tcp_reinit_congestion_control(struct sock *sk, · 197 unmodified lines | ||
| 198 | 198 | icsk->icsk_ca_setsockopt = 1; |
| 199 | 199 | memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv)); |
| 200 | 200 | |
| 201 | + if (ca->flags & TCP_CONG_NEEDS_ECN) | |
| 202 | + INET_ECN_xmit(sk); | |
| 203 | + else | |
| 204 | + INET_ECN_dontxmit(sk); | |
| 205 | + | |
| 201 | 206 | if (!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) |
| 202 | 207 | tcp_init_congestion_control(sk); |
| 203 | 208 | } |
| @@ -980,17 +980,22 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst, · 979 unmodified lines | ||
| 980 | 980 | |
| 981 | 981 | skb = tcp_make_synack(sk, dst, req, foc, synack_type, syn_skb); |
| 982 | 982 | |
| 983 | − tos = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ? | |
| 984 | − tcp_rsk(req)->syn_tos : inet_sk(sk)->tos; | |
| 985 | − | |
| 986 | 983 | if (skb) { |
| 987 | 984 | __tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr); |
| 988 | 985 | |
| 986 | + tos = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ? | |
| 987 | + tcp_rsk(req)->syn_tos & ~INET_ECN_MASK : | |
| 988 | + inet_sk(sk)->tos; | |
| 989 | + | |
| 990 | + if (!INET_ECN_is_capable(tos) && | |
| 991 | + tcp_bpf_ca_needs_ecn((struct sock *)req)) | |
| 992 | + tos |= INET_ECN_ECT_0; | |
| 993 | + | |
| 989 | 994 | rcu_read_lock(); |
| 990 | 995 | err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr, |
| 991 | 996 | ireq->ir_rmt_addr, |
| 992 | 997 | rcu_dereference(ireq->ireq_opt), |
| 993 | − tos & ~INET_ECN_MASK); | |
| 998 | + tos); | |
| 994 | 999 | rcu_read_unlock(); |
| 995 | 1000 | err = net_xmit_eval(err); |
| 996 | 1001 | } |
| @@ -1498,6 +1503,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, · 501 unmodified lines | ||
| 1498 | 1503 | bool *own_req) |
| 1499 | 1504 | { |
| 1500 | 1505 | struct inet_request_sock *ireq; |
| 1506 | + bool found_dup_sk = false; | |
| 1501 | 1507 | struct inet_sock *newinet; |
| 1502 | 1508 | struct tcp_sock *newtp; |
| 1503 | 1509 | struct sock *newsk; |
| @@ -1575,12 +1581,22 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, · 71 unmodified lines | ||
| 1575 | 1581 | |
| 1576 | 1582 | if (__inet_inherit_port(sk, newsk) < 0) |
| 1577 | 1583 | goto put_and_exit; |
| 1578 | − *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); | |
| 1584 | + *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), | |
| 1585 | + &found_dup_sk); | |
| 1579 | 1586 | if (likely(*own_req)) { |
| 1580 | 1587 | tcp_move_syn(newtp, req); |
| 1581 | 1588 | ireq->ireq_opt = NULL; |
| 1582 | 1589 | } else { |
| 1583 | − newinet->inet_opt = NULL; | |
| 1590 | + if (!req_unhash && found_dup_sk) { | |
| 1591 | + /* This code path should only be executed in the | |
| 1592 | + * syncookie case only | |
| 1593 | + */ | |
| 1594 | + bh_unlock_sock(newsk); | |
| 1595 | + sock_put(newsk); | |
| 1596 | + newsk = NULL; | |
| 1597 | + } else { | |
| 1598 | + newinet->inet_opt = NULL; | |
| 1599 | + } | |
| 1584 | 1600 | } |
| 1585 | 1601 | return newsk; |
| 1586 | 1602 | |
| @@ -306,7 +306,9 @@ static int ip6addrlbl_del(struct net *net, · 305 unmodified lines | ||
| 306 | 306 | /* add default label */ |
| 307 | 307 | static int __net_init ip6addrlbl_net_init(struct net *net) |
| 308 | 308 | { |
| 309 | − int err = 0; | |
| 309 | + struct ip6addrlbl_entry *p = NULL; | |
| 310 | + struct hlist_node *n; | |
| 311 | + int err; | |
| 310 | 312 | int i; |
| 311 | 313 | |
| 312 | 314 | ADDRLABEL(KERN_DEBUG "%s\n", __func__); |
| @@ -315,14 +317,20 @@ static int __net_init ip6addrlbl_net_init(struct net *net) · 2 unmodified lines | ||
| 315 | 317 | INIT_HLIST_HEAD(&net->ipv6.ip6addrlbl_table.head); |
| 316 | 318 | |
| 317 | 319 | for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { |
| 318 | − int ret = ip6addrlbl_add(net, | |
| 319 | − ip6addrlbl_init_table[i].prefix, | |
| 320 | − ip6addrlbl_init_table[i].prefixlen, | |
| 321 | − 0, | |
| 322 | − ip6addrlbl_init_table[i].label, 0); | |
| 323 | − /* XXX: should we free all rules when we catch an error? */ | |
| 324 | − if (ret && (!err || err != -ENOMEM)) | |
| 325 | − err = ret; | |
| 320 | + err = ip6addrlbl_add(net, | |
| 321 | + ip6addrlbl_init_table[i].prefix, | |
| 322 | + ip6addrlbl_init_table[i].prefixlen, | |
| 323 | + 0, | |
| 324 | + ip6addrlbl_init_table[i].label, 0); | |
| 325 | + if (err) | |
| 326 | + goto err_ip6addrlbl_add; | |
| 327 | + } | |
| 328 | + return 0; | |
| 329 | + | |
| 330 | +err_ip6addrlbl_add: | |
| 331 | + hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) { | |
| 332 | + hlist_del_rcu(&p->list); | |
| 333 | + kfree_rcu(p, rcu); | |
| 326 | 334 | } |
| 327 | 335 | return err; |
| 328 | 336 | } |
| @@ -527,15 +527,20 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst, · 526 unmodified lines | ||
| 527 | 527 | if (np->repflow && ireq->pktopts) |
| 528 | 528 | fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts)); |
| 529 | 529 | |
| 530 | + tclass = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ? | |
| 531 | + tcp_rsk(req)->syn_tos & ~INET_ECN_MASK : | |
| 532 | + np->tclass; | |
| 533 | + | |
| 534 | + if (!INET_ECN_is_capable(tclass) && | |
| 535 | + tcp_bpf_ca_needs_ecn((struct sock *)req)) | |
| 536 | + tclass |= INET_ECN_ECT_0; | |
| 537 | + | |
| 530 | 538 | rcu_read_lock(); |
| 531 | 539 | opt = ireq->ipv6_opt; |
| 532 | − tclass = sock_net(sk)->ipv4.sysctl_tcp_reflect_tos ? | |
| 533 | − tcp_rsk(req)->syn_tos : np->tclass; | |
| 534 | 540 | if (!opt) |
| 535 | 541 | opt = rcu_dereference(np->opt); |
| 536 | 542 | err = ip6_xmit(sk, skb, fl6, sk->sk_mark, opt, |
| 537 | − tclass & ~INET_ECN_MASK, | |
| 538 | − sk->sk_priority); | |
| 543 | + tclass, sk->sk_priority); | |
| 539 | 544 | rcu_read_unlock(); |
| 540 | 545 | err = net_xmit_eval(err); |
| 541 | 546 | } |
| @@ -1193,6 +1198,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * · 651 unmodified lines | ||
| 1193 | 1198 | const struct ipv6_pinfo *np = tcp_inet6_sk(sk); |
| 1194 | 1199 | struct ipv6_txoptions *opt; |
| 1195 | 1200 | struct inet_sock *newinet; |
| 1201 | + bool found_dup_sk = false; | |
| 1196 | 1202 | struct tcp_sock *newtp; |
| 1197 | 1203 | struct sock *newsk; |
| 1198 | 1204 | #ifdef CONFIG_TCP_MD5SIG |
| @@ -1368,7 +1374,8 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * · 169 unmodified lines | ||
| 1368 | 1374 | tcp_done(newsk); |
| 1369 | 1375 | goto out; |
| 1370 | 1376 | } |
| 1371 | − *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); | |
| 1377 | + *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), | |
| 1378 | + &found_dup_sk); | |
| 1372 | 1379 | if (*own_req) { |
| 1373 | 1380 | tcp_move_syn(newtp, req); |
| 1374 | 1381 | |
| @@ -1383,6 +1390,15 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * · 8 unmodified lines | ||
| 1383 | 1390 | skb_set_owner_r(newnp->pktoptions, newsk); |
| 1384 | 1391 | } |
| 1385 | 1392 | } |
| 1393 | + } else { | |
| 1394 | + if (!req_unhash && found_dup_sk) { | |
| 1395 | + /* This code path should only be executed in the | |
| 1396 | + * syncookie case only | |
| 1397 | + */ | |
| 1398 | + bh_unlock_sock(newsk); | |
| 1399 | + sock_put(newsk); | |
| 1400 | + newsk = NULL; | |
| 1401 | + } | |
| 1386 | 1402 | } |
| 1387 | 1403 | |
| 1388 | 1404 | return newsk; |
| @@ -1645,7 +1645,7 @@ static int iucv_callback_connreq(struct iucv_path *path, · 1644 unmodified lines | ||
| 1645 | 1645 | } |
| 1646 | 1646 | |
| 1647 | 1647 | /* Create the new socket */ |
| 1648 | − nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC, 0); | |
| 1648 | + nsk = iucv_sock_alloc(NULL, sk->sk_protocol, GFP_ATOMIC, 0); | |
| 1649 | 1649 | if (!nsk) { |
| 1650 | 1650 | err = pr_iucv->path_sever(path, user_data); |
| 1651 | 1651 | iucv_path_free(path); |
| @@ -1851,7 +1851,7 @@ static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb) · 199 unmodified lines | ||
| 1851 | 1851 | goto out; |
| 1852 | 1852 | } |
| 1853 | 1853 | |
| 1854 | − nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC, 0); | |
| 1854 | + nsk = iucv_sock_alloc(NULL, sk->sk_protocol, GFP_ATOMIC, 0); | |
| 1855 | 1855 | bh_lock_sock(sk); |
| 1856 | 1856 | if ((sk->sk_state != IUCV_LISTEN) || |
| 1857 | 1857 | sk_acceptq_is_full(sk) || |
| @@ -543,9 +543,8 @@ create_msk: · 542 unmodified lines | ||
| 543 | 543 | fallback = true; |
| 544 | 544 | } else if (subflow_req->mp_join) { |
| 545 | 545 | mptcp_get_options(skb, &mp_opt); |
| 546 | − if (!mp_opt.mp_join || | |
| 547 | − !mptcp_can_accept_new_subflow(subflow_req->msk) || | |
| 548 | − !subflow_hmac_valid(req, &mp_opt)) { | |
| 546 | + if (!mp_opt.mp_join || !subflow_hmac_valid(req, &mp_opt) || | |
| 547 | + !mptcp_can_accept_new_subflow(subflow_req->msk)) { | |
| 549 | 548 | SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); |
| 550 | 549 | fallback = true; |
| 551 | 550 | } |
| @@ -958,14 +958,13 @@ static int dec_ttl_exception_handler(struct datapath *dp, struct sk_buff *skb, · 957 unmodified lines | ||
| 958 | 958 | { |
| 959 | 959 | /* The first action is always 'OVS_DEC_TTL_ATTR_ARG'. */ |
| 960 | 960 | struct nlattr *dec_ttl_arg = nla_data(attr); |
| 961 | − int rem = nla_len(attr); | |
| 962 | 961 | |
| 963 | 962 | if (nla_len(dec_ttl_arg)) { |
| 964 | − struct nlattr *actions = nla_next(dec_ttl_arg, &rem); | |
| 963 | + struct nlattr *actions = nla_data(dec_ttl_arg); | |
| 965 | 964 | |
| 966 | 965 | if (actions) |
| 967 | − return clone_execute(dp, skb, key, 0, actions, rem, | |
| 968 | − last, false); | |
| 966 | + return clone_execute(dp, skb, key, 0, nla_data(actions), | |
| 967 | + nla_len(actions), last, false); | |
| 969 | 968 | } |
| 970 | 969 | consume_skb(skb); |
| 971 | 970 | return 0; |
| @@ -2503,28 +2503,42 @@ static int validate_and_copy_dec_ttl(struct net *net, · 2502 unmodified lines | ||
| 2503 | 2503 | __be16 eth_type, __be16 vlan_tci, |
| 2504 | 2504 | u32 mpls_label_count, bool log) |
| 2505 | 2505 | { |
| 2506 | − int start, err; | |
| 2507 | − u32 nested = true; | |
| 2506 | + const struct nlattr *attrs[OVS_DEC_TTL_ATTR_MAX + 1]; | |
| 2507 | + int start, action_start, err, rem; | |
| 2508 | + const struct nlattr *a, *actions; | |
| 2509 | + | |
| 2510 | + memset(attrs, 0, sizeof(attrs)); | |
| 2511 | + nla_for_each_nested(a, attr, rem) { | |
| 2512 | + int type = nla_type(a); | |
| 2508 | 2513 | |
| 2509 | − if (!nla_len(attr)) | |
| 2510 | − return ovs_nla_add_action(sfa, OVS_ACTION_ATTR_DEC_TTL, | |
| 2511 | − NULL, 0, log); | |
| 2514 | + /* Ignore unknown attributes to be future proof. */ | |
| 2515 | + if (type > OVS_DEC_TTL_ATTR_MAX) | |
| 2516 | + continue; | |
| 2517 | + | |
| 2518 | + if (!type || attrs[type]) | |
| 2519 | + return -EINVAL; | |
| 2520 | + | |
| 2521 | + attrs[type] = a; | |
| 2522 | + } | |
| 2523 | + | |
| 2524 | + actions = attrs[OVS_DEC_TTL_ATTR_ACTION]; | |
| 2525 | + if (rem || !actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN)) | |
| 2526 | + return -EINVAL; | |
| 2512 | 2527 | |
| 2513 | 2528 | start = add_nested_action_start(sfa, OVS_ACTION_ATTR_DEC_TTL, log); |
| 2514 | 2529 | if (start < 0) |
| 2515 | 2530 | return start; |
| 2516 | 2531 | |
| 2517 | − err = ovs_nla_add_action(sfa, OVS_DEC_TTL_ATTR_ACTION, &nested, | |
| 2518 | − sizeof(nested), log); | |
| 2519 | − | |
| 2520 | − if (err) | |
| 2521 | − return err; | |
| 2532 | + action_start = add_nested_action_start(sfa, OVS_DEC_TTL_ATTR_ACTION, log); | |
| 2533 | + if (action_start < 0) | |
| 2534 | + return start; | |
| 2522 | 2535 | |
| 2523 | − err = __ovs_nla_copy_actions(net, attr, key, sfa, eth_type, | |
| 2536 | + err = __ovs_nla_copy_actions(net, actions, key, sfa, eth_type, | |
| 2524 | 2537 | vlan_tci, mpls_label_count, log); |
| 2525 | 2538 | if (err) |
| 2526 | 2539 | return err; |
| 2527 | 2540 | |
| 2541 | + add_nested_action_end(*sfa, action_start); | |
| 2528 | 2542 | add_nested_action_end(*sfa, start); |
| 2529 | 2543 | return 0; |
| 2530 | 2544 | } |
| @@ -3487,20 +3501,42 @@ out: · 956 unmodified lines | ||
| 3487 | 3501 | static int dec_ttl_action_to_attr(const struct nlattr *attr, |
| 3488 | 3502 | struct sk_buff *skb) |
| 3489 | 3503 | { |
| 3490 | − int err = 0, rem = nla_len(attr); | |
| 3491 | − struct nlattr *start; | |
| 3504 | + struct nlattr *start, *action_start; | |
| 3505 | + const struct nlattr *a; | |
| 3506 | + int err = 0, rem; | |
| 3492 | 3507 | |
| 3493 | 3508 | start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_DEC_TTL); |
| 3494 | − | |
| 3495 | 3509 | if (!start) |
| 3496 | 3510 | return -EMSGSIZE; |
| 3497 | 3511 | |
| 3498 | − err = ovs_nla_put_actions(nla_data(attr), rem, skb); | |
| 3499 | − if (err) | |
| 3500 | − nla_nest_cancel(skb, start); | |
| 3501 | − else | |
| 3502 | − nla_nest_end(skb, start); | |
| 3512 | + nla_for_each_attr(a, nla_data(attr), nla_len(attr), rem) { | |
| 3513 | + switch (nla_type(a)) { | |
| 3514 | + case OVS_DEC_TTL_ATTR_ACTION: | |
| 3515 | + | |
| 3516 | + action_start = nla_nest_start_noflag(skb, OVS_DEC_TTL_ATTR_ACTION); | |
| 3517 | + if (!action_start) { | |
| 3518 | + err = -EMSGSIZE; | |
| 3519 | + goto out; | |
| 3520 | + } | |
| 3521 | + | |
| 3522 | + err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb); | |
| 3523 | + if (err) | |
| 3524 | + goto out; | |
| 3525 | + | |
| 3526 | + nla_nest_end(skb, action_start); | |
| 3527 | + break; | |
| 3503 | 3528 | |
| 3529 | + default: | |
| 3530 | + /* Ignore all other option to be future compatible */ | |
| 3531 | + break; | |
| 3532 | + } | |
| 3533 | + } | |
| 3534 | + | |
| 3535 | + nla_nest_end(skb, start); | |
| 3536 | + return 0; | |
| 3537 | + | |
| 3538 | +out: | |
| 3539 | + nla_nest_cancel(skb, start); | |
| 3504 | 3540 | return err; |
| 3505 | 3541 | } |
| 3506 | 3542 | |
| @@ -94,8 +94,8 @@ · 93 unmodified lines | ||
| 94 | 94 | |
| 95 | 95 | /* |
| 96 | 96 | Assumptions: |
| 97 | − - If the device has no dev->header_ops, there is no LL header visible | |
| 98 | − above the device. In this case, its hard_header_len should be 0. | |
| 97 | + - If the device has no dev->header_ops->create, there is no LL header | |
| 98 | + visible above the device. In this case, its hard_header_len should be 0. | |
| 99 | 99 | The device may prepend its own header internally. In this case, its |
| 100 | 100 | needed_headroom should be set to the space needed for it to add its |
| 101 | 101 | internal header. |
| @@ -109,26 +109,26 @@ · 7 unmodified lines | ||
| 109 | 109 | On receive: |
| 110 | 110 | ----------- |
| 111 | 111 | |
| 112 | −Incoming, dev->header_ops != NULL | |
| 112 | +Incoming, dev_has_header(dev) == true | |
| 113 | 113 | mac_header -> ll header |
| 114 | 114 | data -> data |
| 115 | 115 | |
| 116 | −Outgoing, dev->header_ops != NULL | |
| 116 | +Outgoing, dev_has_header(dev) == true | |
| 117 | 117 | mac_header -> ll header |
| 118 | 118 | data -> ll header |
| 119 | 119 | |
| 120 | −Incoming, dev->header_ops == NULL | |
| 120 | +Incoming, dev_has_header(dev) == false | |
| 121 | 121 | mac_header -> data |
| 122 | 122 | However drivers often make it point to the ll header. |
| 123 | 123 | This is incorrect because the ll header should be invisible to us. |
| 124 | 124 | data -> data |
| 125 | 125 | |
| 126 | −Outgoing, dev->header_ops == NULL | |
| 126 | +Outgoing, dev_has_header(dev) == false | |
| 127 | 127 | mac_header -> data. ll header is invisible to us. |
| 128 | 128 | data -> data |
| 129 | 129 | |
| 130 | 130 | Resume |
| 131 | − If dev->header_ops == NULL we are unable to restore the ll header, | |
| 131 | + If dev_has_header(dev) == false we are unable to restore the ll header, | |
| 132 | 132 | because it is invisible to us. |
| 133 | 133 | |
| 134 | 134 | |
| @@ -2083,7 +2083,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, · 1948 unmodified lines | ||
| 2083 | 2083 | |
| 2084 | 2084 | skb->dev = dev; |
| 2085 | 2085 | |
| 2086 | − if (dev->header_ops) { | |
| 2086 | + if (dev_has_header(dev)) { | |
| 2087 | 2087 | /* The device has an explicit notion of ll header, |
| 2088 | 2088 | * exported to higher levels. |
| 2089 | 2089 | * |
| @@ -2212,7 +2212,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, · 122 unmodified lines | ||
| 2212 | 2212 | if (!net_eq(dev_net(dev), sock_net(sk))) |
| 2213 | 2213 | goto drop; |
| 2214 | 2214 | |
| 2215 | − if (dev->header_ops) { | |
| 2215 | + if (dev_has_header(dev)) { | |
| 2216 | 2216 | if (sk->sk_type != SOCK_DGRAM) |
| 2217 | 2217 | skb_push(skb, skb->data - skb_mac_header(skb)); |
| 2218 | 2218 | else if (skb->pkt_type == PACKET_OUTGOING) { |
| @@ -96,10 +96,19 @@ static void rose_loopback_timer(struct timer_list *unused) · 95 unmodified lines | ||
| 96 | 96 | } |
| 97 | 97 | |
| 98 | 98 | if (frametype == ROSE_CALL_REQUEST) { |
| 99 | − if ((dev = rose_dev_get(dest)) != NULL) { | |
| 100 | − if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) | |
| 101 | − kfree_skb(skb); | |
| 102 | − } else { | |
| 99 | + if (!rose_loopback_neigh->dev) { | |
| 100 | + kfree_skb(skb); | |
| 101 | + continue; | |
| 102 | + } | |
| 103 | + | |
| 104 | + dev = rose_dev_get(dest); | |
| 105 | + if (!dev) { | |
| 106 | + kfree_skb(skb); | |
| 107 | + continue; | |
| 108 | + } | |
| 109 | + | |
| 110 | + if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) { | |
| 111 | + dev_put(dev); | |
| 103 | 112 | kfree_skb(skb); |
| 104 | 113 | } |
| 105 | 114 | } else { |
| @@ -1262,6 +1262,8 @@ void tls_device_offload_cleanup_rx(struct sock *sk) · 1261 unmodified lines | ||
| 1262 | 1262 | if (tls_ctx->tx_conf != TLS_HW) { |
| 1263 | 1263 | dev_put(netdev); |
| 1264 | 1264 | tls_ctx->netdev = NULL; |
| 1265 | + } else { | |
| 1266 | + set_bit(TLS_RX_DEV_CLOSED, &tls_ctx->flags); | |
| 1265 | 1267 | } |
| 1266 | 1268 | out: |
| 1267 | 1269 | up_read(&device_offload_lock); |
| @@ -1291,7 +1293,8 @@ static int tls_device_down(struct net_device *netdev) · 23 unmodified lines | ||
| 1291 | 1293 | if (ctx->tx_conf == TLS_HW) |
| 1292 | 1294 | netdev->tlsdev_ops->tls_dev_del(netdev, ctx, |
| 1293 | 1295 | TLS_OFFLOAD_CTX_DIR_TX); |
| 1294 | − if (ctx->rx_conf == TLS_HW) | |
| 1296 | + if (ctx->rx_conf == TLS_HW && | |
| 1297 | + !test_bit(TLS_RX_DEV_CLOSED, &ctx->flags)) | |
| 1295 | 1298 | netdev->tlsdev_ops->tls_dev_del(netdev, ctx, |
| 1296 | 1299 | TLS_OFFLOAD_CTX_DIR_RX); |
| 1297 | 1300 | WRITE_ONCE(ctx->netdev, NULL); |
| @@ -1294,6 +1294,12 @@ static struct sk_buff *tls_wait_data(struct sock *sk, struct sk_psock *psock, · 1293 unmodified lines | ||
| 1294 | 1294 | return NULL; |
| 1295 | 1295 | } |
| 1296 | 1296 | |
| 1297 | + if (!skb_queue_empty(&sk->sk_receive_queue)) { | |
| 1298 | + __strp_unpause(&ctx->strp); | |
| 1299 | + if (ctx->recv_pkt) | |
| 1300 | + return ctx->recv_pkt; | |
| 1301 | + } | |
| 1302 | + | |
| 1297 | 1303 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
| 1298 | 1304 | return NULL; |
| 1299 | 1305 | |
| @@ -841,8 +841,10 @@ void virtio_transport_release(struct vsock_sock *vsk) · 840 unmodified lines | ||
| 841 | 841 | virtio_transport_free_pkt(pkt); |
| 842 | 842 | } |
| 843 | 843 | |
| 844 | − if (remove_sock) | |
| 844 | + if (remove_sock) { | |
| 845 | + sock_set_flag(sk, SOCK_DONE); | |
| 845 | 846 | vsock_remove_sock(vsk); |
| 847 | + } | |
| 846 | 848 | } |
| 847 | 849 | EXPORT_SYMBOL_GPL(virtio_transport_release); |
| 848 | 850 | |
| @@ -1132,8 +1134,8 @@ void virtio_transport_recv_pkt(struct virtio_transport *t, · 283 unmodified lines | ||
| 1132 | 1134 | |
| 1133 | 1135 | lock_sock(sk); |
| 1134 | 1136 | |
| 1135 | − /* Check if sk has been released before lock_sock */ | |
| 1136 | − if (sk->sk_shutdown == SHUTDOWN_MASK) { | |
| 1137 | + /* Check if sk has been closed before lock_sock */ | |
| 1138 | + if (sock_flag(sk, SOCK_DONE)) { | |
| 1137 | 1139 | (void)virtio_transport_reset_no_sock(t, pkt); |
| 1138 | 1140 | release_sock(sk); |
| 1139 | 1141 | sock_put(sk); |
| @@ -1539,7 +1539,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, · 1538 unmodified lines | ||
| 1539 | 1539 | |
| 1540 | 1540 | unlock: |
| 1541 | 1541 | up_write(&card->controls_rwsem); |
| 1542 | − return 0; | |
| 1542 | + return err; | |
| 1543 | 1543 | } |
| 1544 | 1544 | |
| 1545 | 1545 | static int snd_ctl_elem_add_user(struct snd_ctl_file *file, |
| @@ -123,7 +123,7 @@ copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) · 122 unmodified lines | ||
| 123 | 123 | t = (struct snd_efw_transaction *)data; |
| 124 | 124 | length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length); |
| 125 | 125 | |
| 126 | − spin_lock_irq(&efw->lock); | |
| 126 | + spin_lock(&efw->lock); | |
| 127 | 127 | |
| 128 | 128 | if (efw->push_ptr < efw->pull_ptr) |
| 129 | 129 | capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr); |
| @@ -190,7 +190,7 @@ handle_resp_for_user(struct fw_card *card, int generation, int source, · 60 unmodified lines | ||
| 190 | 190 | |
| 191 | 191 | copy_resp_to_buf(efw, data, length, rcode); |
| 192 | 192 | end: |
| 193 | − spin_unlock_irq(&instances_lock); | |
| 193 | + spin_unlock(&instances_lock); | |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | 196 | static void |
| @@ -2506,6 +2506,9 @@ static const struct pci_device_id azx_ids[] = { · 2505 unmodified lines | ||
| 2506 | 2506 | /* DG1 */ |
| 2507 | 2507 | { PCI_DEVICE(0x8086, 0x490d), |
| 2508 | 2508 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, |
| 2509 | + /* Alderlake-S */ | |
| 2510 | + { PCI_DEVICE(0x8086, 0x7ad0), | |
| 2511 | + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2509 | 2512 | /* Elkhart Lake */ |
| 2510 | 2513 | { PCI_DEVICE(0x8086, 0x4b55), |
| 2511 | 2514 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, |
| @@ -9183,6 +9183,8 @@ static void ca0132_mmio_init(struct hda_codec *codec) · 9182 unmodified lines | ||
| 9183 | 9183 | case QUIRK_AE5: |
| 9184 | 9184 | ca0132_mmio_init_ae5(codec); |
| 9185 | 9185 | break; |
| 9186 | + default: | |
| 9187 | + break; | |
| 9186 | 9188 | } |
| 9187 | 9189 | } |
| 9188 | 9190 | |
| @@ -4274,6 +4274,7 @@ HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi), · 4273 unmodified lines | ||
| 4274 | 4274 | HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi), |
| 4275 | 4275 | HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi), |
| 4276 | 4276 | HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi), |
| 4277 | +HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi), | |
| 4277 | 4278 | HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi), |
| 4278 | 4279 | HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi), |
| 4279 | 4280 | HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi), |
| @@ -2522,13 +2522,23 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { · 2521 unmodified lines | ||
| 2522 | 2522 | SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), |
| 2523 | 2523 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), |
| 2524 | 2524 | SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), |
| 2525 | + SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950), | |
| 2526 | + SND_PCI_QUIRK(0x1558, 0x950A, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950), | |
| 2525 | 2527 | SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950), |
| 2526 | 2528 | SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950), |
| 2529 | + SND_PCI_QUIRK(0x1558, 0x95e3, "Clevo P955[ER]T", ALC1220_FIXUP_CLEVO_P950), | |
| 2530 | + SND_PCI_QUIRK(0x1558, 0x95e4, "Clevo P955ER", ALC1220_FIXUP_CLEVO_P950), | |
| 2531 | + SND_PCI_QUIRK(0x1558, 0x95e5, "Clevo P955EE6", ALC1220_FIXUP_CLEVO_P950), | |
| 2532 | + SND_PCI_QUIRK(0x1558, 0x95e6, "Clevo P950R[CDF]", ALC1220_FIXUP_CLEVO_P950), | |
| 2527 | 2533 | SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950), |
| 2528 | 2534 | SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950), |
| 2535 | + SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950), | |
| 2536 | + SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), | |
| 2529 | 2537 | SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), |
| 2538 | + SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), | |
| 2539 | + SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), | |
| 2530 | 2540 | SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), |
| 2531 | − SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), | |
| 2541 | + SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), | |
| 2532 | 2542 | SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), |
| 2533 | 2543 | SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170", ALC1220_FIXUP_CLEVO_PB51ED_PINS), |
| 2534 | 2544 | SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), |
| @@ -4216,6 +4226,12 @@ static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, · 1681 unmodified lines | ||
| 4216 | 4226 | alc_fixup_hp_gpio_led(codec, action, 0x02, 0x20); |
| 4217 | 4227 | } |
| 4218 | 4228 | |
| 4229 | +static void alc287_fixup_hp_gpio_led(struct hda_codec *codec, | |
| 4230 | + const struct hda_fixup *fix, int action) | |
| 4231 | +{ | |
| 4232 | + alc_fixup_hp_gpio_led(codec, action, 0x10, 0); | |
| 4233 | +} | |
| 4234 | + | |
| 4219 | 4235 | /* turn on/off mic-mute LED per capture hook via VREF change */ |
| 4220 | 4236 | static int vref_micmute_led_set(struct led_classdev *led_cdev, |
| 4221 | 4237 | enum led_brightness brightness) |
| @@ -6301,6 +6317,9 @@ enum { · 2079 unmodified lines | ||
| 6301 | 6317 | ALC274_FIXUP_HP_MIC, |
| 6302 | 6318 | ALC274_FIXUP_HP_HEADSET_MIC, |
| 6303 | 6319 | ALC256_FIXUP_ASUS_HPE, |
| 6320 | + ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK, | |
| 6321 | + ALC287_FIXUP_HP_GPIO_LED, | |
| 6322 | + ALC256_FIXUP_HP_HEADSET_MIC, | |
| 6304 | 6323 | }; |
| 6305 | 6324 | |
| 6306 | 6325 | static const struct hda_fixup alc269_fixups[] = { |
| @@ -7705,6 +7724,20 @@ static const struct hda_fixup alc269_fixups[] = { · 1398 unmodified lines | ||
| 7705 | 7724 | .chained = true, |
| 7706 | 7725 | .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC |
| 7707 | 7726 | }, |
| 7727 | + [ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK] = { | |
| 7728 | + .type = HDA_FIXUP_FUNC, | |
| 7729 | + .v.func = alc_fixup_headset_jack, | |
| 7730 | + .chained = true, | |
| 7731 | + .chain_id = ALC269_FIXUP_THINKPAD_ACPI | |
| 7732 | + }, | |
| 7733 | + [ALC287_FIXUP_HP_GPIO_LED] = { | |
| 7734 | + .type = HDA_FIXUP_FUNC, | |
| 7735 | + .v.func = alc287_fixup_hp_gpio_led, | |
| 7736 | + }, | |
| 7737 | + [ALC256_FIXUP_HP_HEADSET_MIC] = { | |
| 7738 | + .type = HDA_FIXUP_FUNC, | |
| 7739 | + .v.func = alc274_fixup_hp_headset_mic, | |
| 7740 | + }, | |
| 7708 | 7741 | }; |
| 7709 | 7742 | |
| 7710 | 7743 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
| @@ -7859,6 +7892,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 148 unmodified lines | ||
| 7859 | 7892 | SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED), |
| 7860 | 7893 | SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED), |
| 7861 | 7894 | SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED), |
| 7895 | + SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED), | |
| 7896 | + SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED), | |
| 7862 | 7897 | SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), |
| 7863 | 7898 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), |
| 7864 | 7899 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
| @@ -7924,11 +7959,49 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 59 unmodified lines | ||
| 7924 | 7959 | SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), |
| 7925 | 7960 | SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), |
| 7926 | 7961 | SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), |
| 7962 | + SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7927 | 7963 | SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), |
| 7964 | + SND_PCI_QUIRK(0x1558, 0x1401, "Clevo L140[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7965 | + SND_PCI_QUIRK(0x1558, 0x1403, "Clevo N140CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7966 | + SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7967 | + SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7968 | + SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7969 | + SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7970 | + SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7971 | + SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7972 | + SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7973 | + SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7974 | + SND_PCI_QUIRK(0x1558, 0x50a3, "Clevo NJ51GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7975 | + SND_PCI_QUIRK(0x1558, 0x50b3, "Clevo NK50S[BEZ]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7976 | + SND_PCI_QUIRK(0x1558, 0x50b6, "Clevo NK50S5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7977 | + SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7978 | + SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7979 | + SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7980 | + SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7981 | + SND_PCI_QUIRK(0x1558, 0x5101, "Clevo S510WU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7982 | + SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7983 | + SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7984 | + SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7985 | + SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7986 | + SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7987 | + SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7988 | + SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7989 | + SND_PCI_QUIRK(0x1558, 0x8535, "Clevo NH50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7990 | + SND_PCI_QUIRK(0x1558, 0x8536, "Clevo NH79D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7928 | 7991 | SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), |
| 7929 | 7992 | SND_PCI_QUIRK(0x1558, 0x8551, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), |
| 7930 | 7993 | SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), |
| 7931 | 7994 | SND_PCI_QUIRK(0x1558, 0x8561, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), |
| 7995 | + SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7996 | + SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7997 | + SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7998 | + SND_PCI_QUIRK(0x1558, 0x8a20, "Clevo NH55DCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7999 | + SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 8000 | + SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 8001 | + SND_PCI_QUIRK(0x1558, 0x951d, "Clevo N950T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 8002 | + SND_PCI_QUIRK(0x1558, 0x961d, "Clevo N960S[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 8003 | + SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 8004 | + SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL53RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), | |
| 7932 | 8005 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), |
| 7933 | 8006 | SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), |
| 7934 | 8007 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), |
| @@ -7966,6 +8039,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 31 unmodified lines | ||
| 7966 | 8039 | SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
| 7967 | 8040 | SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), |
| 7968 | 8041 | SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), |
| 8042 | + SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), | |
| 8043 | + SND_PCI_QUIRK(0x17aa, 0x22c2, "Thinkpad X1 Extreme Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), | |
| 7969 | 8044 | SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), |
| 7970 | 8045 | SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), |
| 7971 | 8046 | SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), |
| @@ -8278,6 +8353,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { · 306 unmodified lines | ||
| 8278 | 8353 | {0x19, 0x02a11020}, |
| 8279 | 8354 | {0x1a, 0x02a11030}, |
| 8280 | 8355 | {0x21, 0x0221101f}), |
| 8356 | + SND_HDA_PIN_QUIRK(0x10ec0236, 0x103c, "HP", ALC256_FIXUP_HP_HEADSET_MIC, | |
| 8357 | + {0x14, 0x90170110}, | |
| 8358 | + {0x19, 0x02a11020}, | |
| 8359 | + {0x21, 0x02211030}), | |
| 8281 | 8360 | SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, |
| 8282 | 8361 | {0x14, 0x90170110}, |
| 8283 | 8362 | {0x21, 0x02211020}), |
| @@ -8380,6 +8459,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { · 96 unmodified lines | ||
| 8380 | 8459 | {0x1a, 0x90a70130}, |
| 8381 | 8460 | {0x1b, 0x90170110}, |
| 8382 | 8461 | {0x21, 0x03211020}), |
| 8462 | + SND_HDA_PIN_QUIRK(0x10ec0256, 0x103c, "HP", ALC256_FIXUP_HP_HEADSET_MIC, | |
| 8463 | + {0x14, 0x90170110}, | |
| 8464 | + {0x19, 0x02a11020}, | |
| 8465 | + {0x21, 0x0221101f}), | |
| 8383 | 8466 | SND_HDA_PIN_QUIRK(0x10ec0274, 0x103c, "HP", ALC274_FIXUP_HP_HEADSET_MIC, |
| 8384 | 8467 | {0x17, 0x90170110}, |
| 8385 | 8468 | {0x19, 0x03a11030}, |
| @@ -70,7 +70,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, · 69 unmodified lines | ||
| 70 | 70 | unsigned int i; |
| 71 | 71 | #endif |
| 72 | 72 | |
| 73 | − mutex_lock(&mgr->msg_lock); | |
| 74 | 73 | err = 0; |
| 75 | 74 | |
| 76 | 75 | /* copy message descriptor from miXart to driver */ |
| @@ -119,8 +118,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, · 42 unmodified lines | ||
| 119 | 118 | writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD)); |
| 120 | 119 | |
| 121 | 120 | _clean_exit: |
| 122 | − mutex_unlock(&mgr->msg_lock); | |
| 123 | − | |
| 124 | 121 | return err; |
| 125 | 122 | } |
| 126 | 123 | |
| @@ -258,7 +255,9 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int · 131 unmodified lines | ||
| 258 | 255 | resp.data = resp_data; |
| 259 | 256 | resp.size = max_resp_size; |
| 260 | 257 | |
| 258 | + mutex_lock(&mgr->msg_lock); | |
| 261 | 259 | err = get_msg(mgr, &resp, msg_frame); |
| 260 | + mutex_unlock(&mgr->msg_lock); | |
| 262 | 261 | |
| 263 | 262 | if( request->message_id != resp.message_id ) |
| 264 | 263 | dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n"); |
| @@ -27,10 +27,15 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <sound/soc-dapm.h> |
| 28 | 28 | #include <sound/soc.h> |
| 29 | 29 | #include <sound/tlv.h> |
| 30 | +#include <sound/rt1015.h> | |
| 30 | 31 | |
| 31 | 32 | #include "rl6231.h" |
| 32 | 33 | #include "rt1015.h" |
| 33 | 34 | |
| 35 | +static const struct rt1015_platform_data i2s_default_platform_data = { | |
| 36 | + .power_up_delay_ms = 50, | |
| 37 | +}; | |
| 38 | + | |
| 34 | 39 | static const struct reg_default rt1015_reg[] = { |
| 35 | 40 | { 0x0000, 0x0000 }, |
| 36 | 41 | { 0x0004, 0xa000 }, |
| @@ -539,7 +544,7 @@ static void rt1015_flush_work(struct work_struct *work) · 502 unmodified lines | ||
| 539 | 544 | struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv, |
| 540 | 545 | flush_work.work); |
| 541 | 546 | struct snd_soc_component *component = rt1015->component; |
| 542 | − unsigned int val, i = 0, count = 20; | |
| 547 | + unsigned int val, i = 0, count = 200; | |
| 543 | 548 | |
| 544 | 549 | while (i < count) { |
| 545 | 550 | usleep_range(1000, 1500); |
| @@ -650,6 +655,7 @@ static int rt1015_amp_drv_event(struct snd_soc_dapm_widget *w, · 104 unmodified lines | ||
| 650 | 655 | case SND_SOC_DAPM_POST_PMU: |
| 651 | 656 | if (rt1015->hw_config == RT1015_HW_28) |
| 652 | 657 | schedule_delayed_work(&rt1015->flush_work, msecs_to_jiffies(10)); |
| 658 | + msleep(rt1015->pdata.power_up_delay_ms); | |
| 653 | 659 | break; |
| 654 | 660 | default: |
| 655 | 661 | break; |
| @@ -1067,9 +1073,16 @@ static struct acpi_device_id rt1015_acpi_match[] = { · 411 unmodified lines | ||
| 1067 | 1073 | MODULE_DEVICE_TABLE(acpi, rt1015_acpi_match); |
| 1068 | 1074 | #endif |
| 1069 | 1075 | |
| 1076 | +static void rt1015_parse_dt(struct rt1015_priv *rt1015, struct device *dev) | |
| 1077 | +{ | |
| 1078 | + device_property_read_u32(dev, "realtek,power-up-delay-ms", | |
| 1079 | + &rt1015->pdata.power_up_delay_ms); | |
| 1080 | +} | |
| 1081 | + | |
| 1070 | 1082 | static int rt1015_i2c_probe(struct i2c_client *i2c, |
| 1071 | 1083 | const struct i2c_device_id *id) |
| 1072 | 1084 | { |
| 1085 | + struct rt1015_platform_data *pdata = dev_get_platdata(&i2c->dev); | |
| 1073 | 1086 | struct rt1015_priv *rt1015; |
| 1074 | 1087 | int ret; |
| 1075 | 1088 | unsigned int val; |
| @@ -1081,6 +1094,13 @@ static int rt1015_i2c_probe(struct i2c_client *i2c, · 5 unmodified lines | ||
| 1081 | 1094 | |
| 1082 | 1095 | i2c_set_clientdata(i2c, rt1015); |
| 1083 | 1096 | |
| 1097 | + rt1015->pdata = i2s_default_platform_data; | |
| 1098 | + | |
| 1099 | + if (pdata) | |
| 1100 | + rt1015->pdata = *pdata; | |
| 1101 | + else | |
| 1102 | + rt1015_parse_dt(rt1015, &i2c->dev); | |
| 1103 | + | |
| 1084 | 1104 | rt1015->regmap = devm_regmap_init_i2c(i2c, &rt1015_regmap); |
| 1085 | 1105 | if (IS_ERR(rt1015->regmap)) { |
| 1086 | 1106 | ret = PTR_ERR(rt1015->regmap); |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #ifndef __RT1015_H__ |
| 14 | 14 | #define __RT1015_H__ |
| 15 | +#include <sound/rt1015.h> | |
| 15 | 16 | |
| 16 | 17 | #define RT1015_DEVICE_ID_VAL 0x1011 |
| 17 | 18 | #define RT1015_DEVICE_ID_VAL2 0x1015 |
| @@ -380,6 +381,7 @@ enum { · 362 unmodified lines | ||
| 380 | 381 | |
| 381 | 382 | struct rt1015_priv { |
| 382 | 383 | struct snd_soc_component *component; |
| 384 | + struct rt1015_platform_data pdata; | |
| 383 | 385 | struct regmap *regmap; |
| 384 | 386 | int sysclk; |
| 385 | 387 | int sysclk_src; |
| @@ -700,6 +700,8 @@ static int kabylake_set_bias_level(struct snd_soc_card *card, · 699 unmodified lines | ||
| 700 | 700 | switch (level) { |
| 701 | 701 | case SND_SOC_BIAS_PREPARE: |
| 702 | 702 | if (dapm->bias_level == SND_SOC_BIAS_ON) { |
| 703 | + if (!__clk_is_enabled(priv->mclk)) | |
| 704 | + return 0; | |
| 703 | 705 | dev_dbg(card->dev, "Disable mclk"); |
| 704 | 706 | clk_disable_unprepare(priv->mclk); |
| 705 | 707 | } else { |
| @@ -458,10 +458,6 @@ static int catpt_dai_prepare(struct snd_pcm_substream *substream, · 457 unmodified lines | ||
| 458 | 458 | if (ret) |
| 459 | 459 | return CATPT_IPC_ERROR(ret); |
| 460 | 460 | |
| 461 | − ret = catpt_dsp_update_lpclock(cdev); | |
| 462 | − if (ret) | |
| 463 | − return ret; | |
| 464 | − | |
| 465 | 461 | ret = catpt_dai_apply_usettings(dai, stream); |
| 466 | 462 | if (ret) |
| 467 | 463 | return ret; |
| @@ -500,6 +496,7 @@ static int catpt_dai_trigger(struct snd_pcm_substream *substream, int cmd, · 32 unmodified lines | ||
| 500 | 496 | case SNDRV_PCM_TRIGGER_RESUME: |
| 501 | 497 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| 502 | 498 | resume_stream: |
| 499 | + catpt_dsp_update_lpclock(cdev); | |
| 503 | 500 | ret = catpt_ipc_resume_stream(cdev, stream->info.stream_hw_id); |
| 504 | 501 | if (ret) |
| 505 | 502 | return CATPT_IPC_ERROR(ret); |
| @@ -507,11 +504,11 @@ static int catpt_dai_trigger(struct snd_pcm_substream *substream, int cmd, · 1 unmodified line | ||
| 507 | 504 | |
| 508 | 505 | case SNDRV_PCM_TRIGGER_STOP: |
| 509 | 506 | stream->prepared = false; |
| 510 | − catpt_dsp_update_lpclock(cdev); | |
| 511 | 507 | fallthrough; |
| 512 | 508 | case SNDRV_PCM_TRIGGER_SUSPEND: |
| 513 | 509 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
| 514 | 510 | ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id); |
| 511 | + catpt_dsp_update_lpclock(cdev); | |
| 515 | 512 | if (ret) |
| 516 | 513 | return CATPT_IPC_ERROR(ret); |
| 517 | 514 | break; |
| @@ -534,6 +531,8 @@ void catpt_stream_update_position(struct catpt_dev *cdev, · 16 unmodified lines | ||
| 534 | 531 | |
| 535 | 532 | dsppos = bytes_to_frames(r, pos->stream_position); |
| 536 | 533 | |
| 534 | + if (!stream->prepared) | |
| 535 | + goto exit; | |
| 537 | 536 | /* only offload is set_write_pos driven */ |
| 538 | 537 | if (stream->template->type != CATPT_STRM_TYPE_RENDER) |
| 539 | 538 | goto exit; |
| @@ -487,9 +487,9 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream, · 486 unmodified lines | ||
| 487 | 487 | kmb_i2s->xfer_resolution = 0x02; |
| 488 | 488 | break; |
| 489 | 489 | case SNDRV_PCM_FORMAT_S24_LE: |
| 490 | − config->data_width = 24; | |
| 491 | − kmb_i2s->ccr = 0x08; | |
| 492 | − kmb_i2s->xfer_resolution = 0x04; | |
| 490 | + config->data_width = 32; | |
| 491 | + kmb_i2s->ccr = 0x14; | |
| 492 | + kmb_i2s->xfer_resolution = 0x05; | |
| 493 | 493 | break; |
| 494 | 494 | case SNDRV_PCM_FORMAT_S32_LE: |
| 495 | 495 | config->data_width = 32; |
| @@ -122,8 +122,10 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component, · 121 unmodified lines | ||
| 122 | 122 | else |
| 123 | 123 | dma_ch = 0; |
| 124 | 124 | |
| 125 | − if (dma_ch < 0) | |
| 125 | + if (dma_ch < 0) { | |
| 126 | + kfree(data); | |
| 126 | 127 | return dma_ch; |
| 128 | + } | |
| 127 | 129 | |
| 128 | 130 | if (cpu_dai->driver->id == LPASS_DP_RX) { |
| 129 | 131 | map = drvdata->hdmiif_map; |
| @@ -147,6 +149,7 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component, · 17 unmodified lines | ||
| 147 | 149 | ret = snd_pcm_hw_constraint_integer(runtime, |
| 148 | 150 | SNDRV_PCM_HW_PARAM_PERIODS); |
| 149 | 151 | if (ret < 0) { |
| 152 | + kfree(data); | |
| 150 | 153 | dev_err(soc_runtime->dev, "setting constraints failed: %d\n", |
| 151 | 154 | ret); |
| 152 | 155 | return -EINVAL; |
| @@ -379,6 +379,10 @@ static const struct usb_audio_device_name usb_audio_names[] = { · 378 unmodified lines | ||
| 379 | 379 | |
| 380 | 380 | DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"), |
| 381 | 381 | |
| 382 | + /* ASUS ROG Strix */ | |
| 383 | + PROFILE_NAME(0x0b05, 0x1917, | |
| 384 | + "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"), | |
| 385 | + | |
| 382 | 386 | /* Dell WD15 Dock */ |
| 383 | 387 | PROFILE_NAME(0x0bda, 0x4014, "Dell", "WD15 Dock", "Dell-WD15-Dock"), |
| 384 | 388 | /* Dell WD19 Dock */ |
| @@ -561,7 +561,8 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { · 560 unmodified lines | ||
| 561 | 561 | }, |
| 562 | 562 | { /* ASUS ROG Strix */ |
| 563 | 563 | .id = USB_ID(0x0b05, 0x1917), |
| 564 | − .map = asus_rog_map, | |
| 564 | + .map = trx40_mobo_map, | |
| 565 | + .connector_map = trx40_mobo_connector_map, | |
| 565 | 566 | }, |
| 566 | 567 | { /* MSI TRX40 Creator */ |
| 567 | 568 | .id = USB_ID(0x0db0, 0x0d64), |
| @@ -1672,13 +1672,13 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, · 1671 unmodified lines | ||
| 1672 | 1672 | && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) |
| 1673 | 1673 | msleep(20); |
| 1674 | 1674 | |
| 1675 | − /* Zoom R16/24, Logitech H650e/H570e, Jabra 550a, Kingston HyperX | |
| 1676 | − * needs a tiny delay here, otherwise requests like get/set | |
| 1677 | − * frequency return as failed despite actually succeeding. | |
| 1675 | + /* Zoom R16/24, many Logitech(at least H650e/H570e/BCC950), | |
| 1676 | + * Jabra 550a, Kingston HyperX needs a tiny delay here, | |
| 1677 | + * otherwise requests like get/set frequency return | |
| 1678 | + * as failed despite actually succeeding. | |
| 1678 | 1679 | */ |
| 1679 | 1680 | if ((chip->usb_id == USB_ID(0x1686, 0x00dd) || |
| 1680 | − chip->usb_id == USB_ID(0x046d, 0x0a46) || | |
| 1681 | − chip->usb_id == USB_ID(0x046d, 0x0a56) || | |
| 1681 | + USB_ID_VENDOR(chip->usb_id) == 0x046d || /* Logitech */ | |
| 1682 | 1682 | chip->usb_id == USB_ID(0x0b0e, 0x0349) || |
| 1683 | 1683 | chip->usb_id == USB_ID(0x0951, 0x16ad)) && |
| 1684 | 1684 | (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) |
| @@ -1758,10 +1758,10 @@ TEST_F(TRACE_poke, getpid_runs_normally) · 1757 unmodified lines | ||
| 1758 | 1758 | * and the code is stored as a positive value. \ |
| 1759 | 1759 | */ \ |
| 1760 | 1760 | if (_result < 0) { \ |
| 1761 | − SYSCALL_RET(_regs) = -result; \ | |
| 1761 | + SYSCALL_RET(_regs) = -_result; \ | |
| 1762 | 1762 | (_regs).ccr |= 0x10000000; \ |
| 1763 | 1763 | } else { \ |
| 1764 | − SYSCALL_RET(_regs) = result; \ | |
| 1764 | + SYSCALL_RET(_regs) = _result; \ | |
| 1765 | 1765 | (_regs).ccr &= ~0x10000000; \ |
| 1766 | 1766 | } \ |
| 1767 | 1767 | } while (0) |
| @@ -1804,8 +1804,8 @@ TEST_F(TRACE_poke, getpid_runs_normally) · 36 unmodified lines | ||
| 1804 | 1804 | #define SYSCALL_RET(_regs) (_regs).a[(_regs).windowbase * 4 + 2] |
| 1805 | 1805 | #elif defined(__sh__) |
| 1806 | 1806 | # define ARCH_REGS struct pt_regs |
| 1807 | −# define SYSCALL_NUM(_regs) (_regs).gpr[3] | |
| 1808 | −# define SYSCALL_RET(_regs) (_regs).gpr[0] | |
| 1807 | +# define SYSCALL_NUM(_regs) (_regs).regs[3] | |
| 1808 | +# define SYSCALL_RET(_regs) (_regs).regs[0] | |
| 1809 | 1809 | #else |
| 1810 | 1810 | # error "Do not know how to find your architecture's registers and syscalls" |
| 1811 | 1811 | #endif |