diff options
author | Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> | 2013-07-24 14:27:33 +0530 |
---|---|---|
committer | Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> | 2013-07-24 14:46:23 +0530 |
commit | d7354e2724391e2424f632fb1636f2ec1148a717 (patch) | |
tree | 9d5fa24ccda8f0b51161b8ffedc640654ed1b75f | |
parent | ac2fc97106aab80f842144968884e1dbe09c47eb (diff) | |
download | SLOF-d7354e2724391e2424f632fb1636f2ec1148a717.zip SLOF-d7354e2724391e2424f632fb1636f2ec1148a717.tar.gz SLOF-d7354e2724391e2424f632fb1636f2ec1148a717.tar.bz2 |
usb: unmap buffers
Clean up all the dma allocated buffers and remove their mappings.
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Acked-by: Thomas Huth <thuth@linux.vnet.ibm.com>
-rw-r--r-- | include/helpers.h | 3 | ||||
-rw-r--r-- | lib/libusb/usb-core.c | 16 | ||||
-rw-r--r-- | lib/libusb/usb-core.h | 1 | ||||
-rw-r--r-- | lib/libusb/usb-ehci.c | 51 | ||||
-rw-r--r-- | lib/libusb/usb-ehci.h | 14 | ||||
-rw-r--r-- | lib/libusb/usb-ohci.c | 33 | ||||
-rw-r--r-- | lib/libusb/usb-ohci.h | 2 | ||||
-rw-r--r-- | lib/libusb/usb.code | 10 | ||||
-rw-r--r-- | lib/libusb/usb.h | 4 | ||||
-rw-r--r-- | lib/libusb/usb.in | 1 | ||||
-rw-r--r-- | slof/fs/usb/dev-hci.fs | 53 | ||||
-rw-r--r-- | slof/helpers.c | 23 |
12 files changed, 169 insertions, 42 deletions
diff --git a/include/helpers.h b/include/helpers.h index 60dbda2..e41d6a0 100644 --- a/include/helpers.h +++ b/include/helpers.h @@ -22,6 +22,9 @@ extern uint32_t SLOF_GetTimer(void); extern void SLOF_msleep(uint32_t time); extern void *SLOF_dma_alloc(long size); extern void SLOF_dma_free(void *virt, long size); +extern void *SLOF_alloc_mem(long size); +extern void *SLOF_alloc_mem_aligned(long align, long size); +extern void SLOF_free_mem(void *addr, long size); extern long SLOF_dma_map_in(void *virt, long size, int cacheable); extern void SLOF_dma_map_out(long phys, void *virt, long size); diff --git a/lib/libusb/usb-core.c b/lib/libusb/usb-core.c index f71b54c..49ebc57 100644 --- a/lib/libusb/usb-core.c +++ b/lib/libusb/usb-core.c @@ -30,7 +30,7 @@ static struct usb_dev *usb_alloc_devpool(void) struct usb_dev *head, *curr, *prev; unsigned int dev_count = 0, i; - head = SLOF_dma_alloc(USB_DEVPOOL_SIZE); + head = SLOF_alloc_mem(USB_DEVPOOL_SIZE); if (!head) return NULL; @@ -175,6 +175,20 @@ void usb_hcd_init(void *hcidev) dprintf("usb_ops for the controller not found\n"); } +void usb_hcd_exit(void *_hcidev) +{ + struct usb_hcd_dev *hcidev = _hcidev; + + dprintf("%s: enter \n", __func__); + if (!hcidev) { + printf("Device Error"); + return; + } + + if (hcidev->ops->exit) + hcidev->ops->exit(hcidev); +} + int usb_send_ctrl(struct usb_pipe *pipe, struct usb_dev_req *req, void *data) { struct usb_dev *dev = NULL; diff --git a/lib/libusb/usb-core.h b/lib/libusb/usb-core.h index 27e2f9b..5914a64 100644 --- a/lib/libusb/usb-core.h +++ b/lib/libusb/usb-core.h @@ -243,6 +243,7 @@ struct usb_dev_hid_descr { struct usb_hcd_ops { const char *name; void (*init)(struct usb_hcd_dev *); + void (*exit)(struct usb_hcd_dev *); void (*detect)(void); void (*disconnect)(void); int (*send_ctrl)(struct usb_pipe *pipe, struct usb_dev_req *req, void *data); diff --git a/lib/libusb/usb-ehci.c b/lib/libusb/usb-ehci.c index 4552b2d..c7fbbf2 100644 --- a/lib/libusb/usb-ehci.c +++ b/lib/libusb/usb-ehci.c @@ -152,6 +152,10 @@ static int ehci_hcd_init(struct ehci_hcd *ehcd) write_reg32(&ehcd->op_regs->asynclistaddr, qh_async_phys); ehcd->qh_async = qh_async; ehcd->qh_async_phys = qh_async_phys; + ehcd->qh_intr = qh_intr; + ehcd->qh_intr_phys = qh_intr_phys; + ehcd->fl = fl; + ehcd->fl_phys = fl_phys; write_reg32(&ehcd->op_regs->usbcmd, usbcmd | CMD_ASE | CMD_RUN); write_reg32(&ehcd->op_regs->configflag, 1); @@ -168,6 +172,25 @@ fail: return -1; } +static int ehci_hcd_exit(struct ehci_hcd *ehcd) +{ + uint32_t usbcmd; + + usbcmd = read_reg32(&ehcd->op_regs->usbcmd); + write_reg32(&ehcd->op_regs->usbcmd, usbcmd | ~CMD_RUN); + write_reg32(&ehcd->op_regs->periodiclistbase, 0); + + SLOF_dma_map_out(ehcd->pool_phys, ehcd->pool, EHCI_PIPE_POOL_SIZE); + SLOF_dma_free(ehcd->pool, EHCI_PIPE_POOL_SIZE); + SLOF_dma_map_out(ehcd->qh_intr_phys, ehcd->qh_intr, sizeof(struct ehci_qh)); + SLOF_dma_free(ehcd->qh_intr, sizeof(struct ehci_qh)); + SLOF_dma_map_out(ehcd->qh_async_phys, ehcd->qh_async, sizeof(struct ehci_qh)); + SLOF_dma_free(ehcd->qh_async, sizeof(struct ehci_qh)); + SLOF_dma_map_out(ehcd->fl_phys, ehcd->fl, sizeof(struct ehci_framelist)); + SLOF_dma_free(ehcd->fl, sizeof(struct ehci_framelist)); + return true; +} + static int ehci_alloc_pipe_pool(struct ehci_hcd *ehcd) { struct ehci_pipe *epipe, *curr, *prev; @@ -175,10 +198,10 @@ static int ehci_alloc_pipe_pool(struct ehci_hcd *ehcd) long epipe_phys = 0; count = EHCI_PIPE_POOL_SIZE/sizeof(*epipe); - epipe = SLOF_dma_alloc(EHCI_PIPE_POOL_SIZE); + ehcd->pool = epipe = SLOF_dma_alloc(EHCI_PIPE_POOL_SIZE); if (!epipe) return -1; - epipe_phys = SLOF_dma_map_in(epipe, EHCI_PIPE_POOL_SIZE, true); + ehcd->pool_phys = epipe_phys = SLOF_dma_map_in(epipe, EHCI_PIPE_POOL_SIZE, true); dprintf("%s: epipe %p, epipe_phys %lx\n", __func__, epipe, epipe_phys); /* Although an array, link them */ @@ -209,7 +232,7 @@ static void ehci_init(struct usb_hcd_dev *hcidev) printf(" EHCI: Initializing\n"); dprintf("%s: device base address %p\n", __func__, hcidev->base); - ehcd = SLOF_dma_alloc(sizeof(*ehcd)); + ehcd = SLOF_alloc_mem(sizeof(*ehcd)); if (!ehcd) { printf("usb-ehci: Unable to allocate memory\n"); return; @@ -229,6 +252,27 @@ static void ehci_init(struct usb_hcd_dev *hcidev) ehci_hub_check_ports(ehcd); } +static void ehci_exit(struct usb_hcd_dev *hcidev) +{ + struct ehci_hcd *ehcd; + static int count = 0; + + dprintf("%s: enter \n", __func__); + + if (!hcidev && !hcidev->priv) { + return; + } + count++; + if (count > 1) { + printf("%s: already called once \n", __func__); + return; + } + ehcd = hcidev->priv; + ehci_hcd_exit(ehcd); + SLOF_free_mem(ehcd, sizeof(*ehcd)); + hcidev->priv = NULL; +} + static void ehci_detect(void) { @@ -501,6 +545,7 @@ static void ehci_put_pipe(struct usb_pipe *pipe) struct usb_hcd_ops ehci_ops = { .name = "ehci-hcd", .init = ehci_init, + .exit = ehci_exit, .detect = ehci_detect, .disconnect = ehci_disconnect, .get_pipe = ehci_get_pipe, diff --git a/lib/libusb/usb-ehci.h b/lib/libusb/usb-ehci.h index f115c17..9b4fa82 100644 --- a/lib/libusb/usb-ehci.h +++ b/lib/libusb/usb-ehci.h @@ -44,20 +44,26 @@ struct ehci_op_regs { uint32_t portsc[0]; } __attribute__ ((packed)); +struct ehci_framelist { + uint32_t fl_ptr[FL_SIZE]; +} __attribute__ ((packed)); + struct ehci_hcd { struct ehci_cap_regs *cap_regs; struct ehci_op_regs *op_regs; struct usb_hcd_dev *hcidev; struct ehci_qh *qh_async; + struct ehci_qh *qh_intr; struct usb_pipe *freelist; struct usb_pipe *end; + struct ehci_framelist *fl; long qh_async_phys; + long qh_intr_phys; + long fl_phys; + void *pool; + long pool_phys; }; -struct ehci_framelist { - uint32_t fl_ptr[FL_SIZE]; -} __attribute__ ((packed)); - struct ehci_qtd { uint32_t next_qtd; uint32_t alt_next_qtd; diff --git a/lib/libusb/usb-ohci.c b/lib/libusb/usb-ohci.c index 53cd555..3cfd15f 100644 --- a/lib/libusb/usb-ohci.c +++ b/lib/libusb/usb-ohci.c @@ -217,11 +217,11 @@ static int ohci_alloc_pipe_pool(struct ohci_hcd *ohcd) dprintf("usb-ohci: %s enter\n", __func__); count = OHCI_PIPE_POOL_SIZE/sizeof(*opipe); - opipe = SLOF_dma_alloc(OHCI_PIPE_POOL_SIZE); + ohcd->pool = opipe = SLOF_dma_alloc(OHCI_PIPE_POOL_SIZE); if (!opipe) return false; - opipe_phys = SLOF_dma_map_in(opipe, OHCI_PIPE_POOL_SIZE, true); + ohcd->pool_phys = opipe_phys = SLOF_dma_map_in(opipe, OHCI_PIPE_POOL_SIZE, true); dprintf("usb-ohci: %s opipe %x, opipe_phys %x size %d count %d\n", __func__, opipe, opipe_phys, sizeof(*opipe), count); /* Although an array, link them*/ @@ -261,7 +261,7 @@ static void ohci_init(struct usb_hcd_dev *hcidev) printf(" OHCI: initializing\n"); dprintf("%s: device base address %p\n", __func__, hcidev->base); - ohcd = SLOF_dma_alloc(sizeof(struct ohci_hcd)); + ohcd = SLOF_alloc_mem(sizeof(struct ohci_hcd)); if (!ohcd) { printf("usb-ohci: Unable to allocate memory\n"); goto out; @@ -293,11 +293,35 @@ static void ohci_init(struct usb_hcd_dev *hcidev) out_free_hcd: SLOF_dma_free(ohcd->hcca, sizeof(struct ohci_hcca)); - SLOF_dma_free(ohcd, sizeof(struct ohci_hcd)); + SLOF_free_mem(ohcd, sizeof(struct ohci_hcd)); out: return; } +static void ohci_exit(struct usb_hcd_dev *hcidev) +{ + struct ohci_hcd *ohcd = NULL; + static int count = 0; + + dprintf("%s: enter \n", __func__); + if (!hcidev && !hcidev->priv) + return; + + count++; + if (count > 1) { + printf("%s: already called once \n", __func__); + return; + } + ohcd = hcidev->priv; + write_reg(&ohcd->regs->hcca, 0); + SLOF_dma_map_out(ohcd->pool_phys, ohcd->pool, OHCI_PIPE_POOL_SIZE); + SLOF_dma_free(ohcd->pool, OHCI_PIPE_POOL_SIZE); + SLOF_dma_map_out(ohcd->hcca_phys, ohcd->hcca, sizeof(struct ohci_hcca)); + SLOF_dma_free(ohcd->hcca, sizeof(struct ohci_hcca)); + SLOF_free_mem(ohcd, sizeof(struct ohci_hcd)); + return; +} + static void ohci_detect(void) { @@ -818,6 +842,7 @@ static int ohci_poll_intr(struct usb_pipe *pipe, uint8_t *data) struct usb_hcd_ops ohci_ops = { .name = "ohci-hcd", .init = ohci_init, + .exit = ohci_exit, .detect = ohci_detect, .disconnect = ohci_disconnect, .get_pipe = ohci_get_pipe, diff --git a/lib/libusb/usb-ohci.h b/lib/libusb/usb-ohci.h index 9347fb6..3fd1b8a 100644 --- a/lib/libusb/usb-ohci.h +++ b/lib/libusb/usb-ohci.h @@ -120,6 +120,8 @@ struct ohci_hcd { struct usb_pipe *end; struct usb_dev rhdev; long hcca_phys; + void *pool; + long pool_phys; }; #define OHCI_CTRL_CBSR (3 << 0) diff --git a/lib/libusb/usb.code b/lib/libusb/usb.code index 59e2236..81e548d 100644 --- a/lib/libusb/usb.code +++ b/lib/libusb/usb.code @@ -45,6 +45,16 @@ PRIM(USB_X2d_HCD_X2d_INIT) MIRP /************************************************/ +/* Remove hcidev with the usb-core */ +/* SLOF: USB-HCD-EXIT ( hcidev -- ) */ +/* LIBNEWUSB: usb_hcd_exit(hcidev) */ +/************************************************/ +PRIM(USB_X2d_HCD_X2d_EXIT) + void *hcidev = TOS.a; POP; + usb_hcd_exit(hcidev); +MIRP + +/************************************************/ /* Initialize hid */ /* SLOF: USB-HID-INIT ( dev -- true | false )*/ /* LIBNEWUSB: usb_hid_init(hcidev) */ diff --git a/lib/libusb/usb.h b/lib/libusb/usb.h index dc6fa03..2be0a7d 100644 --- a/lib/libusb/usb.h +++ b/lib/libusb/usb.h @@ -29,6 +29,10 @@ extern void usb_ehci_register(void); /*******************************************/ extern void usb_hcd_init(void *hcidev); /*******************************************/ +/* SLOF: USB-HCD-EXIT */ +/*******************************************/ +extern void usb_hcd_exit(void *hcidev); +/*******************************************/ /* SLOF: USB-HID-INIT */ /*******************************************/ extern int usb_hid_init(void *dev); diff --git a/lib/libusb/usb.in b/lib/libusb/usb.in index f0e027c..dc7b7a9 100644 --- a/lib/libusb/usb.in +++ b/lib/libusb/usb.in @@ -16,6 +16,7 @@ cod(USB-OHCI-REGISTER) cod(USB-EHCI-REGISTER) cod(USB-HCD-INIT) +cod(USB-HCD-EXIT) cod(USB-HID-INIT) cod(USB-HID-EXIT) cod(USB-READ-KEYB) diff --git a/slof/fs/usb/dev-hci.fs b/slof/fs/usb/dev-hci.fs index 97ad9e4..44bdc09 100644 --- a/slof/fs/usb/dev-hci.fs +++ b/slof/fs/usb/dev-hci.fs @@ -31,6 +31,8 @@ ELSE 3drop THEN /hci-dev BUFFER: hcidev usb_num hcidev usb-setup-hcidev +TRUE VALUE first-time-init? +0 VALUE open-count false VALUE dev-hci-debug? @@ -53,34 +55,6 @@ get-base-address CONSTANT baseaddrs hcidev ; - -0 VALUE open-count - -: USB-HCI-INIT drop 1 ; -: USB-HCI-EXIT drop 1 ; - -: open ( -- true | false ) - dev-hci-debug? IF ." DEV-HCI: Opening (count is " open-count . ." )" cr THEN - open-count 0= IF - hcidev USB-HCI-INIT 0= IF - ." HCI Device setup failed " pwd cr - false EXIT - THEN - THEN - open-count 1 + to open-count - true -; - -: close - dev-hci-debug? IF ." DEV-HCI: Closing (count is " open-count . ." )" cr THEN - open-count 0> IF - open-count 1 - dup to open-count - 0= IF - hcidev USB-HCI-EXIT drop - THEN - THEN -; - \ set HCI into suspend mode \ this disables all activities to shared RAM \ called when linux starts (quiesce) @@ -96,5 +70,24 @@ get-base-address CONSTANT baseaddrs THEN ; -\ create a new entry to suspend HCI -' hc-suspend add-quiesce-xt +: hc-cleanup ( -- ) + my-phandle set-node + dev-hci-debug? IF ." USB-HCI: Cleaning up " pwd cr THEN + hcidev USB-HCD-EXIT + hc-suspend + 0 set-node +; + +: open ( -- true | false ) + true +; + +: close +; + +\ create a new entry to cleanup and suspend HCI +\ after first init +first-time-init? IF + ['] hc-cleanup add-quiesce-xt + false to first-time-init? +THEN diff --git a/slof/helpers.c b/slof/helpers.c index f6e7f19..7b497f1 100644 --- a/slof/helpers.c +++ b/slof/helpers.c @@ -53,6 +53,29 @@ void SLOF_dma_free(void *virt, long size) forth_eval("dma-free"); } +void *SLOF_alloc_mem(long size) +{ + forth_push(size); + forth_eval("alloc-mem"); + return (void *)forth_pop(); +} + +void *SLOF_alloc_mem_aligned(long align, long size) +{ + unsigned long addr = (unsigned long)SLOF_alloc_mem(size + align - 1); + addr = addr + align - 1; + addr = addr & ~(align - 1); + + return (void *)addr; +} + +void SLOF_free_mem(void *addr, long size) +{ + forth_push((long)addr); + forth_push(size); + forth_eval("free-mem"); +} + long SLOF_dma_map_in(void *virt, long size, int cacheable) { forth_push((long)virt); |