From c6e2d363a04085c0f5c4542a94654bfcd619df32 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 4 Jul 2014 15:10:48 -0700 Subject: [PATCH] 3.14-stable patches added patches: alsa-hda-adjust-speaker-hpf-and-add-led-support-for-hp-spectre-13.patch alsa-hda-hdmi-call-overridden-init-on-resume.patch alsa-usb-audio-fix-races-at-disconnection-and-pcm-closing.patch documentation-submittingpatches-describe-the-fixes-tag.patch tracing-fix-syscall_-regfunc-vs-copy_process-race.patch tracing-try-again-for-saved-cmdline-if-failed-due-to-locking.patch --- ...nd-add-led-support-for-hp-spectre-13.patch | 134 ++++++++++++++++++ ...-hdmi-call-overridden-init-on-resume.patch | 35 +++++ ...ces-at-disconnection-and-pcm-closing.patch | 124 ++++++++++++++++ ...ittingpatches-describe-the-fixes-tag.patch | 70 +++++++++ queue-3.14/series | 6 + ...yscall_-regfunc-vs-copy_process-race.patch | 72 ++++++++++ ...ved-cmdline-if-failed-due-to-locking.patch | 79 +++++++++++ 7 files changed, 520 insertions(+) create mode 100644 queue-3.14/alsa-hda-adjust-speaker-hpf-and-add-led-support-for-hp-spectre-13.patch create mode 100644 queue-3.14/alsa-hda-hdmi-call-overridden-init-on-resume.patch create mode 100644 queue-3.14/alsa-usb-audio-fix-races-at-disconnection-and-pcm-closing.patch create mode 100644 queue-3.14/documentation-submittingpatches-describe-the-fixes-tag.patch create mode 100644 queue-3.14/tracing-fix-syscall_-regfunc-vs-copy_process-race.patch create mode 100644 queue-3.14/tracing-try-again-for-saved-cmdline-if-failed-due-to-locking.patch diff --git a/queue-3.14/alsa-hda-adjust-speaker-hpf-and-add-led-support-for-hp-spectre-13.patch b/queue-3.14/alsa-hda-adjust-speaker-hpf-and-add-led-support-for-hp-spectre-13.patch new file mode 100644 index 00000000000..ed9a2c2a7c4 --- /dev/null +++ b/queue-3.14/alsa-hda-adjust-speaker-hpf-and-add-led-support-for-hp-spectre-13.patch @@ -0,0 +1,134 @@ +From 8b3dfdaf0c25a584cb31d04d2574115cf2d422ab Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 24 Jun 2014 13:55:25 +0200 +Subject: ALSA: hda - Adjust speaker HPF and add LED support for HP Spectre 13 + +From: Takashi Iwai + +commit 8b3dfdaf0c25a584cb31d04d2574115cf2d422ab upstream. + +HP Spectre 13 has the IDT 92HD95 codec, and BIOS seems to set the +default high-pass filter in some "safer" range, which results in the +very soft tone from the built-in speakers in contrast to Windows. +Also, the mute LED control is missing, since 92HD95 codec still has no +HP-specific fixups for GPIO setups. + +This patch adds these missing features: the HPF is adjusted by the +vendor-specific verb, and the LED is set up from a DMI string (but +with the default polarity = 0 assumption due to the incomplete BIOS on +the given machine). + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=74841 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/sound/alsa/HD-Audio-Models.txt | 5 ++ + sound/pci/hda/patch_sigmatel.c | 58 ++++++++++++++++++++++++++- + 2 files changed, 62 insertions(+), 1 deletion(-) + +--- a/Documentation/sound/alsa/HD-Audio-Models.txt ++++ b/Documentation/sound/alsa/HD-Audio-Models.txt +@@ -286,6 +286,11 @@ STAC92HD83* + hp-inv-led HP with broken BIOS for inverted mute LED + auto BIOS setup (default) + ++STAC92HD95 ++========== ++ hp-led LED support for HP laptops ++ hp-bass Bass HPF setup for HP Spectre 13 ++ + STAC9872 + ======== + vaio VAIO laptop without SPDIF +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -122,6 +122,12 @@ enum { + }; + + enum { ++ STAC_92HD95_HP_LED, ++ STAC_92HD95_HP_BASS, ++ STAC_92HD95_MODELS ++}; ++ ++enum { + STAC_925x_REF, + STAC_M1, + STAC_M1_2, +@@ -4125,6 +4131,48 @@ static const struct snd_pci_quirk stac92 + {} /* terminator */ + }; + ++static void stac92hd95_fixup_hp_led(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ struct sigmatel_spec *spec = codec->spec; ++ ++ if (action != HDA_FIXUP_ACT_PRE_PROBE) ++ return; ++ ++ if (find_mute_led_cfg(codec, spec->default_polarity)) ++ codec_dbg(codec, "mute LED gpio %d polarity %d\n", ++ spec->gpio_led, ++ spec->gpio_led_polarity); ++} ++ ++static const struct hda_fixup stac92hd95_fixups[] = { ++ [STAC_92HD95_HP_LED] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = stac92hd95_fixup_hp_led, ++ }, ++ [STAC_92HD95_HP_BASS] = { ++ .type = HDA_FIXUP_VERBS, ++ .v.verbs = (const struct hda_verb[]) { ++ {0x1a, 0x795, 0x00}, /* HPF to 100Hz */ ++ {} ++ }, ++ .chained = true, ++ .chain_id = STAC_92HD95_HP_LED, ++ }, ++}; ++ ++static const struct snd_pci_quirk stac92hd95_fixup_tbl[] = { ++ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1911, "HP Spectre 13", STAC_92HD95_HP_BASS), ++ {} /* terminator */ ++}; ++ ++static const struct hda_model_fixup stac92hd95_models[] = { ++ { .id = STAC_92HD95_HP_LED, .name = "hp-led" }, ++ { .id = STAC_92HD95_HP_BASS, .name = "hp-bass" }, ++ {} ++}; ++ ++ + static int stac_parse_auto_config(struct hda_codec *codec) + { + struct sigmatel_spec *spec = codec->spec; +@@ -4577,10 +4625,16 @@ static int patch_stac92hd95(struct hda_c + spec->gen.beep_nid = 0x19; /* digital beep */ + spec->pwr_nids = stac92hd95_pwr_nids; + spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids); +- spec->default_polarity = -1; /* no default cfg */ ++ spec->default_polarity = 0; + + codec->patch_ops = stac_patch_ops; + ++ snd_hda_pick_fixup(codec, stac92hd95_models, stac92hd95_fixup_tbl, ++ stac92hd95_fixups); ++ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); ++ ++ stac_setup_gpio(codec); ++ + err = stac_parse_auto_config(codec); + if (err < 0) { + stac_free(codec); +@@ -4589,6 +4643,8 @@ static int patch_stac92hd95(struct hda_c + + codec->proc_widget_hook = stac92hd_proc_hook; + ++ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); ++ + return 0; + } + diff --git a/queue-3.14/alsa-hda-hdmi-call-overridden-init-on-resume.patch b/queue-3.14/alsa-hda-hdmi-call-overridden-init-on-resume.patch new file mode 100644 index 00000000000..769694e1488 --- /dev/null +++ b/queue-3.14/alsa-hda-hdmi-call-overridden-init-on-resume.patch @@ -0,0 +1,35 @@ +From a283368382c50345dff61525f493ea307f21ec9b Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Wed, 18 Jun 2014 21:48:09 +0200 +Subject: ALSA: hda - hdmi: call overridden init on resume + +From: Pierre Ossman + +commit a283368382c50345dff61525f493ea307f21ec9b upstream. + +We need to call the proper init function in case it has been +overridden, as it might restore things that the generic routing +doesn't know anything about. E.g. AMD cards have special verbs +that need resetting. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=77901 +Fixes: 5a61358433b1 ('ALSA: hda - hdmi: Add ATI/AMD multi-channel audio support') +Signed-off-by: Pierre Ossman +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_hdmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -2165,7 +2165,7 @@ static int generic_hdmi_resume(struct hd + struct hdmi_spec *spec = codec->spec; + int pin_idx; + +- generic_hdmi_init(codec); ++ codec->patch_ops.init(codec); + snd_hda_codec_resume_amp(codec); + snd_hda_codec_resume_cache(codec); + diff --git a/queue-3.14/alsa-usb-audio-fix-races-at-disconnection-and-pcm-closing.patch b/queue-3.14/alsa-usb-audio-fix-races-at-disconnection-and-pcm-closing.patch new file mode 100644 index 00000000000..832b53abc92 --- /dev/null +++ b/queue-3.14/alsa-usb-audio-fix-races-at-disconnection-and-pcm-closing.patch @@ -0,0 +1,124 @@ +From 92a586bdc06de6629dae1b357dac221253f55ff8 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 25 Jun 2014 14:24:47 +0200 +Subject: ALSA: usb-audio: Fix races at disconnection and PCM closing + +From: Takashi Iwai + +commit 92a586bdc06de6629dae1b357dac221253f55ff8 upstream. + +When a USB-audio device is disconnected while PCM is still running, we +still see some race: the disconnect callback calls +snd_usb_endpoint_free() that calls release_urbs() and then kfree() +while a PCM stream would be closed at the same time and calls +stop_endpoints() that leads to wait_clear_urbs(). That is, the EP +object might be deallocated while a PCM stream is syncing with +wait_clear_urbs() with the same EP. + +Basically calling multiple wait_clear_urbs() would work fine, also +calling wait_clear_urbs() and release_urbs() would work, too, as +wait_clear_urbs() just reads some fields in ep. The problem is the +succeeding kfree() in snd_pcm_endpoint_free(). + +This patch moves out the EP deallocation into the later point, the +destructor callback. At this stage, all PCMs must have been already +closed, so it's safe to free the objects. + +Reported-by: Alan Stern +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/card.c | 13 ++++++++++--- + sound/usb/endpoint.c | 17 ++++++++++++++--- + sound/usb/endpoint.h | 1 + + 3 files changed, 25 insertions(+), 6 deletions(-) + +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -304,6 +304,11 @@ static int snd_usb_create_streams(struct + + static int snd_usb_audio_free(struct snd_usb_audio *chip) + { ++ struct list_head *p, *n; ++ ++ list_for_each_safe(p, n, &chip->ep_list) ++ snd_usb_endpoint_free(p); ++ + mutex_destroy(&chip->mutex); + kfree(chip); + return 0; +@@ -580,7 +585,7 @@ static void snd_usb_audio_disconnect(str + struct snd_usb_audio *chip) + { + struct snd_card *card; +- struct list_head *p, *n; ++ struct list_head *p; + + if (chip == (void *)-1L) + return; +@@ -593,14 +598,16 @@ static void snd_usb_audio_disconnect(str + mutex_lock(®ister_mutex); + chip->num_interfaces--; + if (chip->num_interfaces <= 0) { ++ struct snd_usb_endpoint *ep; ++ + snd_card_disconnect(card); + /* release the pcm resources */ + list_for_each(p, &chip->pcm_list) { + snd_usb_stream_disconnect(p); + } + /* release the endpoint resources */ +- list_for_each_safe(p, n, &chip->ep_list) { +- snd_usb_endpoint_free(p); ++ list_for_each_entry(ep, &chip->ep_list, list) { ++ snd_usb_endpoint_release(ep); + } + /* release the midi resources */ + list_for_each(p, &chip->midi_list) { +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -981,19 +981,30 @@ void snd_usb_endpoint_deactivate(struct + } + + /** ++ * snd_usb_endpoint_release: Tear down an snd_usb_endpoint ++ * ++ * @ep: the endpoint to release ++ * ++ * This function does not care for the endpoint's use count but will tear ++ * down all the streaming URBs immediately. ++ */ ++void snd_usb_endpoint_release(struct snd_usb_endpoint *ep) ++{ ++ release_urbs(ep, 1); ++} ++ ++/** + * snd_usb_endpoint_free: Free the resources of an snd_usb_endpoint + * + * @ep: the list header of the endpoint to free + * +- * This function does not care for the endpoint's use count but will tear +- * down all the streaming URBs immediately and free all resources. ++ * This free all resources of the given ep. + */ + void snd_usb_endpoint_free(struct list_head *head) + { + struct snd_usb_endpoint *ep; + + ep = list_entry(head, struct snd_usb_endpoint, list); +- release_urbs(ep, 1); + kfree(ep); + } + +--- a/sound/usb/endpoint.h ++++ b/sound/usb/endpoint.h +@@ -23,6 +23,7 @@ void snd_usb_endpoint_stop(struct snd_us + void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); + int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); + void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); ++void snd_usb_endpoint_release(struct snd_usb_endpoint *ep); + void snd_usb_endpoint_free(struct list_head *head); + + int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep); diff --git a/queue-3.14/documentation-submittingpatches-describe-the-fixes-tag.patch b/queue-3.14/documentation-submittingpatches-describe-the-fixes-tag.patch new file mode 100644 index 00000000000..1984040ce3a --- /dev/null +++ b/queue-3.14/documentation-submittingpatches-describe-the-fixes-tag.patch @@ -0,0 +1,70 @@ +From 8401aa1f59975c03eeebd3ac6d264cbdfe9af5de Mon Sep 17 00:00:00 2001 +From: Jacob Keller +Date: Fri, 6 Jun 2014 14:36:39 -0700 +Subject: Documentation/SubmittingPatches: describe the Fixes: tag + +From: Jacob Keller + +commit 8401aa1f59975c03eeebd3ac6d264cbdfe9af5de upstream. + +Update the SubmittingPatches process to include howto about the new +'Fixes:' tag to be used when a patch fixes an issue in a previous commit +(found by git-bisect for example). + +Signed-off-by: Jacob Keller +Tested-by: Aaron Brown +Signed-off-by: Jeff Kirsher +Cc: Randy Dunlap +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/SubmittingPatches | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +--- a/Documentation/SubmittingPatches ++++ b/Documentation/SubmittingPatches +@@ -119,6 +119,20 @@ Example: + platform_set_drvdata(), but left the variable "dev" unused, + delete it. + ++If your patch fixes a bug in a specific commit, e.g. you found an issue using ++git-bisect, please use the 'Fixes:' tag with the first 12 characters of the ++SHA-1 ID, and the one line summary. ++Example: ++ ++ Fixes: e21d2170f366 ("video: remove unnecessary platform_set_drvdata()") ++ ++The following git-config settings can be used to add a pretty format for ++outputting the above style in the git log or git show commands ++ ++ [core] ++ abbrev = 12 ++ [pretty] ++ fixes = Fixes: %h (\"%s\") + + 3) Separate your changes. + +@@ -430,7 +444,7 @@ person it names. This tag documents tha + have been included in the discussion + + +-14) Using Reported-by:, Tested-by:, Reviewed-by: and Suggested-by: ++14) Using Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: and Fixes: + + If this patch fixes a problem reported by somebody else, consider adding a + Reported-by: tag to credit the reporter for their contribution. Please +@@ -485,6 +499,12 @@ idea was not posted in a public forum. T + idea reporters, they will, hopefully, be inspired to help us again in the + future. + ++A Fixes: tag indicates that the patch fixes an issue in a previous commit. It ++is used to make it easy to determine where a bug originated, which can help ++review a bug fix. This tag also assists the stable kernel team in determining ++which stable kernel versions should receive your fix. This is the preferred ++method for indicating a bug fixed by the patch. See #2 above for more details. ++ + + 15) The canonical patch format + diff --git a/queue-3.14/series b/queue-3.14/series index 9029c2ee941..abd3fc7085f 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -51,3 +51,9 @@ mips-kvm-fix-memory-leak-on-vcpu.patch ipvs-fix-panic-due-to-non-linear-skb.patch ptrace-x86-force-iret-path-after-a-ptrace_stop.patch lz4-add-overrun-checks-to-lz4_uncompress_unknownoutputsize.patch +documentation-submittingpatches-describe-the-fixes-tag.patch +tracing-try-again-for-saved-cmdline-if-failed-due-to-locking.patch +tracing-fix-syscall_-regfunc-vs-copy_process-race.patch +alsa-usb-audio-fix-races-at-disconnection-and-pcm-closing.patch +alsa-hda-hdmi-call-overridden-init-on-resume.patch +alsa-hda-adjust-speaker-hpf-and-add-led-support-for-hp-spectre-13.patch diff --git a/queue-3.14/tracing-fix-syscall_-regfunc-vs-copy_process-race.patch b/queue-3.14/tracing-fix-syscall_-regfunc-vs-copy_process-race.patch new file mode 100644 index 00000000000..3f082db0a3b --- /dev/null +++ b/queue-3.14/tracing-fix-syscall_-regfunc-vs-copy_process-race.patch @@ -0,0 +1,72 @@ +From 4af4206be2bd1933cae20c2b6fb2058dbc887f7c Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Sun, 13 Apr 2014 20:58:54 +0200 +Subject: tracing: Fix syscall_*regfunc() vs copy_process() race + +From: Oleg Nesterov + +commit 4af4206be2bd1933cae20c2b6fb2058dbc887f7c upstream. + +syscall_regfunc() and syscall_unregfunc() should set/clear +TIF_SYSCALL_TRACEPOINT system-wide, but do_each_thread() can race +with copy_process() and miss the new child which was not added to +the process/thread lists yet. + +Change copy_process() to update the child's TIF_SYSCALL_TRACEPOINT +under tasklist. + +Link: http://lkml.kernel.org/p/20140413185854.GB20668@redhat.com + +Fixes: a871bd33a6c0 "tracing: Add syscall tracepoints" +Acked-by: Frederic Weisbecker +Acked-by: Paul E. McKenney +Signed-off-by: Oleg Nesterov +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman + +--- + include/trace/syscall.h | 15 +++++++++++++++ + kernel/fork.c | 2 ++ + 2 files changed, 17 insertions(+) + +--- a/include/trace/syscall.h ++++ b/include/trace/syscall.h +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + #include + +@@ -32,4 +33,18 @@ struct syscall_metadata { + struct ftrace_event_call *exit_event; + }; + ++#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS) ++static inline void syscall_tracepoint_update(struct task_struct *p) ++{ ++ if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) ++ set_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT); ++ else ++ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT); ++} ++#else ++static inline void syscall_tracepoint_update(struct task_struct *p) ++{ ++} ++#endif ++ + #endif /* _TRACE_SYSCALL_H */ +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1484,7 +1484,9 @@ static struct task_struct *copy_process( + + total_forks++; + spin_unlock(¤t->sighand->siglock); ++ syscall_tracepoint_update(p); + write_unlock_irq(&tasklist_lock); ++ + proc_fork_connector(p); + cgroup_post_fork(p); + if (clone_flags & CLONE_THREAD) diff --git a/queue-3.14/tracing-try-again-for-saved-cmdline-if-failed-due-to-locking.patch b/queue-3.14/tracing-try-again-for-saved-cmdline-if-failed-due-to-locking.patch new file mode 100644 index 00000000000..f7515296940 --- /dev/null +++ b/queue-3.14/tracing-try-again-for-saved-cmdline-if-failed-due-to-locking.patch @@ -0,0 +1,79 @@ +From 379cfdac37923653c9d4242d10052378b7563005 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (Red Hat)" +Date: Fri, 30 May 2014 09:42:39 -0400 +Subject: tracing: Try again for saved cmdline if failed due to locking + +From: "Steven Rostedt (Red Hat)" + +commit 379cfdac37923653c9d4242d10052378b7563005 upstream. + +In order to prevent the saved cmdline cache from being filled when +tracing is not active, the comms are only recorded after a trace event +is recorded. + +The problem is, a comm can fail to be recorded if the trace_cmdline_lock +is held. That lock is taken via a trylock to allow it to happen from +any context (including NMI). If the lock fails to be taken, the comm +is skipped. No big deal, as we will try again later. + +But! Because of the code that was added to only record after an event, +we may not try again later as the recording is made as a oneshot per +event per CPU. + +Only disable the recording of the comm if the comm is actually recorded. + +Fixes: 7ffbd48d5cab "tracing: Cache comms only after an event occurred" +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/trace.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -1449,12 +1449,12 @@ static void tracing_stop_tr(struct trace + + void trace_stop_cmdline_recording(void); + +-static void trace_save_cmdline(struct task_struct *tsk) ++static int trace_save_cmdline(struct task_struct *tsk) + { + unsigned pid, idx; + + if (!tsk->pid || unlikely(tsk->pid > PID_MAX_DEFAULT)) +- return; ++ return 0; + + /* + * It's not the end of the world if we don't get +@@ -1463,7 +1463,7 @@ static void trace_save_cmdline(struct ta + * so if we miss here, then better luck next time. + */ + if (!arch_spin_trylock(&trace_cmdline_lock)) +- return; ++ return 0; + + idx = map_pid_to_cmdline[tsk->pid]; + if (idx == NO_CMDLINE_MAP) { +@@ -1488,6 +1488,8 @@ static void trace_save_cmdline(struct ta + memcpy(&saved_cmdlines[idx], tsk->comm, TASK_COMM_LEN); + + arch_spin_unlock(&trace_cmdline_lock); ++ ++ return 1; + } + + void trace_find_cmdline(int pid, char comm[]) +@@ -1529,9 +1531,8 @@ void tracing_record_cmdline(struct task_ + if (!__this_cpu_read(trace_cmdline_save)) + return; + +- __this_cpu_write(trace_cmdline_save, false); +- +- trace_save_cmdline(tsk); ++ if (trace_save_cmdline(tsk)) ++ __this_cpu_write(trace_cmdline_save, false); + } + + void -- 2.47.3