/* Common sprom device-attribute store-handler */ 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) { ssb_err("SPROM write: Could not freeze all devices\n"); goto out_unlock; } res = sprom_write(bus, sprom); err = ssb_devices_thaw(&freeze); if (err) ssb_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; }
static u16 pcidev_to_chipid(struct pci_dev *pci_dev) { u16 chipid_fallback = 0; switch (pci_dev->device) { case 0x4301: chipid_fallback = 0x4301; break; case 0x4305 ... 0x4307: chipid_fallback = 0x4307; break; case 0x4403: chipid_fallback = 0x4402; break; case 0x4610 ... 0x4615: chipid_fallback = 0x4610; break; case 0x4710 ... 0x4715: chipid_fallback = 0x4710; break; case 0x4320 ... 0x4325: chipid_fallback = 0x4309; break; case PCI_DEVICE_ID_BCM4401: case PCI_DEVICE_ID_BCM4401B0: case PCI_DEVICE_ID_BCM4401B1: chipid_fallback = 0x4401; break; default: ssb_err("PCI-ID not in fallback list\n"); } return chipid_fallback; }
/* Early PCI fixup for a device on the PCI-core bridge. */ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev) { u8 lat; if (dev->bus->ops != &ssb_pcicore_pciops) { /* This is not a device on the PCI-core bridge. */ return; } if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) return; ssb_info("PCI: Fixing up bridge %s\n", pci_name(dev)); /* Enable PCI bridge bus mastering and memory space */ pci_set_master(dev); if (pcibios_enable_device(dev, ~0) < 0) { ssb_err("PCI: SSB bridge enable failed\n"); return; } /* Enable PCI bridge BAR1 prefetch and burst */ pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); /* Make sure our latency is high enough to handle the devices behind us */ lat = 168; ssb_info("PCI: Fixing latency timer of device %s to %u\n", pci_name(dev), lat); pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); }
static u8 chipid_to_nrcores(u16 chipid) { switch (chipid) { case 0x5365: return 7; case 0x4306: return 6; case 0x4310: return 8; case 0x4307: case 0x4301: return 5; case 0x4401: case 0x4402: return 3; case 0x4710: case 0x4610: case 0x4704: return 9; default: ssb_err("CHIPID not in nrcores fallback list\n"); } return 1; }