aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-12 15:19:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-12 15:19:34 -0500
commit61bd5e5683244a564ecfe31c73575ee0bc708ccc (patch)
tree6df40bc0d8bd3e27588349fe8b469286fd48bdf9 /drivers
parentbccd17294a26b67a8a19aaa120e3eeaa7da49281 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/srom.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
index 61092156755e..563743643038 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/srom.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
@@ -764,6 +764,22 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
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 */
771static 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 * Read in and validate sprom. 783 * Read in and validate sprom.
768 * Return 0 on success, nonzero on error. 784 * Return 0 on success, nonzero on error.
769 */ 785 */
@@ -772,8 +788,6 @@ sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
772{ 788{
773 int err = 0; 789 int err = 0;
774 uint i; 790 uint i;
775 u8 *bbuf = (u8 *)buf; /* byte buffer */
776 uint nbytes = nwords << 1;
777 struct bcma_device *core; 791 struct bcma_device *core;
778 uint sprom_offset; 792 uint sprom_offset;
779 793
@@ -786,9 +800,9 @@ sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
786 sprom_offset = CHIPCREGOFFS(sromotp); 800 sprom_offset = CHIPCREGOFFS(sromotp);
787 } 801 }
788 802
789 /* read the sprom in bytes */ 803 /* read the sprom */
790 for (i = 0; i < nbytes; i++) 804 for (i = 0; i < nwords; i++)
791 bbuf[i] = bcma_read8(core, sprom_offset+i); 805 buf[i] = bcma_read16(core, sprom_offset+i*2);
792 806
793 if (buf[0] == 0xffff) 807 if (buf[0] == 0xffff)
794 /* 808 /*
@@ -798,13 +812,8 @@ sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
798 */ 812 */
799 return -ENODATA; 813 return -ENODATA;
800 814
801 if (check_crc && 815 if (check_crc && !do_crc_check(buf, nwords))
802 crc8(brcms_srom_crc8_table, bbuf, nbytes, CRC8_INIT_VALUE) !=
803 CRC8_GOOD_VALUE(brcms_srom_crc8_table))
804 err = -EIO; 816 err = -EIO;
805 else
806 /* now correct the endianness of the byte array */
807 le16_to_cpu_buf(buf, nwords);
808 817
809 return err; 818 return err;
810} 819}