===================================================================
@@ -19,6 +19,7 @@
#include <linux/ssb/ssb_regs.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/firmware.h>
#include "ssb_private.h"
@@ -613,6 +614,120 @@ static int sprom_extract(struct ssb_bus
return 0;
}
+static void ssb_vsprom_load_failed(void)
+{
+ printk(KERN_ERR "ssb: The BCM43XX device does not have an "
+ "SPROM built in. Use the command\n");
+ printk(KERN_ERR " 'mkdir -p /lib/firmware/ssb ; /bin/dbus-uuidgen"
+ " > /lib/firmware/ssb/mac_addr'\n");
+ printk(KERN_ERR " to generate the required file.\n");
+}
+
+static inline u8 ascii_to_bin(u8 input)
+{
+ /* return the binary value of the ASCII char in the low nibble */
+ return (input <= 0x39) ? input & 0xF : (input - 0x27) & 0xF;
+}
+
+static void ssb_get_vsprom(const struct firmware *fw, void *context)
+{
+ /* Second part of asynchronous firmware load */
+ int i;
+ struct ssb_bus *bus = context;
+ struct ssb_sprom *sprom = &bus->sprom;
+ u8 buf2[8];
+ char *name;
+
+ if (!fw) {
+ ssb_vsprom_load_failed();
+ return;
+ }
+ /* Get values extracted from SPROM. If sprom_extract_r8() is changed,
+ * this section must be changed as well. For any device with 5GHz
+ * capability, some variables will have to be changed.
+ */
+ sprom->revision = 8;
+ sprom->boardflags_lo = 0x0A01;
+ sprom->boardflags_hi = 0x0006;
+ sprom->boardflags2_lo = 0x0000;
+ sprom->boardflags2_hi = 0x0000;
+ sprom->ant_available_a = 0x00;
+ sprom->ant_available_bg = 0x03;
+ sprom->maxpwr_bg = 0x4A;
+ sprom->itssi_bg = 0x3E;
+ sprom->maxpwr_a = 0xFF;
+ sprom->itssi_a = 0xFF;
+ sprom->maxpwr_ah = 0xFF;
+ sprom->maxpwr_al = 0xFF;
+ sprom->gpio0 = 0x83;
+ sprom->gpio1 = 0xFF;
+ sprom->gpio2 = 0xFF;
+ sprom->gpio3 = 0xFF;
+ sprom->tri2g = 0x6C;
+ sprom->tri5g = 0x00;
+ sprom->tri5gl = 0xFF;
+ sprom->tri5gh = 0xFF;
+ sprom->rxpo2g = 0xFA;
+ sprom->rxpo5g = 0xFF;
+ sprom->rssismf2g = 0x0F;
+ sprom->rssismc2g = 0x00;
+ sprom->rssisav2g = 0x00;
+ sprom->bxa2g = 0x00;
+ sprom->rssismf5g = 0x0F;
+ sprom->rssismc5g = 0x0F;
+ sprom->rssisav5g = 0x07;
+ sprom->bxa5g = 0x03;
+ sprom->pa0b0 = 0x1a57;
+ sprom->pa0b1 = 0xF98A;
+ sprom->pa0b2 = 0xFE91;
+ sprom->pa1b0 = 0xFFFF;
+ sprom->pa1b1 = 0xFFFF;
+ sprom->pa1b2 = 0xFFFF;
+ sprom->pa1lob0 = 0xFFFF;
+ sprom->pa1lob1 = 0xFFFF;
+ sprom->pa1lob2 = 0xFFFF;
+ sprom->pa1hib0 = 0xFFFF;
+ sprom->pa1hib1 = 0xFFFF;
+ sprom->pa1hib2 = 0xFFFF;
+ sprom->cck2gpo = 0xFFFF;
+ sprom->ofdm2gpo = 0x00000002;
+ sprom->ofdm5glpo = 0xFFFFFFFF;
+ sprom->ofdm5gpo = 0xFFFFFFFF;
+ sprom->ofdm5ghpo = 0xFFFFFFFF;
+ memset(sprom->et0mac, 0xFF, 6);
+ memset(sprom->et1mac, 0xFF, 6);
+
+ if (fw->size != 33) {
+ printk(KERN_ERR "ssb: The MAC address file has the wrong"
+ " size\n");
+ goto out;
+ }
+ /* Input MAC address data in ASCII - get low nibble in binary */
+ for (i = 0 ; i < 8; i++) {
+ u8 tmp = ascii_to_bin(fw->data[2 * i]);
+ u8 tmp1 = ascii_to_bin(fw->data[2 * i + 1]);
+ buf2[i] = tmp << 4 | tmp1;
+ }
+ /* make sure 2 least significant bits of first byte are clear
+ * These bits are multicast address and LAA bit, and
+ * copy the randomized MAC address to the sprom variables
+ */
+ buf2[0] &= ~(3);
+ memcpy(sprom->il0mac, buf2, 4);
+
+ /* As there may be more than one such interface on a given box,
+ * modify the random MAC address in the file with the
+ * bus information as provided by dev_name(). This will be in
+ * the form "nnnn:mm:oo.p". The last two digits of the MAC address
+ * will be set to oo and mm.
+ */
+ name = (char *)dev_name(&bus->host_pci->dev);
+ sprom->il0mac[5] = ascii_to_bin(name[5]) << 4 | ascii_to_bin(name[6]);
+ sprom->il0mac[4] = ascii_to_bin(name[8]) << 4 | ascii_to_bin(name[9]);
+out:
+ release_firmware(fw);
+}
+
static int ssb_pci_sprom_get(struct ssb_bus *bus,
struct ssb_sprom *sprom)
{
@@ -620,8 +735,18 @@ static int ssb_pci_sprom_get(struct ssb_
int err = -ENOMEM;
u16 *buf;
- if (!ssb_is_sprom_available(bus))
- return -ENODEV;
+ if (!ssb_is_sprom_available(bus)) {
+ /* This device has no SPROM. Try for a random MAC address */
+ err = request_firmware_nowait(THIS_MODULE,
+ FW_ACTION_HOTPLUG, "ssb/mac_addr",
+ &bus->host_pci->dev, GFP_KERNEL, bus,
+ ssb_get_vsprom);
+ if (err) {
+ ssb_vsprom_load_failed();
+ return err;
+ }
+ return 0;
+ }
buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
if (!buf)
===================================================================
@@ -107,7 +107,8 @@ static void lpphy_read_band_sprom(struct
* opo == ofdm2gpo and we don't know any SSB with LP-PHY
* and SPROM rev below 8.
*/
- B43_WARN_ON(bus->sprom.revision < 8);
+ if (bus->sprom.revision < 8)
+ b43err(dev->wl, "Illegal SPROM Revision\n");
ofdmpo = bus->sprom.ofdm2gpo;
if (cckpo) {
for (i = 0; i < 4; i++) {