Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/cardbus When reading CIS tuples from a BAR, do not b...



details:   https://anonhg.NetBSD.org/src/rev/2301afec5598
branches:  trunk
changeset: 364462:2301afec5598
user:      martin <martin%NetBSD.org@localhost>
date:      Sat Mar 26 13:41:16 2022 +0000

description:
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:

 sys/dev/cardbus/cardbus.c |  31 +++++++++++++++++++++++++------
 1 files changed, 25 insertions(+), 6 deletions(-)

diffs (59 lines):

diff -r e81c270524f1 -r 2301afec5598 sys/dev/cardbus/cardbus.c
--- a/sys/dev/cardbus/cardbus.c Sat Mar 26 13:32:31 2022 +0000
+++ b/sys/dev/cardbus/cardbus.c Sat Mar 26 13:41:16 2022 +0000
@@ -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 @@
        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_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,



Home | Main Index | Thread Index | Old Index