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

usb: xhci-mtk: improve bandwidth scheduling

Mainly improve SuperSpeed ISOC bandwidth in last microframe,
and LowSpeed/FullSpeed IN INT/ISOC bandwidth in split and
idle microframes by introduing a bandwidth budget table;

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Chunfeng Yun and committed by
Greg Kroah-Hartman
95b516c1 87173acc

+104 -60
+102 -60
drivers/usb/host/xhci-mtk-sch.c
··· 18 18 #define HS_BW_BOUNDARY 6144 19 19 /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */ 20 20 #define FS_PAYLOAD_MAX 188 21 + /* 22 + * max number of microframes for split transfer, 23 + * for fs isoc in : 1 ss + 1 idle + 7 cs 24 + */ 25 + #define TT_MICROFRAMES_MAX 9 21 26 22 27 /* mtk scheduler bitmasks */ 23 28 #define EP_BPKTS(p) ((p) & 0x3f) ··· 69 64 return bw_index; 70 65 } 71 66 67 + static u32 get_esit(struct xhci_ep_ctx *ep_ctx) 68 + { 69 + u32 esit; 70 + 71 + esit = 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info)); 72 + if (esit > XHCI_MTK_MAX_ESIT) 73 + esit = XHCI_MTK_MAX_ESIT; 74 + 75 + return esit; 76 + } 77 + 78 + static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev, 79 + struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx) 80 + { 81 + struct mu3h_sch_ep_info *sch_ep; 82 + u32 len_bw_budget_table; 83 + size_t mem_size; 84 + 85 + if (is_fs_or_ls(udev->speed)) 86 + len_bw_budget_table = TT_MICROFRAMES_MAX; 87 + else if ((udev->speed == USB_SPEED_SUPER) 88 + && usb_endpoint_xfer_isoc(&ep->desc)) 89 + len_bw_budget_table = get_esit(ep_ctx); 90 + else 91 + len_bw_budget_table = 1; 92 + 93 + mem_size = sizeof(struct mu3h_sch_ep_info) + 94 + len_bw_budget_table * sizeof(u32); 95 + sch_ep = kzalloc(mem_size, GFP_KERNEL); 96 + if (!sch_ep) 97 + return ERR_PTR(-ENOMEM); 98 + 99 + sch_ep->ep = ep; 100 + 101 + return sch_ep; 102 + } 103 + 72 104 static void setup_sch_info(struct usb_device *udev, 73 105 struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep) 74 106 { 75 107 u32 ep_type; 76 - u32 ep_interval; 77 - u32 max_packet_size; 108 + u32 maxpkt; 78 109 u32 max_burst; 79 110 u32 mult; 80 111 u32 esit_pkts; 81 112 u32 max_esit_payload; 113 + u32 *bwb_table = sch_ep->bw_budget_table; 114 + int i; 82 115 83 116 ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2)); 84 - ep_interval = CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info)); 85 - max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); 117 + maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); 86 118 max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2)); 87 119 mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info)); 88 120 max_esit_payload = ··· 127 85 le32_to_cpu(ep_ctx->ep_info)) << 16) | 128 86 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info)); 129 87 130 - sch_ep->esit = 1 << ep_interval; 88 + sch_ep->esit = get_esit(ep_ctx); 131 89 sch_ep->offset = 0; 132 90 sch_ep->burst_mode = 0; 91 + sch_ep->repeat = 0; 133 92 134 93 if (udev->speed == USB_SPEED_HIGH) { 135 94 sch_ep->cs_count = 0; ··· 141 98 * in a interval 142 99 */ 143 100 sch_ep->num_budget_microframes = 1; 144 - sch_ep->repeat = 0; 145 101 146 102 /* 147 103 * xHCI spec section6.2.3.4 ··· 148 106 * opportunities per microframe 149 107 */ 150 108 sch_ep->pkts = max_burst + 1; 151 - sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts; 109 + sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; 110 + bwb_table[0] = sch_ep->bw_cost_per_microframe; 152 111 } else if (udev->speed == USB_SPEED_SUPER) { 153 112 /* usb3_r1 spec section4.4.7 & 4.4.8 */ 154 113 sch_ep->cs_count = 0; 114 + sch_ep->burst_mode = 1; 155 115 /* 156 116 * some device's (d)wBytesPerInterval is set as 0, 157 117 * then max_esit_payload is 0, so evaluate esit_pkts from 158 118 * mult and burst 159 119 */ 160 - esit_pkts = DIV_ROUND_UP(max_esit_payload, max_packet_size); 120 + esit_pkts = DIV_ROUND_UP(max_esit_payload, maxpkt); 161 121 if (esit_pkts == 0) 162 122 esit_pkts = (mult + 1) * (max_burst + 1); 163 123 164 124 if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) { 165 125 sch_ep->pkts = esit_pkts; 166 126 sch_ep->num_budget_microframes = 1; 167 - sch_ep->repeat = 0; 127 + bwb_table[0] = maxpkt * sch_ep->pkts; 168 128 } 169 129 170 130 if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) { 131 + u32 remainder; 132 + 171 133 if (sch_ep->esit == 1) 172 134 sch_ep->pkts = esit_pkts; 173 135 else if (esit_pkts <= sch_ep->esit) ··· 183 137 sch_ep->num_budget_microframes = 184 138 DIV_ROUND_UP(esit_pkts, sch_ep->pkts); 185 139 186 - if (sch_ep->num_budget_microframes > 1) 187 - sch_ep->repeat = 1; 188 - else 189 - sch_ep->repeat = 0; 140 + sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1); 141 + sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; 142 + 143 + remainder = sch_ep->bw_cost_per_microframe; 144 + remainder *= sch_ep->num_budget_microframes; 145 + remainder -= (maxpkt * esit_pkts); 146 + for (i = 0; i < sch_ep->num_budget_microframes - 1; i++) 147 + bwb_table[i] = sch_ep->bw_cost_per_microframe; 148 + 149 + /* last one <= bw_cost_per_microframe */ 150 + bwb_table[i] = remainder; 190 151 } 191 - sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts; 192 152 } else if (is_fs_or_ls(udev->speed)) { 193 - 194 - /* 195 - * usb_20 spec section11.18.4 196 - * assume worst cases 197 - */ 198 - sch_ep->repeat = 0; 199 153 sch_ep->pkts = 1; /* at most one packet for each microframe */ 200 - if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) { 201 - sch_ep->cs_count = 3; /* at most need 3 CS*/ 202 - /* one for SS and one for budgeted transaction */ 203 - sch_ep->num_budget_microframes = sch_ep->cs_count + 2; 204 - sch_ep->bw_cost_per_microframe = max_packet_size; 205 - } 206 - if (ep_type == ISOC_OUT_EP) { 154 + sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX); 155 + sch_ep->num_budget_microframes = sch_ep->cs_count + 2; 156 + sch_ep->bw_cost_per_microframe = 157 + (maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX; 207 158 208 - /* 209 - * the best case FS budget assumes that 188 FS bytes 210 - * occur in each microframe 211 - */ 212 - sch_ep->num_budget_microframes = DIV_ROUND_UP( 213 - max_packet_size, FS_PAYLOAD_MAX); 214 - sch_ep->bw_cost_per_microframe = FS_PAYLOAD_MAX; 215 - sch_ep->cs_count = sch_ep->num_budget_microframes; 216 - } 217 - if (ep_type == ISOC_IN_EP) { 218 - /* at most need additional two CS. */ 219 - sch_ep->cs_count = DIV_ROUND_UP( 220 - max_packet_size, FS_PAYLOAD_MAX) + 2; 221 - sch_ep->num_budget_microframes = sch_ep->cs_count + 2; 222 - sch_ep->bw_cost_per_microframe = FS_PAYLOAD_MAX; 159 + /* init budget table */ 160 + if (ep_type == ISOC_OUT_EP) { 161 + for (i = 0; i < sch_ep->num_budget_microframes; i++) 162 + bwb_table[i] = sch_ep->bw_cost_per_microframe; 163 + } else if (ep_type == INT_OUT_EP) { 164 + /* only first one consumes bandwidth, others as zero */ 165 + bwb_table[0] = sch_ep->bw_cost_per_microframe; 166 + } else { /* INT_IN_EP or ISOC_IN_EP */ 167 + bwb_table[0] = 0; /* start split */ 168 + bwb_table[1] = 0; /* idle */ 169 + for (i = 2; i < sch_ep->num_budget_microframes; i++) 170 + bwb_table[i] = sch_ep->bw_cost_per_microframe; 223 171 } 224 172 } 225 173 } ··· 224 184 { 225 185 u32 num_esit; 226 186 u32 max_bw = 0; 187 + u32 bw; 227 188 int i; 228 189 int j; 229 190 ··· 233 192 u32 base = offset + i * sch_ep->esit; 234 193 235 194 for (j = 0; j < sch_ep->num_budget_microframes; j++) { 236 - if (sch_bw->bus_bw[base + j] > max_bw) 237 - max_bw = sch_bw->bus_bw[base + j]; 195 + bw = sch_bw->bus_bw[base + j] + 196 + sch_ep->bw_budget_table[j]; 197 + if (bw > max_bw) 198 + max_bw = bw; 238 199 } 239 200 } 240 201 return max_bw; 241 202 } 242 203 243 204 static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw, 244 - struct mu3h_sch_ep_info *sch_ep, int bw_cost) 205 + struct mu3h_sch_ep_info *sch_ep, bool used) 245 206 { 246 207 u32 num_esit; 247 208 u32 base; ··· 253 210 num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; 254 211 for (i = 0; i < num_esit; i++) { 255 212 base = sch_ep->offset + i * sch_ep->esit; 256 - for (j = 0; j < sch_ep->num_budget_microframes; j++) 257 - sch_bw->bus_bw[base + j] += bw_cost; 213 + for (j = 0; j < sch_ep->num_budget_microframes; j++) { 214 + if (used) 215 + sch_bw->bus_bw[base + j] += 216 + sch_ep->bw_budget_table[j]; 217 + else 218 + sch_bw->bus_bw[base + j] -= 219 + sch_ep->bw_budget_table[j]; 220 + } 258 221 } 259 222 } 260 223 ··· 269 220 { 270 221 u32 offset; 271 222 u32 esit; 272 - u32 num_budget_microframes; 273 223 u32 min_bw; 274 224 u32 min_index; 275 225 u32 worst_bw; 276 226 u32 bw_boundary; 277 227 278 - if (sch_ep->esit > XHCI_MTK_MAX_ESIT) 279 - sch_ep->esit = XHCI_MTK_MAX_ESIT; 280 - 281 228 esit = sch_ep->esit; 282 - num_budget_microframes = sch_ep->num_budget_microframes; 283 229 284 230 /* 285 231 * Search through all possible schedule microframes. ··· 283 239 min_bw = ~0; 284 240 min_index = 0; 285 241 for (offset = 0; offset < esit; offset++) { 286 - if ((offset + num_budget_microframes) > sch_ep->esit) 242 + if ((offset + sch_ep->num_budget_microframes) > sch_ep->esit) 287 243 break; 288 244 289 245 /* ··· 307 263 ? SS_BW_BOUNDARY : HS_BW_BOUNDARY; 308 264 309 265 /* check bandwidth */ 310 - if (min_bw + sch_ep->bw_cost_per_microframe > bw_boundary) 266 + if (min_bw > bw_boundary) 311 267 return -ERANGE; 312 268 313 269 /* update bus bandwidth info */ 314 - update_bus_bw(sch_bw, sch_ep, sch_ep->bw_cost_per_microframe); 270 + update_bus_bw(sch_bw, sch_ep, 1); 315 271 316 272 return 0; 317 273 } ··· 406 362 bw_index = get_bw_index(xhci, udev, ep); 407 363 sch_bw = &sch_array[bw_index]; 408 364 409 - sch_ep = kzalloc(sizeof(struct mu3h_sch_ep_info), GFP_NOIO); 410 - if (!sch_ep) 365 + sch_ep = create_sch_ep(udev, ep, ep_ctx); 366 + if (IS_ERR_OR_NULL(sch_ep)) 411 367 return -ENOMEM; 412 368 413 369 setup_sch_info(udev, ep_ctx, sch_ep); ··· 420 376 } 421 377 422 378 list_add_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list); 423 - sch_ep->ep = ep; 424 379 425 380 ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts) 426 381 | EP_BCSCOUNT(sch_ep->cs_count) | EP_BBM(sch_ep->burst_mode)); ··· 464 421 465 422 list_for_each_entry(sch_ep, &sch_bw->bw_ep_list, endpoint) { 466 423 if (sch_ep->ep == ep) { 467 - update_bus_bw(sch_bw, sch_ep, 468 - -sch_ep->bw_cost_per_microframe); 424 + update_bus_bw(sch_bw, sch_ep, 0); 469 425 list_del(&sch_ep->endpoint); 470 426 kfree(sch_ep); 471 427 break;
+2
drivers/usb/host/xhci-mtk.h
··· 57 57 * times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets 58 58 * according to @pkts and @repeat. normal mode is used by 59 59 * default 60 + * @bw_budget_table: table to record bandwidth budget per microframe 60 61 */ 61 62 struct mu3h_sch_ep_info { 62 63 u32 esit; ··· 74 73 u32 pkts; 75 74 u32 cs_count; 76 75 u32 burst_mode; 76 + u32 bw_budget_table[0]; 77 77 }; 78 78 79 79 #define MU3C_U3_PORT_MAX 4