diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/ssb | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/ssb')
-rw-r--r-- | drivers/ssb/driver_chipcommon_pmu.c | 7 | ||||
-rw-r--r-- | drivers/ssb/driver_gige.c | 1 | ||||
-rw-r--r-- | drivers/ssb/driver_mipscore.c | 5 | ||||
-rw-r--r-- | drivers/ssb/driver_pcicore.c | 33 | ||||
-rw-r--r-- | drivers/ssb/main.c | 130 | ||||
-rw-r--r-- | drivers/ssb/pci.c | 1 | ||||
-rw-r--r-- | drivers/ssb/pcihost_wrapper.c | 1 | ||||
-rw-r--r-- | drivers/ssb/pcmcia.c | 232 | ||||
-rw-r--r-- | drivers/ssb/scan.c | 2 | ||||
-rw-r--r-- | drivers/ssb/sprom.c | 31 | ||||
-rw-r--r-- | drivers/ssb/ssb_private.h | 16 |
11 files changed, 234 insertions, 225 deletions
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 64abd11f6fbb..3d551245a4e2 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c | |||
@@ -332,6 +332,12 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) | |||
332 | case 0x5354: | 332 | case 0x5354: |
333 | ssb_pmu0_pllinit_r0(cc, crystalfreq); | 333 | ssb_pmu0_pllinit_r0(cc, crystalfreq); |
334 | break; | 334 | break; |
335 | case 0x4322: | ||
336 | if (cc->pmu.rev == 2) { | ||
337 | chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, 0x0000000A); | ||
338 | chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0); | ||
339 | } | ||
340 | break; | ||
335 | default: | 341 | default: |
336 | ssb_printk(KERN_ERR PFX | 342 | ssb_printk(KERN_ERR PFX |
337 | "ERROR: PLL init unknown for device %04X\n", | 343 | "ERROR: PLL init unknown for device %04X\n", |
@@ -417,6 +423,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) | |||
417 | 423 | ||
418 | switch (bus->chip_id) { | 424 | switch (bus->chip_id) { |
419 | case 0x4312: | 425 | case 0x4312: |
426 | case 0x4322: | ||
420 | /* We keep the default settings: | 427 | /* We keep the default settings: |
421 | * min_msk = 0xCBB | 428 | * min_msk = 0xCBB |
422 | * max_msk = 0x7FFFF | 429 | * max_msk = 0x7FFFF |
diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c index 172f90407b93..5ba92a2719a4 100644 --- a/drivers/ssb/driver_gige.c +++ b/drivers/ssb/driver_gige.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/ssb/ssb_driver_gige.h> | 12 | #include <linux/ssb/ssb_driver_gige.h> |
13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
14 | #include <linux/pci_regs.h> | 14 | #include <linux/pci_regs.h> |
15 | #include <linux/slab.h> | ||
15 | 16 | ||
16 | 17 | ||
17 | /* | 18 | /* |
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 3c6feed46f6e..97efce184a8f 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -270,7 +270,6 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
270 | set_irq(dev, irq++); | 270 | set_irq(dev, irq++); |
271 | } | 271 | } |
272 | break; | 272 | break; |
273 | /* fallthrough */ | ||
274 | case SSB_DEV_PCI: | 273 | case SSB_DEV_PCI: |
275 | case SSB_DEV_ETHERNET: | 274 | case SSB_DEV_ETHERNET: |
276 | case SSB_DEV_ETHERNET_GBIT: | 275 | case SSB_DEV_ETHERNET_GBIT: |
@@ -281,6 +280,10 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) | |||
281 | set_irq(dev, irq++); | 280 | set_irq(dev, irq++); |
282 | break; | 281 | break; |
283 | } | 282 | } |
283 | /* fallthrough */ | ||
284 | case SSB_DEV_EXTIF: | ||
285 | set_irq(dev, 0); | ||
286 | break; | ||
284 | } | 287 | } |
285 | } | 288 | } |
286 | ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); | 289 | ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); |
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 538c570df337..0e8d35224614 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c | |||
@@ -246,20 +246,12 @@ static struct pci_controller ssb_pcicore_controller = { | |||
246 | .pci_ops = &ssb_pcicore_pciops, | 246 | .pci_ops = &ssb_pcicore_pciops, |
247 | .io_resource = &ssb_pcicore_io_resource, | 247 | .io_resource = &ssb_pcicore_io_resource, |
248 | .mem_resource = &ssb_pcicore_mem_resource, | 248 | .mem_resource = &ssb_pcicore_mem_resource, |
249 | .mem_offset = 0x24000000, | ||
250 | }; | 249 | }; |
251 | 250 | ||
252 | static u32 ssb_pcicore_pcibus_iobase = 0x100; | ||
253 | static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA; | ||
254 | |||
255 | /* This function is called when doing a pci_enable_device(). | 251 | /* This function is called when doing a pci_enable_device(). |
256 | * We must first check if the device is a device on the PCI-core bridge. */ | 252 | * We must first check if the device is a device on the PCI-core bridge. */ |
257 | int ssb_pcicore_plat_dev_init(struct pci_dev *d) | 253 | int ssb_pcicore_plat_dev_init(struct pci_dev *d) |
258 | { | 254 | { |
259 | struct resource *res; | ||
260 | int pos, size; | ||
261 | u32 *base; | ||
262 | |||
263 | if (d->bus->ops != &ssb_pcicore_pciops) { | 255 | if (d->bus->ops != &ssb_pcicore_pciops) { |
264 | /* This is not a device on the PCI-core bridge. */ | 256 | /* This is not a device on the PCI-core bridge. */ |
265 | return -ENODEV; | 257 | return -ENODEV; |
@@ -268,27 +260,6 @@ int ssb_pcicore_plat_dev_init(struct pci_dev *d) | |||
268 | ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", | 260 | ssb_printk(KERN_INFO "PCI: Fixing up device %s\n", |
269 | pci_name(d)); | 261 | pci_name(d)); |
270 | 262 | ||
271 | /* Fix up resource bases */ | ||
272 | for (pos = 0; pos < 6; pos++) { | ||
273 | res = &d->resource[pos]; | ||
274 | if (res->flags & IORESOURCE_IO) | ||
275 | base = &ssb_pcicore_pcibus_iobase; | ||
276 | else | ||
277 | base = &ssb_pcicore_pcibus_membase; | ||
278 | res->flags |= IORESOURCE_PCI_FIXED; | ||
279 | if (res->end) { | ||
280 | size = res->end - res->start + 1; | ||
281 | if (*base & (size - 1)) | ||
282 | *base = (*base + size) & ~(size - 1); | ||
283 | res->start = *base; | ||
284 | res->end = res->start + size - 1; | ||
285 | *base += size; | ||
286 | pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start); | ||
287 | } | ||
288 | /* Fix up PCI bridge BAR0 only */ | ||
289 | if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0) | ||
290 | break; | ||
291 | } | ||
292 | /* Fix up interrupt lines */ | 263 | /* Fix up interrupt lines */ |
293 | d->irq = ssb_mips_irq(extpci_core->dev) + 2; | 264 | d->irq = ssb_mips_irq(extpci_core->dev) + 2; |
294 | pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); | 265 | pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); |
@@ -551,13 +522,13 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, | |||
551 | might_sleep_if(pdev->id.coreid != SSB_DEV_PCI); | 522 | might_sleep_if(pdev->id.coreid != SSB_DEV_PCI); |
552 | 523 | ||
553 | /* Enable interrupts for this device. */ | 524 | /* Enable interrupts for this device. */ |
554 | if (bus->host_pci && | 525 | if ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE)) { |
555 | ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE))) { | ||
556 | u32 coremask; | 526 | u32 coremask; |
557 | 527 | ||
558 | /* Calculate the "coremask" for the device. */ | 528 | /* Calculate the "coremask" for the device. */ |
559 | coremask = (1 << dev->core_index); | 529 | coremask = (1 << dev->core_index); |
560 | 530 | ||
531 | SSB_WARN_ON(bus->bustype != SSB_BUSTYPE_PCI); | ||
561 | err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp); | 532 | err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp); |
562 | if (err) | 533 | if (err) |
563 | goto out; | 534 | goto out; |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 579b114be412..80ff7d9e60de 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
19 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
20 | #include <linux/mmc/sdio_func.h> | 20 | #include <linux/mmc/sdio_func.h> |
21 | #include <linux/slab.h> | ||
21 | 22 | ||
22 | #include <pcmcia/cs_types.h> | 23 | #include <pcmcia/cs_types.h> |
23 | #include <pcmcia/cs.h> | 24 | #include <pcmcia/cs.h> |
@@ -140,6 +141,19 @@ static void ssb_device_put(struct ssb_device *dev) | |||
140 | put_device(dev->dev); | 141 | put_device(dev->dev); |
141 | } | 142 | } |
142 | 143 | ||
144 | static inline struct ssb_driver *ssb_driver_get(struct ssb_driver *drv) | ||
145 | { | ||
146 | if (drv) | ||
147 | get_driver(&drv->drv); | ||
148 | return drv; | ||
149 | } | ||
150 | |||
151 | static inline void ssb_driver_put(struct ssb_driver *drv) | ||
152 | { | ||
153 | if (drv) | ||
154 | put_driver(&drv->drv); | ||
155 | } | ||
156 | |||
143 | static int ssb_device_resume(struct device *dev) | 157 | static int ssb_device_resume(struct device *dev) |
144 | { | 158 | { |
145 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | 159 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); |
@@ -210,90 +224,81 @@ int ssb_bus_suspend(struct ssb_bus *bus) | |||
210 | EXPORT_SYMBOL(ssb_bus_suspend); | 224 | EXPORT_SYMBOL(ssb_bus_suspend); |
211 | 225 | ||
212 | #ifdef CONFIG_SSB_SPROM | 226 | #ifdef CONFIG_SSB_SPROM |
213 | int ssb_devices_freeze(struct ssb_bus *bus) | 227 | /** ssb_devices_freeze - Freeze all devices on the bus. |
228 | * | ||
229 | * After freezing no device driver will be handling a device | ||
230 | * on this bus anymore. ssb_devices_thaw() must be called after | ||
231 | * a successful freeze to reactivate the devices. | ||
232 | * | ||
233 | * @bus: The bus. | ||
234 | * @ctx: Context structure. Pass this to ssb_devices_thaw(). | ||
235 | */ | ||
236 | int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx) | ||
214 | { | 237 | { |
215 | struct ssb_device *dev; | 238 | struct ssb_device *sdev; |
216 | struct ssb_driver *drv; | 239 | struct ssb_driver *sdrv; |
217 | int err = 0; | 240 | unsigned int i; |
218 | int i; | 241 | |
219 | pm_message_t state = PMSG_FREEZE; | 242 | memset(ctx, 0, sizeof(*ctx)); |
243 | ctx->bus = bus; | ||
244 | SSB_WARN_ON(bus->nr_devices > ARRAY_SIZE(ctx->device_frozen)); | ||
220 | 245 | ||
221 | /* First check that we are capable to freeze all devices. */ | ||
222 | for (i = 0; i < bus->nr_devices; i++) { | 246 | for (i = 0; i < bus->nr_devices; i++) { |
223 | dev = &(bus->devices[i]); | 247 | sdev = ssb_device_get(&bus->devices[i]); |
224 | if (!dev->dev || | 248 | |
225 | !dev->dev->driver || | 249 | if (!sdev->dev || !sdev->dev->driver || |
226 | !device_is_registered(dev->dev)) | 250 | !device_is_registered(sdev->dev)) { |
227 | continue; | 251 | ssb_device_put(sdev); |
228 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
229 | if (!drv) | ||
230 | continue; | 252 | continue; |
231 | if (!drv->suspend) { | ||
232 | /* Nope, can't suspend this one. */ | ||
233 | return -EOPNOTSUPP; | ||
234 | } | 253 | } |
235 | } | 254 | sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver)); |
236 | /* Now suspend all devices */ | 255 | if (!sdrv || SSB_WARN_ON(!sdrv->remove)) { |
237 | for (i = 0; i < bus->nr_devices; i++) { | 256 | ssb_device_put(sdev); |
238 | dev = &(bus->devices[i]); | ||
239 | if (!dev->dev || | ||
240 | !dev->dev->driver || | ||
241 | !device_is_registered(dev->dev)) | ||
242 | continue; | 257 | continue; |
243 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
244 | if (!drv) | ||
245 | continue; | ||
246 | err = drv->suspend(dev, state); | ||
247 | if (err) { | ||
248 | ssb_printk(KERN_ERR PFX "Failed to freeze device %s\n", | ||
249 | dev_name(dev->dev)); | ||
250 | goto err_unwind; | ||
251 | } | 258 | } |
259 | sdrv->remove(sdev); | ||
260 | ctx->device_frozen[i] = 1; | ||
252 | } | 261 | } |
253 | 262 | ||
254 | return 0; | 263 | return 0; |
255 | err_unwind: | ||
256 | for (i--; i >= 0; i--) { | ||
257 | dev = &(bus->devices[i]); | ||
258 | if (!dev->dev || | ||
259 | !dev->dev->driver || | ||
260 | !device_is_registered(dev->dev)) | ||
261 | continue; | ||
262 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
263 | if (!drv) | ||
264 | continue; | ||
265 | if (drv->resume) | ||
266 | drv->resume(dev); | ||
267 | } | ||
268 | return err; | ||
269 | } | 264 | } |
270 | 265 | ||
271 | int ssb_devices_thaw(struct ssb_bus *bus) | 266 | /** ssb_devices_thaw - Unfreeze all devices on the bus. |
267 | * | ||
268 | * This will re-attach the device drivers and re-init the devices. | ||
269 | * | ||
270 | * @ctx: The context structure from ssb_devices_freeze() | ||
271 | */ | ||
272 | int ssb_devices_thaw(struct ssb_freeze_context *ctx) | ||
272 | { | 273 | { |
273 | struct ssb_device *dev; | 274 | struct ssb_bus *bus = ctx->bus; |
274 | struct ssb_driver *drv; | 275 | struct ssb_device *sdev; |
275 | int err; | 276 | struct ssb_driver *sdrv; |
276 | int i; | 277 | unsigned int i; |
278 | int err, result = 0; | ||
277 | 279 | ||
278 | for (i = 0; i < bus->nr_devices; i++) { | 280 | for (i = 0; i < bus->nr_devices; i++) { |
279 | dev = &(bus->devices[i]); | 281 | if (!ctx->device_frozen[i]) |
280 | if (!dev->dev || | ||
281 | !dev->dev->driver || | ||
282 | !device_is_registered(dev->dev)) | ||
283 | continue; | 282 | continue; |
284 | drv = drv_to_ssb_drv(dev->dev->driver); | 283 | sdev = &bus->devices[i]; |
285 | if (!drv) | 284 | |
285 | if (SSB_WARN_ON(!sdev->dev || !sdev->dev->driver)) | ||
286 | continue; | 286 | continue; |
287 | if (SSB_WARN_ON(!drv->resume)) | 287 | sdrv = drv_to_ssb_drv(sdev->dev->driver); |
288 | if (SSB_WARN_ON(!sdrv || !sdrv->probe)) | ||
288 | continue; | 289 | continue; |
289 | err = drv->resume(dev); | 290 | |
291 | err = sdrv->probe(sdev, &sdev->id); | ||
290 | if (err) { | 292 | if (err) { |
291 | ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", | 293 | ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", |
292 | dev_name(dev->dev)); | 294 | dev_name(sdev->dev)); |
295 | result = err; | ||
293 | } | 296 | } |
297 | ssb_driver_put(sdrv); | ||
298 | ssb_device_put(sdev); | ||
294 | } | 299 | } |
295 | 300 | ||
296 | return 0; | 301 | return result; |
297 | } | 302 | } |
298 | #endif /* CONFIG_SSB_SPROM */ | 303 | #endif /* CONFIG_SSB_SPROM */ |
299 | 304 | ||
@@ -490,8 +495,7 @@ static int ssb_devices_register(struct ssb_bus *bus) | |||
490 | #endif | 495 | #endif |
491 | break; | 496 | break; |
492 | case SSB_BUSTYPE_SDIO: | 497 | case SSB_BUSTYPE_SDIO: |
493 | #ifdef CONFIG_SSB_SDIO | 498 | #ifdef CONFIG_SSB_SDIOHOST |
494 | sdev->irq = bus->host_sdio->dev.irq; | ||
495 | dev->parent = &bus->host_sdio->dev; | 499 | dev->parent = &bus->host_sdio->dev; |
496 | #endif | 500 | #endif |
497 | break; | 501 | break; |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 9e50896233aa..a8dbb06623c9 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/ssb/ssb.h> | 18 | #include <linux/ssb/ssb.h> |
19 | #include <linux/ssb/ssb_regs.h> | 19 | #include <linux/ssb/ssb_regs.h> |
20 | #include <linux/slab.h> | ||
20 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
22 | 23 | ||
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c index 26737a010c6d..6536a041d90d 100644 --- a/drivers/ssb/pcihost_wrapper.c +++ b/drivers/ssb/pcihost_wrapper.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/ssb/ssb.h> | 16 | #include <linux/ssb/ssb.h> |
16 | 17 | ||
17 | 18 | ||
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index 100e7a5c5ea1..e72f4046a5e0 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c | |||
@@ -617,136 +617,140 @@ static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size) | |||
617 | } \ | 617 | } \ |
618 | } while (0) | 618 | } while (0) |
619 | 619 | ||
620 | int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | 620 | static int ssb_pcmcia_get_mac(struct pcmcia_device *p_dev, |
621 | struct ssb_init_invariants *iv) | 621 | tuple_t *tuple, |
622 | void *priv) | ||
622 | { | 623 | { |
623 | tuple_t tuple; | 624 | struct ssb_sprom *sprom = priv; |
624 | int res; | 625 | |
625 | unsigned char buf[32]; | 626 | if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID) |
627 | return -EINVAL; | ||
628 | if (tuple->TupleDataLen != ETH_ALEN + 2) | ||
629 | return -EINVAL; | ||
630 | if (tuple->TupleData[1] != ETH_ALEN) | ||
631 | return -EINVAL; | ||
632 | memcpy(sprom->il0mac, &tuple->TupleData[2], ETH_ALEN); | ||
633 | return 0; | ||
634 | }; | ||
635 | |||
636 | static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev, | ||
637 | tuple_t *tuple, | ||
638 | void *priv) | ||
639 | { | ||
640 | struct ssb_init_invariants *iv = priv; | ||
626 | struct ssb_sprom *sprom = &iv->sprom; | 641 | struct ssb_sprom *sprom = &iv->sprom; |
627 | struct ssb_boardinfo *bi = &iv->boardinfo; | 642 | struct ssb_boardinfo *bi = &iv->boardinfo; |
628 | const char *error_description; | 643 | const char *error_description; |
629 | 644 | ||
645 | GOTO_ERROR_ON(tuple->TupleDataLen < 1, "VEN tpl < 1"); | ||
646 | switch (tuple->TupleData[0]) { | ||
647 | case SSB_PCMCIA_CIS_ID: | ||
648 | GOTO_ERROR_ON((tuple->TupleDataLen != 5) && | ||
649 | (tuple->TupleDataLen != 7), | ||
650 | "id tpl size"); | ||
651 | bi->vendor = tuple->TupleData[1] | | ||
652 | ((u16)tuple->TupleData[2] << 8); | ||
653 | break; | ||
654 | case SSB_PCMCIA_CIS_BOARDREV: | ||
655 | GOTO_ERROR_ON(tuple->TupleDataLen != 2, | ||
656 | "boardrev tpl size"); | ||
657 | sprom->board_rev = tuple->TupleData[1]; | ||
658 | break; | ||
659 | case SSB_PCMCIA_CIS_PA: | ||
660 | GOTO_ERROR_ON((tuple->TupleDataLen != 9) && | ||
661 | (tuple->TupleDataLen != 10), | ||
662 | "pa tpl size"); | ||
663 | sprom->pa0b0 = tuple->TupleData[1] | | ||
664 | ((u16)tuple->TupleData[2] << 8); | ||
665 | sprom->pa0b1 = tuple->TupleData[3] | | ||
666 | ((u16)tuple->TupleData[4] << 8); | ||
667 | sprom->pa0b2 = tuple->TupleData[5] | | ||
668 | ((u16)tuple->TupleData[6] << 8); | ||
669 | sprom->itssi_a = tuple->TupleData[7]; | ||
670 | sprom->itssi_bg = tuple->TupleData[7]; | ||
671 | sprom->maxpwr_a = tuple->TupleData[8]; | ||
672 | sprom->maxpwr_bg = tuple->TupleData[8]; | ||
673 | break; | ||
674 | case SSB_PCMCIA_CIS_OEMNAME: | ||
675 | /* We ignore this. */ | ||
676 | break; | ||
677 | case SSB_PCMCIA_CIS_CCODE: | ||
678 | GOTO_ERROR_ON(tuple->TupleDataLen != 2, | ||
679 | "ccode tpl size"); | ||
680 | sprom->country_code = tuple->TupleData[1]; | ||
681 | break; | ||
682 | case SSB_PCMCIA_CIS_ANTENNA: | ||
683 | GOTO_ERROR_ON(tuple->TupleDataLen != 2, | ||
684 | "ant tpl size"); | ||
685 | sprom->ant_available_a = tuple->TupleData[1]; | ||
686 | sprom->ant_available_bg = tuple->TupleData[1]; | ||
687 | break; | ||
688 | case SSB_PCMCIA_CIS_ANTGAIN: | ||
689 | GOTO_ERROR_ON(tuple->TupleDataLen != 2, | ||
690 | "antg tpl size"); | ||
691 | sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1]; | ||
692 | sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1]; | ||
693 | sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1]; | ||
694 | sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1]; | ||
695 | sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1]; | ||
696 | sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1]; | ||
697 | sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1]; | ||
698 | sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1]; | ||
699 | break; | ||
700 | case SSB_PCMCIA_CIS_BFLAGS: | ||
701 | GOTO_ERROR_ON((tuple->TupleDataLen != 3) && | ||
702 | (tuple->TupleDataLen != 5), | ||
703 | "bfl tpl size"); | ||
704 | sprom->boardflags_lo = tuple->TupleData[1] | | ||
705 | ((u16)tuple->TupleData[2] << 8); | ||
706 | break; | ||
707 | case SSB_PCMCIA_CIS_LEDS: | ||
708 | GOTO_ERROR_ON(tuple->TupleDataLen != 5, | ||
709 | "leds tpl size"); | ||
710 | sprom->gpio0 = tuple->TupleData[1]; | ||
711 | sprom->gpio1 = tuple->TupleData[2]; | ||
712 | sprom->gpio2 = tuple->TupleData[3]; | ||
713 | sprom->gpio3 = tuple->TupleData[4]; | ||
714 | break; | ||
715 | } | ||
716 | return -ENOSPC; /* continue with next entry */ | ||
717 | |||
718 | error: | ||
719 | ssb_printk(KERN_ERR PFX | ||
720 | "PCMCIA: Failed to fetch device invariants: %s\n", | ||
721 | error_description); | ||
722 | return -ENODEV; | ||
723 | } | ||
724 | |||
725 | |||
726 | int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | ||
727 | struct ssb_init_invariants *iv) | ||
728 | { | ||
729 | struct ssb_sprom *sprom = &iv->sprom; | ||
730 | int res; | ||
731 | |||
630 | memset(sprom, 0xFF, sizeof(*sprom)); | 732 | memset(sprom, 0xFF, sizeof(*sprom)); |
631 | sprom->revision = 1; | 733 | sprom->revision = 1; |
632 | sprom->boardflags_lo = 0; | 734 | sprom->boardflags_lo = 0; |
633 | sprom->boardflags_hi = 0; | 735 | sprom->boardflags_hi = 0; |
634 | 736 | ||
635 | /* First fetch the MAC address. */ | 737 | /* First fetch the MAC address. */ |
636 | memset(&tuple, 0, sizeof(tuple)); | 738 | res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, |
637 | tuple.DesiredTuple = CISTPL_FUNCE; | 739 | ssb_pcmcia_get_mac, sprom); |
638 | tuple.TupleData = buf; | 740 | if (res != 0) { |
639 | tuple.TupleDataMax = sizeof(buf); | 741 | ssb_printk(KERN_ERR PFX |
640 | res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple); | 742 | "PCMCIA: Failed to fetch MAC address\n"); |
641 | GOTO_ERROR_ON(res != 0, "MAC first tpl"); | 743 | return -ENODEV; |
642 | res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); | ||
643 | GOTO_ERROR_ON(res != 0, "MAC first tpl data"); | ||
644 | while (1) { | ||
645 | GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1"); | ||
646 | if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID) | ||
647 | break; | ||
648 | res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple); | ||
649 | GOTO_ERROR_ON(res != 0, "MAC next tpl"); | ||
650 | res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); | ||
651 | GOTO_ERROR_ON(res != 0, "MAC next tpl data"); | ||
652 | } | 744 | } |
653 | GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size"); | ||
654 | memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN); | ||
655 | 745 | ||
656 | /* Fetch the vendor specific tuples. */ | 746 | /* Fetch the vendor specific tuples. */ |
657 | memset(&tuple, 0, sizeof(tuple)); | 747 | res = pcmcia_loop_tuple(bus->host_pcmcia, SSB_PCMCIA_CIS, |
658 | tuple.DesiredTuple = SSB_PCMCIA_CIS; | 748 | ssb_pcmcia_do_get_invariants, sprom); |
659 | tuple.TupleData = buf; | 749 | if ((res == 0) || (res == -ENOSPC)) |
660 | tuple.TupleDataMax = sizeof(buf); | 750 | return 0; |
661 | res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple); | ||
662 | GOTO_ERROR_ON(res != 0, "VEN first tpl"); | ||
663 | res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); | ||
664 | GOTO_ERROR_ON(res != 0, "VEN first tpl data"); | ||
665 | while (1) { | ||
666 | GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1"); | ||
667 | switch (tuple.TupleData[0]) { | ||
668 | case SSB_PCMCIA_CIS_ID: | ||
669 | GOTO_ERROR_ON((tuple.TupleDataLen != 5) && | ||
670 | (tuple.TupleDataLen != 7), | ||
671 | "id tpl size"); | ||
672 | bi->vendor = tuple.TupleData[1] | | ||
673 | ((u16)tuple.TupleData[2] << 8); | ||
674 | break; | ||
675 | case SSB_PCMCIA_CIS_BOARDREV: | ||
676 | GOTO_ERROR_ON(tuple.TupleDataLen != 2, | ||
677 | "boardrev tpl size"); | ||
678 | sprom->board_rev = tuple.TupleData[1]; | ||
679 | break; | ||
680 | case SSB_PCMCIA_CIS_PA: | ||
681 | GOTO_ERROR_ON((tuple.TupleDataLen != 9) && | ||
682 | (tuple.TupleDataLen != 10), | ||
683 | "pa tpl size"); | ||
684 | sprom->pa0b0 = tuple.TupleData[1] | | ||
685 | ((u16)tuple.TupleData[2] << 8); | ||
686 | sprom->pa0b1 = tuple.TupleData[3] | | ||
687 | ((u16)tuple.TupleData[4] << 8); | ||
688 | sprom->pa0b2 = tuple.TupleData[5] | | ||
689 | ((u16)tuple.TupleData[6] << 8); | ||
690 | sprom->itssi_a = tuple.TupleData[7]; | ||
691 | sprom->itssi_bg = tuple.TupleData[7]; | ||
692 | sprom->maxpwr_a = tuple.TupleData[8]; | ||
693 | sprom->maxpwr_bg = tuple.TupleData[8]; | ||
694 | break; | ||
695 | case SSB_PCMCIA_CIS_OEMNAME: | ||
696 | /* We ignore this. */ | ||
697 | break; | ||
698 | case SSB_PCMCIA_CIS_CCODE: | ||
699 | GOTO_ERROR_ON(tuple.TupleDataLen != 2, | ||
700 | "ccode tpl size"); | ||
701 | sprom->country_code = tuple.TupleData[1]; | ||
702 | break; | ||
703 | case SSB_PCMCIA_CIS_ANTENNA: | ||
704 | GOTO_ERROR_ON(tuple.TupleDataLen != 2, | ||
705 | "ant tpl size"); | ||
706 | sprom->ant_available_a = tuple.TupleData[1]; | ||
707 | sprom->ant_available_bg = tuple.TupleData[1]; | ||
708 | break; | ||
709 | case SSB_PCMCIA_CIS_ANTGAIN: | ||
710 | GOTO_ERROR_ON(tuple.TupleDataLen != 2, | ||
711 | "antg tpl size"); | ||
712 | sprom->antenna_gain.ghz24.a0 = tuple.TupleData[1]; | ||
713 | sprom->antenna_gain.ghz24.a1 = tuple.TupleData[1]; | ||
714 | sprom->antenna_gain.ghz24.a2 = tuple.TupleData[1]; | ||
715 | sprom->antenna_gain.ghz24.a3 = tuple.TupleData[1]; | ||
716 | sprom->antenna_gain.ghz5.a0 = tuple.TupleData[1]; | ||
717 | sprom->antenna_gain.ghz5.a1 = tuple.TupleData[1]; | ||
718 | sprom->antenna_gain.ghz5.a2 = tuple.TupleData[1]; | ||
719 | sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; | ||
720 | break; | ||
721 | case SSB_PCMCIA_CIS_BFLAGS: | ||
722 | GOTO_ERROR_ON((tuple.TupleDataLen != 3) && | ||
723 | (tuple.TupleDataLen != 5), | ||
724 | "bfl tpl size"); | ||
725 | sprom->boardflags_lo = tuple.TupleData[1] | | ||
726 | ((u16)tuple.TupleData[2] << 8); | ||
727 | break; | ||
728 | case SSB_PCMCIA_CIS_LEDS: | ||
729 | GOTO_ERROR_ON(tuple.TupleDataLen != 5, | ||
730 | "leds tpl size"); | ||
731 | sprom->gpio0 = tuple.TupleData[1]; | ||
732 | sprom->gpio1 = tuple.TupleData[2]; | ||
733 | sprom->gpio2 = tuple.TupleData[3]; | ||
734 | sprom->gpio3 = tuple.TupleData[4]; | ||
735 | break; | ||
736 | } | ||
737 | res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple); | ||
738 | if (res == -ENOSPC) | ||
739 | break; | ||
740 | GOTO_ERROR_ON(res != 0, "VEN next tpl"); | ||
741 | res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); | ||
742 | GOTO_ERROR_ON(res != 0, "VEN next tpl data"); | ||
743 | } | ||
744 | 751 | ||
745 | return 0; | ||
746 | error: | ||
747 | ssb_printk(KERN_ERR PFX | 752 | ssb_printk(KERN_ERR PFX |
748 | "PCMCIA: Failed to fetch device invariants: %s\n", | 753 | "PCMCIA: Failed to fetch device invariants\n"); |
749 | error_description); | ||
750 | return -ENODEV; | 754 | return -ENODEV; |
751 | } | 755 | } |
752 | 756 | ||
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index e8b89e8ac9bd..0d6c0280eb34 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c | |||
@@ -354,7 +354,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
354 | dev->bus = bus; | 354 | dev->bus = bus; |
355 | dev->ops = bus->ops; | 355 | dev->ops = bus->ops; |
356 | 356 | ||
357 | ssb_dprintk(KERN_INFO PFX | 357 | printk(KERN_DEBUG PFX |
358 | "Core %d found: %s " | 358 | "Core %d found: %s " |
359 | "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", | 359 | "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", |
360 | i, ssb_core_name(dev->id.coreid), | 360 | i, ssb_core_name(dev->id.coreid), |
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 | ||
17 | static const struct ssb_sprom *fallback_sprom; | 20 | static const struct ssb_sprom *fallback_sprom; |
18 | 21 | ||
@@ -33,17 +36,27 @@ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, | |||
33 | static int hex2sprom(u16 *sprom, const char *dump, size_t len, | 36 | static 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"); |
128 | out_unlock: | 137 | out_unlock: |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 25433565dfda..0331139a726f 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -176,19 +176,27 @@ extern const struct ssb_sprom *ssb_get_fallback_sprom(void); | |||
176 | 176 | ||
177 | /* core.c */ | 177 | /* core.c */ |
178 | extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m); | 178 | extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m); |
179 | extern int ssb_devices_freeze(struct ssb_bus *bus); | ||
180 | extern int ssb_devices_thaw(struct ssb_bus *bus); | ||
181 | extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); | 179 | extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); |
182 | int ssb_for_each_bus_call(unsigned long data, | 180 | int ssb_for_each_bus_call(unsigned long data, |
183 | int (*func)(struct ssb_bus *bus, unsigned long data)); | 181 | int (*func)(struct ssb_bus *bus, unsigned long data)); |
184 | extern struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev); | 182 | extern struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev); |
185 | 183 | ||
184 | struct ssb_freeze_context { | ||
185 | /* Pointer to the bus */ | ||
186 | struct ssb_bus *bus; | ||
187 | /* Boolean list to indicate whether a device is frozen on this bus. */ | ||
188 | bool device_frozen[SSB_MAX_NR_CORES]; | ||
189 | }; | ||
190 | extern int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx); | ||
191 | extern int ssb_devices_thaw(struct ssb_freeze_context *ctx); | ||
192 | |||
193 | |||
186 | 194 | ||
187 | /* b43_pci_bridge.c */ | 195 | /* b43_pci_bridge.c */ |
188 | #ifdef CONFIG_SSB_B43_PCI_BRIDGE | 196 | #ifdef CONFIG_SSB_B43_PCI_BRIDGE |
189 | extern int __init b43_pci_ssb_bridge_init(void); | 197 | extern int __init b43_pci_ssb_bridge_init(void); |
190 | extern void __exit b43_pci_ssb_bridge_exit(void); | 198 | extern void __exit b43_pci_ssb_bridge_exit(void); |
191 | #else /* CONFIG_SSB_B43_PCI_BRIDGR */ | 199 | #else /* CONFIG_SSB_B43_PCI_BRIDGE */ |
192 | static inline int b43_pci_ssb_bridge_init(void) | 200 | static inline int b43_pci_ssb_bridge_init(void) |
193 | { | 201 | { |
194 | return 0; | 202 | return 0; |
@@ -196,6 +204,6 @@ static inline int b43_pci_ssb_bridge_init(void) | |||
196 | static inline void b43_pci_ssb_bridge_exit(void) | 204 | static inline void b43_pci_ssb_bridge_exit(void) |
197 | { | 205 | { |
198 | } | 206 | } |
199 | #endif /* CONFIG_SSB_PCIHOST */ | 207 | #endif /* CONFIG_SSB_B43_PCI_BRIDGE */ |
200 | 208 | ||
201 | #endif /* LINUX_SSB_PRIVATE_H_ */ | 209 | #endif /* LINUX_SSB_PRIVATE_H_ */ |