target/generic-2.6: add missing bits for 2.6.30 ssb update
authorNicolas Thill <nico@openwrt.org>
Wed, 19 May 2010 17:07:40 +0000 (17:07 +0000)
committerNicolas Thill <nico@openwrt.org>
Wed, 19 May 2010 17:07:40 +0000 (17:07 +0000)
SVN-Revision: 21507

target/linux/generic-2.6/patches-2.6.30/941-ssb_update.patch

index 8d2d1589533c4a088f0ca441d1da60eb76b58a92..391fbba876142ff83968db98cf8a78bde23e34b0 100644 (file)
 +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;
                }
  
                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();
  
        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;
        }