diff options
-rw-r--r-- | arch/mips/bcm63xx/boards/board_bcm963xx.c | 16 | ||||
-rw-r--r-- | drivers/ssb/pci.c | 16 | ||||
-rw-r--r-- | drivers/ssb/sprom.c | 43 | ||||
-rw-r--r-- | drivers/ssb/ssb_private.h | 3 | ||||
-rw-r--r-- | include/linux/ssb/ssb.h | 4 |
5 files changed, 55 insertions, 27 deletions
diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 8dba8cfb752f..40b223b603be 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c | |||
@@ -643,6 +643,17 @@ static struct ssb_sprom bcm63xx_sprom = { | |||
643 | .boardflags_lo = 0x2848, | 643 | .boardflags_lo = 0x2848, |
644 | .boardflags_hi = 0x0000, | 644 | .boardflags_hi = 0x0000, |
645 | }; | 645 | }; |
646 | |||
647 | int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out) | ||
648 | { | ||
649 | if (bus->bustype == SSB_BUSTYPE_PCI) { | ||
650 | memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom)); | ||
651 | return 0; | ||
652 | } else { | ||
653 | printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n"); | ||
654 | return -EINVAL; | ||
655 | } | ||
656 | } | ||
646 | #endif | 657 | #endif |
647 | 658 | ||
648 | /* | 659 | /* |
@@ -793,8 +804,9 @@ void __init board_prom_init(void) | |||
793 | if (!board_get_mac_address(bcm63xx_sprom.il0mac)) { | 804 | if (!board_get_mac_address(bcm63xx_sprom.il0mac)) { |
794 | memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN); | 805 | memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN); |
795 | memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN); | 806 | memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN); |
796 | if (ssb_arch_set_fallback_sprom(&bcm63xx_sprom) < 0) | 807 | if (ssb_arch_register_fallback_sprom( |
797 | printk(KERN_ERR "failed to register fallback SPROM\n"); | 808 | &bcm63xx_get_fallback_sprom) < 0) |
809 | printk(KERN_ERR PFX "failed to register fallback SPROM\n"); | ||
798 | } | 810 | } |
799 | #endif | 811 | #endif |
800 | } | 812 | } |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 6f34963b3c64..7ad48585c5e6 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -662,7 +662,6 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
662 | static int ssb_pci_sprom_get(struct ssb_bus *bus, | 662 | static int ssb_pci_sprom_get(struct ssb_bus *bus, |
663 | struct ssb_sprom *sprom) | 663 | struct ssb_sprom *sprom) |
664 | { | 664 | { |
665 | const struct ssb_sprom *fallback; | ||
666 | int err; | 665 | int err; |
667 | u16 *buf; | 666 | u16 *buf; |
668 | 667 | ||
@@ -707,10 +706,17 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
707 | if (err) { | 706 | if (err) { |
708 | /* All CRC attempts failed. | 707 | /* All CRC attempts failed. |
709 | * Maybe there is no SPROM on the device? | 708 | * Maybe there is no SPROM on the device? |
710 | * If we have a fallback, use that. */ | 709 | * Now we ask the arch code if there is some sprom |
711 | fallback = ssb_get_fallback_sprom(); | 710 | * available for this device in some other storage */ |
712 | if (fallback) { | 711 | err = ssb_fill_sprom_with_fallback(bus, sprom); |
713 | memcpy(sprom, fallback, sizeof(*sprom)); | 712 | if (err) { |
713 | ssb_printk(KERN_WARNING PFX "WARNING: Using" | ||
714 | " fallback SPROM failed (err %d)\n", | ||
715 | err); | ||
716 | } else { | ||
717 | ssb_dprintk(KERN_DEBUG PFX "Using SPROM" | ||
718 | " revision %d provided by" | ||
719 | " platform.\n", sprom->revision); | ||
714 | err = 0; | 720 | err = 0; |
715 | goto out_free; | 721 | goto out_free; |
716 | } | 722 | } |
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c index 5f34d7a3e3a5..45ff0e3a3828 100644 --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | 18 | ||
19 | 19 | ||
20 | static const struct ssb_sprom *fallback_sprom; | 20 | static int(*get_fallback_sprom)(struct ssb_bus *dev, struct ssb_sprom *out); |
21 | 21 | ||
22 | 22 | ||
23 | static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, | 23 | static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, |
@@ -145,36 +145,43 @@ out: | |||
145 | } | 145 | } |
146 | 146 | ||
147 | /** | 147 | /** |
148 | * ssb_arch_set_fallback_sprom - Set a fallback SPROM for use if no SPROM is found. | 148 | * ssb_arch_register_fallback_sprom - Registers a method providing a |
149 | * fallback SPROM if no SPROM is found. | ||
149 | * | 150 | * |
150 | * @sprom: The SPROM data structure to register. | 151 | * @sprom_callback: The callback function. |
151 | * | 152 | * |
152 | * With this function the architecture implementation may register a fallback | 153 | * With this function the architecture implementation may register a |
153 | * SPROM data structure. The fallback is only used for PCI based SSB devices, | 154 | * callback handler which fills the SPROM data structure. The fallback is |
154 | * where no valid SPROM can be found in the shadow registers. | 155 | * only used for PCI based SSB devices, where no valid SPROM can be found |
156 | * in the shadow registers. | ||
155 | * | 157 | * |
156 | * This function is useful for weird architectures that have a half-assed SSB device | 158 | * This function is useful for weird architectures that have a half-assed |
157 | * hardwired to their PCI bus. | 159 | * SSB device hardwired to their PCI bus. |
158 | * | 160 | * |
159 | * Note that it does only work with PCI attached SSB devices. PCMCIA devices currently | 161 | * Note that it does only work with PCI attached SSB devices. PCMCIA |
160 | * don't use this fallback. | 162 | * devices currently don't use this fallback. |
161 | * Architectures must provide the SPROM for native SSB devices anyway, | 163 | * Architectures must provide the SPROM for native SSB devices anyway, so |
162 | * so the fallback also isn't used for native devices. | 164 | * the fallback also isn't used for native devices. |
163 | * | 165 | * |
164 | * This function is available for architecture code, only. So it is not exported. | 166 | * This function is available for architecture code, only. So it is not |
167 | * exported. | ||
165 | */ | 168 | */ |
166 | int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom) | 169 | int ssb_arch_register_fallback_sprom(int (*sprom_callback)(struct ssb_bus *bus, |
170 | struct ssb_sprom *out)) | ||
167 | { | 171 | { |
168 | if (fallback_sprom) | 172 | if (get_fallback_sprom) |
169 | return -EEXIST; | 173 | return -EEXIST; |
170 | fallback_sprom = sprom; | 174 | get_fallback_sprom = sprom_callback; |
171 | 175 | ||
172 | return 0; | 176 | return 0; |
173 | } | 177 | } |
174 | 178 | ||
175 | const struct ssb_sprom *ssb_get_fallback_sprom(void) | 179 | int ssb_fill_sprom_with_fallback(struct ssb_bus *bus, struct ssb_sprom *out) |
176 | { | 180 | { |
177 | return fallback_sprom; | 181 | if (!get_fallback_sprom) |
182 | return -ENOENT; | ||
183 | |||
184 | return get_fallback_sprom(bus, out); | ||
178 | } | 185 | } |
179 | 186 | ||
180 | /* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */ | 187 | /* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */ |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 0331139a726f..77653014db0b 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -171,7 +171,8 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus, | |||
171 | const char *buf, size_t count, | 171 | const char *buf, size_t count, |
172 | int (*sprom_check_crc)(const u16 *sprom, size_t size), | 172 | int (*sprom_check_crc)(const u16 *sprom, size_t size), |
173 | int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom)); | 173 | int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom)); |
174 | extern const struct ssb_sprom *ssb_get_fallback_sprom(void); | 174 | extern int ssb_fill_sprom_with_fallback(struct ssb_bus *bus, |
175 | struct ssb_sprom *out); | ||
175 | 176 | ||
176 | 177 | ||
177 | /* core.c */ | 178 | /* core.c */ |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 9659eff52ca2..045f72ab5dfd 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -404,7 +404,9 @@ extern bool ssb_is_sprom_available(struct ssb_bus *bus); | |||
404 | 404 | ||
405 | /* Set a fallback SPROM. | 405 | /* Set a fallback SPROM. |
406 | * See kdoc at the function definition for complete documentation. */ | 406 | * See kdoc at the function definition for complete documentation. */ |
407 | extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom); | 407 | extern int ssb_arch_register_fallback_sprom( |
408 | int (*sprom_callback)(struct ssb_bus *bus, | ||
409 | struct ssb_sprom *out)); | ||
408 | 410 | ||
409 | /* Suspend a SSB bus. | 411 | /* Suspend a SSB bus. |
410 | * Call this from the parent bus suspend routine. */ | 412 | * Call this from the parent bus suspend routine. */ |