Commit 61bd5e5683244a564ecfe31c73575ee0bc708ccc

Authored by Linus Torvalds
1 parent bccd17294a

brcmsmac: fix reading of PCI sprom contents

It appears that you can only read the sprom contents with aligned 16-bit
reads: anything else causes at least some versions of the broadcom
chipset to abort the PCI transaction, returning 0xff.

This apparently doesn't trigger very often, because most setups don't
use an external srom chip, and the OTP sprom loading doesn't have this
issue.  But at least the current 11" Macbook Air does trigger it, and
wireless communications were broken as a result.

Acked-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 20 additions and 11 deletions Side-by-side Diff

drivers/net/wireless/brcm80211/brcmsmac/srom.c
... ... @@ -764,6 +764,22 @@
764 764 }
765 765  
766 766 /*
  767 + * The crc check is done on a little-endian array, we need
  768 + * to switch the bytes around before checking crc (and
  769 + * then switch it back).
  770 + */
  771 +static int do_crc_check(u16 *buf, unsigned nwords)
  772 +{
  773 + u8 crc;
  774 +
  775 + cpu_to_le16_buf(buf, nwords);
  776 + crc = crc8(brcms_srom_crc8_table, (void *)buf, nwords << 1, CRC8_INIT_VALUE);
  777 + le16_to_cpu_buf(buf, nwords);
  778 +
  779 + return crc == CRC8_GOOD_VALUE(brcms_srom_crc8_table);
  780 +}
  781 +
  782 +/*
767 783 * Read in and validate sprom.
768 784 * Return 0 on success, nonzero on error.
769 785 */
... ... @@ -772,8 +788,6 @@
772 788 {
773 789 int err = 0;
774 790 uint i;
775   - u8 *bbuf = (u8 *)buf; /* byte buffer */
776   - uint nbytes = nwords << 1;
777 791 struct bcma_device *core;
778 792 uint sprom_offset;
779 793  
... ... @@ -786,9 +800,9 @@
786 800 sprom_offset = CHIPCREGOFFS(sromotp);
787 801 }
788 802  
789   - /* read the sprom in bytes */
790   - for (i = 0; i < nbytes; i++)
791   - bbuf[i] = bcma_read8(core, sprom_offset+i);
  803 + /* read the sprom */
  804 + for (i = 0; i < nwords; i++)
  805 + buf[i] = bcma_read16(core, sprom_offset+i*2);
792 806  
793 807 if (buf[0] == 0xffff)
794 808 /*
795 809  
... ... @@ -798,13 +812,8 @@
798 812 */
799 813 return -ENODATA;
800 814  
801   - if (check_crc &&
802   - crc8(brcms_srom_crc8_table, bbuf, nbytes, CRC8_INIT_VALUE) !=
803   - CRC8_GOOD_VALUE(brcms_srom_crc8_table))
  815 + if (check_crc && !do_crc_check(buf, nwords))
804 816 err = -EIO;
805   - else
806   - /* now correct the endianness of the byte array */
807   - le16_to_cpu_buf(buf, nwords);
808 817  
809 818 return err;
810 819 }