Browse Source

remove qtd alloc & free, use static pool instead

sakumisu 1 year ago
parent
commit
74bb03b8b4
2 changed files with 52 additions and 117 deletions
  1. 9 19
      port/ehci/usb_ehci_priv.h
  2. 43 98
      port/ehci/usb_hc_ehci.c

+ 9 - 19
port/ehci/usb_ehci_priv.h

@@ -13,34 +13,25 @@
 #define EHCI_ADDR2QTD(x) ((struct ehci_qtd_hw *)((uint32_t)(x) & ~0x1F))
 #define EHCI_ADDR2ITD(x) ((struct ehci_itd_hw *)((uint32_t)(x) & ~0x1F))
 
-#if CONFIG_USB_EHCI_FRAME_LIST_SIZE == 1024
-#define EHCI_PERIOIDIC_QH_NUM 11
-#elif CONFIG_USB_EHCI_FRAME_LIST_SIZE == 512
-#define EHCI_PERIOIDIC_QH_NUM 10
-#elif CONFIG_USB_EHCI_FRAME_LIST_SIZE == 256
-#define EHCI_PERIOIDIC_QH_NUM 9
-#else
-#error Unsupported frame size list size
-#endif
-
 #define CONFIG_USB_EHCI_QH_NUM  CONFIG_USBHOST_PIPE_NUM
-#define CONFIG_USB_EHCI_QTD_NUM (CONFIG_USBHOST_PIPE_NUM + 3)
+#define CONFIG_USB_EHCI_QTD_NUM 3
 #define CONFIG_USB_EHCI_ITD_NUM 20
 
 extern uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port);
 
+struct ehci_qtd_hw {
+    struct ehci_qtd hw;
+    struct usbh_urb *urb;
+    uint32_t length;
+} __attribute__((aligned(32)));
+
 struct ehci_qh_hw {
     struct ehci_qh hw;
+    struct ehci_qtd_hw qtd_pool[CONFIG_USB_EHCI_QTD_NUM];
     uint32_t first_qtd;
     struct usbh_urb *urb;
-    uint8_t remove_in_iaad;
     usb_osal_sem_t waitsem;
-} __attribute__((aligned(32)));
-
-struct ehci_qtd_hw {
-    struct ehci_qtd hw;
-    struct usbh_urb *urb;
-    uint32_t total_len;
+    uint8_t remove_in_iaad;
 } __attribute__((aligned(32)));
 
 struct ehci_itd_hw {
@@ -55,7 +46,6 @@ struct ehci_itd_hw {
 
 struct ehci_hcd {
     bool ehci_qh_used[CONFIG_USB_EHCI_QH_NUM];
-    bool ehci_qtd_used[CONFIG_USB_EHCI_QTD_NUM];
     bool ehci_itd_used[CONFIG_USB_EHCI_ITD_NUM];
 };
 

+ 43 - 98
port/ehci/usb_hc_ehci.c

@@ -14,7 +14,6 @@
 struct ehci_hcd g_ehci_hcd[CONFIG_USBHOST_MAX_BUS];
 
 USB_NOCACHE_RAM_SECTION struct ehci_qh_hw ehci_qh_pool[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_EHCI_QH_NUM];
-USB_NOCACHE_RAM_SECTION struct ehci_qtd_hw ehci_qtd_pool[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_EHCI_QTD_NUM];
 
 /* The head of the asynchronous queue */
 USB_NOCACHE_RAM_SECTION struct ehci_qh_hw g_async_qh_head[CONFIG_USBHOST_MAX_BUS];
@@ -27,7 +26,7 @@ USB_NOCACHE_RAM_SECTION uint32_t g_framelist[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_U
 static struct ehci_qh_hw *ehci_qh_alloc(struct usbh_bus *bus)
 {
     struct ehci_qh_hw *qh;
-    usb_osal_sem_t waitsem;
+    struct ehci_qtd_hw *qtd;
     size_t flags;
 
     for (uint32_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) {
@@ -37,12 +36,20 @@ static struct ehci_qh_hw *ehci_qh_alloc(struct usbh_bus *bus)
             usb_osal_leave_critical_section(flags);
 
             qh = &ehci_qh_pool[bus->hcd.hcd_id][i];
-            waitsem = qh->waitsem;
-            memset(qh, 0, sizeof(struct ehci_qh_hw));
+            memset(&qh->hw, 0, sizeof(struct ehci_qh));
             qh->hw.hlp = QTD_LIST_END;
             qh->hw.overlay.next_qtd = QTD_LIST_END;
             qh->hw.overlay.alt_next_qtd = QTD_LIST_END;
-            qh->waitsem = waitsem;
+            qh->urb = NULL;
+
+            for (uint32_t j = 0; j < CONFIG_USB_EHCI_QTD_NUM; j++) {
+                qtd = &qh->qtd_pool[j];
+                qtd->hw.next_qtd = QTD_LIST_END;
+                qtd->hw.alt_next_qtd = QTD_LIST_END;
+                qtd->hw.token = QTD_TOKEN_STATUS_HALTED;
+                qtd->urb = NULL;
+            }
+
             return qh;
         }
     }
@@ -65,44 +72,6 @@ static void ehci_qh_free(struct usbh_bus *bus, struct ehci_qh_hw *qh)
     }
 }
 
-static struct ehci_qtd_hw *ehci_qtd_alloc(struct usbh_bus *bus)
-{
-    struct ehci_qtd_hw *qtd;
-    size_t flags;
-
-    for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
-        if (!g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i]) {
-            flags = usb_osal_enter_critical_section();
-            g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i] = true;
-            usb_osal_leave_critical_section(flags);
-
-            qtd = &ehci_qtd_pool[bus->hcd.hcd_id][i];
-            memset(qtd, 0, sizeof(struct ehci_qtd_hw));
-            qtd->hw.next_qtd = QTD_LIST_END;
-            qtd->hw.alt_next_qtd = QTD_LIST_END;
-            qtd->hw.token = QTD_TOKEN_STATUS_HALTED;
-            return qtd;
-        }
-    }
-    return NULL;
-}
-
-static void ehci_qtd_free(struct usbh_bus *bus, struct ehci_qtd_hw *qtd)
-{
-    size_t flags;
-
-    for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
-        if (&ehci_qtd_pool[bus->hcd.hcd_id][i] == qtd) {
-            flags = usb_osal_enter_critical_section();
-            g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i] = false;
-            usb_osal_leave_critical_section(flags);
-
-            qtd->urb = NULL;
-            return;
-        }
-    }
-}
-
 static inline void ehci_qh_add_head(struct ehci_qh_hw *head, struct ehci_qh_hw *n)
 {
     n->hw.hlp = head->hw.hlp;
@@ -281,7 +250,7 @@ static void ehci_qtd_fill(struct ehci_qtd_hw *qtd, uint32_t bufaddr, size_t bufl
     qtd->hw.token = token;
 
     ehci_qtd_bpl_fill(qtd, bufaddr, buflen);
-    qtd->total_len = buflen;
+    qtd->length = buflen;
 }
 
 static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_bus *bus, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
@@ -298,22 +267,9 @@ static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_bus *bus, struct usb
         return NULL;
     }
 
