Commit 61bd5e5683244a564ecfe31c73575ee0bc708ccc
1 parent
bccd17294a
Exists in
master
and in
38 other branches
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 | } |