diff options
Diffstat (limited to 'drivers/ssb/sprom.c')
-rw-r--r-- | drivers/ssb/sprom.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c index 8943015a3ee..d0e6762fec5 100644 --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c | |||
@@ -13,6 +13,8 @@ | |||
13 | 13 | ||
14 | #include "ssb_private.h" | 14 | #include "ssb_private.h" |
15 | 15 | ||
16 | #include <linux/ctype.h> | ||
17 | |||
16 | 18 | ||
17 | static const struct ssb_sprom *fallback_sprom; | 19 | static const struct ssb_sprom *fallback_sprom; |
18 | 20 | ||
@@ -33,17 +35,27 @@ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, | |||
33 | static int hex2sprom(u16 *sprom, const char *dump, size_t len, | 35 | static int hex2sprom(u16 *sprom, const char *dump, size_t len, |
34 | size_t sprom_size_words) | 36 | size_t sprom_size_words) |
35 | { | 37 | { |
36 | char tmp[5] = { 0 }; | 38 | char c, tmp[5] = { 0 }; |
37 | int cnt = 0; | 39 | int err, cnt = 0; |
38 | unsigned long parsed; | 40 | unsigned long parsed; |
39 | 41 | ||
40 | if (len < sprom_size_words * 2) | 42 | /* Strip whitespace at the end. */ |
43 | while (len) { | ||
44 | c = dump[len - 1]; | ||
45 | if (!isspace(c) && c != '\0') | ||
46 | break; | ||
47 | len--; | ||
48 | } | ||
49 | /* Length must match exactly. */ | ||
50 | if (len != sprom_size_words * 4) | ||
41 | return -EINVAL; | 51 | return -EINVAL; |
42 | 52 | ||
43 | while (cnt < sprom_size_words) { | 53 | while (cnt < sprom_size_words) { |
44 | memcpy(tmp, dump, 4); | 54 | memcpy(tmp, dump, 4); |
45 | dump += 4; | 55 | dump += 4; |
46 | parsed = simple_strtoul(tmp, NULL, 16); | 56 | err = strict_strtoul(tmp, 16, &parsed); |
57 | if (err) | ||
58 | return err; | ||
47 | sprom[cnt++] = swab16((u16)parsed); | 59 | sprom[cnt++] = swab16((u16)parsed); |
48 | } | 60 | } |
49 | 61 | ||
@@ -90,6 +102,7 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus, | |||
90 | u16 *sprom; | 102 | u16 *sprom; |
91 | int res = 0, err = -ENOMEM; | 103 | int res = 0, err = -ENOMEM; |
92 | size_t sprom_size_words = bus->sprom_size; | 104 | size_t sprom_size_words = bus->sprom_size; |
105 | struct ssb_freeze_context freeze; | ||
93 | 106 | ||
94 | sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL); | 107 | sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL); |
95 | if (!sprom) | 108 | if (!sprom) |
@@ -111,18 +124,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus, | |||
111 | err = -ERESTARTSYS; | 124 | err = -ERESTARTSYS; |
112 | if (mutex_lock_interruptible(&bus->sprom_mutex)) | 125 | if (mutex_lock_interruptible(&bus->sprom_mutex)) |
113 | goto out_kfree; | 126 | goto out_kfree; |
114 | err = ssb_devices_freeze(bus); | 127 | err = ssb_devices_freeze(bus, &freeze); |
115 | if (err == -EOPNOTSUPP) { | ||
116 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. " | ||
117 | "No suspend support. Is CONFIG_PM enabled?\n"); | ||
118 | goto out_unlock; | ||
119 | } | ||
120 | if (err) { | 128 | if (err) { |
121 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); | 129 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); |
122 | goto out_unlock; | 130 | goto out_unlock; |
123 | } | 131 | } |
124 | res = sprom_write(bus, sprom); | 132 | res = sprom_write(bus, sprom); |
125 | err = ssb_devices_thaw(bus); | 133 | err = ssb_devices_thaw(&freeze); |
126 | if (err) | 134 | if (err) |
127 | ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n"); | 135 | ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n"); |
128 | out_unlock: | 136 | out_unlock: |