Home Home > GIT Browse > openSUSE-15.1
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Tesarik <ptesarik@suse.cz>2019-01-11 15:35:38 +0100
committerPetr Tesarik <ptesarik@suse.cz>2019-01-11 15:35:38 +0100
commitc0878c5953e346ba26b077f7ab234552864b7d59 (patch)
tree0fa808cbc83150a6d2b8dfbb099679af8fda052a
parent171485d8c7e7d3b338cdf8233d266187a6e9d951 (diff)
parentcf3013fa3ca0b5b6ea66b15ecb6db6d6b2859476 (diff)
Merge branch 'users/tiwai/SLE15-SP1/for-next' into SLE15-SP1
Pull alsa fixes from Takashi Iwai
-rw-r--r--config/arm64/default21
-rw-r--r--config/x86_64/default21
-rw-r--r--patches.drivers/0014-ALSA-pcm-add-local-header-file-for-snd-pcm-module.patch201
-rw-r--r--patches.drivers/ALSA-6fire-Use-common-error-handling-code-in-usb6fir.patch78
-rw-r--r--patches.drivers/ALSA-6fire-constify-usb_device_id.patch35
-rw-r--r--patches.drivers/ALSA-6fire-remove-unused-variable-card.patch38
-rw-r--r--patches.drivers/ALSA-Get-rid-of-card-power_lock.patch347
-rw-r--r--patches.drivers/ALSA-Make-CONFIG_SND_OSSEMUL-user-selectable.patch62
-rw-r--r--patches.drivers/ALSA-Use-IS_ENABLED-in-common-headers.patch161
-rw-r--r--patches.drivers/ALSA-Use-scnprintf-instead-of-snprintf-for-show.patch43
-rw-r--r--patches.drivers/ALSA-add-snd_card_disconnect_sync.patch126
-rw-r--r--patches.drivers/ALSA-bcd2000-constify-usb_device_id.patch35
-rw-r--r--patches.drivers/ALSA-caiaq-Add-fall-through-annotation.patch34
-rw-r--r--patches.drivers/ALSA-compress-Remove-empty-init-and-exit.patch48
-rw-r--r--patches.drivers/ALSA-control-Consolidate-helpers-for-adding-and-repl.patch203
-rw-r--r--patches.drivers/ALSA-control-Fix-a-bunch-of-whitespace-errors.patch108
-rw-r--r--patches.drivers/ALSA-control-Fix-memory-corruption-risk-in-snd_ctl_e.patch55
-rw-r--r--patches.drivers/ALSA-control-Fix-missing-__user-annotation.patch35
-rw-r--r--patches.drivers/ALSA-control-Simplify-snd_ctl_elem_list-implementati.patch126
-rw-r--r--patches.drivers/ALSA-control-TLV-data-is-unavailable-at-initial-stat.patch84
-rw-r--r--patches.drivers/ALSA-control-code-refactoring-TLV-ioctl-handler.patch188
-rw-r--r--patches.drivers/ALSA-control-code-refactoring-for-ELEM_READ-ELEM_WRI.patch181
-rw-r--r--patches.drivers/ALSA-control-code-refactoring-for-TLV-request-handle.patch120
-rw-r--r--patches.drivers/ALSA-control-delegate-TLV-eventing-to-each-driver.patch83
-rw-r--r--patches.drivers/ALSA-control-obsolete-user_ctl_lock.patch128
-rw-r--r--patches.drivers/ALSA-control-queue-TLV-event-for-a-set-of-user-defin.patch50
-rw-r--r--patches.drivers/ALSA-control-queue-events-within-locking-of-controls.patch47
-rw-r--r--patches.drivers/ALSA-control-queue-events-within-locking-of-ctl-TLV.patch47
-rw-r--r--patches.drivers/ALSA-control-remove-entry-limitation-for-list-operat.patch43
-rw-r--r--patches.drivers/ALSA-control-use-counting-semaphore-as-write-TLV.patch72
-rw-r--r--patches.drivers/ALSA-control-use-counting-semaphore-as-write-lock-fo.patch148
-rw-r--r--patches.drivers/ALSA-core-Follow-standard-EXPORT_SYMBOL-declarations.patch328
-rw-r--r--patches.drivers/ALSA-core-Use-pS-printk-format-for-direct-addresses.patch45
-rw-r--r--patches.drivers/ALSA-declare-snd_kcontrol_new-structures-as-const.patch582
-rw-r--r--patches.drivers/ALSA-fix-kernel-doc-build-warning.patch38
-rw-r--r--patches.drivers/ALSA-hrtimer-make-hrtimer_hw-const-and-__initconst.patch35
-rw-r--r--patches.drivers/ALSA-hwdep-prevent-a-harmless-shift-wrapping-bug.patch35
-rw-r--r--patches.drivers/ALSA-info-Use-kvzalloc-for-a-temporary-write-buffer.patch52
-rw-r--r--patches.drivers/ALSA-line6-make-snd_pcm_ops-const.patch80
-rw-r--r--patches.drivers/ALSA-line6-stop-using-get_seconds.patch46
-rw-r--r--patches.drivers/ALSA-opl4-Use-IS_REACHABLE.patch58
-rw-r--r--patches.drivers/ALSA-pcm-Add-__force-to-cast-in-snd_pcm_lib_read-wri.patch46
-rw-r--r--patches.drivers/ALSA-pcm-Add-an-ioctl-to-specify-the-supported-proto.patch111
-rw-r--r--patches.drivers/ALSA-pcm-Add-the-explicit-appl_ptr-sync-support.patch121
-rw-r--r--patches.drivers/ALSA-pcm-Adjust-nine-function-calls-together-with-a-.patch129
-rw-r--r--patches.drivers/ALSA-pcm-Allow-drivers-to-set-R-W-wait-time.patch67
-rw-r--r--patches.drivers/ALSA-pcm-Allow-dropping-stream-directly-after-resume.patch39
-rw-r--r--patches.drivers/ALSA-pcm-Apply-power-lock-globally-to-common-ioctls.patch150
-rw-r--r--patches.drivers/ALSA-pcm-Avoid-potential-races-between-OSS-ioctls-an48
-rw-r--r--patches.drivers/ALSA-pcm-Build-OSS-writev-readv-helpers-conditionall.patch111
-rw-r--r--patches.drivers/ALSA-pcm-Build-pcm-notifier-code-conditionally.patch153
-rw-r--r--patches.drivers/ALSA-pcm-Call-directly-the-common-read-write-helpers.patch312
-rw-r--r--patches.drivers/ALSA-pcm-Check-PCM-state-by-a-common-helper-function.patch142
-rw-r--r--patches.drivers/ALSA-pcm-Clean-up-SNDRV_PCM_IOCTL_PAUSE-code.patch42
-rw-r--r--patches.drivers/ALSA-pcm-Clean-up-with-snd_pcm_avail-and-snd_pcm_hw_.patch258
-rw-r--r--patches.drivers/ALSA-pcm-Correct-broken-procfs-set-up.patch40
-rw-r--r--patches.drivers/ALSA-pcm-Direct-in-kernel-read-write-support.patch165
-rw-r--r--patches.drivers/ALSA-pcm-Disable-only-control-mmap-for-explicit-appl.patch78
-rw-r--r--patches.drivers/ALSA-pcm-Don-t-call-register-and-disconnect-callback.patch80
-rw-r--r--patches.drivers/ALSA-pcm-Drop-the-old-copy-and-silence-ops.patch143
-rw-r--r--patches.drivers/ALSA-pcm-Fix-UAF-in-snd_pcm_oss_get_formats.patch54
-rw-r--r--patches.drivers/ALSA-pcm-Fix-mutex-unbalance-in-OSS-emulation-ioctls16
-rw-r--r--patches.drivers/ALSA-pcm-Fix-possible-inconsistent-appl_ptr-update-v10
-rw-r--r--patches.drivers/ALSA-pcm-Fix-power-lock-unbalance-via-OSS-emulation.patch53
-rw-r--r--patches.drivers/ALSA-pcm-Fix-sparse-warning-wrt-PCM-format-type.patch36
-rw-r--r--patches.drivers/ALSA-pcm-Fix-starvation-on-down_write_nonblock.patch12
-rw-r--r--patches.drivers/ALSA-pcm-Fix-structure-definition-for-X32-ABI.patch35
-rw-r--r--patches.drivers/ALSA-pcm-Fix-trailing-semicolon.patch34
-rw-r--r--patches.drivers/ALSA-pcm-Follow-standard-EXPORT_SYMBOL-declarations.patch401
-rw-r--r--patches.drivers/ALSA-pcm-Forcibly-stop-at-disconnect-callback.patch43
-rw-r--r--patches.drivers/ALSA-pcm-Hide-local_irq_disable-enable-and-local_irq.patch156
-rw-r--r--patches.drivers/ALSA-pcm-Introduce-copy_user-copy_kernel-and-fill_si.patch249
-rw-r--r--patches.drivers/ALSA-pcm-Kill-set_fs-in-PCM-OSS-layer.patch148
-rw-r--r--patches.drivers/ALSA-pcm-Mark-expected-switch-fall-through.patch34
-rw-r--r--patches.drivers/ALSA-pcm-More-unification-of-PCM-transfer-codes.patch376
-rw-r--r--patches.drivers/ALSA-pcm-Preprocess-PAUSED-or-SUSPENDED-stream-befor.patch48
-rw-r--r--patches.drivers/ALSA-pcm-Protect-call-to-dma_mmap_coherent-by-check-.patch39
-rw-r--r--patches.drivers/ALSA-pcm-Remove-VLA-usage.patch82
-rw-r--r--patches.drivers/ALSA-pcm-Remove-WARN_ON-at-snd_pcm_hw_params-error.patch49
-rw-r--r--patches.drivers/ALSA-pcm-Remove-incorrect-snd_BUG_ON-usages6
-rw-r--r--patches.drivers/ALSA-pcm-Remove-set_fs-in-PCM-core-code.patch230
-rw-r--r--patches.drivers/ALSA-pcm-Return-0-when-size-start_threshold-in-captu.patch47
-rw-r--r--patches.drivers/ALSA-pcm-Return-EBUSY-for-OSS-ioctls-changing-busy-s32
-rw-r--r--patches.drivers/ALSA-pcm-Return-negative-delays-from-SNDRV_PCM_IOCTL.patch106
-rw-r--r--patches.drivers/ALSA-pcm-Set-config-update-bits-only-when-really-cha.patch98
-rw-r--r--patches.drivers/ALSA-pcm-Shuffle-codes.patch278
-rw-r--r--patches.drivers/ALSA-pcm-Simplify-check-for-dma_mmap_coherent-availa.patch40
-rw-r--r--patches.drivers/ALSA-pcm-Simplify-snd_pcm_playback_silence.patch102
-rw-r--r--patches.drivers/ALSA-pcm-Skip-ack-callback-without-actual-appl_ptr-u8
-rw-r--r--patches.drivers/ALSA-pcm-Unify-delay-calculation-in-snd_pcm_status-a.patch84
-rw-r--r--patches.drivers/ALSA-pcm-Unify-ioctl-functions-for-playback-and-capt.patch378
-rw-r--r--patches.drivers/ALSA-pcm-Unify-playback-and-capture-poll-callbacks.patch142
-rw-r--r--patches.drivers/ALSA-pcm-Unify-read-write-loop.patch348
-rw-r--r--patches.drivers/ALSA-pcm-Update-hardware-pointer-before-start-captur.patch49
-rw-r--r--patches.drivers/ALSA-pcm-Use-ERESTARTSYS-instead-of-EINTR-in-OSS-emu.patch33
-rw-r--r--patches.drivers/ALSA-pcm-Use-common-PCM_RUNTIME_CHECK-for-sanity-che.patch42
-rw-r--r--patches.drivers/ALSA-pcm-Use-common-error-handling-code-in-_snd_pcm_.patch67
-rw-r--r--patches.drivers/ALSA-pcm-Use-krealloc-for-resizing-the-rules-array.patch44
-rw-r--r--patches.drivers/ALSA-pcm-Use-snd_pcm_stop_xrun-for-xrun-injection.patch57
-rw-r--r--patches.drivers/ALSA-pcm-Use-standard-lower_32_bits-and-upper_32_bit.patch39
-rw-r--r--patches.drivers/ALSA-pcm-Workaround-for-weird-PulseAudio-behavior-on6
-rw-r--r--patches.drivers/ALSA-pcm-adaption-of-code-formatting.patch69
-rw-r--r--patches.drivers/ALSA-pcm-add-SNDRV_PCM_FORMAT_-S-U-20.patch143
-rw-r--r--patches.drivers/ALSA-pcm-add-a-helper-function-to-apply-parameter-ru.patch137
-rw-r--r--patches.drivers/ALSA-pcm-add-a-helper-function-to-constrain-interval.patch99
-rw-r--r--patches.drivers/ALSA-pcm-add-a-helper-function-to-constrain-mask-typ.patch107
-rw-r--r--patches.drivers/ALSA-pcm-add-applptr-event-of-tracepoint.patch238
-rw-r--r--patches.drivers/ALSA-pcm-add-comment-about-application-of-rule-to-PC.patch152
-rw-r--r--patches.drivers/ALSA-pcm-add-const-qualifier-for-read-only-table-for.patch41
-rw-r--r--patches.drivers/ALSA-pcm-add-tracepoints-for-final-selection-process.patch70
-rw-r--r--patches.drivers/ALSA-pcm-calculate-non-mask-non-interval-parameters-.patch153
-rw-r--r--patches.drivers/ALSA-pcm-constify-attribute_group-structures.patch43
-rw-r--r--patches.drivers/ALSA-pcm-constify-function-local-and-read-only-table.patch47
-rw-r--r--patches.drivers/ALSA-pcm-enable-parameter-tracepoints-only-when-CONF.patch46
-rw-r--r--patches.drivers/ALSA-pcm-fix-the-comments-that-refers-to-kernel-doc.patch34
-rw-r--r--patches.drivers/ALSA-pcm-include-pcm_local.h-and-remove-some-extrane.patch88
-rw-r--r--patches.drivers/ALSA-pcm-localize-snd_pcm_hw_params_choose.patch143
-rw-r--r--patches.drivers/ALSA-pcm-move-fixup-of-info-flag-after-selecting-sin.patch72
-rw-r--r--patches.drivers/ALSA-pcm-obsolete-RULES_DEBUG-local-macro.patch151
-rw-r--r--patches.drivers/ALSA-pcm-oss-mark-snd_pcm_plug_slave_format-arg-as-c.patch42
-rw-r--r--patches.drivers/ALSA-pcm-oss-refer-to-parameters-instead-of-copying-.patch123
-rw-r--r--patches.drivers/ALSA-pcm-probe-events-when-parameters-are-changed-ac.patch134
-rw-r--r--patches.drivers/ALSA-pcm-remove-SNDRV_PCM_IOCTL1_GSTATE-internal-com.patch36
-rw-r--r--patches.drivers/ALSA-pcm-remove-SNDRV_PCM_IOCTL1_INFO-internal-comma.patch78
-rw-r--r--patches.drivers/ALSA-pcm-remove-function-local-variable-with-alterna.patch48
-rw-r--r--patches.drivers/ALSA-pcm-remove-redundant-variable-runtime.patch45
-rw-r--r--patches.drivers/ALSA-pcm-return-error-immediately-for-parameters-han.patch172
-rw-r--r--patches.drivers/ALSA-pcm-signedness-bug-in-snd_pcm_plug_alloc.patch43
-rw-r--r--patches.drivers/ALSA-pcm-trace-XRUN-event-at-injection-too.patch114
-rw-r--r--patches.drivers/ALSA-pcm-tracepoints-for-refining-PCM-parameters.patch287
-rw-r--r--patches.drivers/ALSA-pcm-unify-codes-to-operate-application-side-pos.patch135
-rw-r--r--patches.drivers/ALSA-pcm-use-do-while-0-for-empty-macro.patch41
-rw-r--r--patches.drivers/ALSA-pcm-use-friendly-name-for-id-of-PCM-substream-i.patch54
-rw-r--r--patches.drivers/ALSA-pcm-use-goto-statement-instead-of-while-stateme.patch129
-rw-r--r--patches.drivers/ALSA-pcm-use-helper-function-to-refer-parameter-as-r.patch114
-rw-r--r--patches.drivers/ALSA-pcm-use-helper-functions-to-check-whether-param.patch40
-rw-r--r--patches.drivers/ALSA-pcm-use-helper-functions-to-refer-parameters-as.patch65
-rw-r--r--patches.drivers/ALSA-pcm-use-s-instead-of-c-for-format-of-PCM-buffer.patch69
-rw-r--r--patches.drivers/ALSA-rawmidi-A-lightweight-function-to-discard-pendi.patch100
-rw-r--r--patches.drivers/ALSA-rawmidi-Initialize-allocated-buffers.patch46
-rw-r--r--patches.drivers/ALSA-rawmidi-Minor-code-refactoring.patch154
-rw-r--r--patches.drivers/ALSA-rawmidi-Simplify-error-paths.patch153
-rw-r--r--patches.drivers/ALSA-rawmidi-Tidy-up-coding-styles.patch409
-rw-r--r--patches.drivers/ALSA-rawmidi-Use-kvmalloc-for-buffers.patch72
-rw-r--r--patches.drivers/ALSA-sb-Use-IS_REACHABLE.patch47
-rw-r--r--patches.drivers/ALSA-seq-Add-sanity-check-for-user-space-pointer-del.patch42
-rw-r--r--patches.drivers/ALSA-seq-Allow-the-modular-sequencer-registration.patch898
-rw-r--r--patches.drivers/ALSA-seq-Allow-the-tristate-build-of-OSS-emulation.patch283
-rw-r--r--patches.drivers/ALSA-seq-Avoid-open-code-for-getting-timer-resolutio.patch39
-rw-r--r--patches.drivers/ALSA-seq-Cancel-pending-autoload-work-at-unbinding-d6
-rw-r--r--patches.drivers/ALSA-seq-Do-error-checks-at-creating-system-ports.patch71
-rw-r--r--patches.drivers/ALSA-seq-Drop-unused-64bit-division-macros.patch53
-rw-r--r--patches.drivers/ALSA-seq-Enable-use-locking-in-all-configurations4
-rw-r--r--patches.drivers/ALSA-seq-Fix-CONFIG_SND_SEQ_MIDI-dependency.patch47
-rw-r--r--patches.drivers/ALSA-seq-Fix-leftovers-at-probe-error-path.patch182
-rw-r--r--patches.drivers/ALSA-seq-Fix-poll-error-return.patch44
-rw-r--r--patches.drivers/ALSA-seq-Follow-standard-EXPORT_SYMBOL-declarations.patch298
-rw-r--r--patches.drivers/ALSA-seq-Mark-expected-switch-fall-through.patch38
-rw-r--r--patches.drivers/ALSA-seq-Minor-cleanup-of-MIDI-event-parser-helpers.patch191
-rw-r--r--patches.drivers/ALSA-seq-Process-queue-tempo-ppq-change-in-a-shot.patch96
-rw-r--r--patches.drivers/ALSA-seq-Remove-dead-codes.patch225
-rw-r--r--patches.drivers/ALSA-seq-Reorganize-kconfig-and-build.patch273
-rw-r--r--patches.drivers/ALSA-seq-Use-no-intrruptible-mutex_lock.patch94
-rw-r--r--patches.drivers/ALSA-seq-add-error-check-in-snd_seq_system_client_in.patch36
-rw-r--r--patches.drivers/ALSA-seq-fix-spelling-mistake-Unamed-Unnamed.patch33
-rw-r--r--patches.drivers/ALSA-seq-oss-Use-the-standard-fall-through-annotatio.patch34
-rw-r--r--patches.drivers/ALSA-seq-virmidi-Fix-discarding-the-unsubscribed-out.patch45
-rw-r--r--patches.drivers/ALSA-seq-virmidi-Offload-the-output-event-processing.patch186
-rw-r--r--patches.drivers/ALSA-seq-virmidi-Use-READ_ONCE-WRITE_ONCE-macros.patch88
-rw-r--r--patches.drivers/ALSA-seq_oss-Mark-expected-switch-fall-through.patch36
-rw-r--r--patches.drivers/ALSA-snd-usb-caiaq-constify-usb_device_id.patch35
-rw-r--r--patches.drivers/ALSA-timer-Adjust-a-condition-check-in-snd_timer_res.patch38
-rw-r--r--patches.drivers/ALSA-timer-Assure-timer-resolution-access-always-loc.patch97
-rw-r--r--patches.drivers/ALSA-timer-Convert-timers-to-use-timer_setup.patch58
-rw-r--r--patches.drivers/ALSA-timer-Follow-standard-EXPORT_SYMBOL-declaration.patch146
-rw-r--r--patches.drivers/ALSA-timer-Improve-user-queue-reallocation.patch185
-rw-r--r--patches.drivers/ALSA-timer-Limit-max-instances-per-timer12
-rw-r--r--patches.drivers/ALSA-timer-Simplify-timer-hw-resolution-calls.patch91
-rw-r--r--patches.drivers/ALSA-timer-Use-common-error-handling-code-in-alsa_ti.patch55
-rw-r--r--patches.drivers/ALSA-timer-Wrap-with-spinlock-for-queue-access.patch61
-rw-r--r--patches.drivers/ALSA-timer-catch-invalid-timer-object-creation.patch44
-rw-r--r--patches.drivers/ALSA-ua101-constify-usb_device_id.patch35
-rw-r--r--patches.drivers/ALSA-us122l-Use-common-error-handling-code-in-us122l.patch53
-rw-r--r--patches.drivers/ALSA-us122l-clean-up-US144-handling.patch167
-rw-r--r--patches.drivers/ALSA-us122l-constify-usb_device_id.patch35
-rw-r--r--patches.drivers/ALSA-usb-Mark-expected-switch-fall-through.patch34
-rw-r--r--patches.drivers/ALSA-usb-Only-get-AudioControl-header-for-UAC1-class.patch89
-rw-r--r--patches.drivers/ALSA-usb-add-UAC3-BADD-profiles-support.patch753
-rw-r--r--patches.drivers/ALSA-usb-audio-ADC3-Fix-channel-mapping-conversion-f.patch36
-rw-r--r--patches.drivers/ALSA-usb-audio-Add-UAC3-Power-Domains-to-suspend-res.patch135
-rw-r--r--patches.drivers/ALSA-usb-audio-Add-bi-directional-terminal-types.patch39
-rw-r--r--patches.drivers/ALSA-usb-audio-Add-custom-mixer-status-quirks-for-RM.patch433
-rw-r--r--patches.drivers/ALSA-usb-audio-Add-insertion-control-for-UAC3-BADD.patch52
-rw-r--r--patches.drivers/ALSA-usb-audio-Add-native-DSD-support-for-Mytek-DACs3
-rw-r--r--patches.drivers/ALSA-usb-audio-Add-sanity-checks-in-UAC3-clock-parse.patch56
-rw-r--r--patches.drivers/ALSA-usb-audio-Add-support-for-Processing-Units-in-U.patch224
-rw-r--r--patches.drivers/ALSA-usb-audio-Add-support-for-Selector-Units-in-UAC.patch116
-rw-r--r--patches.drivers/ALSA-usb-audio-Allow-changing-from-a-bad-sample-rate.patch73
-rw-r--r--patches.drivers/ALSA-usb-audio-Allow-non-vmalloc-buffer-for-PCM-buff.patch203
-rw-r--r--patches.drivers/ALSA-usb-audio-Always-create-the-interrupt-pipe-for-.patch43
-rw-r--r--patches.drivers/ALSA-usb-audio-AudioStreaming-Power-Domain-parsing.patch231
-rw-r--r--patches.drivers/ALSA-usb-audio-Avoid-lowlevel-device-object.patch97
-rw-r--r--patches.drivers/ALSA-usb-audio-Change-in-connectors-control-creation.patch111
-rw-r--r--patches.drivers/ALSA-usb-audio-Clean-up-mixer-element-list-traverse.patch158
-rw-r--r--patches.drivers/ALSA-usb-audio-Convert-timers-to-use-timer_setup.patch281
-rw-r--r--patches.drivers/ALSA-usb-audio-Declare-the-common-variable-in-header.patch48
-rw-r--r--patches.drivers/ALSA-usb-audio-Define-registers-for-CM6206.patch175
-rw-r--r--patches.drivers/ALSA-usb-audio-Drop-superfluous-ifndef.patch43
-rw-r--r--patches.drivers/ALSA-usb-audio-Fix-forgotten-conversion-of-control-q.patch42
-rw-r--r--patches.drivers/ALSA-usb-audio-Fix-invalid-use-of-sizeof-in-parse_ua.patch35
-rw-r--r--patches.drivers/ALSA-usb-audio-Fix-missing-endian-conversion.patch46
-rw-r--r--patches.drivers/ALSA-usb-audio-Fix-potential-zero-division-at-parsin.patch43
-rw-r--r--patches.drivers/ALSA-usb-audio-Follow-standard-coding-style.patch189
-rw-r--r--patches.drivers/ALSA-usb-audio-Generic-DSD-detection-for-Thesycon-ba.patch40
-rw-r--r--patches.drivers/ALSA-usb-audio-Initial-Power-Domain-support.patch200
-rw-r--r--patches.drivers/ALSA-usb-audio-Mark-expected-switch-fall-through.patch42
-rw-r--r--patches.drivers/ALSA-usb-audio-More-strict-sanity-checks-for-clock-p.patch61
-rw-r--r--patches.drivers/ALSA-usb-audio-Move-autoresume-call-at-the-end-of-op.patch131
-rw-r--r--patches.drivers/ALSA-usb-audio-Operate-UAC3-Power-Domains-in-PCM-cal.patch124
-rw-r--r--patches.drivers/ALSA-usb-audio-Processing-Unit-controls-parsing-in-U.patch62
-rw-r--r--patches.drivers/ALSA-usb-audio-Proper-fallback-at-get_term_name.patch47
-rw-r--r--patches.drivers/ALSA-usb-audio-Refactor-clock-finder-helpers.patch190
-rw-r--r--patches.drivers/ALSA-usb-audio-Simplify-PCM-open-close-callbacks.patch96
-rw-r--r--patches.drivers/ALSA-usb-audio-Tidy-up-logic-for-Processing-Unit-min.patch95
-rw-r--r--patches.drivers/ALSA-usb-audio-UAC2-jack-detection.patch188
-rw-r--r--patches.drivers/ALSA-usb-audio-UAC3-Add-support-for-connector-insert.patch252
-rw-r--r--patches.drivers/ALSA-usb-audio-UAC3-Parse-Input-Terminal-number-of-c.patch43
-rw-r--r--patches.drivers/ALSA-usb-audio-UAC3.-Add-support-for-mixer-unit.patch196
-rw-r--r--patches.drivers/ALSA-usb-audio-Unify-virtual-type-units-type-to-UAC3.patch143
-rw-r--r--patches.drivers/ALSA-usb-audio-Use-Class-Specific-EP-for-UAC3-device.patch51
-rw-r--r--patches.drivers/ALSA-usb-audio-add-implicit-fb-quirk-for-Axe-Fx-III.patch37
-rw-r--r--patches.drivers/ALSA-usb-audio-constify-usb_device_id.patch44
-rw-r--r--patches.drivers/ALSA-usb-audio-fix-memory-leak-on-cval.patch41
-rw-r--r--patches.drivers/ALSA-usb-audio-fix-uac-control-query-argument.patch234
-rw-r--r--patches.drivers/ALSA-usb-audio-move-audioformat-quirks-to-quirks.c.patch119
-rw-r--r--patches.drivers/ALSA-usb-audio-quirks-Replace-mdelay-with-msleep-and.patch91
-rw-r--r--patches.drivers/ALSA-usb-audio-remove-redundant-check-on-err.patch37
-rw-r--r--patches.drivers/ALSA-usb-audio-remove-redundant-pointer-urb.patch44
-rw-r--r--patches.drivers/ALSA-usb-audio-silence-a-static-checker-warning.patch36
-rw-r--r--patches.drivers/ALSA-usb-audio-update-clock-valid-control.patch102
-rw-r--r--patches.drivers/ALSA-usb-caiaq-audio-use-irqsave-in-USB-s-complete-c.patch53
-rw-r--r--patches.drivers/ALSA-usb-initial-USB-Audio-Device-Class-3.0-support.patch2005
-rw-r--r--patches.drivers/ALSA-usb-midi-use-irqsave-in-USB-s-complete-callback.patch51
-rw-r--r--patches.drivers/ALSA-usb-mixer-make-string-parsing-independent-of-mi.patch146
-rw-r--r--patches.drivers/ALSA-usb-stream-fix-potential-memory-leak-during-uac.patch52
-rw-r--r--patches.drivers/ALSA-usb-stream-move-audioformat-alloc-init-into-sep.patch100
-rw-r--r--patches.drivers/ALSA-usb-stream-refactor-uac1-2-audio-interface-pars.patch427
-rw-r--r--patches.drivers/ALSA-usb-stream-refactor-uac3-audio-interface-parsin.patch345
-rw-r--r--patches.drivers/ALSA-usx2y-Use-common-error-handling-code-in-submit_.patch58
-rw-r--r--patches.drivers/ALSA-vmaster-Zero-clear-ctl-before-calling-slave-get.patch34
-rw-r--r--patches.drivers/ALSA-vmaster-use-position-offset-macro-of-TLV-data.patch48
-rw-r--r--patches.drivers/Revert-ALSA-usb-audio-Fix-potential-zero-division-at.patch43
-rw-r--r--patches.drivers/include-usb-audio-specify-exact-endiannes-of-descrip.patch96
-rw-r--r--patches.drivers/include-usb-audio-v3-add-BADD-specific-values.patch56
-rw-r--r--patches.drivers/snd_hwdep_dsp_load-don-t-bother-with-access_ok.patch33
-rw-r--r--patches.drivers/usx2y-don-t-bother-with-access_ok-in-dsp_load.patch70
-rw-r--r--patches.drivers/usx2y-don-t-bother-with-memdup_user-for-16-byte-stru.patch111
-rw-r--r--series.conf243
258 files changed, 30057 insertions, 98 deletions
diff --git a/config/arm64/default b/config/arm64/default
index 1d946b78a9..043c397168 100644
--- a/config/arm64/default
+++ b/config/arm64/default
@@ -5171,19 +5171,16 @@ CONFIG_SND_PCM_ELD=y
CONFIG_SND_PCM_IEC958=y
CONFIG_SND_DMAENGINE_PCM=m
CONFIG_SND_HWDEP=m
+CONFIG_SND_SEQ_DEVICE=m
CONFIG_SND_RAWMIDI=m
CONFIG_SND_JACK=y
CONFIG_SND_JACK_INPUT_DEV=y
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_PCM_TIMER=y
-CONFIG_SND_SEQUENCER_OSS=y
CONFIG_SND_HRTIMER=m
-CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_MAX_CARDS=32
CONFIG_SND_SUPPORT_OLD_API=y
@@ -5194,13 +5191,18 @@ CONFIG_SND_DEBUG=y
# CONFIG_SND_DEBUG_VERBOSE is not set
CONFIG_SND_PCM_XRUN_DEBUG=y
CONFIG_SND_VMASTER=y
-CONFIG_SND_RAWMIDI_SEQ=m
-CONFIG_SND_OPL3_LIB_SEQ=m
-# CONFIG_SND_OPL4_LIB_SEQ is not set
-# CONFIG_SND_SBAWE_SEQ is not set
-CONFIG_SND_EMU10K1_SEQ=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_SEQUENCER_OSS=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+CONFIG_SND_SEQ_MIDI_EVENT=m
+CONFIG_SND_SEQ_MIDI=m
+CONFIG_SND_SEQ_MIDI_EMUL=m
+CONFIG_SND_SEQ_VIRMIDI=m
CONFIG_SND_MPU401_UART=m
CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL3_LIB_SEQ=m
+# CONFIG_SND_OPL4_LIB_SEQ is not set
CONFIG_SND_VX_LIB=m
CONFIG_SND_AC97_CODEC=m
CONFIG_SND_DRIVERS=y
@@ -5250,6 +5252,7 @@ CONFIG_SND_INDIGODJ=m
CONFIG_SND_INDIGOIOX=m
CONFIG_SND_INDIGODJX=m
CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1_SEQ=m
CONFIG_SND_EMU10K1X=m
CONFIG_SND_ENS1370=m
CONFIG_SND_ENS1371=m
diff --git a/config/x86_64/default b/config/x86_64/default
index 7dfdb376b5..7538622c17 100644
--- a/config/x86_64/default
+++ b/config/x86_64/default
@@ -5004,20 +5004,17 @@ CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
CONFIG_SND_DMAENGINE_PCM=m
CONFIG_SND_HWDEP=m
+CONFIG_SND_SEQ_DEVICE=m
CONFIG_SND_RAWMIDI=m
CONFIG_SND_COMPRESS_OFFLOAD=m
CONFIG_SND_JACK=y
CONFIG_SND_JACK_INPUT_DEV=y
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_PCM_TIMER=y
-CONFIG_SND_SEQUENCER_OSS=y
CONFIG_SND_HRTIMER=m
-CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_MAX_CARDS=32
CONFIG_SND_SUPPORT_OLD_API=y
@@ -5029,13 +5026,18 @@ CONFIG_SND_DEBUG=y
CONFIG_SND_PCM_XRUN_DEBUG=y
CONFIG_SND_VMASTER=y
CONFIG_SND_DMA_SGBUF=y
-CONFIG_SND_RAWMIDI_SEQ=m
-CONFIG_SND_OPL3_LIB_SEQ=m
-# CONFIG_SND_OPL4_LIB_SEQ is not set
-# CONFIG_SND_SBAWE_SEQ is not set
-CONFIG_SND_EMU10K1_SEQ=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_SEQUENCER_OSS=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+CONFIG_SND_SEQ_MIDI_EVENT=m
+CONFIG_SND_SEQ_MIDI=m
+CONFIG_SND_SEQ_MIDI_EMUL=m
+CONFIG_SND_SEQ_VIRMIDI=m
CONFIG_SND_MPU401_UART=m
CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL3_LIB_SEQ=m
+# CONFIG_SND_OPL4_LIB_SEQ is not set
CONFIG_SND_VX_LIB=m
CONFIG_SND_AC97_CODEC=m
CONFIG_SND_DRIVERS=y
@@ -5089,6 +5091,7 @@ CONFIG_SND_INDIGODJ=m
CONFIG_SND_INDIGOIOX=m
CONFIG_SND_INDIGODJX=m
CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1_SEQ=m
CONFIG_SND_EMU10K1X=m
CONFIG_SND_ENS1370=m
CONFIG_SND_ENS1371=m
diff --git a/patches.drivers/0014-ALSA-pcm-add-local-header-file-for-snd-pcm-module.patch b/patches.drivers/0014-ALSA-pcm-add-local-header-file-for-snd-pcm-module.patch
new file mode 100644
index 0000000000..24788ceb65
--- /dev/null
+++ b/patches.drivers/0014-ALSA-pcm-add-local-header-file-for-snd-pcm-module.patch
@@ -0,0 +1,201 @@
+From 2c4842d3b6b3cf6db0f21e487da7e9bd3aa23090 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 26 May 2017 09:30:46 +0900
+Subject: [PATCH] ALSA: pcm: add local header file for snd-pcm module
+Git-commit: 2c4842d3b6b3cf6db0f21e487da7e9bd3aa23090
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Several files are used to construct PCM core module, a.k.a snd-pcm.
+Although available APIs are described in 'include/sound/pcm.h', some of
+them are not exported as symbols in kernel space. Such APIs are just for
+module local usage.
+
+This commit adds module local header file and move some function prototypes
+into it so that scopes of them are controlled properly and developers
+get no confusion from unavailable symbols.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 32 ------------------------------
+ sound/core/pcm.c | 2 +
+ sound/core/pcm_lib.c | 2 +
+ sound/core/pcm_local.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
+ sound/core/pcm_misc.c | 3 ++
+ sound/core/pcm_native.c | 2 +
+ 6 files changed, 60 insertions(+), 32 deletions(-)
+ create mode 100644 sound/core/pcm_local.h
+
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -969,12 +969,6 @@ static inline unsigned int params_buffer
+ }
+
+ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v);
+-void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c);
+-void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c);
+-void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b,
+- unsigned int k, struct snd_interval *c);
+-void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
+- const struct snd_interval *b, struct snd_interval *c);
+ int snd_interval_list(struct snd_interval *i, unsigned int count,
+ const unsigned int *list, unsigned int mask);
+ int snd_interval_ranges(struct snd_interval *i, unsigned int count,
+@@ -985,15 +979,9 @@ int snd_interval_ratnum(struct snd_inter
+
+ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params);
+ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var);
+-int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
+
+ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
+
+-int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
+-int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
+-
+-int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
+- u_int32_t mask);
+ int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
+ u_int64_t mask);
+ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
+@@ -1081,10 +1069,6 @@ void snd_pcm_set_ops(struct snd_pcm * pc
+ void snd_pcm_set_sync(struct snd_pcm_substream *substream);
+ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg);
+-int snd_pcm_update_state(struct snd_pcm_substream *substream,
+- struct snd_pcm_runtime *runtime);
+-int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
+-void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr);
+ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
+ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ const void __user *buf,
+@@ -1096,8 +1080,6 @@ snd_pcm_sframes_t snd_pcm_lib_writev(str
+ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+ void __user **bufs, snd_pcm_uframes_t frames);
+
+-extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
+-
+ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
+ unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
+ unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit);
+@@ -1131,20 +1113,6 @@ static inline void snd_pcm_set_runtime_b
+ }
+ }
+
+-/*
+- * Timer interface
+- */
+-
+-#ifdef CONFIG_SND_PCM_TIMER
+-void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
+-void snd_pcm_timer_init(struct snd_pcm_substream *substream);
+-void snd_pcm_timer_done(struct snd_pcm_substream *substream);
+-#else
+-static inline void
+-snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) {}
+-static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {}
+-static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
+-#endif
+ /**
+ * snd_pcm_gettime - Fill the timespec depending on the timestamp mode
+ * @runtime: PCM runtime instance
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -31,6 +31,8 @@
+ #include <sound/control.h>
+ #include <sound/info.h>
+
++#include "pcm_local.h"
++
+ MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
+ MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
+ MODULE_LICENSE("GPL");
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -33,6 +33,8 @@
+ #include <sound/pcm_params.h>
+ #include <sound/timer.h>
+
++#include "pcm_local.h"
++
+ #ifdef CONFIG_SND_PCM_XRUN_DEBUG
+ #define CREATE_TRACE_POINTS
+ #include "pcm_trace.h"
+--- /dev/null
++++ b/sound/core/pcm_local.h
+@@ -0,0 +1,51 @@
++/*
++ * pcm_local.h - a local header file for snd-pcm module.
++ *
++ * Copyright (c) Takashi Sakamoto <o-takashi@sakamocchi.jp>
++ *
++ * Licensed under the terms of the GNU General Public License, version 2.
++ */
++
++#ifndef __SOUND_CORE_PCM_LOCAL_H
++#define __SOUND_CORE_PCM_LOCAL_H
++
++extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
++
++void snd_interval_mul(const struct snd_interval *a,
++ const struct snd_interval *b, struct snd_interval *c);
++void snd_interval_div(const struct snd_interval *a,
++ const struct snd_interval *b, struct snd_interval *c);
++void snd_interval_muldivk(const struct snd_interval *a,
++ const struct snd_interval *b,
++ unsigned int k, struct snd_interval *c);
++void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
++ const struct snd_interval *b, struct snd_interval *c);
++
++int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
++int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
++
++int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params);
++
++int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime,
++ snd_pcm_hw_param_t var, u_int32_t mask);
++
++int snd_pcm_update_state(struct snd_pcm_substream *substream,
++ struct snd_pcm_runtime *runtime);
++int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
++
++void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t new_hw_ptr);
++
++#ifdef CONFIG_SND_PCM_TIMER
++void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
++void snd_pcm_timer_init(struct snd_pcm_substream *substream);
++void snd_pcm_timer_done(struct snd_pcm_substream *substream);
++#else
++static inline void
++snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) {}
++static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {}
++static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
++#endif
++
++#endif /* __SOUND_CORE_PCM_LOCAL_H */
+--- a/sound/core/pcm_misc.c
++++ b/sound/core/pcm_misc.c
+@@ -23,6 +23,9 @@
+ #include <linux/export.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
++
++#include "pcm_local.h"
++
+ #define SND_PCM_FORMAT_UNKNOWN (-1)
+
+ /* NOTE: "signed" prefix must be given below since the default char is
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -37,6 +37,8 @@
+ #include <sound/minors.h>
+ #include <linux/uio.h>
+
++#include "pcm_local.h"
++
+ /*
+ * Compatibility
+ */
diff --git a/patches.drivers/ALSA-6fire-Use-common-error-handling-code-in-usb6fir.patch b/patches.drivers/ALSA-6fire-Use-common-error-handling-code-in-usb6fir.patch
new file mode 100644
index 0000000000..124ce3b3b8
--- /dev/null
+++ b/patches.drivers/ALSA-6fire-Use-common-error-handling-code-in-usb6fir.patch
@@ -0,0 +1,78 @@
+From f804fff1361c9da30efc21721dc0ae5934413c4b Mon Sep 17 00:00:00 2001
+From: Markus Elfring <elfring@users.sourceforge.net>
+Date: Wed, 6 Sep 2017 16:26:29 +0200
+Subject: [PATCH] ALSA: 6fire: Use common error handling code in usb6fire_chip_probe()
+Git-commit: f804fff1361c9da30efc21721dc0ae5934413c4b
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+Add a jump target so that a bit of exception handling can be better reused
+at the end of this function.
+
+This issue was detected by using the Coccinelle software.
+
+Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/usb/6fire/chip.c | 31 +++++++++++++------------------
+ 1 file changed, 13 insertions(+), 18 deletions(-)
+
+diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
+index bc2a24f7a791..c7641cb50616 100644
+--- a/sound/usb/6fire/chip.c
++++ b/sound/usb/6fire/chip.c
+@@ -143,37 +143,32 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
+ chip->card = card;
+
+ ret = usb6fire_comm_init(chip);
+- if (ret < 0) {
+- usb6fire_chip_destroy(chip);
+- return ret;
+- }
++ if (ret < 0)
++ goto destroy_chip;
+
+ ret = usb6fire_midi_init(chip);
+- if (ret < 0) {
+- usb6fire_chip_destroy(chip);
+- return ret;
+- }
++ if (ret < 0)
++ goto destroy_chip;
+
+ ret = usb6fire_pcm_init(chip);
+- if (ret < 0) {
+- usb6fire_chip_destroy(chip);
+- return ret;
+- }
++ if (ret < 0)
++ goto destroy_chip;
+
+ ret = usb6fire_control_init(chip);
+- if (ret < 0) {
+- usb6fire_chip_destroy(chip);
+- return ret;
+- }
++ if (ret < 0)
++ goto destroy_chip;
+
+ ret = snd_card_register(card);
+ if (ret < 0) {
+ dev_err(&intf->dev, "cannot register card.");
+- usb6fire_chip_destroy(chip);
+- return ret;
++ goto destroy_chip;
+ }
+ usb_set_intfdata(intf, chip);
+ return 0;
++
++destroy_chip:
++ usb6fire_chip_destroy(chip);
++ return ret;
+ }
+
+ static void usb6fire_chip_disconnect(struct usb_interface *intf)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-6fire-constify-usb_device_id.patch b/patches.drivers/ALSA-6fire-constify-usb_device_id.patch
new file mode 100644
index 0000000000..c8a497a638
--- /dev/null
+++ b/patches.drivers/ALSA-6fire-constify-usb_device_id.patch
@@ -0,0 +1,35 @@
+From 05d72cd5f1f03531e1e678f476bbe207a29ede87 Mon Sep 17 00:00:00 2001
+From: Arvind Yadav <arvind.yadav.cs@gmail.com>
+Date: Sun, 6 Aug 2017 12:18:53 +0530
+Subject: [PATCH] ALSA: 6fire: constify usb_device_id.
+Git-commit: 05d72cd5f1f03531e1e678f476bbe207a29ede87
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+usb_device_id are not supposed to change at runtime. All functions
+working with usb_device_id provided by <linux/usb.h> work with
+const usb_device_id. So mark the non-const structs as const.
+
+Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/usb/6fire/chip.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
+index dcddfc354ba6..bc2a24f7a791 100644
+--- a/sound/usb/6fire/chip.c
++++ b/sound/usb/6fire/chip.c
+@@ -198,7 +198,7 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf)
+ }
+ }
+
+-static struct usb_device_id device_table[] = {
++static const struct usb_device_id device_table[] = {
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x0ccd,
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-6fire-remove-unused-variable-card.patch b/patches.drivers/ALSA-6fire-remove-unused-variable-card.patch
new file mode 100644
index 0000000000..bf818ddb0c
--- /dev/null
+++ b/patches.drivers/ALSA-6fire-remove-unused-variable-card.patch
@@ -0,0 +1,38 @@
+From 49815404bd3870232de8800430a83d7d498ae1e2 Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Mon, 16 Oct 2017 13:35:58 +0100
+Subject: [PATCH] ALSA: 6fire: remove unused variable card
+Git-commit: 49815404bd3870232de8800430a83d7d498ae1e2
+Patch-mainline: v4.15-rc1
+References: bsc#1121278
+
+The pointer card is being assigned a value but it is never used.
+Remove this redundant variable. Cleans up clang warning:
+Value stored to 'card' is never read
+
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/usb/6fire/chip.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
+index c7641cb50616..17d5e3ee6d73 100644
+--- a/sound/usb/6fire/chip.c
++++ b/sound/usb/6fire/chip.c
+@@ -174,11 +174,9 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
+ static void usb6fire_chip_disconnect(struct usb_interface *intf)
+ {
+ struct sfire_chip *chip;
+- struct snd_card *card;
+
+ chip = usb_get_intfdata(intf);
+ if (chip) { /* if !chip, fw upload has been performed */
+- card = chip->card;
+ chip->intf_count--;
+ if (!chip->intf_count) {
+ mutex_lock(&register_mutex);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-Get-rid-of-card-power_lock.patch b/patches.drivers/ALSA-Get-rid-of-card-power_lock.patch
new file mode 100644
index 0000000000..9ab4e7940c
--- /dev/null
+++ b/patches.drivers/ALSA-Get-rid-of-card-power_lock.patch
@@ -0,0 +1,347 @@
+From 7d8e8292013ab72ae1f1500cbc91f198ccb1826d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 30 Aug 2017 16:13:25 +0200
+Subject: [PATCH] ALSA: Get rid of card power_lock
+Git-commit: 7d8e8292013ab72ae1f1500cbc91f198ccb1826d
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+Currently we're taking power_lock at each card component for assuring
+the power-up sequence, but it doesn't help anything in the
+implementation at the moment: it just serializes unnecessarily the
+callers, but it doesn't protect about the power state change itself.
+It used to have some usefulness in the early days where we managed the
+PM manually. But now the suspend/resume core procedure is beyond our
+hands, and power_lock lost its meaning.
+
+This patch drops the power_lock from allover the places.
+There shouldn't be any issues by this change, as it's no helper
+regarding the power state change. Rather we'll get better performance
+by removing the serialization; which is the only slight concern of any
+behavior change, but it can't be a showstopper, after all.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/core.h | 13 ---------
+ sound/core/control.c | 58 ++++++++++++++++++++-----------------
+ sound/core/control_compat.c | 34 ++++++++++------------
+ sound/core/init.c | 5 ----
+ sound/core/pcm_native.c | 30 +++++--------------
+ sound/soc/soc-core.c | 2 --
+ 6 files changed, 53 insertions(+), 89 deletions(-)
+
+diff --git a/include/sound/core.h b/include/sound/core.h
+index 357f36b5ee80..4104a9d1001f 100644
+--- a/include/sound/core.h
++++ b/include/sound/core.h
+@@ -136,7 +136,6 @@ struct snd_card {
+
+ #ifdef CONFIG_PM
+ unsigned int power_state; /* power state */
+- struct mutex power_lock; /* power lock */
+ wait_queue_head_t power_sleep;
+ #endif
+
+@@ -149,16 +148,6 @@ struct snd_card {
+ #define dev_to_snd_card(p) container_of(p, struct snd_card, card_dev)
+
+ #ifdef CONFIG_PM
+-static inline void snd_power_lock(struct snd_card *card)
+-{
+- mutex_lock(&card->power_lock);
+-}
+-
+-static inline void snd_power_unlock(struct snd_card *card)
+-{
+- mutex_unlock(&card->power_lock);
+-}
+-
+ static inline unsigned int snd_power_get_state(struct snd_card *card)
+ {
+ return card->power_state;
+@@ -175,8 +164,6 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state);
+
+ #else /* ! CONFIG_PM */
+
+-#define snd_power_lock(card) do { (void)(card); } while (0)
+-#define snd_power_unlock(card) do { (void)(card); } while (0)
+ static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; }
+ #define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; })
+ #define snd_power_change_state(card, state) do { (void)(card); } while (0)
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 51d4b4ad3e1d..56b3e2d49c82 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -864,14 +864,14 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
+
+ if (copy_from_user(&info, _info, sizeof(info)))
+ return -EFAULT;
+- snd_power_lock(ctl->card);
+ result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
+- if (result >= 0)
+- result = snd_ctl_elem_info(ctl, &info);
+- snd_power_unlock(ctl->card);
+- if (result >= 0)
+- if (copy_to_user(_info, &info, sizeof(info)))
+- return -EFAULT;
++ if (result < 0)
++ return result;
++ result = snd_ctl_elem_info(ctl, &info);
++ if (result < 0)
++ return result;
++ if (copy_to_user(_info, &info, sizeof(info)))
++ return -EFAULT;
+ return result;
+ }
+
+@@ -905,17 +905,19 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
+ if (IS_ERR(control))
+ return PTR_ERR(control);
+
+- snd_power_lock(card);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+- if (result >= 0) {
+- down_read(&card->controls_rwsem);
+- result = snd_ctl_elem_read(card, control);
+- up_read(&card->controls_rwsem);
+- }
+- snd_power_unlock(card);
+- if (result >= 0)
+- if (copy_to_user(_control, control, sizeof(*control)))
+- result = -EFAULT;
++ if (result < 0)
++ goto error;
++
++ down_read(&card->controls_rwsem);
++ result = snd_ctl_elem_read(card, control);
++ up_read(&card->controls_rwsem);
++ if (result < 0)
++ goto error;
++
++ if (copy_to_user(_control, control, sizeof(*control)))
++ result = -EFAULT;
++ error:
+ kfree(control);
+ return result;
+ }
+@@ -964,17 +966,19 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
+ return PTR_ERR(control);
+
+ card = file->card;
+- snd_power_lock(card);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+- if (result >= 0) {
+- down_write(&card->controls_rwsem);
+- result = snd_ctl_elem_write(card, file, control);
+- up_write(&card->controls_rwsem);
+- }
+- snd_power_unlock(card);
+- if (result >= 0)
+- if (copy_to_user(_control, control, sizeof(*control)))
+- result = -EFAULT;
++ if (result < 0)
++ goto error;
++
++ down_write(&card->controls_rwsem);
++ result = snd_ctl_elem_write(card, file, control);
++ up_write(&card->controls_rwsem);
++ if (result < 0)
++ goto error;
++
++ if (copy_to_user(_control, control, sizeof(*control)))
++ result = -EFAULT;
++ error:
+ kfree(control);
+ return result;
+ }
+diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
+index 1fa70766ffab..a848836a5de0 100644
+--- a/sound/core/control_compat.c
++++ b/sound/core/control_compat.c
+@@ -111,12 +111,10 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
+ if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
+ goto error;
+
+- snd_power_lock(ctl->card);
+ err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
+- if (err >= 0)
+- err = snd_ctl_elem_info(ctl, data);
+- snd_power_unlock(ctl->card);
+-
++ if (err < 0)
++ goto error;
++ err = snd_ctl_elem_info(ctl, data);
+ if (err < 0)
+ goto error;
+ /* restore info to 32bit */
+@@ -315,14 +313,13 @@ static int ctl_elem_read_user(struct snd_card *card,
+ if (err < 0)
+ goto error;
+
+- snd_power_lock(card);
+ err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+- if (err >= 0)
+- err = snd_ctl_elem_read(card, data);
+- snd_power_unlock(card);
+- if (err >= 0)
+- err = copy_ctl_value_to_user(userdata, valuep, data,
+- type, count);
++ if (err < 0)
++ goto error;
++ err = snd_ctl_elem_read(card, data);
++ if (err < 0)
++ goto error;
++ err = copy_ctl_value_to_user(userdata, valuep, data, type, count);
+ error:
+ kfree(data);
+ return err;
+@@ -344,14 +341,13 @@ static int ctl_elem_write_user(struct snd_ctl_file *file,
+ if (err < 0)
+ goto error;
+
+- snd_power_lock(card);
+ err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+- if (err >= 0)
+- err = snd_ctl_elem_write(card, file, data);
+- snd_power_unlock(card);
+- if (err >= 0)
+- err = copy_ctl_value_to_user(userdata, valuep, data,
+- type, count);
++ if (err < 0)
++ goto error;
++ err = snd_ctl_elem_write(card, file, data);
++ if (err < 0)
++ goto error;
++ err = copy_ctl_value_to_user(userdata, valuep, data, type, count);
+ error:
+ kfree(data);
+ return err;
+diff --git a/sound/core/init.c b/sound/core/init.c
+index 6e219dc23f96..32ebe2f6bc59 100644
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -253,7 +253,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
+ spin_lock_init(&card->files_lock);
+ INIT_LIST_HEAD(&card->files_list);
+ #ifdef CONFIG_PM
+- mutex_init(&card->power_lock);
+ init_waitqueue_head(&card->power_sleep);
+ #endif
+
+@@ -978,8 +977,6 @@ EXPORT_SYMBOL(snd_card_file_remove);
+ * Waits until the power-state is changed.
+ *
+ * Return: Zero if successful, or a negative error code.
+- *
+- * Note: the power lock must be active before call.
+ */
+ int snd_power_wait(struct snd_card *card, unsigned int power_state)
+ {
+@@ -999,9 +996,7 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state)
+ if (snd_power_get_state(card) == power_state)
+ break;
+ set_current_state(TASK_UNINTERRUPTIBLE);
+- snd_power_unlock(card);
+ schedule_timeout(30 * HZ);
+- snd_power_lock(card);
+ }
+ remove_wait_queue(&card->power_sleep, &wait);
+ return result;
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index cf0433f80067..621142ea9ec6 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1830,7 +1830,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
+ add_wait_queue(&to_check->sleep, &wait);
+ snd_pcm_stream_unlock_irq(substream);
+ up_read(&snd_pcm_link_rwsem);
+- snd_power_unlock(card);
+ if (runtime->no_period_wakeup)
+ tout = MAX_SCHEDULE_TIMEOUT;
+ else {
+@@ -1842,7 +1841,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
+ tout = msecs_to_jiffies(tout * 1000);
+ }
+ tout = schedule_timeout_interruptible(tout);
+- snd_power_lock(card);
+ down_read(&snd_pcm_link_rwsem);
+ snd_pcm_stream_lock_irq(substream);
+ remove_wait_queue(&to_check->sleep, &wait);
+@@ -2764,11 +2762,16 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
+ return 0;
+ }
+
+-static int snd_pcm_common_ioctl(struct file *file,
++static int snd_pcm_common_ioctl1(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+ {
+ struct snd_pcm_file *pcm_file = file->private_data;
++ int res;
++
++ res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0);
++ if (res < 0)
++ return res;
+
+ switch (cmd) {
+ case SNDRV_PCM_IOCTL_PVERSION:
+@@ -2846,21 +2849,6 @@ static int snd_pcm_common_ioctl(struct file *file,
+ return -ENOTTY;
+ }
+
+-static int snd_pcm_common_ioctl1(struct file *file,
+- struct snd_pcm_substream *substream,
+- unsigned int cmd, void __user *arg)
+-{
+- struct snd_card *card = substream->pcm->card;
+- int res;
+-
+- snd_power_lock(card);
+- res = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+- if (res >= 0)
+- res = snd_pcm_common_ioctl(file, substream, cmd, arg);
+- snd_power_unlock(card);
+- return res;
+-}
+-
+ static int snd_pcm_playback_ioctl1(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+@@ -3064,7 +3052,6 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ {
+ snd_pcm_uframes_t *frames = arg;
+ snd_pcm_sframes_t result;
+- int err;
+
+ switch (cmd) {
+ case SNDRV_PCM_IOCTL_FORWARD:
+@@ -3084,10 +3071,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ case SNDRV_PCM_IOCTL_START:
+ return snd_pcm_start_lock_irq(substream);
+ case SNDRV_PCM_IOCTL_DRAIN:
+- snd_power_lock(substream->pcm->card);
+- err = snd_pcm_drain(substream, NULL);
+- snd_power_unlock(substream->pcm->card);
+- return err;
++ return snd_pcm_drain(substream, NULL);
+ case SNDRV_PCM_IOCTL_DROP:
+ return snd_pcm_drop(substream);
+ case SNDRV_PCM_IOCTL_DELAY:
+diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
+index 13c875e2392a..62c11e26ce5c 100644
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -653,9 +653,7 @@ int snd_soc_suspend(struct device *dev)
+ /* Due to the resume being scheduled into a workqueue we could
+ * suspend before that's finished - wait for it to complete.
+ */
+- snd_power_lock(card->snd_card);
+ snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0);
+- snd_power_unlock(card->snd_card);
+
+ /* we're going to block userspace touching us until resume completes */
+ snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-Make-CONFIG_SND_OSSEMUL-user-selectable.patch b/patches.drivers/ALSA-Make-CONFIG_SND_OSSEMUL-user-selectable.patch
new file mode 100644
index 0000000000..c666cd99f8
--- /dev/null
+++ b/patches.drivers/ALSA-Make-CONFIG_SND_OSSEMUL-user-selectable.patch
@@ -0,0 +1,62 @@
+From eb3b705aaed9cab7efef8c905eda919b5fd902b9 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 9 Jun 2017 13:56:05 +0200
+Subject: [PATCH] ALSA: Make CONFIG_SND_OSSEMUL user-selectable
+Git-commit: eb3b705aaed9cab7efef8c905eda919b5fd902b9
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Currently CONFIG_SND_OSSEMUL is selected by each config like
+CONFIG_SND_PCM_OSS. But, as see in the raw MIDI code that is built
+conditionally with CONFIG_SND_OSSEMUL, we should rather make
+CONFIG_SND_OSSEMUL user-selectable as the top kconfig item, and leave
+the rest depending on it.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/Kconfig | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/sound/core/Kconfig b/sound/core/Kconfig
+index 9749f9e8b45c..3a9afc520d4e 100644
+--- a/sound/core/Kconfig
++++ b/sound/core/Kconfig
+@@ -59,12 +59,14 @@ config SND_SEQ_DUMMY
+ will be called snd-seq-dummy.
+
+ config SND_OSSEMUL
++ bool "Enable OSS Emulation"
+ select SOUND_OSS_CORE
+- bool
++ help
++ This option enables the build of OSS emulation layer.
+
+ config SND_MIXER_OSS
+ tristate "OSS Mixer API"
+- select SND_OSSEMUL
++ depends on SND_OSSEMUL
+ help
+ To enable OSS mixer API emulation (/dev/mixer*), say Y here
+ and read <file:Documentation/sound/alsa/OSS-Emulation.txt>.
+@@ -76,7 +78,7 @@ config SND_MIXER_OSS
+
+ config SND_PCM_OSS
+ tristate "OSS PCM (digital audio) API"
+- select SND_OSSEMUL
++ depends on SND_OSSEMUL
+ select SND_PCM
+ help
+ To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y
+@@ -110,7 +112,7 @@ config SND_PCM_TIMER
+ config SND_SEQUENCER_OSS
+ bool "OSS Sequencer API"
+ depends on SND_SEQUENCER
+- select SND_OSSEMUL
++ depends on SND_OSSEMUL
+ help
+ Say Y here to enable OSS sequencer emulation (both
+ /dev/sequencer and /dev/music interfaces).
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-Use-IS_ENABLED-in-common-headers.patch b/patches.drivers/ALSA-Use-IS_ENABLED-in-common-headers.patch
new file mode 100644
index 0000000000..5b5e1f8c77
--- /dev/null
+++ b/patches.drivers/ALSA-Use-IS_ENABLED-in-common-headers.patch
@@ -0,0 +1,161 @@
+From 6d2412b80aabf5d77400fbb960ee041475df86aa Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 12 May 2017 11:44:03 +0200
+Subject: [PATCH] ALSA: Use IS_ENABLED() in common headers
+Git-commit: 6d2412b80aabf5d77400fbb960ee041475df86aa
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Simplify the ifdef conditions with IS_ENABLED() macro in the common
+sound headers. No functional changes.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/core.h | 6 +++---
+ include/sound/mixer_oss.h | 2 +-
+ include/sound/opl3.h | 4 ++--
+ include/sound/pcm.h | 10 +++++-----
+ include/sound/rawmidi.h | 4 ++--
+ 5 files changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/include/sound/core.h b/include/sound/core.h
+index f7d8c10c4c45..55385588eefa 100644
+--- a/include/sound/core.h
++++ b/include/sound/core.h
+@@ -142,7 +142,7 @@ struct snd_card {
+ wait_queue_head_t power_sleep;
+ #endif
+
+-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
++#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
+ struct snd_mixer_oss *mixer_oss;
+ int mixer_oss_change_count;
+ #endif
+@@ -243,7 +243,7 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size
+
+ extern struct snd_card *snd_cards[SNDRV_CARDS];
+ int snd_card_locked(int card);
+-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
++#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
+ #define SND_MIXER_OSS_NOTIFY_REGISTER 0
+ #define SND_MIXER_OSS_NOTIFY_DISCONNECT 1
+ #define SND_MIXER_OSS_NOTIFY_FREE 2
+@@ -394,7 +394,7 @@ static inline void snd_printdd(const char *format, ...) {}
+ #define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */
+
+ /* for easier backward-porting */
+-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
++#if IS_ENABLED(CONFIG_GAMEPORT)
+ #define gameport_set_dev_parent(gp,xdev) ((gp)->dev.parent = (xdev))
+ #define gameport_set_port_data(gp,r) ((gp)->port_data = (r))
+ #define gameport_get_port_data(gp) (gp)->port_data
+diff --git a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h
+index 13cb0b430a1b..930da10fb65b 100644
+--- a/include/sound/mixer_oss.h
++++ b/include/sound/mixer_oss.h
+@@ -22,7 +22,7 @@
+ *
+ */
+
+-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
++#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
+
+ #define SNDRV_OSS_MAX_MIXERS 32
+
+diff --git a/include/sound/opl3.h b/include/sound/opl3.h
+index 6ba670707831..5a87641c6ae4 100644
+--- a/include/sound/opl3.h
++++ b/include/sound/opl3.h
+@@ -321,7 +321,7 @@ struct snd_opl3 {
+ unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */
+ unsigned char rhythm; /* percussion mode flag */
+ unsigned char max_voices; /* max number of voices */
+-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
++#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+ #define SNDRV_OPL3_MODE_SYNTH 0 /* OSS - voices allocated by application */
+ #define SNDRV_OPL3_MODE_SEQ 1 /* ALSA - driver handles voice allocation */
+ int synth_mode; /* synth mode */
+@@ -374,7 +374,7 @@ int snd_opl3_release(struct snd_hwdep * hw, struct file *file);
+
+ void snd_opl3_reset(struct snd_opl3 * opl3);
+
+-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
++#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+ long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count,
+ loff_t *offset);
+ int snd_opl3_load_patch(struct snd_opl3 *opl3,
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index eb16912d6046..3f084486868f 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -34,7 +34,7 @@
+ #define snd_pcm_substream_chip(substream) ((substream)->private_data)
+ #define snd_pcm_chip(pcm) ((pcm)->private_data)
+
+-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+ #include <sound/pcm_oss.h>
+ #endif
+
+@@ -418,7 +418,7 @@ struct snd_pcm_runtime {
+ struct snd_pcm_audio_tstamp_report audio_tstamp_report;
+ struct timespec driver_tstamp;
+
+-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+ /* -- OSS things -- */
+ struct snd_pcm_oss_runtime oss;
+ #endif
+@@ -464,7 +464,7 @@ struct snd_pcm_substream {
+ unsigned int f_flags;
+ void (*pcm_release)(struct snd_pcm_substream *);
+ struct pid *pid;
+-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+ /* -- OSS things -- */
+ struct snd_pcm_oss_substream oss;
+ #endif
+@@ -494,7 +494,7 @@ struct snd_pcm_str {
+ unsigned int substream_count;
+ unsigned int substream_opened;
+ struct snd_pcm_substream *substream;
+-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+ /* -- OSS things -- */
+ struct snd_pcm_oss_stream oss;
+ #endif
+@@ -526,7 +526,7 @@ struct snd_pcm {
+ void (*private_free) (struct snd_pcm *pcm);
+ bool internal; /* pcm is for internal use only */
+ bool nonatomic; /* whole PCM operations are in non-atomic context */
+-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+ struct snd_pcm_oss oss;
+ #endif
+ };
+diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
+index 492a3ca7f17b..6665cb29e1a2 100644
+--- a/include/sound/rawmidi.h
++++ b/include/sound/rawmidi.h
+@@ -30,7 +30,7 @@
+ #include <linux/workqueue.h>
+ #include <linux/device.h>
+
+-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
++#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+ #include <sound/seq_device.h>
+ #endif
+
+@@ -144,7 +144,7 @@ struct snd_rawmidi {
+
+ struct snd_info_entry *proc_entry;
+
+-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
++#if IS_ENABLED(CONFIG_SND_SEQUENCER)
+ struct snd_seq_device *seq_dev;
+ #endif
+ };
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-Use-scnprintf-instead-of-snprintf-for-show.patch b/patches.drivers/ALSA-Use-scnprintf-instead-of-snprintf-for-show.patch
new file mode 100644
index 0000000000..ebe12b07cb
--- /dev/null
+++ b/patches.drivers/ALSA-Use-scnprintf-instead-of-snprintf-for-show.patch
@@ -0,0 +1,43 @@
+From ef21e1750158558d8369067e94d02d285011c37e Mon Sep 17 00:00:00 2001
+From: Jaejoong Kim <climbbb.kim@gmail.com>
+Date: Tue, 27 Feb 2018 11:15:59 +0900
+Subject: [PATCH] ALSA: Use scnprintf() instead of snprintf() for show
+Git-commit: ef21e1750158558d8369067e94d02d285011c37e
+Patch-mainline: v4.17-rc1
+References: bsc#1121278
+
+The show() method should use scnprintf() not snprintf() because snprintf()
+may returns a value that exceeds its second argument.
+
+Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/init.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/core/init.c b/sound/core/init.c
+index 4fa5dd955740..79b4df1c1dc7 100644
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -670,7 +670,7 @@ card_id_show_attr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+ struct snd_card *card = container_of(dev, struct snd_card, card_dev);
+- return snprintf(buf, PAGE_SIZE, "%s\n", card->id);
++ return scnprintf(buf, PAGE_SIZE, "%s\n", card->id);
+ }
+
+ static ssize_t
+@@ -710,7 +710,7 @@ card_number_show_attr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+ struct snd_card *card = container_of(dev, struct snd_card, card_dev);
+- return snprintf(buf, PAGE_SIZE, "%i\n", card->number);
++ return scnprintf(buf, PAGE_SIZE, "%i\n", card->number);
+ }
+
+ static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-add-snd_card_disconnect_sync.patch b/patches.drivers/ALSA-add-snd_card_disconnect_sync.patch
new file mode 100644
index 0000000000..7eed6d821e
--- /dev/null
+++ b/patches.drivers/ALSA-add-snd_card_disconnect_sync.patch
@@ -0,0 +1,126 @@
+From c44027c89e19adafccd404bbe6f9686722ff4217 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 11 Oct 2017 06:36:13 +0000
+Subject: [PATCH] ALSA: add snd_card_disconnect_sync()
+Git-commit: c44027c89e19adafccd404bbe6f9686722ff4217
+Patch-mainline: v4.15-rc1
+References: bsc#1121278
+
+In case of user unbind ALSA driver during playing back / capturing,
+each driver needs to stop and remove it correctly. One note here is
+that we can't cancel from remove function in such case, because
+unbind operation doesn't check return value from remove function.
+So, we *must* stop and remove in this case.
+
+For this purpose, we need to sync (= wait) until the all top-level
+operations are canceled at remove function.
+For example, snd_card_free() processes the disconnection procedure at
+first, then waits for the completion. That's how the hot-unplug works
+safely. It's implemented, at least, in the top-level driver removal.
+
+Now for the lower level driver, we need a similar strategy. Notify to
+the toplevel for hot-unplug (disconnect in ALSA), and sync with the
+stop operation, then continue the rest of its own remove procedure.
+
+This patch adds snd_card_disconnect_sync(), and driver can use it from
+remove function.
+
+Note: the "lower level" driver here refers to a middle layer driver
+(e.g. ASoC components) that can be unbound freely during operation.
+Most of legacy ALSA helper drivers don't have such a problem because
+they can't be unbound.
+
+Note#2: snd_card_disconnect_sync() merely calls snd_card_disconnect()
+and syncs with closing all pending files. It takes only the files
+opened by user-space into account, and doesn't care about object
+refcounts. (The latter is handled by snd_card_free() completion call,
+BTW.) Also, the function doesn't free resources by itself.
+
+Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/core.h | 2 ++
+ sound/core/init.c | 32 ++++++++++++++++++++++++++++++++
+ 2 files changed, 34 insertions(+)
+
+diff --git a/include/sound/core.h b/include/sound/core.h
+index 4104a9d1001f..5f181b875c2f 100644
+--- a/include/sound/core.h
++++ b/include/sound/core.h
+@@ -133,6 +133,7 @@ struct snd_card {
+ struct device card_dev; /* cardX object for sysfs */
+ const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
+ bool registered; /* card_dev is registered? */
++ wait_queue_head_t remove_sleep;
+
+ #ifdef CONFIG_PM
+ unsigned int power_state; /* power state */
+@@ -240,6 +241,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
+ struct snd_card **card_ret);
+
+ int snd_card_disconnect(struct snd_card *card);
++void snd_card_disconnect_sync(struct snd_card *card);
+ int snd_card_free(struct snd_card *card);
+ int snd_card_free_when_closed(struct snd_card *card);
+ void snd_card_set_id(struct snd_card *card, const char *id);
+diff --git a/sound/core/init.c b/sound/core/init.c
+index 32ebe2f6bc59..168ae03d3a1c 100644
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -255,6 +255,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
+ #ifdef CONFIG_PM
+ init_waitqueue_head(&card->power_sleep);
+ #endif
++ init_waitqueue_head(&card->remove_sleep);
+
+ device_initialize(&card->card_dev);
+ card->card_dev.parent = parent;
+@@ -452,6 +453,35 @@ int snd_card_disconnect(struct snd_card *card)
+ }
+ EXPORT_SYMBOL(snd_card_disconnect);
+
++/**
++ * snd_card_disconnect_sync - disconnect card and wait until files get closed
++ * @card: card object to disconnect
++ *
++ * This calls snd_card_disconnect() for disconnecting all belonging components
++ * and waits until all pending files get closed.
++ * It assures that all accesses from user-space finished so that the driver
++ * can release its resources gracefully.
++ */
++void snd_card_disconnect_sync(struct snd_card *card)
++{
++ int err;
++
++ err = snd_card_disconnect(card);
++ if (err < 0) {
++ dev_err(card->dev,
++ "snd_card_disconnect error (%d), skipping sync\n",
++ err);
++ return;
++ }
++
++ spin_lock_irq(&card->files_lock);
++ wait_event_lock_irq(card->remove_sleep,
++ list_empty(&card->files_list),
++ card->files_lock);
++ spin_unlock_irq(&card->files_lock);
++}
++EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
++
+ static int snd_card_do_free(struct snd_card *card)
+ {
+ #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
+@@ -957,6 +987,8 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
+ break;
+ }
+ }
++ if (list_empty(&card->files_list))
++ wake_up_all(&card->remove_sleep);
+ spin_unlock(&card->files_lock);
+ if (!found) {
+ dev_err(card->dev, "card file remove problem (%p)\n", file);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-bcd2000-constify-usb_device_id.patch b/patches.drivers/ALSA-bcd2000-constify-usb_device_id.patch
new file mode 100644
index 0000000000..7c446698c9
--- /dev/null
+++ b/patches.drivers/ALSA-bcd2000-constify-usb_device_id.patch
@@ -0,0 +1,35 @@
+From 5e055ea2117cb0bc840e72b5f506c2c460cfb1da Mon Sep 17 00:00:00 2001
+From: Arvind Yadav <arvind.yadav.cs@gmail.com>
+Date: Sun, 6 Aug 2017 12:18:54 +0530
+Subject: [PATCH] ALSA: bcd2000: constify usb_device_id.
+Git-commit: 5e055ea2117cb0bc840e72b5f506c2c460cfb1da
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+usb_device_id are not supposed to change at runtime. All functions
+working with usb_device_id provided by <linux/usb.h> work with
+const usb_device_id. So mark the non-const structs as const.
+
+Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/usb/bcd2000/bcd2000.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c
+index 2ff9d578753a..7371e5b06035 100644
+--- a/sound/usb/bcd2000/bcd2000.c
++++ b/sound/usb/bcd2000/bcd2000.c
+@@ -29,7 +29,7 @@
+ #define PREFIX "snd-bcd2000: "
+ #define BUFSIZE 64
+
+-static struct usb_device_id id_table[] = {
++static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x1397, 0x00bd) },
+ { },
+ };
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-caiaq-Add-fall-through-annotation.patch b/patches.drivers/ALSA-caiaq-Add-fall-through-annotation.patch
new file mode 100644
index 0000000000..eaaabe2024
--- /dev/null
+++ b/patches.drivers/ALSA-caiaq-Add-fall-through-annotation.patch
@@ -0,0 +1,34 @@
+From 590b516e25636c696550b44b11fcfed42167adfd Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 4 Oct 2018 19:58:23 +0200
+Subject: [PATCH] ALSA: caiaq: Add fall-through annotation
+Git-commit: 590b516e25636c696550b44b11fcfed42167adfd
+Patch-mainline: v4.20-rc1
+References: bsc#1121278
+
+As a preparatory patch for the upcoming -Wimplicit-fallthrough
+compiler checks, add the "fall through" annotation in caiaq driver.
+Note that this seems necessary to be put exactly before the next
+label, so it's outside the ifdef block.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/usb/caiaq/device.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
+index d55ca48de3ea..f4a72e39ffa9 100644
+--- a/sound/usb/caiaq/device.c
++++ b/sound/usb/caiaq/device.c
+@@ -200,6 +200,7 @@ static void usb_ep1_command_reply_dispatch (struct urb* urb)
+ break;
+ }
+ #ifdef CONFIG_SND_USB_CAIAQ_INPUT
++ /* fall through */
+ case EP1_CMD_READ_ERP:
+ case EP1_CMD_READ_ANALOG:
+ snd_usb_caiaq_input_dispatch(cdev, buf, urb->actual_length);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-compress-Remove-empty-init-and-exit.patch b/patches.drivers/ALSA-compress-Remove-empty-init-and-exit.patch
new file mode 100644
index 0000000000..b96191ed0f
--- /dev/null
+++ b/patches.drivers/ALSA-compress-Remove-empty-init-and-exit.patch
@@ -0,0 +1,48 @@
+From a6403299893982a2c0b0a6f43261976c43e1598e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 3 Aug 2018 15:40:25 +0200
+Subject: [PATCH] ALSA: compress: Remove empty init and exit
+Git-commit: a6403299893982a2c0b0a6f43261976c43e1598e
+Patch-mainline: v4.19-rc1
+References: bsc#1121278
+
+For a sake of code simplification, remove the init and the exit
+entries that do nothing.
+
+Notes for readers: actually it's OK to remove *both* init and exit,
+but not OK to remove the exit entry. By removing only the exit while
+keeping init, the module becomes permanently loaded; i.e. you cannot
+unload it any longer!
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/compress_offload.c | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
+index 4b01a37c836e..26b5e245b074 100644
+--- a/sound/core/compress_offload.c
++++ b/sound/core/compress_offload.c
+@@ -1160,18 +1160,6 @@ int snd_compress_deregister(struct snd_compr *device)
+ }
+ EXPORT_SYMBOL_GPL(snd_compress_deregister);
+
+-static int __init snd_compress_init(void)
+-{
+- return 0;
+-}
+-
+-static void __exit snd_compress_exit(void)
+-{
+-}
+-
+-module_init(snd_compress_init);
+-module_exit(snd_compress_exit);
+-
+ MODULE_DESCRIPTION("ALSA Compressed offload framework");
+ MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
+ MODULE_LICENSE("GPL v2");
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-Consolidate-helpers-for-adding-and-repl.patch b/patches.drivers/ALSA-control-Consolidate-helpers-for-adding-and-repl.patch
new file mode 100644
index 0000000000..c5ffa72310
--- /dev/null
+++ b/patches.drivers/ALSA-control-Consolidate-helpers-for-adding-and-repl.patch
@@ -0,0 +1,203 @@
+From 3103c08f968ddba3fff339a59aba40389b3f724f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 22 Nov 2018 15:22:40 +0100
+Subject: [PATCH] ALSA: control: Consolidate helpers for adding and replacing ctl elements
+Git-commit: 3103c08f968ddba3fff339a59aba40389b3f724f
+Patch-mainline: v5.0-rc1
+References: bsc#1121278
+
+Both snd_ctl_add() and snd_ctl_replace() process the things in a
+fairly similar way, and indeed the most of the codes can be unified.
+
+This patch is a refactoring to consolidate the both functions to call
+a single helper with an extra "mode" argument. There should be no
+functional difference, except for one additional sanity check applied
+now to snd_ctl_replace() (which was rather overlooking, IMO), too.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 123 ++++++++++++++++++-------------------------
+ 1 file changed, 52 insertions(+), 71 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 649d3217590e..fad7db402443 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -348,22 +348,41 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
+ return 0;
+ }
+
+-/* add a new kcontrol object; call with card->controls_rwsem locked */
+-static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
++enum snd_ctl_add_mode {
++ CTL_ADD_EXCLUSIVE, CTL_REPLACE, CTL_ADD_ON_REPLACE,
++};
++
++/* add/replace a new kcontrol object; call with card->controls_rwsem locked */
++static int __snd_ctl_add_replace(struct snd_card *card,
++ struct snd_kcontrol *kcontrol,
++ enum snd_ctl_add_mode mode)
+ {
+ struct snd_ctl_elem_id id;
+ unsigned int idx;
+ unsigned int count;
++ struct snd_kcontrol *old;
++ int err;
+
+ id = kcontrol->id;
+ if (id.index > UINT_MAX - kcontrol->count)
+ return -EINVAL;
+
+- if (snd_ctl_find_id(card, &id)) {
+- dev_err(card->dev,
+- "control %i:%i:%i:%s:%i is already present\n",
+- id.iface, id.device, id.subdevice, id.name, id.index);
+- return -EBUSY;
++ old = snd_ctl_find_id(card, &id);
++ if (!old) {
++ if (mode == CTL_REPLACE)
++ return -EINVAL;
++ } else {
++ if (mode == CTL_ADD_EXCLUSIVE) {
++ dev_err(card->dev,
++ "control %i:%i:%i:%s:%i is already present\n",
++ id.iface, id.device, id.subdevice, id.name,
++ id.index);
++ return -EBUSY;
++ }
++
++ err = snd_ctl_remove(card, old);
++ if (err < 0)
++ return err;
+ }
+
+ if (snd_ctl_find_hole(card, kcontrol->count) < 0)
+@@ -382,21 +401,9 @@ static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
+ return 0;
+ }
+
+-/**
+- * snd_ctl_add - add the control instance to the card
+- * @card: the card instance
+- * @kcontrol: the control instance to add
+- *
+- * Adds the control instance created via snd_ctl_new() or
+- * snd_ctl_new1() to the given card. Assigns also an unique
+- * numid used for fast search.
+- *
+- * It frees automatically the control which cannot be added.
+- *
+- * Return: Zero if successful, or a negative error code on failure.
+- *
+- */
+-int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
++static int snd_ctl_add_replace(struct snd_card *card,
++ struct snd_kcontrol *kcontrol,
++ enum snd_ctl_add_mode mode)
+ {
+ int err = -EINVAL;
+
+@@ -406,7 +413,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
+ goto error;
+
+ down_write(&card->controls_rwsem);
+- err = __snd_ctl_add(card, kcontrol);
++ err = __snd_ctl_add_replace(card, kcontrol, mode);
+ up_write(&card->controls_rwsem);
+ if (err < 0)
+ goto error;
+@@ -416,6 +423,25 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
+ snd_ctl_free_one(kcontrol);
+ return err;
+ }
++
++/**
++ * snd_ctl_add - add the control instance to the card
++ * @card: the card instance
++ * @kcontrol: the control instance to add
++ *
++ * Adds the control instance created via snd_ctl_new() or
++ * snd_ctl_new1() to the given card. Assigns also an unique
++ * numid used for fast search.
++ *
++ * It frees automatically the control which cannot be added.
++ *
++ * Return: Zero if successful, or a negative error code on failure.
++ *
++ */
++int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
++{
++ return snd_ctl_add_replace(card, kcontrol, CTL_ADD_EXCLUSIVE);
++}
+ EXPORT_SYMBOL(snd_ctl_add);
+
+ /**
+@@ -435,53 +461,8 @@ EXPORT_SYMBOL(snd_ctl_add);
+ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
+ bool add_on_replace)
+ {
+- struct snd_ctl_elem_id id;
+- unsigned int count;
+- unsigned int idx;
+- struct snd_kcontrol *old;
+- int ret;
+-
+- if (!kcontrol)
+- return -EINVAL;
+- if (snd_BUG_ON(!card || !kcontrol->info)) {
+- ret = -EINVAL;
+- goto error;
+- }
+- id = kcontrol->id;
+- down_write(&card->controls_rwsem);
+- old = snd_ctl_find_id(card, &id);
+- if (!old) {
+- if (add_on_replace)
+- goto add;
+- up_write(&card->controls_rwsem);
+- ret = -EINVAL;
+- goto error;
+- }
+- ret = snd_ctl_remove(card, old);
+- if (ret < 0) {
+- up_write(&card->controls_rwsem);
+- goto error;
+- }
+-add:
+- if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
+- up_write(&card->controls_rwsem);
+- ret = -ENOMEM;
+- goto error;
+- }
+- list_add_tail(&kcontrol->list, &card->controls);
+- card->controls_count += kcontrol->count;
+- kcontrol->id.numid = card->last_numid + 1;
+- card->last_numid += kcontrol->count;
+- id = kcontrol->id;
+- count = kcontrol->count;
+- up_write(&card->controls_rwsem);
+- for (idx = 0; idx < count; idx++, id.index++, id.numid++)
+- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
+- return 0;
+-
+-error:
+- snd_ctl_free_one(kcontrol);
+- return ret;
++ return snd_ctl_add_replace(card, kcontrol,
++ add_on_replace ? CTL_ADD_ON_REPLACE : CTL_REPLACE);
+ }
+ EXPORT_SYMBOL(snd_ctl_replace);
+
+@@ -1369,7 +1350,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
+
+ /* This function manage to free the instance on failure. */
+ down_write(&card->controls_rwsem);
+- err = __snd_ctl_add(card, kctl);
++ err = __snd_ctl_add_replace(card, kctl, CTL_ADD_EXCLUSIVE);
+ if (err < 0) {
+ snd_ctl_free_one(kctl);
+ goto unlock;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-Fix-a-bunch-of-whitespace-errors.patch b/patches.drivers/ALSA-control-Fix-a-bunch-of-whitespace-errors.patch
new file mode 100644
index 0000000000..dedcc79a41
--- /dev/null
+++ b/patches.drivers/ALSA-control-Fix-a-bunch-of-whitespace-errors.patch
@@ -0,0 +1,108 @@
+From dd5f313be0d4d7a46f0e82c42aed4fbc784699ea Mon Sep 17 00:00:00 2001
+From: Richard Fitzgerald <rf@opensource.cirrus.com>
+Date: Tue, 27 Feb 2018 17:29:54 +0000
+Subject: [PATCH] ALSA: control: Fix a bunch of whitespace errors
+Git-commit: dd5f313be0d4d7a46f0e82c42aed4fbc784699ea
+Patch-mainline: v4.17-rc1
+References: bsc#1121278
+
+Remove a bunch of trailing whitespace errors. They are
+fairly annoying if you have your editor set to strip trailing
+whitespace because you find you've introduced more changes
+than you were trying to make.
+
+Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 8a77620a3854..69734b0eafd0 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -105,7 +105,7 @@ static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
+ {
+ unsigned long flags;
+ struct snd_kctl_event *cread;
+-
++
+ spin_lock_irqsave(&ctl->read_lock, flags);
+ while (!list_empty(&ctl->events)) {
+ cread = snd_kctl_event(ctl->events.next);
+@@ -159,7 +159,7 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
+ unsigned long flags;
+ struct snd_ctl_file *ctl;
+ struct snd_kctl_event *ev;
+-
++
+ if (snd_BUG_ON(!card || !id))
+ return;
+ if (card->shutdown)
+@@ -213,7 +213,7 @@ static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count,
+ {
+ unsigned int size;
+ unsigned int idx;
+-
++
+ if (count == 0 || count > MAX_CONTROL_COUNT)
+ return -EINVAL;
+
+@@ -238,7 +238,7 @@ static int snd_ctl_new(struct snd_kcontrol **kctl, unsigned int count,
+ * @ncontrol: the initialization record
+ * @private_data: the private data to set
+ *
+- * Allocates a new struct snd_kcontrol instance and initialize from the given
++ * Allocates a new struct snd_kcontrol instance and initialize from the given
+ * template. When the access field of ncontrol is 0, it's assumed as
+ * READWRITE access. When the count field is 0, it's assumes as one.
+ *
+@@ -251,7 +251,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
+ unsigned int count;
+ unsigned int access;
+ int err;
+-
++
+ if (snd_BUG_ON(!ncontrol || !ncontrol->info))
+ return NULL;
+
+@@ -753,7 +753,7 @@ static int snd_ctl_elem_list(struct snd_card *card,
+ struct snd_ctl_elem_id id;
+ unsigned int offset, space, jidx;
+ int err = 0;
+-
++
+ if (copy_from_user(&list, _list, sizeof(list)))
+ return -EFAULT;
+ offset = list.offset;
+@@ -827,7 +827,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
+ struct snd_kcontrol_volatile *vd;
+ unsigned int index_offset;
+ int result;
+-
++
+ down_read(&card->controls_rwsem);
+ kctl = snd_ctl_find_id(card, &info->id);
+ if (kctl == NULL) {
+@@ -992,7 +992,7 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file,
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
+ int result;
+-
++
+ if (copy_from_user(&id, _id, sizeof(id)))
+ return -EFAULT;
+ down_write(&card->controls_rwsem);
+@@ -1020,7 +1020,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
+ int result;
+-
++
+ if (copy_from_user(&id, _id, sizeof(id)))
+ return -EFAULT;
+ down_write(&card->controls_rwsem);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-Fix-memory-corruption-risk-in-snd_ctl_e.patch b/patches.drivers/ALSA-control-Fix-memory-corruption-risk-in-snd_ctl_e.patch
new file mode 100644
index 0000000000..5d7a9f78a1
--- /dev/null
+++ b/patches.drivers/ALSA-control-Fix-memory-corruption-risk-in-snd_ctl_e.patch
@@ -0,0 +1,55 @@
+From 5a23699a39abc5328921a81b89383d088f6ba9cc Mon Sep 17 00:00:00 2001
+From: Richard Fitzgerald <rf@opensource.cirrus.com>
+Date: Tue, 27 Feb 2018 17:01:18 +0000
+Subject: [PATCH] ALSA: control: Fix memory corruption risk in snd_ctl_elem_read
+Git-commit: 5a23699a39abc5328921a81b89383d088f6ba9cc
+Patch-mainline: v4.16-rc4
+References: bsc#1121278
+
+The patch "ALSA: control: code refactoring for ELEM_READ/ELEM_WRITE
+operations" introduced a potential for kernel memory corruption due
+to an incorrect if statement allowing non-readable controls to fall
+through and call the get function. For TLV controls a driver can omit
+SNDRV_CTL_ELEM_ACCESS_READ to ensure that only the TLV get function
+can be called. Instead the normal get() can be invoked unexpectedly
+and as the driver expects that this will only be called for controls
+<= 512 bytes, potentially try to copy >512 bytes into the 512 byte
+return array, so corrupting kernel memory.
+
+The problem is an attempt to refactor the snd_ctl_elem_read function
+to invert the logic so that it conditionally aborted if the control
+is unreadable instead of conditionally executing. But the if statement
+wasn't inverted correctly.
+
+The correct inversion of
+
+ if (a && !b)
+
+is
+ if (!a || b)
+
+Fixes: becf9e5d553c2 ("ALSA: control: code refactoring for ELEM_READ/ELEM_WRITE operations")
+Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 0b3026d937b1..8a77620a3854 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -889,7 +889,7 @@ static int snd_ctl_elem_read(struct snd_card *card,
+
+ index_offset = snd_ctl_get_ioff(kctl, &control->id);
+ vd = &kctl->vd[index_offset];
+- if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get == NULL)
++ if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL)
+ return -EPERM;
+
+ snd_ctl_build_ioff(&control->id, kctl, index_offset);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-Fix-missing-__user-annotation.patch b/patches.drivers/ALSA-control-Fix-missing-__user-annotation.patch
new file mode 100644
index 0000000000..785272537e
--- /dev/null
+++ b/patches.drivers/ALSA-control-Fix-missing-__user-annotation.patch
@@ -0,0 +1,35 @@
+From 1ba7862f1f5a7a3b268cf79ac236611546888a90 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 23 Apr 2018 15:01:44 +0200
+Subject: [PATCH] ALSA: control: Fix missing __user annotation
+Git-commit: 1ba7862f1f5a7a3b268cf79ac236611546888a90
+Patch-mainline: v4.17-rc3
+References: bsc#1121278
+
+There is one place missing __user annotation to the pointer used by
+the recent code refactoring. Reported by sparse.
+
+Fixes: 450296f305f1 ("ALSA: control: code refactoring TLV ioctl handler")
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 69734b0eafd0..9aa15bfc7936 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1492,7 +1492,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
+ int op_flag)
+ {
+ struct snd_ctl_tlv header;
+- unsigned int *container;
++ unsigned int __user *container;
+ unsigned int container_size;
+ struct snd_kcontrol *kctl;
+ struct snd_ctl_elem_id id;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-Simplify-snd_ctl_elem_list-implementati.patch b/patches.drivers/ALSA-control-Simplify-snd_ctl_elem_list-implementati.patch
new file mode 100644
index 0000000000..f84aace753
--- /dev/null
+++ b/patches.drivers/ALSA-control-Simplify-snd_ctl_elem_list-implementati.patch
@@ -0,0 +1,126 @@
+From 53e7bf452584e73df8a529a2b157a1225a52637f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 22 May 2017 17:43:04 +0200
+Subject: [PATCH] ALSA: control: Simplify snd_ctl_elem_list() implementation
+Git-commit: 53e7bf452584e73df8a529a2b157a1225a52637f
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+This patch simplifies the code of snd_ctl_elem_list() in the following
+Ways:
+
+- Avoid a vmalloc() temporary buffer but do copy in each iteration;
+ the vmalloc buffer was introduced at the time we took the spinlock
+ for the ctl element management.
+
+- Use the standard list_for_each_entry() macro
+
+- Merge two loops into one;
+ it used to be a loop for skipping until offset becomes zero and
+ another loop to copy the data. They can be folded into a single
+ loop easily.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Tested-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 66 ++++++++++++++++----------------------------
+ 1 file changed, 24 insertions(+), 42 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index c109b82eef4b..47080da8451a 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -747,11 +747,11 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
+ static int snd_ctl_elem_list(struct snd_card *card,
+ struct snd_ctl_elem_list __user *_list)
+ {
+- struct list_head *plist;
+ struct snd_ctl_elem_list list;
+ struct snd_kcontrol *kctl;
+- struct snd_ctl_elem_id *dst, *id;
++ struct snd_ctl_elem_id id;
+ unsigned int offset, space, jidx;
++ int err = 0;
+
+ if (copy_from_user(&list, _list, sizeof(list)))
+ return -EFAULT;
+@@ -760,52 +760,34 @@ static int snd_ctl_elem_list(struct snd_card *card,
+ /* try limit maximum space */
+ if (space > 16384)
+ return -ENOMEM;
++ down_read(&card->controls_rwsem);
++ list.count = card->controls_count;
++ list.used = 0;
+ if (space > 0) {
+- /* allocate temporary buffer for atomic operation */
+- dst = vmalloc(space * sizeof(struct snd_ctl_elem_id));
+- if (dst == NULL)
+- return -ENOMEM;
+- down_read(&card->controls_rwsem);
+- list.count = card->controls_count;
+- plist = card->controls.next;
+- while (plist != &card->controls) {
+- if (offset == 0)
+- break;
+- kctl = snd_kcontrol(plist);
+- if (offset < kctl->count)
+- break;
+- offset -= kctl->count;
+- plist = plist->next;
+- }
+- list.used = 0;
+- id = dst;
+- while (space > 0 && plist != &card->controls) {
+- kctl = snd_kcontrol(plist);
+- for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) {
+- snd_ctl_build_ioff(id, kctl, jidx);
+- id++;
+- space--;
++ list_for_each_entry(kctl, &card->controls, list) {
++ if (offset >= kctl->count) {
++ offset -= kctl->count;
++ continue;
++ }
++ for (jidx = offset; jidx < kctl->count; jidx++) {
++ snd_ctl_build_ioff(&id, kctl, jidx);
++ if (copy_to_user(list.pids + list.used, &id,
++ sizeof(id))) {
++ err = -EFAULT;
++ goto out;
++ }
+ list.used++;
++ if (!--space)
++ goto out;
+ }
+- plist = plist->next;
+ offset = 0;
+ }
+- up_read(&card->controls_rwsem);
+- if (list.used > 0 &&
+- copy_to_user(list.pids, dst,
+- list.used * sizeof(struct snd_ctl_elem_id))) {
+- vfree(dst);
+- return -EFAULT;
+- }
+- vfree(dst);
+- } else {
+- down_read(&card->controls_rwsem);
+- list.count = card->controls_count;
+- up_read(&card->controls_rwsem);
+ }
+- if (copy_to_user(_list, &list, sizeof(list)))
+- return -EFAULT;
+- return 0;
++ out:
++ up_read(&card->controls_rwsem);
++ if (!err && copy_to_user(_list, &list, sizeof(list)))
++ err = -EFAULT;
++ return err;
+ }
+
+ static bool validate_element_member_dimension(struct snd_ctl_elem_info *info)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-TLV-data-is-unavailable-at-initial-stat.patch b/patches.drivers/ALSA-control-TLV-data-is-unavailable-at-initial-stat.patch
new file mode 100644
index 0000000000..bd9e02cd19
--- /dev/null
+++ b/patches.drivers/ALSA-control-TLV-data-is-unavailable-at-initial-stat.patch
@@ -0,0 +1,84 @@
+From b8e2204b25a50e389dfb50eeff163fa796a8ec6e Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Thu, 24 Aug 2017 10:46:16 +0900
+Subject: [PATCH] ALSA: control: TLV data is unavailable at initial state of user-defined element set
+Git-commit: b8e2204b25a50e389dfb50eeff163fa796a8ec6e
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+For user-defined element set, in its initial state, TLV data is not
+registered. It's firstly available when any application register it by
+an additional operation. However, in current implementation, it's available
+in its initial state. As a result, applications get -ENXIO to read it.
+
+This commit controls its readability to manage info flags properly. In an
+initial state, elements don't have SND_CTL_ELEM_ACCESS_TLV_READ flag. Once
+TLV write operation is executed, they get the flag.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 6ddffe85126f..51d4b4ad3e1d 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1118,6 +1118,7 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
+ struct user_element *ue = kctl->private_data;
+ unsigned int *container;
+ struct snd_ctl_elem_id id;
++ unsigned int mask = 0;
+ int i;
+ int change;
+
+@@ -1136,13 +1137,21 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
+ return 0;
+ }
+
++ if (ue->tlv_data == NULL) {
++ /* Now TLV data is available. */
++ for (i = 0; i < kctl->count; ++i)
++ kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
++ mask = SNDRV_CTL_EVENT_MASK_INFO;
++ }
++
+ kfree(ue->tlv_data);
+ ue->tlv_data = container;
+ ue->tlv_data_size = size;
+
++ mask |= SNDRV_CTL_EVENT_MASK_TLV;
+ for (i = 0; i < kctl->count; ++i) {
+ snd_ctl_build_ioff(&id, kctl, i);
+- snd_ctl_notify(ue->card, SNDRV_CTL_EVENT_MASK_TLV, &id);
++ snd_ctl_notify(ue->card, mask, &id);
+ }
+
+ return change;
+@@ -1277,8 +1286,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
+ access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+ access &= (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE |
+- SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE);
+- if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)
++ SNDRV_CTL_ELEM_ACCESS_TLV_WRITE);
++
++ /* In initial state, nothing is available as TLV container. */
++ if (access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+ access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+ access |= SNDRV_CTL_ELEM_ACCESS_USER;
+
+@@ -1341,7 +1352,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
+ kctl->get = snd_ctl_elem_user_get;
+ if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
+ kctl->put = snd_ctl_elem_user_put;
+- if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)
++ if (access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+ kctl->tlv.c = snd_ctl_elem_user_tlv;
+
+ /* This function manage to free the instance on failure. */
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-code-refactoring-TLV-ioctl-handler.patch b/patches.drivers/ALSA-control-code-refactoring-TLV-ioctl-handler.patch
new file mode 100644
index 0000000000..b39e5e7e75
--- /dev/null
+++ b/patches.drivers/ALSA-control-code-refactoring-TLV-ioctl-handler.patch
@@ -0,0 +1,188 @@
+From 450296f305f139ccb363657efcea439afa4e762a Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Thu, 3 Aug 2017 20:20:43 +0900
+Subject: [PATCH] ALSA: control: code refactoring TLV ioctl handler
+Git-commit: 450296f305f139ccb363657efcea439afa4e762a
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+In a design of ALSA control core, execution path bifurcates depending on
+target element. When a set with the target element has a handler, it's
+called. Else, registered buffer is copied to user space. These two
+operations are apparently different. In current implementation, they're
+on the same function with a condition statement. This makes it a bit hard
+to understand conditions of each case.
+
+This commit splits codes for these two cases.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 132 +++++++++++++++++++++++++++++--------------
+ 1 file changed, 91 insertions(+), 41 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 989292fe33c2..92389000f0df 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1394,65 +1394,115 @@ static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
+ return 0;
+ }
+
++static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
++ struct snd_kcontrol *kctl,
++ struct snd_ctl_elem_id *id,
++ unsigned int __user *buf, unsigned int size)
++{
++ static const struct {
++ int op;
++ int perm;
++ } pairs[] = {
++ {SNDRV_CTL_TLV_OP_READ, SNDRV_CTL_ELEM_ACCESS_TLV_READ},
++ {SNDRV_CTL_TLV_OP_WRITE, SNDRV_CTL_ELEM_ACCESS_TLV_WRITE},
++ {SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
++ };
++ struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
++ int i;
++ int err;
++
++ /* Check support of the request for this element. */
++ for (i = 0; i < ARRAY_SIZE(pairs); ++i) {
++ if (op_flag == pairs[i].op && (vd->access & pairs[i].perm))
++ break;
++ }
++ if (i == ARRAY_SIZE(pairs))
++ return -ENXIO;
++
++ if (kctl->tlv.c == NULL)
++ return -ENXIO;
++
++ /* When locked, this is unavailable. */
++ if (vd->owner != NULL && vd->owner != file)
++ return -EPERM;
++
++ err = kctl->tlv.c(kctl, op_flag, size, buf);
++ if (err < 0)
++ return err;
++
++ if (err > 0)
++ snd_ctl_notify(file->card, SNDRV_CTL_EVENT_MASK_TLV, id);
++
++ return 0;
++}
++
++static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
++ unsigned int __user *buf, unsigned int size)
++{
++ struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
++ unsigned int len;
++
++ if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ))
++ return -ENXIO;
++
++ if (kctl->tlv.p == NULL)
++ return -ENXIO;
++
++ len = sizeof(unsigned int) * 2 + kctl->tlv.p[1];
++ if (size < len)
++ return -ENOMEM;
++
++ if (copy_to_user(buf, kctl->tlv.p, len))
++ return -EFAULT;
++
++ return 0;
++}
++
+ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
+- struct snd_ctl_tlv __user *_tlv,
++ struct snd_ctl_tlv __user *buf,
+ int op_flag)
+ {
+- struct snd_card *card = file->card;
+- struct snd_ctl_tlv tlv;
++ struct snd_ctl_tlv header;
++ unsigned int *container;
++ unsigned int container_size;
+ struct snd_kcontrol *kctl;
++ struct snd_ctl_elem_id id;
+ struct snd_kcontrol_volatile *vd;
+- unsigned int len;
+
+- if (copy_from_user(&tlv, _tlv, sizeof(tlv)))
++ if (copy_from_user(&header, buf, sizeof(header)))
+ return -EFAULT;
+- if (tlv.length < sizeof(unsigned int) * 2)
++
++ /* In design of control core, numerical ID starts at 1. */
++ if (header.numid == 0)
+ return -EINVAL;
+- if (!tlv.numid)
++
++ /* At least, container should include type and length fields. */
++ if (header.length < sizeof(unsigned int) * 2)
+ return -EINVAL;
++ container_size = header.length;
++ container = buf->tlv;
+
+- kctl = snd_ctl_find_numid(card, tlv.numid);
++ kctl = snd_ctl_find_numid(file->card, header.numid);
+ if (kctl == NULL)
+ return -ENOENT;
+
+- if (kctl->tlv.p == NULL)
+- return -ENXIO;
+-
+- vd = &kctl->vd[tlv.numid - kctl->id.numid];
+- if ((op_flag == SNDRV_CTL_TLV_OP_READ &&
+- (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) == 0) ||
+- (op_flag == SNDRV_CTL_TLV_OP_WRITE &&
+- (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) == 0) ||
+- (op_flag == SNDRV_CTL_TLV_OP_CMD &&
+- (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) == 0))
+- return -ENXIO;
++ /* Calculate index of the element in this set. */
++ id = kctl->id;
++ snd_ctl_build_ioff(&id, kctl, header.numid - id.numid);
++ vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)];
+
+ if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+- int err;
+-
+- if (vd->owner != NULL && vd->owner != file)
+- return -EPERM;
+-
+- err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
+- if (err < 0)
+- return err;
+- if (err > 0) {
+- struct snd_ctl_elem_id id = kctl->id;
+- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &id);
+- }
++ return call_tlv_handler(file, op_flag, kctl, &id, container,
++ container_size);
+ } else {
+- if (op_flag != SNDRV_CTL_TLV_OP_READ)
+- return -ENXIO;
+-
+- len = kctl->tlv.p[1] + 2 * sizeof(unsigned int);
+- if (tlv.length < len)
+- return -ENOMEM;
+-
+- if (copy_to_user(_tlv->tlv, kctl->tlv.p, len))
+- return -EFAULT;
++ if (op_flag == SNDRV_CTL_TLV_OP_READ) {
++ return read_tlv_buf(kctl, &id, container,
++ container_size);
++ }
+ }
+
+- return 0;
++ /* Not supported. */
++ return -ENXIO;
+ }
+
+ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-code-refactoring-for-ELEM_READ-ELEM_WRI.patch b/patches.drivers/ALSA-control-code-refactoring-for-ELEM_READ-ELEM_WRI.patch
new file mode 100644
index 0000000000..285442744c
--- /dev/null
+++ b/patches.drivers/ALSA-control-code-refactoring-for-ELEM_READ-ELEM_WRI.patch
@@ -0,0 +1,181 @@
+From becf9e5d553c2389d857a3c178ce80fdb34a02e1 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Sun, 20 Aug 2017 13:49:07 +0900
+Subject: [PATCH] ALSA: control: code refactoring for ELEM_READ/ELEM_WRITE operations
+Git-commit: becf9e5d553c2389d857a3c178ce80fdb34a02e1
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+ALSA control core handles ELEM_READ/ELEM_WRITE requests within lock
+acquisition of a counting semaphore. The lock is acquired in helper
+functions in the end of call path before calling implementations of each
+driver.
+
+ioctl(2) with SNDRV_CTL_ELEM_READ
+...
+->snd_ctl_ioctl()
+ ->snd_ctl_elem_read_user()
+ ->snd_ctl_elem_read()
+ ->down_read(controls_rwsem)
+ ->snd_ctl_find_id()
+ ->struct snd_kcontrol.get()
+ ->up_read(controls_rwsem)
+
+ioctl(2) with SNDRV_CTL_ELEM_WRITE
+...
+->snd_ctl_ioctl()
+ ->snd_ctl_elem_write_user()
+ ->snd_ctl_elem_write()
+ ->down_read(controls_rwsem)
+ ->snd_ctl_find_id()
+ ->struct snd_kcontrol.put()
+ ->up_read(controls_rwsem)
+
+This commit moves the lock acquisition to middle of the call graph to
+simplify the helper functions. As a result:
+
+ioctl(2) with SNDRV_CTL_ELEM_READ
+...
+->snd_ctl_ioctl()
+ ->snd_ctl_elem_read_user()
+ ->down_read(controls_rwsem)
+ ->snd_ctl_elem_read()
+ ->snd_ctl_find_id()
+ ->struct snd_kcontrol.get()
+ ->up_read(controls_rwsem)
+
+ioctl(2) with SNDRV_CTL_ELEM_WRITE
+...
+->snd_ctl_ioctl()
+ ->snd_ctl_elem_write_user()
+ ->down_read(controls_rwsem)
+ ->snd_ctl_elem_write()
+ ->snd_ctl_find_id()
+ ->struct snd_kcontrol.put()
+ ->up_read(controls_rwsem)
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 77 ++++++++++++++++++++++----------------------
+ 1 file changed, 38 insertions(+), 39 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 79fdb366ac8d..1c1fc0898afb 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -881,24 +881,18 @@ static int snd_ctl_elem_read(struct snd_card *card,
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
+ unsigned int index_offset;
+- int result;
+
+- down_read(&card->controls_rwsem);
+ kctl = snd_ctl_find_id(card, &control->id);
+- if (kctl == NULL) {
+- result = -ENOENT;
+- } else {
+- index_offset = snd_ctl_get_ioff(kctl, &control->id);
+- vd = &kctl->vd[index_offset];
+- if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) &&
+- kctl->get != NULL) {
+- snd_ctl_build_ioff(&control->id, kctl, index_offset);
+- result = kctl->get(kctl, control);
+- } else
+- result = -EPERM;
+- }
+- up_read(&card->controls_rwsem);
+- return result;
++ if (kctl == NULL)
++ return -ENOENT;
++
++ index_offset = snd_ctl_get_ioff(kctl, &control->id);
++ vd = &kctl->vd[index_offset];
++ if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get == NULL)
++ return -EPERM;
++
++ snd_ctl_build_ioff(&control->id, kctl, index_offset);
++ return kctl->get(kctl, control);
+ }
+
+ static int snd_ctl_elem_read_user(struct snd_card *card,
+@@ -913,8 +907,11 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
+
+ snd_power_lock(card);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+- if (result >= 0)
++ if (result >= 0) {
++ down_read(&card->controls_rwsem);
+ result = snd_ctl_elem_read(card, control);
++ up_read(&card->controls_rwsem);
++ }
+ snd_power_unlock(card);
+ if (result >= 0)
+ if (copy_to_user(_control, control, sizeof(*control)))
+@@ -931,29 +928,28 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
+ unsigned int index_offset;
+ int result;
+
+- down_read(&card->controls_rwsem);
+ kctl = snd_ctl_find_id(card, &control->id);
+- if (kctl == NULL) {
+- result = -ENOENT;
+- } else {
+- index_offset = snd_ctl_get_ioff(kctl, &control->id);
+- vd = &kctl->vd[index_offset];
+- if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ||
+- kctl->put == NULL ||
+- (file && vd->owner && vd->owner != file)) {
+- result = -EPERM;
+- } else {
+- snd_ctl_build_ioff(&control->id, kctl, index_offset);
+- result = kctl->put(kctl, control);
+- }
+- if (result > 0) {
+- struct snd_ctl_elem_id id = control->id;
+- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
+- result = 0;
+- }
++ if (kctl == NULL)
++ return -ENOENT;
++
++ index_offset = snd_ctl_get_ioff(kctl, &control->id);
++ vd = &kctl->vd[index_offset];
++ if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || kctl->put == NULL ||
++ (file && vd->owner && vd->owner != file)) {
++ return -EPERM;
+ }
+- up_read(&card->controls_rwsem);
+- return result;
++
++ snd_ctl_build_ioff(&control->id, kctl, index_offset);
++ result = kctl->put(kctl, control);
++ if (result < 0)
++ return result;
++
++ if (result > 0) {
++ struct snd_ctl_elem_id id = control->id;
++ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
++ }
++
++ return 0;
+ }
+
+ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
+@@ -970,8 +966,11 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
+ card = file->card;
+ snd_power_lock(card);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+- if (result >= 0)
++ if (result >= 0) {
++ down_read(&card->controls_rwsem);
+ result = snd_ctl_elem_write(card, file, control);
++ up_read(&card->controls_rwsem);
++ }
+ snd_power_unlock(card);
+ if (result >= 0)
+ if (copy_to_user(_control, control, sizeof(*control)))
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-code-refactoring-for-TLV-request-handle.patch b/patches.drivers/ALSA-control-code-refactoring-for-TLV-request-handle.patch
new file mode 100644
index 0000000000..9a2034b667
--- /dev/null
+++ b/patches.drivers/ALSA-control-code-refactoring-for-TLV-request-handle.patch
@@ -0,0 +1,120 @@
+From 6d4d41f011454240e6890068c41e7530fba9f387 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Thu, 3 Aug 2017 20:20:44 +0900
+Subject: [PATCH] ALSA: control: code refactoring for TLV request handler to user element set
+Git-commit: 6d4d41f011454240e6890068c41e7530fba9f387
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+User-defined element set registers own handler to get callbacks from TLV
+ioctl handler. In the handler, execution path bifurcates depending on
+requests from user space. At write request, container in given buffer is
+registered to the element set, or replaced old TLV data. At the read
+request, the registered data is copied to user space. The command request
+is not allowed. In current implementation, function of the handler
+includes codes for the two cases.
+
+This commit adds two helper functions for these cases so that readers can
+easily get the above design.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 80 ++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 48 insertions(+), 32 deletions(-)
+
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1114,43 +1114,59 @@ static int snd_ctl_elem_user_put(struct
+ return change;
+ }
+
+-static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
+- int op_flag,
+- unsigned int size,
+- unsigned int __user *tlv)
++static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
++ unsigned int size)
+ {
+- struct user_element *ue = kcontrol->private_data;
++ struct user_element *ue = kctl->private_data;
++ unsigned int *container;
++ int change;
++
++ if (size > 1024 * 128) /* sane value */
++ return -EINVAL;
++
++ container = memdup_user(buf, size);
++ if (IS_ERR(container))
++ return PTR_ERR(container);
++
++ change = ue->tlv_data_size != size;
++ if (!change)
++ change = memcmp(ue->tlv_data, container, size);
++ if (!change) {
++ kfree(container);
++ return 0;
++ }
+
+- if (op_flag == SNDRV_CTL_TLV_OP_WRITE) {
+- int change;
+- void *new_data;
+-
+- if (size > 1024 * 128) /* sane value */
+- return -EINVAL;
+-
+- new_data = memdup_user(tlv, size);
+- if (IS_ERR(new_data))
+- return PTR_ERR(new_data);
+- change = ue->tlv_data_size != size;
+- if (!change)
+- change = memcmp(ue->tlv_data, new_data, size) != 0;
+- kfree(ue->tlv_data);
+- ue->tlv_data = new_data;
+- ue->tlv_data_size = size;
+-
+- return change;
+- } else {
+- if (!ue->tlv_data_size || !ue->tlv_data)
+- return -ENXIO;
++ kfree(ue->tlv_data);
++ ue->tlv_data = container;
++ ue->tlv_data_size = size;
+
+- if (size < ue->tlv_data_size)
+- return -ENOSPC;
++ return change;
++}
+
+- if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
+- return -EFAULT;
++static int read_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
++ unsigned int size)
++{
++ struct user_element *ue = kctl->private_data;
+
+- return 0;
+- }
++ if (ue->tlv_data_size == 0 || ue->tlv_data == NULL)
++ return -ENXIO;
++
++ if (size < ue->tlv_data_size)
++ return -ENOSPC;
++
++ if (copy_to_user(buf, ue->tlv_data, ue->tlv_data_size))
++ return -EFAULT;
++
++ return 0;
++}
++
++static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kctl, int op_flag,
++ unsigned int size, unsigned int __user *buf)
++{
++ if (op_flag == SNDRV_CTL_TLV_OP_WRITE)
++ return replace_user_tlv(kctl, buf, size);
++ else
++ return read_user_tlv(kctl, buf, size);
+ }
+
+ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
diff --git a/patches.drivers/ALSA-control-delegate-TLV-eventing-to-each-driver.patch b/patches.drivers/ALSA-control-delegate-TLV-eventing-to-each-driver.patch
new file mode 100644
index 0000000000..7f79bf9176
--- /dev/null
+++ b/patches.drivers/ALSA-control-delegate-TLV-eventing-to-each-driver.patch
@@ -0,0 +1,83 @@
+From fb8027ebfd4b8a3050edba66805bc360ed9b3f11 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Thu, 24 Aug 2017 10:46:14 +0900
+Subject: [PATCH] ALSA: control: delegate TLV eventing to each driver
+Git-commit: fb8027ebfd4b8a3050edba66805bc360ed9b3f11
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+In a design of ALSA control core, a set of elements is represented by
+'struct snd_kcontrol' to share common attributes. The set of elements
+shares TLV (Type-Length-Value) data, too.
+
+On the other hand, in ALSA control interface/protocol for applications,
+a TLV operation is committed to an element. Totally, the operation can
+have sub-effect to the other elements in the set. For example, TLV_WRITE
+operation is expected to change TLV data, which returns to applications.
+Applications attempt to change the TLV data per element, but in the above
+design, they can effect to elements in the same set.
+
+As a default, ALSA control core has no implementation except for TLV_READ
+operation. Thus, the above design looks to have no issue. However, in
+kernel APIs of ALSA control component, developers can program a handler
+for any request of the TLV operation. Therefore, for elements in a set
+which has the handler, applications can commit TLV_WRITE and TLV_COMMAND
+requests.
+
+For the above scenario, ALSA control core assist notification. When the
+handler returns positive value, the core queueing an event for a requested
+element. However, this includes design defects that the event is not
+queued for the other element in a set. Actually, developers can program
+the handlers to keep per-element TLV data, but it depends on each driver.
+
+As of v4.13-rc6, there's no driver in tree to utilize the notification,
+except for user-defined element set. This commit delegates the notification
+into each driver to prevent developers from the design defects.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 12 +++---------
+ 1 file changed, 3 insertions(+), 9 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index de976a8c0177..d6a8502da828 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1138,6 +1138,8 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
+ ue->tlv_data = container;
+ ue->tlv_data_size = size;
+
++ snd_ctl_notify(ue->card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
++
+ return change;
+ }
+
+@@ -1423,7 +1425,6 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
+ };
+ struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)];
+ int i;
+- int err;
+
+ /* Check support of the request for this element. */
+ for (i = 0; i < ARRAY_SIZE(pairs); ++i) {
+@@ -1440,14 +1441,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
+ if (vd->owner != NULL && vd->owner != file)
+ return -EPERM;
+
+- err = kctl->tlv.c(kctl, op_flag, size, buf);
+- if (err < 0)
+- return err;
+-
+- if (err > 0)
+- snd_ctl_notify(file->card, SNDRV_CTL_EVENT_MASK_TLV, id);
+-
+- return 0;
++ return kctl->tlv.c(kctl, op_flag, size, buf);
+ }
+
+ static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-obsolete-user_ctl_lock.patch b/patches.drivers/ALSA-control-obsolete-user_ctl_lock.patch
new file mode 100644
index 0000000000..2ea5640df3
--- /dev/null
+++ b/patches.drivers/ALSA-control-obsolete-user_ctl_lock.patch
@@ -0,0 +1,128 @@
+From 30d8340b5857550007ab6fe9744e4384dfa6e55c Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Thu, 3 Aug 2017 20:20:42 +0900
+Subject: [PATCH] ALSA: control: obsolete user_ctl_lock
+Git-commit: 30d8340b5857550007ab6fe9744e4384dfa6e55c
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+At a previous commit, concurrent requests for TLV data are maintained
+exclusively between read requests and write/command requests. TLV
+callback handlers in each driver has no risk from concurrent access for
+reference/change.
+
+In current implementation, 'struct snd_card' has a mutex to control
+concurrent accesses to user-defined element sets. This commit obsoletes it.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/core.h | 2 --
+ sound/core/control.c | 37 +++++++++++++------------------------
+ sound/core/init.c | 1 -
+ 3 files changed, 13 insertions(+), 27 deletions(-)
+
+--- a/include/sound/core.h
++++ b/include/sound/core.h
+@@ -118,8 +118,6 @@ struct snd_card {
+ int user_ctl_count; /* count of all user controls */
+ struct list_head controls; /* all controls for this card */
+ struct list_head ctl_files; /* active control files */
+- struct mutex user_ctl_lock; /* protects user controls against
+- concurrent access */
+
+ struct snd_info_entry *proc_root; /* root for soundcard specific files */
+ struct snd_info_entry *proc_id; /* the card id */
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1095,9 +1095,7 @@ static int snd_ctl_elem_user_get(struct
+ char *src = ue->elem_data +
+ snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
+
+- mutex_lock(&ue->card->user_ctl_lock);
+ memcpy(&ucontrol->value, src, size);
+- mutex_unlock(&ue->card->user_ctl_lock);
+ return 0;
+ }
+
+@@ -1110,11 +1108,9 @@ static int snd_ctl_elem_user_put(struct
+ char *dst = ue->elem_data +
+ snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
+
+- mutex_lock(&ue->card->user_ctl_lock);
+ change = memcmp(&ucontrol->value, dst, size) != 0;
+ if (change)
+ memcpy(dst, &ucontrol->value, size);
+- mutex_unlock(&ue->card->user_ctl_lock);
+ return change;
+ }
+
+@@ -1124,44 +1120,37 @@ static int snd_ctl_elem_user_tlv(struct
+ unsigned int __user *tlv)
+ {
+ struct user_element *ue = kcontrol->private_data;
+- int change = 0;
+- void *new_data;
+
+ if (op_flag == SNDRV_CTL_TLV_OP_WRITE) {
++ int change;
++ void *new_data;
++
+ if (size > 1024 * 128) /* sane value */
+ return -EINVAL;
+
+ new_data = memdup_user(tlv, size);
+ if (IS_ERR(new_data))
+ return PTR_ERR(new_data);
+- mutex_lock(&ue->card->user_ctl_lock);
+ change = ue->tlv_data_size != size;
+ if (!change)
+ change = memcmp(ue->tlv_data, new_data, size) != 0;
+ kfree(ue->tlv_data);
+ ue->tlv_data = new_data;
+ ue->tlv_data_size = size;
+- mutex_unlock(&ue->card->user_ctl_lock);
++
++ return change;
+ } else {
+- int ret = 0;
++ if (!ue->tlv_data_size || !ue->tlv_data)
++ return -ENXIO;
++
++ if (size < ue->tlv_data_size)
++ return -ENOSPC;
+
+- mutex_lock(&ue->card->user_ctl_lock);
+- if (!ue->tlv_data_size || !ue->tlv_data) {
+- ret = -ENXIO;
+- goto err_unlock;
+- }
+- if (size < ue->tlv_data_size) {
+- ret = -ENOSPC;
+- goto err_unlock;
+- }
+ if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
+- ret = -EFAULT;
+-err_unlock:
+- mutex_unlock(&ue->card->user_ctl_lock);
+- if (ret)
+- return ret;
++ return -EFAULT;
++
++ return 0;
+ }
+- return change;
+ }
+
+ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -248,7 +248,6 @@ int snd_card_new(struct device *parent,
+ INIT_LIST_HEAD(&card->devices);
+ init_rwsem(&card->controls_rwsem);
+ rwlock_init(&card->ctl_files_rwlock);
+- mutex_init(&card->user_ctl_lock);
+ INIT_LIST_HEAD(&card->controls);
+ INIT_LIST_HEAD(&card->ctl_files);
+ spin_lock_init(&card->files_lock);
diff --git a/patches.drivers/ALSA-control-queue-TLV-event-for-a-set-of-user-defin.patch b/patches.drivers/ALSA-control-queue-TLV-event-for-a-set-of-user-defin.patch
new file mode 100644
index 0000000000..0a21c0470a
--- /dev/null
+++ b/patches.drivers/ALSA-control-queue-TLV-event-for-a-set-of-user-defin.patch
@@ -0,0 +1,50 @@
+From da4288287b68fe6902629f4e5306aba2a554bc4b Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Thu, 24 Aug 2017 10:46:15 +0900
+Subject: [PATCH] ALSA: control: queue TLV event for a set of user-defined element
+Git-commit: da4288287b68fe6902629f4e5306aba2a554bc4b
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+In a design of user-defined element set, applications allow to change TLV
+data on the set. This operation doesn't only affects to a target element,
+but also to elements in the set.
+
+This commit generates TLV event for all of elements in the set when the TLV
+data is changed.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index d6a8502da828..6ddffe85126f 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1117,6 +1117,8 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
+ {
+ struct user_element *ue = kctl->private_data;
+ unsigned int *container;
++ struct snd_ctl_elem_id id;
++ int i;
+ int change;
+
+ if (size > 1024 * 128) /* sane value */
+@@ -1138,7 +1140,10 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
+ ue->tlv_data = container;
+ ue->tlv_data_size = size;
+
+- snd_ctl_notify(ue->card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
++ for (i = 0; i < kctl->count; ++i) {
++ snd_ctl_build_ioff(&id, kctl, i);
++ snd_ctl_notify(ue->card, SNDRV_CTL_EVENT_MASK_TLV, &id);
++ }
+
+ return change;
+ }
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-queue-events-within-locking-of-controls.patch b/patches.drivers/ALSA-control-queue-events-within-locking-of-controls.patch
new file mode 100644
index 0000000000..8c92458afb
--- /dev/null
+++ b/patches.drivers/ALSA-control-queue-events-within-locking-of-controls.patch
@@ -0,0 +1,47 @@
+From 28a0989c995087129b11ca3e00eb37ab77c29bce Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Thu, 3 Aug 2017 20:20:40 +0900
+Subject: [PATCH] ALSA: control: queue events within locking of controls_rwsem for TLV operation
+Git-commit: 28a0989c995087129b11ca3e00eb37ab77c29bce
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+Any control event is queued by a call of snd_ctl_notify(). This function
+adds the event to each queue of opened file data corresponding to ALSA
+control character devices. This function acquired two types of lock; a
+counting semaphore for a list of the opened file data and a spinlock for
+card data opened by the file. Typically, this function is called after
+acquiring a counting semaphore for a list of elements in the card data.
+
+In current implementation of TLV request handler, the function is called
+after releasing the semaphore for a list of elements in the card data.
+This release is not necessarily needed.
+
+This commit removes the release to call the function within the critical
+section so that later commits are simple.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 3c6be1452e35..d2e1edbf843a 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1450,9 +1450,8 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
+ err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
+ if (err > 0) {
+ struct snd_ctl_elem_id id = kctl->id;
+- up_read(&card->controls_rwsem);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &id);
+- return 0;
++ err = 0;
+ }
+ } else {
+ if (op_flag != SNDRV_CTL_TLV_OP_READ) {
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-queue-events-within-locking-of-ctl-TLV.patch b/patches.drivers/ALSA-control-queue-events-within-locking-of-ctl-TLV.patch
new file mode 100644
index 0000000000..5670e1b71c
--- /dev/null
+++ b/patches.drivers/ALSA-control-queue-events-within-locking-of-ctl-TLV.patch
@@ -0,0 +1,47 @@
+From 7b42cfafdcbf73bd58687cbe3157b9ca4a0fd2e5 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Sun, 20 Aug 2017 13:49:06 +0900
+Subject: [PATCH] ALSA: control: queue events within locking of controls_rwsem for ELEM_WRITE operation
+Git-commit: 7b42cfafdcbf73bd58687cbe3157b9ca4a0fd2e5
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+Any control event is queued by a call of snd_ctl_notify(). This function
+adds the event to each queue of opened file data corresponding to ALSA
+control character devices. This function acquired two types of lock; a
+counting semaphore for a list of the opened file data and a spinlock for
+card data opened by the file. Typically, this function is called after
+acquiring a counting semaphore for a list of elements in the card data.
+
+In current implementation of a handler for ELEM_WRITE request, the
+function is called after releasing the semaphore for a list of elements
+in the card data. This release is not necessarily needed.
+
+This commit removes the release to call the function within the critical
+section so that later commits are simple.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 9e7a4571488b..79fdb366ac8d 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -948,9 +948,8 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
+ }
+ if (result > 0) {
+ struct snd_ctl_elem_id id = control->id;
+- up_read(&card->controls_rwsem);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
+- return 0;
++ result = 0;
+ }
+ }
+ up_read(&card->controls_rwsem);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-remove-entry-limitation-for-list-operat.patch b/patches.drivers/ALSA-control-remove-entry-limitation-for-list-operat.patch
new file mode 100644
index 0000000000..88b8fd2337
--- /dev/null
+++ b/patches.drivers/ALSA-control-remove-entry-limitation-for-list-operat.patch
@@ -0,0 +1,43 @@
+From 4e361d3c962dda16e27d81e7aa9202828a8f7371 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 24 May 2017 10:04:30 +0900
+Subject: [PATCH] ALSA: control: remove entry limitation for list operation
+Git-commit: 4e361d3c962dda16e27d81e7aa9202828a8f7371
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+In current implementation of ALSA control core, list operation has
+a limitation to handle 16384 entries at once. This seems due to
+allocation in kernel space to copy data from user space.
+
+With a commit 53e7bf452584 ("ALSA: control: Simplify snd_ctl_elem_list()
+implementation"), for the operation, ALSA control core copies data
+into user space directly. No need to care of kernel spaces anymore.
+
+This commit purges the limitation.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 47080da8451a..ecd358213b83 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -757,9 +757,7 @@ static int snd_ctl_elem_list(struct snd_card *card,
+ return -EFAULT;
+ offset = list.offset;
+ space = list.space;
+- /* try limit maximum space */
+- if (space > 16384)
+- return -ENOMEM;
++
+ down_read(&card->controls_rwsem);
+ list.count = card->controls_count;
+ list.used = 0;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-use-counting-semaphore-as-write-TLV.patch b/patches.drivers/ALSA-control-use-counting-semaphore-as-write-TLV.patch
new file mode 100644
index 0000000000..f891abef32
--- /dev/null
+++ b/patches.drivers/ALSA-control-use-counting-semaphore-as-write-TLV.patch
@@ -0,0 +1,72 @@
+From 5bbb1ab5bd0b01c4f0b19ae03fdfec487f839517 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Sun, 20 Aug 2017 13:49:08 +0900
+Subject: [PATCH] ALSA: control: use counting semaphore as write lock for ELEM_WRITE operation
+Git-commit: 5bbb1ab5bd0b01c4f0b19ae03fdfec487f839517
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+In ALSA control interface, applications can execute two types of request
+for value of members on each element; ELEM_READ and ELEM_WRITE. In ALSA
+control core, these two requests are handled within read lock of a
+counting semaphore, therefore several processes can run to execute these
+two requests at the same time. This has an issue because ELEM_WRITE
+requests have an effect to change state of the target element. Concurrent
+access should be controlled for each of ELEM_READ/ELEM_WRITE case.
+
+This commit uses the counting semaphore as write lock for ELEM_WRITE
+requests, while use it as read lock for ELEM_READ requests. The state of
+a target element is maintained exclusively between ELEM_WRITE/ELEM_READ
+operations.
+
+There's a concern. If the counting semaphore is acquired for read lock
+in implementations of 'struct snd_kcontrol.put()' in each driver, this
+commit shall cause dead lock. As of v4.13-rc5, 'snd-mixer-oss.ko',
+'snd-emu10k1.ko' and 'snd-soc-sst-atom-hifi2-platform.ko' includes codes
+for read locks, but these are not in a call graph from
+'struct snd_kcontrol.put(). Therefore, this commit is safe.
+
+In current implementation, the same solution is applied for the other
+operations to element; e.g. ELEM_LOCK and ELEM_UNLOCK. There's another
+discussion about an overhead to maintain concurrent access to an element
+during operating the other elements on the same card instance, because the
+lock primitive is originally implemented to maintain a list of elements on
+the card instance. There's a substantial difference between
+per-element-list lock and per-element lock.
+
+Here, let me investigate another idea to add per-element lock to maintain
+the concurrent accesses with inquiry/change requests to an element. It's
+not so frequent for applications to operate members on elements, while
+adding a new lock primitive to structure increases memory footprint for
+all of element sets somehow. Experimentally, inquiry operation is more
+frequent than change operation and usage of counting semaphore for the
+inquiry operation brings no blocking to the other inquiry operations. Thus
+the overhead is not so critical for usual applications. For the above
+reasons, in this commit, the per-element lock is not introduced.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index 1c1fc0898afb..249140c15d64 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -967,9 +967,9 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
+ snd_power_lock(card);
+ result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+ if (result >= 0) {
+- down_read(&card->controls_rwsem);
++ down_write(&card->controls_rwsem);
+ result = snd_ctl_elem_write(card, file, control);
+- up_read(&card->controls_rwsem);
++ up_write(&card->controls_rwsem);
+ }
+ snd_power_unlock(card);
+ if (result >= 0)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-control-use-counting-semaphore-as-write-lock-fo.patch b/patches.drivers/ALSA-control-use-counting-semaphore-as-write-lock-fo.patch
new file mode 100644
index 0000000000..8bd3fed977
--- /dev/null
+++ b/patches.drivers/ALSA-control-use-counting-semaphore-as-write-lock-fo.patch
@@ -0,0 +1,148 @@
+From 4c8099e9cad5ba11c770042549f68e7687eaa72b Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Thu, 3 Aug 2017 20:20:41 +0900
+Subject: [PATCH] ALSA: control: use counting semaphore as write lock for TLV write/command operations
+Git-commit: 4c8099e9cad5ba11c770042549f68e7687eaa72b
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+In ALSA control interface, applications can execute three types of request
+for Type-Length-Value (TLV) data to a set of elements; read, write and
+command. In ALSA control core, all of the requests are handled within read
+lock to a counting semaphore, therefore several processes can run to access
+to the data at the same time for any purposes. This has an issue because
+write and command requests have side effect to change state of a set of
+elements for the TLV data. Concurrent access should be controlled for each
+of reference/change case.
+
+This commit uses the counting semaphore as read lock for TLV read requests,
+while use it as write lock for TLV write/command requests. The state of a
+set of elements for the TLV data is maintained exclusively between read
+requests and write/command requests, or between write and command requests.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/control.c | 72 +++++++++++++++++++++++---------------------
+ 1 file changed, 38 insertions(+), 34 deletions(-)
+
+diff --git a/sound/core/control.c b/sound/core/control.c
+index d2e1edbf843a..f3bd9bdba9a7 100644
+--- a/sound/core/control.c
++++ b/sound/core/control.c
+@@ -1414,7 +1414,6 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
+ unsigned int len;
+- int err = 0;
+
+ if (copy_from_user(&tlv, _tlv, sizeof(tlv)))
+ return -EFAULT;
+@@ -1422,53 +1421,49 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
+ return -EINVAL;
+ if (!tlv.numid)
+ return -EINVAL;
+- down_read(&card->controls_rwsem);
++
+ kctl = snd_ctl_find_numid(card, tlv.numid);
+- if (kctl == NULL) {
+- err = -ENOENT;
+- goto __kctl_end;
+- }
+- if (kctl->tlv.p == NULL) {
+- err = -ENXIO;
+- goto __kctl_end;
+- }
++ if (kctl == NULL)
++ return -ENOENT;
++
++ if (kctl->tlv.p == NULL)
++ return -ENXIO;
++
+ vd = &kctl->vd[tlv.numid - kctl->id.numid];
+ if ((op_flag == SNDRV_CTL_TLV_OP_READ &&
+ (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) == 0) ||
+ (op_flag == SNDRV_CTL_TLV_OP_WRITE &&
+ (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) == 0) ||
+ (op_flag == SNDRV_CTL_TLV_OP_CMD &&
+- (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) == 0)) {
+- err = -ENXIO;
+- goto __kctl_end;
+- }
++ (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) == 0))
++ return -ENXIO;
++
+ if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+- if (vd->owner != NULL && vd->owner != file) {
+- err = -EPERM;
+- goto __kctl_end;
+- }
++ int err;
++
++ if (vd->owner != NULL && vd->owner != file)
++ return -EPERM;
++
+ err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
++ if (err < 0)
++ return err;
+ if (err > 0) {
+ struct snd_ctl_elem_id id = kctl->id;
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &id);
+- err = 0;
+ }
+ } else {
+- if (op_flag != SNDRV_CTL_TLV_OP_READ) {
+- err = -ENXIO;
+- goto __kctl_end;
+- }
++ if (op_flag != SNDRV_CTL_TLV_OP_READ)
++ return -ENXIO;
++
+ len = kctl->tlv.p[1] + 2 * sizeof(unsigned int);
+- if (tlv.length < len) {
+- err = -ENOMEM;
+- goto __kctl_end;
+- }
++ if (tlv.length < len)
++ return -ENOMEM;
++
+ if (copy_to_user(_tlv->tlv, kctl->tlv.p, len))
+- err = -EFAULT;
++ return -EFAULT;
+ }
+- __kctl_end:
+- up_read(&card->controls_rwsem);
+- return err;
++
++ return 0;
+ }
+
+ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+@@ -1510,11 +1505,20 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
+ case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
+ return snd_ctl_subscribe_events(ctl, ip);
+ case SNDRV_CTL_IOCTL_TLV_READ:
+- return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
++ down_read(&ctl->card->controls_rwsem);
++ err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
++ up_read(&ctl->card->controls_rwsem);
++ return err;
+ case SNDRV_CTL_IOCTL_TLV_WRITE:
+- return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
++ down_write(&ctl->card->controls_rwsem);
++ err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
++ up_write(&ctl->card->controls_rwsem);
++ return err;
+ case SNDRV_CTL_IOCTL_TLV_COMMAND:
+- return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
++ down_write(&ctl->card->controls_rwsem);
++ err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
++ up_write(&ctl->card->controls_rwsem);
++ return err;
+ case SNDRV_CTL_IOCTL_POWER:
+ return -ENOPROTOOPT;
+ case SNDRV_CTL_IOCTL_POWER_STATE:
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-core-Follow-standard-EXPORT_SYMBOL-declarations.patch b/patches.drivers/ALSA-core-Follow-standard-EXPORT_SYMBOL-declarations.patch
new file mode 100644
index 0000000000..348eecfbc7
--- /dev/null
+++ b/patches.drivers/ALSA-core-Follow-standard-EXPORT_SYMBOL-declarations.patch
@@ -0,0 +1,328 @@
+From 35f8001415d301ba47124f463f98eee0e7d0792c Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 16 Jun 2017 16:16:33 +0200
+Subject: [PATCH] ALSA: core: Follow standard EXPORT_SYMBOL() declarations
+Git-commit: 35f8001415d301ba47124f463f98eee0e7d0792c
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Just a tidy up to follow the standard EXPORT_SYMBOL*() declarations
+in order to improve grep-ability.
+
+- Move EXPORT_SYMBOL*() to the position right after its definition
+- Remove superfluous blank line before EXPORT_SYMBOL*() lines
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/info.c | 6 ------
+ sound/core/info_oss.c | 1 -
+ sound/core/init.c | 8 +-------
+ sound/core/isadma.c | 3 ---
+ sound/core/memalloc.c | 13 ++++---------
+ sound/core/memory.c | 2 --
+ sound/core/misc.c | 1 -
+ sound/core/oss/mixer_oss.c | 3 +--
+ sound/core/sound.c | 2 --
+ sound/core/sound_oss.c | 3 ---
+ 10 files changed, 6 insertions(+), 36 deletions(-)
+
+diff --git a/sound/core/info.c b/sound/core/info.c
+index fc14ebe751d8..bcf6a48cc70d 100644
+--- a/sound/core/info.c
++++ b/sound/core/info.c
+@@ -652,7 +652,6 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
+ *line = '\0';
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_info_get_line);
+
+ /**
+@@ -690,7 +689,6 @@ const char *snd_info_get_str(char *dest, const char *src, int len)
+ src++;
+ return src;
+ }
+-
+ EXPORT_SYMBOL(snd_info_get_str);
+
+ /*
+@@ -748,7 +746,6 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module,
+ entry->module = module;
+ return entry;
+ }
+-
+ EXPORT_SYMBOL(snd_info_create_module_entry);
+
+ /**
+@@ -772,7 +769,6 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
+ }
+ return entry;
+ }
+-
+ EXPORT_SYMBOL(snd_info_create_card_entry);
+
+ static void snd_info_disconnect(struct snd_info_entry *entry)
+@@ -815,7 +811,6 @@ void snd_info_free_entry(struct snd_info_entry * entry)
+ entry->private_free(entry);
+ kfree(entry);
+ }
+-
+ EXPORT_SYMBOL(snd_info_free_entry);
+
+ /**
+@@ -858,7 +853,6 @@ int snd_info_register(struct snd_info_entry * entry)
+ mutex_unlock(&info_mutex);
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_info_register);
+
+ /*
+diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
+index 1478c8dfd473..f479374b6bd8 100644
+--- a/sound/core/info_oss.c
++++ b/sound/core/info_oss.c
+@@ -61,7 +61,6 @@ int snd_oss_info_register(int dev, int num, char *string)
+ mutex_unlock(&strings);
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_oss_info_register);
+
+ static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev)
+diff --git a/sound/core/init.c b/sound/core/init.c
+index 6bda8436d765..00f2cbb76e69 100644
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -452,7 +452,6 @@ int snd_card_disconnect(struct snd_card *card)
+ #endif
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_card_disconnect);
+
+ static int snd_card_do_free(struct snd_card *card)
+@@ -718,7 +717,7 @@ int snd_card_add_dev_attr(struct snd_card *card,
+
+ dev_err(card->dev, "Too many groups assigned\n");
+ return -ENOSPC;
+-};
++}
+ EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
+
+ /**
+@@ -775,7 +774,6 @@ int snd_card_register(struct snd_card *card)
+ #endif
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_card_register);
+
+ #ifdef CONFIG_SND_PROC_FS
+@@ -895,7 +893,6 @@ int snd_component_add(struct snd_card *card, const char *component)
+ strcat(card->components, component);
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_component_add);
+
+ /**
+@@ -930,7 +927,6 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
+ spin_unlock(&card->files_lock);
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_card_file_add);
+
+ /**
+@@ -972,7 +968,6 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
+ put_device(&card->card_dev);
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_card_file_remove);
+
+ #ifdef CONFIG_PM
+@@ -1012,6 +1007,5 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state)
+ remove_wait_queue(&card->power_sleep, &wait);
+ return result;
+ }
+-
+ EXPORT_SYMBOL(snd_power_wait);
+ #endif /* CONFIG_PM */
+diff --git a/sound/core/isadma.c b/sound/core/isadma.c
+index 31e8544d7f2d..7a8515abb5f9 100644
+--- a/sound/core/isadma.c
++++ b/sound/core/isadma.c
+@@ -55,7 +55,6 @@ void snd_dma_program(unsigned long dma,
+ enable_dma(dma);
+ release_dma_lock(flags);
+ }
+-
+ EXPORT_SYMBOL(snd_dma_program);
+
+ /**
+@@ -73,7 +72,6 @@ void snd_dma_disable(unsigned long dma)
+ disable_dma(dma);
+ release_dma_lock(flags);
+ }
+-
+ EXPORT_SYMBOL(snd_dma_disable);
+
+ /**
+@@ -113,5 +111,4 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
+ else
+ return size - result;
+ }
+-
+ EXPORT_SYMBOL(snd_dma_pointer);
+diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
+index f05cb6a8cbe0..7f89d3c79a4b 100644
+--- a/sound/core/memalloc.c
++++ b/sound/core/memalloc.c
+@@ -54,6 +54,7 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
+ pg = get_order(size);
+ return (void *) __get_free_pages(gfp_flags, pg);
+ }
++EXPORT_SYMBOL(snd_malloc_pages);
+
+ /**
+ * snd_free_pages - release the pages
+@@ -71,6 +72,7 @@ void snd_free_pages(void *ptr, size_t size)
+ pg = get_order(size);
+ free_pages((unsigned long) ptr, pg);
+ }
++EXPORT_SYMBOL(snd_free_pages);
+
+ /*
+ *
+@@ -217,6 +219,7 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
+ dmab->bytes = size;
+ return 0;
+ }
++EXPORT_SYMBOL(snd_dma_alloc_pages);
+
+ /**
+ * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
+@@ -254,6 +257,7 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
+ return -ENOMEM;
+ return 0;
+ }
++EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
+
+
+ /**
+@@ -287,13 +291,4 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
+ pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type);
+ }
+ }
+-
+-/*
+- * exports
+- */
+-EXPORT_SYMBOL(snd_dma_alloc_pages);
+-EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
+ EXPORT_SYMBOL(snd_dma_free_pages);
+-
+-EXPORT_SYMBOL(snd_malloc_pages);
+-EXPORT_SYMBOL(snd_free_pages);
+diff --git a/sound/core/memory.c b/sound/core/memory.c
+index 4cd664efad77..19c9ea90d9bf 100644
+--- a/sound/core/memory.c
++++ b/sound/core/memory.c
+@@ -55,7 +55,6 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size
+ return 0;
+ #endif
+ }
+-
+ EXPORT_SYMBOL(copy_to_user_fromio);
+
+ /**
+@@ -88,5 +87,4 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size
+ return 0;
+ #endif
+ }
+-
+ EXPORT_SYMBOL(copy_from_user_toio);
+diff --git a/sound/core/misc.c b/sound/core/misc.c
+index 21b228046e88..0f818d593c9e 100644
+--- a/sound/core/misc.c
++++ b/sound/core/misc.c
+@@ -48,7 +48,6 @@ void release_and_free_resource(struct resource *res)
+ kfree(res);
+ }
+ }
+-
+ EXPORT_SYMBOL(release_and_free_resource);
+
+ #ifdef CONFIG_SND_VERBOSE_PRINTK
+diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
+index 2ff9c12d664a..379bf486ccc7 100644
+--- a/sound/core/oss/mixer_oss.c
++++ b/sound/core/oss/mixer_oss.c
+@@ -395,6 +395,7 @@ int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned l
+ fmixer.mixer = card->mixer_oss;
+ return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
+ }
++EXPORT_SYMBOL(snd_mixer_oss_ioctl_card);
+
+ #ifdef CONFIG_COMPAT
+ /* all compatible */
+@@ -1425,5 +1426,3 @@ static void __exit alsa_mixer_oss_exit(void)
+
+ module_init(alsa_mixer_oss_init)
+ module_exit(alsa_mixer_oss_exit)
+-
+-EXPORT_SYMBOL(snd_mixer_oss_ioctl_card);
+diff --git a/sound/core/sound.c b/sound/core/sound.c
+index 175f9e4e01c8..b30f027eb0fe 100644
+--- a/sound/core/sound.c
++++ b/sound/core/sound.c
+@@ -74,7 +74,6 @@ void snd_request_card(int card)
+ return;
+ request_module("snd-card-%i", card);
+ }
+-
+ EXPORT_SYMBOL(snd_request_card);
+
+ static void snd_request_other(int minor)
+@@ -124,7 +123,6 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
+ mutex_unlock(&sound_mutex);
+ return private_data;
+ }
+-
+ EXPORT_SYMBOL(snd_lookup_minor_data);
+
+ #ifdef CONFIG_MODULES
+diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
+index 0ca9d72b2273..0a5c66229a22 100644
+--- a/sound/core/sound_oss.c
++++ b/sound/core/sound_oss.c
+@@ -55,7 +55,6 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
+ mutex_unlock(&sound_oss_mutex);
+ return private_data;
+ }
+-
+ EXPORT_SYMBOL(snd_lookup_oss_minor_data);
+
+ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
+@@ -159,7 +158,6 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
+ kfree(preg);
+ return -EBUSY;
+ }
+-
+ EXPORT_SYMBOL(snd_register_oss_device);
+
+ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
+@@ -200,7 +198,6 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
+ kfree(mptr);
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_unregister_oss_device);
+
+ /*
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-core-Use-pS-printk-format-for-direct-addresses.patch b/patches.drivers/ALSA-core-Use-pS-printk-format-for-direct-addresses.patch
new file mode 100644
index 0000000000..3dcce84a55
--- /dev/null
+++ b/patches.drivers/ALSA-core-Use-pS-printk-format-for-direct-addresses.patch
@@ -0,0 +1,45 @@
+From c8445589450582a3d948779c0fc5106604ce89a1 Mon Sep 17 00:00:00 2001
+From: Helge Deller <deller@gmx.de>
+Date: Wed, 6 Sep 2017 22:28:01 +0200
+Subject: [PATCH] ALSA: core: Use %pS printk format for direct addresses
+Git-commit: c8445589450582a3d948779c0fc5106604ce89a1
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+The debug functions uses wrongly the %pF instead of the %pS printk format
+specifier for printing symbols for the address returned by
+_builtin_return_address(0). Fix it for the ia64, ppc64 and parisc64
+architectures.
+
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/device.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/core/device.c b/sound/core/device.c
+index 8918838b1999..cb0e46f66cc9 100644
+--- a/sound/core/device.c
++++ b/sound/core/device.c
+@@ -128,7 +128,7 @@ void snd_device_disconnect(struct snd_card *card, void *device_data)
+ if (dev)
+ __snd_device_disconnect(dev);
+ else
+- dev_dbg(card->dev, "device disconnect %p (from %pF), not found\n",
++ dev_dbg(card->dev, "device disconnect %p (from %pS), not found\n",
+ device_data, __builtin_return_address(0));
+ }
+ EXPORT_SYMBOL_GPL(snd_device_disconnect);
+@@ -152,7 +152,7 @@ void snd_device_free(struct snd_card *card, void *device_data)
+ if (dev)
+ __snd_device_free(dev);
+ else
+- dev_dbg(card->dev, "device free %p (from %pF), not found\n",
++ dev_dbg(card->dev, "device free %p (from %pS), not found\n",
+ device_data, __builtin_return_address(0));
+ }
+ EXPORT_SYMBOL(snd_device_free);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-declare-snd_kcontrol_new-structures-as-const.patch b/patches.drivers/ALSA-declare-snd_kcontrol_new-structures-as-const.patch
new file mode 100644
index 0000000000..3d7900e29f
--- /dev/null
+++ b/patches.drivers/ALSA-declare-snd_kcontrol_new-structures-as-const.patch
@@ -0,0 +1,582 @@
+From 905e46acd3272d04566fec49afbd7ad9e2ed9ae3 Mon Sep 17 00:00:00 2001
+From: Bhumika Goyal <bhumirks@gmail.com>
+Date: Sat, 27 May 2017 20:16:15 +0530
+Subject: [PATCH] ALSA: declare snd_kcontrol_new structures as const
+Git-commit: 905e46acd3272d04566fec49afbd7ad9e2ed9ae3
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Declare snd_kcontrol_new structures as const as they are only passed an
+argument to the function snd_ctl_new1. This argument is of type const,
+so snd_kcontrol_new structures having this property can be made const.
+Done using Coccinelle:
+
+@r disable optional_qualifier@
+identifier x;
+position p;
+@@
+static struct snd_kcontrol_new x@p={...};
+
+@ok@
+identifier r.x;
+position p;
+@@
+snd_ctl_new1(&x@p,...)
+
+@bad@
+position p != {r.p,ok.p};
+identifier r.x;
+@@
+x@p
+
+@depends on !bad disable optional_qualifier@
+identifier r.x;
+@@
++const
+struct snd_kcontrol_new x;
+
+Cross compiled these files:
+sound/aoa/codecs/tas.c - powerpc
+sound/mips/{hal2.c/sgio2audio.c} - mips
+sound/ppc/{awacs.c/beep.c/tumbler.c} - powerpc
+sound/soc/sh/siu_dai.c - sh
+Could not find an architecture to compile sound/sh/aica.c.
+
+Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
+Acked-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/aoa/codecs/tas.c | 14 +++++++-------
+ sound/aoa/fabrics/layout.c | 8 ++++----
+ sound/core/ctljack.c | 2 +-
+ sound/drivers/vx/vx_mixer.c | 24 ++++++++++++------------
+ sound/firewire/bebob/bebob_maudio.c | 8 ++++----
+ sound/mips/hal2.c | 4 ++--
+ sound/mips/sgio2audio.c | 14 +++++++-------
+ sound/pcmcia/vx/vxp_mixer.c | 4 ++--
+ sound/ppc/awacs.c | 4 ++--
+ sound/ppc/beep.c | 2 +-
+ sound/ppc/tumbler.c | 8 ++++----
+ sound/sh/aica.c | 4 ++--
+ sound/soc/sh/siu_dai.c | 4 ++--
+ sound/usb/mixer_quirks.c | 2 +-
+ 14 files changed, 51 insertions(+), 51 deletions(-)
+
+diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
+index 78ed1ffbf786..733b6365dad6 100644
+--- a/sound/aoa/codecs/tas.c
++++ b/sound/aoa/codecs/tas.c
+@@ -271,7 +271,7 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
+-static struct snd_kcontrol_new volume_control = {
++static const struct snd_kcontrol_new volume_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -314,7 +314,7 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
+-static struct snd_kcontrol_new mute_control = {
++static const struct snd_kcontrol_new mute_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -426,7 +426,7 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
+-static struct snd_kcontrol_new drc_range_control = {
++static const struct snd_kcontrol_new drc_range_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "DRC Range",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -466,7 +466,7 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
+-static struct snd_kcontrol_new drc_switch_control = {
++static const struct snd_kcontrol_new drc_switch_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "DRC Range Switch",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -524,7 +524,7 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
+-static struct snd_kcontrol_new capture_source_control = {
++static const struct snd_kcontrol_new capture_source_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* If we name this 'Input Source', it properly shows up in
+ * alsamixer as a selection, * but it's shown under the
+@@ -586,7 +586,7 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
+-static struct snd_kcontrol_new treble_control = {
++static const struct snd_kcontrol_new treble_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Treble",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -637,7 +637,7 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
+-static struct snd_kcontrol_new bass_control = {
++static const struct snd_kcontrol_new bass_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Bass",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c
+index a0c4a5de809c..1eddf8fa188f 100644
+--- a/sound/aoa/fabrics/layout.c
++++ b/sound/aoa/fabrics/layout.c
+@@ -707,7 +707,7 @@ static int detect_choice_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
+-static struct snd_kcontrol_new headphone_detect_choice = {
++static const struct snd_kcontrol_new headphone_detect_choice = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Headphone Detect Autoswitch",
+ .info = control_info,
+@@ -717,7 +717,7 @@ static struct snd_kcontrol_new headphone_detect_choice = {
+ .private_value = 0,
+ };
+
+-static struct snd_kcontrol_new lineout_detect_choice = {
++static const struct snd_kcontrol_new lineout_detect_choice = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line-Out Detect Autoswitch",
+ .info = control_info,
+@@ -749,7 +749,7 @@ static int detected_get(struct snd_kcontrol *kcontrol,
+ return 0;
+ }
+
+-static struct snd_kcontrol_new headphone_detected = {
++static const struct snd_kcontrol_new headphone_detected = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Headphone Detected",
+ .info = control_info,
+@@ -758,7 +758,7 @@ static struct snd_kcontrol_new headphone_detected = {
+ .private_value = 0,
+ };
+
+-static struct snd_kcontrol_new lineout_detected = {
++static const struct snd_kcontrol_new lineout_detected = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line-Out Detected",
+ .info = control_info,
+diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c
+index 84a3cd683068..0249d5e6ac23 100644
+--- a/sound/core/ctljack.c
++++ b/sound/core/ctljack.c
+@@ -23,7 +23,7 @@ static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
+ return 0;
+ }
+
+-static struct snd_kcontrol_new jack_detect_kctl = {
++static const struct snd_kcontrol_new jack_detect_kctl = {
+ /* name is filled later */
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
+index be9477e30739..98a41ac40b60 100644
+--- a/sound/drivers/vx/vx_mixer.c
++++ b/sound/drivers/vx/vx_mixer.c
+@@ -455,7 +455,7 @@ static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
+ return 0;
+ }
+
+-static struct snd_kcontrol_new vx_control_output_level = {
++static const struct snd_kcontrol_new vx_control_output_level = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+@@ -514,7 +514,7 @@ static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
+ return 0;
+ }
+
+-static struct snd_kcontrol_new vx_control_audio_src = {
++static const struct snd_kcontrol_new vx_control_audio_src = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = vx_audio_src_info,
+@@ -558,7 +558,7 @@ static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
+ return 0;
+ }
+
+-static struct snd_kcontrol_new vx_control_clock_mode = {
++static const struct snd_kcontrol_new vx_control_clock_mode = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Clock Mode",
+ .info = vx_clock_mode_info,
+@@ -717,7 +717,7 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
+
+ static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0);
+
+-static struct snd_kcontrol_new vx_control_audio_gain = {
++static const struct snd_kcontrol_new vx_control_audio_gain = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+@@ -727,14 +727,14 @@ static struct snd_kcontrol_new vx_control_audio_gain = {
+ .put = vx_audio_gain_put,
+ .tlv = { .p = db_scale_audio_gain },
+ };
+-static struct snd_kcontrol_new vx_control_output_switch = {
++static const struct snd_kcontrol_new vx_control_output_switch = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Switch",
+ .info = vx_audio_sw_info,
+ .get = vx_audio_sw_get,
+ .put = vx_audio_sw_put
+ };
+-static struct snd_kcontrol_new vx_control_monitor_gain = {
++static const struct snd_kcontrol_new vx_control_monitor_gain = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Monitoring Volume",
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+@@ -744,7 +744,7 @@ static struct snd_kcontrol_new vx_control_monitor_gain = {
+ .put = vx_audio_monitor_put,
+ .tlv = { .p = db_scale_audio_gain },
+ };
+-static struct snd_kcontrol_new vx_control_monitor_switch = {
++static const struct snd_kcontrol_new vx_control_monitor_switch = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Monitoring Switch",
+ .info = vx_audio_sw_info, /* shared */
+@@ -805,7 +805,7 @@ static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
+ return 0;
+ }
+
+-static struct snd_kcontrol_new vx_control_iec958_mask = {
++static const struct snd_kcontrol_new vx_control_iec958_mask = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
+@@ -813,7 +813,7 @@ static struct snd_kcontrol_new vx_control_iec958_mask = {
+ .get = vx_iec958_mask_get,
+ };
+
+-static struct snd_kcontrol_new vx_control_iec958 = {
++static const struct snd_kcontrol_new vx_control_iec958 = {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .info = vx_iec958_info,
+@@ -878,7 +878,7 @@ static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
+ return 0;
+ }
+
+-static struct snd_kcontrol_new vx_control_vu_meter = {
++static const struct snd_kcontrol_new vx_control_vu_meter = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ /* name will be filled later */
+@@ -886,7 +886,7 @@ static struct snd_kcontrol_new vx_control_vu_meter = {
+ .get = vx_vu_meter_get,
+ };
+
+-static struct snd_kcontrol_new vx_control_peak_meter = {
++static const struct snd_kcontrol_new vx_control_peak_meter = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ /* name will be filled later */
+@@ -894,7 +894,7 @@ static struct snd_kcontrol_new vx_control_peak_meter = {
+ .get = vx_peak_meter_get,
+ };
+
+-static struct snd_kcontrol_new vx_control_saturation = {
++static const struct snd_kcontrol_new vx_control_saturation = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Input Saturation",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c
+index 07e5abdbceb5..d10208f92edf 100644
+--- a/sound/firewire/bebob/bebob_maudio.c
++++ b/sound/firewire/bebob/bebob_maudio.c
+@@ -396,7 +396,7 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl,
+
+ return err;
+ }
+-static struct snd_kcontrol_new special_clk_ctl = {
++static const struct snd_kcontrol_new special_clk_ctl = {
+ .name = "Clock Source",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -429,7 +429,7 @@ static int special_sync_ctl_get(struct snd_kcontrol *kctl,
+
+ return 0;
+ }
+-static struct snd_kcontrol_new special_sync_ctl = {
++static const struct snd_kcontrol_new special_sync_ctl = {
+ .name = "Sync Status",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+@@ -521,7 +521,7 @@ static int special_dig_in_iface_ctl_set(struct snd_kcontrol *kctl,
+ mutex_unlock(&bebob->mutex);
+ return err;
+ }
+-static struct snd_kcontrol_new special_dig_in_iface_ctl = {
++static const struct snd_kcontrol_new special_dig_in_iface_ctl = {
+ .name = "Digital Input Interface",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -577,7 +577,7 @@ static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl,
+ mutex_unlock(&bebob->mutex);
+ return err;
+ }
+-static struct snd_kcontrol_new special_dig_out_iface_ctl = {
++static const struct snd_kcontrol_new special_dig_out_iface_ctl = {
+ .name = "Digital Output Interface",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
+index 684dc4ddef41..6505deb8c06b 100644
+--- a/sound/mips/hal2.c
++++ b/sound/mips/hal2.c
+@@ -264,7 +264,7 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol,
+ return old != new;
+ }
+
+-static struct snd_kcontrol_new hal2_ctrl_headphone = {
++static const struct snd_kcontrol_new hal2_ctrl_headphone = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Headphone Playback Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -274,7 +274,7 @@ static struct snd_kcontrol_new hal2_ctrl_headphone = {
+ .put = hal2_gain_put,
+ };
+
+-static struct snd_kcontrol_new hal2_ctrl_mic = {
++static const struct snd_kcontrol_new hal2_ctrl_mic = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic Capture Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
+index f07aa3993f83..0ebc1c3727df 100644
+--- a/sound/mips/sgio2audio.c
++++ b/sound/mips/sgio2audio.c
+@@ -230,7 +230,7 @@ static int sgio2audio_source_put(struct snd_kcontrol *kcontrol,
+ }
+
+ /* dac1/pcm0 mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
++static const struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Volume",
+ .index = 0,
+@@ -242,7 +242,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
+ };
+
+ /* dac2/pcm1 mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
++static const struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Volume",
+ .index = 1,
+@@ -254,7 +254,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
+ };
+
+ /* record level mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
++static const struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -265,7 +265,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
+ };
+
+ /* record level source control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
++static const struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -275,7 +275,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
+ };
+
+ /* line mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_line = {
++static const struct snd_kcontrol_new sgio2audio_ctrl_line = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line Playback Volume",
+ .index = 0,
+@@ -287,7 +287,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_line = {
+ };
+
+ /* cd mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_cd = {
++static const struct snd_kcontrol_new sgio2audio_ctrl_cd = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line Playback Volume",
+ .index = 1,
+@@ -299,7 +299,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_cd = {
+ };
+
+ /* mic mixer control */
+-static struct snd_kcontrol_new sgio2audio_ctrl_mic = {
++static const struct snd_kcontrol_new sgio2audio_ctrl_mic = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic Playback Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c
+index 1ca3eef9e305..304b153005a5 100644
+--- a/sound/pcmcia/vx/vxp_mixer.c
++++ b/sound/pcmcia/vx/vxp_mixer.c
+@@ -69,7 +69,7 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
+
+ static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);
+
+-static struct snd_kcontrol_new vx_control_mic_level = {
++static const struct snd_kcontrol_new vx_control_mic_level = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+@@ -109,7 +109,7 @@ static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
+ return 0;
+ }
+
+-static struct snd_kcontrol_new vx_control_mic_boost = {
++static const struct snd_kcontrol_new vx_control_mic_boost = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic Boost",
+ .info = vx_mic_boost_info,
+diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
+index 1468e4b7bf93..d1e4ef1c5c30 100644
+--- a/sound/ppc/awacs.c
++++ b/sound/ppc/awacs.c
+@@ -514,7 +514,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = {
+ },
+ };
+
+-static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
++static const struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Headphone Playback Switch",
+ .info = snd_pmac_boolean_stereo_info,
+@@ -523,7 +523,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
+ .private_value = AMP_CH_HD,
+ };
+
+-static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {
++static const struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Speaker Playback Switch",
+ .info = snd_pmac_boolean_stereo_info,
+diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
+index d3524f9fa05d..f19eb3e39937 100644
+--- a/sound/ppc/beep.c
++++ b/sound/ppc/beep.c
+@@ -206,7 +206,7 @@ static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol,
+ return oval != chip->beep->volume;
+ }
+
+-static struct snd_kcontrol_new snd_pmac_beep_mixer = {
++static const struct snd_kcontrol_new snd_pmac_beep_mixer = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Beep Playback Volume",
+ .info = snd_pmac_info_beep,
+diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
+index 58ee8089bbf9..0779a2912237 100644
+--- a/sound/ppc/tumbler.c
++++ b/sound/ppc/tumbler.c
+@@ -897,7 +897,7 @@ static struct snd_kcontrol_new snapper_mixers[] = {
+ },
+ };
+
+-static struct snd_kcontrol_new tumbler_hp_sw = {
++static const struct snd_kcontrol_new tumbler_hp_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Headphone Playback Switch",
+ .info = snd_pmac_boolean_mono_info,
+@@ -905,7 +905,7 @@ static struct snd_kcontrol_new tumbler_hp_sw = {
+ .put = tumbler_put_mute_switch,
+ .private_value = TUMBLER_MUTE_HP,
+ };
+-static struct snd_kcontrol_new tumbler_speaker_sw = {
++static const struct snd_kcontrol_new tumbler_speaker_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Speaker Playback Switch",
+ .info = snd_pmac_boolean_mono_info,
+@@ -913,7 +913,7 @@ static struct snd_kcontrol_new tumbler_speaker_sw = {
+ .put = tumbler_put_mute_switch,
+ .private_value = TUMBLER_MUTE_AMP,
+ };
+-static struct snd_kcontrol_new tumbler_lineout_sw = {
++static const struct snd_kcontrol_new tumbler_lineout_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line Out Playback Switch",
+ .info = snd_pmac_boolean_mono_info,
+@@ -921,7 +921,7 @@ static struct snd_kcontrol_new tumbler_lineout_sw = {
+ .put = tumbler_put_mute_switch,
+ .private_value = TUMBLER_MUTE_LINE,
+ };
+-static struct snd_kcontrol_new tumbler_drc_sw = {
++static const struct snd_kcontrol_new tumbler_drc_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "DRC Switch",
+ .info = snd_pmac_boolean_mono_info,
+diff --git a/sound/sh/aica.c b/sound/sh/aica.c
+index fbbc25279559..ab4802df62e1 100644
+--- a/sound/sh/aica.c
++++ b/sound/sh/aica.c
+@@ -535,7 +535,7 @@ static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
+-static struct snd_kcontrol_new snd_aica_pcmswitch_control = {
++static const struct snd_kcontrol_new snd_aica_pcmswitch_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Switch",
+ .index = 0,
+@@ -544,7 +544,7 @@ static struct snd_kcontrol_new snd_aica_pcmswitch_control = {
+ .put = aica_pcmswitch_put
+ };
+
+-static struct snd_kcontrol_new snd_aica_pcmvolume_control = {
++static const struct snd_kcontrol_new snd_aica_pcmvolume_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Volume",
+ .index = 0,
+diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
+index 76b2ab8c2b4a..4a22aadac294 100644
+--- a/sound/soc/sh/siu_dai.c
++++ b/sound/soc/sh/siu_dai.c
+@@ -441,7 +441,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl,
+ return 0;
+ }
+
+-static struct snd_kcontrol_new playback_controls = {
++static const struct snd_kcontrol_new playback_controls = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Volume",
+ .index = 0,
+@@ -451,7 +451,7 @@ static struct snd_kcontrol_new playback_controls = {
+ .private_value = VOLUME_PLAYBACK,
+ };
+
+-static struct snd_kcontrol_new capture_controls = {
++static const struct snd_kcontrol_new capture_controls = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Capture Volume",
+ .index = 0,
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index 4fa0053a40af..e3d1dec48ee4 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -362,7 +362,7 @@ static int snd_audigy2nx_led_resume(struct usb_mixer_elem_list *list)
+ }
+
+ /* name and private_value are set dynamically */
+-static struct snd_kcontrol_new snd_audigy2nx_control = {
++static const struct snd_kcontrol_new snd_audigy2nx_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = snd_audigy2nx_led_info,
+ .get = snd_audigy2nx_led_get,
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-fix-kernel-doc-build-warning.patch b/patches.drivers/ALSA-fix-kernel-doc-build-warning.patch
new file mode 100644
index 0000000000..485ee83697
--- /dev/null
+++ b/patches.drivers/ALSA-fix-kernel-doc-build-warning.patch
@@ -0,0 +1,38 @@
+From 3f1185d6c9d3fe91aa85ec8d3f4d71207452c458 Mon Sep 17 00:00:00 2001
+From: Randy Dunlap <rdunlap@infradead.org>
+Date: Sun, 29 Oct 2017 17:08:52 -0700
+Subject: [PATCH] ALSA: fix kernel-doc build warning
+Git-commit: 3f1185d6c9d3fe91aa85ec8d3f4d71207452c458
+Patch-mainline: v4.15-rc1
+References: bsc#1121278
+
+Fix kernel-doc build error. A symbol that ends with an underscore
+character ('_') has special meaning in reST (reStructuredText), so add
+a '*' to prevent this error and to indicate that there are several of
+these values to choose from.
+
+../sound/core/jack.c:312: ERROR: Unknown target name: "snd_jack_btn".
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/jack.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/jack.c b/sound/core/jack.c
+index f652e90efd7e..84c2a17c56ee 100644
+--- a/sound/core/jack.c
++++ b/sound/core/jack.c
+@@ -310,7 +310,7 @@ EXPORT_SYMBOL(snd_jack_set_parent);
+ * @type: Jack report type for this key
+ * @keytype: Input layer key type to be reported
+ *
+- * Map a SND_JACK_BTN_ button type to an input layer key, allowing
++ * Map a SND_JACK_BTN_* button type to an input layer key, allowing
+ * reporting of keys on accessories via the jack abstraction. If no
+ * mapping is provided but keys are enabled in the jack type then
+ * BTN_n numeric buttons will be reported.
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-hrtimer-make-hrtimer_hw-const-and-__initconst.patch b/patches.drivers/ALSA-hrtimer-make-hrtimer_hw-const-and-__initconst.patch
new file mode 100644
index 0000000000..0c8ff4ab2e
--- /dev/null
+++ b/patches.drivers/ALSA-hrtimer-make-hrtimer_hw-const-and-__initconst.patch
@@ -0,0 +1,35 @@
+From 38405834a6abdf2a644c1384b97d8f0cca769350 Mon Sep 17 00:00:00 2001
+From: Bhumika Goyal <bhumirks@gmail.com>
+Date: Tue, 19 Sep 2017 16:44:38 +0530
+Subject: [PATCH] ALSA: hrtimer: make hrtimer_hw const and __initconst
+Git-commit: 38405834a6abdf2a644c1384b97d8f0cca769350
+Patch-mainline: v4.15-rc1
+References: bsc#1121278
+
+Make this const as it is only used during a copy operation. Also, make
+it __initconst as it is only used during the init phase and after this
+it is not referenced anywhere.
+
+Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/hrtimer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
+index 1ac0c423903e..5603e49f7bf7 100644
+--- a/sound/core/hrtimer.c
++++ b/sound/core/hrtimer.c
+@@ -127,7 +127,7 @@ static int snd_hrtimer_stop(struct snd_timer *t)
+ return 0;
+ }
+
+-static struct snd_timer_hardware hrtimer_hw = {
++static const struct snd_timer_hardware hrtimer_hw __initconst = {
+ .flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_TASKLET,
+ .open = snd_hrtimer_open,
+ .close = snd_hrtimer_close,
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-hwdep-prevent-a-harmless-shift-wrapping-bug.patch b/patches.drivers/ALSA-hwdep-prevent-a-harmless-shift-wrapping-bug.patch
new file mode 100644
index 0000000000..0e49fceaf0
--- /dev/null
+++ b/patches.drivers/ALSA-hwdep-prevent-a-harmless-shift-wrapping-bug.patch
@@ -0,0 +1,35 @@
+From c4fd43793bdecb986bfc80e00c8792556c3f1c7f Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Thu, 14 Sep 2017 02:01:16 +0300
+Subject: [PATCH] ALSA: hwdep: prevent a harmless shift wrapping bug
+Git-commit: c4fd43793bdecb986bfc80e00c8792556c3f1c7f
+Patch-mainline: v4.15-rc1
+References: bsc#1121278
+
+The "info.index" variable represents a bit in hw->dsp_loaded which is
+an unsigned int. If it's higher than 31 we hit a shift wrapping bug.
+This seems harmless, but I wanted to silence the static checker warning.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/hwdep.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
+index a73baa1242be..8faae3d1455d 100644
+--- a/sound/core/hwdep.c
++++ b/sound/core/hwdep.c
+@@ -228,6 +228,8 @@ static int snd_hwdep_dsp_load(struct snd_hwdep *hw,
+ memset(&info, 0, sizeof(info));
+ if (copy_from_user(&info, _info, sizeof(info)))
+ return -EFAULT;
++ if (info.index >= 32)
++ return -EINVAL;
+ /* check whether the dsp was already loaded */
+ if (hw->dsp_loaded & (1 << info.index))
+ return -EBUSY;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-info-Use-kvzalloc-for-a-temporary-write-buffer.patch b/patches.drivers/ALSA-info-Use-kvzalloc-for-a-temporary-write-buffer.patch
new file mode 100644
index 0000000000..2ac0c08237
--- /dev/null
+++ b/patches.drivers/ALSA-info-Use-kvzalloc-for-a-temporary-write-buffer.patch
@@ -0,0 +1,52 @@
+From ffb73b08e79418fbf3f2ea44a7818a6715399d2c Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 22 May 2017 17:39:13 +0200
+Subject: [PATCH] ALSA: info: Use kvzalloc() for a temporary write buffer
+Git-commit: ffb73b08e79418fbf3f2ea44a7818a6715399d2c
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+We used to use kmalloc (more exactly, krealloc()) for creating and
+growing the temporary buffer for text proc write. It can grow up to
+16kB, and it's already a bit doubtful whether it's always safe to use
+kmalloc(). With the recent addition of kvmalloc(), we can have a
+better chance for succeed of memory allocation, so let's switch to
+that new API.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/info.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sound/core/info.c b/sound/core/info.c
+index 8ab72e0f5932..fc14ebe751d8 100644
+--- a/sound/core/info.c
++++ b/sound/core/info.c
+@@ -344,12 +344,12 @@ static ssize_t snd_info_text_entry_write(struct file *file,
+ }
+ }
+ if (next > buf->len) {
+- char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next),
+- GFP_KERNEL | __GFP_ZERO);
++ char *nbuf = kvzalloc(PAGE_ALIGN(next), GFP_KERNEL);
+ if (!nbuf) {
+ err = -ENOMEM;
+ goto error;
+ }
++ kvfree(buf->buffer);
+ buf->buffer = nbuf;
+ buf->len = PAGE_ALIGN(next);
+ }
+@@ -427,7 +427,7 @@ static int snd_info_text_entry_release(struct inode *inode, struct file *file)
+ single_release(inode, file);
+ kfree(data->rbuffer);
+ if (data->wbuffer) {
+- kfree(data->wbuffer->buffer);
++ kvfree(data->wbuffer->buffer);
+ kfree(data->wbuffer);
+ }
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-line6-make-snd_pcm_ops-const.patch b/patches.drivers/ALSA-line6-make-snd_pcm_ops-const.patch
new file mode 100644
index 0000000000..a0a2c7af78
--- /dev/null
+++ b/patches.drivers/ALSA-line6-make-snd_pcm_ops-const.patch
@@ -0,0 +1,80 @@
+From e195a331c4124a6527e5e1b6fbd93a6b4a984d7b Mon Sep 17 00:00:00 2001
+From: Bhumika Goyal <bhumirks@gmail.com>
+Date: Wed, 27 Sep 2017 11:49:27 +0530
+Subject: [PATCH] ALSA: line6: make snd_pcm_ops const
+Git-commit: e195a331c4124a6527e5e1b6fbd93a6b4a984d7b
+Patch-mainline: v4.15-rc1
+References: bsc#1121278
+
+Make these const as they are only passed to a const argument of the
+function snd_pcm_set_ops in the file referencing them. Also, add const
+to the declaration in the headers.
+
+Structures found using Coccinelle and changes done by hand.
+
+Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/usb/line6/capture.c | 2 +-
+ sound/usb/line6/capture.h | 2 +-
+ sound/usb/line6/playback.c | 2 +-
+ sound/usb/line6/playback.h | 2 +-
+ 4 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
+index 7c812565f90d..947d6168f24a 100644
+--- a/sound/usb/line6/capture.c
++++ b/sound/usb/line6/capture.c
+@@ -248,7 +248,7 @@ static int snd_line6_capture_close(struct snd_pcm_substream *substream)
+ }
+
+ /* capture operators */
+-struct snd_pcm_ops snd_line6_capture_ops = {
++const struct snd_pcm_ops snd_line6_capture_ops = {
+ .open = snd_line6_capture_open,
+ .close = snd_line6_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h
+index 890b21bff18c..b67ccc39fd25 100644
+--- a/sound/usb/line6/capture.h
++++ b/sound/usb/line6/capture.h
+@@ -17,7 +17,7 @@
+ #include "driver.h"
+ #include "pcm.h"
+
+-extern struct snd_pcm_ops snd_line6_capture_ops;
++extern const struct snd_pcm_ops snd_line6_capture_ops;
+
+ extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf,
+ int fsize);
+diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
+index 812d18191e01..819e9b2d1d6e 100644
+--- a/sound/usb/line6/playback.c
++++ b/sound/usb/line6/playback.c
+@@ -393,7 +393,7 @@ static int snd_line6_playback_close(struct snd_pcm_substream *substream)
+ }
+
+ /* playback operators */
+-struct snd_pcm_ops snd_line6_playback_ops = {
++const struct snd_pcm_ops snd_line6_playback_ops = {
+ .open = snd_line6_playback_open,
+ .close = snd_line6_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h
+index 51fce29e8726..d8d3b8a07a72 100644
+--- a/sound/usb/line6/playback.h
++++ b/sound/usb/line6/playback.h
+@@ -27,7 +27,7 @@
+ */
+ #define USE_CLEAR_BUFFER_WORKAROUND 1
+
+-extern struct snd_pcm_ops snd_line6_playback_ops;
++extern const struct snd_pcm_ops snd_line6_playback_ops;
+
+ extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm);
+ extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-line6-stop-using-get_seconds.patch b/patches.drivers/ALSA-line6-stop-using-get_seconds.patch
new file mode 100644
index 0000000000..64e7a1952c
--- /dev/null
+++ b/patches.drivers/ALSA-line6-stop-using-get_seconds.patch
@@ -0,0 +1,46 @@
+From a8eaad7b04eaab3df6b8db722d4418286815b46c Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Mon, 18 Jun 2018 17:41:01 +0200
+Subject: [PATCH] ALSA: line6: stop using get_seconds()
+Git-commit: a8eaad7b04eaab3df6b8db722d4418286815b46c
+Patch-mainline: v4.19-rc1
+References: bsc#1121278
+
+The get_seconds() function is deprecated because it truncates the
+timestamp to 32 bits, so all users should change to ktime_get_seconds()
+or ktime_get_real_seconds().
+
+The firmware interface for passing the timestamp is also limited to
+32 bits, so this patch only has the cosmetic effect of avoiding the
+old interface.
+
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/usb/line6/toneport.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
+index 750467fb95db..f47ba94e6f4a 100644
+--- a/sound/usb/line6/toneport.c
++++ b/sound/usb/line6/toneport.c
+@@ -367,12 +367,13 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport)
+ */
+ static void toneport_setup(struct usb_line6_toneport *toneport)
+ {
+- int ticks;
++ u32 ticks;
+ struct usb_line6 *line6 = &toneport->line6;
+ struct usb_device *usbdev = line6->usbdev;
+
+ /* sync time on device with host: */
+- ticks = (int)get_seconds();
++ /* note: 32-bit timestamps overflow in year 2106 */
++ ticks = (u32)ktime_get_real_seconds();
+ line6_write_data(line6, 0x80c6, &ticks, 4);
+
+ /* enable device: */
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-opl4-Use-IS_REACHABLE.patch b/patches.drivers/ALSA-opl4-Use-IS_REACHABLE.patch
new file mode 100644
index 0000000000..22a8faa188
--- /dev/null
+++ b/patches.drivers/ALSA-opl4-Use-IS_REACHABLE.patch
@@ -0,0 +1,58 @@
+From 2e2d4cb450e951b90629b3f988c48ed01c69c1ac Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 12 May 2017 11:52:06 +0200
+Subject: [PATCH] ALSA: opl4: Use IS_REACHABLE()
+Git-commit: 2e2d4cb450e951b90629b3f988c48ed01c69c1ac
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Rewrite the complex ifdef condition with IS_REACHABLE().
+The ifdef in opl4_local.h was without defined(MODLE) check, but this
+is likely the oversight. Use IS_REACHABLE() here as well.
+
+Acked-by: Clemens Ladisch <clemens@ladisch.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/drivers/opl4/opl4_lib.c | 4 ++--
+ sound/drivers/opl4/opl4_local.h | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
+index 89c7aa04b3bc..240656e54400 100644
+--- a/sound/drivers/opl4/opl4_lib.c
++++ b/sound/drivers/opl4/opl4_lib.c
+@@ -153,7 +153,7 @@ static int snd_opl4_detect(struct snd_opl4 *opl4)
+ return 0;
+ }
+
+-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
++#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
+ static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev)
+ {
+ struct snd_opl4 *opl4 = seq_dev->private_data;
+@@ -249,7 +249,7 @@ int snd_opl4_create(struct snd_card *card,
+ snd_opl4_create_mixer(opl4);
+ snd_opl4_create_proc(opl4);
+
+-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
++#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
+ opl4->seq_client = -1;
+ if (opl4->hardware < OPL3_HW_OPL4_ML)
+ snd_opl4_create_seq_dev(opl4, seq_device);
+diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h
+index 9a41bdebce6b..d5bac93f8245 100644
+--- a/sound/drivers/opl4/opl4_local.h
++++ b/sound/drivers/opl4/opl4_local.h
+@@ -184,7 +184,7 @@ struct snd_opl4 {
+ #endif
+ struct mutex access_mutex;
+
+-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
++#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
+ int used;
+
+ int seq_dev_num;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Add-__force-to-cast-in-snd_pcm_lib_read-wri.patch b/patches.drivers/ALSA-pcm-Add-__force-to-cast-in-snd_pcm_lib_read-wri.patch
new file mode 100644
index 0000000000..f6794e483d
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Add-__force-to-cast-in-snd_pcm_lib_read-wri.patch
@@ -0,0 +1,46 @@
+From 95a48b7d4459948b6bacf809809cf01a7dc06d1d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 25 Jul 2018 23:00:54 +0200
+Subject: [PATCH] ALSA: pcm: Add __force to cast in snd_pcm_lib_read/write()
+Git-commit: 95a48b7d4459948b6bacf809809cf01a7dc06d1d
+Patch-mainline: v4.19-rc1
+References: bsc#1121278
+
+The snd_pcm_lib_read() and snd_pcm_lib_write() inline functions have
+the explicit cast from a user pointer to a kernel pointer, but they
+lacks of __force prefix.
+
+This fixes sparse warnings like:
+ ./include/sound/pcm.h:1093:47: warning: cast removes address space of expression
+
+Fixes: 68541213720d ("ALSA: pcm: Direct in-kernel read/write support")
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 1206045ccf03..d6bd3caf6878 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -1090,14 +1090,14 @@ static inline snd_pcm_sframes_t
+ snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ const void __user *buf, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false);
++ return __snd_pcm_lib_xfer(substream, (void __force *)buf, true, frames, false);
+ }
+
+ static inline snd_pcm_sframes_t
+ snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ void __user *buf, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false);
++ return __snd_pcm_lib_xfer(substream, (void __force *)buf, true, frames, false);
+ }
+
+ static inline snd_pcm_sframes_t
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Add-an-ioctl-to-specify-the-supported-proto.patch b/patches.drivers/ALSA-pcm-Add-an-ioctl-to-specify-the-supported-proto.patch
new file mode 100644
index 0000000000..3e25c32df4
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Add-an-ioctl-to-specify-the-supported-proto.patch
@@ -0,0 +1,111 @@
+From 4b671f57747468d7c810caaf955f79ff1aece4d4 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 19 Jun 2017 23:11:54 +0200
+Subject: [PATCH] ALSA: pcm: Add an ioctl to specify the supported protocol version
+Git-commit: 4b671f57747468d7c810caaf955f79ff1aece4d4
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+We have an ioctl to inform the PCM protocol version the running kernel
+supports, but there is no way to know which protocol version the
+user-space can understand. This lack of information caused headaches
+in the past when we tried to extend the ABI. For example, because we
+couldn't guarantee the validity of the reserved bytes, we had to
+introduce a new ioctl SNDRV_PCM_IOCTL_STATUS_EXT for assigning a few
+new fields in the formerly reserved bits. If we could know that it's
+a new alsa-lib, we could assume the availability of the new fields,
+thus we could have reused the existing SNDRV_PCM_IOCTL_STATUS.
+
+In order to improve the ABI extensibility, this patch adds a new ioctl
+for user-space to inform its supporting protocol version to the
+kernel. By reporting the supported protocol from user-space, the
+kernel can judge which feature should be provided and which not.
+
+With the addition of the new ioctl, the PCM protocol version is bumped
+to 2.0.14, too. User-space checks the kernel protocol version via
+SNDRV_PCM_INFO_PVERSION, then it sets the supported version back via
+SNDRV_PCM_INFO_USER_PVERSION.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 1 +
+ include/uapi/sound/asound.h | 3 ++-
+ sound/core/pcm_compat.c | 1 +
+ sound/core/pcm_native.c | 7 +++++++
+ 4 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 5a22075c5fcf..24febf9e177c 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -218,6 +218,7 @@ struct snd_pcm_ops {
+ struct snd_pcm_file {
+ struct snd_pcm_substream *substream;
+ int no_compat_mmap;
++ unsigned int user_pversion; /* supported protocol version */
+ };
+
+ struct snd_pcm_hw_rule;
+diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
+index 7eee52eb7462..1949923a40bf 100644
+--- a/include/uapi/sound/asound.h
++++ b/include/uapi/sound/asound.h
+@@ -152,7 +152,7 @@ struct snd_hwdep_dsp_image {
+ * *
+ *****************************************************************************/
+
+-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 13)
++#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14)
+
+ typedef unsigned long snd_pcm_uframes_t;
+ typedef signed long snd_pcm_sframes_t;
+@@ -564,6 +564,7 @@ enum {
+ #define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
+ #define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
+ #define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
++#define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int)
+ #define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
+ #define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
+ #define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
+diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
+index 8a0f8d51e95d..10f537f4d735 100644
+--- a/sound/core/pcm_compat.c
++++ b/sound/core/pcm_compat.c
+@@ -676,6 +676,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
+ case SNDRV_PCM_IOCTL_INFO:
+ case SNDRV_PCM_IOCTL_TSTAMP:
+ case SNDRV_PCM_IOCTL_TTSTAMP:
++ case SNDRV_PCM_IOCTL_USER_PVERSION:
+ case SNDRV_PCM_IOCTL_HWSYNC:
+ case SNDRV_PCM_IOCTL_PREPARE:
+ case SNDRV_PCM_IOCTL_RESET:
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 9ade0c8b54a3..1c53d93e68f2 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -2770,6 +2770,8 @@ static int snd_pcm_common_ioctl(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+ {
++ struct snd_pcm_file *pcm_file = file->private_data;
++
+ switch (cmd) {
+ case SNDRV_PCM_IOCTL_PVERSION:
+ return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
+@@ -2779,6 +2781,11 @@ static int snd_pcm_common_ioctl(struct file *file,
+ return 0;
+ case SNDRV_PCM_IOCTL_TTSTAMP:
+ return snd_pcm_tstamp(substream, arg);
++ case SNDRV_PCM_IOCTL_USER_PVERSION:
++ if (get_user(pcm_file->user_pversion,
++ (unsigned int __user *)arg))
++ return -EFAULT;
++ return 0;
+ case SNDRV_PCM_IOCTL_HW_REFINE:
+ return snd_pcm_hw_refine_user(substream, arg);
+ case SNDRV_PCM_IOCTL_HW_PARAMS:
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Add-the-explicit-appl_ptr-sync-support.patch b/patches.drivers/ALSA-pcm-Add-the-explicit-appl_ptr-sync-support.patch
new file mode 100644
index 0000000000..abd0d911b8
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Add-the-explicit-appl_ptr-sync-support.patch
@@ -0,0 +1,121 @@
+From 42f945970af9df6216e3d771b4df371d02d8742c Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 19 Jun 2017 22:39:18 +0200
+Subject: [PATCH] ALSA: pcm: Add the explicit appl_ptr sync support
+Git-commit: 42f945970af9df6216e3d771b4df371d02d8742c
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Currently x86 platforms use the PCM status/control mmaps for
+transferring the PCM status and appl_ptr between kernel and
+user-spaces. The mmap is a most efficient way of communication, but
+it has a drawback per its nature, namely, it can't notify the change
+explicitly to kernel.
+
+The lack of appl_ptr update notification is a problem on a few
+existing drivers, but it's mostly a small issue and negligible.
+However, a new type of driver that uses DSP for a deep buffer
+management requires the exact position of appl_ptr for calculating the
+buffer prefetch size, and the asynchronous appl_ptr update between
+kernel and user-spaces becomes a significant problem for it.
+
+How can we enforce user-space to report the appl_ptr update? The way
+is relatively simple. Just by disabling the PCM control mmap, the
+user-space is supposed to fall back to the mode using SYNC_PTR ioctl,
+and the kernel gets control over that. This fallback mode is used in
+all non-x86 platforms as default, and also in the 32bit compatible
+model on all platforms including x86. It's been implemented already
+over a decade, so we can say it's fairly safe and stably working.
+
+With the help of the knowledge above, this patch introduces a new PCM
+info flag SNDRV_PCM_INFO_SYNC_APPLPTR for achieving the appl_ptr sync
+from user-space. When a driver sets this flag at open, the PCM status
+/ control mmap is disabled, which effectively switches to SYNC_PTR
+mode in user-space side.
+
+In this version, both PCM status and control mmaps are disabled
+although only the latter, control mmap, is the target. It's because
+the current alsa-lib implementation supposes that both status and
+control mmaps are always coupled, thus it handles a fatal error when
+only one of them fails.
+
+Of course, the disablement of the status/control mmaps may bring a
+slight performance overhead. Thus, as of now, this should be used
+only for the dedicated devices that deserves.
+
+Note that the disablement of mmap is a sort of workaround. In the
+later patch, we'll introduce the way to identify the protocol version
+alsa-lib supports, and keep mmap working while the sync_ptr is
+performed together.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/uapi/sound/asound.h | 1 +
+ sound/core/pcm_native.c | 23 +++++++++++++++++++++--
+ 2 files changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
+index fd41697cb4d3..7eee52eb7462 100644
+--- a/include/uapi/sound/asound.h
++++ b/include/uapi/sound/asound.h
+@@ -268,6 +268,7 @@ typedef int __bitwise snd_pcm_subformat_t;
+ #define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
+ #define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */
+ #define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */
++#define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */
+ #define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */
+ #define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */
+ #define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index d35c6614fdab..9ade0c8b54a3 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -3376,10 +3376,29 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
+ area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+ return 0;
+ }
++
++static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
++{
++ if (pcm_file->no_compat_mmap)
++ return false;
++ /* Disallow the status/control mmap when SYNC_APPLPTR flag is set;
++ * it enforces the user-space to fall back to snd_pcm_sync_ptr(),
++ * thus it effectively assures the manual update of appl_ptr.
++ * In theory, it should be enough to disallow only PCM control mmap,
++ * but since the current alsa-lib implementation requires both status
++ * and control mmaps always paired, we have to disable both of them.
++ */
++ if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)
++ return false;
++ return true;
++}
++
+ #else /* ! coherent mmap */
+ /*
+ * don't support mmap for status and control records.
+ */
++#define pcm_status_mmap_allowed(pcm_file) false
++
+ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
+ struct vm_area_struct *area)
+ {
+@@ -3563,11 +3582,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
+ offset = area->vm_pgoff << PAGE_SHIFT;
+ switch (offset) {
+ case SNDRV_PCM_MMAP_OFFSET_STATUS:
+- if (pcm_file->no_compat_mmap)
++ if (!pcm_status_mmap_allowed(pcm_file))
+ return -ENXIO;
+ return snd_pcm_mmap_status(substream, file, area);
+ case SNDRV_PCM_MMAP_OFFSET_CONTROL:
+- if (pcm_file->no_compat_mmap)
++ if (!pcm_status_mmap_allowed(pcm_file))
+ return -ENXIO;
+ return snd_pcm_mmap_control(substream, file, area);
+ default:
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Adjust-nine-function-calls-together-with-a-.patch b/patches.drivers/ALSA-pcm-Adjust-nine-function-calls-together-with-a-.patch
new file mode 100644
index 0000000000..0f82abff1d
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Adjust-nine-function-calls-together-with-a-.patch
@@ -0,0 +1,129 @@
+From c8da9be4a75f1f63024a16b976c5be47405c13dc Mon Sep 17 00:00:00 2001
+From: Markus Elfring <elfring@users.sourceforge.net>
+Date: Wed, 23 Aug 2017 09:20:29 +0200
+Subject: [PATCH] ALSA: pcm: Adjust nine function calls together with a variable assignment
+Git-commit: c8da9be4a75f1f63024a16b976c5be47405c13dc
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+The script "checkpatch.pl" pointed information out like the following.
+
+Error: do not use assignment in if condition
+
+Thus fix the affected source code places.
+
+Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm.c | 38 +++++++++++++++++++++++---------------
+ 1 file changed, 23 insertions(+), 15 deletions(-)
+
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index 048df9658f50..c790f79e45ae 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -523,7 +523,9 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
+
+ sprintf(name, "pcm%i%c", pcm->device,
+ pstr->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
+- if ((entry = snd_info_create_card_entry(pcm->card, name, pcm->card->proc_root)) == NULL)
++ entry = snd_info_create_card_entry(pcm->card, name,
++ pcm->card->proc_root);
++ if (!entry)
+ return -ENOMEM;
+ entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ if (snd_info_register(entry) < 0) {
+@@ -531,8 +533,8 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
+ return -ENOMEM;
+ }
+ pstr->proc_root = entry;
+-
+- if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) {
++ entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root);
++ if (entry) {
+ snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read);
+ if (snd_info_register(entry) < 0) {
+ snd_info_free_entry(entry);
+@@ -542,8 +544,9 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
+ pstr->proc_info_entry = entry;
+
+ #ifdef CONFIG_SND_PCM_XRUN_DEBUG
+- if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
+- pstr->proc_root)) != NULL) {
++ entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
++ pstr->proc_root);
++ if (entry) {
+ entry->c.text.read = snd_pcm_xrun_debug_read;
+ entry->c.text.write = snd_pcm_xrun_debug_write;
+ entry->mode |= S_IWUSR;
+@@ -580,7 +583,9 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
+ card = substream->pcm->card;
+
+ sprintf(name, "sub%i", substream->number);
+- if ((entry = snd_info_create_card_entry(card, name, substream->pstr->proc_root)) == NULL)
++ entry = snd_info_create_card_entry(card, name,
++ substream->pstr->proc_root);
++ if (!entry)
+ return -ENOMEM;
+ entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ if (snd_info_register(entry) < 0) {
+@@ -588,8 +593,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
+ return -ENOMEM;
+ }
+ substream->proc_root = entry;
+-
+- if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) {
++ entry = snd_info_create_card_entry(card, "info", substream->proc_root);
++ if (entry) {
+ snd_info_set_text_ops(entry, substream,
+ snd_pcm_substream_proc_info_read);
+ if (snd_info_register(entry) < 0) {
+@@ -598,8 +603,9 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
+ }
+ }
+ substream->proc_info_entry = entry;
+-
+- if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) {
++ entry = snd_info_create_card_entry(card, "hw_params",
++ substream->proc_root);
++ if (entry) {
+ snd_info_set_text_ops(entry, substream,
+ snd_pcm_substream_proc_hw_params_read);
+ if (snd_info_register(entry) < 0) {
+@@ -608,8 +614,9 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
+ }
+ }
+ substream->proc_hw_params_entry = entry;
+-
+- if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) {
++ entry = snd_info_create_card_entry(card, "sw_params",
++ substream->proc_root);
++ if (entry) {
+ snd_info_set_text_ops(entry, substream,
+ snd_pcm_substream_proc_sw_params_read);
+ if (snd_info_register(entry) < 0) {
+@@ -618,8 +625,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
+ }
+ }
+ substream->proc_sw_params_entry = entry;
+-
+- if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) {
++ entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL);
++ if (entry) {
+ snd_info_set_text_ops(entry, substream,
+ snd_pcm_substream_proc_status_read);
+ if (snd_info_register(entry) < 0) {
+@@ -1230,7 +1237,8 @@ static void snd_pcm_proc_init(void)
+ {
+ struct snd_info_entry *entry;
+
+- if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
++ entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL);
++ if (entry) {
+ snd_info_set_text_ops(entry, NULL, snd_pcm_proc_read);
+ if (snd_info_register(entry) < 0) {
+ snd_info_free_entry(entry);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Allow-drivers-to-set-R-W-wait-time.patch b/patches.drivers/ALSA-pcm-Allow-drivers-to-set-R-W-wait-time.patch
new file mode 100644
index 0000000000..3c71347637
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Allow-drivers-to-set-R-W-wait-time.patch
@@ -0,0 +1,67 @@
+From d64c5cf8e89d124355924c513a42b16f0d7d3a03 Mon Sep 17 00:00:00 2001
+From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+Date: Fri, 6 Jul 2018 13:50:36 +0100
+Subject: [PATCH] ALSA: pcm: Allow drivers to set R/W wait time.
+Git-commit: d64c5cf8e89d124355924c513a42b16f0d7d3a03
+Patch-mainline: v4.19-rc1
+References: bsc#1121278
+
+Currently ALSA core blocks userspace for about 10 seconds for PCM R/W IO.
+This needs to be configurable for modern hardware like DSPs where no
+pointer update in milliseconds can indicate terminal DSP errors.
+
+Add a substream variable to set the wait time in ms. This allows userspace
+and drivers to recover more quickly from terminal DSP errors.
+
+Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 1 +
+ sound/core/pcm_lib.c | 17 ++++++++++++-----
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index e054c583d3b3..fcdf358a25f0 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -462,6 +462,7 @@ struct snd_pcm_substream {
+ /* -- timer section -- */
+ struct snd_timer *timer; /* timer */
+ unsigned timer_running: 1; /* time is running */
++ long wait_time; /* time in ms for R/W to wait for avail */
+ /* -- next substream -- */
+ struct snd_pcm_substream *next;
+ /* -- linked substreams -- */
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index c1d2e8e1fc6b..5736860f325b 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1833,12 +1833,19 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
+ if (runtime->no_period_wakeup)
+ wait_time = MAX_SCHEDULE_TIMEOUT;
+ else {
+- wait_time = 10;
+- if (runtime->rate) {
+- long t = runtime->period_size * 2 / runtime->rate;
+- wait_time = max(t, wait_time);
++ /* use wait time from substream if available */
++ if (substream->wait_time) {
++ wait_time = substream->wait_time;
++ } else {
++ wait_time = 10;
++
++ if (runtime->rate) {
++ long t = runtime->period_size * 2 /
++ runtime->rate;
++ wait_time = max(t, wait_time);
++ }
++ wait_time = msecs_to_jiffies(wait_time * 1000);
+ }
+- wait_time = msecs_to_jiffies(wait_time * 1000);
+ }
+
+ for (;;) {
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Allow-dropping-stream-directly-after-resume.patch b/patches.drivers/ALSA-pcm-Allow-dropping-stream-directly-after-resume.patch
new file mode 100644
index 0000000000..cb0f23dcd5
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Allow-dropping-stream-directly-after-resume.patch
@@ -0,0 +1,39 @@
+From 4b95ff781e30c50298257d22a2c3743b2e5739be Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 24 May 2016 15:08:31 +0200
+Subject: [PATCH] ALSA: pcm: Allow dropping stream directly after resume
+Git-commit: 4b95ff781e30c50298257d22a2c3743b2e5739be
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+So far, the PCM core refuses DROP ioctl when the stream in the
+suspended state. This was basically to avoid the invalid state change
+*during* the suspend. But since we protect the power change globally
+in the common PCM ioctl caller side, it's guaranteed that
+snd_pcm_drop() is called at the right power state. So we can assume
+that the drop of stream is safe immediately after SUSPENDED state.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index bd1b74aa2068..69cf9b02ac70 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1883,8 +1883,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
+ runtime = substream->runtime;
+
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
+- runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED ||
+- runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
++ runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
+ return -EBADFD;
+
+ snd_pcm_stream_lock_irq(substream);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Apply-power-lock-globally-to-common-ioctls.patch b/patches.drivers/ALSA-pcm-Apply-power-lock-globally-to-common-ioctls.patch
new file mode 100644
index 0000000000..1be9959877
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Apply-power-lock-globally-to-common-ioctls.patch
@@ -0,0 +1,150 @@
+From 68b4acd322494444803a3f49884ae889c8ec6689 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 24 May 2016 15:07:39 +0200
+Subject: [PATCH] ALSA: pcm: Apply power lock globally to common ioctls
+Git-commit: 68b4acd322494444803a3f49884ae889c8ec6689
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+All PCM common ioctls should run only in the powered up state, but
+currently only a few ioctls do the proper snd_power_lock() and
+snd_power_wait() invocations. Instead of adding to each place, do it
+commonly in the caller side, so that all these ioctls are assured to
+be operated at the power up state.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 56 ++++++++++++++---------------------------
+ 1 file changed, 19 insertions(+), 37 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 798bca967c0e..bd1b74aa2068 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1540,14 +1540,7 @@ static const struct action_ops snd_pcm_action_resume = {
+
+ static int snd_pcm_resume(struct snd_pcm_substream *substream)
+ {
+- struct snd_card *card = substream->pcm->card;
+- int res;
+-
+- snd_power_lock(card);
+- if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
+- res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
+- snd_power_unlock(card);
+- return res;
++ return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
+ }
+
+ #else
+@@ -1566,17 +1559,9 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream)
+ */
+ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
+ {
+- struct snd_card *card = substream->pcm->card;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int result;
+
+- snd_power_lock(card);
+- if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+- result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+- if (result < 0)
+- goto _unlock;
+- }
+-
+ snd_pcm_stream_lock_irq(substream);
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_XRUN:
+@@ -1589,8 +1574,6 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
+ result = -EBADFD;
+ }
+ snd_pcm_stream_unlock_irq(substream);
+- _unlock:
+- snd_power_unlock(card);
+ return result;
+ }
+
+@@ -1694,8 +1677,6 @@ static const struct action_ops snd_pcm_action_prepare = {
+ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
+ struct file *file)
+ {
+- int res;
+- struct snd_card *card = substream->pcm->card;
+ int f_flags;
+
+ if (file)
+@@ -1703,12 +1684,8 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
+ else
+ f_flags = substream->f_flags;
+
+- snd_power_lock(card);
+- if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
+- res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
+- substream, f_flags);
+- snd_power_unlock(card);
+- return res;
++ return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
++ substream, f_flags);
+ }
+
+ /*
+@@ -1805,15 +1782,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+
+- snd_power_lock(card);
+- if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+- result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
+- if (result < 0) {
+- snd_power_unlock(card);
+- return result;
+- }
+- }
+-
+ if (file) {
+ if (file->f_flags & O_NONBLOCK)
+ nonblock = 1;
+@@ -1896,7 +1864,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
+ unlock:
+ snd_pcm_stream_unlock_irq(substream);
+ up_read(&snd_pcm_link_rwsem);
+- snd_power_unlock(card);
+
+ return result;
+ }
+@@ -2798,7 +2765,7 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
+ return 0;
+ }
+
+-static int snd_pcm_common_ioctl1(struct file *file,
++static int snd_pcm_common_ioctl(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+ {
+@@ -2873,6 +2840,21 @@ static int snd_pcm_common_ioctl1(struct file *file,
+ return -ENOTTY;
+ }
+
++static int snd_pcm_common_ioctl1(struct file *file,
++ struct snd_pcm_substream *substream,
++ unsigned int cmd, void __user *arg)
++{
++ struct snd_card *card = substream->pcm->card;
++ int res;
++
++ snd_power_lock(card);
++ res = snd_power_wait(card, SNDRV_CTL_POWER_D0);
++ if (res >= 0)
++ res = snd_pcm_common_ioctl(file, substream, cmd, arg);
++ snd_power_unlock(card);
++ return res;
++}
++
+ static int snd_pcm_playback_ioctl1(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Avoid-potential-races-between-OSS-ioctls-an b/patches.drivers/ALSA-pcm-Avoid-potential-races-between-OSS-ioctls-an
index 372155bfa2..199b69a8b5 100644
--- a/patches.drivers/ALSA-pcm-Avoid-potential-races-between-OSS-ioctls-an
+++ b/patches.drivers/ALSA-pcm-Avoid-potential-races-between-OSS-ioctls-an
@@ -40,7 +40,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
-@@ -835,8 +835,8 @@ static int choose_rate(struct snd_pcm_su
+@@ -823,8 +823,8 @@ static int choose_rate(struct snd_pcm_su
return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
}
@@ -51,21 +51,21 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_pcm_hw_params *params, *sparams;
-@@ -850,11 +850,8 @@ static int snd_pcm_oss_change_params(str
- struct snd_mask sformat_mask;
+@@ -838,11 +838,8 @@ static int snd_pcm_oss_change_params(str
+ const struct snd_mask *sformat_mask;
struct snd_mask mask;
- if (trylock) {
- if (!(mutex_trylock(&runtime->oss.params_lock)))
- return -EAGAIN;
- } else if (mutex_lock_interruptible(&runtime->oss.params_lock))
-- return -EINTR;
+- return -ERESTARTSYS;
+ if (!runtime->oss.params)
+ return 0;
sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL);
params = kmalloc(sizeof(*params), GFP_KERNEL);
sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
-@@ -1080,6 +1077,23 @@ failure:
+@@ -1068,6 +1065,23 @@ failure:
kfree(sw_params);
kfree(params);
kfree(sparams);
@@ -89,7 +89,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
mutex_unlock(&runtime->oss.params_lock);
return err;
}
-@@ -1108,11 +1122,14 @@ static int snd_pcm_oss_get_active_substr
+@@ -1096,11 +1110,14 @@ static int snd_pcm_oss_get_active_substr
return 0;
}
@@ -104,7 +104,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
if (err < 0) {
pcm_dbg(substream->pcm,
-@@ -1132,8 +1149,6 @@ static int snd_pcm_oss_make_ready(struct
+@@ -1120,8 +1137,6 @@ static int snd_pcm_oss_make_ready(struct
struct snd_pcm_runtime *runtime;
int err;
@@ -113,7 +113,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
runtime = substream->runtime;
if (runtime->oss.params) {
err = snd_pcm_oss_change_params(substream, false);
-@@ -1141,6 +1156,29 @@ static int snd_pcm_oss_make_ready(struct
+@@ -1129,6 +1144,29 @@ static int snd_pcm_oss_make_ready(struct
return err;
}
if (runtime->oss.prepare) {
@@ -143,7 +143,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
err = snd_pcm_oss_prepare(substream);
if (err < 0)
return err;
-@@ -1368,13 +1406,14 @@ static ssize_t snd_pcm_oss_write1(struct
+@@ -1332,13 +1370,14 @@ static ssize_t snd_pcm_oss_write1(struct
if (atomic_read(&substream->mmap_count))
return -ENXIO;
@@ -160,7 +160,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
tmp = bytes;
if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
-@@ -1475,13 +1514,14 @@ static ssize_t snd_pcm_oss_read1(struct
+@@ -1439,13 +1478,14 @@ static ssize_t snd_pcm_oss_read1(struct
if (atomic_read(&substream->mmap_count))
return -ENXIO;
@@ -177,7 +177,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
if (runtime->oss.buffer_used == 0) {
tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
-@@ -1537,10 +1577,12 @@ static int snd_pcm_oss_reset(struct snd_
+@@ -1501,10 +1541,12 @@ static int snd_pcm_oss_reset(struct snd_
continue;
runtime = substream->runtime;
snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
@@ -190,7 +190,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
return 0;
}
-@@ -1626,9 +1668,10 @@ static int snd_pcm_oss_sync(struct snd_p
+@@ -1590,9 +1632,10 @@ static int snd_pcm_oss_sync(struct snd_p
goto __direct;
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
return err;
@@ -202,7 +202,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (runtime->oss.buffer_used > 0) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm, "sync: buffer_used\n");
-@@ -1696,7 +1739,9 @@ static int snd_pcm_oss_sync(struct snd_p
+@@ -1643,7 +1686,9 @@ static int snd_pcm_oss_sync(struct snd_p
substream->f_flags = saved_f_flags;
if (err < 0)
return err;
@@ -212,7 +212,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
-@@ -1707,8 +1752,10 @@ static int snd_pcm_oss_sync(struct snd_p
+@@ -1654,8 +1699,10 @@ static int snd_pcm_oss_sync(struct snd_p
err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
if (err < 0)
return err;
@@ -223,7 +223,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
return 0;
}
-@@ -1727,10 +1774,13 @@ static int snd_pcm_oss_set_rate(struct s
+@@ -1674,10 +1721,13 @@ static int snd_pcm_oss_set_rate(struct s
rate = 1000;
else if (rate > 192000)
rate = 192000;
@@ -237,7 +237,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
return snd_pcm_oss_get_rate(pcm_oss_file);
}
-@@ -1758,10 +1808,13 @@ static int snd_pcm_oss_set_channels(stru
+@@ -1705,10 +1755,13 @@ static int snd_pcm_oss_set_channels(stru
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -251,7 +251,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
return snd_pcm_oss_get_channels(pcm_oss_file);
}
-@@ -1845,10 +1898,13 @@ static int snd_pcm_oss_set_format(struct
+@@ -1792,10 +1845,13 @@ static int snd_pcm_oss_set_format(struct
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -265,7 +265,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
}
return snd_pcm_oss_get_format(pcm_oss_file);
-@@ -1868,8 +1924,6 @@ static int snd_pcm_oss_set_subdivide1(st
+@@ -1815,8 +1871,6 @@ static int snd_pcm_oss_set_subdivide1(st
{
struct snd_pcm_runtime *runtime;
@@ -274,7 +274,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
runtime = substream->runtime;
if (subdivide == 0) {
subdivide = runtime->oss.subdivision;
-@@ -1893,9 +1947,16 @@ static int snd_pcm_oss_set_subdivide(str
+@@ -1840,9 +1894,16 @@ static int snd_pcm_oss_set_subdivide(str
for (idx = 1; idx >= 0; --idx) {
struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
@@ -292,7 +292,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
return err;
}
return err;
-@@ -1905,8 +1966,6 @@ static int snd_pcm_oss_set_fragment1(str
+@@ -1852,8 +1913,6 @@ static int snd_pcm_oss_set_fragment1(str
{
struct snd_pcm_runtime *runtime;
@@ -301,7 +301,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
runtime = substream->runtime;
if (runtime->oss.subdivision || runtime->oss.fragshift)
return -EINVAL;
-@@ -1926,9 +1985,16 @@ static int snd_pcm_oss_set_fragment(stru
+@@ -1873,9 +1932,16 @@ static int snd_pcm_oss_set_fragment(stru
for (idx = 1; idx >= 0; --idx) {
struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
@@ -319,7 +319,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
return err;
}
return err;
-@@ -2012,6 +2078,9 @@ static int snd_pcm_oss_set_trigger(struc
+@@ -1959,6 +2025,9 @@ static int snd_pcm_oss_set_trigger(struc
}
if (psubstream) {
runtime = psubstream->runtime;
@@ -329,7 +329,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (trigger & PCM_ENABLE_OUTPUT) {
if (runtime->oss.trigger)
goto _skip1;
-@@ -2029,13 +2098,19 @@ static int snd_pcm_oss_set_trigger(struc
+@@ -1976,13 +2045,19 @@ static int snd_pcm_oss_set_trigger(struc
cmd = SNDRV_PCM_IOCTL_DROP;
runtime->oss.prepare = 1;
}
@@ -353,7 +353,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (trigger & PCM_ENABLE_INPUT) {
if (runtime->oss.trigger)
goto _skip2;
-@@ -2050,11 +2125,14 @@ static int snd_pcm_oss_set_trigger(struc
+@@ -1997,11 +2072,14 @@ static int snd_pcm_oss_set_trigger(struc
cmd = SNDRV_PCM_IOCTL_DROP;
runtime->oss.prepare = 1;
}
diff --git a/patches.drivers/ALSA-pcm-Build-OSS-writev-readv-helpers-conditionall.patch b/patches.drivers/ALSA-pcm-Build-OSS-writev-readv-helpers-conditionall.patch
new file mode 100644
index 0000000000..19dd4adbb9
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Build-OSS-writev-readv-helpers-conditionall.patch
@@ -0,0 +1,111 @@
+From fed5794fccf40297f17e0032cc8211cdad0ba6df Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 21 May 2017 19:08:57 +0200
+Subject: [PATCH] ALSA: pcm: Build OSS writev/readv helpers conditionally
+Git-commit: fed5794fccf40297f17e0032cc8211cdad0ba6df
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+The snd_pcm_oss_writev3() and snd_pcm_oss_readv3() are used only in
+io.c with CONFIG_SND_PCM_OSS_PLUGINS=y. Add an ifdef to reduce the
+build of these functions.
+
+Along with it, since they are called always for in-kernel copy, reduce
+the argument and call snd_pcm_kernel_writev() and *_readv() directly
+instead.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/io.c | 4 ++--
+ sound/core/oss/pcm_oss.c | 12 ++++++------
+ sound/core/oss/pcm_plugin.h | 6 ++----
+ 3 files changed, 10 insertions(+), 12 deletions(-)
+
+diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
+index 6faa1d719206..d870b2d93135 100644
+--- a/sound/core/oss/io.c
++++ b/sound/core/oss/io.c
+@@ -26,9 +26,9 @@
+ #include "pcm_plugin.h"
+
+ #define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
+-#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1)
++#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count)
+ #define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
+-#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1)
++#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count)
+
+ /*
+ * Basic io plugin
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index 2d6a825cfe88..5e1009d959a8 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1232,7 +1232,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
+ return ret;
+ }
+
+-snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
++#ifdef CONFIG_SND_PCM_OSS_PLUGINS
++snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+@@ -1249,8 +1250,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
+ if (ret < 0)
+ break;
+ }
+- ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
+- in_kernel);
++ ret = snd_pcm_kernel_writev(substream, bufs, frames);
+ if (ret != -EPIPE && ret != -ESTRPIPE)
+ break;
+
+@@ -1262,7 +1262,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
+ return ret;
+ }
+
+-snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
++snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+@@ -1283,13 +1283,13 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void *
+ if (ret < 0)
+ break;
+ }
+- ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
+- in_kernel);
++ ret = snd_pcm_kernel_readv(substream, bufs, frames);
+ if (ret != -EPIPE && ret != -ESTRPIPE)
+ break;
+ }
+ return ret;
+ }
++#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
+
+ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel)
+ {
+diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
+index 73c068abaca5..c9cd29d86efd 100644
+--- a/sound/core/oss/pcm_plugin.h
++++ b/sound/core/oss/pcm_plugin.h
+@@ -162,11 +162,9 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream,
+ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream,
+ char *ptr, snd_pcm_uframes_t size, int in_kernel);
+ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream,
+- void **bufs, snd_pcm_uframes_t frames,
+- int in_kernel);
++ void **bufs, snd_pcm_uframes_t frames);
+ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
+- void **bufs, snd_pcm_uframes_t frames,
+- int in_kernel);
++ void **bufs, snd_pcm_uframes_t frames);
+
+ #else
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Build-pcm-notifier-code-conditionally.patch b/patches.drivers/ALSA-pcm-Build-pcm-notifier-code-conditionally.patch
new file mode 100644
index 0000000000..8339d3f369
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Build-pcm-notifier-code-conditionally.patch
@@ -0,0 +1,153 @@
+From 58f30d650c7f5275d4d57e62862970e1078af462 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 12 May 2017 11:35:17 +0200
+Subject: [PATCH] ALSA: pcm: Build pcm notifier code conditionally
+Git-commit: 58f30d650c7f5275d4d57e62862970e1078af462
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+The PCM notifier code is used only by OSS emulation layer, so we can
+build it conditionally for reducing the size.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 15 ++++++++-------
+ sound/core/pcm.c | 33 ++++++++++++++++++++-------------
+ 2 files changed, 28 insertions(+), 20 deletions(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 361749e60799..eb16912d6046 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -531,13 +531,6 @@ struct snd_pcm {
+ #endif
+ };
+
+-struct snd_pcm_notify {
+- int (*n_register) (struct snd_pcm * pcm);
+- int (*n_disconnect) (struct snd_pcm * pcm);
+- int (*n_unregister) (struct snd_pcm * pcm);
+- struct list_head list;
+-};
+-
+ /*
+ * Registering
+ */
+@@ -552,7 +545,15 @@ int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
+ struct snd_pcm **rpcm);
+ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count);
+
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
++struct snd_pcm_notify {
++ int (*n_register) (struct snd_pcm * pcm);
++ int (*n_disconnect) (struct snd_pcm * pcm);
++ int (*n_unregister) (struct snd_pcm * pcm);
++ struct list_head list;
++};
+ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
++#endif
+
+ /*
+ * Native I/O
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index 8e980aa678d0..24acbfb5c531 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -36,8 +36,10 @@ MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
+ MODULE_LICENSE("GPL");
+
+ static LIST_HEAD(snd_pcm_devices);
+-static LIST_HEAD(snd_pcm_notify_list);
+ static DEFINE_MUTEX(register_mutex);
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
++static LIST_HEAD(snd_pcm_notify_list);
++#endif
+
+ static int snd_pcm_free(struct snd_pcm *pcm);
+ static int snd_pcm_dev_free(struct snd_device *device);
+@@ -884,16 +886,23 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
+ put_device(&pstr->dev);
+ }
+
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
++#define pcm_call_notify(pcm, call) \
++ do { \
++ struct snd_pcm_notify *_notify; \
++ list_for_each_entry(_notify, &snd_pcm_notify_list, list) \
++ _notify->call(pcm); \
++ } while (0)
++#else
++#define pcm_call_notify(pcm, call) /* NOP */
++#endif
++
+ static int snd_pcm_free(struct snd_pcm *pcm)
+ {
+- struct snd_pcm_notify *notify;
+-
+ if (!pcm)
+ return 0;
+- if (!pcm->internal) {
+- list_for_each_entry(notify, &snd_pcm_notify_list, list)
+- notify->n_unregister(pcm);
+- }
++ if (!pcm->internal)
++ pcm_call_notify(pcm, n_unregister);
+ if (pcm->private_free)
+ pcm->private_free(pcm);
+ snd_pcm_lib_preallocate_free_for_all(pcm);
+@@ -1069,7 +1078,6 @@ static int snd_pcm_dev_register(struct snd_device *device)
+ {
+ int cidx, err;
+ struct snd_pcm_substream *substream;
+- struct snd_pcm_notify *notify;
+ struct snd_pcm *pcm;
+
+ if (snd_BUG_ON(!device || !device->device_data))
+@@ -1107,8 +1115,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
+ snd_pcm_timer_init(substream);
+ }
+
+- list_for_each_entry(notify, &snd_pcm_notify_list, list)
+- notify->n_register(pcm);
++ pcm_call_notify(pcm, n_register);
+
+ unlock:
+ mutex_unlock(&register_mutex);
+@@ -1118,7 +1125,6 @@ static int snd_pcm_dev_register(struct snd_device *device)
+ static int snd_pcm_dev_disconnect(struct snd_device *device)
+ {
+ struct snd_pcm *pcm = device->device_data;
+- struct snd_pcm_notify *notify;
+ struct snd_pcm_substream *substream;
+ int cidx;
+
+@@ -1138,8 +1144,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
+ }
+ }
+ if (!pcm->internal) {
+- list_for_each_entry(notify, &snd_pcm_notify_list, list)
+- notify->n_disconnect(pcm);
++ pcm_call_notify(pcm, n_disconnect);
+ }
+ for (cidx = 0; cidx < 2; cidx++) {
+ if (!pcm->internal)
+@@ -1151,6 +1156,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
+ return 0;
+ }
+
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+ /**
+ * snd_pcm_notify - Add/remove the notify list
+ * @notify: PCM notify list
+@@ -1183,6 +1189,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
+ return 0;
+ }
+ EXPORT_SYMBOL(snd_pcm_notify);
++#endif /* CONFIG_SND_PCM_OSS */
+
+ #ifdef CONFIG_SND_PROC_FS
+ /*
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Call-directly-the-common-read-write-helpers.patch b/patches.drivers/ALSA-pcm-Call-directly-the-common-read-write-helpers.patch
new file mode 100644
index 0000000000..820eff442c
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Call-directly-the-common-read-write-helpers.patch
@@ -0,0 +1,312 @@
+From c48f12ee0acbd431d6c3ed249f79a6d68b757058 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 21 May 2017 09:35:21 +0200
+Subject: [PATCH] ALSA: pcm: Call directly the common read/write helpers
+Git-commit: c48f12ee0acbd431d6c3ed249f79a6d68b757058
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Make snd_pcm_lib_read() and *_write() static inline functions that
+call the common helper functions directly. This reduces a slight
+amount of codes, and at the same time, it's a preparation for the
+further cleanups / fixes.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 43 +++++++++---
+ sound/core/pcm_lib.c | 156 +++++++++++++++----------------------------
+ 2 files changed, 89 insertions(+), 110 deletions(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 0da5117636ec..0fac948bb053 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -1072,15 +1072,40 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream);
+ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg);
+ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
+-snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream,
+- const void __user *buf,
+- snd_pcm_uframes_t frames);
+-snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream,
+- void __user *buf, snd_pcm_uframes_t frames);
+-snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
+- void __user **bufs, snd_pcm_uframes_t frames);
+-snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+- void __user **bufs, snd_pcm_uframes_t frames);
++snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
++ void *buf, bool interleaved,
++ snd_pcm_uframes_t frames);
++snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
++ void *buf, bool interleaved,
++ snd_pcm_uframes_t frames);
++
++static inline snd_pcm_sframes_t
++snd_pcm_lib_write(struct snd_pcm_substream *substream,
++ const void __user *buf, snd_pcm_uframes_t frames)
++{
++ return __snd_pcm_lib_write(substream, (void *)buf, true, frames);
++}
++
++static inline snd_pcm_sframes_t
++snd_pcm_lib_read(struct snd_pcm_substream *substream,
++ void __user *buf, snd_pcm_uframes_t frames)
++{
++ return __snd_pcm_lib_read(substream, (void *)buf, true, frames);
++}
++
++static inline snd_pcm_sframes_t
++snd_pcm_lib_writev(struct snd_pcm_substream *substream,
++ void __user **bufs, snd_pcm_uframes_t frames)
++{
++ return __snd_pcm_lib_write(substream, (void *)bufs, false, frames);
++}
++
++static inline snd_pcm_sframes_t
++snd_pcm_lib_readv(struct snd_pcm_substream *substream,
++ void __user **bufs, snd_pcm_uframes_t frames)
++{
++ return __snd_pcm_lib_read(substream, (void *)bufs, false, frames);
++}
+
+ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
+ unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 51eeea9088de..ae030c5eb7c6 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1994,12 +1994,12 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
+ }
+
+ typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
+- unsigned long data, unsigned int off,
++ void *data, unsigned int off,
+ snd_pcm_uframes_t size);
+
+ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
+ unsigned int hwoff,
+- unsigned long data, unsigned int off,
++ void *data, unsigned int off,
+ snd_pcm_uframes_t frames)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+@@ -2021,7 +2021,7 @@ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
+
+ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
+ unsigned int hwoff,
+- unsigned long data, unsigned int off,
++ void *data, unsigned int off,
+ snd_pcm_uframes_t frames)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+@@ -2098,21 +2098,39 @@ static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
+ }
+ }
+
+-static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
+- unsigned long data,
+- snd_pcm_uframes_t size,
+- int nonblock,
+- transfer_f transfer)
++snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
++ void *data, bool interleaved,
++ snd_pcm_uframes_t size)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t xfer = 0;
+ snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
+- int err = 0;
++ transfer_f transfer;
++ bool nonblock;
++ int err;
++
++ err = pcm_sanity_check(substream);
++ if (err < 0)
++ return err;
++ runtime = substream->runtime;
++
++ if (interleaved) {
++ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
++ runtime->channels > 1)
++ return -EINVAL;
++ transfer = snd_pcm_lib_write_transfer;
++ } else {
++ if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
++ return -EINVAL;
++ transfer = snd_pcm_lib_writev_transfer;
++ }
+
+ if (size == 0)
+ return 0;
+
++ nonblock = !!(substream->f_flags & O_NONBLOCK);
++
+ snd_pcm_stream_lock_irq(substream);
+ err = pcm_accessible_state(runtime);
+ if (err < 0)
+@@ -2180,53 +2198,11 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
+ snd_pcm_stream_unlock_irq(substream);
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
+ }
+-
+-snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size)
+-{
+- struct snd_pcm_runtime *runtime;
+- int nonblock;
+- int err;
+-
+- err = pcm_sanity_check(substream);
+- if (err < 0)
+- return err;
+- runtime = substream->runtime;
+- nonblock = !!(substream->f_flags & O_NONBLOCK);
+-
+- if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
+- runtime->channels > 1)
+- return -EINVAL;
+- return snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock,
+- snd_pcm_lib_write_transfer);
+-}
+-
+-EXPORT_SYMBOL(snd_pcm_lib_write);
+-
+-snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
+- void __user **bufs,
+- snd_pcm_uframes_t frames)
+-{
+- struct snd_pcm_runtime *runtime;
+- int nonblock;
+- int err;
+-
+- err = pcm_sanity_check(substream);
+- if (err < 0)
+- return err;
+- runtime = substream->runtime;
+- nonblock = !!(substream->f_flags & O_NONBLOCK);
+-
+- if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+- return -EINVAL;
+- return snd_pcm_lib_write1(substream, (unsigned long)bufs, frames,
+- nonblock, snd_pcm_lib_writev_transfer);
+-}
+-
+-EXPORT_SYMBOL(snd_pcm_lib_writev);
++EXPORT_SYMBOL(__snd_pcm_lib_write);
+
+ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
+ unsigned int hwoff,
+- unsigned long data, unsigned int off,
++ void *data, unsigned int off,
+ snd_pcm_uframes_t frames)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+@@ -2248,7 +2224,7 @@ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
+
+ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
+ unsigned int hwoff,
+- unsigned long data, unsigned int off,
++ void *data, unsigned int off,
+ snd_pcm_uframes_t frames)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+@@ -2286,21 +2262,39 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
+-static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
+- unsigned long data,
+- snd_pcm_uframes_t size,
+- int nonblock,
+- transfer_f transfer)
++snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
++ void *data, bool interleaved,
++ snd_pcm_uframes_t size)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t xfer = 0;
+ snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
+- int err = 0;
++ transfer_f transfer;
++ bool nonblock;
++ int err;
++
++ err = pcm_sanity_check(substream);
++ if (err < 0)
++ return err;
++ runtime = substream->runtime;
++
++ if (interleaved) {
++ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
++ runtime->channels > 1)
++ return -EINVAL;
++ transfer = snd_pcm_lib_read_transfer;
++ } else {
++ if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
++ return -EINVAL;
++ transfer = snd_pcm_lib_readv_transfer;
++ }
+
+ if (size == 0)
+ return 0;
+
++ nonblock = !!(substream->f_flags & O_NONBLOCK);
++
+ snd_pcm_stream_lock_irq(substream);
+ err = pcm_accessible_state(runtime);
+ if (err < 0)
+@@ -2375,47 +2369,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
+ snd_pcm_stream_unlock_irq(substream);
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
+ }
+-
+-snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size)
+-{
+- struct snd_pcm_runtime *runtime;
+- int nonblock;
+- int err;
+-
+- err = pcm_sanity_check(substream);
+- if (err < 0)
+- return err;
+- runtime = substream->runtime;
+- nonblock = !!(substream->f_flags & O_NONBLOCK);
+- if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
+- return -EINVAL;
+- return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
+-}
+-
+-EXPORT_SYMBOL(snd_pcm_lib_read);
+-
+-snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+- void __user **bufs,
+- snd_pcm_uframes_t frames)
+-{
+- struct snd_pcm_runtime *runtime;
+- int nonblock;
+- int err;
+-
+- err = pcm_sanity_check(substream);
+- if (err < 0)
+- return err;
+- runtime = substream->runtime;
+- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+- return -EBADFD;
+-
+- nonblock = !!(substream->f_flags & O_NONBLOCK);
+- if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+- return -EINVAL;
+- return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
+-}
+-
+-EXPORT_SYMBOL(snd_pcm_lib_readv);
++EXPORT_SYMBOL(__snd_pcm_lib_read);
+
+ /*
+ * standard channel mapping helpers
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Check-PCM-state-by-a-common-helper-function.patch b/patches.drivers/ALSA-pcm-Check-PCM-state-by-a-common-helper-function.patch
new file mode 100644
index 0000000000..8cd045601d
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Check-PCM-state-by-a-common-helper-function.patch
@@ -0,0 +1,142 @@
+From 6ba63929ae76e5aaafa14021517fab41cfcd5c83 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 24 May 2017 17:51:30 +0200
+Subject: [PATCH] ALSA: pcm: Check PCM state by a common helper function
+Git-commit: 6ba63929ae76e5aaafa14021517fab41cfcd5c83
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 81 ++++++++++++++++----------------------------
+ 1 file changed, 29 insertions(+), 52 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 9c5fe62e2c51..5fcd798672b4 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2019,6 +2019,22 @@ typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwof
+ unsigned long data, unsigned int off,
+ snd_pcm_uframes_t size);
+
++static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
++{
++ switch (runtime->status->state) {
++ case SNDRV_PCM_STATE_PREPARED:
++ case SNDRV_PCM_STATE_RUNNING:
++ case SNDRV_PCM_STATE_PAUSED:
++ return 0;
++ case SNDRV_PCM_STATE_XRUN:
++ return -EPIPE;
++ case SNDRV_PCM_STATE_SUSPENDED:
++ return -ESTRPIPE;
++ default:
++ return -EBADFD;
++ }
++}
++
+ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
+ unsigned long data,
+ snd_pcm_uframes_t size,
+@@ -2035,21 +2051,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
+ return 0;
+
+ snd_pcm_stream_lock_irq(substream);
+- switch (runtime->status->state) {
+- case SNDRV_PCM_STATE_PREPARED:
+- case SNDRV_PCM_STATE_RUNNING:
+- case SNDRV_PCM_STATE_PAUSED:
+- break;
+- case SNDRV_PCM_STATE_XRUN:
+- err = -EPIPE;
+- goto _end_unlock;
+- case SNDRV_PCM_STATE_SUSPENDED:
+- err = -ESTRPIPE;
+- goto _end_unlock;
+- default:
+- err = -EBADFD;
++ err = pcm_accessible_state(runtime);
++ if (err < 0)
+ goto _end_unlock;
+- }
+
+ runtime->twake = runtime->control->avail_min ? : 1;
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+@@ -2085,16 +2089,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
+ snd_pcm_stream_lock_irq(substream);
+ if (err < 0)
+ goto _end_unlock;
+- switch (runtime->status->state) {
+- case SNDRV_PCM_STATE_XRUN:
+- err = -EPIPE;
+- goto _end_unlock;
+- case SNDRV_PCM_STATE_SUSPENDED:
+- err = -ESTRPIPE;
++ err = pcm_accessible_state(runtime);
++ if (err < 0)
+ goto _end_unlock;
+- default:
+- break;
+- }
+ appl_ptr += frames;
+ if (appl_ptr >= runtime->boundary)
+ appl_ptr -= runtime->boundary;
+@@ -2265,27 +2262,14 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
+ return 0;
+
+ snd_pcm_stream_lock_irq(substream);
+- switch (runtime->status->state) {
+- case SNDRV_PCM_STATE_PREPARED:
+- if (size >= runtime->start_threshold) {
+- err = snd_pcm_start(substream);
+- if (err < 0)
+- goto _end_unlock;
+- }
+- break;
+- case SNDRV_PCM_STATE_DRAINING:
+- case SNDRV_PCM_STATE_RUNNING:
+- case SNDRV_PCM_STATE_PAUSED:
+- break;
+- case SNDRV_PCM_STATE_XRUN:
+- err = -EPIPE;
+- goto _end_unlock;
+- case SNDRV_PCM_STATE_SUSPENDED:
+- err = -ESTRPIPE;
+- goto _end_unlock;
+- default:
+- err = -EBADFD;
++ err = pcm_accessible_state(runtime);
++ if (err < 0)
+ goto _end_unlock;
++ if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
++ size >= runtime->start_threshold) {
++ err = snd_pcm_start(substream);
++ if (err < 0)
++ goto _end_unlock;
+ }
+
+ runtime->twake = runtime->control->avail_min ? : 1;
+@@ -2329,16 +2313,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
+ snd_pcm_stream_lock_irq(substream);
+ if (err < 0)
+ goto _end_unlock;
+- switch (runtime->status->state) {
+- case SNDRV_PCM_STATE_XRUN:
+- err = -EPIPE;
+- goto _end_unlock;
+- case SNDRV_PCM_STATE_SUSPENDED:
+- err = -ESTRPIPE;
++ err = pcm_accessible_state(runtime);
++ if (err < 0)
+ goto _end_unlock;
+- default:
+- break;
+- }
+ appl_ptr += frames;
+ if (appl_ptr >= runtime->boundary)
+ appl_ptr -= runtime->boundary;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Clean-up-SNDRV_PCM_IOCTL_PAUSE-code.patch b/patches.drivers/ALSA-pcm-Clean-up-SNDRV_PCM_IOCTL_PAUSE-code.patch
new file mode 100644
index 0000000000..4727d18223
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Clean-up-SNDRV_PCM_IOCTL_PAUSE-code.patch
@@ -0,0 +1,42 @@
+From 34bcc44abb302d1586bf1eb7548be75d0f56babc Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 24 May 2016 14:58:04 +0200
+Subject: [PATCH] ALSA: pcm: Clean up SNDRV_PCM_IOCTL_PAUSE code
+Git-commit: 34bcc44abb302d1586bf1eb7548be75d0f56babc
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Use snd_pcm_action_lock_irq() helper instead of open coding.
+No functional change.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 07995e645327..798bca967c0e 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -2865,13 +2865,9 @@ static int snd_pcm_common_ioctl1(struct file *file,
+ case SNDRV_PCM_IOCTL_DROP:
+ return snd_pcm_drop(substream);
+ case SNDRV_PCM_IOCTL_PAUSE:
+- {
+- int res;
+- snd_pcm_stream_lock_irq(substream);
+- res = snd_pcm_pause(substream, (int)(unsigned long)arg);
+- snd_pcm_stream_unlock_irq(substream);
+- return res;
+- }
++ return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
++ substream,
++ (int)(unsigned long)arg);
+ }
+ pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
+ return -ENOTTY;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Clean-up-with-snd_pcm_avail-and-snd_pcm_hw_.patch b/patches.drivers/ALSA-pcm-Clean-up-with-snd_pcm_avail-and-snd_pcm_hw_.patch
new file mode 100644
index 0000000000..2a6dfc073c
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Clean-up-with-snd_pcm_avail-and-snd_pcm_hw_.patch
@@ -0,0 +1,258 @@
+From 763e5067aac91ce569a8b1212e6c31968bc7d325 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 11 Apr 2018 17:56:52 +0200
+Subject: [PATCH] ALSA: pcm: Clean up with snd_pcm_avail() and snd_pcm_hw_avail() helpers
+Git-commit: 763e5067aac91ce569a8b1212e6c31968bc7d325
+Patch-mainline: v4.18-rc1
+References: bsc#1121278
+
+Introduce two new direction-neutral helpers to calculate the avail and
+hw_avail values, and clean up the code with them.
+
+The two separated forward and rewind functions are gathered to the
+unified functions.
+
+No functional change but only code reductions.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_compat.c | 10 ++-----
+ sound/core/pcm_lib.c | 15 ++--------
+ sound/core/pcm_local.h | 18 ++++++++++++
+ sound/core/pcm_native.c | 65 +++++++----------------------------------
+ 4 files changed, 33 insertions(+), 75 deletions(-)
+
+diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
+index b719d0bd833e..0be248543f1e 100644
+--- a/sound/core/pcm_compat.c
++++ b/sound/core/pcm_compat.c
+@@ -44,10 +44,7 @@ static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
+
+ if (get_user(frames, src))
+ return -EFAULT;
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- err = snd_pcm_playback_rewind(substream, frames);
+- else
+- err = snd_pcm_capture_rewind(substream, frames);
++ err = snd_pcm_rewind(substream, frames);
+ if (put_user(err, src))
+ return -EFAULT;
+ return err < 0 ? err : 0;
+@@ -61,10 +58,7 @@ static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream,
+
+ if (get_user(frames, src))
+ return -EFAULT;
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- err = snd_pcm_playback_forward(substream, frames);
+- else
+- err = snd_pcm_capture_forward(substream, frames);
++ err = snd_pcm_forward(substream, frames);
+ if (put_user(err, src))
+ return -EFAULT;
+ return err < 0 ? err : 0;
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index f4a19509cccf..44b5ae833082 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -191,10 +191,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
+ {
+ snd_pcm_uframes_t avail;
+
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- avail = snd_pcm_playback_avail(runtime);
+- else
+- avail = snd_pcm_capture_avail(runtime);
++ avail = snd_pcm_avail(substream);
+ if (avail > runtime->avail_max)
+ runtime->avail_max = avail;
+ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+@@ -1856,10 +1853,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
+ * This check must happen after been added to the waitqueue
+ * and having current state be INTERRUPTIBLE.
+ */
+- if (is_playback)
+- avail = snd_pcm_playback_avail(runtime);
+- else
+- avail = snd_pcm_capture_avail(runtime);
++ avail = snd_pcm_avail(substream);
+ if (avail >= runtime->twake)
+ break;
+ snd_pcm_stream_unlock_irq(substream);
+@@ -2175,10 +2169,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ runtime->twake = runtime->control->avail_min ? : 1;
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+ snd_pcm_update_hw_ptr(substream);
+- if (is_playback)
+- avail = snd_pcm_playback_avail(runtime);
+- else
+- avail = snd_pcm_capture_avail(runtime);
++ avail = snd_pcm_avail(substream);
+ while (size > 0) {
+ snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
+ snd_pcm_uframes_t cont;
+diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
+index 16f254732b2a..7a499d02df6c 100644
+--- a/sound/core/pcm_local.h
++++ b/sound/core/pcm_local.h
+@@ -36,6 +36,24 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
+ void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t new_hw_ptr);
+
++static inline snd_pcm_uframes_t
++snd_pcm_avail(struct snd_pcm_substream *substream)
++{
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ return snd_pcm_playback_avail(substream->runtime);
++ else
++ return snd_pcm_capture_avail(substream->runtime);
++}
++
++static inline snd_pcm_uframes_t
++snd_pcm_hw_avail(struct snd_pcm_substream *substream)
++{
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ return snd_pcm_playback_hw_avail(substream->runtime);
++ else
++ return snd_pcm_capture_hw_avail(substream->runtime);
++}
++
+ #ifdef CONFIG_SND_PCM_TIMER
+ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
+ void snd_pcm_timer_init(struct snd_pcm_substream *substream);
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 35ffccea94c3..f69d89c907b9 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -908,8 +908,8 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
+ _tstamp_end:
+ status->appl_ptr = runtime->control->appl_ptr;
+ status->hw_ptr = runtime->status->hw_ptr;
++ status->avail = snd_pcm_avail(substream);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+- status->avail = snd_pcm_playback_avail(runtime);
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
+ runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+ status->delay = runtime->buffer_size - status->avail;
+@@ -917,7 +917,6 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
+ } else
+ status->delay = 0;
+ } else {
+- status->avail = snd_pcm_capture_avail(runtime);
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+ status->delay = status->avail + runtime->delay;
+ else
+@@ -2610,28 +2609,9 @@ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
+ return ret < 0 ? 0 : frames;
+ }
+
+-static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
+- snd_pcm_uframes_t frames)
++static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t frames)
+ {
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- snd_pcm_sframes_t ret;
+-
+- if (frames == 0)
+- return 0;
+-
+- snd_pcm_stream_lock_irq(substream);
+- ret = do_pcm_hwsync(substream);
+- if (!ret)
+- ret = rewind_appl_ptr(substream, frames,
+- snd_pcm_playback_hw_avail(runtime));
+- snd_pcm_stream_unlock_irq(substream);
+- return ret;
+-}
+-
+-static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,
+- snd_pcm_uframes_t frames)
+-{
+- struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_sframes_t ret;
+
+ if (frames == 0)
+@@ -2641,33 +2621,14 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
+ ret = do_pcm_hwsync(substream);
+ if (!ret)
+ ret = rewind_appl_ptr(substream, frames,
+- snd_pcm_capture_hw_avail(runtime));
+- snd_pcm_stream_unlock_irq(substream);
+- return ret;
+-}
+-
+-static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,
+- snd_pcm_uframes_t frames)
+-{
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- snd_pcm_sframes_t ret;
+-
+- if (frames == 0)
+- return 0;
+-
+- snd_pcm_stream_lock_irq(substream);
+- ret = do_pcm_hwsync(substream);
+- if (!ret)
+- ret = forward_appl_ptr(substream, frames,
+- snd_pcm_playback_avail(runtime));
++ snd_pcm_hw_avail(substream));
+ snd_pcm_stream_unlock_irq(substream);
+ return ret;
+ }
+
+-static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream,
+- snd_pcm_uframes_t frames)
++static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t frames)
+ {
+- struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_sframes_t ret;
+
+ if (frames == 0)
+@@ -2677,7 +2638,7 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
+ ret = do_pcm_hwsync(substream);
+ if (!ret)
+ ret = forward_appl_ptr(substream, frames,
+- snd_pcm_capture_avail(runtime));
++ snd_pcm_avail(substream));
+ snd_pcm_stream_unlock_irq(substream);
+ return ret;
+ }
+@@ -2830,10 +2791,7 @@ static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream,
+ return -EFAULT;
+ if (put_user(0, _frames))
+ return -EFAULT;
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- result = snd_pcm_playback_rewind(substream, frames);
+- else
+- result = snd_pcm_capture_rewind(substream, frames);
++ result = snd_pcm_rewind(substream, frames);
+ __put_user(result, _frames);
+ return result < 0 ? result : 0;
+ }
+@@ -2848,10 +2806,7 @@ static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream,
+ return -EFAULT;
+ if (put_user(0, _frames))
+ return -EFAULT;
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- result = snd_pcm_playback_forward(substream, frames);
+- else
+- result = snd_pcm_capture_forward(substream, frames);
++ result = snd_pcm_forward(substream, frames);
+ __put_user(result, _frames);
+ return result < 0 ? result : 0;
+ }
+@@ -2992,7 +2947,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ /* provided only for OSS; capture-only and no value returned */
+ if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
+ return -EINVAL;
+- result = snd_pcm_capture_forward(substream, *frames);
++ result = snd_pcm_forward(substream, *frames);
+ return result < 0 ? result : 0;
+ }
+ case SNDRV_PCM_IOCTL_HW_PARAMS:
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Correct-broken-procfs-set-up.patch b/patches.drivers/ALSA-pcm-Correct-broken-procfs-set-up.patch
new file mode 100644
index 0000000000..22e9cbcefb
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Correct-broken-procfs-set-up.patch
@@ -0,0 +1,40 @@
+From e6b4c525d94e6fb28d5c4b9eb4016caa12f68841 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 24 Aug 2017 22:11:07 +0200
+Subject: [PATCH] ALSA: pcm: Correct broken procfs set up
+Git-commit: e6b4c525d94e6fb28d5c4b9eb4016caa12f68841
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+The commit c8da9be4a75f ("ALSA: pcm: Adjust nine function calls
+together with a variable assignment") contained a badly incorrect
+conversion, a "status" PCM procfs creation was replaced with the next
+one. Luckily, this could be spotted easily by the kernel runtime
+warning.
+
+Fixes: c8da9be4a75f ("ALSA: pcm: Adjust nine function calls together...")
+Reported-by: Fabio Estevam <fabio.estevam@nxp.com>
+Tested-by: Fabio Estevam <fabio.estevam@nxp.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index c790f79e45ae..7eadb7fd8074 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -625,7 +625,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
+ }
+ }
+ substream->proc_sw_params_entry = entry;
+- entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL);
++ entry = snd_info_create_card_entry(card, "status",
++ substream->proc_root);
+ if (entry) {
+ snd_info_set_text_ops(entry, substream,
+ snd_pcm_substream_proc_status_read);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Direct-in-kernel-read-write-support.patch b/patches.drivers/ALSA-pcm-Direct-in-kernel-read-write-support.patch
new file mode 100644
index 0000000000..4d307eab90
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Direct-in-kernel-read-write-support.patch
@@ -0,0 +1,165 @@
+From 68541213720df9bb7904cc1fecab563d424849ae Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 24 May 2017 18:23:20 +0200
+Subject: [PATCH] ALSA: pcm: Direct in-kernel read/write support
+Git-commit: 68541213720df9bb7904cc1fecab563d424849ae
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Now all materials are ready, let's allow the direct in-kernel
+read/write, i.e. a kernel-space buffer is passed for read or write,
+instead of the normal user-space buffer. This feature is used by OSS
+layer and UAC1 driver, for example.
+
+The __snd_pcm_lib_xfer() takes in_kernel argument that indicates the
+in-kernel buffer copy. When this flag is set, another transfer code
+is used. It's either via copy_kernel PCM ops or the normal memcpy(),
+depending on the driver setup.
+
+As external API, snd_pcm_kernel_read(), *_write() and other variants
+are provided.
+
+That's all. This support is really simple because of the code
+refactoring until now.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 38 +++++++++++++++++++++++++++++++++-----
+ sound/core/pcm_lib.c | 26 +++++++++++++++++++++++++-
+ 2 files changed, 58 insertions(+), 6 deletions(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index db649083c76d..c24f85f12b71 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -1074,34 +1074,62 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
+ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
+ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ void *buf, bool interleaved,
+- snd_pcm_uframes_t frames);
++ snd_pcm_uframes_t frames, bool in_kernel);
+
+ static inline snd_pcm_sframes_t
+ snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ const void __user *buf, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
++ return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false);
+ }
+
+ static inline snd_pcm_sframes_t
+ snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ void __user *buf, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
++ return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false);
+ }
+
+ static inline snd_pcm_sframes_t
+ snd_pcm_lib_writev(struct snd_pcm_substream *substream,
+ void __user **bufs, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
++ return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, false);
+ }
+
+ static inline snd_pcm_sframes_t
+ snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+ void __user **bufs, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
++ return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, false);
++}
++
++static inline snd_pcm_sframes_t
++snd_pcm_kernel_write(struct snd_pcm_substream *substream,
++ const void *buf, snd_pcm_uframes_t frames)
++{
++ return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, true);
++}
++
++static inline snd_pcm_sframes_t
++snd_pcm_kernel_read(struct snd_pcm_substream *substream,
++ void *buf, snd_pcm_uframes_t frames)
++{
++ return __snd_pcm_lib_xfer(substream, buf, true, frames, true);
++}
++
++static inline snd_pcm_sframes_t
++snd_pcm_kernel_writev(struct snd_pcm_substream *substream,
++ void **bufs, snd_pcm_uframes_t frames)
++{
++ return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
++}
++
++static inline snd_pcm_sframes_t
++snd_pcm_kernel_readv(struct snd_pcm_substream *substream,
++ void **bufs, snd_pcm_uframes_t frames)
++{
++ return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
+ }
+
+ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index f31949b20c0d..95b8ef15029f 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1994,6 +1994,15 @@ static int default_write_copy(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
++/* default copy_kernel ops for write */
++static int default_write_copy_kernel(struct snd_pcm_substream *substream,
++ int channel, unsigned long hwoff,
++ void *buf, unsigned long bytes)
++{
++ memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes);
++ return 0;
++}
++
+ /* fill silence instead of copy data; called as a transfer helper
+ * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
+ * a NULL buffer is passed
+@@ -2027,6 +2036,15 @@ static int default_read_copy(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
++/* default copy_kernel ops for read */
++static int default_read_copy_kernel(struct snd_pcm_substream *substream,
++ int channel, unsigned long hwoff,
++ void *buf, unsigned long bytes)
++{
++ memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), bytes);
++ return 0;
++}
++
+ /* call transfer function with the converted pointers and sizes;
+ * for interleaved mode, it's one shot for all samples
+ */
+@@ -2126,7 +2144,7 @@ static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
+ /* the common loop for read/write data */
+ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ void *data, bool interleaved,
+- snd_pcm_uframes_t size)
++ snd_pcm_uframes_t size, bool in_kernel)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t xfer = 0;
+@@ -2159,6 +2177,12 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ transfer = fill_silence;
+ else
+ return -EINVAL;
++ } else if (in_kernel) {
++ if (substream->ops->copy_kernel)
++ transfer = substream->ops->copy_kernel;
++ else
++ transfer = is_playback ?
++ default_write_copy_kernel : default_read_copy_kernel;
+ } else {
+ if (substream->ops->copy_user)
+ transfer = (pcm_transfer_f)substream->ops->copy_user;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Disable-only-control-mmap-for-explicit-appl.patch b/patches.drivers/ALSA-pcm-Disable-only-control-mmap-for-explicit-appl.patch
new file mode 100644
index 0000000000..8917a5b385
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Disable-only-control-mmap-for-explicit-appl.patch
@@ -0,0 +1,78 @@
+From b602aa8eb1a0f52f0f9a09728b3b1c9133136656 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 27 Jun 2017 11:54:37 +0200
+Subject: [PATCH] ALSA: pcm: Disable only control mmap for explicit appl_ptr sync
+Git-commit: b602aa8eb1a0f52f0f9a09728b3b1c9133136656
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Now that user-space (typically alsa-lib) can specify which protocol
+version it supports, we can optimize the kernel code depending on the
+reported protocol version.
+
+In this patch, we change the previous hack for enforcing the appl_ptr
+sync by disabling status/control mmap. Instead of forcibly disabling
+both mmaps, we disable only the control mmap when user-space declares
+the supported protocol version new enough. For older user-space,
+still both PCM status and control mmaps are disabled when requested by
+the driver due to the compatibility reason.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 22 +++++++++++++++++-----
+ 1 file changed, 17 insertions(+), 5 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 1c53d93e68f2..0d1834310531 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -3388,12 +3388,23 @@ static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
+ {
+ if (pcm_file->no_compat_mmap)
+ return false;
+- /* Disallow the status/control mmap when SYNC_APPLPTR flag is set;
++ /* See pcm_control_mmap_allowed() below.
++ * Since older alsa-lib requires both status and control mmaps to be
++ * coupled, we have to disable the status mmap for old alsa-lib, too.
++ */
++ if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) &&
++ (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR))
++ return false;
++ return true;
++}
++
++static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file)
++{
++ if (pcm_file->no_compat_mmap)
++ return false;
++ /* Disallow the control mmap when SYNC_APPLPTR flag is set;
+ * it enforces the user-space to fall back to snd_pcm_sync_ptr(),
+ * thus it effectively assures the manual update of appl_ptr.
+- * In theory, it should be enough to disallow only PCM control mmap,
+- * but since the current alsa-lib implementation requires both status
+- * and control mmaps always paired, we have to disable both of them.
+ */
+ if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)
+ return false;
+@@ -3405,6 +3416,7 @@ static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
+ * don't support mmap for status and control records.
+ */
+ #define pcm_status_mmap_allowed(pcm_file) false
++#define pcm_control_mmap_allowed(pcm_file) false
+
+ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
+ struct vm_area_struct *area)
+@@ -3593,7 +3605,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
+ return -ENXIO;
+ return snd_pcm_mmap_status(substream, file, area);
+ case SNDRV_PCM_MMAP_OFFSET_CONTROL:
+- if (!pcm_status_mmap_allowed(pcm_file))
++ if (!pcm_control_mmap_allowed(pcm_file))
+ return -ENXIO;
+ return snd_pcm_mmap_control(substream, file, area);
+ default:
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Don-t-call-register-and-disconnect-callback.patch b/patches.drivers/ALSA-pcm-Don-t-call-register-and-disconnect-callback.patch
new file mode 100644
index 0000000000..e6300cd2c4
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Don-t-call-register-and-disconnect-callback.patch
@@ -0,0 +1,80 @@
+From 8b645e4a40dd490b9426670fffe9bb9e2878c3fd Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 17 Oct 2017 11:40:55 +0200
+Subject: [PATCH] ALSA: pcm: Don't call register and disconnect callbacks for internal PCM
+Git-commit: 8b645e4a40dd490b9426670fffe9bb9e2878c3fd
+Patch-mainline: v4.15-rc1
+References: bsc#1121278
+
+The internal PCM (aka DPCM backend PCM) doesn't need any registration
+procedure, thus currently we bail out immediately at dev_register
+callback. Similarly, its counterpart, dev_disconnect callback, is
+superfluous for the internal PCM. For simplifying and avoiding the
+conflicting disconnect call for internal PCM objects, this patch drops
+dev_register and dev_disconnect callbacks for the internal ops.
+
+The only uncertain thing by this action is whether skipping the PCM
+state change to SNDRV_PCM_STATE_DISCONNECT for the internal PCM is
+mandatory. Looking through the current implementations, this doesn't
+look so, hence dropping the whole dev_disconnect would make more
+sense.
+
+Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index 7eadb7fd8074..1b073ed0b1f9 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -775,6 +775,9 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
+ .dev_register = snd_pcm_dev_register,
+ .dev_disconnect = snd_pcm_dev_disconnect,
+ };
++ static struct snd_device_ops internal_ops = {
++ .dev_free = snd_pcm_dev_free,
++ };
+
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
+@@ -801,7 +804,8 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
+ if (err < 0)
+ goto free_pcm;
+
+- err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops);
++ err = snd_device_new(card, SNDRV_DEV_PCM, pcm,
++ internal ? &internal_ops : &ops);
+ if (err < 0)
+ goto free_pcm;
+
+@@ -1099,8 +1103,6 @@ static int snd_pcm_dev_register(struct snd_device *device)
+ if (snd_BUG_ON(!device || !device->device_data))
+ return -ENXIO;
+ pcm = device->device_data;
+- if (pcm->internal)
+- return 0;
+
+ mutex_lock(&register_mutex);
+ err = snd_pcm_add(pcm);
+@@ -1159,12 +1161,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
+ snd_pcm_stream_unlock_irq(substream);
+ }
+ }
+- if (!pcm->internal) {
+- pcm_call_notify(pcm, n_disconnect);
+- }
++
++ pcm_call_notify(pcm, n_disconnect);
+ for (cidx = 0; cidx < 2; cidx++) {
+- if (!pcm->internal)
+- snd_unregister_device(&pcm->streams[cidx].dev);
++ snd_unregister_device(&pcm->streams[cidx].dev);
+ free_chmap(&pcm->streams[cidx]);
+ }
+ mutex_unlock(&pcm->open_mutex);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Drop-the-old-copy-and-silence-ops.patch b/patches.drivers/ALSA-pcm-Drop-the-old-copy-and-silence-ops.patch
new file mode 100644
index 0000000000..01e402fdae
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Drop-the-old-copy-and-silence-ops.patch
@@ -0,0 +1,143 @@
+From 2ae48354a1a7afbec0c61280e6410a90894a21e7 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 10 May 2017 22:21:52 +0200
+Subject: [PATCH] ALSA: pcm: Drop the old copy and silence ops
+Git-commit: 2ae48354a1a7afbec0c61280e6410a90894a21e7
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Now that all users of old copy and silence ops have been converted to
+the new PCM ops, the old stuff can be retired and go away.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 5 -----
+ sound/core/pcm_lib.c | 38 +-------------------------------------
+ sound/soc/soc-pcm.c | 2 --
+ 3 files changed, 1 insertion(+), 44 deletions(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 86b126be49a2..0da5117636ec 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -78,11 +78,6 @@ struct snd_pcm_ops {
+ struct timespec *system_ts, struct timespec *audio_ts,
+ struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
+ struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
+- int (*copy)(struct snd_pcm_substream *substream, int channel,
+- snd_pcm_uframes_t pos,
+- void __user *buf, snd_pcm_uframes_t count);
+- int (*silence)(struct snd_pcm_substream *substream, int channel,
+- snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
+ int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
+ unsigned long pos, unsigned long bytes);
+ int (*copy_user)(struct snd_pcm_substream *substream, int channel,
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 1fca1ffd235e..9c5fe62e2c51 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -118,9 +118,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
+ frames_to_bytes(runtime, ofs),
+ frames_to_bytes(runtime, transfer));
+ snd_BUG_ON(err < 0);
+- } else if (substream->ops->silence) {
+- err = substream->ops->silence(substream, -1, ofs, transfer);
+- snd_BUG_ON(err < 0);
+ } else {
+ hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
+ snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
+@@ -135,11 +132,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
+ samples_to_bytes(runtime, transfer));
+ snd_BUG_ON(err < 0);
+ }
+- } else if (substream->ops->silence) {
+- for (c = 0; c < channels; ++c) {
+- err = substream->ops->silence(substream, c, ofs, transfer);
+- snd_BUG_ON(err < 0);
+- }
+ } else {
+ size_t dma_csize = runtime->dma_bytes / channels;
+ for (c = 0; c < channels; ++c) {
+@@ -2015,9 +2007,6 @@ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
+ err = substream->ops->copy_user(substream, 0, hwoff, buf, frames);
+ if (err < 0)
+ return err;
+- } else if (substream->ops->copy) {
+- if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
+- return err;
+ } else {
+ char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
+ if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
+@@ -2139,8 +2128,7 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
+ runtime = substream->runtime;
+- if (snd_BUG_ON(!substream->ops->copy_user && !substream->ops->copy
+- && !runtime->dma_area))
++ if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
+ return -EINVAL;
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+@@ -2200,19 +2188,6 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
+ if (err < 0)
+ return err;
+ }
+- } else if (substream->ops->copy) {
+- if (snd_BUG_ON(!substream->ops->silence))
+- return -EINVAL;
+- for (c = 0; c < channels; ++c, ++bufs) {
+- if (*bufs == NULL) {
+- if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0)
+- return err;
+- } else {
+- buf = *bufs + samples_to_bytes(runtime, off);
+- if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
+- return err;
+- }
+- }
+ } else {
+ /* default transfer behaviour */
+ size_t dma_csize = runtime->dma_bytes / channels;
+@@ -2266,9 +2241,6 @@ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
+ err = substream->ops->copy_user(substream, 0, hwoff, buf, frames);
+ if (err < 0)
+ return err;
+- } else if (substream->ops->copy) {
+- if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
+- return err;
+ } else {
+ char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
+ if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
+@@ -2430,14 +2402,6 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
+ if (err < 0)
+ return err;
+ }
+- } else if (substream->ops->copy) {
+- for (c = 0; c < channels; ++c, ++bufs) {
+- if (*bufs == NULL)
+- continue;
+- buf = *bufs + samples_to_bytes(runtime, off);
+- if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
+- return err;
+- }
+ } else {
+ snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
+ for (c = 0; c < channels; ++c, ++bufs) {
+diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
+index 8867ed9e5f56..dcc5ece08668 100644
+--- a/sound/soc/soc-pcm.c
++++ b/sound/soc/soc-pcm.c
+@@ -2746,8 +2746,6 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
+ rtd->ops.copy_user = platform->driver->ops->copy_user;
+ rtd->ops.copy_kernel = platform->driver->ops->copy_kernel;
+ rtd->ops.fill_silence = platform->driver->ops->fill_silence;
+- rtd->ops.copy = platform->driver->ops->copy;
+- rtd->ops.silence = platform->driver->ops->silence;
+ rtd->ops.page = platform->driver->ops->page;
+ rtd->ops.mmap = platform->driver->ops->mmap;
+ }
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Fix-UAF-in-snd_pcm_oss_get_formats.patch b/patches.drivers/ALSA-pcm-Fix-UAF-in-snd_pcm_oss_get_formats.patch
new file mode 100644
index 0000000000..aaa9b2fdcc
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Fix-UAF-in-snd_pcm_oss_get_formats.patch
@@ -0,0 +1,54 @@
+From 01c0b4265cc16bc1f43f475c5944c55c10d5768f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 10 Mar 2018 23:04:23 +0100
+Subject: [PATCH] ALSA: pcm: Fix UAF in snd_pcm_oss_get_formats()
+Git-commit: 01c0b4265cc16bc1f43f475c5944c55c10d5768f
+Patch-mainline: v4.16-rc6
+References: bsc#1121278
+
+snd_pcm_oss_get_formats() has an obvious use-after-free around
+snd_mask_test() calls, as spotted by syzbot. The passed format_mask
+argument is a pointer to the hw_params object that is freed before the
+loop. What a surprise that it has been present since the original
+code of decades ago...
+
+Reported-by: syzbot+4090700a4f13fccaf648@syzkaller.appspotmail.com
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_oss.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index b044c0a5a674..02298c9c6020 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1762,10 +1762,9 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
+ return -ENOMEM;
+ _snd_pcm_hw_params_any(params);
+ err = snd_pcm_hw_refine(substream, params);
+- format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
+- kfree(params);
+ if (err < 0)
+- return err;
++ goto error;
++ format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ for (fmt = 0; fmt < 32; ++fmt) {
+ if (snd_mask_test(format_mask, fmt)) {
+ int f = snd_pcm_oss_format_to(fmt);
+@@ -1773,7 +1772,10 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
+ formats |= f;
+ }
+ }
+- return formats;
++
++ error:
++ kfree(params);
++ return err < 0 ? err : formats;
+ }
+
+ static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Fix-mutex-unbalance-in-OSS-emulation-ioctls b/patches.drivers/ALSA-pcm-Fix-mutex-unbalance-in-OSS-emulation-ioctls
index 16fec6a1cc..8ba88609ef 100644
--- a/patches.drivers/ALSA-pcm-Fix-mutex-unbalance-in-OSS-emulation-ioctls
+++ b/patches.drivers/ALSA-pcm-Fix-mutex-unbalance-in-OSS-emulation-ioctls
@@ -25,7 +25,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
-@@ -835,6 +835,23 @@ static int choose_rate(struct snd_pcm_su
+@@ -823,6 +823,23 @@ static int choose_rate(struct snd_pcm_su
return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
}
@@ -49,7 +49,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
/* call with params_lock held */
static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
{
-@@ -1774,6 +1791,8 @@ static int snd_pcm_oss_set_rate(struct s
+@@ -1721,6 +1738,8 @@ static int snd_pcm_oss_set_rate(struct s
for (idx = 1; idx >= 0; --idx) {
struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
struct snd_pcm_runtime *runtime;
@@ -58,7 +58,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (substream == NULL)
continue;
runtime = substream->runtime;
-@@ -1781,15 +1800,14 @@ static int snd_pcm_oss_set_rate(struct s
+@@ -1728,15 +1747,14 @@ static int snd_pcm_oss_set_rate(struct s
rate = 1000;
else if (rate > 192000)
rate = 192000;
@@ -78,7 +78,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
return snd_pcm_oss_get_rate(pcm_oss_file);
}
-@@ -1814,18 +1832,19 @@ static int snd_pcm_oss_set_channels(stru
+@@ -1761,18 +1779,19 @@ static int snd_pcm_oss_set_channels(stru
for (idx = 1; idx >= 0; --idx) {
struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
struct snd_pcm_runtime *runtime;
@@ -103,7 +103,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
return snd_pcm_oss_get_channels(pcm_oss_file);
}
-@@ -1896,6 +1915,7 @@ static int snd_pcm_oss_get_formats(struc
+@@ -1843,6 +1862,7 @@ static int snd_pcm_oss_get_formats(struc
static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
{
int formats, idx;
@@ -111,7 +111,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (format != AFMT_QUERY) {
formats = snd_pcm_oss_get_formats(pcm_oss_file);
-@@ -1909,15 +1929,14 @@ static int snd_pcm_oss_set_format(struct
+@@ -1856,15 +1876,14 @@ static int snd_pcm_oss_set_format(struct
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -131,7 +131,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
}
return snd_pcm_oss_get_format(pcm_oss_file);
-@@ -1965,12 +1984,11 @@ static int snd_pcm_oss_set_subdivide(str
+@@ -1912,12 +1931,11 @@ static int snd_pcm_oss_set_subdivide(str
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -148,7 +148,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (err < 0)
return err;
}
-@@ -2005,12 +2023,11 @@ static int snd_pcm_oss_set_fragment(stru
+@@ -1952,12 +1970,11 @@ static int snd_pcm_oss_set_fragment(stru
if (substream == NULL)
continue;
runtime = substream->runtime;
diff --git a/patches.drivers/ALSA-pcm-Fix-possible-inconsistent-appl_ptr-update-v b/patches.drivers/ALSA-pcm-Fix-possible-inconsistent-appl_ptr-update-v
index 55da2a0708..fdd03ccb01 100644
--- a/patches.drivers/ALSA-pcm-Fix-possible-inconsistent-appl_ptr-update-v
+++ b/patches.drivers/ALSA-pcm-Fix-possible-inconsistent-appl_ptr-update-v
@@ -35,7 +35,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
-@@ -58,15 +58,16 @@ void snd_pcm_playback_silence(struct snd
+@@ -62,15 +62,16 @@ void snd_pcm_playback_silence(struct snd
if (runtime->silence_size < runtime->boundary) {
snd_pcm_sframes_t noise_dist, n;
@@ -55,7 +55,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
if (runtime->silence_filled >= runtime->buffer_size)
return;
-@@ -2292,7 +2293,9 @@ static snd_pcm_sframes_t snd_pcm_lib_rea
+@@ -2224,7 +2225,9 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str
continue; /* draining */
}
frames = size > avail ? avail : size;
@@ -66,12 +66,12 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (frames > cont)
frames = cont;
if (snd_BUG_ON(!frames)) {
-@@ -2300,8 +2303,6 @@ static snd_pcm_sframes_t snd_pcm_lib_rea
+@@ -2232,8 +2235,6 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str
snd_pcm_stream_unlock_irq(substream);
return -EINVAL;
}
- appl_ptr = runtime->control->appl_ptr;
- appl_ofs = appl_ptr % runtime->buffer_size;
snd_pcm_stream_unlock_irq(substream);
- err = transfer(substream, appl_ofs, data, offset, frames);
- snd_pcm_stream_lock_irq(substream);
+ err = writer(substream, appl_ofs, data, offset, frames,
+ transfer);
diff --git a/patches.drivers/ALSA-pcm-Fix-power-lock-unbalance-via-OSS-emulation.patch b/patches.drivers/ALSA-pcm-Fix-power-lock-unbalance-via-OSS-emulation.patch
new file mode 100644
index 0000000000..21699f6b33
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Fix-power-lock-unbalance-via-OSS-emulation.patch
@@ -0,0 +1,53 @@
+From bcab3a6e64a9647e022b46182c9687a8c3aa9d11 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 30 Aug 2017 14:50:07 +0200
+Subject: [PATCH] ALSA: pcm: Fix power lock unbalance via OSS emulation
+Git-commit: bcab3a6e64a9647e022b46182c9687a8c3aa9d11
+Patch-mainline: v4.13
+References: bsc#1121278
+
+PCM OSS emulation issues the drain ioctl without power lock. It used
+to work in the earlier kernels as the power lock was taken inside
+snd_pcm_drain() itself. But since 68b4acd32249 ("ALSA: pcm: Apply
+power lock globally to common ioctls"), the power lock is taken
+outside the function. Due to that change, the call via OSS emulation
+leads to the unbalanced power lock, thus it deadlocks.
+
+As a quick fix, just take the power lock before snd_pcm_drain() call
+for OSS emulation path. A better cleanup will follow later.
+
+Fixes: 68b4acd32249 ("ALSA: pcm: Apply power lock globally to common ioctls")
+Reported-and-tested-by: Markus Trippelsdorf <markus@trippelsdorf.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 22995cb3bd44..cf0433f80067 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -3064,6 +3064,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ {
+ snd_pcm_uframes_t *frames = arg;
+ snd_pcm_sframes_t result;
++ int err;
+
+ switch (cmd) {
+ case SNDRV_PCM_IOCTL_FORWARD:
+@@ -3083,7 +3084,10 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ case SNDRV_PCM_IOCTL_START:
+ return snd_pcm_start_lock_irq(substream);
+ case SNDRV_PCM_IOCTL_DRAIN:
+- return snd_pcm_drain(substream, NULL);
++ snd_power_lock(substream->pcm->card);
++ err = snd_pcm_drain(substream, NULL);
++ snd_power_unlock(substream->pcm->card);
++ return err;
+ case SNDRV_PCM_IOCTL_DROP:
+ return snd_pcm_drop(substream);
+ case SNDRV_PCM_IOCTL_DELAY:
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Fix-sparse-warning-wrt-PCM-format-type.patch b/patches.drivers/ALSA-pcm-Fix-sparse-warning-wrt-PCM-format-type.patch
new file mode 100644
index 0000000000..627a7854b1
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Fix-sparse-warning-wrt-PCM-format-type.patch
@@ -0,0 +1,36 @@
+From f8b6c0cfbdd7359db9bb4da38dd54217296f9264 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 25 Jul 2018 23:19:38 +0200
+Subject: [PATCH] ALSA: pcm: Fix sparse warning wrt PCM format type
+Git-commit: f8b6c0cfbdd7359db9bb4da38dd54217296f9264
+Patch-mainline: v4.19-rc1
+References: bsc#1121278
+
+The PCM format type is with __bitwise, hence it needs the explicit
+cast with __force. It's ugly, but there is a reason for that cost...
+
+This fixes the sparse warning:
+ sound/core/oss/pcm_oss.c:1854:55: warning: incorrect type in argument 1 (different base types)
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_oss.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index 905a53c1cde5..f8d4a419f3af 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -1851,7 +1851,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
+ format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ for (fmt = 0; fmt < 32; ++fmt) {
+ if (snd_mask_test(format_mask, fmt)) {
+- int f = snd_pcm_oss_format_to(fmt);
++ int f = snd_pcm_oss_format_to((__force snd_pcm_format_t)fmt);
+ if (f >= 0)
+ formats |= f;
+ }
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Fix-starvation-on-down_write_nonblock.patch b/patches.drivers/ALSA-pcm-Fix-starvation-on-down_write_nonblock.patch
index e8ac5a19d1..c0506c38c3 100644
--- a/patches.drivers/ALSA-pcm-Fix-starvation-on-down_write_nonblock.patch
+++ b/patches.drivers/ALSA-pcm-Fix-starvation-on-down_write_nonblock.patch
@@ -51,9 +51,9 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
#include <linux/uio.h>
+#include <linux/delay.h>
- /*
- * Compatibility
-@@ -79,12 +80,12 @@ static DECLARE_RWSEM(snd_pcm_link_rwsem)
+ #include "pcm_local.h"
+
+@@ -91,12 +92,12 @@ static DECLARE_RWSEM(snd_pcm_link_rwsem)
* and this may lead to a deadlock when the code path takes read sem
* twice (e.g. one in snd_pcm_action_nonatomic() and another in
* snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to
@@ -68,8 +68,8 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
+ msleep(1);
}
- /**
-@@ -1826,7 +1827,7 @@ static int snd_pcm_link(struct snd_pcm_s
+ #define PCM_LOCK_DEFAULT 0
+@@ -1967,7 +1968,7 @@ static int snd_pcm_link(struct snd_pcm_s
res = -ENOMEM;
goto _nolock;
}
@@ -78,7 +78,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
write_lock_irq(&snd_pcm_link_rwlock);
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
substream->runtime->status->state != substream1->runtime->status->state ||
-@@ -1873,7 +1874,7 @@ static int snd_pcm_unlink(struct snd_pcm
+@@ -2014,7 +2015,7 @@ static int snd_pcm_unlink(struct snd_pcm
struct snd_pcm_substream *s;
int res = 0;
diff --git a/patches.drivers/ALSA-pcm-Fix-structure-definition-for-X32-ABI.patch b/patches.drivers/ALSA-pcm-Fix-structure-definition-for-X32-ABI.patch
new file mode 100644
index 0000000000..7c1d76d7b8
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Fix-structure-definition-for-X32-ABI.patch
@@ -0,0 +1,35 @@
+From c9adcdbc653b52e4be834f535eefec833f9ca6b1 Mon Sep 17 00:00:00 2001
+From: Baolin Wang <baolin.wang@linaro.org>
+Date: Thu, 21 Sep 2017 14:03:29 +0800
+Subject: [PATCH] ALSA: pcm: Fix structure definition for X32 ABI
+Git-commit: c9adcdbc653b52e4be834f535eefec833f9ca6b1
+Patch-mainline: v4.14-rc4
+References: bsc#1121278
+
+X32 ABI uses the 64bit timespec in addition to 64bit alignment of 64bit
+values. We have added compat ABI for these ioctls, but this patch adds
+one missing padding into 'struct snd_pcm_mmap_status_x32' to fix
+incompatibilities.
+
+Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_compat.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
+index 3a1cc7b97e46..b719d0bd833e 100644
+--- a/sound/core/pcm_compat.c
++++ b/sound/core/pcm_compat.c
+@@ -547,6 +547,7 @@ struct snd_pcm_mmap_status_x32 {
+ u32 pad2; /* alignment */
+ struct timespec tstamp;
+ s32 suspended_state;
++ s32 pad3;
+ struct timespec audio_tstamp;
+ } __packed;
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Fix-trailing-semicolon.patch b/patches.drivers/ALSA-pcm-Fix-trailing-semicolon.patch
new file mode 100644
index 0000000000..a9a574bbe2
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Fix-trailing-semicolon.patch
@@ -0,0 +1,34 @@
+From 3c7f69195cdd2a14ab85dfb32805e866eb241a6e Mon Sep 17 00:00:00 2001
+From: Luis de Bethencourt <luisbg@kernel.org>
+Date: Tue, 16 Jan 2018 13:26:26 +0000
+Subject: [PATCH] ALSA: pcm: Fix trailing semicolon
+Git-commit: 3c7f69195cdd2a14ab85dfb32805e866eb241a6e
+Patch-mainline: v4.16-rc1
+References: bsc#1121278
+
+The trailing semicolon is an empty statement that does no operation.
+Removing it since it doesn't do anything.
+
+Signed-off-by: Luis de Bethencourt <luisbg@kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index f08772568c17..484a18d96371 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -3446,7 +3446,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
+ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
+ struct vm_area_struct *area)
+ {
+- struct snd_pcm_runtime *runtime = substream->runtime;;
++ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
+ return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Follow-standard-EXPORT_SYMBOL-declarations.patch b/patches.drivers/ALSA-pcm-Follow-standard-EXPORT_SYMBOL-declarations.patch
new file mode 100644
index 0000000000..00920514d3
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Follow-standard-EXPORT_SYMBOL-declarations.patch
@@ -0,0 +1,401 @@
+From 602d7d72c8255f80898e94562f777635efd1ddaf Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 16 Jun 2017 16:12:30 +0200
+Subject: [PATCH] ALSA: pcm: Follow standard EXPORT_SYMBOL() declarations
+Git-commit: 602d7d72c8255f80898e94562f777635efd1ddaf
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Just a tidy up to follow the standard EXPORT_SYMBOL*() declarations
+in order to improve grep-ability.
+
+- Remove superfluous blank line before EXPORT_SYMBOL*() lines
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 21 ---------------------
+ sound/core/pcm_memory.c | 6 ------
+ sound/core/pcm_misc.c | 11 -----------
+ sound/core/pcm_native.c | 7 -------
+ 4 files changed, 45 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 631cd598ba6c..461c21f21caf 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -490,7 +490,6 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction,
+ for (substream = stream->substream; substream != NULL; substream = substream->next)
+ substream->ops = ops;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_set_ops);
+
+ /**
+@@ -508,7 +507,6 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream)
+ runtime->sync.id32[2] = -1;
+ runtime->sync.id32[3] = -1;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_set_sync);
+
+ /*
+@@ -625,7 +623,6 @@ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
+ }
+ return changed;
+ }
+-
+ EXPORT_SYMBOL(snd_interval_refine);
+
+ static int snd_interval_refine_first(struct snd_interval *i)
+@@ -888,7 +885,6 @@ int snd_interval_ratnum(struct snd_interval *i,
+ }
+ return err;
+ }
+-
+ EXPORT_SYMBOL(snd_interval_ratnum);
+
+ /**
+@@ -1026,7 +1022,6 @@ int snd_interval_list(struct snd_interval *i, unsigned int count,
+ }
+ return snd_interval_refine(i, &list_range);
+ }
+-
+ EXPORT_SYMBOL(snd_interval_list);
+
+ /**
+@@ -1165,7 +1160,6 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
+ va_end(args);
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_rule_add);
+
+ /**
+@@ -1229,7 +1223,6 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa
+ struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
+ return snd_interval_setinteger(constrs_interval(constrs, var));
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
+
+ /**
+@@ -1255,7 +1248,6 @@ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_par
+ t.integer = 0;
+ return snd_interval_refine(constrs_interval(constrs, var), &t);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
+
+ static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
+@@ -1286,7 +1278,6 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
+ snd_pcm_hw_rule_list, (void *)l,
+ var, -1);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
+
+ static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params,
+@@ -1353,7 +1344,6 @@ int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
+ snd_pcm_hw_rule_ratnums, (void *)r,
+ var, -1);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
+
+ static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
+@@ -1388,7 +1378,6 @@ int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
+ snd_pcm_hw_rule_ratdens, (void *)r,
+ var, -1);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
+
+ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
+@@ -1435,7 +1424,6 @@ int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
+ (void*) l,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
+
+ static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
+@@ -1463,7 +1451,6 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
+ snd_pcm_hw_rule_step, (void *) step,
+ var, -1);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
+
+ static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
+@@ -1494,7 +1481,6 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
+ snd_pcm_hw_rule_pow2, NULL,
+ var, -1);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
+
+ static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
+@@ -1553,7 +1539,6 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
+ _snd_pcm_hw_param_any(params, k);
+ params->info = ~0U;
+ }
+-
+ EXPORT_SYMBOL(_snd_pcm_hw_params_any);
+
+ /**
+@@ -1586,7 +1571,6 @@ int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
+ }
+ return -EINVAL;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_param_value);
+
+ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
+@@ -1604,7 +1588,6 @@ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
+ snd_BUG();
+ }
+ }
+-
+ EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
+
+ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
+@@ -1651,7 +1634,6 @@ int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
+ }
+ return snd_pcm_hw_param_value(params, var, dir);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_param_first);
+
+ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
+@@ -1698,7 +1680,6 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
+ }
+ return snd_pcm_hw_param_value(params, var, dir);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_param_last);
+
+ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
+@@ -1796,7 +1777,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
+ }
+ return -ENXIO;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_lib_ioctl);
+
+ /**
+@@ -1832,7 +1812,6 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
+ kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_period_elapsed);
+
+ /*
+diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
+index b45f6aa32264..ae33e456708c 100644
+--- a/sound/core/pcm_memory.c
++++ b/sound/core/pcm_memory.c
+@@ -120,7 +120,6 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
+ snd_pcm_lib_preallocate_free(substream);
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
+
+ #ifdef CONFIG_SND_VERBOSE_PROCFS
+@@ -263,7 +262,6 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
+ substream->dma_buffer.dev.dev = data;
+ return snd_pcm_lib_preallocate_pages1(substream, size, max);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
+
+ /**
+@@ -292,7 +290,6 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
+ return err;
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
+
+ #ifdef CONFIG_SND_DMA_SGBUF
+@@ -314,7 +311,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
+ return NULL;
+ return sgbuf->page_table[idx];
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
+ #endif /* CONFIG_SND_DMA_SGBUF */
+
+@@ -370,7 +366,6 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
+ runtime->dma_bytes = size;
+ return 1; /* area was changed */
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
+
+ /**
+@@ -398,7 +393,6 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
+ snd_pcm_set_runtime_buffer(substream, NULL);
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_lib_free_pages);
+
+ int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream,
+diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
+index dd8383e29315..9be81025372f 100644
+--- a/sound/core/pcm_misc.c
++++ b/sound/core/pcm_misc.c
+@@ -248,7 +248,6 @@ int snd_pcm_format_signed(snd_pcm_format_t format)
+ return -EINVAL;
+ return val;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_signed);
+
+ /**
+@@ -267,7 +266,6 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format)
+ return val;
+ return !val;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_unsigned);
+
+ /**
+@@ -280,7 +278,6 @@ int snd_pcm_format_linear(snd_pcm_format_t format)
+ {
+ return snd_pcm_format_signed(format) >= 0;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_linear);
+
+ /**
+@@ -299,7 +296,6 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format)
+ return -EINVAL;
+ return val;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_little_endian);
+
+ /**
+@@ -318,7 +314,6 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format)
+ return val;
+ return !val;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_big_endian);
+
+ /**
+@@ -337,7 +332,6 @@ int snd_pcm_format_width(snd_pcm_format_t format)
+ return -EINVAL;
+ return val;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_width);
+
+ /**
+@@ -356,7 +350,6 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format)
+ return -EINVAL;
+ return val;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_physical_width);
+
+ /**
+@@ -374,7 +367,6 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
+ return -EINVAL;
+ return samples * phys_width / 8;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_size);
+
+ /**
+@@ -391,7 +383,6 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
+ return NULL;
+ return pcm_formats[(INT)format].silence;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_silence_64);
+
+ /**
+@@ -462,7 +453,6 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
+ #endif
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_format_set_silence);
+
+ /**
+@@ -491,7 +481,6 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
+ }
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
+
+ /**
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 7e8f3656b695..d35c6614fdab 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1278,7 +1278,6 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
+ {
+ return snd_pcm_action(&snd_pcm_action_stop, substream, state);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_stop);
+
+ /**
+@@ -1453,7 +1452,6 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream)
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+ return err;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_suspend);
+
+ /**
+@@ -1485,7 +1483,6 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
+ }
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_suspend_all);
+
+ /* resume */
+@@ -2369,7 +2366,6 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
+ }
+ snd_pcm_detach_substream(substream);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_release_substream);
+
+ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
+@@ -2411,7 +2407,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
+ snd_pcm_release_substream(substream);
+ return err;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_open_substream);
+
+ static int snd_pcm_open_file(struct file *file,
+@@ -3504,7 +3499,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
+ area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
+ return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
+ #endif /* SNDRV_PCM_INFO_MMAP */
+
+@@ -3553,7 +3547,6 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
+ atomic_inc(&substream->mmap_count);
+ return err;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_mmap_data);
+
+ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Forcibly-stop-at-disconnect-callback.patch b/patches.drivers/ALSA-pcm-Forcibly-stop-at-disconnect-callback.patch
new file mode 100644
index 0000000000..e5baca298d
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Forcibly-stop-at-disconnect-callback.patch
@@ -0,0 +1,43 @@
+From 6ca73de7ebc5dac358551633e0c69ab6b5007baa Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 11 Oct 2017 11:42:00 +0200
+Subject: [PATCH] ALSA: pcm: Forcibly stop at disconnect callback
+Git-commit: 6ca73de7ebc5dac358551633e0c69ab6b5007baa
+Patch-mainline: v4.15-rc1
+References: bsc#1121278
+
+So far we assumed that each driver implements the hotplug PCM handling
+properly, e.g. dealing with the pending PCM stream at disconnect
+callback. But most codes don't care, and it eventually leaves the PCM
+stream inconsistent state when an abrupt disconnection like sysfs
+unbind happens.
+
+This patch is simple but a big-hammer solution: invoke snd_pcm_stop()
+at the common PCM disconnect callback always when the stream is
+running.
+
+Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index 1b073ed0b1f9..9070f277f8db 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -1154,6 +1154,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
+ for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
+ snd_pcm_stream_lock_irq(substream);
+ if (substream->runtime) {
++ if (snd_pcm_running(substream))
++ snd_pcm_stop(substream,
++ SNDRV_PCM_STATE_DISCONNECTED);
++ /* to be sure, set the state unconditionally */
+ substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
+ wake_up(&substream->runtime->sleep);
+ wake_up(&substream->runtime->tsleep);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Hide-local_irq_disable-enable-and-local_irq.patch b/patches.drivers/ALSA-pcm-Hide-local_irq_disable-enable-and-local_irq.patch
new file mode 100644
index 0000000000..bae8c025d6
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Hide-local_irq_disable-enable-and-local_irq.patch
@@ -0,0 +1,156 @@
+From 10aa7cad37d330dbff6a285af56dc4a7153a8f00 Mon Sep 17 00:00:00 2001
+From: Anna-Maria Gleixner <anna-maria@linutronix.de>
+Date: Fri, 4 May 2018 17:28:10 +0200
+Subject: [PATCH] ALSA: pcm: Hide local_irq_disable/enable() and local_irqsave/restore()
+Git-commit: 10aa7cad37d330dbff6a285af56dc4a7153a8f00
+Patch-mainline: v4.18-rc1
+References: bsc#1121278
+
+The snd_pcm_stream_lock_irq*() functions decouple disabling interrupts
+from the actual locking process. This does not work as expected if the
+locking primitives are replaced like on preempt-rt.
+
+Provide one function for locking which uses correct locking primitives.
+
+Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 85 ++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 57 insertions(+), 28 deletions(-)
+
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -99,6 +99,57 @@ static inline void down_write_nonblock(s
+ cond_resched();
+ }
+
++#define PCM_LOCK_DEFAULT 0
++#define PCM_LOCK_IRQ 1
++#define PCM_LOCK_IRQSAVE 2
++
++static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream,
++ unsigned int mode)
++{
++ unsigned long flags = 0;
++ if (substream->pcm->nonatomic) {
++ down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
++ mutex_lock(&substream->self_group.mutex);
++ } else {
++ switch (mode) {
++ case PCM_LOCK_DEFAULT:
++ read_lock(&snd_pcm_link_rwlock);
++ break;
++ case PCM_LOCK_IRQ:
++ read_lock_irq(&snd_pcm_link_rwlock);
++ break;
++ case PCM_LOCK_IRQSAVE:
++ read_lock_irqsave(&snd_pcm_link_rwlock, flags);
++ break;
++ }
++ spin_lock(&substream->self_group.lock);
++ }
++ return flags;
++}
++
++static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,
++ unsigned int mode, unsigned long flags)
++{
++ if (substream->pcm->nonatomic) {
++ mutex_unlock(&substream->self_group.mutex);
++ up_read(&snd_pcm_link_rwsem);
++ } else {
++ spin_unlock(&substream->self_group.lock);
++
++ switch (mode) {
++ case PCM_LOCK_DEFAULT:
++ read_unlock(&snd_pcm_link_rwlock);
++ break;
++ case PCM_LOCK_IRQ:
++ read_unlock_irq(&snd_pcm_link_rwlock);
++ break;
++ case PCM_LOCK_IRQSAVE:
++ read_unlock_irqrestore(&snd_pcm_link_rwlock, flags);
++ break;
++ }
++ }
++}
++
+ /**
+ * snd_pcm_stream_lock - Lock the PCM stream
+ * @substream: PCM substream
+@@ -109,13 +160,7 @@ static inline void down_write_nonblock(s
+ */
+ void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
+ {
+- if (substream->pcm->nonatomic) {
+- down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
+- mutex_lock(&substream->self_group.mutex);
+- } else {
+- read_lock(&snd_pcm_link_rwlock);
+- spin_lock(&substream->self_group.lock);
+- }
++ __snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT);
+ }
+ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
+
+@@ -127,13 +172,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
+ */
+ void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
+ {
+- if (substream->pcm->nonatomic) {
+- mutex_unlock(&substream->self_group.mutex);
+- up_read(&snd_pcm_link_rwsem);
+- } else {
+- spin_unlock(&substream->self_group.lock);
+- read_unlock(&snd_pcm_link_rwlock);
+- }
++ __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0);
+ }
+ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
+
+@@ -147,9 +186,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock)
+ */
+ void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
+ {
+- if (!substream->pcm->nonatomic)
+- local_irq_disable();
+- snd_pcm_stream_lock(substream);
++ __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ);
+ }
+ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
+
+@@ -161,19 +198,13 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_ir
+ */
+ void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
+ {
+- snd_pcm_stream_unlock(substream);
+- if (!substream->pcm->nonatomic)
+- local_irq_enable();
++ __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0);
+ }
+ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
+
+ unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
+ {
+- unsigned long flags = 0;
+- if (!substream->pcm->nonatomic)
+- local_irq_save(flags);
+- snd_pcm_stream_lock(substream);
+- return flags;
++ return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE);
+ }
+ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
+
+@@ -187,9 +218,7 @@ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_i
+ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
+ unsigned long flags)
+ {
+- snd_pcm_stream_unlock(substream);
+- if (!substream->pcm->nonatomic)
+- local_irq_restore(flags);
++ __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags);
+ }
+ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
+
diff --git a/patches.drivers/ALSA-pcm-Introduce-copy_user-copy_kernel-and-fill_si.patch b/patches.drivers/ALSA-pcm-Introduce-copy_user-copy_kernel-and-fill_si.patch
new file mode 100644
index 0000000000..321386906a
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Introduce-copy_user-copy_kernel-and-fill_si.patch
@@ -0,0 +1,249 @@
+From 29d1a873de542cbb46d0641037d2601cb76be5b1 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 10 May 2017 20:02:35 +0200
+Subject: [PATCH] ALSA: pcm: Introduce copy_user, copy_kernel and fill_silence ops
+Git-commit: 29d1a873de542cbb46d0641037d2601cb76be5b1
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+For supporting the explicit in-kernel copy of PCM buffer data, and
+also for further code refactoring, three new PCM ops, copy_user,
+copy_kernel and fill_silence, are introduced. The old copy and
+silence ops will be deprecated and removed later once when all callers
+are converted.
+
+The copy_kernel ops is the new one, and it's supposed to transfer the
+PCM data from the given kernel buffer to the hardware ring-buffer (or
+vice-versa depending on the stream direction), while the copy_user ops
+is equivalent with the former copy ops, to transfer the data from the
+user-space buffer.
+
+The major difference of the new copy_* and fill_silence ops from the
+previous ops is that the new ops take bytes instead of frames for size
+and position arguments. It has two merits: first, it allows the
+callback implementation often simpler (just call directly memcpy() &
+co), and second, it may unify the implementations of both interleaved
+and non-interleaved cases, as we'll see in the later patch.
+
+As of this stage, copy_kernel ops isn't referred yet, but only
+copy_user is used.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Acked-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 7 ++++
+ sound/core/pcm_lib.c | 89 ++++++++++++++++++++++++++++++++++++--------
+ sound/soc/soc-pcm.c | 3 ++
+ 3 files changed, 84 insertions(+), 15 deletions(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 79fedf517070..86b126be49a2 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -83,6 +83,13 @@ struct snd_pcm_ops {
+ void __user *buf, snd_pcm_uframes_t count);
+ int (*silence)(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
++ int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
++ unsigned long pos, unsigned long bytes);
++ int (*copy_user)(struct snd_pcm_substream *substream, int channel,
++ unsigned long pos, void __user *buf,
++ unsigned long bytes);
++ int (*copy_kernel)(struct snd_pcm_substream *substream, int channel,
++ unsigned long pos, void *buf, unsigned long bytes);
+ struct page *(*page)(struct snd_pcm_substream *substream,
+ unsigned long offset);
+ int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index e50548af4004..1fca1ffd235e 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -57,6 +57,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t frames, ofs, transfer;
++ char *hwbuf;
++ int err;
+
+ if (runtime->silence_size < runtime->boundary) {
+ snd_pcm_sframes_t noise_dist, n;
+@@ -111,27 +113,37 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
+ transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
+ if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
+ runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
+- if (substream->ops->silence) {
+- int err;
++ if (substream->ops->fill_silence) {
++ err = substream->ops->fill_silence(substream, 0,
++ frames_to_bytes(runtime, ofs),
++ frames_to_bytes(runtime, transfer));
++ snd_BUG_ON(err < 0);
++ } else if (substream->ops->silence) {
+ err = substream->ops->silence(substream, -1, ofs, transfer);
+ snd_BUG_ON(err < 0);
+ } else {
+- char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
++ hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
+ snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
+ }
+ } else {
+ unsigned int c;
+ unsigned int channels = runtime->channels;
+- if (substream->ops->silence) {
++ if (substream->ops->fill_silence) {
++ for (c = 0; c < channels; ++c) {
++ err = substream->ops->fill_silence(substream, c,
++ samples_to_bytes(runtime, ofs),
++ samples_to_bytes(runtime, transfer));
++ snd_BUG_ON(err < 0);
++ }
++ } else if (substream->ops->silence) {
+ for (c = 0; c < channels; ++c) {
+- int err;
+ err = substream->ops->silence(substream, c, ofs, transfer);
+ snd_BUG_ON(err < 0);
+ }
+ } else {
+ size_t dma_csize = runtime->dma_bytes / channels;
+ for (c = 0; c < channels; ++c) {
+- char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs);
++ hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs);
+ snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
+ }
+ }
+@@ -1997,7 +2009,13 @@ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+ char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
+- if (substream->ops->copy) {
++ if (substream->ops->copy_user) {
++ hwoff = frames_to_bytes(runtime, hwoff);
++ frames = frames_to_bytes(runtime, frames);
++ err = substream->ops->copy_user(substream, 0, hwoff, buf, frames);
++ if (err < 0)
++ return err;
++ } else if (substream->ops->copy) {
+ if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
+ return err;
+ } else {
+@@ -2121,7 +2139,8 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
+ runtime = substream->runtime;
+- if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area))
++ if (snd_BUG_ON(!substream->ops->copy_user && !substream->ops->copy
++ && !runtime->dma_area))
+ return -EINVAL;
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+@@ -2158,8 +2177,30 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
+ int err;
+ void __user **bufs = (void __user **)data;
+ int channels = runtime->channels;
++ char __user *buf;
+ int c;
+- if (substream->ops->copy) {
++
++ if (substream->ops->copy_user) {
++ hwoff = samples_to_bytes(runtime, hwoff);
++ off = samples_to_bytes(runtime, off);
++ frames = samples_to_bytes(runtime, frames);
++ for (c = 0; c < channels; ++c, ++bufs) {
++ buf = *bufs + off;
++ if (!*bufs) {
++ if (snd_BUG_ON(!substream->ops->fill_silence))
++ return -EINVAL;
++ err = substream->ops->fill_silence(substream, c,
++ hwoff,
++ frames);
++ } else {
++ err = substream->ops->copy_user(substream, c,
++ hwoff, buf,
++ frames);
++ }
++ if (err < 0)
++ return err;
++ }
++ } else if (substream->ops->copy) {
+ if (snd_BUG_ON(!substream->ops->silence))
+ return -EINVAL;
+ for (c = 0; c < channels; ++c, ++bufs) {
+@@ -2167,7 +2208,7 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
+ if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0)
+ return err;
+ } else {
+- char __user *buf = *bufs + samples_to_bytes(runtime, off);
++ buf = *bufs + samples_to_bytes(runtime, off);
+ if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
+ return err;
+ }
+@@ -2219,7 +2260,13 @@ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+ char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
+- if (substream->ops->copy) {
++ if (substream->ops->copy_user) {
++ hwoff = frames_to_bytes(runtime, hwoff);
++ frames = frames_to_bytes(runtime, frames);
++ err = substream->ops->copy_user(substream, 0, hwoff, buf, frames);
++ if (err < 0)
++ return err;
++ } else if (substream->ops->copy) {
+ if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
+ return err;
+ } else {
+@@ -2367,10 +2414,24 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
+ int err;
+ void __user **bufs = (void __user **)data;
+ int channels = runtime->channels;
++ char __user *buf;
++ char *hwbuf;
+ int c;
+- if (substream->ops->copy) {
++
++ if (substream->ops->copy_user) {
++ hwoff = samples_to_bytes(runtime, hwoff);
++ off = samples_to_bytes(runtime, off);
++ frames = samples_to_bytes(runtime, frames);
++ for (c = 0; c < channels; ++c, ++bufs) {
++ if (!*bufs)
++ continue;
++ err = substream->ops->copy_user(substream, c, hwoff,
++ *bufs + off, frames);
++ if (err < 0)
++ return err;
++ }
++ } else if (substream->ops->copy) {
+ for (c = 0; c < channels; ++c, ++bufs) {
+- char __user *buf;
+ if (*bufs == NULL)
+ continue;
+ buf = *bufs + samples_to_bytes(runtime, off);
+@@ -2380,8 +2441,6 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
+ } else {
+ snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
+ for (c = 0; c < channels; ++c, ++bufs) {
+- char *hwbuf;
+- char __user *buf;
+ if (*bufs == NULL)
+ continue;
+
+diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
+index efc5831f205d..8867ed9e5f56 100644
+--- a/sound/soc/soc-pcm.c
++++ b/sound/soc/soc-pcm.c
+@@ -2743,6 +2743,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
+
+ if (platform->driver->ops) {
+ rtd->ops.ack = platform->driver->ops->ack;
++ rtd->ops.copy_user = platform->driver->ops->copy_user;
++ rtd->ops.copy_kernel = platform->driver->ops->copy_kernel;
++ rtd->ops.fill_silence = platform->driver->ops->fill_silence;
+ rtd->ops.copy = platform->driver->ops->copy;
+ rtd->ops.silence = platform->driver->ops->silence;
+ rtd->ops.page = platform->driver->ops->page;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Kill-set_fs-in-PCM-OSS-layer.patch b/patches.drivers/ALSA-pcm-Kill-set_fs-in-PCM-OSS-layer.patch
new file mode 100644
index 0000000000..df8fb3ea35
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Kill-set_fs-in-PCM-OSS-layer.patch
@@ -0,0 +1,148 @@
+From 13f72c8c28fc4b2d5329c940086c8939756600c2 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 21 May 2017 10:14:42 +0200
+Subject: [PATCH] ALSA: pcm: Kill set_fs() in PCM OSS layer
+Git-commit: 13f72c8c28fc4b2d5329c940086c8939756600c2
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+This is the last-standing one: kill the set_fs() usage in PCM OSS
+layer by replacing with the new API functions to deal with the direct
+in-kernel buffer copying.
+
+The code to fill the silence can be replaced even to a one-liner to
+pass NULL buffer instead of the manual copying.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_oss.c | 77 +++++++---------------------------------
+ 1 file changed, 12 insertions(+), 65 deletions(-)
+
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index e306f05ce51d..2d6a825cfe88 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -67,18 +67,6 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
+ static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
+ static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
+
+-static inline mm_segment_t snd_enter_user(void)
+-{
+- mm_segment_t fs = get_fs();
+- set_fs(get_ds());
+- return fs;
+-}
+-
+-static inline void snd_leave_user(mm_segment_t fs)
+-{
+- set_fs(fs);
+-}
+-
+ /*
+ * helper functions to process hw_params
+ */
+@@ -1191,14 +1179,8 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
+ if (ret < 0)
+ break;
+ }
+- if (in_kernel) {
+- mm_segment_t fs;
+- fs = snd_enter_user();
+- ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
+- snd_leave_user(fs);
+- } else {
+- ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
+- }
++ ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
++ frames, in_kernel);
+ if (ret != -EPIPE && ret != -ESTRPIPE)
+ break;
+ /* test, if we can't store new data, because the stream */
+@@ -1234,14 +1216,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
+ ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
+ if (ret < 0)
+ break;
+- if (in_kernel) {
+- mm_segment_t fs;
+- fs = snd_enter_user();
+- ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
+- snd_leave_user(fs);
+- } else {
+- ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
+- }
++ ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
++ frames, in_kernel);
+ if (ret == -EPIPE) {
+ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+ ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+@@ -1273,14 +1249,8 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
+ if (ret < 0)
+ break;
+ }
+- if (in_kernel) {
+- mm_segment_t fs;
+- fs = snd_enter_user();
+- ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
+- snd_leave_user(fs);
+- } else {
+- ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
+- }
++ ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
++ in_kernel);
+ if (ret != -EPIPE && ret != -ESTRPIPE)
+ break;
+
+@@ -1313,14 +1283,8 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void *
+ if (ret < 0)
+ break;
+ }
+- if (in_kernel) {
+- mm_segment_t fs;
+- fs = snd_enter_user();
+- ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
+- snd_leave_user(fs);
+- } else {
+- ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
+- }
++ ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
++ in_kernel);
+ if (ret != -EPIPE && ret != -ESTRPIPE)
+ break;
+ }
+@@ -1650,27 +1614,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
+ size = runtime->control->appl_ptr % runtime->period_size;
+ if (size > 0) {
+ size = runtime->period_size - size;
+- if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
+- size = (runtime->frame_bits * size) / 8;
+- while (size > 0) {
+- mm_segment_t fs;
+- size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
+- size -= size1;
+- size1 *= 8;
+- size1 /= runtime->sample_bits;
+- snd_pcm_format_set_silence(runtime->format,
+- runtime->oss.buffer,
+- size1);
+- size1 /= runtime->channels; /* frames */
+- fs = snd_enter_user();
+- snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1);
+- snd_leave_user(fs);
+- }
+- } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
+- void __user *buffers[runtime->channels];
+- memset(buffers, 0, runtime->channels * sizeof(void *));
+- snd_pcm_lib_writev(substream, buffers, size);
+- }
++ if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED)
++ snd_pcm_lib_write(substream, NULL, size);
++ else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
++ snd_pcm_lib_writev(substream, NULL, size);
+ }
+ mutex_unlock(&runtime->oss.params_lock);
+ /*
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Mark-expected-switch-fall-through.patch b/patches.drivers/ALSA-pcm-Mark-expected-switch-fall-through.patch
new file mode 100644
index 0000000000..9967e4cf21
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Mark-expected-switch-fall-through.patch
@@ -0,0 +1,34 @@
+From 5a6cd13d4faef48bdcb7ae9c1e98175332ced7cd Mon Sep 17 00:00:00 2001
+From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
+Date: Wed, 1 Aug 2018 10:58:25 -0500
+Subject: [PATCH] ALSA: pcm: Mark expected switch fall-through
+Git-commit: 5a6cd13d4faef48bdcb7ae9c1e98175332ced7cd
+Patch-mainline: v4.19-rc1
+References: bsc#1121278
+
+In preparation to enabling -Wimplicit-fallthrough, mark switch cases
+where we are expecting to fall through.
+
+Addresses-coverity-id: 1357375 ("Missing break in switch")
+Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_plugin.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
+index 85bab922ce69..0391cb1a4f19 100644
+--- a/sound/core/oss/pcm_plugin.c
++++ b/sound/core/oss/pcm_plugin.c
+@@ -353,6 +353,7 @@ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
+ if (snd_mask_test(format_mask, (__force int)format1))
+ return format1;
+ }
++ /* fall through */
+ default:
+ return (__force snd_pcm_format_t)-EINVAL;
+ }
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-More-unification-of-PCM-transfer-codes.patch b/patches.drivers/ALSA-pcm-More-unification-of-PCM-transfer-codes.patch
new file mode 100644
index 0000000000..68f51c00fc
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-More-unification-of-PCM-transfer-codes.patch
@@ -0,0 +1,376 @@
+From 9f60063094ba72e2767be18289baf5151f1f1c2f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 24 May 2017 18:15:26 +0200
+Subject: [PATCH] ALSA: pcm: More unification of PCM transfer codes
+Git-commit: 9f60063094ba72e2767be18289baf5151f1f1c2f
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+This patch proceeds more abstraction of PCM read/write loop codes.
+
+For both interleaved and non-interleaved transfers, the same copy or
+silence transfer code (which is defined as pcm_transfer_f) is used
+now. This became possible since we switched to byte size to copy_*
+and fill_silence ops argument instead of frames.
+
+And, for both read and write, we can use the same copy function (which
+is defined as pcm_copy_f), just depending on whether interleaved or
+non-interleaved mode.
+
+The transfer function is determined at the beginning of the loop,
+depending on whether the driver gives the specific copy ops or it's
+the standard read/write.
+
+Another bonus by this change is that we now guarantee the silencing
+behavior when NULL buffer is passed to write helpers. It'll simplify
+some codes later.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 254 +++++++++++++++++++++----------------------
+ 1 file changed, 123 insertions(+), 131 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index ae030c5eb7c6..0c53a34201c1 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1993,77 +1993,100 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
+ return err;
+ }
+
+-typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
+- void *data, unsigned int off,
+- snd_pcm_uframes_t size);
++typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream,
++ int channel, unsigned long hwoff,
++ void *buf, unsigned long bytes);
+
+-static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
+- unsigned int hwoff,
+- void *data, unsigned int off,
+- snd_pcm_uframes_t frames)
++typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void *,
++ snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f);
++
++/* calculate the target DMA-buffer position to be written/read */
++static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
++ int channel, unsigned long hwoff)
++{
++ return runtime->dma_area + hwoff +
++ channel * (runtime->dma_bytes / runtime->channels);
++}
++
++/* default copy_user ops for write */
++static int default_write_copy_user(struct snd_pcm_substream *substream,
++ int channel, unsigned long hwoff,
++ void __user *buf, unsigned long bytes)
++{
++ if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
++ buf, bytes))
++ return -EFAULT;
++ return 0;
++}
++
++/* fill silence instead of copy data; called as a transfer helper
++ * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
++ * a NULL buffer is passed
++ */
++static int fill_silence(struct snd_pcm_substream *substream, int channel,
++ unsigned long hwoff, void *buf, unsigned long bytes)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+- int err;
+- char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
+- if (substream->ops->copy_user) {
+- hwoff = frames_to_bytes(runtime, hwoff);
+- frames = frames_to_bytes(runtime, frames);
+- err = substream->ops->copy_user(substream, 0, hwoff, buf, frames);
+- if (err < 0)
+- return err;
+- } else {
+- char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
+- if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
+- return -EFAULT;
+- }
++
++ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
++ return 0;
++ if (substream->ops->fill_silence)
++ return substream->ops->fill_silence(substream, channel,
++ hwoff, bytes);
++
++ snd_pcm_format_set_silence(runtime->format,
++ get_dma_ptr(runtime, channel, hwoff),
++ bytes_to_samples(runtime, bytes));
+ return 0;
+ }
+-
+-static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
+- unsigned int hwoff,
+- void *data, unsigned int off,
+- snd_pcm_uframes_t frames)
++
++/* call transfer function with the converted pointers and sizes;
++ * for interleaved mode, it's one shot for all samples
++ */
++static int interleaved_copy(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t hwoff, void *data,
++ snd_pcm_uframes_t off,
++ snd_pcm_uframes_t frames,
++ pcm_transfer_f transfer)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ /* convert to bytes */
++ hwoff = frames_to_bytes(runtime, hwoff);
++ off = frames_to_bytes(runtime, off);
++ frames = frames_to_bytes(runtime, frames);
++ return transfer(substream, 0, hwoff, data + off, frames);
++}
++
++/* call transfer function with the converted pointers and sizes for each
++ * non-interleaved channel; when buffer is NULL, silencing instead of copying
++ */
++static int noninterleaved_copy(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t hwoff, void *data,
++ snd_pcm_uframes_t off,
++ snd_pcm_uframes_t frames,
++ pcm_transfer_f transfer)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+- int err;
+- void __user **bufs = (void __user **)data;
+ int channels = runtime->channels;
+- char __user *buf;
+- int c;
+-
+- if (substream->ops->copy_user) {
+- hwoff = samples_to_bytes(runtime, hwoff);
+- off = samples_to_bytes(runtime, off);
+- frames = samples_to_bytes(runtime, frames);
+- for (c = 0; c < channels; ++c, ++bufs) {
+- buf = *bufs + off;
+- if (!*bufs) {
+- if (snd_BUG_ON(!substream->ops->fill_silence))
+- return -EINVAL;
+- err = substream->ops->fill_silence(substream, c,
+- hwoff,
+- frames);
+- } else {
+- err = substream->ops->copy_user(substream, c,
+- hwoff, buf,
+- frames);
+- }
+- if (err < 0)
+- return err;
+- }
+- } else {
+- /* default transfer behaviour */
+- size_t dma_csize = runtime->dma_bytes / channels;
+- for (c = 0; c < channels; ++c, ++bufs) {
+- char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
+- if (*bufs == NULL) {
+- snd_pcm_format_set_silence(runtime->format, hwbuf, frames);
+- } else {
+- char __user *buf = *bufs + samples_to_bytes(runtime, off);
+- if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)))
+- return -EFAULT;
+- }
+- }
++ void **bufs = data;
++ int c, err;
++
++ /* convert to bytes; note that it's not frames_to_bytes() here.
++ * in non-interleaved mode, we copy for each channel, thus
++ * each copy is n_samples bytes x channels = whole frames.
++ */
++ off = samples_to_bytes(runtime, off);
++ frames = samples_to_bytes(runtime, frames);
++ hwoff = samples_to_bytes(runtime, hwoff);
++ for (c = 0; c < channels; ++c, ++bufs) {
++ if (!data || !*bufs)
++ err = fill_silence(substream, c, hwoff, NULL, frames);
++ else
++ err = transfer(substream, c, hwoff, *bufs + off,
++ frames);
++ if (err < 0)
++ return err;
+ }
+ return 0;
+ }
+@@ -2106,24 +2129,33 @@ snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t xfer = 0;
+ snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
+- transfer_f transfer;
++ pcm_copy_f writer;
++ pcm_transfer_f transfer;
+ bool nonblock;
+ int err;
+
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
+- runtime = substream->runtime;
+
+ if (interleaved) {
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
+ runtime->channels > 1)
+ return -EINVAL;
+- transfer = snd_pcm_lib_write_transfer;
++ writer = interleaved_copy;
+ } else {
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+ return -EINVAL;
+- transfer = snd_pcm_lib_writev_transfer;
++ writer = noninterleaved_copy;
++ }
++
++ if (!data) {
++ transfer = fill_silence;
++ } else {
++ if (substream->ops->copy_user)
++ transfer = (pcm_transfer_f)substream->ops->copy_user;
++ else
++ transfer = default_write_copy_user;
+ }
+
+ if (size == 0)
+@@ -2166,7 +2198,8 @@ snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ appl_ptr = runtime->control->appl_ptr;
+ appl_ofs = appl_ptr % runtime->buffer_size;
+ snd_pcm_stream_unlock_irq(substream);
+- err = transfer(substream, appl_ofs, data, offset, frames);
++ err = writer(substream, appl_ofs, data, offset, frames,
++ transfer);
+ snd_pcm_stream_lock_irq(substream);
+ if (err < 0)
+ goto _end_unlock;
+@@ -2200,65 +2233,15 @@ snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ }
+ EXPORT_SYMBOL(__snd_pcm_lib_write);
+
+-static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
+- unsigned int hwoff,
+- void *data, unsigned int off,
+- snd_pcm_uframes_t frames)
+-{
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- int err;
+- char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
+- if (substream->ops->copy_user) {
+- hwoff = frames_to_bytes(runtime, hwoff);
+- frames = frames_to_bytes(runtime, frames);
+- err = substream->ops->copy_user(substream, 0, hwoff, buf, frames);
+- if (err < 0)
+- return err;
+- } else {
+- char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
+- if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
+- return -EFAULT;
+- }
+- return 0;
+-}
+-
+-static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
+- unsigned int hwoff,
+- void *data, unsigned int off,
+- snd_pcm_uframes_t frames)
++/* default copy_user ops for read */
++static int default_read_copy_user(struct snd_pcm_substream *substream,
++ int channel, unsigned long hwoff,
++ void *buf, unsigned long bytes)
+ {
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- int err;
+- void __user **bufs = (void __user **)data;
+- int channels = runtime->channels;
+- char __user *buf;
+- char *hwbuf;
+- int c;
+-
+- if (substream->ops->copy_user) {
+- hwoff = samples_to_bytes(runtime, hwoff);
+- off = samples_to_bytes(runtime, off);
+- frames = samples_to_bytes(runtime, frames);
+- for (c = 0; c < channels; ++c, ++bufs) {
+- if (!*bufs)
+- continue;
+- err = substream->ops->copy_user(substream, c, hwoff,
+- *bufs + off, frames);
+- if (err < 0)
+- return err;
+- }
+- } else {
+- snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
+- for (c = 0; c < channels; ++c, ++bufs) {
+- if (*bufs == NULL)
+- continue;
+-
+- hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
+- buf = *bufs + samples_to_bytes(runtime, off);
+- if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames)))
+- return -EFAULT;
+- }
+- }
++ if (copy_to_user((void __user *)buf,
++ get_dma_ptr(substream->runtime, channel, hwoff),
++ bytes))
++ return -EFAULT;
+ return 0;
+ }
+
+@@ -2270,26 +2253,34 @@ snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t xfer = 0;
+ snd_pcm_uframes_t offset = 0;
+ snd_pcm_uframes_t avail;
+- transfer_f transfer;
++ pcm_copy_f reader;
++ pcm_transfer_f transfer;
+ bool nonblock;
+ int err;
+
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
+- runtime = substream->runtime;
++
++ if (!data)
++ return -EINVAL;
+
+ if (interleaved) {
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
+ runtime->channels > 1)
+ return -EINVAL;
+- transfer = snd_pcm_lib_read_transfer;
++ reader = interleaved_copy;
+ } else {
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+ return -EINVAL;
+- transfer = snd_pcm_lib_readv_transfer;
++ reader = noninterleaved_copy;
+ }
+
++ if (substream->ops->copy_user)
++ transfer = (pcm_transfer_f)substream->ops->copy_user;
++ else
++ transfer = default_read_copy_user;
++
+ if (size == 0)
+ return 0;
+
+@@ -2343,7 +2334,8 @@ snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ appl_ptr = runtime->control->appl_ptr;
+ appl_ofs = appl_ptr % runtime->buffer_size;
+ snd_pcm_stream_unlock_irq(substream);
+- err = transfer(substream, appl_ofs, data, offset, frames);
++ err = reader(substream, appl_ofs, data, offset, frames,
++ transfer);
+ snd_pcm_stream_lock_irq(substream);
+ if (err < 0)
+ goto _end_unlock;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Preprocess-PAUSED-or-SUSPENDED-stream-befor.patch b/patches.drivers/ALSA-pcm-Preprocess-PAUSED-or-SUSPENDED-stream-befor.patch
new file mode 100644
index 0000000000..e6147473d3
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Preprocess-PAUSED-or-SUSPENDED-stream-befor.patch
@@ -0,0 +1,48 @@
+From 1b745cd97425f7b0b9d0c87c1b9766c31b7d0a7e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 24 May 2016 15:40:03 +0200
+Subject: [PATCH] ALSA: pcm: Preprocess PAUSED or SUSPENDED stream before PREPARE
+Git-commit: 1b745cd97425f7b0b9d0c87c1b9766c31b7d0a7e
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Calling PREPARE ioctl to the stream in either PAUSED or SUSPENDED
+state may confuse some drivers that don't handle the state properly.
+Instead of fixing each driver, PCM core should take care of the proper
+state change before actually trying to (re-)prepare the stream.
+Namely, when the stream is in PAUSED state, it triggers PAUSE_RELEASE,
+and when in SUSPENDED state, it triggers STOP, before calling prepare
+callbacks.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 69cf9b02ac70..0941b9c92b3f 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1684,6 +1684,17 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
+ else
+ f_flags = substream->f_flags;
+
++ snd_pcm_stream_lock_irq(substream);
++ switch (substream->runtime->status->state) {
++ case SNDRV_PCM_STATE_PAUSED:
++ snd_pcm_pause(substream, 0);
++ /* fallthru */
++ case SNDRV_PCM_STATE_SUSPENDED:
++ snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
++ break;
++ }
++ snd_pcm_stream_unlock_irq(substream);
++
+ return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
+ substream, f_flags);
+ }
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Protect-call-to-dma_mmap_coherent-by-check-.patch b/patches.drivers/ALSA-pcm-Protect-call-to-dma_mmap_coherent-by-check-.patch
new file mode 100644
index 0000000000..205c1c4808
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Protect-call-to-dma_mmap_coherent-by-check-.patch
@@ -0,0 +1,39 @@
+From abe594c2cf55b46d4feb61c01fe9063afff2e50c Mon Sep 17 00:00:00 2001
+From: Geert Uytterhoeven <geert@linux-m68k.org>
+Date: Sun, 9 Jul 2017 21:31:02 +0200
+Subject: [PATCH] ALSA: pcm: Protect call to dma_mmap_coherent() by check for HAS_DMA
+Git-commit: abe594c2cf55b46d4feb61c01fe9063afff2e50c
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+If NO_DMA=y:
+
+ sound/core/pcm_native.o: In function `snd_pcm_lib_default_mmap':
+ pcm_native.c:(.text+0x144c): undefined reference to `bad_dma_ops'
+ pcm_native.c:(.text+0x1474): undefined reference to `dma_common_mmap'
+
+Add a check for HAS_DMA to fix this.
+
+Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 0d1834310531..b26c7e61d600 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -3502,7 +3502,7 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
+ }
+ #endif /* CONFIG_GENERIC_ALLOCATOR */
+ #ifndef CONFIG_X86 /* for avoiding warnings arch/x86/mm/pat.c */
+- if (!substream->ops->page &&
++ if (IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page &&
+ substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
+ return dma_mmap_coherent(substream->dma_buffer.dev.dev,
+ area,
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Remove-VLA-usage.patch b/patches.drivers/ALSA-pcm-Remove-VLA-usage.patch
new file mode 100644
index 0000000000..831689f164
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Remove-VLA-usage.patch
@@ -0,0 +1,82 @@
+From 5730f9f744cfe20b771adc33f3b476b95d3eebba Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 13 Mar 2018 11:18:57 +0100
+Subject: [PATCH] ALSA: pcm: Remove VLA usage
+Git-commit: 5730f9f744cfe20b771adc33f3b476b95d3eebba
+Patch-mainline: v4.17-rc1
+References: bsc#1121278
+
+A helper function used by snd_pcm_hw_refine() still keeps using VLA
+for timestamps of hw constraint rules that are non-fixed size.
+
+Let's replace the VLA with a simple kmalloc() array.
+
+Reference: https://lkml.org/lkml/2018/3/7/621
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 77ba50ddcf9e..756a9a3884a5 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -323,7 +323,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_constraints *constrs =
+ &substream->runtime->hw_constraints;
+ unsigned int k;
+- unsigned int rstamps[constrs->rules_num];
++ unsigned int *rstamps;
+ unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
+ unsigned int stamp;
+ struct snd_pcm_hw_rule *r;
+@@ -331,7 +331,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ struct snd_mask old_mask;
+ struct snd_interval old_interval;
+ bool again;
+- int changed;
++ int changed, err = 0;
+
+ /*
+ * Each application of rule has own sequence number.
+@@ -339,8 +339,9 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ * Each member of 'rstamps' array represents the sequence number of
+ * recent application of corresponding rule.
+ */
+- for (k = 0; k < constrs->rules_num; k++)
+- rstamps[k] = 0;
++ rstamps = kcalloc(constrs->rules_num, sizeof(unsigned int), GFP_KERNEL);
++ if (!rstamps)
++ return -ENOMEM;
+
+ /*
+ * Each member of 'vstamps' array represents the sequence number of
+@@ -398,8 +399,10 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ }
+
+ changed = r->func(params, r);
+- if (changed < 0)
+- return changed;
++ if (changed < 0) {
++ err = changed;
++ goto out;
++ }
+
+ /*
+ * When the parameter is changed, notify it to the caller
+@@ -430,7 +433,9 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ if (again)
+ goto retry;
+
+- return 0;
++ out:
++ kfree(rstamps);
++ return err;
+ }
+
+ static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Remove-WARN_ON-at-snd_pcm_hw_params-error.patch b/patches.drivers/ALSA-pcm-Remove-WARN_ON-at-snd_pcm_hw_params-error.patch
new file mode 100644
index 0000000000..e5e25da791
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Remove-WARN_ON-at-snd_pcm_hw_params-error.patch
@@ -0,0 +1,49 @@
+From e1a3a981e320a6916b30ff53571ba144274def0e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 9 Apr 2018 17:12:16 +0200
+Subject: [PATCH] ALSA: pcm: Remove WARN_ON() at snd_pcm_hw_params() error
+Git-commit: e1a3a981e320a6916b30ff53571ba144274def0e
+Patch-mainline: v4.17-rc1
+References: bsc#1121278
+
+snd_pcm_hw_params() (more exactly snd_pcm_hw_params_choose()) contains
+a check of the return error from snd_pcm_hw_param_first() and _last()
+with snd_BUG_ON() -- i.e. it may trigger WARN_ON() depending on the
+kconfig.
+
+This was a valid check in the past, as these functions shouldn't
+return any error if the parameters have been already refined via
+snd_pcm_hw_refine() beforehand. However, the recent rewrite
+introduced a kmalloc() in snd_pcm_hw_refine() for removing VLA, and
+this brought a possibility to trigger an error. As a result, syzbot
+caught lots of superfluous kernel WARN_ON() and paniced via fault
+injection.
+
+As the WARN_ON() is no longer valid with the introduction of
+kmalloc(), let's drop snd_BUG_ON() check, in order to make the world
+peaceful place again.
+
+Reported-by: syzbot+803e0047ac3a3096bb4f@syzkaller.appspotmail.com
+Fixes: 5730f9f744cf ("ALSA: pcm: Remove VLA usage")
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index b84554893fab..35ffccea94c3 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -617,7 +617,7 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+ changed = snd_pcm_hw_param_first(pcm, params, *v, NULL);
+ else
+ changed = snd_pcm_hw_param_last(pcm, params, *v, NULL);
+- if (snd_BUG_ON(changed < 0))
++ if (changed < 0)
+ return changed;
+ if (changed == 0)
+ continue;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Remove-incorrect-snd_BUG_ON-usages b/patches.drivers/ALSA-pcm-Remove-incorrect-snd_BUG_ON-usages
index d28bd94d5d..6c6deae36e 100644
--- a/patches.drivers/ALSA-pcm-Remove-incorrect-snd_BUG_ON-usages
+++ b/patches.drivers/ALSA-pcm-Remove-incorrect-snd_BUG_ON-usages
@@ -46,7 +46,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
-@@ -467,7 +467,6 @@ static int snd_pcm_hw_param_near(struct
+@@ -455,7 +455,6 @@ static int snd_pcm_hw_param_near(struct
v = snd_pcm_hw_param_last(pcm, params, var, dir);
else
v = snd_pcm_hw_param_first(pcm, params, var, dir);
@@ -56,7 +56,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
-@@ -1665,7 +1665,7 @@ int snd_pcm_hw_param_first(struct snd_pc
+@@ -1632,7 +1632,7 @@ int snd_pcm_hw_param_first(struct snd_pc
return changed;
if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
@@ -65,7 +65,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
return err;
}
return snd_pcm_hw_param_value(params, var, dir);
-@@ -1712,7 +1712,7 @@ int snd_pcm_hw_param_last(struct snd_pcm
+@@ -1678,7 +1678,7 @@ int snd_pcm_hw_param_last(struct snd_pcm
return changed;
if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
diff --git a/patches.drivers/ALSA-pcm-Remove-set_fs-in-PCM-core-code.patch b/patches.drivers/ALSA-pcm-Remove-set_fs-in-PCM-core-code.patch
new file mode 100644
index 0000000000..8104f53705
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Remove-set_fs-in-PCM-core-code.patch
@@ -0,0 +1,230 @@
+From c2c86a97175f552fd32b339426a489c7af818123 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 10 May 2017 14:33:44 +0200
+Subject: [PATCH] ALSA: pcm: Remove set_fs() in PCM core code
+Git-commit: c2c86a97175f552fd32b339426a489c7af818123
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+PCM core code has a few usages of set_fs(), mostly for two codepaths:
+- The DELAY ioctl call from pcm_compat.c
+- The ioctl wrapper in kernel context for PCM OSS and other
+
+This patch removes the set_fs() usage in these places by a slight code
+refactoring. For the former point, snd_pcm_delay() is changed to
+return the value directly instead of putting the value to the given
+address. Each caller stores the result in an appropriate manner.
+
+For fixing the latter, snd_pcm_lib_kernel_ioctl() is changed to call
+the functions directly as well. For achieving it, now the function
+accepts only the limited set of ioctls that have been used, so far.
+The primary user of this function is the PCM OSS layer, and the only
+other user is USB UAC1 gadget driver. Both drivers don't need the
+full set of ioctls.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_compat.c | 12 ++---
+ sound/core/pcm_native.c | 102 +++++++++++++++++++++++++---------------
+ 2 files changed, 67 insertions(+), 47 deletions(-)
+
+diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
+index 1f64ab0c2a95..8a0f8d51e95d 100644
+--- a/sound/core/pcm_compat.c
++++ b/sound/core/pcm_compat.c
+@@ -27,17 +27,13 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
+ s32 __user *src)
+ {
+ snd_pcm_sframes_t delay;
+- mm_segment_t fs;
+- int err;
+
+- fs = snd_enter_user();
+- err = snd_pcm_delay(substream, &delay);
+- snd_leave_user(fs);
+- if (err < 0)
+- return err;
++ delay = snd_pcm_delay(substream);
++ if (delay < 0)
++ return delay;
+ if (put_user(delay, src))
+ return -EFAULT;
+- return err;
++ return 0;
+ }
+
+ static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index ecde57afa45a..889364cbced8 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -181,20 +181,6 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
+ }
+ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
+
+-static inline mm_segment_t snd_enter_user(void)
+-{
+- mm_segment_t fs = get_fs();
+- set_fs(get_ds());
+- return fs;
+-}
+-
+-static inline void snd_leave_user(mm_segment_t fs)
+-{
+- set_fs(fs);
+-}
+-
+-
+-
+ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
+ {
+ struct snd_pcm_runtime *runtime;
+@@ -1081,6 +1067,7 @@ static const struct action_ops snd_pcm_action_start = {
+ * @substream: the PCM substream instance
+ *
+ * Return: Zero if successful, or a negative error code.
++ * The stream lock must be acquired before calling this function.
+ */
+ int snd_pcm_start(struct snd_pcm_substream *substream)
+ {
+@@ -1088,6 +1075,13 @@ int snd_pcm_start(struct snd_pcm_substream *substream)
+ SNDRV_PCM_STATE_RUNNING);
+ }
+
++/* take the stream lock and start the streams */
++static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
++{
++ return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream,
++ SNDRV_PCM_STATE_RUNNING);
++}
++
+ /*
+ * stop callbacks
+ */
+@@ -2575,8 +2569,7 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
+ return err;
+ }
+
+-static int snd_pcm_delay(struct snd_pcm_substream *substream,
+- snd_pcm_sframes_t __user *res)
++static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+@@ -2592,10 +2585,7 @@ static int snd_pcm_delay(struct snd_pcm_substream *substream,
+ n += runtime->delay;
+ }
+ snd_pcm_stream_unlock_irq(substream);
+- if (!err)
+- if (put_user(n, res))
+- err = -EFAULT;
+- return err;
++ return err < 0 ? err : n;
+ }
+
+ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
+@@ -2683,7 +2673,7 @@ static int snd_pcm_common_ioctl1(struct file *file,
+ case SNDRV_PCM_IOCTL_RESET:
+ return snd_pcm_reset(substream);
+ case SNDRV_PCM_IOCTL_START:
+- return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING);
++ return snd_pcm_start_lock_irq(substream);
+ case SNDRV_PCM_IOCTL_LINK:
+ return snd_pcm_link(substream, (int)(unsigned long) arg);
+ case SNDRV_PCM_IOCTL_UNLINK:
+@@ -2695,7 +2685,16 @@ static int snd_pcm_common_ioctl1(struct file *file,
+ case SNDRV_PCM_IOCTL_HWSYNC:
+ return snd_pcm_hwsync(substream);
+ case SNDRV_PCM_IOCTL_DELAY:
+- return snd_pcm_delay(substream, arg);
++ {
++ snd_pcm_sframes_t delay = snd_pcm_delay(substream);
++ snd_pcm_sframes_t __user *res = arg;
++
++ if (delay < 0)
++ return delay;
++ if (put_user(delay, res))
++ return -EFAULT;
++ return 0;
++ }
+ case SNDRV_PCM_IOCTL_SYNC_PTR:
+ return snd_pcm_sync_ptr(substream, arg);
+ #ifdef CONFIG_SND_SUPPORT_OLD_API
+@@ -2909,30 +2908,55 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
+ (void __user *)arg);
+ }
+
++/**
++ * snd_pcm_kernel_ioctl - Execute PCM ioctl in the kernel-space
++ * @substream: PCM substream
++ * @cmd: IOCTL cmd
++ * @arg: IOCTL argument
++ *
++ * The function is provided primarily for OSS layer and USB gadget drivers,
++ * and it allows only the limited set of ioctls (hw_params, sw_params,
++ * prepare, start, drain, drop, forward).
++ */
+ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
+ {
+- mm_segment_t fs;
+- int result;
++ snd_pcm_uframes_t *frames = arg;
++ snd_pcm_sframes_t result;
+
+- fs = snd_enter_user();
+- switch (substream->stream) {
+- case SNDRV_PCM_STREAM_PLAYBACK:
+- result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
+- (void __user *)arg);
+- break;
+- case SNDRV_PCM_STREAM_CAPTURE:
+- result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
+- (void __user *)arg);
+- break;
++ switch (cmd) {
++ case SNDRV_PCM_IOCTL_FORWARD:
++ {
++ /* provided only for OSS; capture-only and no value returned */
++ if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
++ return -EINVAL;
++ result = snd_pcm_capture_forward(substream, *frames);
++ return result < 0 ? result : 0;
++ }
++ case SNDRV_PCM_IOCTL_HW_PARAMS:
++ return snd_pcm_hw_params(substream, arg);
++ case SNDRV_PCM_IOCTL_SW_PARAMS:
++ return snd_pcm_sw_params(substream, arg);
++ case SNDRV_PCM_IOCTL_PREPARE:
++ return snd_pcm_prepare(substream, NULL);
++ case SNDRV_PCM_IOCTL_START:
++ return snd_pcm_start_lock_irq(substream);
++ case SNDRV_PCM_IOCTL_DRAIN:
++ return snd_pcm_drain(substream, NULL);
++ case SNDRV_PCM_IOCTL_DROP:
++ return snd_pcm_drop(substream);
++ case SNDRV_PCM_IOCTL_DELAY:
++ {
++ result = snd_pcm_delay(substream);
++ if (result < 0)
++ return result;
++ *frames = result;
++ return 0;
++ }
+ default:
+- result = -EINVAL;
+- break;
++ return -EINVAL;
+ }
+- snd_leave_user(fs);
+- return result;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
+
+ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Return-0-when-size-start_threshold-in-captu.patch b/patches.drivers/ALSA-pcm-Return-0-when-size-start_threshold-in-captu.patch
new file mode 100644
index 0000000000..98f9a24ac9
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Return-0-when-size-start_threshold-in-captu.patch
@@ -0,0 +1,47 @@
+From 62ba568f7aef4beb0eda945a2b2a91b7a2b8f215 Mon Sep 17 00:00:00 2001
+From: Ricardo Biehl Pasquali <pasqualirb@gmail.com>
+Date: Sat, 25 Aug 2018 16:53:23 -0300
+Subject: [PATCH] ALSA: pcm: Return 0 when size < start_threshold in capture
+Git-commit: 62ba568f7aef4beb0eda945a2b2a91b7a2b8f215
+Patch-mainline: v4.20-rc1
+References: bsc#1121278
+
+In __snd_pcm_lib_xfer(), when capture, if state is PREPARED
+and size is less than start_threshold nothing can be done.
+As there is no error, 0 is returned.
+
+Signed-off-by: Ricardo Biehl Pasquali <pasqualirb@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 4e6110d778bd..7f71c2449af5 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2173,11 +2173,16 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ goto _end_unlock;
+
+ if (!is_playback &&
+- runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+- size >= runtime->start_threshold) {
+- err = snd_pcm_start(substream);
+- if (err < 0)
++ runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
++ if (size >= runtime->start_threshold) {
++ err = snd_pcm_start(substream);
++ if (err < 0)
++ goto _end_unlock;
++ } else {
++ /* nothing to do */
++ err = 0;
+ goto _end_unlock;
++ }
+ }
+
+ runtime->twake = runtime->control->avail_min ? : 1;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Return-EBUSY-for-OSS-ioctls-changing-busy-s b/patches.drivers/ALSA-pcm-Return-EBUSY-for-OSS-ioctls-changing-busy-s
index c0f39aac16..70bbc01bb7 100644
--- a/patches.drivers/ALSA-pcm-Return-EBUSY-for-OSS-ioctls-changing-busy-s
+++ b/patches.drivers/ALSA-pcm-Return-EBUSY-for-OSS-ioctls-changing-busy-s
@@ -42,7 +42,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
struct snd_pcm_plugin *plugin_last;
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
-@@ -1406,6 +1406,7 @@ static ssize_t snd_pcm_oss_write1(struct
+@@ -1370,6 +1370,7 @@ static ssize_t snd_pcm_oss_write1(struct
if (atomic_read(&substream->mmap_count))
return -ENXIO;
@@ -50,7 +50,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
while (bytes > 0) {
if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
tmp = -ERESTARTSYS;
-@@ -1469,6 +1470,7 @@ static ssize_t snd_pcm_oss_write1(struct
+@@ -1433,6 +1434,7 @@ static ssize_t snd_pcm_oss_write1(struct
}
tmp = 0;
}
@@ -58,7 +58,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
}
-@@ -1514,6 +1516,7 @@ static ssize_t snd_pcm_oss_read1(struct
+@@ -1478,6 +1480,7 @@ static ssize_t snd_pcm_oss_read1(struct
if (atomic_read(&substream->mmap_count))
return -ENXIO;
@@ -66,7 +66,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
while (bytes > 0) {
if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
tmp = -ERESTARTSYS;
-@@ -1562,6 +1565,7 @@ static ssize_t snd_pcm_oss_read1(struct
+@@ -1526,6 +1529,7 @@ static ssize_t snd_pcm_oss_read1(struct
}
tmp = 0;
}
@@ -74,7 +74,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
}
-@@ -1668,8 +1672,11 @@ static int snd_pcm_oss_sync(struct snd_p
+@@ -1632,8 +1636,11 @@ static int snd_pcm_oss_sync(struct snd_p
goto __direct;
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
return err;
@@ -87,7 +87,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
format = snd_pcm_oss_format_from(runtime->oss.format);
width = snd_pcm_format_physical_width(format);
if (runtime->oss.buffer_used > 0) {
-@@ -1681,10 +1688,8 @@ static int snd_pcm_oss_sync(struct snd_p
+@@ -1645,10 +1652,8 @@ static int snd_pcm_oss_sync(struct snd_p
runtime->oss.buffer + runtime->oss.buffer_used,
size);
err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
@@ -100,7 +100,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
} else if (runtime->oss.period_ptr > 0) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm, "sync: period_ptr\n");
-@@ -1694,10 +1699,8 @@ static int snd_pcm_oss_sync(struct snd_p
+@@ -1658,10 +1663,8 @@ static int snd_pcm_oss_sync(struct snd_p
runtime->oss.buffer,
size * 8 / width);
err = snd_pcm_oss_sync1(substream, size);
@@ -113,9 +113,9 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
}
/*
* The ALSA's period might be a bit large than OSS one.
-@@ -1728,7 +1731,11 @@ static int snd_pcm_oss_sync(struct snd_p
- snd_pcm_lib_writev(substream, buffers, size);
- }
+@@ -1675,7 +1678,11 @@ static int snd_pcm_oss_sync(struct snd_p
+ else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+ snd_pcm_lib_writev(substream, NULL, size);
}
+unlock:
mutex_unlock(&runtime->oss.params_lock);
@@ -125,7 +125,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
/*
* finish sync: drain the buffer
*/
-@@ -1776,6 +1783,8 @@ static int snd_pcm_oss_set_rate(struct s
+@@ -1723,6 +1730,8 @@ static int snd_pcm_oss_set_rate(struct s
rate = 192000;
if (mutex_lock_interruptible(&runtime->oss.params_lock))
return -ERESTARTSYS;
@@ -134,7 +134,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (runtime->oss.rate != rate) {
runtime->oss.params = 1;
runtime->oss.rate = rate;
-@@ -1810,6 +1819,8 @@ static int snd_pcm_oss_set_channels(stru
+@@ -1757,6 +1766,8 @@ static int snd_pcm_oss_set_channels(stru
runtime = substream->runtime;
if (mutex_lock_interruptible(&runtime->oss.params_lock))
return -ERESTARTSYS;
@@ -143,7 +143,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (runtime->oss.channels != channels) {
runtime->oss.params = 1;
runtime->oss.channels = channels;
-@@ -1898,6 +1909,8 @@ static int snd_pcm_oss_set_format(struct
+@@ -1845,6 +1856,8 @@ static int snd_pcm_oss_set_format(struct
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -152,7 +152,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (mutex_lock_interruptible(&runtime->oss.params_lock))
return -ERESTARTSYS;
if (runtime->oss.format != format) {
-@@ -1952,6 +1965,8 @@ static int snd_pcm_oss_set_subdivide(str
+@@ -1899,6 +1912,8 @@ static int snd_pcm_oss_set_subdivide(str
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -161,7 +161,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (mutex_lock_interruptible(&runtime->oss.params_lock))
return -ERESTARTSYS;
err = snd_pcm_oss_set_subdivide1(substream, subdivide);
-@@ -1990,6 +2005,8 @@ static int snd_pcm_oss_set_fragment(stru
+@@ -1937,6 +1952,8 @@ static int snd_pcm_oss_set_fragment(stru
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -170,7 +170,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
if (mutex_lock_interruptible(&runtime->oss.params_lock))
return -ERESTARTSYS;
err = snd_pcm_oss_set_fragment1(substream, val);
-@@ -2384,6 +2401,7 @@ static void snd_pcm_oss_init_substream(s
+@@ -2331,6 +2348,7 @@ static void snd_pcm_oss_init_substream(s
runtime->oss.maxfrags = 0;
runtime->oss.subdivision = 0;
substream->pcm_release = snd_pcm_oss_release_substream;
diff --git a/patches.drivers/ALSA-pcm-Return-negative-delays-from-SNDRV_PCM_IOCTL.patch b/patches.drivers/ALSA-pcm-Return-negative-delays-from-SNDRV_PCM_IOCTL.patch
new file mode 100644
index 0000000000..0ef669232e
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Return-negative-delays-from-SNDRV_PCM_IOCTL.patch
@@ -0,0 +1,106 @@
+From 912e4c332037e7ed063c164985c36fb2b549ea3a Mon Sep 17 00:00:00 2001
+From: Jeffery Miller <jmiller@neverware.com>
+Date: Fri, 20 Apr 2018 23:20:46 -0500
+Subject: [PATCH] ALSA: pcm: Return negative delays from SNDRV_PCM_IOCTL_DELAY.
+Git-commit: 912e4c332037e7ed063c164985c36fb2b549ea3a
+Patch-mainline: v4.17-rc3
+References: bsc#1121278
+
+The commit c2c86a97175f ("ALSA: pcm: Remove set_fs() in PCM core code")
+changed SNDRV_PCM_IOCTL_DELAY to return an inconsistent error instead of a
+negative delay. Originally the call would succeed and return the negative
+delay. The Chromium OS Audio Server (CRAS) gets confused and hangs when
+the error is returned instead of the negative delay.
+
+Help CRAS avoid the issue by rolling back the behavior to return a
+negative delay instead of an error.
+
+Fixes: c2c86a97175f ("ALSA: pcm: Remove set_fs() in PCM core code")
+Signed-off-by: Jeffery Miller <jmiller@neverware.com>
+Cc: <stable@vger.kernel.org> # v4.13+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_compat.c | 7 ++++---
+ sound/core/pcm_native.c | 23 +++++++++++------------
+ 2 files changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
+index b719d0bd833e..06d7c40af570 100644
+--- a/sound/core/pcm_compat.c
++++ b/sound/core/pcm_compat.c
+@@ -27,10 +27,11 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
+ s32 __user *src)
+ {
+ snd_pcm_sframes_t delay;
++ int err;
+
+- delay = snd_pcm_delay(substream);
+- if (delay < 0)
+- return delay;
++ err = snd_pcm_delay(substream, &delay);
++ if (err)
++ return err;
+ if (put_user(delay, src))
+ return -EFAULT;
+ return 0;
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 35ffccea94c3..06aa499543b6 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -2692,7 +2692,8 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
+ return err;
+ }
+
+-static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream)
++static int snd_pcm_delay(struct snd_pcm_substream *substream,
++ snd_pcm_sframes_t *delay)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+@@ -2708,7 +2709,9 @@ static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream)
+ n += runtime->delay;
+ }
+ snd_pcm_stream_unlock_irq(substream);
+- return err < 0 ? err : n;
++ if (!err)
++ *delay = n;
++ return err;
+ }
+
+ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
+@@ -2916,11 +2919,13 @@ static int snd_pcm_common_ioctl(struct file *file,
+ return snd_pcm_hwsync(substream);
+ case SNDRV_PCM_IOCTL_DELAY:
+ {
+- snd_pcm_sframes_t delay = snd_pcm_delay(substream);
++ snd_pcm_sframes_t delay;
+ snd_pcm_sframes_t __user *res = arg;
++ int err;
+
+- if (delay < 0)
+- return delay;
++ err = snd_pcm_delay(substream, &delay);
++ if (err)
++ return err;
+ if (put_user(delay, res))
+ return -EFAULT;
+ return 0;
+@@ -3008,13 +3013,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
+ case SNDRV_PCM_IOCTL_DROP:
+ return snd_pcm_drop(substream);
+ case SNDRV_PCM_IOCTL_DELAY:
+- {
+- result = snd_pcm_delay(substream);
+- if (result < 0)
+- return result;
+- *frames = result;
+- return 0;
+- }
++ return snd_pcm_delay(substream, frames);
+ default:
+ return -EINVAL;
+ }
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Set-config-update-bits-only-when-really-cha.patch b/patches.drivers/ALSA-pcm-Set-config-update-bits-only-when-really-cha.patch
new file mode 100644
index 0000000000..43b64205d3
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Set-config-update-bits-only-when-really-cha.patch
@@ -0,0 +1,98 @@
+From 7a0a87160a1dc09220ec485b31d0f82f687a053f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 2 Jan 2018 11:00:57 +0100
+Subject: [PATCH] ALSA: pcm: Set config update bits only when really changed
+Git-commit: 7a0a87160a1dc09220ec485b31d0f82f687a053f
+Patch-mainline: v4.16-rc1
+References: bsc#1121278
+
+The PCM config space refine codes touch the parameter rmask and cmask
+bits when the given config parameter is changed. But in most places
+it checks only whether the changed value is non-zero or not, and they
+don't consider whether a negative error value is returned. This will
+lead to the incorrect update bits set upon the error path.
+
+Fix the codes to check properly the return code whether it's really
+updated or an error.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_oss.c | 10 +++++-----
+ sound/core/pcm_lib.c | 4 ++--
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index e49f448ee04f..5d131088ac7c 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -186,7 +186,7 @@ static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params,
+ {
+ int changed;
+ changed = snd_mask_refine(hw_param_mask(params, var), val);
+- if (changed) {
++ if (changed > 0) {
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
+@@ -233,7 +233,7 @@ static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
+ val, open);
+ else
+ return -EINVAL;
+- if (changed) {
++ if (changed > 0) {
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
+@@ -294,7 +294,7 @@ static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
+ val, open);
+ else
+ return -EINVAL;
+- if (changed) {
++ if (changed > 0) {
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
+@@ -500,7 +500,7 @@ static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
+ }
+ } else
+ return -EINVAL;
+- if (changed) {
++ if (changed > 0) {
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
+@@ -540,7 +540,7 @@ static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
+ {
+ int changed;
+ changed = snd_interval_setinteger(hw_param_interval(params, var));
+- if (changed) {
++ if (changed > 0) {
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 10e7ef7a8804..bfff8d001466 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1603,7 +1603,7 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
+ changed = snd_interval_refine_first(hw_param_interval(params, var));
+ else
+ return -EINVAL;
+- if (changed) {
++ if (changed > 0) {
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
+@@ -1649,7 +1649,7 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
+ changed = snd_interval_refine_last(hw_param_interval(params, var));
+ else
+ return -EINVAL;
+- if (changed) {
++ if (changed > 0) {
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Shuffle-codes.patch b/patches.drivers/ALSA-pcm-Shuffle-codes.patch
new file mode 100644
index 0000000000..3ecf01b61f
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Shuffle-codes.patch
@@ -0,0 +1,278 @@
+From bdc4acf7f6eb14a64c549c04c741b18e3afb350e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 24 May 2017 17:59:17 +0200
+Subject: [PATCH] ALSA: pcm: Shuffle codes
+Git-commit: bdc4acf7f6eb14a64c549c04c741b18e3afb350e
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Just shuffle the codes, without any change otherwise.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 212 +++++++++++++++++++++----------------------
+ 1 file changed, 106 insertions(+), 106 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 5fcd798672b4..51eeea9088de 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1993,6 +1993,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
+ return err;
+ }
+
++typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
++ unsigned long data, unsigned int off,
++ snd_pcm_uframes_t size);
++
+ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
+ unsigned int hwoff,
+ unsigned long data, unsigned int off,
+@@ -2015,9 +2019,68 @@ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
+-typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
+- unsigned long data, unsigned int off,
+- snd_pcm_uframes_t size);
++static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
++ unsigned int hwoff,
++ unsigned long data, unsigned int off,
++ snd_pcm_uframes_t frames)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int err;
++ void __user **bufs = (void __user **)data;
++ int channels = runtime->channels;
++ char __user *buf;
++ int c;
++
++ if (substream->ops->copy_user) {
++ hwoff = samples_to_bytes(runtime, hwoff);
++ off = samples_to_bytes(runtime, off);
++ frames = samples_to_bytes(runtime, frames);
++ for (c = 0; c < channels; ++c, ++bufs) {
++ buf = *bufs + off;
++ if (!*bufs) {
++ if (snd_BUG_ON(!substream->ops->fill_silence))
++ return -EINVAL;
++ err = substream->ops->fill_silence(substream, c,
++ hwoff,
++ frames);
++ } else {
++ err = substream->ops->copy_user(substream, c,
++ hwoff, buf,
++ frames);
++ }
++ if (err < 0)
++ return err;
++ }
++ } else {
++ /* default transfer behaviour */
++ size_t dma_csize = runtime->dma_bytes / channels;
++ for (c = 0; c < channels; ++c, ++bufs) {
++ char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
++ if (*bufs == NULL) {
++ snd_pcm_format_set_silence(runtime->format, hwbuf, frames);
++ } else {
++ char __user *buf = *bufs + samples_to_bytes(runtime, off);
++ if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)))
++ return -EFAULT;
++ }
++ }
++ }
++ return 0;
++}
++
++/* sanity-check for read/write methods */
++static int pcm_sanity_check(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime;
++ if (PCM_RUNTIME_CHECK(substream))
++ return -ENXIO;
++ runtime = substream->runtime;
++ if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
++ return -EINVAL;
++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
++ return -EBADFD;
++ return 0;
++}
+
+ static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
+ {
+@@ -2118,20 +2181,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
+ }
+
+-/* sanity-check for read/write methods */
+-static int pcm_sanity_check(struct snd_pcm_substream *substream)
+-{
+- struct snd_pcm_runtime *runtime;
+- if (PCM_RUNTIME_CHECK(substream))
+- return -ENXIO;
+- runtime = substream->runtime;
+- if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
+- return -EINVAL;
+- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+- return -EBADFD;
+- return 0;
+-}
+-
+ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size)
+ {
+ struct snd_pcm_runtime *runtime;
+@@ -2153,55 +2202,6 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v
+
+ EXPORT_SYMBOL(snd_pcm_lib_write);
+
+-static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
+- unsigned int hwoff,
+- unsigned long data, unsigned int off,
+- snd_pcm_uframes_t frames)
+-{
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- int err;
+- void __user **bufs = (void __user **)data;
+- int channels = runtime->channels;
+- char __user *buf;
+- int c;
+-
+- if (substream->ops->copy_user) {
+- hwoff = samples_to_bytes(runtime, hwoff);
+- off = samples_to_bytes(runtime, off);
+- frames = samples_to_bytes(runtime, frames);
+- for (c = 0; c < channels; ++c, ++bufs) {
+- buf = *bufs + off;
+- if (!*bufs) {
+- if (snd_BUG_ON(!substream->ops->fill_silence))
+- return -EINVAL;
+- err = substream->ops->fill_silence(substream, c,
+- hwoff,
+- frames);
+- } else {
+- err = substream->ops->copy_user(substream, c,
+- hwoff, buf,
+- frames);
+- }
+- if (err < 0)
+- return err;
+- }
+- } else {
+- /* default transfer behaviour */
+- size_t dma_csize = runtime->dma_bytes / channels;
+- for (c = 0; c < channels; ++c, ++bufs) {
+- char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
+- if (*bufs == NULL) {
+- snd_pcm_format_set_silence(runtime->format, hwbuf, frames);
+- } else {
+- char __user *buf = *bufs + samples_to_bytes(runtime, off);
+- if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)))
+- return -EFAULT;
+- }
+- }
+- }
+- return 0;
+-}
+-
+ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
+ void __user **bufs,
+ snd_pcm_uframes_t frames)
+@@ -2246,6 +2246,46 @@ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
++static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
++ unsigned int hwoff,
++ unsigned long data, unsigned int off,
++ snd_pcm_uframes_t frames)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int err;
++ void __user **bufs = (void __user **)data;
++ int channels = runtime->channels;
++ char __user *buf;
++ char *hwbuf;
++ int c;
++
++ if (substream->ops->copy_user) {
++ hwoff = samples_to_bytes(runtime, hwoff);
++ off = samples_to_bytes(runtime, off);
++ frames = samples_to_bytes(runtime, frames);
++ for (c = 0; c < channels; ++c, ++bufs) {
++ if (!*bufs)
++ continue;
++ err = substream->ops->copy_user(substream, c, hwoff,
++ *bufs + off, frames);
++ if (err < 0)
++ return err;
++ }
++ } else {
++ snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
++ for (c = 0; c < channels; ++c, ++bufs) {
++ if (*bufs == NULL)
++ continue;
++
++ hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
++ buf = *bufs + samples_to_bytes(runtime, off);
++ if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames)))
++ return -EFAULT;
++ }
++ }
++ return 0;
++}
++
+ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
+ unsigned long data,
+ snd_pcm_uframes_t size,
+@@ -2354,46 +2394,6 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u
+
+ EXPORT_SYMBOL(snd_pcm_lib_read);
+
+-static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
+- unsigned int hwoff,
+- unsigned long data, unsigned int off,
+- snd_pcm_uframes_t frames)
+-{
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- int err;
+- void __user **bufs = (void __user **)data;
+- int channels = runtime->channels;
+- char __user *buf;
+- char *hwbuf;
+- int c;
+-
+- if (substream->ops->copy_user) {
+- hwoff = samples_to_bytes(runtime, hwoff);
+- off = samples_to_bytes(runtime, off);
+- frames = samples_to_bytes(runtime, frames);
+- for (c = 0; c < channels; ++c, ++bufs) {
+- if (!*bufs)
+- continue;
+- err = substream->ops->copy_user(substream, c, hwoff,
+- *bufs + off, frames);
+- if (err < 0)
+- return err;
+- }
+- } else {
+- snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
+- for (c = 0; c < channels; ++c, ++bufs) {
+- if (*bufs == NULL)
+- continue;
+-
+- hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
+- buf = *bufs + samples_to_bytes(runtime, off);
+- if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames)))
+- return -EFAULT;
+- }
+- }
+- return 0;
+-}
+-
+ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+ void __user **bufs,
+ snd_pcm_uframes_t frames)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Simplify-check-for-dma_mmap_coherent-availa.patch b/patches.drivers/ALSA-pcm-Simplify-check-for-dma_mmap_coherent-availa.patch
new file mode 100644
index 0000000000..1705f1e615
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Simplify-check-for-dma_mmap_coherent-availa.patch
@@ -0,0 +1,40 @@
+From 85dc0f8554fa024b02eb50dcca71fa9881a45ea5 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 10 Jul 2017 16:05:58 +0200
+Subject: [PATCH] ALSA: pcm: Simplify check for dma_mmap_coherent() availability
+Git-commit: 85dc0f8554fa024b02eb50dcca71fa9881a45ea5
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+We check the availability of dma_mmap_coherent() in hw_support_mmap()
+but with an ugly ifdef of lots of arch-checks. Now we have a nice
+CONFIG_ARCH_NO_COHERENT_DMA_MMAP kconfig, and this can be used
+together with CONFIG_HAS_DMA check for a cleaner and more
+comprehensive check.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index b26c7e61d600..2a730f38e375 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -238,10 +238,8 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
+ {
+ if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
+ return false;
+- /* check architectures that return -EINVAL from dma_mmap_coherent() */
+- /* FIXME: this should be some global flag */
+-#if defined(CONFIG_C6X) || defined(CONFIG_FRV) || defined(CONFIG_MN10300) ||\
+- defined(CONFIG_PARISC) || defined(CONFIG_XTENSA)
++ /* architecture supports dma_mmap_coherent()? */
++#if defined(CONFIG_ARCH_NO_COHERENT_DMA_MMAP) || !defined(CONFIG_HAS_DMA)
+ if (!substream->ops->mmap &&
+ substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
+ return false;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Simplify-snd_pcm_playback_silence.patch b/patches.drivers/ALSA-pcm-Simplify-snd_pcm_playback_silence.patch
new file mode 100644
index 0000000000..3bff20f162
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Simplify-snd_pcm_playback_silence.patch
@@ -0,0 +1,102 @@
+From a9cd29e79965f0f769d13edcf2e9adb389698e7b Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 24 May 2017 18:18:15 +0200
+Subject: [PATCH] ALSA: pcm: Simplify snd_pcm_playback_silence()
+Git-commit: a9cd29e79965f0f769d13edcf2e9adb389698e7b
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Use the existing silence helper codes for simplification.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 50 ++++++++++++++++++--------------------------
+ 1 file changed, 20 insertions(+), 30 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index af73c629a6b2..f31949b20c0d 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -44,6 +44,9 @@
+ #define trace_hw_ptr_error(substream, reason)
+ #endif
+
++static int fill_silence_frames(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
++
+ /*
+ * fill ring buffer with silence
+ * runtime->silence_start: starting pointer to silence area
+@@ -57,7 +60,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t frames, ofs, transfer;
+- char *hwbuf;
+ int err;
+
+ if (runtime->silence_size < runtime->boundary) {
+@@ -111,35 +113,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
+ ofs = runtime->silence_start % runtime->buffer_size;
+ while (frames > 0) {
+ transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
+- if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
+- runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
+- if (substream->ops->fill_silence) {
+- err = substream->ops->fill_silence(substream, 0,
+- frames_to_bytes(runtime, ofs),
+- frames_to_bytes(runtime, transfer));
+- snd_BUG_ON(err < 0);
+- } else {
+- hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
+- snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
+- }
+- } else {
+- unsigned int c;
+- unsigned int channels = runtime->channels;
+- if (substream->ops->fill_silence) {
+- for (c = 0; c < channels; ++c) {
+- err = substream->ops->fill_silence(substream, c,
+- samples_to_bytes(runtime, ofs),
+- samples_to_bytes(runtime, transfer));
+- snd_BUG_ON(err < 0);
+- }
+- } else {
+- size_t dma_csize = runtime->dma_bytes / channels;
+- for (c = 0; c < channels; ++c) {
+- hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs);
+- snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
+- }
+- }
+- }
++ err = fill_silence_frames(substream, ofs, transfer);
++ snd_BUG_ON(err < 0);
+ runtime->silence_filled += transfer;
+ frames -= transfer;
+ ofs = 0;
+@@ -2103,6 +2078,21 @@ static int noninterleaved_copy(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
++/* fill silence on the given buffer position;
++ * called from snd_pcm_playback_silence()
++ */
++static int fill_silence_frames(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t off, snd_pcm_uframes_t frames)
++{
++ if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
++ substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
++ return interleaved_copy(substream, off, NULL, 0, frames,
++ fill_silence);
++ else
++ return noninterleaved_copy(substream, off, NULL, 0, frames,
++ fill_silence);
++}
++
+ /* sanity-check for read/write methods */
+ static int pcm_sanity_check(struct snd_pcm_substream *substream)
+ {
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Skip-ack-callback-without-actual-appl_ptr-u b/patches.drivers/ALSA-pcm-Skip-ack-callback-without-actual-appl_ptr-u
index 59bea6d2a3..0982f2a367 100644
--- a/patches.drivers/ALSA-pcm-Skip-ack-callback-without-actual-appl_ptr-u
+++ b/patches.drivers/ALSA-pcm-Skip-ack-callback-without-actual-appl_ptr-u
@@ -21,12 +21,12 @@ Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
- sound/core/pcm_native.c | 3 +++
+ sound/core/pcm_lib.c | 3 +++
1 file changed, 3 insertions(+)
---- a/sound/core/pcm_native.c
-+++ b/sound/core/pcm_native.c
-@@ -2462,6 +2462,9 @@ static int apply_appl_ptr(struct snd_pcm
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2111,6 +2111,9 @@ int pcm_lib_apply_appl_ptr(struct snd_pc
snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr;
int ret;
diff --git a/patches.drivers/ALSA-pcm-Unify-delay-calculation-in-snd_pcm_status-a.patch b/patches.drivers/ALSA-pcm-Unify-delay-calculation-in-snd_pcm_status-a.patch
new file mode 100644
index 0000000000..78d76fe30e
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Unify-delay-calculation-in-snd_pcm_status-a.patch
@@ -0,0 +1,84 @@
+From c99c5a3bb575f67700f9d1b216652750ea4a31a5 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 11 Apr 2018 18:07:27 +0200
+Subject: [PATCH] ALSA: pcm: Unify delay calculation in snd_pcm_status() and snd_pcm_delay()
+Git-commit: c99c5a3bb575f67700f9d1b216652750ea4a31a5
+Patch-mainline: v4.18-rc1
+References: bsc#1121278
+
+Yet another slight code cleanup: there are two places where
+calculating the PCM delay, and they can be unified in a single
+helper. It reduces the multiple open codes.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 37 ++++++++++++++++---------------------
+ 1 file changed, 16 insertions(+), 21 deletions(-)
+
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -857,6 +857,18 @@ static int snd_pcm_sw_params_user(struct
+ return err;
+ }
+
++static inline snd_pcm_uframes_t
++snd_pcm_calc_delay(struct snd_pcm_substream *substream)
++{
++ snd_pcm_uframes_t delay;
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ delay = snd_pcm_playback_hw_avail(substream->runtime);
++ else
++ delay = snd_pcm_capture_avail(substream->runtime);
++ return delay + substream->runtime->delay;
++}
++
+ int snd_pcm_status(struct snd_pcm_substream *substream,
+ struct snd_pcm_status *status)
+ {
+@@ -909,19 +921,8 @@ int snd_pcm_status(struct snd_pcm_substr
+ status->appl_ptr = runtime->control->appl_ptr;
+ status->hw_ptr = runtime->status->hw_ptr;
+ status->avail = snd_pcm_avail(substream);
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
+- runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+- status->delay = runtime->buffer_size - status->avail;
+- status->delay += runtime->delay;
+- } else
+- status->delay = 0;
+- } else {
+- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+- status->delay = status->avail + runtime->delay;
+- else
+- status->delay = 0;
+- }
++ status->delay = snd_pcm_running(substream) ?
++ snd_pcm_calc_delay(substream) : 0;
+ status->avail_max = runtime->avail_max;
+ status->overrange = runtime->overrange;
+ runtime->avail_max = 0;
+@@ -2656,19 +2657,13 @@ static int snd_pcm_hwsync(struct snd_pcm
+ static int snd_pcm_delay(struct snd_pcm_substream *substream,
+ snd_pcm_sframes_t *delay)
+ {
+- struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+ snd_pcm_sframes_t n = 0;
+
+ snd_pcm_stream_lock_irq(substream);
+ err = do_pcm_hwsync(substream);
+- if (!err) {
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- n = snd_pcm_playback_hw_avail(runtime);
+- else
+- n = snd_pcm_capture_avail(runtime);
+- n += runtime->delay;
+- }
++ if (!err)
++ n = snd_pcm_calc_delay(substream);
+ snd_pcm_stream_unlock_irq(substream);
+ if (!err)
+ *delay = n;
diff --git a/patches.drivers/ALSA-pcm-Unify-ioctl-functions-for-playback-and-capt.patch b/patches.drivers/ALSA-pcm-Unify-ioctl-functions-for-playback-and-capt.patch
new file mode 100644
index 0000000000..b17f9be81c
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Unify-ioctl-functions-for-playback-and-capt.patch
@@ -0,0 +1,378 @@
+From 67616feda99e32cb676b0907284bbb6957e45480 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 30 Aug 2017 15:39:32 +0200
+Subject: [PATCH] ALSA: pcm: Unify ioctl functions for playback and capture streams
+Git-commit: 67616feda99e32cb676b0907284bbb6957e45480
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+Some ioctl functions are implemented individually for both playback
+and capture streams although most of the codes are identical with just
+a few different stream-specific function calls. This patch unifies
+these places, removes the superfluous trivial check and flattens the
+call paths as a cleanup. Meanwhile, for better readability, some
+codes (e.g. xfer ioctls or forward/rewind ioctls) are factored out as
+functions.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_compat.c | 5 +-
+ sound/core/pcm_native.c | 283 +++++++++++++++-------------------------
+ 2 files changed, 105 insertions(+), 183 deletions(-)
+
+diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
+index 10f537f4d735..3a1cc7b97e46 100644
+--- a/sound/core/pcm_compat.c
++++ b/sound/core/pcm_compat.c
+@@ -689,10 +689,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
+ case SNDRV_PCM_IOCTL_XRUN:
+ case SNDRV_PCM_IOCTL_LINK:
+ case SNDRV_PCM_IOCTL_UNLINK:
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- return snd_pcm_playback_ioctl1(file, substream, cmd, argp);
+- else
+- return snd_pcm_capture_ioctl1(file, substream, cmd, argp);
++ return snd_pcm_common_ioctl(file, substream, cmd, argp);
+ case SNDRV_PCM_IOCTL_HW_REFINE32:
+ return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
+ case SNDRV_PCM_IOCTL_HW_PARAMS32:
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 621142ea9ec6..2fec2feac387 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -2761,14 +2761,103 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
+ runtime->tstamp_type = arg;
+ return 0;
+ }
+-
+-static int snd_pcm_common_ioctl1(struct file *file,
++
++static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream,
++ struct snd_xferi __user *_xferi)
++{
++ struct snd_xferi xferi;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ snd_pcm_sframes_t result;
++
++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
++ return -EBADFD;
++ if (put_user(0, &_xferi->result))
++ return -EFAULT;
++ if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
++ return -EFAULT;
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
++ else
++ result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
++ __put_user(result, &_xferi->result);
++ return result < 0 ? result : 0;
++}
++
++static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
++ struct snd_xfern __user *_xfern)
++{
++ struct snd_xfern xfern;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ void *bufs;
++ snd_pcm_sframes_t result;
++
++ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
++ return -EBADFD;
++ if (runtime->channels > 128)
++ return -EINVAL;
++ if (put_user(0, &_xfern->result))
++ return -EFAULT;
++ if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
++ return -EFAULT;
++
++ bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels);
++ if (IS_ERR(bufs))
++ return PTR_ERR(bufs);
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
++ else
++ result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
++ kfree(bufs);
++ __put_user(result, &_xfern->result);
++ return result < 0 ? result : 0;
++}
++
++static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t __user *_frames)
++{
++ snd_pcm_uframes_t frames;
++ snd_pcm_sframes_t result;
++
++ if (get_user(frames, _frames))
++ return -EFAULT;
++ if (put_user(0, _frames))
++ return -EFAULT;
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ result = snd_pcm_playback_rewind(substream, frames);
++ else
++ result = snd_pcm_capture_rewind(substream, frames);
++ __put_user(result, _frames);
++ return result < 0 ? result : 0;
++}
++
++static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t __user *_frames)
++{
++ snd_pcm_uframes_t frames;
++ snd_pcm_sframes_t result;
++
++ if (get_user(frames, _frames))
++ return -EFAULT;
++ if (put_user(0, _frames))
++ return -EFAULT;
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ result = snd_pcm_playback_forward(substream, frames);
++ else
++ result = snd_pcm_capture_forward(substream, frames);
++ __put_user(result, _frames);
++ return result < 0 ? result : 0;
++}
++
++static int snd_pcm_common_ioctl(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+ {
+ struct snd_pcm_file *pcm_file = file->private_data;
+ int res;
+
++ if (PCM_RUNTIME_CHECK(substream))
++ return -ENXIO;
++
+ res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0);
+ if (res < 0)
+ return res;
+@@ -2844,187 +2933,23 @@ static int snd_pcm_common_ioctl1(struct file *file,
+ return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
+ substream,
+ (int)(unsigned long)arg);
+- }
+- pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
+- return -ENOTTY;
+-}
+-
+-static int snd_pcm_playback_ioctl1(struct file *file,
+- struct snd_pcm_substream *substream,
+- unsigned int cmd, void __user *arg)
+-{
+- if (PCM_RUNTIME_CHECK(substream))
+- return -ENXIO;
+- if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
+- return -EINVAL;
+- switch (cmd) {
+ case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
+- {
+- struct snd_xferi xferi;
+- struct snd_xferi __user *_xferi = arg;
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- snd_pcm_sframes_t result;
+- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+- return -EBADFD;
+- if (put_user(0, &_xferi->result))
+- return -EFAULT;
+- if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
+- return -EFAULT;
+- result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
+- __put_user(result, &_xferi->result);
+- return result < 0 ? result : 0;
+- }
+- case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
+- {
+- struct snd_xfern xfern;
+- struct snd_xfern __user *_xfern = arg;
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- void __user **bufs;
+- snd_pcm_sframes_t result;
+- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+- return -EBADFD;
+- if (runtime->channels > 128)
+- return -EINVAL;
+- if (put_user(0, &_xfern->result))
+- return -EFAULT;
+- if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
+- return -EFAULT;
+-
+- bufs = memdup_user(xfern.bufs,
+- sizeof(void *) * runtime->channels);
+- if (IS_ERR(bufs))
+- return PTR_ERR(bufs);
+- result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
+- kfree(bufs);
+- __put_user(result, &_xfern->result);
+- return result < 0 ? result : 0;
+- }
+- case SNDRV_PCM_IOCTL_REWIND:
+- {
+- snd_pcm_uframes_t frames;
+- snd_pcm_uframes_t __user *_frames = arg;
+- snd_pcm_sframes_t result;
+- if (get_user(frames, _frames))
+- return -EFAULT;
+- if (put_user(0, _frames))
+- return -EFAULT;
+- result = snd_pcm_playback_rewind(substream, frames);
+- __put_user(result, _frames);
+- return result < 0 ? result : 0;
+- }
+- case SNDRV_PCM_IOCTL_FORWARD:
+- {
+- snd_pcm_uframes_t frames;
+- snd_pcm_uframes_t __user *_frames = arg;
+- snd_pcm_sframes_t result;
+- if (get_user(frames, _frames))
+- return -EFAULT;
+- if (put_user(0, _frames))
+- return -EFAULT;
+- result = snd_pcm_playback_forward(substream, frames);
+- __put_user(result, _frames);
+- return result < 0 ? result : 0;
+- }
+- }
+- return snd_pcm_common_ioctl1(file, substream, cmd, arg);
+-}
+-
+-static int snd_pcm_capture_ioctl1(struct file *file,
+- struct snd_pcm_substream *substream,
+- unsigned int cmd, void __user *arg)
+-{
+- if (PCM_RUNTIME_CHECK(substream))
+- return -ENXIO;
+- if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE))
+- return -EINVAL;
+- switch (cmd) {
+ case SNDRV_PCM_IOCTL_READI_FRAMES:
+- {
+- struct snd_xferi xferi;
+- struct snd_xferi __user *_xferi = arg;
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- snd_pcm_sframes_t result;
+- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+- return -EBADFD;
+- if (put_user(0, &_xferi->result))
+- return -EFAULT;
+- if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
+- return -EFAULT;
+- result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
+- __put_user(result, &_xferi->result);
+- return result < 0 ? result : 0;
+- }
++ return snd_pcm_xferi_frames_ioctl(substream, arg);
++ case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
+ case SNDRV_PCM_IOCTL_READN_FRAMES:
+- {
+- struct snd_xfern xfern;
+- struct snd_xfern __user *_xfern = arg;
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- void *bufs;
+- snd_pcm_sframes_t result;
+- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+- return -EBADFD;
+- if (runtime->channels > 128)
+- return -EINVAL;
+- if (put_user(0, &_xfern->result))
+- return -EFAULT;
+- if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
+- return -EFAULT;
+-
+- bufs = memdup_user(xfern.bufs,
+- sizeof(void *) * runtime->channels);
+- if (IS_ERR(bufs))
+- return PTR_ERR(bufs);
+- result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
+- kfree(bufs);
+- __put_user(result, &_xfern->result);
+- return result < 0 ? result : 0;
+- }
++ return snd_pcm_xfern_frames_ioctl(substream, arg);
+ case SNDRV_PCM_IOCTL_REWIND:
+- {
+- snd_pcm_uframes_t frames;
+- snd_pcm_uframes_t __user *_frames = arg;
+- snd_pcm_sframes_t result;
+- if (get_user(frames, _frames))
+- return -EFAULT;
+- if (put_user(0, _frames))
+- return -EFAULT;
+- result = snd_pcm_capture_rewind(substream, frames);
+- __put_user(result, _frames);
+- return result < 0 ? result : 0;
+- }
++ return snd_pcm_rewind_ioctl(substream, arg);
+ case SNDRV_PCM_IOCTL_FORWARD:
+- {
+- snd_pcm_uframes_t frames;
+- snd_pcm_uframes_t __user *_frames = arg;
+- snd_pcm_sframes_t result;
+- if (get_user(frames, _frames))
+- return -EFAULT;
+- if (put_user(0, _frames))
+- return -EFAULT;
+- result = snd_pcm_capture_forward(substream, frames);
+- __put_user(result, _frames);
+- return result < 0 ? result : 0;
++ return snd_pcm_forward_ioctl(substream, arg);
+ }
+- }
+- return snd_pcm_common_ioctl1(file, substream, cmd, arg);
+-}
+-
+-static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
+- unsigned long arg)
+-{
+- struct snd_pcm_file *pcm_file;
+-
+- pcm_file = file->private_data;
+-
+- if (((cmd >> 8) & 0xff) != 'A')
+- return -ENOTTY;
+-
+- return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
+- (void __user *)arg);
++ pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
++ return -ENOTTY;
+ }
+
+-static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
+- unsigned long arg)
++static long snd_pcm_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
+ {
+ struct snd_pcm_file *pcm_file;
+
+@@ -3033,8 +2958,8 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
+ if (((cmd >> 8) & 0xff) != 'A')
+ return -ENOTTY;
+
+- return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
+- (void __user *)arg);
++ return snd_pcm_common_ioctl(file, pcm_file->substream, cmd,
++ (void __user *)arg);
+ }
+
+ /**
+@@ -3775,7 +3700,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
+ .release = snd_pcm_release,
+ .llseek = no_llseek,
+ .poll = snd_pcm_playback_poll,
+- .unlocked_ioctl = snd_pcm_playback_ioctl,
++ .unlocked_ioctl = snd_pcm_ioctl,
+ .compat_ioctl = snd_pcm_ioctl_compat,
+ .mmap = snd_pcm_mmap,
+ .fasync = snd_pcm_fasync,
+@@ -3789,7 +3714,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
+ .release = snd_pcm_release,
+ .llseek = no_llseek,
+ .poll = snd_pcm_capture_poll,
+- .unlocked_ioctl = snd_pcm_capture_ioctl,
++ .unlocked_ioctl = snd_pcm_ioctl,
+ .compat_ioctl = snd_pcm_ioctl_compat,
+ .mmap = snd_pcm_mmap,
+ .fasync = snd_pcm_fasync,
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Unify-playback-and-capture-poll-callbacks.patch b/patches.drivers/ALSA-pcm-Unify-playback-and-capture-poll-callbacks.patch
new file mode 100644
index 0000000000..c3586a3551
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Unify-playback-and-capture-poll-callbacks.patch
@@ -0,0 +1,142 @@
+From 6448fcba2a7fe6856ba74bef623559a00267f54e Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 11 Apr 2018 18:05:00 +0200
+Subject: [PATCH] ALSA: pcm: Unify playback and capture poll callbacks
+Git-commit: 6448fcba2a7fe6856ba74bef623559a00267f54e
+Patch-mainline: v4.18-rc1
+References: bsc#1121278
+
+The poll callbacks for playback and capture directions are doing
+fairly similar but with a slight difference. This patch unifies the
+two functions into a single callback. The advantage of this
+refactoring is that the direction-specific procedures become clearer.
+
+There should be no functional change but only the code cleanup.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 74 ++++++++++++------------------------------------
+ 1 file changed, 19 insertions(+), 55 deletions(-)
+
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -3096,82 +3096,46 @@ static ssize_t snd_pcm_writev(struct kio
+ return result;
+ }
+
+-static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
++static unsigned int snd_pcm_poll(struct file *file, poll_table *wait)
+ {
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
+- unsigned int mask;
++ unsigned int mask, ok;
+ snd_pcm_uframes_t avail;
+
+ pcm_file = file->private_data;
+
+ substream = pcm_file->substream;
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ ok = POLLOUT | POLLWRNORM;
++ else
++ ok = POLLIN | POLLRDNORM;
+ if (PCM_RUNTIME_CHECK(substream))
+- return POLLOUT | POLLWRNORM | POLLERR;
+- runtime = substream->runtime;
+-
+- poll_wait(file, &runtime->sleep, wait);
+-
+- snd_pcm_stream_lock_irq(substream);
+- avail = snd_pcm_playback_avail(runtime);
+- switch (runtime->status->state) {
+- case SNDRV_PCM_STATE_RUNNING:
+- case SNDRV_PCM_STATE_PREPARED:
+- case SNDRV_PCM_STATE_PAUSED:
+- if (avail >= runtime->control->avail_min) {
+- mask = POLLOUT | POLLWRNORM;
+- break;
+- }
+- /* Fall through */
+- case SNDRV_PCM_STATE_DRAINING:
+- mask = 0;
+- break;
+- default:
+- mask = POLLOUT | POLLWRNORM | POLLERR;
+- break;
+- }
+- snd_pcm_stream_unlock_irq(substream);
+- return mask;
+-}
+-
+-static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
+-{
+- struct snd_pcm_file *pcm_file;
+- struct snd_pcm_substream *substream;
+- struct snd_pcm_runtime *runtime;
+- unsigned int mask;
+- snd_pcm_uframes_t avail;
+-
+- pcm_file = file->private_data;
++ return ok | POLLERR;
+
+- substream = pcm_file->substream;
+- if (PCM_RUNTIME_CHECK(substream))
+- return POLLIN | POLLRDNORM | POLLERR;
+ runtime = substream->runtime;
+-
+ poll_wait(file, &runtime->sleep, wait);
+
++ mask = 0;
+ snd_pcm_stream_lock_irq(substream);
+- avail = snd_pcm_capture_avail(runtime);
++ avail = snd_pcm_avail(substream);
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_RUNNING:
+ case SNDRV_PCM_STATE_PREPARED:
+ case SNDRV_PCM_STATE_PAUSED:
+- if (avail >= runtime->control->avail_min) {
+- mask = POLLIN | POLLRDNORM;
+- break;
+- }
+- mask = 0;
++ if (avail >= runtime->control->avail_min)
++ mask = ok;
+ break;
+ case SNDRV_PCM_STATE_DRAINING:
+- if (avail > 0) {
+- mask = POLLIN | POLLRDNORM;
+- break;
++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
++ mask = ok;
++ if (!avail)
++ mask |= POLLERR;
+ }
+- /* Fall through */
++ break;
+ default:
+- mask = POLLIN | POLLRDNORM | POLLERR;
++ mask = ok | POLLERR;
+ break;
+ }
+ snd_pcm_stream_unlock_irq(substream);
+@@ -3663,7 +3627,7 @@ const struct file_operations snd_pcm_f_o
+ .open = snd_pcm_playback_open,
+ .release = snd_pcm_release,
+ .llseek = no_llseek,
+- .poll = snd_pcm_playback_poll,
++ .poll = snd_pcm_poll,
+ .unlocked_ioctl = snd_pcm_ioctl,
+ .compat_ioctl = snd_pcm_ioctl_compat,
+ .mmap = snd_pcm_mmap,
+@@ -3677,7 +3641,7 @@ const struct file_operations snd_pcm_f_o
+ .open = snd_pcm_capture_open,
+ .release = snd_pcm_release,
+ .llseek = no_llseek,
+- .poll = snd_pcm_capture_poll,
++ .poll = snd_pcm_poll,
+ .unlocked_ioctl = snd_pcm_ioctl,
+ .compat_ioctl = snd_pcm_ioctl_compat,
+ .mmap = snd_pcm_mmap,
diff --git a/patches.drivers/ALSA-pcm-Unify-read-write-loop.patch b/patches.drivers/ALSA-pcm-Unify-read-write-loop.patch
new file mode 100644
index 0000000000..75ab032555
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Unify-read-write-loop.patch
@@ -0,0 +1,348 @@
+From 5c7264cfbb209efea04bbbd69b8b4f5f2fc5f86d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 24 May 2017 22:36:23 +0200
+Subject: [PATCH] ALSA: pcm: Unify read/write loop
+Git-commit: 5c7264cfbb209efea04bbbd69b8b4f5f2fc5f86d
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Both __snd_pcm_lib_read() and __snd_pcm_write() functions have almost
+the same code to loop over samples. For simplification, this patch
+unifies both as the single helper, __snd_pcm_lib_xfer().
+
+Other than that, there should be no functional change by this patch.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 13 ++-
+ sound/core/pcm_lib.c | 184 +++++++++++--------------------------------
+ 2 files changed, 51 insertions(+), 146 deletions(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 0fac948bb053..db649083c76d 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -1072,10 +1072,7 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream);
+ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg);
+ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
+-snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+- void *buf, bool interleaved,
+- snd_pcm_uframes_t frames);
+-snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
++snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ void *buf, bool interleaved,
+ snd_pcm_uframes_t frames);
+
+@@ -1083,28 +1080,28 @@ static inline snd_pcm_sframes_t
+ snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ const void __user *buf, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_write(substream, (void *)buf, true, frames);
++ return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
+ }
+
+ static inline snd_pcm_sframes_t
+ snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ void __user *buf, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_read(substream, (void *)buf, true, frames);
++ return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
+ }
+
+ static inline snd_pcm_sframes_t
+ snd_pcm_lib_writev(struct snd_pcm_substream *substream,
+ void __user **bufs, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_write(substream, (void *)bufs, false, frames);
++ return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
+ }
+
+ static inline snd_pcm_sframes_t
+ snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+ void __user **bufs, snd_pcm_uframes_t frames)
+ {
+- return __snd_pcm_lib_read(substream, (void *)bufs, false, frames);
++ return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
+ }
+
+ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 0c53a34201c1..af73c629a6b2 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2008,13 +2008,13 @@ static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
+ channel * (runtime->dma_bytes / runtime->channels);
+ }
+
+-/* default copy_user ops for write */
+-static int default_write_copy_user(struct snd_pcm_substream *substream,
+- int channel, unsigned long hwoff,
+- void __user *buf, unsigned long bytes)
++/* default copy_user ops for write; used for both interleaved and non- modes */
++static int default_write_copy(struct snd_pcm_substream *substream,
++ int channel, unsigned long hwoff,
++ void *buf, unsigned long bytes)
+ {
+ if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
+- buf, bytes))
++ (void __user *)buf, bytes))
+ return -EFAULT;
+ return 0;
+ }
+@@ -2040,6 +2040,18 @@ static int fill_silence(struct snd_pcm_substream *substream, int channel,
+ return 0;
+ }
+
++/* default copy_user ops for read; used for both interleaved and non- modes */
++static int default_read_copy(struct snd_pcm_substream *substream,
++ int channel, unsigned long hwoff,
++ void *buf, unsigned long bytes)
++{
++ if (copy_to_user((void __user *)buf,
++ get_dma_ptr(substream->runtime, channel, hwoff),
++ bytes))
++ return -EFAULT;
++ return 0;
++}
++
+ /* call transfer function with the converted pointers and sizes;
+ * for interleaved mode, it's one shot for all samples
+ */
+@@ -2121,9 +2133,10 @@ static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
+ }
+ }
+
+-snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+- void *data, bool interleaved,
+- snd_pcm_uframes_t size)
++/* the common loop for read/write data */
++snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
++ void *data, bool interleaved,
++ snd_pcm_uframes_t size)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t xfer = 0;
+@@ -2132,12 +2145,14 @@ snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ pcm_copy_f writer;
+ pcm_transfer_f transfer;
+ bool nonblock;
++ bool is_playback;
+ int err;
+
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
+
++ is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ if (interleaved) {
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
+ runtime->channels > 1)
+@@ -2150,12 +2165,16 @@ snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ }
+
+ if (!data) {
+- transfer = fill_silence;
++ if (is_playback)
++ transfer = fill_silence;
++ else
++ return -EINVAL;
+ } else {
+ if (substream->ops->copy_user)
+ transfer = (pcm_transfer_f)substream->ops->copy_user;
+ else
+- transfer = default_write_copy_user;
++ transfer = is_playback ?
++ default_write_copy : default_read_copy;
+ }
+
+ if (size == 0)
+@@ -2168,129 +2187,8 @@ snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ if (err < 0)
+ goto _end_unlock;
+
+- runtime->twake = runtime->control->avail_min ? : 1;
+- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+- snd_pcm_update_hw_ptr(substream);
+- avail = snd_pcm_playback_avail(runtime);
+- while (size > 0) {
+- snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
+- snd_pcm_uframes_t cont;
+- if (!avail) {
+- if (nonblock) {
+- err = -EAGAIN;
+- goto _end_unlock;
+- }
+- runtime->twake = min_t(snd_pcm_uframes_t, size,
+- runtime->control->avail_min ? : 1);
+- err = wait_for_avail(substream, &avail);
+- if (err < 0)
+- goto _end_unlock;
+- }
+- frames = size > avail ? avail : size;
+- cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
+- if (frames > cont)
+- frames = cont;
+- if (snd_BUG_ON(!frames)) {
+- runtime->twake = 0;
+- snd_pcm_stream_unlock_irq(substream);
+- return -EINVAL;
+- }
+- appl_ptr = runtime->control->appl_ptr;
+- appl_ofs = appl_ptr % runtime->buffer_size;
+- snd_pcm_stream_unlock_irq(substream);
+- err = writer(substream, appl_ofs, data, offset, frames,
+- transfer);
+- snd_pcm_stream_lock_irq(substream);
+- if (err < 0)
+- goto _end_unlock;
+- err = pcm_accessible_state(runtime);
+- if (err < 0)
+- goto _end_unlock;
+- appl_ptr += frames;
+- if (appl_ptr >= runtime->boundary)
+- appl_ptr -= runtime->boundary;
+- runtime->control->appl_ptr = appl_ptr;
+- if (substream->ops->ack)
+- substream->ops->ack(substream);
+-
+- offset += frames;
+- size -= frames;
+- xfer += frames;
+- avail -= frames;
+- if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+- snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
+- err = snd_pcm_start(substream);
+- if (err < 0)
+- goto _end_unlock;
+- }
+- }
+- _end_unlock:
+- runtime->twake = 0;
+- if (xfer > 0 && err >= 0)
+- snd_pcm_update_state(substream, runtime);
+- snd_pcm_stream_unlock_irq(substream);
+- return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
+-}
+-EXPORT_SYMBOL(__snd_pcm_lib_write);
+-
+-/* default copy_user ops for read */
+-static int default_read_copy_user(struct snd_pcm_substream *substream,
+- int channel, unsigned long hwoff,
+- void *buf, unsigned long bytes)
+-{
+- if (copy_to_user((void __user *)buf,
+- get_dma_ptr(substream->runtime, channel, hwoff),
+- bytes))
+- return -EFAULT;
+- return 0;
+-}
+-
+-snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+- void *data, bool interleaved,
+- snd_pcm_uframes_t size)
+-{
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- snd_pcm_uframes_t xfer = 0;
+- snd_pcm_uframes_t offset = 0;
+- snd_pcm_uframes_t avail;
+- pcm_copy_f reader;
+- pcm_transfer_f transfer;
+- bool nonblock;
+- int err;
+-
+- err = pcm_sanity_check(substream);
+- if (err < 0)
+- return err;
+-
+- if (!data)
+- return -EINVAL;
+-
+- if (interleaved) {
+- if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
+- runtime->channels > 1)
+- return -EINVAL;
+- reader = interleaved_copy;
+- } else {
+- if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+- return -EINVAL;
+- reader = noninterleaved_copy;
+- }
+-
+- if (substream->ops->copy_user)
+- transfer = (pcm_transfer_f)substream->ops->copy_user;
+- else
+- transfer = default_read_copy_user;
+-
+- if (size == 0)
+- return 0;
+-
+- nonblock = !!(substream->f_flags & O_NONBLOCK);
+-
+- snd_pcm_stream_lock_irq(substream);
+- err = pcm_accessible_state(runtime);
+- if (err < 0)
+- goto _end_unlock;
+- if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
++ if (!is_playback &&
++ runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+ size >= runtime->start_threshold) {
+ err = snd_pcm_start(substream);
+ if (err < 0)
+@@ -2300,13 +2198,16 @@ snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ runtime->twake = runtime->control->avail_min ? : 1;
+ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+ snd_pcm_update_hw_ptr(substream);
+- avail = snd_pcm_capture_avail(runtime);
++ if (is_playback)
++ avail = snd_pcm_playback_avail(runtime);
++ else
++ avail = snd_pcm_capture_avail(runtime);
+ while (size > 0) {
+ snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
+ snd_pcm_uframes_t cont;
+ if (!avail) {
+- if (runtime->status->state ==
+- SNDRV_PCM_STATE_DRAINING) {
++ if (!is_playback &&
++ runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
+ goto _end_unlock;
+ }
+@@ -2334,7 +2235,7 @@ snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ appl_ptr = runtime->control->appl_ptr;
+ appl_ofs = appl_ptr % runtime->buffer_size;
+ snd_pcm_stream_unlock_irq(substream);
+- err = reader(substream, appl_ofs, data, offset, frames,
++ err = writer(substream, appl_ofs, data, offset, frames,
+ transfer);
+ snd_pcm_stream_lock_irq(substream);
+ if (err < 0)
+@@ -2353,6 +2254,13 @@ snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ size -= frames;
+ xfer += frames;
+ avail -= frames;
++ if (is_playback &&
++ runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
++ snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
++ err = snd_pcm_start(substream);
++ if (err < 0)
++ goto _end_unlock;
++ }
+ }
+ _end_unlock:
+ runtime->twake = 0;
+@@ -2361,7 +2269,7 @@ snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+ snd_pcm_stream_unlock_irq(substream);
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
+ }
+-EXPORT_SYMBOL(__snd_pcm_lib_read);
++EXPORT_SYMBOL(__snd_pcm_lib_xfer);
+
+ /*
+ * standard channel mapping helpers
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Update-hardware-pointer-before-start-captur.patch b/patches.drivers/ALSA-pcm-Update-hardware-pointer-before-start-captur.patch
new file mode 100644
index 0000000000..96aa24c8dc
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Update-hardware-pointer-before-start-captur.patch
@@ -0,0 +1,49 @@
+From 64b6acf60b665fffd419c23886a1cbeeb253cfb4 Mon Sep 17 00:00:00 2001
+From: Ricardo Biehl Pasquali <pasqualirb@gmail.com>
+Date: Fri, 7 Sep 2018 16:58:54 -0300
+Subject: [PATCH] ALSA: pcm: Update hardware pointer before start capture
+Git-commit: 64b6acf60b665fffd419c23886a1cbeeb253cfb4
+Patch-mainline: v4.20-rc1
+References: bsc#1121278
+
+This ensures the transfer loop won't waste a run to read
+the few frames (if any) between start and hw_ptr update.
+It will wait for the next interrupt with wait_for_avail().
+
+Signed-off-by: Ricardo Biehl Pasquali <pasqualirb@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 7f71c2449af5..40013b26f671 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2172,6 +2172,10 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ if (err < 0)
+ goto _end_unlock;
+
++ runtime->twake = runtime->control->avail_min ? : 1;
++ if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
++ snd_pcm_update_hw_ptr(substream);
++
+ if (!is_playback &&
+ runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
+ if (size >= runtime->start_threshold) {
+@@ -2185,10 +2189,8 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ }
+ }
+
+- runtime->twake = runtime->control->avail_min ? : 1;
+- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+- snd_pcm_update_hw_ptr(substream);
+ avail = snd_pcm_avail(substream);
++
+ while (size > 0) {
+ snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
+ snd_pcm_uframes_t cont;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Use-ERESTARTSYS-instead-of-EINTR-in-OSS-emu.patch b/patches.drivers/ALSA-pcm-Use-ERESTARTSYS-instead-of-EINTR-in-OSS-emu.patch
new file mode 100644
index 0000000000..02e269fbaa
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Use-ERESTARTSYS-instead-of-EINTR-in-OSS-emu.patch
@@ -0,0 +1,33 @@
+From c64ed5dd9feba193c76eb460b451225ac2a0d87b Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 9 Jan 2018 08:51:02 +0100
+Subject: [PATCH] ALSA: pcm: Use ERESTARTSYS instead of EINTR in OSS emulation
+Git-commit: c64ed5dd9feba193c76eb460b451225ac2a0d87b
+Patch-mainline: v4.16-rc1
+References: bsc#1121278
+
+Fix the last standing EINTR in the whole subsystem. Use more correct
+ERESTARTSYS for pending signals.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_oss.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index c7d8489d39c8..e8b19876c420 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -842,7 +842,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
+ if (!(mutex_trylock(&runtime->oss.params_lock)))
+ return -EAGAIN;
+ } else if (mutex_lock_interruptible(&runtime->oss.params_lock))
+- return -EINTR;
++ return -ERESTARTSYS;
+ sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL);
+ params = kmalloc(sizeof(*params), GFP_KERNEL);
+ sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Use-common-PCM_RUNTIME_CHECK-for-sanity-che.patch b/patches.drivers/ALSA-pcm-Use-common-PCM_RUNTIME_CHECK-for-sanity-che.patch
new file mode 100644
index 0000000000..cf2a5c3a32
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Use-common-PCM_RUNTIME_CHECK-for-sanity-che.patch
@@ -0,0 +1,42 @@
+From 4e99151435cb2e88b6d0d49939bf836c35e555a3 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 24 May 2016 15:53:36 +0200
+Subject: [PATCH] ALSA: pcm: Use common PCM_RUNTIME_CHECK() for sanity checks
+Git-commit: 4e99151435cb2e88b6d0d49939bf836c35e555a3
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Just a code cleanup.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 0941b9c92b3f..05858c91c0ea 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -2869,7 +2869,7 @@ static int snd_pcm_playback_ioctl1(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+ {
+- if (snd_BUG_ON(!substream))
++ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
+ if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
+ return -EINVAL;
+@@ -2949,7 +2949,7 @@ static int snd_pcm_capture_ioctl1(struct file *file,
+ struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+ {
+- if (snd_BUG_ON(!substream))
++ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
+ if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE))
+ return -EINVAL;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Use-common-error-handling-code-in-_snd_pcm_.patch b/patches.drivers/ALSA-pcm-Use-common-error-handling-code-in-_snd_pcm_.patch
new file mode 100644
index 0000000000..422e50e56b
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Use-common-error-handling-code-in-_snd_pcm_.patch
@@ -0,0 +1,67 @@
+From 97d15a141f84a02d40d2ee442df5c6bd2f62b3d8 Mon Sep 17 00:00:00 2001
+From: Markus Elfring <elfring@users.sourceforge.net>
+Date: Wed, 23 Aug 2017 08:40:37 +0200
+Subject: [PATCH] ALSA: pcm: Use common error handling code in _snd_pcm_new()
+Git-commit: 97d15a141f84a02d40d2ee442df5c6bd2f62b3d8
+Patch-mainline: v4.14-rc1
+References: bsc#1121278
+
+Add a jump target so that a bit of exception handling can be better reused
+at the end of this function.
+
+This issue was detected by using the Coccinelle software.
+
+Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm.c | 30 ++++++++++++++++++------------
+ 1 file changed, 18 insertions(+), 12 deletions(-)
+
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index 89c7485519cb..048df9658f50 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -783,21 +783,27 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
+ INIT_LIST_HEAD(&pcm->list);
+ if (id)
+ strlcpy(pcm->id, id, sizeof(pcm->id));
+- if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
+- snd_pcm_free(pcm);
+- return err;
+- }
+- if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count)) < 0) {
+- snd_pcm_free(pcm);
+- return err;
+- }
+- if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) {
+- snd_pcm_free(pcm);
+- return err;
+- }
++
++ err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ playback_count);
++ if (err < 0)
++ goto free_pcm;
++
++ err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count);
++ if (err < 0)
++ goto free_pcm;
++
++ err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops);
++ if (err < 0)
++ goto free_pcm;
++
+ if (rpcm)
+ *rpcm = pcm;
+ return 0;
++
++free_pcm:
++ snd_pcm_free(pcm);
++ return err;
+ }
+
+ /**
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Use-krealloc-for-resizing-the-rules-array.patch b/patches.drivers/ALSA-pcm-Use-krealloc-for-resizing-the-rules-array.patch
new file mode 100644
index 0000000000..4119db940a
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Use-krealloc-for-resizing-the-rules-array.patch
@@ -0,0 +1,44 @@
+From 09b9ddfaa18317f463085d602cf5f60a5fa88665 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 13 Mar 2018 11:31:25 +0100
+Subject: [PATCH] ALSA: pcm: Use krealloc() for resizing the rules array
+Git-commit: 09b9ddfaa18317f463085d602cf5f60a5fa88665
+Patch-mainline: v4.17-rc1
+References: bsc#1121278
+
+Just a minor simplification. Change from kcalloc() shouldn't matter
+as each array element is fully initialized.
+
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index a83152e7d387..f4a19509cccf 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1129,16 +1129,12 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
+ if (constrs->rules_num >= constrs->rules_all) {
+ struct snd_pcm_hw_rule *new;
+ unsigned int new_rules = constrs->rules_all + 16;
+- new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL);
++ new = krealloc(constrs->rules, new_rules * sizeof(*c),
++ GFP_KERNEL);
+ if (!new) {
+ va_end(args);
+ return -ENOMEM;
+ }
+- if (constrs->rules) {
+- memcpy(new, constrs->rules,
+- constrs->rules_num * sizeof(*c));
+- kfree(constrs->rules);
+- }
+ constrs->rules = new;
+ constrs->rules_all = new_rules;
+ }
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Use-snd_pcm_stop_xrun-for-xrun-injection.patch b/patches.drivers/ALSA-pcm-Use-snd_pcm_stop_xrun-for-xrun-injection.patch
new file mode 100644
index 0000000000..9b8f63b2ff
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Use-snd_pcm_stop_xrun-for-xrun-injection.patch
@@ -0,0 +1,57 @@
+From e647f5a5c5d165c87750e8c0dcbe341b5a378ffd Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 4 Jul 2018 15:08:05 +0200
+Subject: [PATCH] ALSA: pcm: Use snd_pcm_stop_xrun() for xrun injection
+Git-commit: e647f5a5c5d165c87750e8c0dcbe341b5a378ffd
+Patch-mainline: v4.19-rc1
+References: bsc#1121278
+
+Basically the xrun injection routine can simply call the standard
+helper snd_pcm_stop_xrun(), but with one exception: it may be called
+even when the stream is closed.
+
+Make snd_pcm_stop_xrun() more robust and check the NULL runtime state,
+and simplify xrun injection code by calling it.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm.c | 7 +------
+ sound/core/pcm_native.c | 2 +-
+ 2 files changed, 2 insertions(+), 7 deletions(-)
+
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index 6f037a4b8b52..fdb9b92fc8d6 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -492,13 +492,8 @@ static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+ {
+ struct snd_pcm_substream *substream = entry->private_data;
+- struct snd_pcm_runtime *runtime;
+
+- snd_pcm_stream_lock_irq(substream);
+- runtime = substream->runtime;
+- if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+- __snd_pcm_xrun(substream);
+- snd_pcm_stream_unlock_irq(substream);
++ snd_pcm_stop_xrun(substream);
+ }
+
+ static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry,
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 20174d0c0527..66c90f486af9 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1339,7 +1339,7 @@ int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
+ unsigned long flags;
+
+ snd_pcm_stream_lock_irqsave(substream, flags);
+- if (snd_pcm_running(substream))
++ if (substream->runtime && snd_pcm_running(substream))
+ __snd_pcm_xrun(substream);
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+ return 0;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Use-standard-lower_32_bits-and-upper_32_bit.patch b/patches.drivers/ALSA-pcm-Use-standard-lower_32_bits-and-upper_32_bit.patch
new file mode 100644
index 0000000000..42b512da5f
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-Use-standard-lower_32_bits-and-upper_32_bit.patch
@@ -0,0 +1,39 @@
+From 191bb51e72c3b2b1ed1b2bd7ac30dd9f7ccea306 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 25 Jul 2018 23:00:55 +0200
+Subject: [PATCH] ALSA: pcm: Use standard lower_32_bits() and upper_32_bits()
+Git-commit: 191bb51e72c3b2b1ed1b2bd7ac30dd9f7ccea306
+Patch-mainline: v4.19-rc1
+References: bsc#1121278
+
+Instead of open codes, use the standard macros for obtaining the lower
+and upper 32bit values.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_plugin.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
+index 85a56af104bd..85bab922ce69 100644
+--- a/sound/core/oss/pcm_plugin.c
++++ b/sound/core/oss/pcm_plugin.c
+@@ -281,10 +281,10 @@ static int snd_pcm_plug_formats(const struct snd_mask *mask,
+ SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
+ snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW);
+
+- if (formats.bits[0] & (u32)linfmts)
+- formats.bits[0] |= (u32)linfmts;
+- if (formats.bits[1] & (u32)(linfmts >> 32))
+- formats.bits[1] |= (u32)(linfmts >> 32);
++ if (formats.bits[0] & lower_32_bits(linfmts))
++ formats.bits[0] |= lower_32_bits(linfmts);
++ if (formats.bits[1] & upper_32_bits(linfmts))
++ formats.bits[1] |= upper_32_bits(linfmts);
+ return snd_mask_test(&formats, (__force int)format);
+ }
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-Workaround-for-weird-PulseAudio-behavior-on b/patches.drivers/ALSA-pcm-Workaround-for-weird-PulseAudio-behavior-on
index 8552333244..69ae73d49a 100644
--- a/patches.drivers/ALSA-pcm-Workaround-for-weird-PulseAudio-behavior-on
+++ b/patches.drivers/ALSA-pcm-Workaround-for-weird-PulseAudio-behavior-on
@@ -33,7 +33,7 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
-@@ -2493,7 +2493,7 @@ static snd_pcm_sframes_t forward_appl_pt
+@@ -2618,7 +2618,7 @@ static snd_pcm_sframes_t forward_appl_pt
return ret < 0 ? ret : frames;
}
@@ -42,10 +42,10 @@ Signed-off-by: Takashi Iwai <tiwai@suse.de>
static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames,
snd_pcm_sframes_t avail)
-@@ -2510,7 +2510,12 @@ static snd_pcm_sframes_t rewind_appl_ptr
+@@ -2635,7 +2635,12 @@ static snd_pcm_sframes_t rewind_appl_ptr
if (appl_ptr < 0)
appl_ptr += runtime->boundary;
- ret = apply_appl_ptr(substream, appl_ptr);
+ ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
- return ret < 0 ? ret : frames;
+ /* NOTE: we return zero for errors because PulseAudio gets depressed
+ * upon receiving an error from rewind ioctl and stops processing
diff --git a/patches.drivers/ALSA-pcm-adaption-of-code-formatting.patch b/patches.drivers/ALSA-pcm-adaption-of-code-formatting.patch
new file mode 100644
index 0000000000..03e3987644
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-adaption-of-code-formatting.patch
@@ -0,0 +1,69 @@
+From a1c06e39a9373501b4f28caf37fbccba52532f79 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 06:37:04 +0900
+Subject: [PATCH] ALSA: pcm: adaption of code formatting
+Git-commit: a1c06e39a9373501b4f28caf37fbccba52532f79
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+This commit modifies current for readability in below aspects:
+ - use bool type variable instead of int type variable assigned to 0/1
+ - move variable definition from loop to top of the function definition
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index db4cdd114ed4..40560e579d33 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -328,9 +328,11 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ unsigned int rstamps[constrs->rules_num];
+ unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
+ unsigned int stamp = 2;
++ struct snd_pcm_hw_rule *r;
++ unsigned int d;
+ struct snd_mask old_mask;
+ struct snd_interval old_interval;
+- int again;
++ bool again;
+ int changed;
+
+ for (k = 0; k < constrs->rules_num; k++)
+@@ -338,10 +340,9 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
+ vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
+ retry:
+- again = 0;
++ again = false;
+ for (k = 0; k < constrs->rules_num; k++) {
+- struct snd_pcm_hw_rule *r = &constrs->rules[k];
+- unsigned int d;
++ r = &constrs->rules[k];
+ if (r->cond && !(r->cond & params->flags))
+ continue;
+ for (d = 0; r->deps[d] >= 0; d++) {
+@@ -375,7 +376,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ if (changed && r->var >= 0) {
+ params->cmask |= (1 << r->var);
+ vstamps[r->var] = stamp;
+- again = 1;
++ again = true;
+ }
+ if (changed < 0)
+ return changed;
+@@ -453,7 +454,6 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ params->rmask = 0;
+ return 0;
+ }
+-
+ EXPORT_SYMBOL(snd_pcm_hw_refine);
+
+ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-add-SNDRV_PCM_FORMAT_-S-U-20.patch b/patches.drivers/ALSA-pcm-add-SNDRV_PCM_FORMAT_-S-U-20.patch
new file mode 100644
index 0000000000..7cf339ff61
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-add-SNDRV_PCM_FORMAT_-S-U-20.patch
@@ -0,0 +1,143 @@
+From 823dbb6eb08a2865bcd236b4f52b1b9de216418a Mon Sep 17 00:00:00 2001
+From: "Maciej S. Szmigiero" <mail@maciej.szmigiero.name>
+Date: Mon, 27 Nov 2017 23:33:29 +0100
+Subject: [PATCH] ALSA: pcm: add SNDRV_PCM_FORMAT_{S,U}20
+Git-commit: 823dbb6eb08a2865bcd236b4f52b1b9de216418a
+Patch-mainline: v4.16-rc1
+References: bsc#1121278
+
+This format is similar to existing SNDRV_PCM_FORMAT_{S,U}20_3 that keep
+20-bit PCM samples in 3 bytes, however i.MX6 platform SSI FIFO does not
+allow 3-byte accesses (including DMA) so a 4-byte (more conventional)
+format is needed for it.
+
+Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 8 ++++++++
+ include/sound/soc-dai.h | 2 ++
+ include/uapi/sound/asound.h | 9 +++++++++
+ sound/core/pcm_misc.c | 19 ++++++++++++++++++-
+ 4 files changed, 37 insertions(+), 1 deletion(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 24febf9e177c..e054c583d3b3 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -169,6 +169,10 @@ struct snd_pcm_ops {
+ #define SNDRV_PCM_FMTBIT_IMA_ADPCM _SNDRV_PCM_FMTBIT(IMA_ADPCM)
+ #define SNDRV_PCM_FMTBIT_MPEG _SNDRV_PCM_FMTBIT(MPEG)
+ #define SNDRV_PCM_FMTBIT_GSM _SNDRV_PCM_FMTBIT(GSM)
++#define SNDRV_PCM_FMTBIT_S20_LE _SNDRV_PCM_FMTBIT(S20_LE)
++#define SNDRV_PCM_FMTBIT_U20_LE _SNDRV_PCM_FMTBIT(U20_LE)
++#define SNDRV_PCM_FMTBIT_S20_BE _SNDRV_PCM_FMTBIT(S20_BE)
++#define SNDRV_PCM_FMTBIT_U20_BE _SNDRV_PCM_FMTBIT(U20_BE)
+ #define SNDRV_PCM_FMTBIT_SPECIAL _SNDRV_PCM_FMTBIT(SPECIAL)
+ #define SNDRV_PCM_FMTBIT_S24_3LE _SNDRV_PCM_FMTBIT(S24_3LE)
+ #define SNDRV_PCM_FMTBIT_U24_3LE _SNDRV_PCM_FMTBIT(U24_3LE)
+@@ -202,6 +206,8 @@ struct snd_pcm_ops {
+ #define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_LE
+ #define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_LE
+ #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
++#define SNDRV_PCM_FMTBIT_S20 SNDRV_PCM_FMTBIT_S20_LE
++#define SNDRV_PCM_FMTBIT_U20 SNDRV_PCM_FMTBIT_U20_LE
+ #endif
+ #ifdef SNDRV_BIG_ENDIAN
+ #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_BE
+@@ -213,6 +219,8 @@ struct snd_pcm_ops {
+ #define SNDRV_PCM_FMTBIT_FLOAT SNDRV_PCM_FMTBIT_FLOAT_BE
+ #define SNDRV_PCM_FMTBIT_FLOAT64 SNDRV_PCM_FMTBIT_FLOAT64_BE
+ #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE
++#define SNDRV_PCM_FMTBIT_S20 SNDRV_PCM_FMTBIT_S20_BE
++#define SNDRV_PCM_FMTBIT_U20 SNDRV_PCM_FMTBIT_U20_BE
+ #endif
+
+ struct snd_pcm_file {
+diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
+index 58acd00cae19..d970879944fc 100644
+--- a/include/sound/soc-dai.h
++++ b/include/sound/soc-dai.h
+@@ -102,6 +102,8 @@ struct snd_compr_stream;
+ SNDRV_PCM_FMTBIT_S16_BE |\
+ SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S20_3BE |\
++ SNDRV_PCM_FMTBIT_S20_LE |\
++ SNDRV_PCM_FMTBIT_S20_BE |\
+ SNDRV_PCM_FMTBIT_S24_3LE |\
+ SNDRV_PCM_FMTBIT_S24_3BE |\
+ SNDRV_PCM_FMTBIT_S32_LE |\
+diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
+index c227ccba60ae..07d61583fd02 100644
+--- a/include/uapi/sound/asound.h
++++ b/include/uapi/sound/asound.h
+@@ -214,6 +214,11 @@ typedef int __bitwise snd_pcm_format_t;
+ #define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
+ #define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
+ #define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
++#define SNDRV_PCM_FORMAT_S20_LE ((__force snd_pcm_format_t) 25) /* in four bytes, LSB justified */
++#define SNDRV_PCM_FORMAT_S20_BE ((__force snd_pcm_format_t) 26) /* in four bytes, LSB justified */
++#define SNDRV_PCM_FORMAT_U20_LE ((__force snd_pcm_format_t) 27) /* in four bytes, LSB justified */
++#define SNDRV_PCM_FORMAT_U20_BE ((__force snd_pcm_format_t) 28) /* in four bytes, LSB justified */
++/* gap in the numbering for a future standard linear format */
+ #define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
+ #define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
+ #define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
+@@ -248,6 +253,8 @@ typedef int __bitwise snd_pcm_format_t;
+ #define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
+ #define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
+ #define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
++#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_LE
++#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_LE
+ #endif
+ #ifdef SNDRV_BIG_ENDIAN
+ #define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
+@@ -259,6 +266,8 @@ typedef int __bitwise snd_pcm_format_t;
+ #define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
+ #define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
+ #define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
++#define SNDRV_PCM_FORMAT_S20 SNDRV_PCM_FORMAT_S20_BE
++#define SNDRV_PCM_FORMAT_U20 SNDRV_PCM_FORMAT_U20_BE
+ #endif
+
+ typedef int __bitwise snd_pcm_subformat_t;
+diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
+index 9be81025372f..c4eb561d2008 100644
+--- a/sound/core/pcm_misc.c
++++ b/sound/core/pcm_misc.c
+@@ -163,13 +163,30 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
+ .width = 32, .phys = 32, .le = 0, .signd = 0,
+ .silence = { 0x69, 0x69, 0x69, 0x69 },
+ },
+- /* FIXME: the following three formats are not defined properly yet */
++ /* FIXME: the following two formats are not defined properly yet */
+ [SNDRV_PCM_FORMAT_MPEG] = {
+ .le = -1, .signd = -1,
+ },
+ [SNDRV_PCM_FORMAT_GSM] = {
+ .le = -1, .signd = -1,
+ },
++ [SNDRV_PCM_FORMAT_S20_LE] = {
++ .width = 20, .phys = 32, .le = 1, .signd = 1,
++ .silence = {},
++ },
++ [SNDRV_PCM_FORMAT_S20_BE] = {
++ .width = 20, .phys = 32, .le = 0, .signd = 1,
++ .silence = {},
++ },
++ [SNDRV_PCM_FORMAT_U20_LE] = {
++ .width = 20, .phys = 32, .le = 1, .signd = 0,
++ .silence = { 0x00, 0x00, 0x08, 0x00 },
++ },
++ [SNDRV_PCM_FORMAT_U20_BE] = {
++ .width = 20, .phys = 32, .le = 0, .signd = 0,
++ .silence = { 0x00, 0x08, 0x00, 0x00 },
++ },
++ /* FIXME: the following format is not defined properly yet */
+ [SNDRV_PCM_FORMAT_SPECIAL] = {
+ .le = -1, .signd = -1,
+ },
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-add-a-helper-function-to-apply-parameter-ru.patch b/patches.drivers/ALSA-pcm-add-a-helper-function-to-apply-parameter-ru.patch
new file mode 100644
index 0000000000..13beea1c27
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-add-a-helper-function-to-apply-parameter-ru.patch
@@ -0,0 +1,137 @@
+From 9cc07f55d42be47ad2b06dae9541d9fd964c3287 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 06:37:01 +0900
+Subject: [PATCH] ALSA: pcm: add a helper function to apply parameter rules
+Git-commit: 9cc07f55d42be47ad2b06dae9541d9fd964c3287
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Application of rules to parameters of PCM substream is done in a call of
+snd_pcm_hw_refine(), while the function includes much codes and is not
+enough friendly to readers.
+
+This commit splits the codes to a separated function so that readers can
+get it easily. I leave desicion into compilers to merge the function into
+its callee.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 77 ++++++++++++++++++++++++-----------------
+ 1 file changed, 45 insertions(+), 32 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 7e811ace6bf2..000e6e9a0c2b 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -319,43 +319,23 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
+-int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+- struct snd_pcm_hw_params *params)
++static int constrain_params_by_rules(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
+ {
++ struct snd_pcm_hw_constraints *constrs =
++ &substream->runtime->hw_constraints;
+ unsigned int k;
+- struct snd_pcm_hardware *hw;
+- struct snd_interval *i = NULL;
+- struct snd_mask *m = NULL;
+- struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints;
+ unsigned int rstamps[constrs->rules_num];
+ unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
+ unsigned int stamp = 2;
+- int changed, again;
+- int err;
+-
+- struct snd_mask __maybe_unused old_mask;
+- struct snd_interval __maybe_unused old_interval;
+-
+- params->info = 0;
+- params->fifo_size = 0;
+- if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
+- params->msbits = 0;
+- if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
+- params->rate_num = 0;
+- params->rate_den = 0;
+- }
+-
+- err = constrain_mask_params(substream, params);
+- if (err < 0)
+- return err;
+-
+- err = constrain_interval_params(substream, params);
+- if (err < 0)
+- return err;
++ struct snd_mask old_mask;
++ struct snd_interval old_interval;
++ int again;
++ int changed;
+
+ for (k = 0; k < constrs->rules_num; k++)
+ rstamps[k] = 0;
+- for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
++ for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
+ vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
+ do {
+ again = 0;
+@@ -405,6 +385,39 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ stamp++;
+ }
+ } while (again);
++
++ return 0;
++}
++
++int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_pcm_hardware *hw;
++ struct snd_interval *i = NULL;
++ struct snd_mask *m = NULL;
++ int err;
++
++ params->info = 0;
++ params->fifo_size = 0;
++ if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
++ params->msbits = 0;
++ if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
++ params->rate_num = 0;
++ params->rate_den = 0;
++ }
++
++ err = constrain_mask_params(substream, params);
++ if (err < 0)
++ return err;
++
++ err = constrain_interval_params(substream, params);
++ if (err < 0)
++ return err;
++
++ err = constrain_params_by_rules(substream, params);
++ if (err < 0)
++ return err;
++
+ if (!params->msbits) {
+ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
+ if (snd_interval_single(i))
+@@ -432,10 +445,10 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ if (snd_mask_min(m) == snd_mask_max(m) &&
+ snd_interval_min(i) == snd_interval_max(i)) {
+- changed = substream->ops->ioctl(substream,
++ err = substream->ops->ioctl(substream,
+ SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
+- if (changed < 0)
+- return changed;
++ if (err < 0)
++ return err;
+ }
+ }
+ params->rmask = 0;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-add-a-helper-function-to-constrain-interval.patch b/patches.drivers/ALSA-pcm-add-a-helper-function-to-constrain-interval.patch
new file mode 100644
index 0000000000..e1435b6a0b
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-add-a-helper-function-to-constrain-interval.patch
@@ -0,0 +1,99 @@
+From 3432fa040211660989844209b67b414185003004 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 06:37:00 +0900
+Subject: [PATCH] ALSA: pcm: add a helper function to constrain interval-type parameters
+Git-commit: 3432fa040211660989844209b67b414185003004
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Application of constraints to interval-type parameters for PCM substream
+is done in a call of snd_pcm_hw_refine(), while the function includes
+much codes and is not enough friendly to readers.
+
+This commit splits the codes to a separated function so that readers can
+get it easily. I leave desicion into compilers to merge the function into
+its callee.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 55 +++++++++++++++++++++++++++--------------
+ 1 file changed, 36 insertions(+), 19 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 1dee5f960fbe..7e811ace6bf2 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -286,6 +286,39 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
++static int constrain_interval_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_pcm_hw_constraints *constrs =
++ &substream->runtime->hw_constraints;
++ struct snd_interval *i;
++ unsigned int k;
++ struct snd_interval old_interval;
++ int changed;
++
++ for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
++ i = hw_param_interval(params, k);
++ if (snd_interval_empty(i))
++ return -EINVAL;
++ if (!(params->rmask & (1 << k)))
++ continue;
++
++ if (trace_hw_interval_param_enabled())
++ old_interval = *i;
++
++ changed = snd_interval_refine(i, constrs_interval(constrs, k));
++
++ trace_hw_interval_param(substream, k, 0, &old_interval, i);
++
++ if (changed)
++ params->cmask |= 1 << k;
++ if (changed < 0)
++ return changed;
++ }
++
++ return 0;
++}
++
+ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+@@ -316,25 +349,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ if (err < 0)
+ return err;
+
+- for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
+- i = hw_param_interval(params, k);
+- if (snd_interval_empty(i))
+- return -EINVAL;
+- if (!(params->rmask & (1 << k)))
+- continue;
+-
+- if (trace_hw_interval_param_enabled())
+- old_interval = *i;
+-
+- changed = snd_interval_refine(i, constrs_interval(constrs, k));
+-
+- trace_hw_interval_param(substream, k, 0, &old_interval, i);
+-
+- if (changed)
+- params->cmask |= 1 << k;
+- if (changed < 0)
+- return changed;
+- }
++ err = constrain_interval_params(substream, params);
++ if (err < 0)
++ return err;
+
+ for (k = 0; k < constrs->rules_num; k++)
+ rstamps[k] = 0;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-add-a-helper-function-to-constrain-mask-typ.patch b/patches.drivers/ALSA-pcm-add-a-helper-function-to-constrain-mask-typ.patch
new file mode 100644
index 0000000000..57c2bab8eb
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-add-a-helper-function-to-constrain-mask-typ.patch
@@ -0,0 +1,107 @@
+From 561e1cadb4dca3783de82cfa453a142129953e4d Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 06:36:59 +0900
+Subject: [PATCH] ALSA: pcm: add a helper function to constrain mask-type parameters
+Git-commit: 561e1cadb4dca3783de82cfa453a142129953e4d
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Application of constraints to mask-type parameters for PCM substream is
+done in a call of snd_pcm_hw_refine(), while the function includes much
+codes and is not enough friendly to readers.
+
+This commit splits the codes to a separated function so that readers can
+get it easily. I leave desicion into compilers to merge the function into
+its callee.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 56 +++++++++++++++++++++++++++--------------
+ 1 file changed, 37 insertions(+), 19 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 2bde07a4a87f..1dee5f960fbe 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -253,6 +253,39 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
+ return true;
+ }
+
++static int constrain_mask_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_pcm_hw_constraints *constrs =
++ &substream->runtime->hw_constraints;
++ struct snd_mask *m;
++ unsigned int k;
++ struct snd_mask old_mask;
++ int changed;
++
++ for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
++ m = hw_param_mask(params, k);
++ if (snd_mask_empty(m))
++ return -EINVAL;
++ if (!(params->rmask & (1 << k)))
++ continue;
++
++ if (trace_hw_mask_param_enabled())
++ old_mask = *m;
++
++ changed = snd_mask_refine(m, constrs_mask(constrs, k));
++
++ trace_hw_mask_param(substream, k, 0, &old_mask, m);
++
++ if (changed)
++ params->cmask |= 1 << k;
++ if (changed < 0)
++ return changed;
++ }
++
++ return 0;
++}
++
+ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+@@ -265,6 +298,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
+ unsigned int stamp = 2;
+ int changed, again;
++ int err;
+
+ struct snd_mask __maybe_unused old_mask;
+ struct snd_interval __maybe_unused old_interval;
+@@ -278,25 +312,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ params->rate_den = 0;
+ }
+
+- for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
+- m = hw_param_mask(params, k);
+- if (snd_mask_empty(m))
+- return -EINVAL;
+- if (!(params->rmask & (1 << k)))
+- continue;
+-
+- if (trace_hw_mask_param_enabled())
+- old_mask = *m;
+-
+- changed = snd_mask_refine(m, constrs_mask(constrs, k));
+-
+- trace_hw_mask_param(substream, k, 0, &old_mask, m);
+-
+- if (changed)
+- params->cmask |= 1 << k;
+- if (changed < 0)
+- return changed;
+- }
++ err = constrain_mask_params(substream, params);
++ if (err < 0)
++ return err;
+
+ for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
+ i = hw_param_interval(params, k);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-add-applptr-event-of-tracepoint.patch b/patches.drivers/ALSA-pcm-add-applptr-event-of-tracepoint.patch
new file mode 100644
index 0000000000..3ec7a628d1
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-add-applptr-event-of-tracepoint.patch
@@ -0,0 +1,238 @@
+From fccf53881e9b564321326f62ed5f85130fa6e569 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Mon, 12 Jun 2017 09:41:45 +0900
+Subject: [PATCH] ALSA: pcm: add 'applptr' event of tracepoint
+Git-commit: fccf53881e9b564321326f62ed5f85130fa6e569
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+In design of ALSA PCM core, status and control data for runtime of ALSA
+PCM substream are shared between kernel/user spaces by page frame
+mapping with read-only attribute. Both of hardware-side and
+application-side position on PCM buffer are maintained as a part of
+the status data. In a view of ALSA PCM application, these two positions
+can be updated by executing ioctl(2) with some commands.
+
+There's an event of tracepoint for hardware-side position; 'hwptr'.
+On the other hand, no events for application-side position. This commit
+adds a new event for this purpose; 'applptr'. When the application-side
+position is changed in kernel space, this event is probed with useful
+information for developers.
+
+I note that the event is not probed for all of ALSA PCM applications, When
+applications are written by read/write programming scenario, the event is
+surely probed. The applications execute ioctl(2) with
+SNDRV_PCM_IOCTL_[READ|WRITE][N/I]_FRAMES to read/write any PCM frame, then
+ALSA PCM core updates the application-side position in kernel land.
+However, when applications are written by mmap programming scenario, if
+maintaining the application side position in kernel space accurately,
+applications should voluntarily execute ioctl(2) with
+SNDRV_PCM_IOCTL_SYNC_PTR to commit the number of handled PCM frames. If
+not voluntarily, the application-side position is not changed, thus the
+added event is not probed.
+
+There's a loophole, using architectures to which ALSA PCM core judges
+non cache coherent. In this case, the status and control data is not mapped
+into processe's VMA for any applications. Userland library, alsa-lib, is
+programmed for this case. It executes ioctl(2) with
+SNDRV_PCM_IOCTL_SYNC_PTR command every time to requiring the status and
+control data.
+
+ARM is such an architecture. Below is an example with serial sound interface
+(ssi) on i.mx6 quad core SoC. I use v4.1 kernel released by fsl-community
+with patches from VIA Tech. Inc. for VAB820, and my backport patches for
+relevant features for this patchset. I use Ubuntu 17.04 from
+ports.ubuntu.com as user land for armhf architecture.
+
+$ aplay -v -M -D hw:imx6vab820sgtl5,0 /dev/urandom -f S16_LE -r 48000 --period-size=128 --buffer-size=256
+Playing raw data '/dev/urandom' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
+Hardware PCM card 0 'imx6-vab820-sgtl5000' device 0 subdevice 0
+Its setup is:
+ stream : PLAYBACK
+ access : MMAP_INTERLEAVED
+ format : S16_LE
+ subformat : STD
+ channels : 1
+ rate : 48000
+ exact rate : 48000 (48000/1)
+ msbits : 16
+ buffer_size : 256
+ period_size : 128
+ period_time : 2666
+ tstamp_mode : NONE
+ tstamp_type : MONOTONIC
+ period_step : 1
+ avail_min : 128
+ period_event : 0
+ start_threshold : 256
+ stop_threshold : 256
+ silence_threshold: 0
+ silence_size : 0
+ boundary : 1073741824
+ appl_ptr : 0
+ hw_ptr : 0
+mmap_area[0] = 0x76f98000,0,16 (16)
+
+$ trace-cmd record -e snd_pcm:hwptr -e snd_pcm:applptr
+$ trace-cmd report
+...
+60.208495: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=0, period=128, buf=256
+60.208633: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=0, period=128, buf=256
+60.210022: hwptr: pcmC0D0p/sub0: IRQ: pos=128, old=1536, base=1536, period=128, buf=256
+60.210202: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=128, period=128, buf=256
+60.210344: hwptr: pcmC0D0p/sub0: POS: pos=128, old=1664, base=1536, period=128, buf=256
+60.210348: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=128, period=128, buf=256
+60.210486: applptr: pcmC0D0p/sub0: prev=1792, curr=1792, avail=128, period=128, buf=256
+60.210626: applptr: pcmC0D0p/sub0: prev=1792, curr=1920, avail=0, period=128, buf=256
+60.211002: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=0, period=128, buf=256
+60.211142: hwptr: pcmC0D0p/sub0: POS: pos=128, old=1664, base=1536, period=128, buf=256
+60.211146: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=0, period=128, buf=256
+60.211287: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=0, period=128, buf=256
+60.212690: hwptr: pcmC0D0p/sub0: IRQ: pos=0, old=1664, base=1536, period=128, buf=256
+60.212866: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=128, period=128, buf=256
+60.212999: hwptr: pcmC0D0p/sub0: POS: pos=0, old=1792, base=1792, period=128, buf=256
+60.213003: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=128, period=128, buf=256
+60.213135: applptr: pcmC0D0p/sub0: prev=1920, curr=1920, avail=128, period=128, buf=256
+60.213276: applptr: pcmC0D0p/sub0: prev=1920, curr=2048, avail=0, period=128, buf=256
+60.213654: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=0, period=128, buf=256
+60.213796: hwptr: pcmC0D0p/sub0: POS: pos=0, old=1792, base=1792, period=128, buf=256
+60.213800: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=0, period=128, buf=256
+60.213937: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=0, period=128, buf=256
+60.215356: hwptr: pcmC0D0p/sub0: IRQ: pos=128, old=1792, base=1792, period=128, buf=256
+60.215542: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=128, period=128, buf=256
+60.215679: hwptr: pcmC0D0p/sub0: POS: pos=128, old=1920, base=1792, period=128, buf=256
+60.215683: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=128, period=128, buf=256
+60.215813: applptr: pcmC0D0p/sub0: prev=2048, curr=2048, avail=128, period=128, buf=256
+60.215947: applptr: pcmC0D0p/sub0: prev=2048, curr=2176, avail=0, period=128, buf=256
+...
+
+We can surely see 'applptr' event is probed even if the application run
+for mmap programming scenario ('-M' option and 'hw' plugin). Below is a
+result of strace:
+
+02:44:15.886382 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.887203 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
+02:44:15.887471 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.887637 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.887805 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.887969 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.888132 read(3, "..."..., 256) = 256
+02:44:15.889040 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.889221 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.889431 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.889606 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
+02:44:15.889833 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.889998 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.890164 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.891048 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.891228 read(3, "..."..., 256) = 256
+02:44:15.891497 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.891661 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.891829 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+02:44:15.891991 poll([{fd=4, events=POLLOUT|POLLERR|POLLNVAL}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
+02:44:15.893007 ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x56a32b30) = 0
+
+We can see 7 calls of ioctl(2) with SNDRV_PCM_IOCTL_SYNC_PTR per loop with
+call of poll(2). 128 PCM frames are transferred per loop of one poll(2),
+because the PCM substream is configured with S16_LE format and 1 channel
+(2 byte * 1 * 128 = 256 bytes). This equals to the size of period of PCM
+buffer. Comparing to the probed data, one of the 7 calls of ioctl(2) is
+actually used to commit the number of copied PCM frames to kernel space.
+The other calls are just used to check runtime status of PCM substream;
+e.g. XRUN.
+
+The tracepoint event is useful to investigate this case. I note that below
+modules are related to the above sample.
+
+ * snd-soc-dummy.ko
+ * snd-soc-imx-sgtl5000.ko
+ * snd-soc-fsl-ssi.ko
+ * snd-soc-imx-pcm-dma.ko
+ * snd-soc-sgtl5000.ko
+
+My additional note is lock acquisition. The event is probed under acquiring
+PCM stream lock. This means that calculation in the event is free from
+any hardware events.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 4 ++++
+ sound/core/pcm_trace.h | 38 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 42 insertions(+)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index d82f1437667f..e73b6e4135f6 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -42,6 +42,7 @@
+ #define trace_hwptr(substream, pos, in_interrupt)
+ #define trace_xrun(substream)
+ #define trace_hw_ptr_error(substream, reason)
++#define trace_applptr(substream, prev, curr)
+ #endif
+
+ static int fill_silence_frames(struct snd_pcm_substream *substream,
+@@ -2119,6 +2120,9 @@ int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
+ return ret;
+ }
+ }
++
++ trace_applptr(substream, old_appl_ptr, appl_ptr);
++
+ return 0;
+ }
+
+diff --git a/sound/core/pcm_trace.h b/sound/core/pcm_trace.h
+index b63b654da5ff..e672368ab878 100644
+--- a/sound/core/pcm_trace.h
++++ b/sound/core/pcm_trace.h
+@@ -102,6 +102,44 @@ TRACE_EVENT(hw_ptr_error,
+ __entry->number, __entry->reason)
+ );
+
++TRACE_EVENT(applptr,
++ TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_uframes_t prev, snd_pcm_uframes_t curr),
++ TP_ARGS(substream, prev, curr),
++ TP_STRUCT__entry(
++ __field( unsigned int, card )
++ __field( unsigned int, device )
++ __field( unsigned int, number )
++ __field( unsigned int, stream )
++ __field( snd_pcm_uframes_t, prev )
++ __field( snd_pcm_uframes_t, curr )
++ __field( snd_pcm_uframes_t, avail )
++ __field( snd_pcm_uframes_t, period_size )
++ __field( snd_pcm_uframes_t, buffer_size )
++ ),
++ TP_fast_assign(
++ __entry->card = (substream)->pcm->card->number;
++ __entry->device = (substream)->pcm->device;
++ __entry->number = (substream)->number;
++ __entry->stream = (substream)->stream;
++ __entry->prev = (prev);
++ __entry->curr = (curr);
++ __entry->avail = (substream)->stream ? snd_pcm_capture_avail(substream->runtime) : snd_pcm_playback_avail(substream->runtime);
++ __entry->period_size = (substream)->runtime->period_size;
++ __entry->buffer_size = (substream)->runtime->buffer_size;
++ ),
++ TP_printk("pcmC%dD%d%s/sub%d: prev=%lu, curr=%lu, avail=%lu, period=%lu, buf=%lu",
++ __entry->card,
++ __entry->device,
++ __entry->stream ? "c" : "p",
++ __entry->number,
++ __entry->prev,
++ __entry->curr,
++ __entry->avail,
++ __entry->period_size,
++ __entry->buffer_size
++ )
++);
++
+ #endif /* _PCM_TRACE_H */
+
+ /* This part must be outside protection */
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-add-comment-about-application-of-rule-to-PC.patch b/patches.drivers/ALSA-pcm-add-comment-about-application-of-rule-to-PC.patch
new file mode 100644
index 0000000000..1a20c8b261
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-add-comment-about-application-of-rule-to-PC.patch
@@ -0,0 +1,152 @@
+From d81052f92c3d018ade20ecbf461004566428d9a5 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 06:37:06 +0900
+Subject: [PATCH] ALSA: pcm: add comment about application of rule to PCM parameters
+Git-commit: d81052f92c3d018ade20ecbf461004566428d9a5
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Drivers add rules of parameters to runtime of PCM substream, when
+applications open ALSA PCM character device. When applications call
+ioctl(2) with SNDRV_PCM_IOCTL_HW_REFINE or SNDRV_PCM_IOCTL_HW_PARAMS, the
+rules are applied to the parameters and return the result to user space.
+
+The rule can have dependency between parameters. Additionally, it can have
+condition flags about application of rules. Userspace applications can
+indicate the flags to suppress change of parameters.
+
+This commit attempts to describe the mechanism.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 53 ++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 52 insertions(+), 1 deletion(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 80275aa0bcca..422ee4629698 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -267,6 +267,8 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
+ m = hw_param_mask(params, k);
+ if (snd_mask_empty(m))
+ return -EINVAL;
++
++ /* This parameter is not requested to change by a caller. */
+ if (!(params->rmask & (1 << k)))
+ continue;
+
+@@ -277,6 +279,7 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
+
+ trace_hw_mask_param(substream, k, 0, &old_mask, m);
+
++ /* Set corresponding flag so that the caller gets it. */
+ if (changed)
+ params->cmask |= 1 << k;
+ if (changed < 0)
+@@ -300,6 +303,8 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
+ i = hw_param_interval(params, k);
+ if (snd_interval_empty(i))
+ return -EINVAL;
++
++ /* This parameter is not requested to change by a caller. */
+ if (!(params->rmask & (1 << k)))
+ continue;
+
+@@ -310,6 +315,7 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
+
+ trace_hw_interval_param(substream, k, 0, &old_interval, i);
+
++ /* Set corresponding flag so that the caller gets it. */
+ if (changed)
+ params->cmask |= 1 << k;
+ if (changed < 0)
+@@ -327,7 +333,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ unsigned int k;
+ unsigned int rstamps[constrs->rules_num];
+ unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
+- unsigned int stamp = 2;
++ unsigned int stamp;
+ struct snd_pcm_hw_rule *r;
+ unsigned int d;
+ struct snd_mask old_mask;
+@@ -335,16 +341,54 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ bool again;
+ int changed;
+
++ /*
++ * Each application of rule has own sequence number.
++ *
++ * Each member of 'rstamps' array represents the sequence number of
++ * recent application of corresponding rule.
++ */
+ for (k = 0; k < constrs->rules_num; k++)
+ rstamps[k] = 0;
++
++ /*
++ * Each member of 'vstamps' array represents the sequence number of
++ * recent application of rule in which corresponding parameters were
++ * changed.
++ *
++ * In initial state, elements corresponding to parameters requested by
++ * a caller is 1. For unrequested parameters, corresponding members
++ * have 0 so that the parameters are never changed anymore.
++ */
+ for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
+ vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
++
++ /* Due to the above design, actual sequence number starts at 2. */
++ stamp = 2;
+ retry:
++ /* Apply all rules in order. */
+ again = false;
+ for (k = 0; k < constrs->rules_num; k++) {
+ r = &constrs->rules[k];
++
++ /*
++ * Check condition bits of this rule. When the rule has
++ * some condition bits, parameter without the bits is
++ * never processed. SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP
++ * is an example of the condition bits.
++ */
+ if (r->cond && !(r->cond & params->flags))
+ continue;
++
++ /*
++ * The 'deps' array includes maximum three dependencies
++ * to SNDRV_PCM_HW_PARAM_XXXs for this rule. The fourth
++ * member of this array is a sentinel and should be
++ * negative value.
++ *
++ * This rule should be processed in this time when dependent
++ * parameters were changed at former applications of the other
++ * rules.
++ */
+ for (d = 0; r->deps[d] >= 0; d++) {
+ if (vstamps[r->deps[d]] > rstamps[k])
+ break;
+@@ -373,6 +417,12 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ }
+
+ rstamps[k] = stamp;
++
++ /*
++ * When the parameters is changed, notify it to the caller
++ * by corresponding returned bit, then preparing for next
++ * iteration.
++ */
+ if (changed && r->var >= 0) {
+ params->cmask |= (1 << r->var);
+ vstamps[r->var] = stamp;
+@@ -383,6 +433,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ stamp++;
+ }
+
++ /* Iterate to evaluate all rules till no parameters are changed. */
+ if (again)
+ goto retry;
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-add-const-qualifier-for-read-only-table-for.patch b/patches.drivers/ALSA-pcm-add-const-qualifier-for-read-only-table-for.patch
new file mode 100644
index 0000000000..edd9bc4ee1
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-add-const-qualifier-for-read-only-table-for.patch
@@ -0,0 +1,41 @@
+From 8b674308a26a774896652dafe0dac7ee297eed9b Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 17 May 2017 08:48:17 +0900
+Subject: [PATCH] ALSA: pcm: add const qualifier for read-only table for sampling rate
+Git-commit: 8b674308a26a774896652dafe0dac7ee297eed9b
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+There's a read-only table for each sampling rate, while it doesn't have
+const qualifier and can be modified.
+
+This commit add the qualifier. As a result, a symbol for the table
+moves from .data section to .rodata.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 13dec5ec93f2..d5a967b57bb4 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1986,8 +1986,10 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
+ #error "Change this table"
+ #endif
+
+-static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
+- 48000, 64000, 88200, 96000, 176400, 192000 };
++static const unsigned int rates[] = {
++ 5512, 8000, 11025, 16000, 22050, 32000, 44100,
++ 48000, 64000, 88200, 96000, 176400, 192000
++};
+
+ const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
+ .count = ARRAY_SIZE(rates),
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-add-tracepoints-for-final-selection-process.patch b/patches.drivers/ALSA-pcm-add-tracepoints-for-final-selection-process.patch
new file mode 100644
index 0000000000..353383aad7
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-add-tracepoints-for-final-selection-process.patch
@@ -0,0 +1,70 @@
+From 7b8a54aff30e96b980aa65b0b2e4ebdffcd57196 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 21:46:49 +0900
+Subject: [PATCH] ALSA: pcm: add tracepoints for final selection process of hardware parameters
+Git-commit: 7b8a54aff30e96b980aa65b0b2e4ebdffcd57196
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Results of ioctl(2) with SNDRV_PCM_IOCTL_HW_REFINE and
+SNDRV_PCM_IOCTL_HW_PARAMS are different, because the latter has single
+value for several parameters; e.g. channels of PCM substream. Selection
+of the single value is done independently of application of constraints.
+It's helpful for developers to trace the selection process.
+
+This commit adds tracepoints to snd_pcm_hw_params_choose() for the
+purpose.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 8d9d181b1c03..076187ae8859 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -598,16 +598,38 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+ -1
+ };
+ const int *v;
++ struct snd_mask old_mask;
++ struct snd_interval old_interval;
+ int err;
+
+ for (v = vars; *v != -1; v++) {
++ /* Keep old parameter to trace. */
++ if (trace_hw_mask_param_enabled()) {
++ if (hw_is_mask(*v))
++ old_mask = *hw_param_mask(params, *v);
++ }
++ if (trace_hw_interval_param_enabled()) {
++ if (hw_is_interval(*v))
++ old_interval = *hw_param_interval(params, *v);
++ }
+ if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
+ err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
+ else
+ err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
+ if (snd_BUG_ON(err < 0))
+ return err;
++
++ /* Trace the parameter. */
++ if (hw_is_mask(*v)) {
++ trace_hw_mask_param(pcm, *v, 0, &old_mask,
++ hw_param_mask(params, *v));
++ }
++ if (hw_is_interval(*v)) {
++ trace_hw_interval_param(pcm, *v, 0, &old_interval,
++ hw_param_interval(params, *v));
++ }
+ }
++
+ return 0;
+ }
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-calculate-non-mask-non-interval-parameters-.patch b/patches.drivers/ALSA-pcm-calculate-non-mask-non-interval-parameters-.patch
new file mode 100644
index 0000000000..b82aaae66a
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-calculate-non-mask-non-interval-parameters-.patch
@@ -0,0 +1,153 @@
+From f9a076bff053100c9c3d1d5cca33ca856688b782 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 09:34:39 +0900
+Subject: [PATCH] ALSA: pcm: calculate non-mask/non-interval parameters always when possible
+Git-commit: f9a076bff053100c9c3d1d5cca33ca856688b782
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+A structure for parameters of PCM runtime has parameters which are
+not classified as mask/interval type. They are decided only when
+corresponding normal parameters have unique values.
+ * struct snd_pcm_hw_params.msbits
+ * struct snd_pcm_hw_params.rate_num
+ * struct snd_pcm_hw_params.rate_den
+ * struct snd_pcm_hw_params.fifo_size
+
+Current implementation of hw_params ioctl sometimes doesn't decide these
+parameters even if corresponding parameters are fixed, because these
+parameters are evaluated before a call of snd_pcm_hw_params_choose().
+
+This commit adds a helper function to process the parameters and call it
+in proper positions.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 70 ++++++++++++++++++++++++++---------------
+ 1 file changed, 44 insertions(+), 26 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 87a507f12f2f..dfe6113a6a60 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -440,12 +440,45 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
++static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ const struct snd_interval *i;
++ const struct snd_mask *m;
++ int err;
++
++ if (!params->msbits) {
++ i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
++ if (snd_interval_single(i))
++ params->msbits = snd_interval_value(i);
++ }
++
++ if (!params->rate_den) {
++ i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
++ if (snd_interval_single(i)) {
++ params->rate_num = snd_interval_value(i);
++ params->rate_den = 1;
++ }
++ }
++
++ if (!params->fifo_size) {
++ m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
++ i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
++ if (snd_mask_single(m) && snd_interval_single(i)) {
++ err = substream->ops->ioctl(substream,
++ SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
++ if (err < 0)
++ return err;
++ }
++ }
++
++ return 0;
++}
++
+ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+ struct snd_pcm_hardware *hw;
+- const struct snd_interval *i;
+- const struct snd_mask *m;
+ int err;
+
+ params->info = 0;
+@@ -469,20 +502,6 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ if (err < 0)
+ return err;
+
+- if (!params->msbits) {
+- i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
+- if (snd_interval_single(i))
+- params->msbits = snd_interval_value(i);
+- }
+-
+- if (!params->rate_den) {
+- i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
+- if (snd_interval_single(i)) {
+- params->rate_num = snd_interval_value(i);
+- params->rate_den = 1;
+- }
+- }
+-
+ hw = &substream->runtime->hw;
+ if (!params->info) {
+ params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
+@@ -491,16 +510,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ params->info &= ~(SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID);
+ }
+- if (!params->fifo_size) {
+- m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
+- i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+- if (snd_mask_single(m) && snd_interval_single(i)) {
+- err = substream->ops->ioctl(substream,
+- SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
+- if (err < 0)
+- return err;
+- }
+- }
++
+ params->rmask = 0;
+ return 0;
+ }
+@@ -517,6 +527,8 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
+ return PTR_ERR(params);
+
+ err = snd_pcm_hw_refine(substream, params);
++ if (err >= 0)
++ err = fixup_unreferenced_params(substream, params);
+ if (copy_to_user(_params, params, sizeof(*params))) {
+ if (!err)
+ err = -EFAULT;
+@@ -596,6 +608,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
+ if (err < 0)
+ goto _error;
+
++ err = fixup_unreferenced_params(substream, params);
++ if (err < 0)
++ goto _error;
++
+ if (substream->ops->hw_params != NULL) {
+ err = substream->ops->hw_params(substream, params);
+ if (err < 0)
+@@ -3621,6 +3637,8 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
+ }
+ snd_pcm_hw_convert_from_old_params(params, oparams);
+ err = snd_pcm_hw_refine(substream, params);
++ if (err >= 0)
++ err = fixup_unreferenced_params(substream, params);
+ snd_pcm_hw_convert_to_old_params(oparams, params);
+ if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+ if (!err)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-constify-attribute_group-structures.patch b/patches.drivers/ALSA-pcm-constify-attribute_group-structures.patch
new file mode 100644
index 0000000000..90e2d4fe0e
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-constify-attribute_group-structures.patch
@@ -0,0 +1,43 @@
+From 343fe850668cc38ba0524aa5880b041b2567ae5c Mon Sep 17 00:00:00 2001
+From: Arvind Yadav <arvind.yadav.cs@gmail.com>
+Date: Thu, 29 Jun 2017 16:02:56 +0530
+Subject: [PATCH] ALSA: pcm: constify attribute_group structures.
+Git-commit: 343fe850668cc38ba0524aa5880b041b2567ae5c
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+attribute_groups are not supposed to change at runtime. All functions
+working with attribute_groups provided by <linux/device.h> work with const
+attribute_group. So mark the non-const structs as const.
+
+File size before:
+ text data bss dec hex filename
+ 9781 240 8 10029 272d sound/core/pcm.o
+
+File size After adding 'const':
+ text data bss dec hex filename
+ 9813 176 8 9997 270d sound/core/pcm.o
+
+Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index 4b3290447398..89c7485519cb 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -1067,7 +1067,7 @@ static struct attribute *pcm_dev_attrs[] = {
+ NULL
+ };
+
+-static struct attribute_group pcm_dev_attr_group = {
++static const struct attribute_group pcm_dev_attr_group = {
+ .attrs = pcm_dev_attrs,
+ };
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-constify-function-local-and-read-only-table.patch b/patches.drivers/ALSA-pcm-constify-function-local-and-read-only-table.patch
new file mode 100644
index 0000000000..d70fc315fa
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-constify-function-local-and-read-only-table.patch
@@ -0,0 +1,47 @@
+From b46fe5d9607c2a14618c746a02892ead0f0f4637 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 17 May 2017 08:48:18 +0900
+Subject: [PATCH] ALSA: pcm: constify function local and read-only table
+Git-commit: b46fe5d9607c2a14618c746a02892ead0f0f4637
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+In a function snd_pcm_hw_params_choose(), target parameters are arranged
+into a table. Though each entry of this table is read-only, they don't
+have const qualifier.
+
+This commit adds the qualifier.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index af439e5554b6..ab4b1d1e44ee 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1734,7 +1734,7 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last);
+ int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+ struct snd_pcm_hw_params *params)
+ {
+- static int vars[] = {
++ static const int vars[] = {
+ SNDRV_PCM_HW_PARAM_ACCESS,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_HW_PARAM_SUBFORMAT,
+@@ -1745,7 +1745,8 @@ int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+ SNDRV_PCM_HW_PARAM_TICK_TIME,
+ -1
+ };
+- int err, *v;
++ const int *v;
++ int err;
+
+ for (v = vars; *v != -1; v++) {
+ if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-enable-parameter-tracepoints-only-when-CONF.patch b/patches.drivers/ALSA-pcm-enable-parameter-tracepoints-only-when-CONF.patch
new file mode 100644
index 0000000000..70bc2a67fd
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-enable-parameter-tracepoints-only-when-CONF.patch
@@ -0,0 +1,46 @@
+From 37567c55035a3a6c6cdf060301a7d8e514627afa Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 7 Jun 2017 08:46:44 +0900
+Subject: [PATCH] ALSA: pcm: enable parameter tracepoints only when CONFIG_SND_DEBUG is enabled
+Git-commit: 37567c55035a3a6c6cdf060301a7d8e514627afa
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+In a previous commit, tracepoints are added for PCM parameter processing.
+As long as I know, this implementation increases size of relocatable
+object by 35%. For vendors who are conscious of memory footprint, it
+brings apparent disadvantage.
+
+This commit utilizes CONFIG_SND_DEBUG configuration to enable/disable the
+tracepoints.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index b98b3ccde4f0..2ce3c98a1418 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -39,8 +39,15 @@
+
+ #include "pcm_local.h"
+
++#ifdef CONFIG_SND_DEBUG
+ #define CREATE_TRACE_POINTS
+ #include "pcm_param_trace.h"
++#else
++#define trace_hw_mask_param_enabled() 0
++#define trace_hw_interval_param_enabled() 0
++#define trace_hw_mask_param(substream, type, index, prev, curr)
++#define trace_hw_interval_param(substream, type, index, prev, curr)
++#endif
+
+ /*
+ * Compatibility
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-fix-the-comments-that-refers-to-kernel-doc.patch b/patches.drivers/ALSA-pcm-fix-the-comments-that-refers-to-kernel-doc.patch
new file mode 100644
index 0000000000..c9e0d20e13
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-fix-the-comments-that-refers-to-kernel-doc.patch
@@ -0,0 +1,34 @@
+From 52204718b1f04a84feadd86f3eab5b4da365306f Mon Sep 17 00:00:00 2001
+From: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Date: Sun, 14 May 2017 12:38:44 -0300
+Subject: [PATCH] ALSA: pcm: fix the comments that refers to kernel-doc
+Git-commit: 52204718b1f04a84feadd86f3eab5b4da365306f
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+The markup inside the #if 0 comment actually refers to a
+kernel-doc markup. As we're getting rid of DocBook update it.
+
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 3f084486868f..c609b891c4c2 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -1055,7 +1055,7 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format);
+ int snd_pcm_format_linear(snd_pcm_format_t format);
+ int snd_pcm_format_little_endian(snd_pcm_format_t format);
+ int snd_pcm_format_big_endian(snd_pcm_format_t format);
+-#if 0 /* just for DocBook */
++#if 0 /* just for kernel-doc */
+ /**
+ * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
+ * @format: the format to check
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-include-pcm_local.h-and-remove-some-extrane.patch b/patches.drivers/ALSA-pcm-include-pcm_local.h-and-remove-some-extrane.patch
new file mode 100644
index 0000000000..1d8ef8a840
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-include-pcm_local.h-and-remove-some-extrane.patch
@@ -0,0 +1,88 @@
+From 7421a1671abe5bc07cc7a09f5a1be45acc403db7 Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Tue, 30 May 2017 11:39:45 +0100
+Subject: [PATCH] ALSA: pcm: include pcm_local.h and remove some extraneous tabs
+Git-commit: 7421a1671abe5bc07cc7a09f5a1be45acc403db7
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+We need to include pcm_local.h to clean up some smatch warnings:
+
+symbol 'snd_pcm_timer_done' was not declared. Should it be static?
+symbol 'snd_pcm_timer_init' was not declared. Should it be static?
+symbol 'snd_pcm_timer_resolution_change' was not declared. Should
+ it be static?
+
+Also remove some extraneous tabs on empty lines and replace space
+intentation with a tab.
+
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_timer.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
+index 20ecd8f18080..11389f13de73 100644
+--- a/sound/core/pcm_timer.c
++++ b/sound/core/pcm_timer.c
+@@ -25,6 +25,8 @@
+ #include <sound/pcm.h>
+ #include <sound/timer.h>
+
++#include "pcm_local.h"
++
+ /*
+ * Timer functions
+ */
+@@ -33,8 +35,8 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
+ {
+ unsigned long rate, mult, fsize, l, post;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+-
+- mult = 1000000000;
++
++ mult = 1000000000;
+ rate = runtime->rate;
+ if (snd_BUG_ON(!rate))
+ return;
+@@ -65,7 +67,7 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
+ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
+ {
+ struct snd_pcm_substream *substream;
+-
++
+ substream = timer->private_data;
+ return substream->runtime ? substream->runtime->timer_resolution : 0;
+ }
+@@ -73,7 +75,7 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
+ static int snd_pcm_timer_start(struct snd_timer * timer)
+ {
+ struct snd_pcm_substream *substream;
+-
++
+ substream = snd_timer_chip(timer);
+ substream->timer_running = 1;
+ return 0;
+@@ -82,7 +84,7 @@ static int snd_pcm_timer_start(struct snd_timer * timer)
+ static int snd_pcm_timer_stop(struct snd_timer * timer)
+ {
+ struct snd_pcm_substream *substream;
+-
++
+ substream = snd_timer_chip(timer);
+ substream->timer_running = 0;
+ return 0;
+@@ -112,7 +114,7 @@ void snd_pcm_timer_init(struct snd_pcm_substream *substream)
+ {
+ struct snd_timer_id tid;
+ struct snd_timer *timer;
+-
++
+ tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
+ tid.dev_class = SNDRV_TIMER_CLASS_PCM;
+ tid.card = substream->pcm->card->number;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-localize-snd_pcm_hw_params_choose.patch b/patches.drivers/ALSA-pcm-localize-snd_pcm_hw_params_choose.patch
new file mode 100644
index 0000000000..ff0916a596
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-localize-snd_pcm_hw_params_choose.patch
@@ -0,0 +1,143 @@
+From 60f96aaecb19ca294addfff0d2d0335293f3c379 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 21:46:48 +0900
+Subject: [PATCH] ALSA: pcm: localize snd_pcm_hw_params_choose()
+Git-commit: 60f96aaecb19ca294addfff0d2d0335293f3c379
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+As of v4.12, snd_pcm_hw_params_choose() is just called in a process
+context of ioctl(2) with SNDRV_PCM_IOCTL_HW_PARAMS. The function locates
+in a different file, which has no tracepoints.
+
+This commit moves the function to a file with the tracepoints for later
+commit.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 40 ----------------------------------------
+ sound/core/pcm_local.h | 3 ---
+ sound/core/pcm_native.c | 40 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 40 insertions(+), 43 deletions(-)
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 95b8ef15029f..9dc7bbfe8853 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1700,46 +1700,6 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
+
+ EXPORT_SYMBOL(snd_pcm_hw_param_last);
+
+-/**
+- * snd_pcm_hw_param_choose - choose a configuration defined by @params
+- * @pcm: PCM instance
+- * @params: the hw_params instance
+- *
+- * Choose one configuration from configuration space defined by @params.
+- * The configuration chosen is that obtained fixing in this order:
+- * first access, first format, first subformat, min channels,
+- * min rate, min period time, max buffer size, min tick time
+- *
+- * Return: Zero if successful, or a negative error code on failure.
+- */
+-int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+- struct snd_pcm_hw_params *params)
+-{
+- static const int vars[] = {
+- SNDRV_PCM_HW_PARAM_ACCESS,
+- SNDRV_PCM_HW_PARAM_FORMAT,
+- SNDRV_PCM_HW_PARAM_SUBFORMAT,
+- SNDRV_PCM_HW_PARAM_CHANNELS,
+- SNDRV_PCM_HW_PARAM_RATE,
+- SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+- SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+- SNDRV_PCM_HW_PARAM_TICK_TIME,
+- -1
+- };
+- const int *v;
+- int err;
+-
+- for (v = vars; *v != -1; v++) {
+- if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
+- err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
+- else
+- err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
+- if (snd_BUG_ON(err < 0))
+- return err;
+- }
+- return 0;
+-}
+-
+ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
+ void *arg)
+ {
+diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
+index 34c66decaaf2..e4bf2af62b02 100644
+--- a/sound/core/pcm_local.h
++++ b/sound/core/pcm_local.h
+@@ -24,9 +24,6 @@ void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
+ int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
+ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
+
+-int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream,
+- struct snd_pcm_hw_params *params);
+-
+ int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime,
+ snd_pcm_hw_param_t var, u_int32_t mask);
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 3293db0172db..8d9d181b1c03 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -571,6 +571,46 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
+ #endif
+ }
+
++/**
++ * snd_pcm_hw_param_choose - choose a configuration defined by @params
++ * @pcm: PCM instance
++ * @params: the hw_params instance
++ *
++ * Choose one configuration from configuration space defined by @params.
++ * The configuration chosen is that obtained fixing in this order:
++ * first access, first format, first subformat, min channels,
++ * min rate, min period time, max buffer size, min tick time
++ *
++ * Return: Zero if successful, or a negative error code on failure.
++ */
++static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
++ struct snd_pcm_hw_params *params)
++{
++ static const int vars[] = {
++ SNDRV_PCM_HW_PARAM_ACCESS,
++ SNDRV_PCM_HW_PARAM_FORMAT,
++ SNDRV_PCM_HW_PARAM_SUBFORMAT,
++ SNDRV_PCM_HW_PARAM_CHANNELS,
++ SNDRV_PCM_HW_PARAM_RATE,
++ SNDRV_PCM_HW_PARAM_PERIOD_TIME,
++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
++ SNDRV_PCM_HW_PARAM_TICK_TIME,
++ -1
++ };
++ const int *v;
++ int err;
++
++ for (v = vars; *v != -1; v++) {
++ if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
++ err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
++ else
++ err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
++ if (snd_BUG_ON(err < 0))
++ return err;
++ }
++ return 0;
++}
++
+ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-move-fixup-of-info-flag-after-selecting-sin.patch b/patches.drivers/ALSA-pcm-move-fixup-of-info-flag-after-selecting-sin.patch
new file mode 100644
index 0000000000..0b7867dbd4
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-move-fixup-of-info-flag-after-selecting-sin.patch
@@ -0,0 +1,72 @@
+From 7802fb52564b5d6b4fdcf25a08d487897f9e4a8b Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 09:34:40 +0900
+Subject: [PATCH] ALSA: pcm: move fixup of info flag after selecting single parameters
+Git-commit: 7802fb52564b5d6b4fdcf25a08d487897f9e4a8b
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+When drivers register no flags about information of PCM hardware, ALSA
+PCM core fixups it roughly. Currently, this operation places in a
+function snd_pcm_hw_refine(). It can be moved to a function
+fixup_unreferenced_params() because it doesn't affects operations
+between these two functions.
+
+This idea is better to bundle codes with similar purposes and this commit
+achieves it.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index dfe6113a6a60..3293db0172db 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -472,13 +472,21 @@ static int fixup_unreferenced_params(struct snd_pcm_substream *substream,
+ }
+ }
+
++ if (!params->info) {
++ params->info = substream->runtime->hw.info;
++ params->info &= ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
++ SNDRV_PCM_INFO_DRAIN_TRIGGER);
++ if (!hw_support_mmap(substream))
++ params->info &= ~(SNDRV_PCM_INFO_MMAP |
++ SNDRV_PCM_INFO_MMAP_VALID);
++ }
++
+ return 0;
+ }
+
+ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+- struct snd_pcm_hardware *hw;
+ int err;
+
+ params->info = 0;
+@@ -502,16 +510,8 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ if (err < 0)
+ return err;
+
+- hw = &substream->runtime->hw;
+- if (!params->info) {
+- params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
+- SNDRV_PCM_INFO_DRAIN_TRIGGER);
+- if (!hw_support_mmap(substream))
+- params->info &= ~(SNDRV_PCM_INFO_MMAP |
+- SNDRV_PCM_INFO_MMAP_VALID);
+- }
+-
+ params->rmask = 0;
++
+ return 0;
+ }
+ EXPORT_SYMBOL(snd_pcm_hw_refine);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-obsolete-RULES_DEBUG-local-macro.patch b/patches.drivers/ALSA-pcm-obsolete-RULES_DEBUG-local-macro.patch
new file mode 100644
index 0000000000..54a0a232e7
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-obsolete-RULES_DEBUG-local-macro.patch
@@ -0,0 +1,151 @@
+From c6706de0ce8bc8cd1e336b8cf0acabf1adedba6c Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 7 Jun 2017 08:46:45 +0900
+Subject: [PATCH] ALSA: pcm: obsolete RULES_DEBUG local macro
+Git-commit: c6706de0ce8bc8cd1e336b8cf0acabf1adedba6c
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Added tracepoints obsoleted RULES_DEBUG local macro and relevant codes.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 89 ++++-------------------------------------
+ 1 file changed, 7 insertions(+), 82 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 2ce3c98a1418..2bde07a4a87f 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -253,29 +253,6 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
+ return true;
+ }
+
+-#undef RULES_DEBUG
+-
+-#ifdef RULES_DEBUG
+-#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v
+-static const char * const snd_pcm_hw_param_names[] = {
+- HW_PARAM(ACCESS),
+- HW_PARAM(FORMAT),
+- HW_PARAM(SUBFORMAT),
+- HW_PARAM(SAMPLE_BITS),
+- HW_PARAM(FRAME_BITS),
+- HW_PARAM(CHANNELS),
+- HW_PARAM(RATE),
+- HW_PARAM(PERIOD_TIME),
+- HW_PARAM(PERIOD_SIZE),
+- HW_PARAM(PERIOD_BYTES),
+- HW_PARAM(PERIODS),
+- HW_PARAM(BUFFER_TIME),
+- HW_PARAM(BUFFER_SIZE),
+- HW_PARAM(BUFFER_BYTES),
+- HW_PARAM(TICK_TIME),
+-};
+-#endif
+-
+ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+@@ -310,14 +287,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+
+ if (trace_hw_mask_param_enabled())
+ old_mask = *m;
+-#ifdef RULES_DEBUG
+- pr_debug("%s = ", snd_pcm_hw_param_names[k]);
+- pr_cont("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
+-#endif
++
+ changed = snd_mask_refine(m, constrs_mask(constrs, k));
+-#ifdef RULES_DEBUG
+- pr_cont("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
+-#endif
++
+ trace_hw_mask_param(substream, k, 0, &old_mask, m);
+
+ if (changed)
+@@ -335,25 +307,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+
+ if (trace_hw_interval_param_enabled())
+ old_interval = *i;
+-#ifdef RULES_DEBUG
+- pr_debug("%s = ", snd_pcm_hw_param_names[k]);
+- if (i->empty)
+- pr_cont("empty");
+- else
+- pr_cont("%c%u %u%c",
+- i->openmin ? '(' : '[', i->min,
+- i->max, i->openmax ? ')' : ']');
+- pr_cont(" -> ");
+-#endif
++
+ changed = snd_interval_refine(i, constrs_interval(constrs, k));
+-#ifdef RULES_DEBUG
+- if (i->empty)
+- pr_cont("empty\n");
+- else
+- pr_cont("%c%u %u%c\n",
+- i->openmin ? '(' : '[', i->min,
+- i->max, i->openmax ? ')' : ']');
+-#endif
++
+ trace_hw_interval_param(substream, k, 0, &old_interval, i);
+
+ if (changed)
+@@ -391,41 +347,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ if (hw_is_interval(r->var))
+ old_interval = *hw_param_interval(params, r->var);
+ }
+-#ifdef RULES_DEBUG
+- pr_debug("Rule %d [%p]: ", k, r->func);
+- if (r->var >= 0) {
+- pr_cont("%s = ", snd_pcm_hw_param_names[r->var]);
+- if (hw_is_mask(r->var)) {
+- m = hw_param_mask(params, r->var);
+- pr_cont("%x", *m->bits);
+- } else {
+- i = hw_param_interval(params, r->var);
+- if (i->empty)
+- pr_cont("empty");
+- else
+- pr_cont("%c%u %u%c",
+- i->openmin ? '(' : '[', i->min,
+- i->max, i->openmax ? ')' : ']');
+- }
+- }
+-#endif
++
+ changed = r->func(params, r);
+-#ifdef RULES_DEBUG
+- if (r->var >= 0) {
+- pr_cont(" -> ");
+- if (hw_is_mask(r->var))
+- pr_cont("%x", *m->bits);
+- else {
+- if (i->empty)
+- pr_cont("empty");
+- else
+- pr_cont("%c%u %u%c",
+- i->openmin ? '(' : '[', i->min,
+- i->max, i->openmax ? ')' : ']');
+- }
+- }
+- pr_cont("\n");
+-#endif
++
+ if (hw_is_mask(r->var)) {
+ trace_hw_mask_param(substream, r->var, k + 1,
+ &old_mask, hw_param_mask(params, r->var));
+@@ -434,6 +358,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ trace_hw_interval_param(substream, r->var, k + 1,
+ &old_interval, hw_param_interval(params, r->var));
+ }
++
+ rstamps[k] = stamp;
+ if (changed && r->var >= 0) {
+ params->cmask |= (1 << r->var);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-oss-mark-snd_pcm_plug_slave_format-arg-as-c.patch b/patches.drivers/ALSA-pcm-oss-mark-snd_pcm_plug_slave_format-arg-as-c.patch
new file mode 100644
index 0000000000..cfe6590356
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-oss-mark-snd_pcm_plug_slave_format-arg-as-c.patch
@@ -0,0 +1,42 @@
+From dcab5fb7a5b0472e035da7dfe21168802c1b9d3b Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Thu, 18 May 2017 15:35:55 +0200
+Subject: [PATCH] ALSA: pcm/oss: mark snd_pcm_plug_slave_format arg as const
+Git-commit: dcab5fb7a5b0472e035da7dfe21168802c1b9d3b
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Only one of the two declarations has the const modifier in the
+argument list, so we get a warning when CONFIG_SND_PCM_OSS_PLUGINS
+is disabled:
+
+Sound/core/oss/pcm_oss.c: In function 'snd_pcm_oss_change_params':
+sound/core/oss/pcm_oss.c:898:47: error: passing argument 2 of 'snd_pcm_plug_slave_format' discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
+
+This makes the two declarations match again.
+
+Fixes: e76bf3c4b4e4 ("ALSA: pcm/oss: refer to parameters instead of copying to reduce usage of kernel stack")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_plugin.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
+index 38e2c14cb893..73c068abaca5 100644
+--- a/sound/core/oss/pcm_plugin.h
++++ b/sound/core/oss/pcm_plugin.h
+@@ -172,7 +172,7 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
+
+ static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
+ static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; }
+-static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; }
++static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; }
+
+ #endif
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-oss-refer-to-parameters-instead-of-copying-.patch b/patches.drivers/ALSA-pcm-oss-refer-to-parameters-instead-of-copying-.patch
new file mode 100644
index 0000000000..6ec333ac7e
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-oss-refer-to-parameters-instead-of-copying-.patch
@@ -0,0 +1,123 @@
+From e76bf3c4b4e456fa8f2c729fa1e8c644857529a8 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 17 May 2017 08:48:19 +0900
+Subject: [PATCH] ALSA: pcm/oss: refer to parameters instead of copying to reduce usage of kernel stack
+Git-commit: e76bf3c4b4e456fa8f2c729fa1e8c644857529a8
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Some functions in compatibility layer for Open Sound System interface has
+local variable to copy some parameters in runtime of PCM substream, while
+this can be replaced with reference of pointers to parameter itself. This
+brings an advantage to reduce usage of kernel stack.
+
+This commit applies this idea.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_oss.c | 16 ++++++++--------
+ sound/core/oss/pcm_plugin.c | 5 +++--
+ sound/core/oss/pcm_plugin.h | 2 +-
+ 3 files changed, 12 insertions(+), 11 deletions(-)
+
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index 2a473513bd54..e306f05ce51d 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -848,7 +848,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
+ int direct;
+ snd_pcm_format_t format, sformat;
+ int n;
+- struct snd_mask sformat_mask;
++ const struct snd_mask *sformat_mask;
+ struct snd_mask mask;
+
+ if (trylock) {
+@@ -891,18 +891,18 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
+
+ format = snd_pcm_oss_format_from(runtime->oss.format);
+
+- sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
++ sformat_mask = hw_param_mask_c(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
+ if (direct)
+ sformat = format;
+ else
+- sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
++ sformat = snd_pcm_plug_slave_format(format, sformat_mask);
+
+ if ((__force int)sformat < 0 ||
+- !snd_mask_test(&sformat_mask, (__force int)sformat)) {
++ !snd_mask_test(sformat_mask, (__force int)sformat)) {
+ for (sformat = (__force snd_pcm_format_t)0;
+ (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST;
+ sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) {
+- if (snd_mask_test(&sformat_mask, (__force int)sformat) &&
++ if (snd_mask_test(sformat_mask, (__force int)sformat) &&
+ snd_pcm_oss_format_to(sformat) >= 0)
+ break;
+ }
+@@ -1780,7 +1780,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
+ int direct;
+ struct snd_pcm_hw_params *params;
+ unsigned int formats = 0;
+- struct snd_mask format_mask;
++ const struct snd_mask *format_mask;
+ int fmt;
+
+ if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
+@@ -1802,12 +1802,12 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
+ return -ENOMEM;
+ _snd_pcm_hw_params_any(params);
+ err = snd_pcm_hw_refine(substream, params);
+- format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
++ format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ kfree(params);
+ if (err < 0)
+ return err;
+ for (fmt = 0; fmt < 32; ++fmt) {
+- if (snd_mask_test(&format_mask, fmt)) {
++ if (snd_mask_test(format_mask, fmt)) {
+ int f = snd_pcm_oss_format_to(fmt);
+ if (f >= 0)
+ formats |= f;
+diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
+index 727ac44d39f4..cadc93792868 100644
+--- a/sound/core/oss/pcm_plugin.c
++++ b/sound/core/oss/pcm_plugin.c
+@@ -266,7 +266,8 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
+ return frames;
+ }
+
+-static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format)
++static int snd_pcm_plug_formats(const struct snd_mask *mask,
++ snd_pcm_format_t format)
+ {
+ struct snd_mask formats = *mask;
+ u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
+@@ -309,7 +310,7 @@ static snd_pcm_format_t preferred_formats[] = {
+ };
+
+ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
+- struct snd_mask *format_mask)
++ const struct snd_mask *format_mask)
+ {
+ int i;
+
+diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
+index a5035c2369a6..38e2c14cb893 100644
+--- a/sound/core/oss/pcm_plugin.h
++++ b/sound/core/oss/pcm_plugin.h
+@@ -126,7 +126,7 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *slave_params);
+
+ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
+- struct snd_mask *format_mask);
++ const struct snd_mask *format_mask);
+
+ int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin);
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-probe-events-when-parameters-are-changed-ac.patch b/patches.drivers/ALSA-pcm-probe-events-when-parameters-are-changed-ac.patch
new file mode 100644
index 0000000000..a1e4ada2f3
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-probe-events-when-parameters-are-changed-ac.patch
@@ -0,0 +1,134 @@
+From 82e7d5012f73e51209305876bed2aac53b62cde3 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Sun, 11 Jun 2017 23:56:13 +0900
+Subject: [PATCH] ALSA: pcm: probe events when parameters are changed actually
+Git-commit: 82e7d5012f73e51209305876bed2aac53b62cde3
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+At present, trace events are probed even if corresponding parameter is
+not actually changed. This is inconvenient.
+
+This commit improves the behaviour.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 56 +++++++++++++++++++++--------------------
+ 1 file changed, 29 insertions(+), 27 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 425f54827e78..5099078dde93 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -278,12 +278,12 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
+ changed = snd_mask_refine(m, constrs_mask(constrs, k));
+ if (changed < 0)
+ return changed;
+-
+- trace_hw_mask_param(substream, k, 0, &old_mask, m);
++ if (changed == 0)
++ continue;
+
+ /* Set corresponding flag so that the caller gets it. */
+- if (changed)
+- params->cmask |= 1 << k;
++ trace_hw_mask_param(substream, k, 0, &old_mask, m);
++ params->cmask |= 1 << k;
+ }
+
+ return 0;
+@@ -314,12 +314,12 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
+ changed = snd_interval_refine(i, constrs_interval(constrs, k));
+ if (changed < 0)
+ return changed;
+-
+- trace_hw_interval_param(substream, k, 0, &old_interval, i);
++ if (changed == 0)
++ continue;
+
+ /* Set corresponding flag so that the caller gets it. */
+- if (changed)
+- params->cmask |= 1 << k;
++ trace_hw_interval_param(substream, k, 0, &old_interval, i);
++ params->cmask |= 1 << k;
+ }
+
+ return 0;
+@@ -409,29 +409,29 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ if (changed < 0)
+ return changed;
+
+- if (hw_is_mask(r->var)) {
+- trace_hw_mask_param(substream, r->var, k + 1,
+- &old_mask, hw_param_mask(params, r->var));
+- }
+- if (hw_is_interval(r->var)) {
+- trace_hw_interval_param(substream, r->var, k + 1,
+- &old_interval, hw_param_interval(params, r->var));
+- }
+-
+- rstamps[k] = stamp;
+-
+ /*
+- * When the parameters is changed, notify it to the caller
++ * When the parameter is changed, notify it to the caller
+ * by corresponding returned bit, then preparing for next
+ * iteration.
+ */
+ if (changed && r->var >= 0) {
++ if (hw_is_mask(r->var)) {
++ trace_hw_mask_param(substream, r->var,
++ k + 1, &old_mask,
++ hw_param_mask(params, r->var));
++ }
++ if (hw_is_interval(r->var)) {
++ trace_hw_interval_param(substream, r->var,
++ k + 1, &old_interval,
++ hw_param_interval(params, r->var));
++ }
++
+ params->cmask |= (1 << r->var);
+ vstamps[r->var] = stamp;
+ again = true;
+ }
+
+- stamp++;
++ rstamps[k] = stamp++;
+ }
+
+ /* Iterate to evaluate all rules till no parameters are changed. */
+@@ -604,7 +604,7 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+ const int *v;
+ struct snd_mask old_mask;
+ struct snd_interval old_interval;
+- int err;
++ int changed;
+
+ for (v = vars; *v != -1; v++) {
+ /* Keep old parameter to trace. */
+@@ -617,13 +617,15 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+ old_interval = *hw_param_interval(params, *v);
+ }
+ if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
+- err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
++ changed = snd_pcm_hw_param_first(pcm, params, *v, NULL);
+ else
+- err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
+- if (snd_BUG_ON(err < 0))
+- return err;
++ changed = snd_pcm_hw_param_last(pcm, params, *v, NULL);
++ if (snd_BUG_ON(changed < 0))
++ return changed;
++ if (changed == 0)
++ continue;
+
+- /* Trace the parameter. */
++ /* Trace the changed parameter. */
+ if (hw_is_mask(*v)) {
+ trace_hw_mask_param(pcm, *v, 0, &old_mask,
+ hw_param_mask(params, *v));
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-remove-SNDRV_PCM_IOCTL1_GSTATE-internal-com.patch b/patches.drivers/ALSA-pcm-remove-SNDRV_PCM_IOCTL1_GSTATE-internal-com.patch
new file mode 100644
index 0000000000..7b4500a7d0
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-remove-SNDRV_PCM_IOCTL1_GSTATE-internal-com.patch
@@ -0,0 +1,36 @@
+From ba61faf0d75df9537393b2b796df41c30dcfcce7 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 14 Jun 2017 19:30:04 +0900
+Subject: [PATCH] ALSA: pcm: remove SNDRV_PCM_IOCTL1_GSTATE internal command
+Git-commit: ba61faf0d75df9537393b2b796df41c30dcfcce7
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+SNDRV_PCM_IOCTL1_GSTATE was firstly introduced in v0.9.0, however never
+be used and the purpose is missing.
+
+This commit removes the long-abandoned command, bye.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index 48e3eecac86d..5a22075c5fcf 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -104,7 +104,7 @@ struct snd_pcm_ops {
+ #define SNDRV_PCM_IOCTL1_RESET 0
+ /* 1 is absent slot. */
+ #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2
+-#define SNDRV_PCM_IOCTL1_GSTATE 3
++/* 3 is absent slot. */
+ #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4
+
+ #define SNDRV_PCM_TRIGGER_STOP 0
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-remove-SNDRV_PCM_IOCTL1_INFO-internal-comma.patch b/patches.drivers/ALSA-pcm-remove-SNDRV_PCM_IOCTL1_INFO-internal-comma.patch
new file mode 100644
index 0000000000..cf78a42fea
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-remove-SNDRV_PCM_IOCTL1_INFO-internal-comma.patch
@@ -0,0 +1,78 @@
+From e11f0f90a626f93899687b1cc909ee37dd6c5809 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 14 Jun 2017 19:30:03 +0900
+Subject: [PATCH] ALSA: pcm: remove SNDRV_PCM_IOCTL1_INFO internal command
+Git-commit: e11f0f90a626f93899687b1cc909ee37dd6c5809
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Drivers can implement 'struct snd_pcm_ops.ioctl' to handle some requests
+from ALSA PCM core. These requests are internal purpose in kernel land.
+Usually common set of operations are used for it.
+
+SNDRV_PCM_IOCTL1_INFO is one of the requests. According to code comment,
+it has been obsoleted in the old days.
+
+We can see old releases in ftp.alsa-project.org. The command was firstly
+introduced in v0.5.0 release as SND_PCM_IOCTL1_INFO, to allow drivers to
+fill data of 'struct snd_pcm_channel_info' type. In v0.9.0 release,
+this was obsoleted by the other commands for ioctl(2) such as
+SNDRV_PCM_IOCTL_CHANNEL_INFO.
+
+This commit removes the long-abandoned command, bye.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ include/sound/pcm.h | 2 +-
+ sound/core/pcm_lib.c | 2 --
+ sound/core/pcm_native.c | 6 +-----
+ 3 files changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/include/sound/pcm.h b/include/sound/pcm.h
+index c24f85f12b71..48e3eecac86d 100644
+--- a/include/sound/pcm.h
++++ b/include/sound/pcm.h
+@@ -102,7 +102,7 @@ struct snd_pcm_ops {
+ #endif
+
+ #define SNDRV_PCM_IOCTL1_RESET 0
+-#define SNDRV_PCM_IOCTL1_INFO 1
++/* 1 is absent slot. */
+ #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2
+ #define SNDRV_PCM_IOCTL1_GSTATE 3
+ #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 75308ddc54ca..631cd598ba6c 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -1787,8 +1787,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
+ {
+ switch (cmd) {
+- case SNDRV_PCM_IOCTL1_INFO:
+- return 0;
+ case SNDRV_PCM_IOCTL1_RESET:
+ return snd_pcm_lib_ioctl_reset(substream, arg);
+ case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 05858c91c0ea..7e8f3656b695 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -212,11 +212,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
+ info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
+ strlcpy(info->subname, substream->name, sizeof(info->subname));
+ runtime = substream->runtime;
+- /* AB: FIXME!!! This is definitely nonsense */
+- if (runtime) {
+- info->sync = runtime->sync;
+- substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
+- }
++
+ return 0;
+ }
+
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-remove-function-local-variable-with-alterna.patch b/patches.drivers/ALSA-pcm-remove-function-local-variable-with-alterna.patch
new file mode 100644
index 0000000000..2732f399a8
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-remove-function-local-variable-with-alterna.patch
@@ -0,0 +1,48 @@
+From d656b4a6549f0f5863b7888b25a7b20d03ecbce7 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 06:37:03 +0900
+Subject: [PATCH] ALSA: pcm: remove function local variable with alternative evaluation
+Git-commit: d656b4a6549f0f5863b7888b25a7b20d03ecbce7
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+A local variable is used to judge whether a parameter should be handled
+due to reverse dependency of the other rules. However, this can be
+obsoleted by check of a sentinel in dependency array.
+
+This commit removes the local variable and check the sentinel to reduce
+stack usage.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 41aeb6facdec..db4cdd114ed4 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -342,16 +342,13 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ for (k = 0; k < constrs->rules_num; k++) {
+ struct snd_pcm_hw_rule *r = &constrs->rules[k];
+ unsigned int d;
+- int doit = 0;
+ if (r->cond && !(r->cond & params->flags))
+ continue;
+ for (d = 0; r->deps[d] >= 0; d++) {
+- if (vstamps[r->deps[d]] > rstamps[k]) {
+- doit = 1;
++ if (vstamps[r->deps[d]] > rstamps[k])
+ break;
+- }
+ }
+- if (!doit)
++ if (r->deps[d] < 0)
+ continue;
+
+ if (trace_hw_mask_param_enabled()) {
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-remove-redundant-variable-runtime.patch b/patches.drivers/ALSA-pcm-remove-redundant-variable-runtime.patch
new file mode 100644
index 0000000000..a8bf969bb2
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-remove-redundant-variable-runtime.patch
@@ -0,0 +1,45 @@
+From de168981384097f810d3ecfb4bcfa5019cc7c160 Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Sun, 15 Oct 2017 22:06:44 +0100
+Subject: [PATCH] ALSA: pcm: remove redundant variable runtime
+Git-commit: de168981384097f810d3ecfb4bcfa5019cc7c160
+Patch-mainline: v4.15-rc1
+References: bsc#1121278
+
+An earlier commit removed the access to variable runtime
+and we are now left with unused variable that is redundant,
+so remove it.
+
+Cleans up the clang warning: Value stored to 'runtime' is never read
+
+Fixes: e11f0f90a626 ("ALSA: pcm: remove SNDRV_PCM_IOCTL1_INFO internal command")
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 2fec2feac387..a4d92e46c459 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -195,7 +195,6 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
+
+ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
+ {
+- struct snd_pcm_runtime *runtime;
+ struct snd_pcm *pcm = substream->pcm;
+ struct snd_pcm_str *pstr = substream->pstr;
+
+@@ -211,7 +210,6 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
+ info->subdevices_count = pstr->substream_count;
+ info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
+ strlcpy(info->subname, substream->name, sizeof(info->subname));
+- runtime = substream->runtime;
+
+ return 0;
+ }
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-return-error-immediately-for-parameters-han.patch b/patches.drivers/ALSA-pcm-return-error-immediately-for-parameters-han.patch
new file mode 100644
index 0000000000..3cd7d17e3b
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-return-error-immediately-for-parameters-han.patch
@@ -0,0 +1,172 @@
+From f74ae15fe3da7905b78e986ad906a333587cf160 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Sun, 11 Jun 2017 23:56:12 +0900
+Subject: [PATCH] ALSA: pcm: return error immediately for parameters handling
+Git-commit: f74ae15fe3da7905b78e986ad906a333587cf160
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+When refining mask/interval parameters, helper functions can return error
+code. This error is not handled immediately. This seems to return
+parameters to userspace applications in its meddle of processing.
+
+However, in general, when receiving error from system calls, the
+application might not handle argument buffer. It's reasonable to
+judge the above design as superfluity.
+
+This commit handles the error immediately.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 66 ++++++++++++++++++++++++-----------------
+ 1 file changed, 38 insertions(+), 28 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 076187ae8859..425f54827e78 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -276,14 +276,14 @@ static int constrain_mask_params(struct snd_pcm_substream *substream,
+ old_mask = *m;
+
+ changed = snd_mask_refine(m, constrs_mask(constrs, k));
++ if (changed < 0)
++ return changed;
+
+ trace_hw_mask_param(substream, k, 0, &old_mask, m);
+
+ /* Set corresponding flag so that the caller gets it. */
+ if (changed)
+ params->cmask |= 1 << k;
+- if (changed < 0)
+- return changed;
+ }
+
+ return 0;
+@@ -312,14 +312,14 @@ static int constrain_interval_params(struct snd_pcm_substream *substream,
+ old_interval = *i;
+
+ changed = snd_interval_refine(i, constrs_interval(constrs, k));
++ if (changed < 0)
++ return changed;
+
+ trace_hw_interval_param(substream, k, 0, &old_interval, i);
+
+ /* Set corresponding flag so that the caller gets it. */
+ if (changed)
+ params->cmask |= 1 << k;
+- if (changed < 0)
+- return changed;
+ }
+
+ return 0;
+@@ -406,6 +406,8 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ }
+
+ changed = r->func(params, r);
++ if (changed < 0)
++ return changed;
+
+ if (hw_is_mask(r->var)) {
+ trace_hw_mask_param(substream, r->var, k + 1,
+@@ -428,8 +430,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ vstamps[r->var] = stamp;
+ again = true;
+ }
+- if (changed < 0)
+- return changed;
++
+ stamp++;
+ }
+
+@@ -527,13 +528,16 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
+ return PTR_ERR(params);
+
+ err = snd_pcm_hw_refine(substream, params);
+- if (err >= 0)
+- err = fixup_unreferenced_params(substream, params);
+- if (copy_to_user(_params, params, sizeof(*params))) {
+- if (!err)
+- err = -EFAULT;
+- }
++ if (err < 0)
++ goto end;
+
++ err = fixup_unreferenced_params(substream, params);
++ if (err < 0)
++ goto end;
++
++ if (copy_to_user(_params, params, sizeof(*params)))
++ err = -EFAULT;
++end:
+ kfree(params);
+ return err;
+ }
+@@ -749,11 +753,12 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
+ return PTR_ERR(params);
+
+ err = snd_pcm_hw_params(substream, params);
+- if (copy_to_user(_params, params, sizeof(*params))) {
+- if (!err)
+- err = -EFAULT;
+- }
++ if (err < 0)
++ goto end;
+
++ if (copy_to_user(_params, params, sizeof(*params)))
++ err = -EFAULT;
++end:
+ kfree(params);
+ return err;
+ }
+@@ -3699,14 +3704,17 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
+ }
+ snd_pcm_hw_convert_from_old_params(params, oparams);
+ err = snd_pcm_hw_refine(substream, params);
+- if (err >= 0)
+- err = fixup_unreferenced_params(substream, params);
+- snd_pcm_hw_convert_to_old_params(oparams, params);
+- if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+- if (!err)
+- err = -EFAULT;
+- }
++ if (err < 0)
++ goto out_old;
++
++ err = fixup_unreferenced_params(substream, params);
++ if (err < 0)
++ goto out_old;
+
++ snd_pcm_hw_convert_to_old_params(oparams, params);
++ if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
++ err = -EFAULT;
++out_old:
+ kfree(oparams);
+ out:
+ kfree(params);
+@@ -3729,14 +3737,16 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
+ err = PTR_ERR(oparams);
+ goto out;
+ }
++
+ snd_pcm_hw_convert_from_old_params(params, oparams);
+ err = snd_pcm_hw_params(substream, params);
+- snd_pcm_hw_convert_to_old_params(oparams, params);
+- if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+- if (!err)
+- err = -EFAULT;
+- }
++ if (err < 0)
++ goto out_old;
+
++ snd_pcm_hw_convert_to_old_params(oparams, params);
++ if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
++ err = -EFAULT;
++out_old:
+ kfree(oparams);
+ out:
+ kfree(params);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-signedness-bug-in-snd_pcm_plug_alloc.patch b/patches.drivers/ALSA-pcm-signedness-bug-in-snd_pcm_plug_alloc.patch
new file mode 100644
index 0000000000..901e62e8b1
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-signedness-bug-in-snd_pcm_plug_alloc.patch
@@ -0,0 +1,43 @@
+From 6f128fa41f310e1f39ebcea9621d2905549ecf52 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Mon, 27 Aug 2018 12:21:45 +0300
+Subject: [PATCH] ALSA: pcm: signedness bug in snd_pcm_plug_alloc()
+Git-commit: 6f128fa41f310e1f39ebcea9621d2905549ecf52
+Patch-mainline: v4.20-rc1
+References: bsc#1121278
+
+The "frames" variable is unsigned so the error handling doesn't work
+properly.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/oss/pcm_plugin.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
+index 0391cb1a4f19..141c5f3a9575 100644
+--- a/sound/core/oss/pcm_plugin.c
++++ b/sound/core/oss/pcm_plugin.c
+@@ -111,7 +111,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames)
+ while (plugin->next) {
+ if (plugin->dst_frames)
+ frames = plugin->dst_frames(plugin, frames);
+- if (snd_BUG_ON(frames <= 0))
++ if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0))
+ return -ENXIO;
+ plugin = plugin->next;
+ err = snd_pcm_plugin_alloc(plugin, frames);
+@@ -123,7 +123,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames)
+ while (plugin->prev) {
+ if (plugin->src_frames)
+ frames = plugin->src_frames(plugin, frames);
+- if (snd_BUG_ON(frames <= 0))
++ if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0))
+ return -ENXIO;
+ plugin = plugin->prev;
+ err = snd_pcm_plugin_alloc(plugin, frames);
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-trace-XRUN-event-at-injection-too.patch b/patches.drivers/ALSA-pcm-trace-XRUN-event-at-injection-too.patch
new file mode 100644
index 0000000000..61654a899b
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-trace-XRUN-event-at-injection-too.patch
@@ -0,0 +1,114 @@
+From 9cd641ed31f576d08f7b784850ba93eef050f32f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 4 Jul 2018 14:46:27 +0200
+Subject: [PATCH] ALSA: pcm: trace XRUN event at injection, too
+Git-commit: 9cd641ed31f576d08f7b784850ba93eef050f32f
+Patch-mainline: v4.19-rc1
+References: bsc#1121278
+
+The PCM xrun injection triggers directly snd_pcm_stop() without the
+standard xrun handler, hence it's not recorded on the event buffer.
+Ditto for snd_pcm_stop_xrun() call and SNDRV_PCM_IOCTL_XRUN ioctl.
+They are inconvenient from the debugging POV.
+
+Let's make them to trigger XRUN via the standard helper more
+consistently.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm.c | 2 +-
+ sound/core/pcm_lib.c | 7 ++++---
+ sound/core/pcm_local.h | 2 ++
+ sound/core/pcm_native.c | 8 ++++----
+ 4 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index c352bfb973cc..6f037a4b8b52 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -497,7 +497,7 @@ static void snd_pcm_xrun_injection_write(struct snd_info_entry *entry,
+ snd_pcm_stream_lock_irq(substream);
+ runtime = substream->runtime;
+ if (runtime && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
+- snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
++ __snd_pcm_xrun(substream);
+ snd_pcm_stream_unlock_irq(substream);
+ }
+
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 44b5ae833082..c1d2e8e1fc6b 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -153,7 +153,8 @@ EXPORT_SYMBOL(snd_pcm_debug_name);
+ dump_stack(); \
+ } while (0)
+
+-static void xrun(struct snd_pcm_substream *substream)
++/* call with stream lock held */
++void __snd_pcm_xrun(struct snd_pcm_substream *substream)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+@@ -201,7 +202,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
+ }
+ } else {
+ if (avail >= runtime->stop_threshold) {
+- xrun(substream);
++ __snd_pcm_xrun(substream);
+ return -EPIPE;
+ }
+ }
+@@ -297,7 +298,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
+ }
+
+ if (pos == SNDRV_PCM_POS_XRUN) {
+- xrun(substream);
++ __snd_pcm_xrun(substream);
+ return -EPIPE;
+ }
+ if (pos >= runtime->buffer_size) {
+diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
+index 7a499d02df6c..c515612969a4 100644
+--- a/sound/core/pcm_local.h
++++ b/sound/core/pcm_local.h
+@@ -65,4 +65,6 @@ static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {}
+ static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
+ #endif
+
++void __snd_pcm_xrun(struct snd_pcm_substream *substream);
++
+ #endif /* __SOUND_CORE_PCM_LOCAL_H */
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index cecc79772c94..20174d0c0527 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -1337,13 +1337,12 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream)
+ int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
+ {
+ unsigned long flags;
+- int ret = 0;
+
+ snd_pcm_stream_lock_irqsave(substream, flags);
+ if (snd_pcm_running(substream))
+- ret = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
++ __snd_pcm_xrun(substream);
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+- return ret;
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
+
+@@ -1591,7 +1590,8 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
+ result = 0; /* already there */
+ break;
+ case SNDRV_PCM_STATE_RUNNING:
+- result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
++ __snd_pcm_xrun(substream);
++ result = 0;
+ break;
+ default:
+ result = -EBADFD;
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-tracepoints-for-refining-PCM-parameters.patch b/patches.drivers/ALSA-pcm-tracepoints-for-refining-PCM-parameters.patch
new file mode 100644
index 0000000000..38c1b454fc
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-tracepoints-for-refining-PCM-parameters.patch
@@ -0,0 +1,287 @@
+From be4e31dab0e14c1f6fa5c03b33056058b93316e2 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Wed, 7 Jun 2017 08:46:43 +0900
+Subject: [PATCH] ALSA: pcm: tracepoints for refining PCM parameters
+Git-commit: be4e31dab0e14c1f6fa5c03b33056058b93316e2
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+When working for devices which support configurable modes for its data
+transmission or which consists of several components, developers are
+likely to use rules of parameters of PCM substream. However, there's no
+infrastructure to assist their work.
+
+In old days, ALSA PCM core got a local 'RULES_DEBUG' macro to debug
+refinement of parameters for PCM substream. Although this is merely a
+makeshift. With some modifications, we get the infrastructure.
+
+This commit is for the purpose. Refinement of mask/interval type of
+PCM parameters is probed as tracepoint events as 'hw_mask_param' and
+'hw_interval_param' on existent 'snd_pcm' subsystem.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/Makefile | 1 +
+ sound/core/pcm_native.c | 33 ++++++++
+ sound/core/pcm_param_trace.h | 142 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 176 insertions(+)
+ create mode 100644 sound/core/pcm_param_trace.h
+
+diff --git a/sound/core/Makefile b/sound/core/Makefile
+index e85d9dd12c2d..a8514b313a89 100644
+--- a/sound/core/Makefile
++++ b/sound/core/Makefile
+@@ -22,6 +22,7 @@ snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o
+
+ # for trace-points
+ CFLAGS_pcm_lib.o := -I$(src)
++CFLAGS_pcm_native.o := -I$(src)
+
+ snd-pcm-dmaengine-objs := pcm_dmaengine.o
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index bf5d0f2acfb9..b98b3ccde4f0 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -39,6 +39,9 @@
+
+ #include "pcm_local.h"
+
++#define CREATE_TRACE_POINTS
++#include "pcm_param_trace.h"
++
+ /*
+ * Compatibility
+ */
+@@ -279,6 +282,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ unsigned int stamp = 2;
+ int changed, again;
+
++ struct snd_mask __maybe_unused old_mask;
++ struct snd_interval __maybe_unused old_interval;
++
+ params->info = 0;
+ params->fifo_size = 0;
+ if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
+@@ -294,6 +300,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ return -EINVAL;
+ if (!(params->rmask & (1 << k)))
+ continue;
++
++ if (trace_hw_mask_param_enabled())
++ old_mask = *m;
+ #ifdef RULES_DEBUG
+ pr_debug("%s = ", snd_pcm_hw_param_names[k]);
+ pr_cont("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
+@@ -302,6 +311,8 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ #ifdef RULES_DEBUG
+ pr_cont("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
+ #endif
++ trace_hw_mask_param(substream, k, 0, &old_mask, m);
++
+ if (changed)
+ params->cmask |= 1 << k;
+ if (changed < 0)
+@@ -314,6 +325,9 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ return -EINVAL;
+ if (!(params->rmask & (1 << k)))
+ continue;
++
++ if (trace_hw_interval_param_enabled())
++ old_interval = *i;
+ #ifdef RULES_DEBUG
+ pr_debug("%s = ", snd_pcm_hw_param_names[k]);
+ if (i->empty)
+@@ -333,6 +347,8 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ i->openmin ? '(' : '[', i->min,
+ i->max, i->openmax ? ')' : ']');
+ #endif
++ trace_hw_interval_param(substream, k, 0, &old_interval, i);
++
+ if (changed)
+ params->cmask |= 1 << k;
+ if (changed < 0)
+@@ -359,6 +375,15 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ }
+ if (!doit)
+ continue;
++
++ if (trace_hw_mask_param_enabled()) {
++ if (hw_is_mask(r->var))
++ old_mask = *hw_param_mask(params, r->var);
++ }
++ if (trace_hw_interval_param_enabled()) {
++ if (hw_is_interval(r->var))
++ old_interval = *hw_param_interval(params, r->var);
++ }
+ #ifdef RULES_DEBUG
+ pr_debug("Rule %d [%p]: ", k, r->func);
+ if (r->var >= 0) {
+@@ -394,6 +419,14 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ }
+ pr_cont("\n");
+ #endif
++ if (hw_is_mask(r->var)) {
++ trace_hw_mask_param(substream, r->var, k + 1,
++ &old_mask, hw_param_mask(params, r->var));
++ }
++ if (hw_is_interval(r->var)) {
++ trace_hw_interval_param(substream, r->var, k + 1,
++ &old_interval, hw_param_interval(params, r->var));
++ }
+ rstamps[k] = stamp;
+ if (changed && r->var >= 0) {
+ params->cmask |= (1 << r->var);
+diff --git a/sound/core/pcm_param_trace.h b/sound/core/pcm_param_trace.h
+new file mode 100644
+index 000000000000..872922326b38
+--- /dev/null
++++ b/sound/core/pcm_param_trace.h
+@@ -0,0 +1,142 @@
++#undef TRACE_SYSTEM
++#define TRACE_SYSTEM snd_pcm
++
++#if !defined(_PCM_PARAMS_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
++#define _PCM_PARAMS_TRACE_H
++
++#include <linux/tracepoint.h>
++
++#define HW_PARAM_ENTRY(param) {SNDRV_PCM_HW_PARAM_##param, #param}
++#define hw_param_labels \
++ HW_PARAM_ENTRY(ACCESS), \
++ HW_PARAM_ENTRY(FORMAT), \
++ HW_PARAM_ENTRY(SUBFORMAT), \
++ HW_PARAM_ENTRY(SAMPLE_BITS), \
++ HW_PARAM_ENTRY(FRAME_BITS), \
++ HW_PARAM_ENTRY(CHANNELS), \
++ HW_PARAM_ENTRY(RATE), \
++ HW_PARAM_ENTRY(PERIOD_TIME), \
++ HW_PARAM_ENTRY(PERIOD_SIZE), \
++ HW_PARAM_ENTRY(PERIOD_BYTES), \
++ HW_PARAM_ENTRY(PERIODS), \
++ HW_PARAM_ENTRY(BUFFER_TIME), \
++ HW_PARAM_ENTRY(BUFFER_SIZE), \
++ HW_PARAM_ENTRY(BUFFER_BYTES), \
++ HW_PARAM_ENTRY(TICK_TIME)
++
++TRACE_EVENT(hw_mask_param,
++ TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_mask *prev, const struct snd_mask *curr),
++ TP_ARGS(substream, type, index, prev, curr),
++ TP_STRUCT__entry(
++ __field(int, card)
++ __field(int, device)
++ __field(int, subdevice)
++ __field(int, direction)
++ __field(snd_pcm_hw_param_t, type)
++ __field(int, index)
++ __field(int, total)
++ __array(__u32, prev_bits, 8)
++ __array(__u32, curr_bits, 8)
++ ),
++ TP_fast_assign(
++ __entry->card = substream->pcm->card->number;
++ __entry->device = substream->pcm->device;
++ __entry->subdevice = substream->number;
++ __entry->direction = substream->stream;
++ __entry->type = type;
++ __entry->index = index;
++ __entry->total = substream->runtime->hw_constraints.rules_num;
++ memcpy(__entry->prev_bits, prev->bits, sizeof(__u32) * 8);
++ memcpy(__entry->curr_bits, curr->bits, sizeof(__u32) * 8);
++ ),
++ TP_printk("%d,%d,%d,%d %03d/%03d %s %08x%08x%08x%08x %08x%08x%08x%08x",
++ __entry->card,
++ __entry->device,
++ __entry->subdevice,
++ __entry->direction,
++ __entry->index,
++ __entry->total,
++ __print_symbolic(__entry->type, hw_param_labels),
++ __entry->prev_bits[3], __entry->prev_bits[2],
++ __entry->prev_bits[1], __entry->prev_bits[0],
++ __entry->curr_bits[3], __entry->curr_bits[2],
++ __entry->curr_bits[1], __entry->curr_bits[0]
++ )
++);
++
++TRACE_EVENT(hw_interval_param,
++ TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_interval *prev, const struct snd_interval *curr),
++ TP_ARGS(substream, type, index, prev, curr),
++ TP_STRUCT__entry(
++ __field(int, card)
++ __field(int, device)
++ __field(int, subdevice)
++ __field(int, direction)
++ __field(snd_pcm_hw_param_t, type)
++ __field(int, index)
++ __field(int, total)
++ __field(unsigned int, prev_min)
++ __field(unsigned int, prev_max)
++ __field(unsigned int, prev_openmin)
++ __field(unsigned int, prev_openmax)
++ __field(unsigned int, prev_integer)
++ __field(unsigned int, prev_empty)
++ __field(unsigned int, curr_min)
++ __field(unsigned int, curr_max)
++ __field(unsigned int, curr_openmin)
++ __field(unsigned int, curr_openmax)
++ __field(unsigned int, curr_integer)
++ __field(unsigned int, curr_empty)
++ ),
++ TP_fast_assign(
++ __entry->card = substream->pcm->card->number;
++ __entry->device = substream->pcm->device;
++ __entry->subdevice = substream->number;
++ __entry->direction = substream->stream;
++ __entry->type = type;
++ __entry->index = index;
++ __entry->total = substream->runtime->hw_constraints.rules_num;
++ __entry->prev_min = prev->min;
++ __entry->prev_max = prev->max;
++ __entry->prev_openmin = prev->openmin;
++ __entry->prev_openmax = prev->openmax;
++ __entry->prev_integer = prev->integer;
++ __entry->prev_empty = prev->empty;
++ __entry->curr_min = curr->min;
++ __entry->curr_max = curr->max;
++ __entry->curr_openmin = curr->openmin;
++ __entry->curr_openmax = curr->openmax;
++ __entry->curr_integer = curr->integer;
++ __entry->curr_empty = curr->empty;
++ ),
++ TP_printk("%d,%d,%d,%d %03d/%03d %s %d %d %s%u %u%s %d %d %s%u %u%s",
++ __entry->card,
++ __entry->device,
++ __entry->subdevice,
++ __entry->direction,
++ __entry->index,
++ __entry->total,
++ __print_symbolic(__entry->type, hw_param_labels),
++ __entry->prev_empty,
++ __entry->prev_integer,
++ __entry->prev_openmin ? "(" : "[",
++ __entry->prev_min,
++ __entry->prev_max,
++ __entry->prev_openmax ? ")" : "]",
++ __entry->curr_empty,
++ __entry->curr_integer,
++ __entry->curr_openmin ? "(" : "[",
++ __entry->curr_min,
++ __entry->curr_max,
++ __entry->curr_openmax ? ")" : "]"
++ )
++);
++
++#endif /* _PCM_PARAMS_TRACE_H */
++
++/* This part must be outside protection */
++#undef TRACE_INCLUDE_PATH
++#define TRACE_INCLUDE_PATH .
++#undef TRACE_INCLUDE_FILE
++#define TRACE_INCLUDE_FILE pcm_param_trace
++#include <trace/define_trace.h>
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-unify-codes-to-operate-application-side-pos.patch b/patches.drivers/ALSA-pcm-unify-codes-to-operate-application-side-pos.patch
new file mode 100644
index 0000000000..278cdd9b33
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-unify-codes-to-operate-application-side-pos.patch
@@ -0,0 +1,135 @@
+From 66e01a5cf63f2b132059d0d3d78ed737207489f2 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Mon, 12 Jun 2017 09:41:44 +0900
+Subject: [PATCH] ALSA: pcm: unify codes to operate application-side position on PCM buffer
+Git-commit: 66e01a5cf63f2b132059d0d3d78ed737207489f2
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+In a series of recent work, ALSA PCM core got some arrangements to handle
+application-side position on PCM buffer. However, relevant codes still
+disperse to two translation units
+
+This commit unifies these codes into a helper function.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_lib.c | 27 ++++++++++++++++++++++++---
+ sound/core/pcm_local.h | 2 ++
+ sound/core/pcm_native.c | 28 ++++------------------------
+ 3 files changed, 30 insertions(+), 27 deletions(-)
+
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2101,6 +2101,27 @@ static int pcm_accessible_state(struct s
+ }
+ }
+
++/* update to the given appl_ptr and call ack callback if needed;
++ * when an error is returned, take back to the original value
++ */
++int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t appl_ptr)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr;
++ int ret;
++
++ runtime->control->appl_ptr = appl_ptr;
++ if (substream->ops->ack) {
++ ret = substream->ops->ack(substream);
++ if (ret < 0) {
++ runtime->control->appl_ptr = old_appl_ptr;
++ return ret;
++ }
++ }
++ return 0;
++}
++
+ /* the common loop for read/write data */
+ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ void *data, bool interleaved,
+@@ -2220,9 +2241,9 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(str
+ appl_ptr += frames;
+ if (appl_ptr >= runtime->boundary)
+ appl_ptr -= runtime->boundary;
+- runtime->control->appl_ptr = appl_ptr;
+- if (substream->ops->ack)
+- substream->ops->ack(substream);
++ err = pcm_lib_apply_appl_ptr(substream, appl_ptr);
++ if (err < 0)
++ goto _end_unlock;
+
+ offset += frames;
+ size -= frames;
+--- a/sound/core/pcm_local.h
++++ b/sound/core/pcm_local.h
+@@ -27,6 +27,8 @@ int snd_pcm_hw_constraints_complete(stru
+ int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime,
+ snd_pcm_hw_param_t var, u_int32_t mask);
+
++int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t appl_ptr);
+ int snd_pcm_update_state(struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime);
+ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -2598,27 +2598,6 @@ static int do_pcm_hwsync(struct snd_pcm_
+ }
+ }
+
+-/* update to the given appl_ptr and call ack callback if needed;
+- * when an error is returned, take back to the original value
+- */
+-static int apply_appl_ptr(struct snd_pcm_substream *substream,
+- snd_pcm_uframes_t appl_ptr)
+-{
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr;
+- int ret;
+-
+- runtime->control->appl_ptr = appl_ptr;
+- if (substream->ops->ack) {
+- ret = substream->ops->ack(substream);
+- if (ret < 0) {
+- runtime->control->appl_ptr = old_appl_ptr;
+- return ret;
+- }
+- }
+- return 0;
+-}
+-
+ /* increase the appl_ptr; returns the processed frames or a negative error */
+ static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames,
+@@ -2635,7 +2614,7 @@ static snd_pcm_sframes_t forward_appl_pt
+ appl_ptr = runtime->control->appl_ptr + frames;
+ if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
+ appl_ptr -= runtime->boundary;
+- ret = apply_appl_ptr(substream, appl_ptr);
++ ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
+ return ret < 0 ? ret : frames;
+ }
+
+@@ -2655,7 +2634,7 @@ static snd_pcm_sframes_t rewind_appl_ptr
+ appl_ptr = runtime->control->appl_ptr - frames;
+ if (appl_ptr < 0)
+ appl_ptr += runtime->boundary;
+- ret = apply_appl_ptr(substream, appl_ptr);
++ ret = pcm_lib_apply_appl_ptr(substream, appl_ptr);
+ return ret < 0 ? ret : frames;
+ }
+
+@@ -2783,7 +2762,8 @@ static int snd_pcm_sync_ptr(struct snd_p
+ }
+ snd_pcm_stream_lock_irq(substream);
+ if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
+- err = apply_appl_ptr(substream, sync_ptr.c.control.appl_ptr);
++ err = pcm_lib_apply_appl_ptr(substream,
++ sync_ptr.c.control.appl_ptr);
+ if (err < 0) {
+ snd_pcm_stream_unlock_irq(substream);
+ return err;
diff --git a/patches.drivers/ALSA-pcm-use-do-while-0-for-empty-macro.patch b/patches.drivers/ALSA-pcm-use-do-while-0-for-empty-macro.patch
new file mode 100644
index 0000000000..f1e0bfb6ed
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-use-do-while-0-for-empty-macro.patch
@@ -0,0 +1,41 @@
+From 9aee03f39c13fc674f5973baa69d13e32b45b535 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Thu, 18 May 2017 15:35:54 +0200
+Subject: [PATCH] ALSA: pcm: use "do {} while (0)" for empty macro
+Git-commit: 9aee03f39c13fc674f5973baa69d13e32b45b535
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Recent compilers produce a harmless warning for the new pcm_call_notify()
+macro when CONFIG_SND_PCM_OSS is disabled:
+
+Sound/core/pcm.c: In function 'snd_pcm_free':
+sound/core/pcm.c:905:37: error: suggest braces around empty body in an 'if' statement [-Werror=empty-body]
+
+This turns the empty macro into a 'do {} while (0)' statement to avoid
+the warning.
+
+Fixes: 58f30d650c7f ("ALSA: pcm: Build pcm notifier code conditionally")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/core/pcm.c b/sound/core/pcm.c
+index 24acbfb5c531..d30dba0ee688 100644
+--- a/sound/core/pcm.c
++++ b/sound/core/pcm.c
+@@ -894,7 +894,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
+ _notify->call(pcm); \
+ } while (0)
+ #else
+-#define pcm_call_notify(pcm, call) /* NOP */
++#define pcm_call_notify(pcm, call) do {} while (0)
+ #endif
+
+ static int snd_pcm_free(struct snd_pcm *pcm)
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-use-friendly-name-for-id-of-PCM-substream-i.patch b/patches.drivers/ALSA-pcm-use-friendly-name-for-id-of-PCM-substream-i.patch
new file mode 100644
index 0000000000..8bac0f7f0d
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-use-friendly-name-for-id-of-PCM-substream-i.patch
@@ -0,0 +1,54 @@
+From 6baca010c71176f406299ea1949e721ab995ff01 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 21:46:50 +0900
+Subject: [PATCH] ALSA: pcm: use friendly name for id of PCM substream in trace print
+Git-commit: 6baca010c71176f406299ea1949e721ab995ff01
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+Use the same print format of snd_pcm_debug_name() for userspace tracing
+program.
+
+Suggested-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_param_trace.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/sound/core/pcm_param_trace.h b/sound/core/pcm_param_trace.h
+index 872922326b38..86c8d658a25c 100644
+--- a/sound/core/pcm_param_trace.h
++++ b/sound/core/pcm_param_trace.h
+@@ -49,11 +49,11 @@ TRACE_EVENT(hw_mask_param,
+ memcpy(__entry->prev_bits, prev->bits, sizeof(__u32) * 8);
+ memcpy(__entry->curr_bits, curr->bits, sizeof(__u32) * 8);
+ ),
+- TP_printk("%d,%d,%d,%d %03d/%03d %s %08x%08x%08x%08x %08x%08x%08x%08x",
++ TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %08x%08x%08x%08x %08x%08x%08x%08x",
+ __entry->card,
+ __entry->device,
++ __entry->direction ? "c" : "p",
+ __entry->subdevice,
+- __entry->direction,
+ __entry->index,
+ __entry->total,
+ __print_symbolic(__entry->type, hw_param_labels),
+@@ -109,11 +109,11 @@ TRACE_EVENT(hw_interval_param,
+ __entry->curr_integer = curr->integer;
+ __entry->curr_empty = curr->empty;
+ ),
+- TP_printk("%d,%d,%d,%d %03d/%03d %s %d %d %s%u %u%s %d %d %s%u %u%s",
++ TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %d %d %s%u %u%s %d %d %s%u %u%s",
+ __entry->card,
+ __entry->device,
++ __entry->direction ? "c" : "p",
+ __entry->subdevice,
+- __entry->direction,
+ __entry->index,
+ __entry->total,
+ __print_symbolic(__entry->type, hw_param_labels),
+--
+2.20.1
+
diff --git a/patches.drivers/ALSA-pcm-use-goto-statement-instead-of-while-stateme.patch b/patches.drivers/ALSA-pcm-use-goto-statement-instead-of-while-stateme.patch
new file mode 100644
index 0000000000..9d6136f8f8
--- /dev/null
+++ b/patches.drivers/ALSA-pcm-use-goto-statement-instead-of-while-stateme.patch
@@ -0,0 +1,129 @@
+From 0d4e399965738bb90dcee2fd5aeb15c1ccc81b42 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 9 Jun 2017 06:37:02 +0900
+Subject: [PATCH] ALSA: pcm: use goto statement instead of while statement to reduce indentation
+Git-commit: 0d4e399965738bb90dcee2fd5aeb15c1ccc81b42
+Patch-mainline: v4.13-rc1
+References: bsc#1121278
+
+In a process to calculate parameters of PCM substream, application of all
+rules is iterated several times till parameter dependencies are satisfied.
+In current implementation, two loops are used for the design, however this
+brings two-level indentation and decline readability.
+
+This commit attempts to reduce the indentation by using goto statement,
+instead of outer while loop.
+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/core/pcm_native.c | 86 +++++++++++++++++++++--------------------
+ 1 file changed, 44 insertions(+), 42 deletions(-)
+
+diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
+index 000e6e9a0c2b..41aeb6facdec 100644
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -337,54 +337,56 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
+ rstamps[k] = 0;
+ for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
+ vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
+- do {
+- again = 0;
+- for (k = 0; k < constrs->rules_num; k++) {
+- struct snd_pcm_hw_rule *r = &constrs->rules[k];
+- unsigned int d;
+- int doit = 0;
+- if (r->cond && !(r->cond & params->flags))
+- continue;
+- for (d = 0; r->deps[d] >= 0; d++) {
+- if (vstamps[r->deps[d]] > rstamps[k]) {
+- doit = 1;
+- break;
+- }
++retry:
++ again = 0;
++ for (k = 0; k < constrs->rules_num; k++) {
++ struct snd_pcm_hw_rule *r = &constrs->rules[k];
++ unsigned int d;
++ int doit = 0;
++ if (r->cond && !(r->cond & params->flags))
++ continue;
++ for (d = 0; r->deps[d] >= 0; d++) {
++ if (vstamps[r->deps[d]] > rstamps[k]) {
++ doit = 1;
++ break;
+ }
+- if (!doit)
+- continue;
++ }
++ if (!doit)
++ continue;
+
+- if (trace_hw_mask_param_enabled()) {
+- if (hw_is_mask(r->var))
+- old_mask = *hw_param_mask(params, r->var);
+- }
+- if (trace_hw_interval_param_enabled()) {
+- if (hw_is_interval(r->var))
+- old_interval = *hw_param_interval(params, r->var);
+- }
++ if (trace_hw_mask_param_enabled()) {
++ if (hw_is_mask(r->var))
++ old_mask = *hw_param_mask(params, r->var);
++ }
++ if (trace_hw_interval_param_enabled()) {
++ if (hw_is_interval(r->var))
++ old_interval = *hw_param_interval(params, r->var);
++ }
+
+- changed = r->func(params, r);
++ changed = r->func(params, r);
+
+- if (hw_is_mask(r->var)) {
+- trace_hw_mask_param(substream, r->var, k + 1,
+- &old_mask, hw_param_mask(params, r->var));