Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'fixes-for-v5.9-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus

Felipe writes:

USB: fixes for v5.9-rc

Three ZLP fixes on dwc3 and a resource leak fix on the TCM gadget

Signed-off-by: Felipe Balbi <balbi@kernel.org>

* tag 'fixes-for-v5.9-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb:
usb: dwc3: gadget: Handle ZLP for sg requests
usb: dwc3: gadget: Fix handling ZLP
usb: dwc3: gadget: Don't setup more than requested
usb: gadget: f_tcm: Fix some resource leaks in some error paths

+93 -21
+89 -18
drivers/usb/dwc3/gadget.c
··· 1054 1054 * dwc3_prepare_one_trb - setup one TRB from one request 1055 1055 * @dep: endpoint for which this request is prepared 1056 1056 * @req: dwc3_request pointer 1057 + * @trb_length: buffer size of the TRB 1057 1058 * @chain: should this TRB be chained to the next? 1058 1059 * @node: only for isochronous endpoints. First TRB needs different type. 1059 1060 */ 1060 1061 static void dwc3_prepare_one_trb(struct dwc3_ep *dep, 1061 - struct dwc3_request *req, unsigned chain, unsigned node) 1062 + struct dwc3_request *req, unsigned int trb_length, 1063 + unsigned chain, unsigned node) 1062 1064 { 1063 1065 struct dwc3_trb *trb; 1064 - unsigned int length; 1065 1066 dma_addr_t dma; 1066 1067 unsigned stream_id = req->request.stream_id; 1067 1068 unsigned short_not_ok = req->request.short_not_ok; 1068 1069 unsigned no_interrupt = req->request.no_interrupt; 1069 1070 unsigned is_last = req->request.is_last; 1070 1071 1071 - if (req->request.num_sgs > 0) { 1072 - length = sg_dma_len(req->start_sg); 1072 + if (req->request.num_sgs > 0) 1073 1073 dma = sg_dma_address(req->start_sg); 1074 - } else { 1075 - length = req->request.length; 1074 + else 1076 1075 dma = req->request.dma; 1077 - } 1078 1076 1079 1077 trb = &dep->trb_pool[dep->trb_enqueue]; 1080 1078 ··· 1084 1086 1085 1087 req->num_trbs++; 1086 1088 1087 - __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, 1089 + __dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node, 1088 1090 stream_id, short_not_ok, no_interrupt, is_last); 1089 1091 } 1090 1092 ··· 1094 1096 struct scatterlist *sg = req->start_sg; 1095 1097 struct scatterlist *s; 1096 1098 int i; 1097 - 1099 + unsigned int length = req->request.length; 1098 1100 unsigned int remaining = req->request.num_mapped_sgs 1099 1101 - req->num_queued_sgs; 1100 1102 1103 + /* 1104 + * If we resume preparing the request, then get the remaining length of 1105 + * the request and resume where we left off. 1106 + */ 1107 + for_each_sg(req->request.sg, s, req->num_queued_sgs, i) 1108 + length -= sg_dma_len(s); 1109 + 1101 1110 for_each_sg(sg, s, remaining, i) { 1102 - unsigned int length = req->request.length; 1103 1111 unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); 1104 1112 unsigned int rem = length % maxp; 1113 + unsigned int trb_length; 1105 1114 unsigned chain = true; 1115 + 1116 + trb_length = min_t(unsigned int, length, sg_dma_len(s)); 1117 + 1118 + length -= trb_length; 1106 1119 1107 1120 /* 1108 1121 * IOMMU driver is coalescing the list of sgs which shares a ··· 1122 1113 * sgs passed. So mark the chain bit to false if it isthe last 1123 1114 * mapped sg. 1124 1115 */ 1125 - if (i == remaining - 1) 1116 + if ((i == remaining - 1) || !length) 1126 1117 chain = false; 1127 1118 1128 1119 if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { ··· 1132 1123 req->needs_extra_trb = true; 1133 1124 1134 1125 /* prepare normal TRB */ 1135 - dwc3_prepare_one_trb(dep, req, true, i); 1126 + dwc3_prepare_one_trb(dep, req, trb_length, true, i); 1136 1127 1137 1128 /* Now prepare one extra TRB to align transfer size */ 1138 1129 trb = &dep->trb_pool[dep->trb_enqueue]; ··· 1143 1134 req->request.short_not_ok, 1144 1135 req->request.no_interrupt, 1145 1136 req->request.is_last); 1137 + } else if (req->request.zero && req->request.length && 1138 + !usb_endpoint_xfer_isoc(dep->endpoint.desc) && 1139 + !rem && !chain) { 1140 + struct dwc3 *dwc = dep->dwc; 1141 + struct dwc3_trb *trb; 1142 + 1143 + req->needs_extra_trb = true; 1144 + 1145 + /* Prepare normal TRB */ 1146 + dwc3_prepare_one_trb(dep, req, trb_length, true, i); 1147 + 1148 + /* Prepare one extra TRB to handle ZLP */ 1149 + trb = &dep->trb_pool[dep->trb_enqueue]; 1150 + req->num_trbs++; 1151 + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, 1152 + !req->direction, 1, 1153 + req->request.stream_id, 1154 + req->request.short_not_ok, 1155 + req->request.no_interrupt, 1156 + req->request.is_last); 1157 + 1158 + /* Prepare one more TRB to handle MPS alignment */ 1159 + if (!req->direction) { 1160 + trb = &dep->trb_pool[dep->trb_enqueue]; 1161 + req->num_trbs++; 1162 + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp, 1163 + false, 1, req->request.stream_id, 1164 + req->request.short_not_ok, 1165 + req->request.no_interrupt, 1166 + req->request.is_last); 1167 + } 1146 1168 } else { 1147 - dwc3_prepare_one_trb(dep, req, chain, i); 1169 + dwc3_prepare_one_trb(dep, req, trb_length, chain, i); 1148 1170 } 1149 1171 1150 1172 /* ··· 1189 1149 req->start_sg = sg_next(s); 1190 1150 1191 1151 req->num_queued_sgs++; 1152 + 1153 + /* 1154 + * The number of pending SG entries may not correspond to the 1155 + * number of mapped SG entries. If all the data are queued, then 1156 + * don't include unused SG entries. 1157 + */ 1158 + if (length == 0) { 1159 + req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs; 1160 + break; 1161 + } 1192 1162 1193 1163 if (!dwc3_calc_trbs_left(dep)) 1194 1164 break; ··· 1219 1169 req->needs_extra_trb = true; 1220 1170 1221 1171 /* prepare normal TRB */ 1222 - dwc3_prepare_one_trb(dep, req, true, 0); 1172 + dwc3_prepare_one_trb(dep, req, length, true, 0); 1223 1173 1224 1174 /* Now prepare one extra TRB to align transfer size */ 1225 1175 trb = &dep->trb_pool[dep->trb_enqueue]; ··· 1230 1180 req->request.no_interrupt, 1231 1181 req->request.is_last); 1232 1182 } else if (req->request.zero && req->request.length && 1183 + !usb_endpoint_xfer_isoc(dep->endpoint.desc) && 1233 1184 (IS_ALIGNED(req->request.length, maxp))) { 1234 1185 struct dwc3 *dwc = dep->dwc; 1235 1186 struct dwc3_trb *trb; ··· 1238 1187 req->needs_extra_trb = true; 1239 1188 1240 1189 /* prepare normal TRB */ 1241 - dwc3_prepare_one_trb(dep, req, true, 0); 1190 + dwc3_prepare_one_trb(dep, req, length, true, 0); 1242 1191 1243 - /* Now prepare one extra TRB to handle ZLP */ 1192 + /* Prepare one extra TRB to handle ZLP */ 1244 1193 trb = &dep->trb_pool[dep->trb_enqueue]; 1245 1194 req->num_trbs++; 1246 1195 __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, 1247 - false, 1, req->request.stream_id, 1196 + !req->direction, 1, req->request.stream_id, 1248 1197 req->request.short_not_ok, 1249 1198 req->request.no_interrupt, 1250 1199 req->request.is_last); 1200 + 1201 + /* Prepare one more TRB to handle MPS alignment for OUT */ 1202 + if (!req->direction) { 1203 + trb = &dep->trb_pool[dep->trb_enqueue]; 1204 + req->num_trbs++; 1205 + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp, 1206 + false, 1, req->request.stream_id, 1207 + req->request.short_not_ok, 1208 + req->request.no_interrupt, 1209 + req->request.is_last); 1210 + } 1251 1211 } else { 1252 - dwc3_prepare_one_trb(dep, req, false, 0); 1212 + dwc3_prepare_one_trb(dep, req, length, false, 0); 1253 1213 } 1254 1214 } 1255 1215 ··· 2733 2671 status); 2734 2672 2735 2673 if (req->needs_extra_trb) { 2674 + unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); 2675 + 2736 2676 ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, 2737 2677 status); 2678 + 2679 + /* Reclaim MPS padding TRB for ZLP */ 2680 + if (!req->direction && req->request.zero && req->request.length && 2681 + !usb_endpoint_xfer_isoc(dep->endpoint.desc) && 2682 + (IS_ALIGNED(req->request.length, maxp))) 2683 + ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, status); 2684 + 2738 2685 req->needs_extra_trb = false; 2739 2686 } 2740 2687
+4 -3
drivers/usb/gadget/function/f_tcm.c
··· 753 753 goto err_sts; 754 754 755 755 return 0; 756 + 756 757 err_sts: 757 - usb_ep_free_request(fu->ep_status, stream->req_status); 758 - stream->req_status = NULL; 759 - err_out: 760 758 usb_ep_free_request(fu->ep_out, stream->req_out); 761 759 stream->req_out = NULL; 760 + err_out: 761 + usb_ep_free_request(fu->ep_in, stream->req_in); 762 + stream->req_in = NULL; 762 763 out: 763 764 return -ENOMEM; 764 765 }