summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authormartin <martin@NetBSD.org>2022-03-26 13:41:16 +0000
committermartin <martin@NetBSD.org>2022-03-26 13:41:16 +0000
commitf3a7128c1ae6eccddb3c275cfc75ac2b6512a2a3 (patch)
treeb6380aeb5ef481c5fd2a41799f048e82909deba3 /sys/dev
parentdafd800a99698b9831b8f36cf9b70825aa7ab1f6 (diff)
When reading CIS tuples from a BAR, do not blindly copy 2k of data (or
to the end of the BAR space), but instead follow the tuples and stop reading once we reach the end of the list. I have a card bwi0 at cardbus0 function 0: Broadcom Wireless bwi0: BBP id 0x4306, BBP rev 0x2, BBP pkg 0 where the BAR claims 8k space but seems to only implement 6k (but that is impossible to report as the spec only allows 2^n sizes) and the CIS starts at a bit over 4k (so the old code tried reading beyound the 6k limit and caused pci bus errors). An alternative would be to avoid reporting bus errors during this access, but since we are only interested in the CIS chain anyway (and that ends way earlier) this is a simpler solution.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/cardbus/cardbus.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c
index ad2ff21a811..6b2bca6e977 100644
--- a/sys/dev/cardbus/cardbus.c
+++ b/sys/dev/cardbus/cardbus.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cardbus.c,v 1.113 2021/11/01 21:28:03 andvar Exp $ */
+/* $NetBSD: cardbus.c,v 1.114 2022/03/26 13:41:16 martin Exp $ */
/*
* Copyright (c) 1997, 1998, 1999 and 2000
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.113 2021/11/01 21:28:03 andvar Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.114 2022/03/26 13:41:16 martin Exp $");
#include "opt_cardbus.h"
@@ -163,6 +163,7 @@ cardbus_read_tuples(struct cardbus_attach_args *ca, pcireg_t cis_ptr,
pcireg_t reg;
int found = 0;
int cardbus_space = cis_ptr & CARDBUS_CIS_ASIMASK;
+ size_t mlen, n, tlen;
int i, j;
memset(tuples, 0, len);
@@ -262,10 +263,28 @@ cardbus_read_tuples(struct cardbus_attach_args *ca, pcireg_t cis_ptr,
cardbus_conf_write(cc, cf, tag,
PCI_COMMAND_STATUS_REG,
command | PCI_COMMAND_MEM_ENABLE);
- /* XXX byte order? */
- bus_space_read_region_1(bar_tag, bar_memh,
- cis_ptr, tuples,
- MIN(bar_size - MIN(bar_size, cis_ptr), len));
+
+ mlen = MIN(bar_size - MIN(bar_size, cis_ptr), len);
+ for (n = 0; n < mlen; ) {
+ tuples[n] = bus_space_read_1(bar_tag, bar_memh,
+ cis_ptr+n);
+ if (tuples[n] == PCMCIA_CISTPL_END)
+ break;
+ if (tuples[n] == PCMCIA_CISTPL_NULL) {
+ n++;
+ continue;
+ }
+ n++;
+ tuples[n] = bus_space_read_1(bar_tag, bar_memh,
+ cis_ptr+n);
+ tlen = tuples[n];
+ n++;
+ if (n+tlen >= mlen)
+ break;
+ bus_space_read_region_1(bar_tag, bar_memh,
+ cis_ptr+n, tuples+n, tlen);
+ n += tlen;
+ }
found++;
}
command = cardbus_conf_read(cc, cf, tag,