aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikunj A Dadhania <nikunj@linux.vnet.ibm.com>2013-07-24 14:27:33 +0530
committerNikunj A Dadhania <nikunj@linux.vnet.ibm.com>2013-07-24 14:46:23 +0530
commitd7354e2724391e2424f632fb1636f2ec1148a717 (patch)
tree9d5fa24ccda8f0b51161b8ffedc640654ed1b75f
parentac2fc97106aab80f842144968884e1dbe09c47eb (diff)
downloadSLOF-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.h3
-rw-r--r--lib/libusb/usb-core.c16
-rw-r--r--lib/libusb/usb-core.h1
-rw-r--r--lib/libusb/usb-ehci.c51
-rw-r--r--lib/libusb/usb-ehci.h14
-rw-r--r--lib/libusb/usb-ohci.c33
-rw-r--r--lib/libusb/usb-ohci.h2
-rw-r--r--lib/libusb/usb.code10
-rw-r--r--lib/libusb/usb.h4
-rw-r--r--lib/libusb/usb.in1
-rw-r--r--slof/fs/usb/dev-hci.fs53
-rw-r--r--slof/helpers.c23
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);