diff options
Diffstat (limited to 'target/linux')
| -rw-r--r-- | target/linux/generic-2.6/patches-2.6.30/941-ssb_update.patch | 169 | 
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 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;   	}  | 
