ar71xx: add support for the TL-WR841N v1.5 board
[openwrt.git] / target / linux / generic-2.6 / patches-2.6.28 / 975-ssb-fallback-sprom.patch
1 --- a/drivers/ssb/pci.c
2 +++ b/drivers/ssb/pci.c
3 @@ -514,6 +514,7 @@ unsupported:
4 static int ssb_pci_sprom_get(struct ssb_bus *bus,
5 struct ssb_sprom *sprom)
6 {
7 + const struct ssb_sprom *fallback;
8 int err = -ENOMEM;
9 u16 *buf;
10
11 @@ -533,12 +534,23 @@ static int ssb_pci_sprom_get(struct ssb_
12 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
13 sprom_do_read(bus, buf);
14 err = sprom_check_crc(buf, bus->sprom_size);
15 - if (err)
16 + if (err) {
17 + /* All CRC attempts failed.
18 + * Maybe there is no SPROM on the device?
19 + * If we have a fallback, use that. */
20 + fallback = ssb_get_fallback_sprom();
21 + if (fallback) {
22 + memcpy(sprom, fallback, sizeof(*sprom));
23 + err = 0;
24 + goto out_free;
25 + }
26 ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
27 " SPROM CRC (corrupt SPROM)\n");
28 + }
29 }
30 err = sprom_extract(bus, sprom, buf, bus->sprom_size);
31
32 +out_free:
33 kfree(buf);
34 out:
35 return err;
36 --- a/drivers/ssb/sprom.c
37 +++ b/drivers/ssb/sprom.c
38 @@ -14,6 +14,9 @@
39 #include "ssb_private.h"
40
41
42 +static const struct ssb_sprom *fallback_sprom;
43 +
44 +
45 static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
46 size_t sprom_size_words)
47 {
48 @@ -131,3 +134,36 @@ out:
49 return res;
50 return err ? err : count;
51 }
52 +
53 +/**
54 + * ssb_arch_set_fallback_sprom - Set a fallback SPROM for use if no SPROM is found.
55 + *
56 + * @sprom: The SPROM data structure to register.
57 + *
58 + * With this function the architecture implementation may register a fallback
59 + * SPROM data structure. The fallback is only used for PCI based SSB devices,
60 + * where no valid SPROM can be found in the shadow registers.
61 + *
62 + * This function is useful for weird architectures that have a half-assed SSB device
63 + * hardwired to their PCI bus.
64 + *
65 + * Note that it does only work with PCI attached SSB devices. PCMCIA devices currently
66 + * don't use this fallback.
67 + * Architectures must provide the SPROM for native SSB devices anyway,
68 + * so the fallback also isn't used for native devices.
69 + *
70 + * This function is available for architecture code, only. So it is not exported.
71 + */
72 +int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom)
73 +{
74 + if (fallback_sprom)
75 + return -EEXIST;
76 + fallback_sprom = sprom;
77 +
78 + return 0;
79 +}
80 +
81 +const struct ssb_sprom *ssb_get_fallback_sprom(void)
82 +{
83 + return fallback_sprom;
84 +}
85 --- a/drivers/ssb/ssb_private.h
86 +++ b/drivers/ssb/ssb_private.h
87 @@ -131,6 +131,7 @@ ssize_t ssb_attr_sprom_store(struct ssb_
88 const char *buf, size_t count,
89 int (*sprom_check_crc)(const u16 *sprom, size_t size),
90 int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom));
91 +extern const struct ssb_sprom *ssb_get_fallback_sprom(void);
92
93
94 /* core.c */
95 --- a/include/linux/ssb/ssb.h
96 +++ b/include/linux/ssb/ssb.h
97 @@ -339,6 +339,10 @@ extern int ssb_bus_pcmciabus_register(st
98
99 extern void ssb_bus_unregister(struct ssb_bus *bus);
100
101 +/* Set a fallback SPROM.
102 + * See kdoc at the function definition for complete documentation. */
103 +extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
104 +
105 /* Suspend a SSB bus.
106 * Call this from the parent bus suspend routine. */
107 extern int ssb_bus_suspend(struct ssb_bus *bus);
This page took 0.058538 seconds and 5 git commands to generate.