aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb/sprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ssb/sprom.c')
-rw-r--r--drivers/ssb/sprom.c30
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
17static const struct ssb_sprom *fallback_sprom; 19static const struct ssb_sprom *fallback_sprom;
18 20
@@ -33,17 +35,27 @@ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
33static int hex2sprom(u16 *sprom, const char *dump, size_t len, 35static 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");
128out_unlock: 136out_unlock: