root/drivers/usb/host/xhci-mtk-sch.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. is_fs_or_ls
  2. get_bw_index
  3. get_esit
  4. find_tt
  5. drop_tt
  6. create_sch_ep
  7. setup_sch_info
  8. get_max_bw
  9. update_bus_bw
  10. check_sch_tt
  11. update_sch_tt
  12. check_sch_bw
  13. need_bw_sch
  14. xhci_mtk_sch_init
  15. xhci_mtk_sch_exit
  16. xhci_mtk_add_ep_quirk
  17. xhci_mtk_drop_ep_quirk

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2015 MediaTek Inc.
   4  * Author:
   5  *  Zhigang.Wei <zhigang.wei@mediatek.com>
   6  *  Chunfeng.Yun <chunfeng.yun@mediatek.com>
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/module.h>
  11 #include <linux/slab.h>
  12 
  13 #include "xhci.h"
  14 #include "xhci-mtk.h"
  15 
  16 #define SSP_BW_BOUNDARY 130000
  17 #define SS_BW_BOUNDARY  51000
  18 /* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
  19 #define HS_BW_BOUNDARY  6144
  20 /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
  21 #define FS_PAYLOAD_MAX 188
  22 /*
  23  * max number of microframes for split transfer,
  24  * for fs isoc in : 1 ss + 1 idle + 7 cs
  25  */
  26 #define TT_MICROFRAMES_MAX 9
  27 
  28 /* mtk scheduler bitmasks */
  29 #define EP_BPKTS(p)     ((p) & 0x7f)
  30 #define EP_BCSCOUNT(p)  (((p) & 0x7) << 8)
  31 #define EP_BBM(p)       ((p) << 11)
  32 #define EP_BOFFSET(p)   ((p) & 0x3fff)
  33 #define EP_BREPEAT(p)   (((p) & 0x7fff) << 16)
  34 
  35 static int is_fs_or_ls(enum usb_device_speed speed)
  36 {
  37         return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW;
  38 }
  39 
  40 /*
  41 * get the index of bandwidth domains array which @ep belongs to.
  42 *
  43 * the bandwidth domain array is saved to @sch_array of struct xhci_hcd_mtk,
  44 * each HS root port is treated as a single bandwidth domain,
  45 * but each SS root port is treated as two bandwidth domains, one for IN eps,
  46 * one for OUT eps.
  47 * @real_port value is defined as follow according to xHCI spec:
  48 * 1 for SSport0, ..., N+1 for SSportN, N+2 for HSport0, N+3 for HSport1, etc
  49 * so the bandwidth domain array is organized as follow for simplification:
  50 * SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY
  51 */
  52 static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev,
  53         struct usb_host_endpoint *ep)
  54 {
  55         struct xhci_virt_device *virt_dev;
  56         int bw_index;
  57 
  58         virt_dev = xhci->devs[udev->slot_id];
  59 
  60         if (udev->speed >= USB_SPEED_SUPER) {
  61                 if (usb_endpoint_dir_out(&ep->desc))
  62                         bw_index = (virt_dev->real_port - 1) * 2;
  63                 else
  64                         bw_index = (virt_dev->real_port - 1) * 2 + 1;
  65         } else {
  66                 /* add one more for each SS port */
  67                 bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports - 1;
  68         }
  69 
  70         return bw_index;
  71 }
  72 
  73 static u32 get_esit(struct xhci_ep_ctx *ep_ctx)
  74 {
  75         u32 esit;
  76 
  77         esit = 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
  78         if (esit > XHCI_MTK_MAX_ESIT)
  79                 esit = XHCI_MTK_MAX_ESIT;
  80 
  81         return esit;
  82 }
  83 
  84 static struct mu3h_sch_tt *find_tt(struct usb_device *udev)
  85 {
  86         struct usb_tt *utt = udev->tt;
  87         struct mu3h_sch_tt *tt, **tt_index, **ptt;
  88         unsigned int port;
  89         bool allocated_index = false;
  90 
  91         if (!utt)
  92                 return NULL;    /* Not below a TT */
  93 
  94         /*
  95          * Find/create our data structure.
  96          * For hubs with a single TT, we get it directly.
  97          * For hubs with multiple TTs, there's an extra level of pointers.
  98          */
  99         tt_index = NULL;
 100         if (utt->multi) {
 101                 tt_index = utt->hcpriv;
 102                 if (!tt_index) {        /* Create the index array */
 103                         tt_index = kcalloc(utt->hub->maxchild,
 104                                         sizeof(*tt_index), GFP_KERNEL);
 105                         if (!tt_index)
 106                                 return ERR_PTR(-ENOMEM);
 107                         utt->hcpriv = tt_index;
 108                         allocated_index = true;
 109                 }
 110                 port = udev->ttport - 1;
 111                 ptt = &tt_index[port];
 112         } else {
 113                 port = 0;
 114                 ptt = (struct mu3h_sch_tt **) &utt->hcpriv;
 115         }
 116 
 117         tt = *ptt;
 118         if (!tt) {      /* Create the mu3h_sch_tt */
 119                 tt = kzalloc(sizeof(*tt), GFP_KERNEL);
 120                 if (!tt) {
 121                         if (allocated_index) {
 122                                 utt->hcpriv = NULL;
 123                                 kfree(tt_index);
 124                         }
 125                         return ERR_PTR(-ENOMEM);
 126                 }
 127                 INIT_LIST_HEAD(&tt->ep_list);
 128                 tt->usb_tt = utt;
 129                 tt->tt_port = port;
 130                 *ptt = tt;
 131         }
 132 
 133         return tt;
 134 }
 135 
 136 /* Release the TT above udev, if it's not in use */
 137 static void drop_tt(struct usb_device *udev)
 138 {
 139         struct usb_tt *utt = udev->tt;
 140         struct mu3h_sch_tt *tt, **tt_index, **ptt;
 141         int i, cnt;
 142 
 143         if (!utt || !utt->hcpriv)
 144                 return;         /* Not below a TT, or never allocated */
 145 
 146         cnt = 0;
 147         if (utt->multi) {
 148                 tt_index = utt->hcpriv;
 149                 ptt = &tt_index[udev->ttport - 1];
 150                 /*  How many entries are left in tt_index? */
 151                 for (i = 0; i < utt->hub->maxchild; ++i)
 152                         cnt += !!tt_index[i];
 153         } else {
 154                 tt_index = NULL;
 155                 ptt = (struct mu3h_sch_tt **)&utt->hcpriv;
 156         }
 157 
 158         tt = *ptt;
 159         if (!tt || !list_empty(&tt->ep_list))
 160                 return;         /* never allocated , or still in use*/
 161 
 162         *ptt = NULL;
 163         kfree(tt);
 164 
 165         if (cnt == 1) {
 166                 utt->hcpriv = NULL;
 167                 kfree(tt_index);
 168         }
 169 }
 170 
 171 static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
 172         struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
 173 {
 174         struct mu3h_sch_ep_info *sch_ep;
 175         struct mu3h_sch_tt *tt = NULL;
 176         u32 len_bw_budget_table;
 177         size_t mem_size;
 178 
 179         if (is_fs_or_ls(udev->speed))
 180                 len_bw_budget_table = TT_MICROFRAMES_MAX;
 181         else if ((udev->speed >= USB_SPEED_SUPER)
 182                         && usb_endpoint_xfer_isoc(&ep->desc))
 183                 len_bw_budget_table = get_esit(ep_ctx);
 184         else
 185                 len_bw_budget_table = 1;
 186 
 187         mem_size = sizeof(struct mu3h_sch_ep_info) +
 188                         len_bw_budget_table * sizeof(u32);
 189         sch_ep = kzalloc(mem_size, GFP_KERNEL);
 190         if (!sch_ep)
 191                 return ERR_PTR(-ENOMEM);
 192 
 193         if (is_fs_or_ls(udev->speed)) {
 194                 tt = find_tt(udev);
 195                 if (IS_ERR(tt)) {
 196                         kfree(sch_ep);
 197                         return ERR_PTR(-ENOMEM);
 198                 }
 199         }
 200 
 201         sch_ep->sch_tt = tt;
 202         sch_ep->ep = ep;
 203 
 204         return sch_ep;
 205 }
 206 
 207 static void setup_sch_info(struct usb_device *udev,
 208                 struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep)
 209 {
 210         u32 ep_type;
 211         u32 maxpkt;
 212         u32 max_burst;
 213         u32 mult;
 214         u32 esit_pkts;
 215         u32 max_esit_payload;
 216         u32 *bwb_table = sch_ep->bw_budget_table;
 217         int i;
 218 
 219         ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
 220         maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
 221         max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2));
 222         mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info));
 223         max_esit_payload =
 224                 (CTX_TO_MAX_ESIT_PAYLOAD_HI(
 225                         le32_to_cpu(ep_ctx->ep_info)) << 16) |
 226                  CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
 227 
 228         sch_ep->esit = get_esit(ep_ctx);
 229         sch_ep->ep_type = ep_type;
 230         sch_ep->maxpkt = maxpkt;
 231         sch_ep->offset = 0;
 232         sch_ep->burst_mode = 0;
 233         sch_ep->repeat = 0;
 234 
 235         if (udev->speed == USB_SPEED_HIGH) {
 236                 sch_ep->cs_count = 0;
 237 
 238                 /*
 239                  * usb_20 spec section5.9
 240                  * a single microframe is enough for HS synchromous endpoints
 241                  * in a interval
 242                  */
 243                 sch_ep->num_budget_microframes = 1;
 244 
 245                 /*
 246                  * xHCI spec section6.2.3.4
 247                  * @max_burst is the number of additional transactions
 248                  * opportunities per microframe
 249                  */
 250                 sch_ep->pkts = max_burst + 1;
 251                 sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
 252                 bwb_table[0] = sch_ep->bw_cost_per_microframe;
 253         } else if (udev->speed >= USB_SPEED_SUPER) {
 254                 /* usb3_r1 spec section4.4.7 & 4.4.8 */
 255                 sch_ep->cs_count = 0;
 256                 sch_ep->burst_mode = 1;
 257                 /*
 258                  * some device's (d)wBytesPerInterval is set as 0,
 259                  * then max_esit_payload is 0, so evaluate esit_pkts from
 260                  * mult and burst
 261                  */
 262                 esit_pkts = DIV_ROUND_UP(max_esit_payload, maxpkt);
 263                 if (esit_pkts == 0)
 264                         esit_pkts = (mult + 1) * (max_burst + 1);
 265 
 266                 if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
 267                         sch_ep->pkts = esit_pkts;
 268                         sch_ep->num_budget_microframes = 1;
 269                         bwb_table[0] = maxpkt * sch_ep->pkts;
 270                 }
 271 
 272                 if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
 273                         u32 remainder;
 274 
 275                         if (sch_ep->esit == 1)
 276                                 sch_ep->pkts = esit_pkts;
 277                         else if (esit_pkts <= sch_ep->esit)
 278                                 sch_ep->pkts = 1;
 279                         else
 280                                 sch_ep->pkts = roundup_pow_of_two(esit_pkts)
 281                                         / sch_ep->esit;
 282 
 283                         sch_ep->num_budget_microframes =
 284                                 DIV_ROUND_UP(esit_pkts, sch_ep->pkts);
 285 
 286                         sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1);
 287                         sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
 288 
 289                         remainder = sch_ep->bw_cost_per_microframe;
 290                         remainder *= sch_ep->num_budget_microframes;
 291                         remainder -= (maxpkt * esit_pkts);
 292                         for (i = 0; i < sch_ep->num_budget_microframes - 1; i++)
 293                                 bwb_table[i] = sch_ep->bw_cost_per_microframe;
 294 
 295                         /* last one <= bw_cost_per_microframe */
 296                         bwb_table[i] = remainder;
 297                 }
 298         } else if (is_fs_or_ls(udev->speed)) {
 299                 sch_ep->pkts = 1; /* at most one packet for each microframe */
 300 
 301                 /*
 302                  * num_budget_microframes and cs_count will be updated when
 303                  * check TT for INT_OUT_EP, ISOC/INT_IN_EP type
 304                  */
 305                 sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX);
 306                 sch_ep->num_budget_microframes = sch_ep->cs_count;
 307                 sch_ep->bw_cost_per_microframe =
 308                         (maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX;
 309 
 310                 /* init budget table */
 311                 if (ep_type == ISOC_OUT_EP) {
 312                         for (i = 0; i < sch_ep->num_budget_microframes; i++)
 313                                 bwb_table[i] =  sch_ep->bw_cost_per_microframe;
 314                 } else if (ep_type == INT_OUT_EP) {
 315                         /* only first one consumes bandwidth, others as zero */
 316                         bwb_table[0] = sch_ep->bw_cost_per_microframe;
 317                 } else { /* INT_IN_EP or ISOC_IN_EP */
 318                         bwb_table[0] = 0; /* start split */
 319                         bwb_table[1] = 0; /* idle */
 320                         /*
 321                          * due to cs_count will be updated according to cs
 322                          * position, assign all remainder budget array
 323                          * elements as @bw_cost_per_microframe, but only first
 324                          * @num_budget_microframes elements will be used later
 325                          */
 326                         for (i = 2; i < TT_MICROFRAMES_MAX; i++)
 327                                 bwb_table[i] =  sch_ep->bw_cost_per_microframe;
 328                 }
 329         }
 330 }
 331 
 332 /* Get maximum bandwidth when we schedule at offset slot. */
 333 static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
 334         struct mu3h_sch_ep_info *sch_ep, u32 offset)
 335 {
 336         u32 num_esit;
 337         u32 max_bw = 0;
 338         u32 bw;
 339         int i;
 340         int j;
 341 
 342         num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
 343         for (i = 0; i < num_esit; i++) {
 344                 u32 base = offset + i * sch_ep->esit;
 345 
 346                 for (j = 0; j < sch_ep->num_budget_microframes; j++) {
 347                         bw = sch_bw->bus_bw[base + j] +
 348                                         sch_ep->bw_budget_table[j];
 349                         if (bw > max_bw)
 350                                 max_bw = bw;
 351                 }
 352         }
 353         return max_bw;
 354 }
 355 
 356 static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
 357         struct mu3h_sch_ep_info *sch_ep, bool used)
 358 {
 359         u32 num_esit;
 360         u32 base;
 361         int i;
 362         int j;
 363 
 364         num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
 365         for (i = 0; i < num_esit; i++) {
 366                 base = sch_ep->offset + i * sch_ep->esit;
 367                 for (j = 0; j < sch_ep->num_budget_microframes; j++) {
 368                         if (used)
 369                                 sch_bw->bus_bw[base + j] +=
 370                                         sch_ep->bw_budget_table[j];
 371                         else
 372                                 sch_bw->bus_bw[base + j] -=
 373                                         sch_ep->bw_budget_table[j];
 374                 }
 375         }
 376 }
 377 
 378 static int check_sch_tt(struct usb_device *udev,
 379         struct mu3h_sch_ep_info *sch_ep, u32 offset)
 380 {
 381         struct mu3h_sch_tt *tt = sch_ep->sch_tt;
 382         u32 extra_cs_count;
 383         u32 fs_budget_start;
 384         u32 start_ss, last_ss;
 385         u32 start_cs, last_cs;
 386         int i;
 387 
 388         start_ss = offset % 8;
 389         fs_budget_start = (start_ss + 1) % 8;
 390 
 391         if (sch_ep->ep_type == ISOC_OUT_EP) {
 392                 last_ss = start_ss + sch_ep->cs_count - 1;
 393 
 394                 /*
 395                  * usb_20 spec section11.18:
 396                  * must never schedule Start-Split in Y6
 397                  */
 398                 if (!(start_ss == 7 || last_ss < 6))
 399                         return -ERANGE;
 400 
 401                 for (i = 0; i < sch_ep->cs_count; i++)
 402                         if (test_bit(offset + i, tt->split_bit_map))
 403                                 return -ERANGE;
 404 
 405         } else {
 406                 u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX);
 407 
 408                 /*
 409                  * usb_20 spec section11.18:
 410                  * must never schedule Start-Split in Y6
 411                  */
 412                 if (start_ss == 6)
 413                         return -ERANGE;
 414 
 415                 /* one uframe for ss + one uframe for idle */
 416                 start_cs = (start_ss + 2) % 8;
 417                 last_cs = start_cs + cs_count - 1;
 418 
 419                 if (last_cs > 7)
 420                         return -ERANGE;
 421 
 422                 if (sch_ep->ep_type == ISOC_IN_EP)
 423                         extra_cs_count = (last_cs == 7) ? 1 : 2;
 424                 else /*  ep_type : INTR IN / INTR OUT */
 425                         extra_cs_count = (fs_budget_start == 6) ? 1 : 2;
 426 
 427                 cs_count += extra_cs_count;
 428                 if (cs_count > 7)
 429                         cs_count = 7; /* HW limit */
 430 
 431                 for (i = 0; i < cs_count + 2; i++) {
 432                         if (test_bit(offset + i, tt->split_bit_map))
 433                                 return -ERANGE;
 434                 }
 435 
 436                 sch_ep->cs_count = cs_count;
 437                 /* one for ss, the other for idle */
 438                 sch_ep->num_budget_microframes = cs_count + 2;
 439 
 440                 /*
 441                  * if interval=1, maxp >752, num_budge_micoframe is larger
 442                  * than sch_ep->esit, will overstep boundary
 443                  */
 444                 if (sch_ep->num_budget_microframes > sch_ep->esit)
 445                         sch_ep->num_budget_microframes = sch_ep->esit;
 446         }
 447 
 448         return 0;
 449 }
 450 
 451 static void update_sch_tt(struct usb_device *udev,
 452         struct mu3h_sch_ep_info *sch_ep)
 453 {
 454         struct mu3h_sch_tt *tt = sch_ep->sch_tt;
 455         u32 base, num_esit;
 456         int i, j;
 457 
 458         num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
 459         for (i = 0; i < num_esit; i++) {
 460                 base = sch_ep->offset + i * sch_ep->esit;
 461                 for (j = 0; j < sch_ep->num_budget_microframes; j++)
 462                         set_bit(base + j, tt->split_bit_map);
 463         }
 464 
 465         list_add_tail(&sch_ep->tt_endpoint, &tt->ep_list);
 466 }
 467 
 468 static int check_sch_bw(struct usb_device *udev,
 469         struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)
 470 {
 471         u32 offset;
 472         u32 esit;
 473         u32 min_bw;
 474         u32 min_index;
 475         u32 worst_bw;
 476         u32 bw_boundary;
 477         u32 min_num_budget;
 478         u32 min_cs_count;
 479         bool tt_offset_ok = false;
 480         int ret;
 481 
 482         esit = sch_ep->esit;
 483 
 484         /*
 485          * Search through all possible schedule microframes.
 486          * and find a microframe where its worst bandwidth is minimum.
 487          */
 488         min_bw = ~0;
 489         min_index = 0;
 490         min_cs_count = sch_ep->cs_count;
 491         min_num_budget = sch_ep->num_budget_microframes;
 492         for (offset = 0; offset < esit; offset++) {
 493                 if (is_fs_or_ls(udev->speed)) {
 494                         ret = check_sch_tt(udev, sch_ep, offset);
 495                         if (ret)
 496                                 continue;
 497                         else
 498                                 tt_offset_ok = true;
 499                 }
 500 
 501                 if ((offset + sch_ep->num_budget_microframes) > sch_ep->esit)
 502                         break;
 503 
 504                 worst_bw = get_max_bw(sch_bw, sch_ep, offset);
 505                 if (min_bw > worst_bw) {
 506                         min_bw = worst_bw;
 507                         min_index = offset;
 508                         min_cs_count = sch_ep->cs_count;
 509                         min_num_budget = sch_ep->num_budget_microframes;
 510                 }
 511                 if (min_bw == 0)
 512                         break;
 513         }
 514 
 515         if (udev->speed == USB_SPEED_SUPER_PLUS)
 516                 bw_boundary = SSP_BW_BOUNDARY;
 517         else if (udev->speed == USB_SPEED_SUPER)
 518                 bw_boundary = SS_BW_BOUNDARY;
 519         else
 520                 bw_boundary = HS_BW_BOUNDARY;
 521 
 522         /* check bandwidth */
 523         if (min_bw > bw_boundary)
 524                 return -ERANGE;
 525 
 526         sch_ep->offset = min_index;
 527         sch_ep->cs_count = min_cs_count;
 528         sch_ep->num_budget_microframes = min_num_budget;
 529 
 530         if (is_fs_or_ls(udev->speed)) {
 531                 /* all offset for tt is not ok*/
 532                 if (!tt_offset_ok)
 533                         return -ERANGE;
 534 
 535                 update_sch_tt(udev, sch_ep);
 536         }
 537 
 538         /* update bus bandwidth info */
 539         update_bus_bw(sch_bw, sch_ep, 1);
 540 
 541         return 0;
 542 }
 543 
 544 static bool need_bw_sch(struct usb_host_endpoint *ep,
 545         enum usb_device_speed speed, int has_tt)
 546 {
 547         /* only for periodic endpoints */
 548         if (usb_endpoint_xfer_control(&ep->desc)
 549                 || usb_endpoint_xfer_bulk(&ep->desc))
 550                 return false;
 551 
 552         /*
 553          * for LS & FS periodic endpoints which its device is not behind
 554          * a TT are also ignored, root-hub will schedule them directly,
 555          * but need set @bpkts field of endpoint context to 1.
 556          */
 557         if (is_fs_or_ls(speed) && !has_tt)
 558                 return false;
 559 
 560         return true;
 561 }
 562 
 563 int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk)
 564 {
 565         struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd);
 566         struct mu3h_sch_bw_info *sch_array;
 567         int num_usb_bus;
 568         int i;
 569 
 570         /* ss IN and OUT are separated */
 571         num_usb_bus = xhci->usb3_rhub.num_ports * 2 + xhci->usb2_rhub.num_ports;
 572 
 573         sch_array = kcalloc(num_usb_bus, sizeof(*sch_array), GFP_KERNEL);
 574         if (sch_array == NULL)
 575                 return -ENOMEM;
 576 
 577         for (i = 0; i < num_usb_bus; i++)
 578                 INIT_LIST_HEAD(&sch_array[i].bw_ep_list);
 579 
 580         mtk->sch_array = sch_array;
 581 
 582         return 0;
 583 }
 584 EXPORT_SYMBOL_GPL(xhci_mtk_sch_init);
 585 
 586 void xhci_mtk_sch_exit(struct xhci_hcd_mtk *mtk)
 587 {
 588         kfree(mtk->sch_array);
 589 }
 590 EXPORT_SYMBOL_GPL(xhci_mtk_sch_exit);
 591 
 592 int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
 593                 struct usb_host_endpoint *ep)
 594 {
 595         struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
 596         struct xhci_hcd *xhci;
 597         struct xhci_ep_ctx *ep_ctx;
 598         struct xhci_slot_ctx *slot_ctx;
 599         struct xhci_virt_device *virt_dev;
 600         struct mu3h_sch_bw_info *sch_bw;
 601         struct mu3h_sch_ep_info *sch_ep;
 602         struct mu3h_sch_bw_info *sch_array;
 603         unsigned int ep_index;
 604         int bw_index;
 605         int ret = 0;
 606 
 607         xhci = hcd_to_xhci(hcd);
 608         virt_dev = xhci->devs[udev->slot_id];
 609         ep_index = xhci_get_endpoint_index(&ep->desc);
 610         slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
 611         ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
 612         sch_array = mtk->sch_array;
 613 
 614         xhci_dbg(xhci, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n",
 615                 __func__, usb_endpoint_type(&ep->desc), udev->speed,
 616                 usb_endpoint_maxp(&ep->desc),
 617                 usb_endpoint_dir_in(&ep->desc), ep);
 618 
 619         if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) {
 620                 /*
 621                  * set @bpkts to 1 if it is LS or FS periodic endpoint, and its
 622                  * device does not connected through an external HS hub
 623                  */
 624                 if (usb_endpoint_xfer_int(&ep->desc)
 625                         || usb_endpoint_xfer_isoc(&ep->desc))
 626                         ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(1));
 627 
 628                 return 0;
 629         }
 630 
 631         bw_index = get_bw_index(xhci, udev, ep);
 632         sch_bw = &sch_array[bw_index];
 633 
 634         sch_ep = create_sch_ep(udev, ep, ep_ctx);
 635         if (IS_ERR_OR_NULL(sch_ep))
 636                 return -ENOMEM;
 637 
 638         setup_sch_info(udev, ep_ctx, sch_ep);
 639 
 640         ret = check_sch_bw(udev, sch_bw, sch_ep);
 641         if (ret) {
 642                 xhci_err(xhci, "Not enough bandwidth!\n");
 643                 if (is_fs_or_ls(udev->speed))
 644                         drop_tt(udev);
 645 
 646                 kfree(sch_ep);
 647                 return -ENOSPC;
 648         }
 649 
 650         list_add_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
 651 
 652         ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
 653                 | EP_BCSCOUNT(sch_ep->cs_count) | EP_BBM(sch_ep->burst_mode));
 654         ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset)
 655                 | EP_BREPEAT(sch_ep->repeat));
 656 
 657         xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
 658                         sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode,
 659                         sch_ep->offset, sch_ep->repeat);
 660 
 661         return 0;
 662 }
 663 EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk);
 664 
 665 void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
 666                 struct usb_host_endpoint *ep)
 667 {
 668         struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
 669         struct xhci_hcd *xhci;
 670         struct xhci_slot_ctx *slot_ctx;
 671         struct xhci_virt_device *virt_dev;
 672         struct mu3h_sch_bw_info *sch_array;
 673         struct mu3h_sch_bw_info *sch_bw;
 674         struct mu3h_sch_ep_info *sch_ep;
 675         int bw_index;
 676 
 677         xhci = hcd_to_xhci(hcd);
 678         virt_dev = xhci->devs[udev->slot_id];
 679         slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
 680         sch_array = mtk->sch_array;
 681 
 682         xhci_dbg(xhci, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n",
 683                 __func__, usb_endpoint_type(&ep->desc), udev->speed,
 684                 usb_endpoint_maxp(&ep->desc),
 685                 usb_endpoint_dir_in(&ep->desc), ep);
 686 
 687         if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT))
 688                 return;
 689 
 690         bw_index = get_bw_index(xhci, udev, ep);
 691         sch_bw = &sch_array[bw_index];
 692 
 693         list_for_each_entry(sch_ep, &sch_bw->bw_ep_list, endpoint) {
 694                 if (sch_ep->ep == ep) {
 695                         update_bus_bw(sch_bw, sch_ep, 0);
 696                         list_del(&sch_ep->endpoint);
 697                         if (is_fs_or_ls(udev->speed)) {
 698                                 list_del(&sch_ep->tt_endpoint);
 699                                 drop_tt(udev);
 700                         }
 701                         kfree(sch_ep);
 702                         break;
 703                 }
 704         }
 705 }
 706 EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk);

/* [<][>][^][v][top][bottom][index][help] */