From: Sasha Levin Date: Mon, 31 Aug 2020 20:08:09 +0000 (-0400) Subject: Fixes for 5.4 X-Git-Tag: v4.4.235~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ab81d4b40e6b772dd942486906a60df4588390a0;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- 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 index 00000000000..75a1bf75024 --- /dev/null +++ b/queue-5.4/drm-i915-fix-cmd-parser-desc-matching-with-masks.patch @@ -0,0 +1,90 @@ +From 233a88fe497a377fd379f073465e1f7f90fdcd0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Aug 2020 22:59:26 +0300 +Subject: drm/i915: Fix cmd parser desc matching with masks + +From: Mika Kuoppala + +[ 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 +Cc: stable@vger.kernel.org # v5.4+ +Cc: Miroslav Benes +Cc: Takashi Iwai +Cc: Tyler Hicks +Cc: Jon Bloomfield +Cc: Chris Wilson +Signed-off-by: Mika Kuoppala +Reviewed-by: Chris Wilson +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.4/series b/queue-5.4/series index aaca1ab4075..1eed5c6b089 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -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 index 00000000000..e014e35d596 --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-don-t-setup-more-than-requested.patch @@ -0,0 +1,174 @@ +From 62e4a4980863c9c23578444048125eccf36b37dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Aug 2020 19:46:23 -0700 +Subject: usb: dwc3: gadget: Don't setup more than requested + +From: Thinh Nguyen + +[ 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: # v4.18+ +Fixes: a31e63b608ff ("usb: dwc3: gadget: Correct handling of scattergather lists") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6c16b61bcc9 --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-fix-handling-zlp.patch @@ -0,0 +1,80 @@ +From 70c16b1f47c6a043e9403054ed7fda13c683e91f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Aug 2020 19:46:29 -0700 +Subject: usb: dwc3: gadget: Fix handling ZLP + +From: Thinh Nguyen + +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: # v4.5+ +Fixes: d6e5a549cc4d ("usb: dwc3: simplify ZLP handling") +Fixes: 04c03d10e507 ("usb: dwc3: gadget: handle request->zero") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +--- + 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 index 00000000000..43600c22910 --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch @@ -0,0 +1,64 @@ +From 7cba59b6ca01d090368e66d8300a33803395221c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Aug 2020 19:46:35 -0700 +Subject: usb: dwc3: gadget: Handle ZLP for sg requests + +From: Thinh Nguyen + +[ 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: # v4.5+ +Fixes: 04c03d10e507 ("usb: dwc3: gadget: handle request->zero") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Sasha Levin +--- + 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 +