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