carl9170-fix-misuse-of-device-driver-api.patch
revert-x86-build-move-_etext-to-actual-end-of-.text.patch
vmci-fix-integer-overflow-in-vmci-handle-arrays.patch
+staging-vchiq_2835_arm-revert-quit-using-custom-down_interruptible.patch
+staging-vchiq-make-wait-events-interruptible.patch
+staging-vchiq-revert-switch-to-wait_for_completion_killable.patch
+staging-fsl-dpaa2-ethsw-fix-memory-leak-of-switchdev_work.patch
+staging-bcm2835-camera-replace-spinlock-protecting-context_map-with-mutex.patch
+staging-bcm2835-camera-ensure-all-buffers-are-returned-on-disable.patch
+staging-bcm2835-camera-remove-check-of-the-number-of-buffers-supplied.patch
+staging-bcm2835-camera-handle-empty-eos-buffers-whilst-streaming.patch
+staging-rtl8712-reduce-stack-usage-again.patch
--- /dev/null
+From 70ec64ccdaac5d8f634338e33b016c1c99831499 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Sat, 29 Jun 2019 14:13:29 +0200
+Subject: staging: bcm2835-camera: Ensure all buffers are returned on disable
+
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+
+commit 70ec64ccdaac5d8f634338e33b016c1c99831499 upstream.
+
+With the recent change to match MMAL and V4L2 buffers there
+is a need to wait for all MMAL buffers to be returned during
+stop_streaming.
+
+Fixes: 938416707071 ("staging: bcm2835-camera: Remove V4L2/MMAL buffer remapping")
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Acked-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 22 +++++++---
+ drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c | 4 +
+ drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h | 3 +
+ 3 files changed, 23 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -576,6 +576,7 @@ static void stop_streaming(struct vb2_qu
+ int ret;
+ unsigned long timeout;
+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
++ struct vchiq_mmal_port *port = dev->capture.port;
+
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
+ __func__, dev);
+@@ -599,12 +600,6 @@ static void stop_streaming(struct vb2_qu
+ &dev->capture.frame_count,
+ sizeof(dev->capture.frame_count));
+
+- /* wait for last frame to complete */
+- timeout = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ);
+- if (timeout == 0)
+- v4l2_err(&dev->v4l2_dev,
+- "timed out waiting for frame completion\n");
+-
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+ "disabling connection\n");
+
+@@ -619,6 +614,21 @@ static void stop_streaming(struct vb2_qu
+ ret);
+ }
+
++ /* wait for all buffers to be returned */
++ while (atomic_read(&port->buffers_with_vpu)) {
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "%s: Waiting for buffers to be returned - %d outstanding\n",
++ __func__, atomic_read(&port->buffers_with_vpu));
++ timeout = wait_for_completion_timeout(&dev->capture.frame_cmplt,
++ HZ);
++ if (timeout == 0) {
++ v4l2_err(&dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
++ __func__,
++ atomic_read(&port->buffers_with_vpu));
++ break;
++ }
++ }
++
+ if (disable_camera(dev) < 0)
+ v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n");
+ }
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+@@ -240,6 +240,8 @@ static void buffer_work_cb(struct work_s
+ struct mmal_msg_context *msg_context =
+ container_of(work, struct mmal_msg_context, u.bulk.work);
+
++ atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
++
+ msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
+ msg_context->u.bulk.port,
+ msg_context->u.bulk.status,
+@@ -380,6 +382,8 @@ buffer_from_host(struct vchiq_mmal_insta
+ /* initialise work structure ready to schedule callback */
+ INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
+
++ atomic_inc(&port->buffers_with_vpu);
++
+ /* prep the buffer from host message */
+ memset(&m, 0xbc, sizeof(m)); /* just to make debug clearer */
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
+@@ -71,6 +71,9 @@ struct vchiq_mmal_port {
+ struct list_head buffers;
+ /* lock to serialise adding and removing buffers from list */
+ spinlock_t slock;
++
++ /* Count of buffers the VPU has yet to return */
++ atomic_t buffers_with_vpu;
+ /* callback on buffer completion */
+ vchiq_mmal_buffer_cb buffer_cb;
+ /* callback context */
--- /dev/null
+From a26be06d6d96c10a9ab005e99d93fbb5d3babd98 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Sat, 29 Jun 2019 14:48:23 +0200
+Subject: staging: bcm2835-camera: Handle empty EOS buffers whilst streaming
+
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+
+commit a26be06d6d96c10a9ab005e99d93fbb5d3babd98 upstream.
+
+The change to mapping V4L2 to MMAL buffers 1:1 didn't handle
+the condition we get with raw pixel buffers (eg YUV and RGB)
+direct from the camera's stills port. That sends the pixel buffer
+and then an empty buffer with the EOS flag set. The EOS buffer
+wasn't handled and returned an error up the stack.
+
+Handle the condition correctly by returning it to the component
+if streaming, or returning with an error if stopping streaming.
+
+Fixes: 938416707071 ("staging: bcm2835-camera: Remove V4L2/MMAL buffer remapping")
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Acked-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c | 21 +++++-----
+ drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c | 5 +-
+ 2 files changed, 15 insertions(+), 11 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+@@ -336,16 +336,13 @@ static void buffer_cb(struct vchiq_mmal_
+ return;
+ } else if (length == 0) {
+ /* stream ended */
+- if (buf) {
+- /* this should only ever happen if the port is
+- * disabled and there are buffers still queued
++ if (dev->capture.frame_count) {
++ /* empty buffer whilst capturing - expected to be an
++ * EOS, so grab another frame
+ */
+- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+- pr_debug("Empty buffer");
+- } else if (dev->capture.frame_count) {
+- /* grab another frame */
+ if (is_capturing(dev)) {
+- pr_debug("Grab another frame");
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Grab another frame");
+ vchiq_mmal_port_parameter_set(
+ instance,
+ dev->capture.camera_port,
+@@ -353,8 +350,14 @@ static void buffer_cb(struct vchiq_mmal_
+ &dev->capture.frame_count,
+ sizeof(dev->capture.frame_count));
+ }
++ if (vchiq_mmal_submit_buffer(instance, port, buf))
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Failed to return EOS buffer");
+ } else {
+- /* signal frame completion */
++ /* stopping streaming.
++ * return buffer, and signal frame completion
++ */
++ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ complete(&dev->capture.frame_cmplt);
+ }
+ } else {
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+@@ -290,8 +290,6 @@ static int bulk_receive(struct vchiq_mma
+
+ /* store length */
+ msg_context->u.bulk.buffer_used = rd_len;
+- msg_context->u.bulk.mmal_flags =
+- msg->u.buffer_from_host.buffer_header.flags;
+ msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
+ msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
+
+@@ -452,6 +450,9 @@ static void buffer_to_host_cb(struct vch
+ return;
+ }
+
++ msg_context->u.bulk.mmal_flags =
++ msg->u.buffer_from_host.buffer_header.flags;
++
+ if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
+ /* message reception had an error */
+ pr_warn("error %d in reply\n", msg->h.status);
--- /dev/null
+From bb8e97006d701ae725a177f8f322e5a75fa761b7 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Sat, 29 Jun 2019 14:13:30 +0200
+Subject: staging: bcm2835-camera: Remove check of the number of buffers supplied
+
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+
+commit bb8e97006d701ae725a177f8f322e5a75fa761b7 upstream.
+
+Before commit "staging: bcm2835-camera: Remove V4L2/MMAL buffer remapping"
+there was a need to ensure that there were sufficient buffers supplied from
+the user to cover those being sent to the VPU (always 1).
+
+Now the buffers are linked 1:1 between MMAL and V4L2,
+therefore there is no need for that check, and indeed it is wrong
+as there is no need to submit all the buffers before starting streaming.
+
+Fixes: 938416707071 ("staging: bcm2835-camera: Remove V4L2/MMAL buffer remapping")
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Acked-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+@@ -1328,16 +1328,6 @@ static int port_enable(struct vchiq_mmal
+ if (port->enabled)
+ return 0;
+
+- /* ensure there are enough buffers queued to cover the buffer headers */
+- if (port->buffer_cb) {
+- hdr_count = 0;
+- list_for_each(buf_head, &port->buffers) {
+- hdr_count++;
+- }
+- if (hdr_count < port->current_buffer.num)
+- return -ENOSPC;
+- }
+-
+ ret = port_action_port(instance, port,
+ MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
+ if (ret)
--- /dev/null
+From 8dedab2903f152aa3cee9ae3d57c828dea0d356e Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Sat, 29 Jun 2019 14:13:17 +0200
+Subject: staging: bcm2835-camera: Replace spinlock protecting context_map with mutex
+
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+
+commit 8dedab2903f152aa3cee9ae3d57c828dea0d356e upstream.
+
+The commit "staging: bcm2835-camera: Replace open-coded idr with a struct idr."
+replaced an internal implementation of an idr with the standard functions
+and a spinlock. idr_alloc(GFP_KERNEL) can sleep whilst calling kmem_cache_alloc
+to allocate the new node, but this is not valid whilst in an atomic context
+due to the spinlock.
+
+There is no need for this to be a spinlock as a standard mutex is
+sufficient.
+
+Fixes: 950fd867c635 ("staging: bcm2835-camera: Replace open-coded idr with a struct idr.")
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
+Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Acked-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
+@@ -161,7 +161,8 @@ struct vchiq_mmal_instance {
+ void *bulk_scratch;
+
+ struct idr context_map;
+- spinlock_t context_map_lock;
++ /* protect accesses to context_map */
++ struct mutex context_map_lock;
+
+ /* component to use next */
+ int component_idx;
+@@ -184,10 +185,10 @@ get_msg_context(struct vchiq_mmal_instan
+ * that when we service the VCHI reply, we can look up what
+ * message is being replied to.
+ */
+- spin_lock(&instance->context_map_lock);
++ mutex_lock(&instance->context_map_lock);
+ handle = idr_alloc(&instance->context_map, msg_context,
+ 0, 0, GFP_KERNEL);
+- spin_unlock(&instance->context_map_lock);
++ mutex_unlock(&instance->context_map_lock);
+
+ if (handle < 0) {
+ kfree(msg_context);
+@@ -211,9 +212,9 @@ release_msg_context(struct mmal_msg_cont
+ {
+ struct vchiq_mmal_instance *instance = msg_context->instance;
+
+- spin_lock(&instance->context_map_lock);
++ mutex_lock(&instance->context_map_lock);
+ idr_remove(&instance->context_map, msg_context->handle);
+- spin_unlock(&instance->context_map_lock);
++ mutex_unlock(&instance->context_map_lock);
+ kfree(msg_context);
+ }
+
+@@ -1849,7 +1850,7 @@ int vchiq_mmal_init(struct vchiq_mmal_in
+
+ instance->bulk_scratch = vmalloc(PAGE_SIZE);
+
+- spin_lock_init(&instance->context_map_lock);
++ mutex_init(&instance->context_map_lock);
+ idr_init_base(&instance->context_map, 1);
+
+ params.callback_param = instance;
--- /dev/null
+From 5555ebbbac822b4fa28db2be15aaf98b3c21af26 Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Sat, 8 Jun 2019 12:50:31 +0100
+Subject: staging: fsl-dpaa2/ethsw: fix memory leak of switchdev_work
+
+From: Colin Ian King <colin.king@canonical.com>
+
+commit 5555ebbbac822b4fa28db2be15aaf98b3c21af26 upstream.
+
+In the default event case switchdev_work is being leaked because
+nothing is queued for work. Fix this by kfree'ing switchdev_work
+before returning NOTIFY_DONE.
+
+Addresses-Coverity: ("Resource leak")
+Fixes: 44baaa43d7cc ("staging: fsl-dpaa2/ethsw: Add Freescale DPAA2 Ethernet Switch driver")
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
++++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+@@ -1086,6 +1086,7 @@ static int port_switchdev_event(struct n
+ dev_hold(dev);
+ break;
+ default:
++ kfree(switchdev_work);
+ return NOTIFY_DONE;
+ }
+
--- /dev/null
+From fbd6b25009ac76b2034168cd21d5e01f8c2d83d1 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Fri, 28 Jun 2019 14:37:48 +0200
+Subject: staging: rtl8712: reduce stack usage, again
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+commit fbd6b25009ac76b2034168cd21d5e01f8c2d83d1 upstream.
+
+An earlier patch I sent reduced the stack usage enough to get
+below the warning limit, and I could show this was safe, but with
+GCC_PLUGIN_STRUCTLEAK_BYREF_ALL, it gets worse again because large stack
+variables in the same function no longer overlap:
+
+drivers/staging/rtl8712/rtl871x_ioctl_linux.c: In function 'translate_scan.isra.2':
+drivers/staging/rtl8712/rtl871x_ioctl_linux.c:322:1: error: the frame size of 1200 bytes is larger than 1024 bytes [-Werror=frame-larger-than=]
+
+Split out the largest two blocks in the affected function into two
+separate functions and mark those noinline_for_stack.
+
+Fixes: 8c5af16f7953 ("staging: rtl8712: reduce stack usage")
+Fixes: 81a56f6dcd20 ("gcc-plugins: structleak: Generalize to all variable types")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/rtl8712/rtl871x_ioctl_linux.c | 159 ++++++++++++++------------
+ 1 file changed, 89 insertions(+), 70 deletions(-)
+
+--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
++++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+@@ -124,10 +124,91 @@ static inline void handle_group_key(stru
+ }
+ }
+
+-static noinline_for_stack char *translate_scan(struct _adapter *padapter,
+- struct iw_request_info *info,
+- struct wlan_network *pnetwork,
+- char *start, char *stop)
++static noinline_for_stack char *translate_scan_wpa(struct iw_request_info *info,
++ struct wlan_network *pnetwork,
++ struct iw_event *iwe,
++ char *start, char *stop)
++{
++ /* parsing WPA/WPA2 IE */
++ u8 buf[MAX_WPA_IE_LEN];
++ u8 wpa_ie[255], rsn_ie[255];
++ u16 wpa_len = 0, rsn_len = 0;
++ int n, i;
++
++ r8712_get_sec_ie(pnetwork->network.IEs,
++ pnetwork->network.IELength, rsn_ie, &rsn_len,
++ wpa_ie, &wpa_len);
++ if (wpa_len > 0) {
++ memset(buf, 0, MAX_WPA_IE_LEN);
++ n = sprintf(buf, "wpa_ie=");
++ for (i = 0; i < wpa_len; i++) {
++ n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
++ "%02x", wpa_ie[i]);
++ if (n >= MAX_WPA_IE_LEN)
++ break;
++ }
++ memset(iwe, 0, sizeof(*iwe));
++ iwe->cmd = IWEVCUSTOM;
++ iwe->u.data.length = (u16)strlen(buf);
++ start = iwe_stream_add_point(info, start, stop,
++ iwe, buf);
++ memset(iwe, 0, sizeof(*iwe));
++ iwe->cmd = IWEVGENIE;
++ iwe->u.data.length = (u16)wpa_len;
++ start = iwe_stream_add_point(info, start, stop,
++ iwe, wpa_ie);
++ }
++ if (rsn_len > 0) {
++ memset(buf, 0, MAX_WPA_IE_LEN);
++ n = sprintf(buf, "rsn_ie=");
++ for (i = 0; i < rsn_len; i++) {
++ n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
++ "%02x", rsn_ie[i]);
++ if (n >= MAX_WPA_IE_LEN)
++ break;
++ }
++ memset(iwe, 0, sizeof(*iwe));
++ iwe->cmd = IWEVCUSTOM;
++ iwe->u.data.length = strlen(buf);
++ start = iwe_stream_add_point(info, start, stop,
++ iwe, buf);
++ memset(iwe, 0, sizeof(*iwe));
++ iwe->cmd = IWEVGENIE;
++ iwe->u.data.length = rsn_len;
++ start = iwe_stream_add_point(info, start, stop, iwe,
++ rsn_ie);
++ }
++
++ return start;
++}
++
++static noinline_for_stack char *translate_scan_wps(struct iw_request_info *info,
++ struct wlan_network *pnetwork,
++ struct iw_event *iwe,
++ char *start, char *stop)
++{
++ /* parsing WPS IE */
++ u8 wps_ie[512];
++ uint wps_ielen;
++
++ if (r8712_get_wps_ie(pnetwork->network.IEs,
++ pnetwork->network.IELength,
++ wps_ie, &wps_ielen)) {
++ if (wps_ielen > 2) {
++ iwe->cmd = IWEVGENIE;
++ iwe->u.data.length = (u16)wps_ielen;
++ start = iwe_stream_add_point(info, start, stop,
++ iwe, wps_ie);
++ }
++ }
++
++ return start;
++}
++
++static char *translate_scan(struct _adapter *padapter,
++ struct iw_request_info *info,
++ struct wlan_network *pnetwork,
++ char *start, char *stop)
+ {
+ struct iw_event iwe;
+ struct ieee80211_ht_cap *pht_capie;
+@@ -240,73 +321,11 @@ static noinline_for_stack char *translat
+ /* Check if we added any event */
+ if ((current_val - start) > iwe_stream_lcp_len(info))
+ start = current_val;
+- /* parsing WPA/WPA2 IE */
+- {
+- u8 buf[MAX_WPA_IE_LEN];
+- u8 wpa_ie[255], rsn_ie[255];
+- u16 wpa_len = 0, rsn_len = 0;
+- int n;
+-
+- r8712_get_sec_ie(pnetwork->network.IEs,
+- pnetwork->network.IELength, rsn_ie, &rsn_len,
+- wpa_ie, &wpa_len);
+- if (wpa_len > 0) {
+- memset(buf, 0, MAX_WPA_IE_LEN);
+- n = sprintf(buf, "wpa_ie=");
+- for (i = 0; i < wpa_len; i++) {
+- n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
+- "%02x", wpa_ie[i]);
+- if (n >= MAX_WPA_IE_LEN)
+- break;
+- }
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = IWEVCUSTOM;
+- iwe.u.data.length = (u16)strlen(buf);
+- start = iwe_stream_add_point(info, start, stop,
+- &iwe, buf);
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = IWEVGENIE;
+- iwe.u.data.length = (u16)wpa_len;
+- start = iwe_stream_add_point(info, start, stop,
+- &iwe, wpa_ie);
+- }
+- if (rsn_len > 0) {
+- memset(buf, 0, MAX_WPA_IE_LEN);
+- n = sprintf(buf, "rsn_ie=");
+- for (i = 0; i < rsn_len; i++) {
+- n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
+- "%02x", rsn_ie[i]);
+- if (n >= MAX_WPA_IE_LEN)
+- break;
+- }
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = IWEVCUSTOM;
+- iwe.u.data.length = strlen(buf);
+- start = iwe_stream_add_point(info, start, stop,
+- &iwe, buf);
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = IWEVGENIE;
+- iwe.u.data.length = rsn_len;
+- start = iwe_stream_add_point(info, start, stop, &iwe,
+- rsn_ie);
+- }
+- }
+
+- { /* parsing WPS IE */
+- u8 wps_ie[512];
+- uint wps_ielen;
+-
+- if (r8712_get_wps_ie(pnetwork->network.IEs,
+- pnetwork->network.IELength,
+- wps_ie, &wps_ielen)) {
+- if (wps_ielen > 2) {
+- iwe.cmd = IWEVGENIE;
+- iwe.u.data.length = (u16)wps_ielen;
+- start = iwe_stream_add_point(info, start, stop,
+- &iwe, wps_ie);
+- }
+- }
+- }
++ start = translate_scan_wpa(info, pnetwork, &iwe, start, stop);
++
++ start = translate_scan_wps(info, pnetwork, &iwe, start, stop);
++
+ /* Add quality statistics */
+ iwe.cmd = IWEVQUAL;
+ rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
--- /dev/null
+From 77cf3f5dcf35c8f547f075213dbc15146d44cc76 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Thu, 9 May 2019 16:31:35 +0200
+Subject: staging: vchiq: make wait events interruptible
+
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+
+commit 77cf3f5dcf35c8f547f075213dbc15146d44cc76 upstream.
+
+The killable version of wait_event() is meant to be used on situations
+where it should not fail at all costs, but still have the convenience of
+being able to kill it if really necessary. Wait events in VCHIQ doesn't
+fit this criteria, as it's mainly used as an interface to V4L2 and ALSA
+devices.
+
+Fixes: 852b2876a8a8 ("staging: vchiq: rework remove_event handling")
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+@@ -395,13 +395,21 @@ remote_event_create(wait_queue_head_t *w
+ init_waitqueue_head(wq);
+ }
+
++/*
++ * All the event waiting routines in VCHIQ used a custom semaphore
++ * implementation that filtered most signals. This achieved a behaviour similar
++ * to the "killable" family of functions. While cleaning up this code all the
++ * routines where switched to the "interruptible" family of functions, as the
++ * former was deemed unjustified and the use "killable" set all VCHIQ's
++ * threads in D state.
++ */
+ static inline int
+ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
+ {
+ if (!event->fired) {
+ event->armed = 1;
+ dsb(sy);
+- if (wait_event_killable(*wq, event->fired)) {
++ if (wait_event_interruptible(*wq, event->fired)) {
+ event->armed = 0;
+ return 0;
+ }
--- /dev/null
+From 086efbabdc04563268372aaef4d66039d85ee76c Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Thu, 9 May 2019 16:31:34 +0200
+Subject: staging: vchiq: revert "switch to wait_for_completion_killable"
+
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+
+commit 086efbabdc04563268372aaef4d66039d85ee76c upstream.
+
+The killable version of wait_for_completion() is meant to be used on
+situations where it should not fail at all costs, but still have the
+convenience of being able to kill it if really necessary. VCHIQ doesn't
+fit this criteria, as it's mainly used as an interface to V4L2 and ALSA
+devices.
+
+Fixes: a772f116702e ("staging: vchiq: switch to wait_for_completion_killable")
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 21 +++++-----
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c | 21 +++++-----
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c | 6 +-
+ 3 files changed, 25 insertions(+), 23 deletions(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -532,7 +532,8 @@ add_completion(VCHIQ_INSTANCE_T instance
+ vchiq_log_trace(vchiq_arm_log_level,
+ "%s - completion queue full", __func__);
+ DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);
+- if (wait_for_completion_killable(&instance->remove_event)) {
++ if (wait_for_completion_interruptible(
++ &instance->remove_event)) {
+ vchiq_log_info(vchiq_arm_log_level,
+ "service_callback interrupted");
+ return VCHIQ_RETRY;
+@@ -643,7 +644,7 @@ service_callback(VCHIQ_REASON_T reason,
+ }
+
+ DEBUG_TRACE(SERVICE_CALLBACK_LINE);
+- if (wait_for_completion_killable(
++ if (wait_for_completion_interruptible(
+ &user_service->remove_event)
+ != 0) {
+ vchiq_log_info(vchiq_arm_log_level,
+@@ -978,7 +979,7 @@ vchiq_ioctl(struct file *file, unsigned
+ has been closed until the client library calls the
+ CLOSE_DELIVERED ioctl, signalling close_event. */
+ if (user_service->close_pending &&
+- wait_for_completion_killable(
++ wait_for_completion_interruptible(
+ &user_service->close_event))
+ status = VCHIQ_RETRY;
+ break;
+@@ -1154,7 +1155,7 @@ vchiq_ioctl(struct file *file, unsigned
+
+ DEBUG_TRACE(AWAIT_COMPLETION_LINE);
+ mutex_unlock(&instance->completion_mutex);
+- rc = wait_for_completion_killable(
++ rc = wait_for_completion_interruptible(
+ &instance->insert_event);
+ mutex_lock(&instance->completion_mutex);
+ if (rc != 0) {
+@@ -1324,7 +1325,7 @@ vchiq_ioctl(struct file *file, unsigned
+ do {
+ spin_unlock(&msg_queue_spinlock);
+ DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
+- if (wait_for_completion_killable(
++ if (wait_for_completion_interruptible(
+ &user_service->insert_event)) {
+ vchiq_log_info(vchiq_arm_log_level,
+ "DEQUEUE_MESSAGE interrupted");
+@@ -2328,7 +2329,7 @@ vchiq_keepalive_thread_func(void *v)
+ while (1) {
+ long rc = 0, uc = 0;
+
+- if (wait_for_completion_killable(&arm_state->ka_evt)
++ if (wait_for_completion_interruptible(&arm_state->ka_evt)
+ != 0) {
+ vchiq_log_error(vchiq_susp_log_level,
+ "%s interrupted", __func__);
+@@ -2579,7 +2580,7 @@ block_resume(struct vchiq_arm_state *arm
+ write_unlock_bh(&arm_state->susp_res_lock);
+ vchiq_log_info(vchiq_susp_log_level, "%s wait for previously "
+ "blocked clients", __func__);
+- if (wait_for_completion_killable_timeout(
++ if (wait_for_completion_interruptible_timeout(
+ &arm_state->blocked_blocker, timeout_val)
+ <= 0) {
+ vchiq_log_error(vchiq_susp_log_level, "%s wait for "
+@@ -2605,7 +2606,7 @@ block_resume(struct vchiq_arm_state *arm
+ write_unlock_bh(&arm_state->susp_res_lock);
+ vchiq_log_info(vchiq_susp_log_level, "%s wait for resume",
+ __func__);
+- if (wait_for_completion_killable_timeout(
++ if (wait_for_completion_interruptible_timeout(
+ &arm_state->vc_resume_complete, timeout_val)
+ <= 0) {
+ vchiq_log_error(vchiq_susp_log_level, "%s wait for "
+@@ -2812,7 +2813,7 @@ vchiq_arm_force_suspend(struct vchiq_sta
+ do {
+ write_unlock_bh(&arm_state->susp_res_lock);
+
+- rc = wait_for_completion_killable_timeout(
++ rc = wait_for_completion_interruptible_timeout(
+ &arm_state->vc_suspend_complete,
+ msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS));
+
+@@ -2908,7 +2909,7 @@ vchiq_arm_allow_resume(struct vchiq_stat
+ write_unlock_bh(&arm_state->susp_res_lock);
+
+ if (resume) {
+- if (wait_for_completion_killable(
++ if (wait_for_completion_interruptible(
+ &arm_state->vc_resume_complete) < 0) {
+ vchiq_log_error(vchiq_susp_log_level,
+ "%s interrupted", __func__);
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+@@ -568,7 +568,7 @@ reserve_space(struct vchiq_state *state,
+ remote_event_signal(&state->remote->trigger);
+
+ if (!is_blocking ||
+- (wait_for_completion_killable(
++ (wait_for_completion_interruptible(
+ &state->slot_available_event)))
+ return NULL; /* No space available */
+ }
+@@ -838,7 +838,7 @@ queue_message(struct vchiq_state *state,
+ spin_unlock("a_spinlock);
+ mutex_unlock(&state->slot_mutex);
+
+- if (wait_for_completion_killable(
++ if (wait_for_completion_interruptible(
+ &state->data_quota_event))
+ return VCHIQ_RETRY;
+
+@@ -869,7 +869,7 @@ queue_message(struct vchiq_state *state,
+ service_quota->slot_use_count);
+ VCHIQ_SERVICE_STATS_INC(service, quota_stalls);
+ mutex_unlock(&state->slot_mutex);
+- if (wait_for_completion_killable(
++ if (wait_for_completion_interruptible(
+ &service_quota->quota_event))
+ return VCHIQ_RETRY;
+ if (service->closing)
+@@ -1718,7 +1718,8 @@ parse_rx_slots(struct vchiq_state *state
+ &service->bulk_rx : &service->bulk_tx;
+
+ DEBUG_TRACE(PARSE_LINE);
+- if (mutex_lock_killable(&service->bulk_mutex)) {
++ if (mutex_lock_killable(
++ &service->bulk_mutex) != 0) {
+ DEBUG_TRACE(PARSE_LINE);
+ goto bail_not_ready;
+ }
+@@ -2436,7 +2437,7 @@ vchiq_open_service_internal(struct vchiq
+ QMFLAGS_IS_BLOCKING);
+ if (status == VCHIQ_SUCCESS) {
+ /* Wait for the ACK/NAK */
+- if (wait_for_completion_killable(&service->remove_event)) {
++ if (wait_for_completion_interruptible(&service->remove_event)) {
+ status = VCHIQ_RETRY;
+ vchiq_release_service_internal(service);
+ } else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) &&
+@@ -2803,7 +2804,7 @@ vchiq_connect_internal(struct vchiq_stat
+ }
+
+ if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) {
+- if (wait_for_completion_killable(&state->connect))
++ if (wait_for_completion_interruptible(&state->connect))
+ return VCHIQ_RETRY;
+
+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
+@@ -2902,7 +2903,7 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE
+ }
+
+ while (1) {
+- if (wait_for_completion_killable(&service->remove_event)) {
++ if (wait_for_completion_interruptible(&service->remove_event)) {
+ status = VCHIQ_RETRY;
+ break;
+ }
+@@ -2963,7 +2964,7 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDL
+ request_poll(service->state, service, VCHIQ_POLL_REMOVE);
+ }
+ while (1) {
+- if (wait_for_completion_killable(&service->remove_event)) {
++ if (wait_for_completion_interruptible(&service->remove_event)) {
+ status = VCHIQ_RETRY;
+ break;
+ }
+@@ -3046,7 +3047,7 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ
+ VCHIQ_SERVICE_STATS_INC(service, bulk_stalls);
+ do {
+ mutex_unlock(&service->bulk_mutex);
+- if (wait_for_completion_killable(
++ if (wait_for_completion_interruptible(
+ &service->bulk_remove_event)) {
+ status = VCHIQ_RETRY;
+ goto error_exit;
+@@ -3123,7 +3124,7 @@ waiting:
+
+ if (bulk_waiter) {
+ bulk_waiter->bulk = bulk;
+- if (wait_for_completion_killable(&bulk_waiter->event))
++ if (wait_for_completion_interruptible(&bulk_waiter->event))
+ status = VCHIQ_RETRY;
+ else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
+ status = VCHIQ_ERROR;
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c
+@@ -50,7 +50,7 @@ void vchiu_queue_push(struct vchiu_queue
+ return;
+
+ while (queue->write == queue->read + queue->size) {
+- if (wait_for_completion_killable(&queue->pop))
++ if (wait_for_completion_interruptible(&queue->pop))
+ flush_signals(current);
+ }
+
+@@ -63,7 +63,7 @@ void vchiu_queue_push(struct vchiu_queue
+ struct vchiq_header *vchiu_queue_peek(struct vchiu_queue *queue)
+ {
+ while (queue->write == queue->read) {
+- if (wait_for_completion_killable(&queue->push))
++ if (wait_for_completion_interruptible(&queue->push))
+ flush_signals(current);
+ }
+
+@@ -77,7 +77,7 @@ struct vchiq_header *vchiu_queue_pop(str
+ struct vchiq_header *header;
+
+ while (queue->write == queue->read) {
+- if (wait_for_completion_killable(&queue->push))
++ if (wait_for_completion_interruptible(&queue->push))
+ flush_signals(current);
+ }
+
--- /dev/null
+From 061ca1401f96c254e7f179bf97a1fc5c7f47e1e1 Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Thu, 9 May 2019 16:31:33 +0200
+Subject: staging: vchiq_2835_arm: revert "quit using custom down_interruptible()"
+
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+
+commit 061ca1401f96c254e7f179bf97a1fc5c7f47e1e1 upstream.
+
+The killable version of down() is meant to be used on situations where
+it should not fail at all costs, but still have the convenience of being
+able to kill it if really necessary. VCHIQ doesn't fit this criteria, as
+it's mainly used as an interface to V4L2 and ALSA devices.
+
+Fixes: ff5979ad8636 ("staging: vchiq_2835_arm: quit using custom down_interruptible()")
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+@@ -523,7 +523,7 @@ create_pagelist(char __user *buf, size_t
+ (g_cache_line_size - 1)))) {
+ char *fragments;
+
+- if (down_killable(&g_free_fragments_sema)) {
++ if (down_interruptible(&g_free_fragments_sema) != 0) {
+ cleanup_pagelistinfo(pagelistinfo);
+ return NULL;
+ }