libpayload: usb: xhci: Count new Max Scratchpad Bufs bits from XHCI 1.1

The 1.1 revision of the XHCI specification added an extra 5 bits to the
Max Scratchpad Bufs field of HCSPARAMS2 that newer controllers make use
of. Not honoring these bits means we're not allocating as many
scratchpad buffers as the controller expects, which means it will
interpret some uninitialized values from the end of the pointer array as
scratchpad buffer pointers, which obviously doesn't end well. Let's fix
that.

BRANCH=none
BUG=chrome-os-partner:42279
TEST=Makes a USB-related memory corruption issue disappear.

Original-Change-Id: I7c907492339262bda31cdd2b5c0b588de7df8544
Original-Signed-off-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/291681
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>

Change-Id: Iba1007bfebffe1f564f78bb875fff9ba0fe11a38
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: http://review.coreboot.org/11189
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Julius Werner 2015-08-07 13:14:20 -07:00 committed by Aaron Durbin
parent 8b4988933c
commit 57ddd9abc7
2 changed files with 7 additions and 4 deletions

View File

@ -227,7 +227,8 @@ xhci_init (unsigned long physical_bar)
* Let dcbaa[0] point to another array of pointers, sp_ptrs. * Let dcbaa[0] point to another array of pointers, sp_ptrs.
* The pointers therein point to scratchpad buffers (pages). * The pointers therein point to scratchpad buffers (pages).
*/ */
const size_t max_sp_bufs = xhci->capreg->Max_Scratchpad_Bufs; const size_t max_sp_bufs = xhci->capreg->Max_Scratchpad_Bufs_Hi << 5 |
xhci->capreg->Max_Scratchpad_Bufs_Lo;
xhci_debug("max scratchpad bufs: 0x%zx\n", max_sp_bufs); xhci_debug("max scratchpad bufs: 0x%zx\n", max_sp_bufs);
if (max_sp_bufs) { if (max_sp_bufs) {
const size_t sp_ptrs_size = max_sp_bufs * sizeof(u64); const size_t sp_ptrs_size = max_sp_bufs * sizeof(u64);
@ -417,7 +418,8 @@ xhci_shutdown(hci_t *const controller)
#endif #endif
if (xhci->sp_ptrs) { if (xhci->sp_ptrs) {
const size_t max_sp_bufs = xhci->capreg->Max_Scratchpad_Bufs; size_t max_sp_bufs = xhci->capreg->Max_Scratchpad_Bufs_Hi << 5 |
xhci->capreg->Max_Scratchpad_Bufs_Lo;
for (i = 0; i < max_sp_bufs; ++i) { for (i = 0; i < max_sp_bufs; ++i) {
if (xhci->sp_ptrs[i]) if (xhci->sp_ptrs[i])
free(phys_to_virt(xhci->sp_ptrs[i])); free(phys_to_virt(xhci->sp_ptrs[i]));

View File

@ -348,9 +348,10 @@ typedef struct xhci {
struct { struct {
unsigned long IST:4; unsigned long IST:4;
unsigned long ERST_Max:4; unsigned long ERST_Max:4;
unsigned long:18; unsigned long:13;
unsigned long Max_Scratchpad_Bufs_Hi:5;
unsigned long SPR:1; unsigned long SPR:1;
unsigned long Max_Scratchpad_Bufs:5; unsigned long Max_Scratchpad_Bufs_Lo:5;
} __attribute__ ((packed)); } __attribute__ ((packed));
} __attribute__ ((packed)); } __attribute__ ((packed));
union { union {