aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic-2.6/patches-2.6.30/941-ssb_update.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic-2.6/patches-2.6.30/941-ssb_update.patch')
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/941-ssb_update.patch169
1 files changed, 166 insertions, 3 deletions
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 8d2d158953..391fbba876 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;
}