@@ -8,6 +8,7 @@
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32))
#include <linux/netdevice.h>
+#include <linux/pm.h>
#define SDIO_VENDOR_ID_INTEL 0x0089
#define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402
@@ -43,6 +44,31 @@ enum netdev_tx {
typedef enum netdev_tx netdev_tx_t;
#endif /* __KERNEL__ */
+
+/*
+ * dev_pm_ops is only available on kernels >= 2.6.29, for
+ * older kernels we rely on reverting the work to old
+ * power management style stuff.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+/*
+ * Use this if you want to use the same suspend and resume callbacks for suspend
+ * to RAM and hibernation.
+ */
+#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \
+struct dev_pm_ops name = { \
+ .suspend = suspend_fn, \
+ .resume = resume_fn, \
+ .freeze = suspend_fn, \
+ .thaw = resume_fn, \
+ .poweroff = suspend_fn, \
+ .restore = resume_fn, \
+}
+#else
+#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn)
+#endif /* >= 2.6.29 */
+
+
#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) */
#endif /* LINUX_26_32_COMPAT_H */
new file mode 100644
@@ -0,0 +1,57 @@
+The 2.6.29 kernel has new struct dev_pm_ops [1] which are used
+on the pci device to distinguish power management hooks for suspend
+to RAM and hibernation. Older kernels don't have these so we need
+to resort back to the good ol' suspend/resume. Fortunately the calls
+are not so different so it should be possible to resuse the same
+calls on compat code with only slight modifications.
+
+[1] http://lxr.linux.no/#linux+v2.6.29/include/linux/pm.h#L170
+
+--- a/drivers/net/wireless/ath/ath5k/base.c 2009-10-07 01:58:19.000000000 -0400
++++ b/drivers/net/wireless/ath/ath5k/base.c 2009-10-07 02:19:58.000000000 -0400
+@@ -197,6 +197,32 @@
+ #ifdef CONFIG_PM
+ static int ath5k_pci_suspend(struct device *dev);
+ static int ath5k_pci_resume(struct device *dev);
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29))
++#endif
++static int ath5k_pci_suspend_compat(struct pci_dev *pdev, pm_message_t state)
++{
++ int r;
++
++ r = ath5k_pci_suspend(pdev->dev);
++ if (r)
++ return r;
++
++ pci_save_state(pdev);
++ pci_disable_device(pdev);
++ pci_set_power_state(pdev, PCI_D3hot);
++}
++
++static int ath5k_pci_resume_compat(struct pci_dev *pdev)
++{
++ int r;
++
++ pci_restore_state(pdev);
++ r = pci_enable_device(pdev);
++ if (r)
++ return r;
++
++ return ath5k_pci_resume(pdev->dev);
++}
+
+ SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
+ #define ATH5K_PM_OPS (&ath5k_pm_ops)
+@@ -209,7 +235,12 @@
+ .id_table = ath5k_pci_id_table,
+ .probe = ath5k_pci_probe,
+ .remove = __devexit_p(ath5k_pci_remove),
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+ .driver.pm = ATH5K_PM_OPS,
++#else
++ .suspend = ath5k_pci_suspend_compat,
++ .resume = ath5k_pci_resume_compat,
++#endif
+ };
+
+