diff mbox

[2/2] ssb: Save sprom image for dump of device at alternate location

Message ID 4d044307.Ipm73VWEgifFrF0m%Larry.Finger@lwfinger.net (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Larry Finger Dec. 12, 2010, 3:35 a.m. UTC
None
diff mbox

Patch

Index: wireless-testing/drivers/ssb/pci.c
===================================================================
--- wireless-testing.orig/drivers/ssb/pci.c
+++ wireless-testing/drivers/ssb/pci.c
@@ -709,7 +709,7 @@  static int ssb_pci_sprom_get(struct ssb_
 			if (fallback) {
 				memcpy(sprom, fallback, sizeof(*sprom));
 				err = 0;
-				goto out_free;
+				goto out;
 			}
 			ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
 				   " SPROM CRC (corrupt SPROM)\n");
@@ -763,8 +763,8 @@  static int ssb_pci_sprom_get(struct ssb_
 	}
 	err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 
-out_free:
-	kfree(buf);
+out:
+	bus->sprom_data = buf;
 	return err;
 }
 
@@ -1013,6 +1013,7 @@  void ssb_pci_exit(struct ssb_bus *bus)
 	if (bus->bustype != SSB_BUSTYPE_PCI)
 		return;
 
+	kfree(bus->sprom_data);
 	pdev = bus->host_pci;
 	device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
 }
Index: wireless-testing/drivers/ssb/sprom.c
===================================================================
--- wireless-testing.orig/drivers/ssb/sprom.c
+++ wireless-testing/drivers/ssb/sprom.c
@@ -72,24 +72,29 @@  ssize_t ssb_attr_sprom_show(struct ssb_b
 	ssize_t count = 0;
 	size_t sprom_size_words = bus->sprom_size;
 
-	sprom = kcalloc(sprom_size_words, sizeof(u16), GFP_KERNEL);
-	if (!sprom)
-		goto out;
-
-	/* 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 = sprom_read(bus, sprom);
-	mutex_unlock(&bus->sprom_mutex);
-
+	if (bus->sprom_data) {
+		sprom = bus->sprom_data;
+		err = 0;
+	} else {
+		sprom = kcalloc(sprom_size_words, sizeof(u16), GFP_KERNEL);
+		if (!sprom)
+			goto out;
+
+		/* 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 = sprom_read(bus, sprom);
+		mutex_unlock(&bus->sprom_mutex);
+	}
 	if (!err)
 		count = sprom2hex(sprom, buf, PAGE_SIZE, sprom_size_words);
 
 out_kfree:
-	kfree(sprom);
+	if (!bus->sprom_data)
+		kfree(sprom);
 out:
 	return err ? err : count;
 }
@@ -105,6 +110,8 @@  ssize_t ssb_attr_sprom_store(struct ssb_
 	size_t sprom_size_words = bus->sprom_size;
 	struct ssb_freeze_context freeze;
 
+	if (bus->sprom_offset < SSB_SPROM_BASE1)
+		return -EINVAL;
 	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
 	if (!sprom)
 		goto out;
Index: wireless-testing/include/linux/ssb/ssb.h
===================================================================
--- wireless-testing.orig/include/linux/ssb/ssb.h
+++ wireless-testing/include/linux/ssb/ssb.h
@@ -311,6 +311,7 @@  struct ssb_bus {
 	u16 chip_rev;
 	u16 sprom_offset;
 	u16 sprom_size;		/* number of words in sprom */
+	u16 *sprom_data;	/* saved sprom raw data */
 	u8 chip_package;
 
 	/* List of devices (cores) on the backplane. */