diff options
author | Hauke Mehrtens <hauke@hauke-m.de> | 2011-05-10 17:31:30 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2011-05-19 04:55:47 -0400 |
commit | b3ae52b6b0335eba547221aad2cb3c50902e3d2d (patch) | |
tree | b7901a68a97fc73e6e711828f93ec8dbcca5722d /drivers/ssb | |
parent | b7f720d68c0042cc8ce496e31a61df79a77f1b48 (diff) |
SSB: Change fallback sprom to callback mechanism.
Some embedded devices like the Netgear WNDR3300 have two SSB based cards
without an own sprom on the pci bus. We have to provide two different
fallback sproms for these and this was not possible with the old solution.
In the bcm47xx architecture the sprom data is stored in the nvram in the
main flash storage. The architecture code will be able to fill the sprom
with the stored data based on the bus where the device was found.
The bcm63xx code should do the same thing as before, just using the new
API.
Acked-by: Michael Buesch <mb@bu3sch.de>
Cc: netdev@vger.kernel.org
Cc: linux-wireless@vger.kernel.org
Cc: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2362/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/ssb')
-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 |
3 files changed, 38 insertions, 24 deletions
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 */ |