in sprom.c [99:147]
ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
const char *buf, size_t count,
int (*sprom_check_crc)(const u16 *sprom, size_t size),
int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom))
{
u16 *sprom;
int res = 0, err = -ENOMEM;
size_t sprom_size_words = bus->sprom_size;
struct ssb_freeze_context freeze;
sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
if (!sprom)
goto out;
err = hex2sprom(sprom, buf, count, sprom_size_words);
if (err) {
err = -EINVAL;
goto out_kfree;
}
err = sprom_check_crc(sprom, sprom_size_words);
if (err) {
err = -EINVAL;
goto out_kfree;
}
/* Use interruptible locking, as the SPROM write might
* be holding the lock for several seconds. So allow userspace
* to cancel operation.
*/
err = -ERESTARTSYS;
if (mutex_lock_interruptible(&bus->sprom_mutex))
goto out_kfree;
err = ssb_devices_freeze(bus, &freeze);
if (err) {
pr_err("SPROM write: Could not freeze all devices\n");
goto out_unlock;
}
res = sprom_write(bus, sprom);
err = ssb_devices_thaw(&freeze);
if (err)
pr_err("SPROM write: Could not thaw all devices\n");
out_unlock:
mutex_unlock(&bus->sprom_mutex);
out_kfree:
kfree(sprom);
out:
if (res)
return res;
return err ? err : count;
}