From: Sasha Levin Date: Mon, 31 Aug 2020 20:08:09 +0000 (-0400) Subject: Fixes for 4.19 X-Git-Tag: v4.4.235~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=803108240f0ff43081e55b013b1f733a71dfdab5;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/btrfs-check-the-right-error-variable-in-btrfs_del_di.patch b/queue-4.19/btrfs-check-the-right-error-variable-in-btrfs_del_di.patch new file mode 100644 index 00000000000..cd5516dab30 --- /dev/null +++ b/queue-4.19/btrfs-check-the-right-error-variable-in-btrfs_del_di.patch @@ -0,0 +1,59 @@ +From c622ed68c728eef955d16e21230994d0ba66d0fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Aug 2020 17:31:16 -0400 +Subject: btrfs: check the right error variable in btrfs_del_dir_entries_in_log + +From: Josef Bacik + +[ Upstream commit fb2fecbad50964b9f27a3b182e74e437b40753ef ] + +With my new locking code dbench is so much faster that I tripped over a +transaction abort from ENOSPC. This turned out to be because +btrfs_del_dir_entries_in_log was checking for ret == -ENOSPC, but this +function sets err on error, and returns err. So instead of properly +marking the inode as needing a full commit, we were returning -ENOSPC +and aborting in __btrfs_unlink_inode. Fix this by checking the proper +variable so that we return the correct thing in the case of ENOSPC. + +The ENOENT needs to be checked, because btrfs_lookup_dir_item_index() +can return -ENOENT if the dir item isn't in the tree log (which would +happen if we hadn't fsync'ed this guy). We actually handle that case in +__btrfs_unlink_inode, so it's an expected error to get back. + +Fixes: 4a500fd178c8 ("Btrfs: Metadata ENOSPC handling for tree log") +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +[ add note and comment about ENOENT ] +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/tree-log.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index 090315f4ac78f..3e903e6a33870 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -3422,11 +3422,13 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, + btrfs_free_path(path); + out_unlock: + mutex_unlock(&dir->log_mutex); +- if (ret == -ENOSPC) { ++ if (err == -ENOSPC) { + btrfs_set_log_full_commit(root->fs_info, trans); +- ret = 0; +- } else if (ret < 0) +- btrfs_abort_transaction(trans, ret); ++ err = 0; ++ } else if (err < 0 && err != -ENOENT) { ++ /* ENOENT can be returned if the entry hasn't been fsynced yet */ ++ btrfs_abort_transaction(trans, err); ++ } + + btrfs_end_log_trans(root); + +-- +2.25.1 + diff --git a/queue-4.19/series b/queue-4.19/series index 430938d6233..6d3a9017427 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -116,3 +116,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 +btrfs-check-the-right-error-variable-in-btrfs_del_di.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-4.19/usb-dwc3-gadget-don-t-setup-more-than-requested.patch b/queue-4.19/usb-dwc3-gadget-don-t-setup-more-than-requested.patch new file mode 100644 index 00000000000..5718067439b --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-don-t-setup-more-than-requested.patch @@ -0,0 +1,174 @@ +From 107a586320a437ea7ea76b3920c75b7c60e3ff81 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 2f5f4ca5c0d04..5d8a28efddad9 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-4.19/usb-dwc3-gadget-fix-handling-zlp.patch b/queue-4.19/usb-dwc3-gadget-fix-handling-zlp.patch new file mode 100644 index 00000000000..25422c7632f --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-fix-handling-zlp.patch @@ -0,0 +1,80 @@ +From a73b22d4c7ead1d796366f5fda580f72f0825a54 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 5d8a28efddad9..9f6b430773000 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); + } +@@ -2347,8 +2358,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-4.19/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch b/queue-4.19/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch new file mode 100644 index 00000000000..1ceadb25078 --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch @@ -0,0 +1,64 @@ +From fee8ea7332b96d8110eedfba5dcf977598a63bba 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 9f6b430773000..7bf2573dd459e 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 +