]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 4.14
authorSasha Levin <sashal@kernel.org>
Wed, 12 Feb 2020 03:57:54 +0000 (22:57 -0500)
committerSasha Levin <sashal@kernel.org>
Wed, 12 Feb 2020 03:57:54 +0000 (22:57 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.14/asoc-pcm-update-fe-be-trigger-order-based-on-the-com.patch [new file with mode: 0644]
queue-4.14/hv_sock-remove-the-accept-port-restriction.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/asoc-pcm-update-fe-be-trigger-order-based-on-the-com.patch b/queue-4.14/asoc-pcm-update-fe-be-trigger-order-based-on-the-com.patch
new file mode 100644 (file)
index 0000000..cb029d3
--- /dev/null
@@ -0,0 +1,185 @@
+From c0942f363b3af1f8cdc56ea2d3682647edceb514 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Nov 2019 14:48:11 -0800
+Subject: ASoC: pcm: update FE/BE trigger order based on the command
+
+From: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+
+[ Upstream commit acbf27746ecfa96b290b54cc7f05273482ea128a ]
+
+Currently, the trigger orders SND_SOC_DPCM_TRIGGER_PRE/POST
+determine the order in which FE DAI and BE DAI are triggered.
+In the case of SND_SOC_DPCM_TRIGGER_PRE, the FE DAI is
+triggered before the BE DAI and in the case of
+SND_SOC_DPCM_TRIGGER_POST, the BE DAI is triggered before
+the FE DAI. And this order remains the same irrespective of the
+trigger command.
+
+In the case of the SOF driver, during playback, the FW
+expects the BE DAI to be triggered before the FE DAI during
+the START trigger. The BE DAI trigger handles the starting of
+Link DMA and so it must be started before the FE DAI is started
+to prevent xruns during pause/release. This can be addressed
+by setting the trigger order for the FE dai link to
+SND_SOC_DPCM_TRIGGER_POST. But during the STOP trigger,
+the FW expects the FE DAI to be triggered before the BE DAI.
+Retaining the same order during the START and STOP commands,
+results in FW error as the DAI component in the FW is still
+active.
+
+The issue can be fixed by mirroring the trigger order of
+FE and BE DAI's during the START and STOP trigger. So, with the
+trigger order set to SND_SOC_DPCM_TRIGGER_PRE, the FE DAI will be
+trigger first during SNDRV_PCM_TRIGGER_START/STOP/RESUME
+and the BE DAI will be triggered first during the
+STOP/SUSPEND/PAUSE commands. Conversely, with the trigger order
+set to SND_SOC_DPCM_TRIGGER_POST, the BE DAI will be triggered
+first during the SNDRV_PCM_TRIGGER_START/STOP/RESUME commands
+and the FE DAI will be triggered first during the
+SNDRV_PCM_TRIGGER_STOP/SUSPEND/PAUSE commands.
+
+Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20191104224812.3393-2-ranjani.sridharan@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/soc-pcm.c | 95 ++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 68 insertions(+), 27 deletions(-)
+
+diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
+index 70e1a60a2e980..89f772ed47053 100644
+--- a/sound/soc/soc-pcm.c
++++ b/sound/soc/soc-pcm.c
+@@ -2123,42 +2123,81 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
+ }
+ EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger);
++static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream,
++                                int cmd, bool fe_first)
++{
++      struct snd_soc_pcm_runtime *fe = substream->private_data;
++      int ret;
++
++      /* call trigger on the frontend before the backend. */
++      if (fe_first) {
++              dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n",
++                      fe->dai_link->name, cmd);
++
++              ret = soc_pcm_trigger(substream, cmd);
++              if (ret < 0)
++                      return ret;
++
++              ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
++              return ret;
++      }
++
++      /* call trigger on the frontend after the backend. */
++      ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
++      if (ret < 0)
++              return ret;
++
++      dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n",
++              fe->dai_link->name, cmd);
++
++      ret = soc_pcm_trigger(substream, cmd);
++
++      return ret;
++}
++
+ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
+ {
+       struct snd_soc_pcm_runtime *fe = substream->private_data;
+-      int stream = substream->stream, ret;
++      int stream = substream->stream;
++      int ret = 0;
+       enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
+       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+       switch (trigger) {
+       case SND_SOC_DPCM_TRIGGER_PRE:
+-              /* call trigger on the frontend before the backend. */
+-
+-              dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n",
+-                              fe->dai_link->name, cmd);
+-
+-              ret = soc_pcm_trigger(substream, cmd);
+-              if (ret < 0) {
+-                      dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
+-                      goto out;
++              switch (cmd) {
++              case SNDRV_PCM_TRIGGER_START:
++              case SNDRV_PCM_TRIGGER_RESUME:
++              case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++                      ret = dpcm_dai_trigger_fe_be(substream, cmd, true);
++                      break;
++              case SNDRV_PCM_TRIGGER_STOP:
++              case SNDRV_PCM_TRIGGER_SUSPEND:
++              case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++                      ret = dpcm_dai_trigger_fe_be(substream, cmd, false);
++                      break;
++              default:
++                      ret = -EINVAL;
++                      break;
+               }
+-
+-              ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
+               break;
+       case SND_SOC_DPCM_TRIGGER_POST:
+-              /* call trigger on the frontend after the backend. */
+-
+-              ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
+-              if (ret < 0) {
+-                      dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
+-                      goto out;
++              switch (cmd) {
++              case SNDRV_PCM_TRIGGER_START:
++              case SNDRV_PCM_TRIGGER_RESUME:
++              case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++                      ret = dpcm_dai_trigger_fe_be(substream, cmd, false);
++                      break;
++              case SNDRV_PCM_TRIGGER_STOP:
++              case SNDRV_PCM_TRIGGER_SUSPEND:
++              case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++                      ret = dpcm_dai_trigger_fe_be(substream, cmd, true);
++                      break;
++              default:
++                      ret = -EINVAL;
++                      break;
+               }
+-
+-              dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n",
+-                              fe->dai_link->name, cmd);
+-
+-              ret = soc_pcm_trigger(substream, cmd);
+               break;
+       case SND_SOC_DPCM_TRIGGER_BESPOKE:
+               /* bespoke trigger() - handles both FE and BEs */
+@@ -2167,10 +2206,6 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
+                               fe->dai_link->name, cmd);
+               ret = soc_pcm_bespoke_trigger(substream, cmd);
+-              if (ret < 0) {
+-                      dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
+-                      goto out;
+-              }
+               break;
+       default:
+               dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd,
+@@ -2179,6 +2214,12 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
+               goto out;
+       }
++      if (ret < 0) {
++              dev_err(fe->dev, "ASoC: trigger FE cmd: %d failed: %d\n",
++                      cmd, ret);
++              goto out;
++      }
++
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+-- 
+2.20.1
+
diff --git a/queue-4.14/hv_sock-remove-the-accept-port-restriction.patch b/queue-4.14/hv_sock-remove-the-accept-port-restriction.patch
new file mode 100644 (file)
index 0000000..764ff68
--- /dev/null
@@ -0,0 +1,168 @@
+From d7c1e55fdece37f1454987722615dbc0c3c713ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jan 2020 03:08:18 +0000
+Subject: hv_sock: Remove the accept port restriction
+
+From: Sunil Muthuswamy <sunilmut@microsoft.com>
+
+[ Upstream commit c742c59e1fbd022b64d91aa9a0092b3a699d653c ]
+
+Currently, hv_sock restricts the port the guest socket can accept
+connections on. hv_sock divides the socket port namespace into two parts
+for server side (listening socket), 0-0x7FFFFFFF & 0x80000000-0xFFFFFFFF
+(there are no restrictions on client port namespace). The first part
+(0-0x7FFFFFFF) is reserved for sockets where connections can be accepted.
+The second part (0x80000000-0xFFFFFFFF) is reserved for allocating ports
+for the peer (host) socket, once a connection is accepted.
+This reservation of the port namespace is specific to hv_sock and not
+known by the generic vsock library (ex: af_vsock). This is problematic
+because auto-binds/ephemeral ports are handled by the generic vsock
+library and it has no knowledge of this port reservation and could
+allocate a port that is not compatible with hv_sock (and legitimately so).
+The issue hasn't surfaced so far because the auto-bind code of vsock
+(__vsock_bind_stream) prior to the change 'VSOCK: bind to random port for
+VMADDR_PORT_ANY' would start walking up from LAST_RESERVED_PORT (1023) and
+start assigning ports. That will take a large number of iterations to hit
+0x7FFFFFFF. But, after the above change to randomize port selection, the
+issue has started coming up more frequently.
+There has really been no good reason to have this port reservation logic
+in hv_sock from the get go. Reserving a local port for peer ports is not
+how things are handled generally. Peer ports should reflect the peer port.
+This fixes the issue by lifting the port reservation, and also returns the
+right peer port. Since the code converts the GUID to the peer port (by
+using the first 4 bytes), there is a possibility of conflicts, but that
+seems like a reasonable risk to take, given this is limited to vsock and
+that only applies to all local sockets.
+
+Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/vmw_vsock/hyperv_transport.c | 68 +++++---------------------------
+ 1 file changed, 9 insertions(+), 59 deletions(-)
+
+diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
+index 6614512f81800..736b76ec8cf01 100644
+--- a/net/vmw_vsock/hyperv_transport.c
++++ b/net/vmw_vsock/hyperv_transport.c
+@@ -144,28 +144,15 @@ struct hvsock {
+  ****************************************************************************
+  * The only valid Service GUIDs, from the perspectives of both the host and *
+  * Linux VM, that can be connected by the other end, must conform to this   *
+- * format: <port>-facb-11e6-bd58-64006a7986d3, and the "port" must be in    *
+- * this range [0, 0x7FFFFFFF].                                              *
++ * format: <port>-facb-11e6-bd58-64006a7986d3.                              *
+  ****************************************************************************
+  *
+  * When we write apps on the host to connect(), the GUID ServiceID is used.
+  * When we write apps in Linux VM to connect(), we only need to specify the
+  * port and the driver will form the GUID and use that to request the host.
+  *
+- * From the perspective of Linux VM:
+- * 1. the local ephemeral port (i.e. the local auto-bound port when we call
+- * connect() without explicit bind()) is generated by __vsock_bind_stream(),
+- * and the range is [1024, 0xFFFFFFFF).
+- * 2. the remote ephemeral port (i.e. the auto-generated remote port for
+- * a connect request initiated by the host's connect()) is generated by
+- * hvs_remote_addr_init() and the range is [0x80000000, 0xFFFFFFFF).
+  */
+-#define MAX_LISTEN_PORT                       ((u32)0x7FFFFFFF)
+-#define MAX_VM_LISTEN_PORT            MAX_LISTEN_PORT
+-#define MAX_HOST_LISTEN_PORT          MAX_LISTEN_PORT
+-#define MIN_HOST_EPHEMERAL_PORT               (MAX_HOST_LISTEN_PORT + 1)
+-
+ /* 00000000-facb-11e6-bd58-64006a7986d3 */
+ static const uuid_le srv_id_template =
+       UUID_LE(0x00000000, 0xfacb, 0x11e6, 0xbd, 0x58,
+@@ -188,33 +175,6 @@ static void hvs_addr_init(struct sockaddr_vm *addr, const uuid_le *svr_id)
+       vsock_addr_init(addr, VMADDR_CID_ANY, port);
+ }
+-static void hvs_remote_addr_init(struct sockaddr_vm *remote,
+-                               struct sockaddr_vm *local)
+-{
+-      static u32 host_ephemeral_port = MIN_HOST_EPHEMERAL_PORT;
+-      struct sock *sk;
+-
+-      vsock_addr_init(remote, VMADDR_CID_ANY, VMADDR_PORT_ANY);
+-
+-      while (1) {
+-              /* Wrap around ? */
+-              if (host_ephemeral_port < MIN_HOST_EPHEMERAL_PORT ||
+-                  host_ephemeral_port == VMADDR_PORT_ANY)
+-                      host_ephemeral_port = MIN_HOST_EPHEMERAL_PORT;
+-
+-              remote->svm_port = host_ephemeral_port++;
+-
+-              sk = vsock_find_connected_socket(remote, local);
+-              if (!sk) {
+-                      /* Found an available ephemeral port */
+-                      return;
+-              }
+-
+-              /* Release refcnt got in vsock_find_connected_socket */
+-              sock_put(sk);
+-      }
+-}
+-
+ static void hvs_set_channel_pending_send_size(struct vmbus_channel *chan)
+ {
+       set_channel_pending_send_size(chan,
+@@ -342,12 +302,7 @@ static void hvs_open_connection(struct vmbus_channel *chan)
+       if_type = &chan->offermsg.offer.if_type;
+       if_instance = &chan->offermsg.offer.if_instance;
+       conn_from_host = chan->offermsg.offer.u.pipe.user_def[0];
+-
+-      /* The host or the VM should only listen on a port in
+-       * [0, MAX_LISTEN_PORT]
+-       */
+-      if (!is_valid_srv_id(if_type) ||
+-          get_port_by_srv_id(if_type) > MAX_LISTEN_PORT)
++      if (!is_valid_srv_id(if_type))
+               return;
+       hvs_addr_init(&addr, conn_from_host ? if_type : if_instance);
+@@ -372,6 +327,13 @@ static void hvs_open_connection(struct vmbus_channel *chan)
+               new->sk_state = TCP_SYN_SENT;
+               vnew = vsock_sk(new);
++
++              hvs_addr_init(&vnew->local_addr, if_type);
++
++              /* Remote peer is always the host */
++              vsock_addr_init(&vnew->remote_addr,
++                              VMADDR_CID_HOST, VMADDR_PORT_ANY);
++              vnew->remote_addr.svm_port = get_port_by_srv_id(if_instance);
+               hvs_new = vnew->trans;
+               hvs_new->chan = chan;
+       } else {
+@@ -411,8 +373,6 @@ static void hvs_open_connection(struct vmbus_channel *chan)
+               sk->sk_ack_backlog++;
+               hvs_addr_init(&vnew->local_addr, if_type);
+-              hvs_remote_addr_init(&vnew->remote_addr, &vnew->local_addr);
+-
+               hvs_new->vm_srv_id = *if_type;
+               hvs_new->host_srv_id = *if_instance;
+@@ -717,16 +677,6 @@ static bool hvs_stream_is_active(struct vsock_sock *vsk)
+ static bool hvs_stream_allow(u32 cid, u32 port)
+ {
+-      /* The host's port range [MIN_HOST_EPHEMERAL_PORT, 0xFFFFFFFF) is
+-       * reserved as ephemeral ports, which are used as the host's ports
+-       * when the host initiates connections.
+-       *
+-       * Perform this check in the guest so an immediate error is produced
+-       * instead of a timeout.
+-       */
+-      if (port > MAX_HOST_LISTEN_PORT)
+-              return false;
+-
+       if (cid == VMADDR_CID_HOST)
+               return true;
+-- 
+2.20.1
+
index e2ea4938be4aa59d1e782aa82f6275a7988f0544..2a0c5d401c3ae8f39a0809bf85d07a6053699c9e 100644 (file)
@@ -138,3 +138,5 @@ cifs-fail-i-o-on-soft-mounts-if-sessionsetup-errors-out.patch
 clocksource-prevent-double-add_timer_on-for-watchdog_timer.patch
 perf-core-fix-mlock-accounting-in-perf_mmap.patch
 rxrpc-fix-service-call-disconnection.patch
+asoc-pcm-update-fe-be-trigger-order-based-on-the-com.patch
+hv_sock-remove-the-accept-port-restriction.patch