static int ssb_pci_sprom_get()

in pci.c [857:925]


static int ssb_pci_sprom_get(struct ssb_bus *bus,
			     struct ssb_sprom *sprom)
{
	int err;
	u16 *buf;

	if (!ssb_is_sprom_available(bus)) {
		pr_err("No SPROM available!\n");
		return -ENODEV;
	}
	if (bus->chipco.dev) {	/* can be unavailable! */
		/*
		 * get SPROM offset: SSB_SPROM_BASE1 except for
		 * chipcommon rev >= 31 or chip ID is 0x4312 and
		 * chipcommon status & 3 == 2
		 */
		if (bus->chipco.dev->id.revision >= 31)
			bus->sprom_offset = SSB_SPROM_BASE31;
		else if (bus->chip_id == 0x4312 &&
			 (bus->chipco.status & 0x03) == 2)
			bus->sprom_offset = SSB_SPROM_BASE31;
		else
			bus->sprom_offset = SSB_SPROM_BASE1;
	} else {
		bus->sprom_offset = SSB_SPROM_BASE1;
	}
	pr_debug("SPROM offset is 0x%x\n", bus->sprom_offset);

	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
	if (!buf)
		return -ENOMEM;
	bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
	sprom_do_read(bus, buf);
	err = sprom_check_crc(buf, bus->sprom_size);
	if (err) {
		/* try for a 440 byte SPROM - revision 4 and higher */
		kfree(buf);
		buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
			      GFP_KERNEL);
		if (!buf)
			return -ENOMEM;
		bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
		sprom_do_read(bus, buf);
		err = sprom_check_crc(buf, bus->sprom_size);
		if (err) {
			/* All CRC attempts failed.
			 * Maybe there is no SPROM on the device?
			 * Now we ask the arch code if there is some sprom
			 * available for this device in some other storage */
			err = ssb_fill_sprom_with_fallback(bus, sprom);
			if (err) {
				pr_warn("WARNING: Using fallback SPROM failed (err %d)\n",
					err);
				goto out_free;
			} else {
				pr_debug("Using SPROM revision %d provided by platform\n",
					 sprom->revision);
				err = 0;
				goto out_free;
			}
			pr_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
		}
	}
	err = sprom_extract(bus, sprom, buf, bus->sprom_size);

out_free:
	kfree(buf);
	return err;
}