diff --git a/target/linux/generic-2.6/patches-2.6.30/941-ssb_update.patch b/target/linux/generic-2.6/patches-2.6.30/941-ssb_update.patch index 8d2d15895..391fbba87 100644 --- a/target/linux/generic-2.6/patches-2.6.30/941-ssb_update.patch +++ b/target/linux/generic-2.6/patches-2.6.30/941-ssb_update.patch @@ -128,7 +128,170 @@ +EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c -@@ -472,6 +472,8 @@ static int ssb_devices_register(struct s +@@ -120,6 +120,19 @@ static void ssb_device_put(struct ssb_de + put_device(dev->dev); + } + ++static inline struct ssb_driver *ssb_driver_get(struct ssb_driver *drv) ++{ ++ if (drv) ++ get_driver(&drv->drv); ++ return drv; ++} ++ ++static inline void ssb_driver_put(struct ssb_driver *drv) ++{ ++ if (drv) ++ put_driver(&drv->drv); ++} ++ + static int ssb_device_resume(struct device *dev) + { + struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); +@@ -190,90 +203,81 @@ int ssb_bus_suspend(struct ssb_bus *bus) + EXPORT_SYMBOL(ssb_bus_suspend); + + #ifdef CONFIG_SSB_SPROM +-int ssb_devices_freeze(struct ssb_bus *bus) ++/** ssb_devices_freeze - Freeze all devices on the bus. ++ * ++ * After freezing no device driver will be handling a device ++ * on this bus anymore. ssb_devices_thaw() must be called after ++ * a successful freeze to reactivate the devices. ++ * ++ * @bus: The bus. ++ * @ctx: Context structure. Pass this to ssb_devices_thaw(). ++ */ ++int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx) + { +- struct ssb_device *dev; +- struct ssb_driver *drv; +- int err = 0; +- int i; +- pm_message_t state = PMSG_FREEZE; ++ struct ssb_device *sdev; ++ struct ssb_driver *sdrv; ++ unsigned int i; ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ ctx->bus = bus; ++ SSB_WARN_ON(bus->nr_devices > ARRAY_SIZE(ctx->device_frozen)); + +- /* First check that we are capable to freeze all devices. */ + for (i = 0; i < bus->nr_devices; i++) { +- dev = &(bus->devices[i]); +- if (!dev->dev || +- !dev->dev->driver || +- !device_is_registered(dev->dev)) +- continue; +- drv = drv_to_ssb_drv(dev->dev->driver); +- if (!drv) ++ sdev = ssb_device_get(&bus->devices[i]); ++ ++ if (!sdev->dev || !sdev->dev->driver || ++ !device_is_registered(sdev->dev)) { ++ ssb_device_put(sdev); + continue; +- if (!drv->suspend) { +- /* Nope, can't suspend this one. */ +- return -EOPNOTSUPP; + } +- } +- /* Now suspend all devices */ +- for (i = 0; i < bus->nr_devices; i++) { +- dev = &(bus->devices[i]); +- if (!dev->dev || +- !dev->dev->driver || +- !device_is_registered(dev->dev)) +- continue; +- drv = drv_to_ssb_drv(dev->dev->driver); +- if (!drv) ++ sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver)); ++ if (!sdrv || SSB_WARN_ON(!sdrv->remove)) { ++ ssb_device_put(sdev); + continue; +- err = drv->suspend(dev, state); +- if (err) { +- ssb_printk(KERN_ERR PFX "Failed to freeze device %s\n", +- dev_name(dev->dev)); +- goto err_unwind; + } ++ sdrv->remove(sdev); ++ ctx->device_frozen[i] = 1; + } + + return 0; +-err_unwind: +- for (i--; i >= 0; i--) { +- dev = &(bus->devices[i]); +- if (!dev->dev || +- !dev->dev->driver || +- !device_is_registered(dev->dev)) +- continue; +- drv = drv_to_ssb_drv(dev->dev->driver); +- if (!drv) +- continue; +- if (drv->resume) +- drv->resume(dev); +- } +- return err; + } + +-int ssb_devices_thaw(struct ssb_bus *bus) ++/** ssb_devices_thaw - Unfreeze all devices on the bus. ++ * ++ * This will re-attach the device drivers and re-init the devices. ++ * ++ * @ctx: The context structure from ssb_devices_freeze() ++ */ ++int ssb_devices_thaw(struct ssb_freeze_context *ctx) + { +- struct ssb_device *dev; +- struct ssb_driver *drv; +- int err; +- int i; ++ struct ssb_bus *bus = ctx->bus; ++ struct ssb_device *sdev; ++ struct ssb_driver *sdrv; ++ unsigned int i; ++ int err, result = 0; + + for (i = 0; i < bus->nr_devices; i++) { +- dev = &(bus->devices[i]); +- if (!dev->dev || +- !dev->dev->driver || +- !device_is_registered(dev->dev)) ++ if (!ctx->device_frozen[i]) + continue; +- drv = drv_to_ssb_drv(dev->dev->driver); +- if (!drv) ++ sdev = &bus->devices[i]; ++ ++ if (SSB_WARN_ON(!sdev->dev || !sdev->dev->driver)) + continue; +- if (SSB_WARN_ON(!drv->resume)) ++ sdrv = drv_to_ssb_drv(sdev->dev->driver); ++ if (SSB_WARN_ON(!sdrv || !sdrv->probe)) + continue; +- err = drv->resume(dev); ++ ++ err = sdrv->probe(sdev, &sdev->id); + if (err) { + ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", +- dev_name(dev->dev)); ++ dev_name(sdev->dev)); ++ result = err; + } ++ ssb_driver_put(sdrv); ++ ssb_device_put(sdev); + } + +- return 0; ++ return result; + } + #endif /* CONFIG_SSB_SPROM */ + +@@ -472,6 +476,8 @@ static int ssb_devices_register(struct s case SSB_BUSTYPE_SSB: dev->dma_mask = &dev->coherent_dma_mask; break; @@ -137,7 +300,7 @@ } sdev->dev = dev; -@@ -1358,8 +1360,10 @@ static int __init ssb_modinit(void) +@@ -1358,8 +1364,10 @@ static int __init ssb_modinit(void) ssb_buses_lock(); err = ssb_attach_queued_buses(); ssb_buses_unlock(); @@ -149,7 +312,7 @@ err = b43_pci_ssb_bridge_init(); if (err) { -@@ -1375,7 +1379,7 @@ static int __init ssb_modinit(void) +@@ -1375,7 +1383,7 @@ static int __init ssb_modinit(void) /* don't fail SSB init because of this */ err = 0; }