-    qtd_setup = ehci_qtd_alloc(bus);
-    if (buflen > 0) {
-        qtd_data = ehci_qtd_alloc(bus);
-    }
-
-    qtd_status = ehci_qtd_alloc(bus);
-    if (qtd_status == NULL) {
-        ehci_qh_free(bus, qh);
-        if (qtd_setup) {
-            ehci_qtd_free(bus, qtd_setup);
-        }
-        if (qtd_data) {
-            ehci_qtd_free(bus, qtd_data);
-        }
-        return NULL;
-    }
+    qtd_setup = &qh->qtd_pool[0];
+    qtd_data = &qh->qtd_pool[1];
+    qtd_status = &qh->qtd_pool[2];
 
     ehci_qh_fill(qh,
                  urb->hport->dev_addr,
@@ -408,17 +364,6 @@ static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_bus *bus, struct usbh_u
         return NULL;
     }
 
-    for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
-        if (!g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i]) {
-            qtd_num++;
-        }
-    }
-
-    if (qtd_num < ((buflen + 0x3fff) / 0x4000)) {
-        ehci_qh_free(bus, qh);
-        return NULL;
-    }
-
     ehci_qh_fill(qh,
                  urb->hport->dev_addr,
                  urb->ep->bEndpointAddress,
@@ -431,7 +376,7 @@ static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_bus *bus, struct usbh_u
                  urb->hport->port);
 
     while (buflen >= 0) {
-        qtd = ehci_qtd_alloc(bus);
+        qtd = &qh->qtd_pool[qtd_num];
 
         if (buflen > 0x4000) {
             xfer_len = 0x4000;
@@ -470,6 +415,11 @@ static struct ehci_qh_hw *ehci_bulk_urb_init(struct usbh_bus *bus, struct usbh_u
         if (buflen == 0) {
             break;
         }
+        qtd_num++;
+
+        if (qtd_num == CONFIG_USB_EHCI_QTD_NUM) {
+            return NULL;
+        }
     }
 
     /* update qh first qtd */
@@ -515,17 +465,6 @@ static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_bus *bus, struct usbh_u
         return NULL;
     }
 
-    for (uint32_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
-        if (!g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[i]) {
-            qtd_num++;
-        }
-    }
-
-    if (qtd_num < ((buflen + 0x3fff) / 0x4000)) {
-        ehci_qh_free(bus, qh);
-        return NULL;
-    }
-
     ehci_qh_fill(qh,
                  urb->hport->dev_addr,
                  urb->ep->bEndpointAddress,
@@ -538,7 +477,7 @@ static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_bus *bus, struct usbh_u
                  urb->hport->port);
 
     while (buflen >= 0) {
-        qtd = ehci_qtd_alloc(bus);
+        qtd = &qh->qtd_pool[qtd_num];
 
         if (buflen > 0x4000) {
             xfer_len = 0x4000;
@@ -577,6 +516,11 @@ static struct ehci_qh_hw *ehci_intr_urb_init(struct usbh_bus *bus, struct usbh_u
         if (buflen == 0) {
             break;
         }
+        qtd_num++;
+
+        if (qtd_num == CONFIG_USB_EHCI_QTD_NUM) {
+            return NULL;
+        }
     }
 
     /* update qh first qtd */
@@ -641,9 +585,8 @@ static void ehci_qh_scan_qtds(struct usbh_bus *bus, struct ehci_qh_hw *qhead, st
     qtd = EHCI_ADDR2QTD(qh->first_qtd);
 
     while (qtd) {
-        qtd->urb->actual_length += (qtd->total_len - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT));
+        qtd->urb->actual_length += (qtd->length - ((qtd->hw.token & QTD_TOKEN_NBYTES_MASK) >> QTD_TOKEN_NBYTES_SHIFT));
 
-        ehci_qtd_free(bus, qtd);
         qh->first_qtd = qtd->hw.next_qtd;
         qtd = EHCI_ADDR2QTD(qh->first_qtd);
     }
@@ -676,7 +619,7 @@ static void ehci_check_qh(struct usbh_bus *bus, struct ehci_qh_hw *qhead, struct
     urb = qh->urb;
 
     if ((token & QTD_TOKEN_STATUS_ERRORS) == 0) {
-        if (qh->hw.overlay.token & QTD_TOKEN_TOGGLE) {
+        if (token & QTD_TOKEN_TOGGLE) {
             urb->data_toggle = true;
         } else {
             urb->data_toggle = false;
@@ -714,7 +657,6 @@ static void ehci_kill_qh(struct usbh_bus *bus, struct ehci_qh_hw *qhead, struct
     qtd = EHCI_ADDR2QTD(qh->first_qtd);
 
     while (qtd) {
-        ehci_qtd_free(bus, qtd);
         qh->first_qtd = qtd->hw.next_qtd;
         qtd = EHCI_ADDR2QTD(qh->first_qtd);
     }
@@ -770,14 +712,20 @@ int usb_hc_init(struct usbh_bus *bus)
     uint32_t regval;
 
     memset(&g_ehci_hcd[bus->hcd.hcd_id], 0, sizeof(struct ehci_hcd));
+    memset(ehci_qh_pool, 0, sizeof(struct ehci_qh_hw) * CONFIG_USB_EHCI_QH_NUM);
 
-    if (sizeof(struct ehci_qh_hw) % 32) {
-        USB_LOG_ERR("struct ehci_qh_hw is not align 32\r\n");
-        return -USB_ERR_INVAL;
-    }
-    if (sizeof(struct ehci_qtd_hw) % 32) {
-        USB_LOG_ERR("struct ehci_qtd_hw is not align 32\r\n");
-        return -USB_ERR_INVAL;
+    for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
+        qh = &ehci_qh_pool[bus->hcd.hcd_id][index];
+        if ((uint32_t)&qh->hw % 32) {
+            USB_LOG_ERR("struct ehci_qh_hw is not align 32\r\n");
+            return -USB_ERR_INVAL;
+        }
+        for (uint8_t i = 0; i < CONFIG_USB_EHCI_QTD_NUM; i++) {
+            if ((uint32_t)&qh->qtd_pool[i] % 32) {
+                USB_LOG_ERR("struct ehci_qtd_hw is not align 32\r\n");
+                return -USB_ERR_INVAL;
+            }
+        }
     }
 
     for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
@@ -1306,9 +1254,6 @@ void USBH_IRQHandler(uint8_t busid)
                     for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) {
                         g_ehci_hcd[bus->hcd.hcd_id].ehci_qh_used[index] = false;
                     }
-                    for (uint8_t index = 0; index < CONFIG_USB_EHCI_QTD_NUM; index++) {
-                        g_ehci_hcd[bus->hcd.hcd_id].ehci_qtd_used[index] = false;
-                    }
                     for (uint8_t index = 0; index < CONFIG_USB_EHCI_ITD_NUM; index++) {
                         g_ehci_hcd[bus->hcd.hcd_id].ehci_itd_used[index] = false;
                     }