]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Mon, 31 Aug 2020 20:08:09 +0000 (16:08 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 31 Aug 2020 20:08:09 +0000 (16:08 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.4/drm-i915-fix-cmd-parser-desc-matching-with-masks.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/usb-dwc3-gadget-don-t-setup-more-than-requested.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-gadget-fix-handling-zlp.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch [new file with mode: 0644]

diff --git a/queue-5.4/drm-i915-fix-cmd-parser-desc-matching-with-masks.patch b/queue-5.4/drm-i915-fix-cmd-parser-desc-matching-with-masks.patch
new file mode 100644 (file)
index 0000000..75a1bf7
--- /dev/null
@@ -0,0 +1,90 @@
+From 233a88fe497a377fd379f073465e1f7f90fdcd0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Aug 2020 22:59:26 +0300
+Subject: drm/i915: Fix cmd parser desc matching with masks
+
+From: Mika Kuoppala <mika.kuoppala@linux.intel.com>
+
+[ Upstream commit e5f10d6385cda083037915c12b130887c8831d2b ]
+
+Our variety of defined gpu commands have the actual
+command id field and possibly length and flags applied.
+
+We did start to apply the mask during initialization of
+the cmd descriptors but forgot to also apply it on comparisons.
+
+Fix comparisons in order to properly deny access with
+associated commands.
+
+v2: fix lri with correct mask (Chris)
+
+References: 926abff21a8f ("drm/i915/cmdparser: Ignore Length operands during command matching")
+Reported-by: Nicolai Stange <nstange@suse.de>
+Cc: stable@vger.kernel.org # v5.4+
+Cc: Miroslav Benes <mbenes@suse.cz>
+Cc: Takashi Iwai <tiwai@suse.de>
+Cc: Tyler Hicks <tyhicks@canonical.com>
+Cc: Jon Bloomfield <jon.bloomfield@intel.com>
+Cc: Chris Wilson <chris.p.wilson@intel.com>
+Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Link: https://patchwork.freedesktop.org/patch/msgid/20200817195926.12671-1-mika.kuoppala@linux.intel.com
+(cherry picked from commit 3b4efa148da36f158cce3f662e831af2834b8e0f)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/i915_cmd_parser.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
+index 21417ac8e878e..a9a69760c18d0 100644
+--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
+@@ -1207,6 +1207,12 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj,
+       return dst;
+ }
++static inline bool cmd_desc_is(const struct drm_i915_cmd_descriptor * const desc,
++                             const u32 cmd)
++{
++      return desc->cmd.value == (cmd & desc->cmd.mask);
++}
++
+ static bool check_cmd(const struct intel_engine_cs *engine,
+                     const struct drm_i915_cmd_descriptor *desc,
+                     const u32 *cmd, u32 length)
+@@ -1245,19 +1251,19 @@ static bool check_cmd(const struct intel_engine_cs *engine,
+                        * allowed mask/value pair given in the whitelist entry.
+                        */
+                       if (reg->mask) {
+-                              if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
++                              if (cmd_desc_is(desc, MI_LOAD_REGISTER_MEM)) {
+                                       DRM_DEBUG_DRIVER("CMD: Rejected LRM to masked register 0x%08X\n",
+                                                        reg_addr);
+                                       return false;
+                               }
+-                              if (desc->cmd.value == MI_LOAD_REGISTER_REG) {
++                              if (cmd_desc_is(desc, MI_LOAD_REGISTER_REG)) {
+                                       DRM_DEBUG_DRIVER("CMD: Rejected LRR to masked register 0x%08X\n",
+                                                        reg_addr);
+                                       return false;
+                               }
+-                              if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) &&
++                              if (cmd_desc_is(desc, MI_LOAD_REGISTER_IMM(1)) &&
+                                   (offset + 2 > length ||
+                                    (cmd[offset + 1] & reg->mask) != reg->value)) {
+                                       DRM_DEBUG_DRIVER("CMD: Rejected LRI to masked register 0x%08X\n",
+@@ -1488,7 +1494,7 @@ int intel_engine_cmd_parser(struct i915_gem_context *ctx,
+                       goto err;
+               }
+-              if (desc->cmd.value == MI_BATCH_BUFFER_START) {
++              if (cmd_desc_is(desc, MI_BATCH_BUFFER_START)) {
+                       ret = check_bbstart(ctx, cmd, offset, length,
+                                           batch_len, batch_start,
+                                           shadow_batch_start);
+-- 
+2.25.1
+
index aaca1ab4075bc39d38ecab7afc482820abbb7d7c..1eed5c6b089238579805261b043fdc33b0695f9a 100644 (file)
@@ -197,3 +197,7 @@ usb-gadget-f_ncm-add-bounds-checks-to-ncm_unwrap_ntb.patch
 usb-gadget-u_f-unbreak-offset-calculation-in-vlas.patch
 usb-cdc-acm-rework-notification_buffer-resizing.patch
 usb-storage-add-unusual_uas-entry-for-sony-psz-drives.patch
+drm-i915-fix-cmd-parser-desc-matching-with-masks.patch
+usb-dwc3-gadget-don-t-setup-more-than-requested.patch
+usb-dwc3-gadget-fix-handling-zlp.patch
+usb-dwc3-gadget-handle-zlp-for-sg-requests.patch
diff --git a/queue-5.4/usb-dwc3-gadget-don-t-setup-more-than-requested.patch b/queue-5.4/usb-dwc3-gadget-don-t-setup-more-than-requested.patch
new file mode 100644 (file)
index 0000000..e014e35
--- /dev/null
@@ -0,0 +1,174 @@
+From 62e4a4980863c9c23578444048125eccf36b37dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2020 19:46:23 -0700
+Subject: usb: dwc3: gadget: Don't setup more than requested
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+[ Upstream commit 5d187c0454ef4c5e046a81af36882d4d515922ec ]
+
+The SG list may be set up with entry size more than the requested
+length. Check the usb_request->length and make sure that we don't setup
+the TRBs to send/receive more than requested. This case may occur when
+the SG entry is allocated up to a certain minimum size, but the request
+length is less than that. It can also occur when the request is reused
+for a different request length.
+
+Cc: <stable@vger.kernel.org> # v4.18+
+Fixes: a31e63b608ff ("usb: dwc3: gadget: Correct handling of scattergather lists")
+Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc3/gadget.c | 51 +++++++++++++++++++++++++++------------
+ 1 file changed, 35 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 17340864a5408..816216870a1bb 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1017,26 +1017,24 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
+  * dwc3_prepare_one_trb - setup one TRB from one request
+  * @dep: endpoint for which this request is prepared
+  * @req: dwc3_request pointer
++ * @trb_length: buffer size of the TRB
+  * @chain: should this TRB be chained to the next?
+  * @node: only for isochronous endpoints. First TRB needs different type.
+  */
+ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
+-              struct dwc3_request *req, unsigned chain, unsigned node)
++              struct dwc3_request *req, unsigned int trb_length,
++              unsigned chain, unsigned node)
+ {
+       struct dwc3_trb         *trb;
+-      unsigned int            length;
+       dma_addr_t              dma;
+       unsigned                stream_id = req->request.stream_id;
+       unsigned                short_not_ok = req->request.short_not_ok;
+       unsigned                no_interrupt = req->request.no_interrupt;
+-      if (req->request.num_sgs > 0) {
+-              length = sg_dma_len(req->start_sg);
++      if (req->request.num_sgs > 0)
+               dma = sg_dma_address(req->start_sg);
+-      } else {
+-              length = req->request.length;
++      else
+               dma = req->request.dma;
+-      }
+       trb = &dep->trb_pool[dep->trb_enqueue];
+@@ -1048,7 +1046,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
+       req->num_trbs++;
+-      __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node,
++      __dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node,
+                       stream_id, short_not_ok, no_interrupt);
+ }
+@@ -1058,16 +1056,27 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
+       struct scatterlist *sg = req->start_sg;
+       struct scatterlist *s;
+       int             i;
+-
++      unsigned int length = req->request.length;
+       unsigned int remaining = req->request.num_mapped_sgs
+               - req->num_queued_sgs;
++      /*
++       * If we resume preparing the request, then get the remaining length of
++       * the request and resume where we left off.
++       */
++      for_each_sg(req->request.sg, s, req->num_queued_sgs, i)
++              length -= sg_dma_len(s);
++
+       for_each_sg(sg, s, remaining, i) {
+-              unsigned int length = req->request.length;
+               unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
+               unsigned int rem = length % maxp;
++              unsigned int trb_length;
+               unsigned chain = true;
++              trb_length = min_t(unsigned int, length, sg_dma_len(s));
++
++              length -= trb_length;
++
+               /*
+                * IOMMU driver is coalescing the list of sgs which shares a
+                * page boundary into one and giving it to USB driver. With
+@@ -1075,7 +1084,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
+                * sgs passed. So mark the chain bit to false if it isthe last
+                * mapped sg.
+                */
+-              if (i == remaining - 1)
++              if ((i == remaining - 1) || !length)
+                       chain = false;
+               if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) {
+@@ -1085,7 +1094,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
+                       req->needs_extra_trb = true;
+                       /* prepare normal TRB */
+-                      dwc3_prepare_one_trb(dep, req, true, i);
++                      dwc3_prepare_one_trb(dep, req, trb_length, true, i);
+                       /* Now prepare one extra TRB to align transfer size */
+                       trb = &dep->trb_pool[dep->trb_enqueue];
+@@ -1096,7 +1105,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
+                                       req->request.short_not_ok,
+                                       req->request.no_interrupt);
+               } else {
+-                      dwc3_prepare_one_trb(dep, req, chain, i);
++                      dwc3_prepare_one_trb(dep, req, trb_length, chain, i);
+               }
+               /*
+@@ -1111,6 +1120,16 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
+               req->num_queued_sgs++;
++              /*
++               * The number of pending SG entries may not correspond to the
++               * number of mapped SG entries. If all the data are queued, then
++               * don't include unused SG entries.
++               */
++              if (length == 0) {
++                      req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs;
++                      break;
++              }
++
+               if (!dwc3_calc_trbs_left(dep))
+                       break;
+       }
+@@ -1130,7 +1149,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
+               req->needs_extra_trb = true;
+               /* prepare normal TRB */
+-              dwc3_prepare_one_trb(dep, req, true, 0);
++              dwc3_prepare_one_trb(dep, req, length, true, 0);
+               /* Now prepare one extra TRB to align transfer size */
+               trb = &dep->trb_pool[dep->trb_enqueue];
+@@ -1147,7 +1166,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
+               req->needs_extra_trb = true;
+               /* prepare normal TRB */
+-              dwc3_prepare_one_trb(dep, req, true, 0);
++              dwc3_prepare_one_trb(dep, req, length, true, 0);
+               /* Now prepare one extra TRB to handle ZLP */
+               trb = &dep->trb_pool[dep->trb_enqueue];
+@@ -1157,7 +1176,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
+                               req->request.short_not_ok,
+                               req->request.no_interrupt);
+       } else {
+-              dwc3_prepare_one_trb(dep, req, false, 0);
++              dwc3_prepare_one_trb(dep, req, length, false, 0);
+       }
+ }
+-- 
+2.25.1
+
diff --git a/queue-5.4/usb-dwc3-gadget-fix-handling-zlp.patch b/queue-5.4/usb-dwc3-gadget-fix-handling-zlp.patch
new file mode 100644 (file)
index 0000000..6c16b61
--- /dev/null
@@ -0,0 +1,80 @@
+From 70c16b1f47c6a043e9403054ed7fda13c683e91f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2020 19:46:29 -0700
+Subject: usb: dwc3: gadget: Fix handling ZLP
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+The usb_request->zero doesn't apply for isoc. Also, if we prepare a
+0-length (ZLP) TRB for the OUT direction, we need to prepare an extra
+TRB to pad up to the MPS alignment. Use the same bounce buffer for the
+ZLP TRB and the extra pad TRB.
+
+Cc: <stable@vger.kernel.org> # v4.5+
+Fixes: d6e5a549cc4d ("usb: dwc3: simplify ZLP handling")
+Fixes: 04c03d10e507 ("usb: dwc3: gadget: handle request->zero")
+Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+---
+ drivers/usb/dwc3/gadget.c | 24 ++++++++++++++++++++++--
+ 1 file changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 816216870a1bb..8e67591df76be 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1159,6 +1159,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
+                               req->request.short_not_ok,
+                               req->request.no_interrupt);
+       } else if (req->request.zero && req->request.length &&
++                 !usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+                  (IS_ALIGNED(req->request.length, maxp))) {
+               struct dwc3     *dwc = dep->dwc;
+               struct dwc3_trb *trb;
+@@ -1168,13 +1169,23 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
+               /* prepare normal TRB */
+               dwc3_prepare_one_trb(dep, req, length, true, 0);
+-              /* Now prepare one extra TRB to handle ZLP */
++              /* Prepare one extra TRB to handle ZLP */
+               trb = &dep->trb_pool[dep->trb_enqueue];
+               req->num_trbs++;
+               __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
+-                              false, 1, req->request.stream_id,
++                              !req->direction, 1, req->request.stream_id,
+                               req->request.short_not_ok,
+                               req->request.no_interrupt);
++
++              /* Prepare one more TRB to handle MPS alignment for OUT */
++              if (!req->direction) {
++                      trb = &dep->trb_pool[dep->trb_enqueue];
++                      req->num_trbs++;
++                      __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp,
++                                             false, 1, req->request.stream_id,
++                                             req->request.short_not_ok,
++                                             req->request.no_interrupt);
++              }
+       } else {
+               dwc3_prepare_one_trb(dep, req, length, false, 0);
+       }
+@@ -2578,8 +2589,17 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
+                               status);
+       if (req->needs_extra_trb) {
++              unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
++
+               ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
+                               status);
++
++              /* Reclaim MPS padding TRB for ZLP */
++              if (!req->direction && req->request.zero && req->request.length &&
++                  !usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
++                  (IS_ALIGNED(req->request.length, maxp)))
++                      ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, status);
++
+               req->needs_extra_trb = false;
+       }
+-- 
+2.25.1
+
diff --git a/queue-5.4/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch b/queue-5.4/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch
new file mode 100644 (file)
index 0000000..43600c2
--- /dev/null
@@ -0,0 +1,64 @@
+From 7cba59b6ca01d090368e66d8300a33803395221c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2020 19:46:35 -0700
+Subject: usb: dwc3: gadget: Handle ZLP for sg requests
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+[ Upstream commit bc9a2e226ea95e1699f7590845554de095308b75 ]
+
+Currently dwc3 doesn't handle usb_request->zero for SG requests. This
+change checks and prepares extra TRBs for the ZLP for SG requests.
+
+Cc: <stable@vger.kernel.org> # v4.5+
+Fixes: 04c03d10e507 ("usb: dwc3: gadget: handle request->zero")
+Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc3/gadget.c | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 8e67591df76be..4225544342519 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1104,6 +1104,35 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
+                                       req->request.stream_id,
+                                       req->request.short_not_ok,
+                                       req->request.no_interrupt);
++              } else if (req->request.zero && req->request.length &&
++                         !usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
++                         !rem && !chain) {
++                      struct dwc3     *dwc = dep->dwc;
++                      struct dwc3_trb *trb;
++
++                      req->needs_extra_trb = true;
++
++                      /* Prepare normal TRB */
++                      dwc3_prepare_one_trb(dep, req, trb_length, true, i);
++
++                      /* Prepare one extra TRB to handle ZLP */
++                      trb = &dep->trb_pool[dep->trb_enqueue];
++                      req->num_trbs++;
++                      __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
++                                             !req->direction, 1,
++                                             req->request.stream_id,
++                                             req->request.short_not_ok,
++                                             req->request.no_interrupt);
++
++                      /* Prepare one more TRB to handle MPS alignment */
++                      if (!req->direction) {
++                              trb = &dep->trb_pool[dep->trb_enqueue];
++                              req->num_trbs++;
++                              __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp,
++                                                     false, 1, req->request.stream_id,
++                                                     req->request.short_not_ok,
++                                                     req->request.no_interrupt);
++                      }
+               } else {
+                       dwc3_prepare_one_trb(dep, req, trb_length, chain, i);
+               }
+-- 
+2.25.1
+