Nico Huber (nico.huber(a)secunet.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1906
-gerrit
commit 27a999df2944c153900fb9567e76d17cf299ca13
Author: Nico Huber <nico.huber(a)secunet.com>
Date: Thu Nov 22 17:37:32 2012 +0100
libpayload: Fix memalign() for fragmented alignment regions
Found a bug in the memory allocator ;-)
If the total free space in an alignment region is large enough for an
allocation but fragmented, such that there is no contiguous, sufficient
large, free space in the region, memalign() was looking at the same
region again and again in an endless loop. The advancing to the next
region was just missing.
Change-Id: I3fad833804675ee495577ca2749b007f46b5ff69
Signed-off-by: Nico Huber <nico.huber(a)secunet.com>
---
payloads/libpayload/libc/malloc.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/payloads/libpayload/libc/malloc.c b/payloads/libpayload/libc/malloc.c
index 3c5a3fd..82bae3c 100644
--- a/payloads/libpayload/libc/malloc.c
+++ b/payloads/libpayload/libc/malloc.c
@@ -387,6 +387,9 @@ look_further:
count = 0;
}
}
+ /* The free space in this region is fragmented,
+ so we will move on and try the next one: */
+ reg = reg->next;
goto look_further; // end condition is once a new region is allocated - it always has enough space
}
Nico Huber (nico.huber(a)secunet.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1905
-gerrit
commit 963e22013423215647fe8f99de7316f65fdfdcc7
Author: Nico Huber <nico.huber(a)secunet.com>
Date: Thu Nov 22 17:21:57 2012 +0100
libpayload: Fix interrupt-queue cleanup for OHCI
We have to free TDs more carefully if they have been processed by the
controller yet. The current code tries to force the controller to post
them back to the done queue, but that seems wrong. We can't be sure,
when they get written back. This resulted in leaking TDs with an invalid
reference to a freed interrupt queue.
The new approach: Mark the interrupt queue to be destroyed and handle
the freeing later, when the controller posted the last TD to the done
queue.
Change-Id: I79d80a9dc89e1ca79dc125c4bbccbf23664227b3
Signed-off-by: Nico Huber <nico.huber(a)secunet.com>
---
payloads/libpayload/drivers/usb/ohci.c | 37 +++++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/payloads/libpayload/drivers/usb/ohci.c b/payloads/libpayload/drivers/usb/ohci.c
index ad5638c..7db3141 100644
--- a/payloads/libpayload/drivers/usb/ohci.c
+++ b/payloads/libpayload/drivers/usb/ohci.c
@@ -520,6 +520,7 @@ struct _intr_queue {
int reqsize;
endpoint_t *endp;
unsigned int remaining_tds;
+ int destroy;
};
typedef struct _intrq_td intrq_td_t;
@@ -648,7 +649,7 @@ ohci_destroy_intr_queue(endpoint_t *const ep, void *const q_)
/* Free data buffer. */
free(intrq->data);
- /* Process done queue and free processed TDs. */
+ /* Free TDs already fetched from the done queue. */
ohci_process_done_queue(ohci, 1);
while (intrq->head) {
intrq_td_t *const cur_td = intrq->head;
@@ -656,12 +657,11 @@ ohci_destroy_intr_queue(endpoint_t *const ep, void *const q_)
free(cur_td);
--intrq->remaining_tds;
}
- if (intrq->remaining_tds) {
- printf("error: ohci_destroy_intr_queue(): "
- "freed all but %d TDs.\n", intrq->remaining_tds);
- }
- free(intrq);
+ /* Mark interrupt queue to be destroyed.
+ ohci_process_done_queue() will free the remaining TDs
+ and finish the interrupt queue off once all TDs are gone. */
+ intrq->destroy = 1;
/* Save data toggle. */
ep->toggle = intrq->ed.head_pointer & ED_TOGGLE;
@@ -734,11 +734,28 @@ ohci_process_done_queue(ohci_t *const ohci, const int spew_debug)
/* Free processed async TDs. */
free((void *)done_td);
break;
- case TD_QUEUETYPE_INTR:
- /* Save done TD if it comes from an interrupt queue. */
- INTRQ_TD_FROM_TD(done_td)->next = temp_tdq;
- temp_tdq = INTRQ_TD_FROM_TD(done_td);
+ case TD_QUEUETYPE_INTR: {
+ intrq_td_t *const td = INTRQ_TD_FROM_TD(done_td);
+ intr_queue_t *const intrq = td->intrq;
+ /* Check if the corresponding interrupt
+ queue is still beeing processed. */
+ if (intrq->destroy) {
+ /* Free this TD, and */
+ free(td);
+ --intrq->remaining_tds;
+ /* the interrupt queue if it has no more TDs. */
+ if (!intrq->remaining_tds)
+ free(intrq);
+ usb_debug("Freed TD from orphaned interrupt "
+ "queue, %d TDs remain.\n",
+ intrq->remaining_tds);
+ } else {
+ /* Save done TD to be processed. */
+ td->next = temp_tdq;
+ temp_tdq = td;
+ }
break;
+ }
default:
break;
}
Nico Huber (nico.huber(a)secunet.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1902
-gerrit
commit 7f59b31c4efaadebd2897b302c381b80f7925cab
Author: Nico Huber <nico.huber(a)secunet.com>
Date: Thu Nov 22 11:14:03 2012 +0100
libpayload: ehci: Prevent some race conditions
Prevent race conditions, when an interrupt-queue underrun occurred and
the controller is currently working on our queue head or a transfer is
still in progress.
Change-Id: Ia14f80a08071306ee5d1349780be081bfacb206a
Signed-off-by: Nico Huber <nico.huber(a)secunet.com>
---
payloads/libpayload/drivers/usb/ehci.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/payloads/libpayload/drivers/usb/ehci.c b/payloads/libpayload/drivers/usb/ehci.c
index 4ff137e..6a1cfb5 100644
--- a/payloads/libpayload/drivers/usb/ehci.c
+++ b/payloads/libpayload/drivers/usb/ehci.c
@@ -626,8 +626,14 @@ static u8 *ehci_poll_intr_queue(void *const queue)
intrq->head = intrq->head->next;
}
/* reset queue if we fully processed it after underrun */
- else if (intrq->qh.td.next_qtd & QTD_TERMINATE) {
+ else if ((intrq->qh.td.next_qtd & QTD_TERMINATE) &&
+ /* to prevent race conditions:
+ not our head and not active */
+ (intrq->qh.current_td_ptr !=
+ virt_to_phys(&intrq->head->td)) &&
+ !(intrq->qh.td.token & QTD_ACTIVE)) {
usb_debug("resetting underrun ehci interrupt queue.\n");
+ intrq->qh.current_td_ptr = 0;
memset((void *)&intrq->qh.td, 0, sizeof(intrq->qh.td));
intrq->qh.td.next_qtd = virt_to_phys(&intrq->head->td);
}
Nico Huber (nico.huber(a)secunet.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1903
-gerrit
commit a194d14df2677e48ac3726106a6545ebded463a5
Author: Nico Huber <nico.huber(a)secunet.com>
Date: Thu Nov 22 11:18:19 2012 +0100
libpayload: Detach devices behind removed USB hubs
When a USB hub got removed, we should also remove all devices that
were attached to it.
Change-Id: I73c0da1b7570f1af9726925ca222781b3d752557
Signed-off-by: Nico Huber <nico.huber(a)secunet.com>
---
payloads/libpayload/drivers/usb/usbhub.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/payloads/libpayload/drivers/usb/usbhub.c b/payloads/libpayload/drivers/usb/usbhub.c
index 47215fc..90e08db 100644
--- a/payloads/libpayload/drivers/usb/usbhub.c
+++ b/payloads/libpayload/drivers/usb/usbhub.c
@@ -53,6 +53,17 @@ typedef struct {
static void
usb_hub_destroy (usbdev_t *dev)
{
+ int i;
+
+ /* First, detach all devices behind this hub. */
+ int *const ports = HUB_INST (dev)->ports;
+ for (i = 1; i <= HUB_INST (dev)->num_ports; i++) {
+ if (ports[i] != -1) {
+ usb_detach_device(dev->controller, ports[i]);
+ ports[i] = -1;
+ }
+ }
+
free (HUB_INST (dev)->ports);
free (HUB_INST (dev)->descriptor);
free (HUB_INST (dev));
Nico Huber (nico.huber(a)secunet.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1900
-gerrit
commit 3fb1e361abf89f27f3f86203e6830e9d14ae9bdb
Author: Nico Huber <nico.huber(a)secunet.com>
Date: Wed Nov 21 16:25:55 2012 +0100
libpayload: More compliant error recovery in USB MSC
If an endpoint gets stalled by an MSC device, after successful
transmission of a command (CBW), we should still ask for the status
(CSW). Otherwise, the driver and the device get desynchronized on the
command tags.
Change-Id: I53167f22c43b3a237cb4539b3affe37799378b93
Signed-off-by: Nico Huber <nico.huber(a)secunet.com>
---
payloads/libpayload/drivers/usb/usbmsc.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/payloads/libpayload/drivers/usb/usbmsc.c b/payloads/libpayload/drivers/usb/usbmsc.c
index 5cfb3c6..7e8b360 100644
--- a/payloads/libpayload/drivers/usb/usbmsc.c
+++ b/payloads/libpayload/drivers/usb/usbmsc.c
@@ -227,16 +227,12 @@ execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen,
if (buflen > 0) {
if (dir == cbw_direction_data_in) {
if (dev->controller->
- bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0)) {
+ bulk (MSC_INST (dev)->bulk_in, buflen, buf, 0))
clear_stall (MSC_INST (dev)->bulk_in);
- return MSC_COMMAND_FAIL;
- }
} else {
if (dev->controller->
- bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0)) {
+ bulk (MSC_INST (dev)->bulk_out, buflen, buf, 0))
clear_stall (MSC_INST (dev)->bulk_out);
- return MSC_COMMAND_FAIL;
- }
}
}
int ret = get_csw (MSC_INST (dev)->bulk_in, &csw);
Nico Huber (nico.huber(a)secunet.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1899
-gerrit
commit 983586c8c5496b76a250e7af2ee64026afff6e60
Author: Nico Huber <nico.huber(a)secunet.com>
Date: Wed Nov 21 16:22:26 2012 +0100
libpayload: Reduce error output from EHCI
Stalled transfers are not fatal, so don't spew on the console on every
tiny failure.
Change-Id: I175c1e83a6af09c1abbd43d045ed6dbf0c79f871
Signed-off-by: Nico Huber <nico.huber(a)secunet.com>
---
payloads/libpayload/drivers/usb/ehci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payloads/libpayload/drivers/usb/ehci.c b/payloads/libpayload/drivers/usb/ehci.c
index 5f70b64..4ff137e 100644
--- a/payloads/libpayload/drivers/usb/ehci.c
+++ b/payloads/libpayload/drivers/usb/ehci.c
@@ -211,7 +211,7 @@ static int wait_for_tds(qtd_t *head)
return 1;
}
if (cur->token & QTD_HALTED) {
- printf("ERROR with packet\n");
+ usb_debug("ERROR with packet\n");
dump_td(virt_to_phys(cur));
usb_debug("-----------------\n");
return 1;
Nico Huber (nico.huber(a)secunet.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1898
-gerrit
commit 3c35827c65b42886da678eb7db219b0f153b51f9
Author: Nico Huber <nico.huber(a)secunet.com>
Date: Tue Nov 20 17:49:00 2012 +0100
libpayload: Handle underruns in UHCI interrupt queues
If usb_poll() isn't called fast enough, the UHCI controller marks an
underrun interrupt queue as done (terminating the queue at the head).
We can recover from this situation, when usb_poll() gets called again,
and the queue is processed.
Change-Id: Id56c9df44d6dbd53cd30ad89dfb5bf5977799829
Signed-off-by: Nico Huber <nico.huber(a)secunet.com>
---
payloads/libpayload/drivers/usb/uhci.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/payloads/libpayload/drivers/usb/uhci.c b/payloads/libpayload/drivers/usb/uhci.c
index bfa53f6..386392b 100644
--- a/payloads/libpayload/drivers/usb/uhci.c
+++ b/payloads/libpayload/drivers/usb/uhci.c
@@ -590,6 +590,11 @@ uhci_poll_intr_queue (void *q_)
q->lastread = (q->lastread + 1) % q->total;
return &q->data[current*q->reqsize];
}
+ /* reset queue if we fully processed it after underrun */
+ else if (q->qh->elementlinkptr & FLISTP_TERMINATE) {
+ usb_debug("resetting underrun uhci interrupt queue.\n");
+ q->qh->elementlinkptr = virt_to_phys(q->tds + q->lastread);
+ }
return NULL;
}