X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=package%2Fmac80211%2Fpatches%2F405-ath9k-move-PCI-code-into-separate-file.patch;fp=package%2Fmac80211%2Fpatches%2F405-ath9k-move-PCI-code-into-separate-file.patch;h=0000000000000000000000000000000000000000;hb=bbd55c00ef3a5a3d0a0a7c08cc23786d74427a26;hp=4a55ded9e79e8090a3966469ee73277671e6bea3;hpb=5f36bc68ecce74ca8beaa099038054e179dc69bd;p=openwrt%2Fsvn-archive%2Farchive.git diff --git a/package/mac80211/patches/405-ath9k-move-PCI-code-into-separate-file.patch b/package/mac80211/patches/405-ath9k-move-PCI-code-into-separate-file.patch deleted file mode 100644 index 4a55ded9e7..0000000000 --- a/package/mac80211/patches/405-ath9k-move-PCI-code-into-separate-file.patch +++ /dev/null @@ -1,735 +0,0 @@ -From 4803193b165c67abcd7cb10dd0c178dbcffb6cc7 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Mon, 5 Jan 2009 11:01:09 +0100 -Subject: [PATCH v3 05/11] ath9k: move PCI code into separate file - -Now that we have converted all bus specific routines to replaceable, we -can move the PCI specific codes into a separate file. - -Changes-licensed-under: ISC - -Signed-off-by: Gabor Juhos -Signed-off-by: Imre Kaloz ---- - drivers/net/wireless/ath9k/Makefile | 1 + - drivers/net/wireless/ath9k/core.h | 19 ++- - drivers/net/wireless/ath9k/main.c | 300 +++-------------------------------- - drivers/net/wireless/ath9k/pci.c | 287 +++++++++++++++++++++++++++++++++ - 4 files changed, 328 insertions(+), 279 deletions(-) - create mode 100644 drivers/net/wireless/ath9k/pci.c - ---- a/drivers/net/wireless/ath9k/Makefile -+++ b/drivers/net/wireless/ath9k/Makefile -@@ -11,6 +11,7 @@ ath9k-y += hw.o \ - xmit.o \ - rc.o - -+ath9k-$(CONFIG_PCI) += pci.o - ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o - - obj-$(CONFIG_ATH9K) += ath9k.o ---- a/drivers/net/wireless/ath9k/core.h -+++ b/drivers/net/wireless/ath9k/core.h -@@ -18,7 +18,7 @@ - #define CORE_H - - #include --#include -+#include - #include - #include - #include -@@ -767,4 +767,21 @@ static inline void ath_bus_cleanup(struc - sc->bus_ops->cleanup(sc); - } - -+extern struct ieee80211_ops ath9k_ops; -+ -+irqreturn_t ath_isr(int irq, void *dev); -+void ath_cleanup(struct ath_softc *sc); -+int ath_attach(u16 devid, struct ath_softc *sc); -+void ath_detach(struct ath_softc *sc); -+const char *ath_mac_bb_name(u32 mac_bb_version); -+const char *ath_rf_name(u16 rf_version); -+ -+#ifdef CONFIG_PCI -+int ath_pci_init(void); -+void ath_pci_exit(void); -+#else -+static inline int ath_pci_init(void) { return 0; }; -+static inline void ath_pci_exit(void) {}; -+#endif -+ - #endif /* CORE_H */ ---- a/drivers/net/wireless/ath9k/main.c -+++ b/drivers/net/wireless/ath9k/main.c -@@ -28,39 +28,6 @@ MODULE_DESCRIPTION("Support for Atheros - MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); - MODULE_LICENSE("Dual BSD/GPL"); - --static struct pci_device_id ath_pci_id_table[] __devinitdata = { -- { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ -- { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ -- { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ -- { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ -- { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ -- { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ -- { 0 } --}; -- --static void ath_detach(struct ath_softc *sc); --static void ath_cleanup(struct ath_softc *sc); -- --/* return bus cachesize in 4B word units */ -- --static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) --{ -- u8 u8tmp; -- -- pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, -- (u8 *)&u8tmp); -- *csz = (int)u8tmp; -- -- /* -- * This check was put in to avoid "unplesant" consequences if -- * the bootrom has not fully initialized all PCI devices. -- * Sometimes the cache line size register is not set -- */ -- -- if (*csz == 0) -- *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ --} -- - static void ath_cache_conf_rate(struct ath_softc *sc, - struct ieee80211_conf *conf) - { -@@ -500,7 +467,7 @@ static void ath9k_tasklet(unsigned long - ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask); - } - --static irqreturn_t ath_isr(int irq, void *dev) -+irqreturn_t ath_isr(int irq, void *dev) - { - struct ath_softc *sc = dev; - struct ath_hal *ah = sc->sc_ah; -@@ -1281,7 +1248,7 @@ static int ath_start_rfkill_poll(struct - } - #endif /* CONFIG_RFKILL */ - --static void ath_cleanup(struct ath_softc *sc) -+void ath_cleanup(struct ath_softc *sc) - { - ath_detach(sc); - free_irq(sc->irq, sc); -@@ -1289,7 +1256,7 @@ static void ath_cleanup(struct ath_softc - ieee80211_free_hw(sc->hw); - } - --static void ath_detach(struct ath_softc *sc) -+void ath_detach(struct ath_softc *sc) - { - struct ieee80211_hw *hw = sc->hw; - int i = 0; -@@ -1543,7 +1510,7 @@ bad: - return error; - } - --static int ath_attach(u16 devid, struct ath_softc *sc) -+int ath_attach(u16 devid, struct ath_softc *sc) - { - struct ieee80211_hw *hw = sc->hw; - int error = 0; -@@ -2466,7 +2433,7 @@ static int ath9k_ampdu_action(struct iee - return ret; - } - --static struct ieee80211_ops ath9k_ops = { -+struct ieee80211_ops ath9k_ops = { - .tx = ath9k_tx, - .start = ath9k_start, - .stop = ath9k_stop, -@@ -2510,7 +2477,7 @@ static struct { - /* - * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. - */ --static const char * -+const char * - ath_mac_bb_name(u32 mac_bb_version) - { - int i; -@@ -2527,7 +2494,7 @@ ath_mac_bb_name(u32 mac_bb_version) - /* - * Return the RF name. "????" is returned if the RF is unknown. - */ --static const char * -+const char * - ath_rf_name(u16 rf_version) - { - int i; -@@ -2541,234 +2508,7 @@ ath_rf_name(u16 rf_version) - return "????"; - } - --static void ath_pci_cleanup(struct ath_softc *sc) --{ -- struct pci_dev *pdev = to_pci_dev(sc->dev); -- -- pci_iounmap(pdev, sc->mem); -- pci_release_region(pdev, 0); -- pci_disable_device(pdev); --} -- --static struct ath_bus_ops ath_pci_bus_ops = { -- .read_cachesize = ath_pci_read_cachesize, -- .cleanup = ath_pci_cleanup, --}; -- --static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) --{ -- void __iomem *mem; -- struct ath_softc *sc; -- struct ieee80211_hw *hw; -- u8 csz; -- u32 val; -- int ret = 0; -- struct ath_hal *ah; -- -- if (pci_enable_device(pdev)) -- return -EIO; -- -- ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); -- -- if (ret) { -- printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); -- goto bad; -- } -- -- ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); -- -- if (ret) { -- printk(KERN_ERR "ath9k: 32-bit DMA consistent " -- "DMA enable failed\n"); -- goto bad; -- } -- -- /* -- * Cache line size is used to size and align various -- * structures used to communicate with the hardware. -- */ -- pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); -- if (csz == 0) { -- /* -- * Linux 2.4.18 (at least) writes the cache line size -- * register as a 16-bit wide register which is wrong. -- * We must have this setup properly for rx buffer -- * DMA to work so force a reasonable value here if it -- * comes up zero. -- */ -- csz = L1_CACHE_BYTES / sizeof(u32); -- pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); -- } -- /* -- * The default setting of latency timer yields poor results, -- * set it to the value used by other systems. It may be worth -- * tweaking this setting more. -- */ -- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); -- -- pci_set_master(pdev); -- -- /* -- * Disable the RETRY_TIMEOUT register (0x41) to keep -- * PCI Tx retries from interfering with C3 CPU state. -- */ -- pci_read_config_dword(pdev, 0x40, &val); -- if ((val & 0x0000ff00) != 0) -- pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); -- -- ret = pci_request_region(pdev, 0, "ath9k"); -- if (ret) { -- dev_err(&pdev->dev, "PCI memory region reserve error\n"); -- ret = -ENODEV; -- goto bad; -- } -- -- mem = pci_iomap(pdev, 0, 0); -- if (!mem) { -- printk(KERN_ERR "PCI memory map error\n") ; -- ret = -EIO; -- goto bad1; -- } -- -- hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); -- if (hw == NULL) { -- printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n"); -- goto bad2; -- } -- -- SET_IEEE80211_DEV(hw, &pdev->dev); -- pci_set_drvdata(pdev, hw); -- -- sc = hw->priv; -- sc->hw = hw; -- sc->dev = &pdev->dev; -- sc->mem = mem; -- sc->bus_ops = &ath_pci_bus_ops; -- -- if (ath_attach(id->device, sc) != 0) { -- ret = -ENODEV; -- goto bad3; -- } -- -- /* setup interrupt service routine */ -- -- if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) { -- printk(KERN_ERR "%s: request_irq failed\n", -- wiphy_name(hw->wiphy)); -- ret = -EIO; -- goto bad4; -- } -- -- sc->irq = pdev->irq; -- -- ah = sc->sc_ah; -- printk(KERN_INFO -- "%s: Atheros AR%s MAC/BB Rev:%x " -- "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", -- wiphy_name(hw->wiphy), -- ath_mac_bb_name(ah->ah_macVersion), -- ah->ah_macRev, -- ath_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)), -- ah->ah_phyRev, -- (unsigned long)mem, pdev->irq); -- -- return 0; --bad4: -- ath_detach(sc); --bad3: -- ieee80211_free_hw(hw); --bad2: -- pci_iounmap(pdev, mem); --bad1: -- pci_release_region(pdev, 0); --bad: -- pci_disable_device(pdev); -- return ret; --} -- --static void ath_pci_remove(struct pci_dev *pdev) --{ -- struct ieee80211_hw *hw = pci_get_drvdata(pdev); -- struct ath_softc *sc = hw->priv; -- -- ath_cleanup(sc); --} -- --#ifdef CONFIG_PM -- --static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) --{ -- struct ieee80211_hw *hw = pci_get_drvdata(pdev); -- struct ath_softc *sc = hw->priv; -- -- ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); -- --#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) -- if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) -- cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); --#endif -- -- pci_save_state(pdev); -- pci_disable_device(pdev); -- pci_set_power_state(pdev, 3); -- -- return 0; --} -- --static int ath_pci_resume(struct pci_dev *pdev) --{ -- struct ieee80211_hw *hw = pci_get_drvdata(pdev); -- struct ath_softc *sc = hw->priv; -- u32 val; -- int err; -- -- err = pci_enable_device(pdev); -- if (err) -- return err; -- pci_restore_state(pdev); -- /* -- * Suspend/Resume resets the PCI configuration space, so we have to -- * re-disable the RETRY_TIMEOUT register (0x41) to keep -- * PCI Tx retries from interfering with C3 CPU state -- */ -- pci_read_config_dword(pdev, 0x40, &val); -- if ((val & 0x0000ff00) != 0) -- pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); -- -- /* Enable LED */ -- ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, -- AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -- ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); -- --#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) -- /* -- * check the h/w rfkill state on resume -- * and start the rfkill poll timer -- */ -- if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) -- queue_delayed_work(sc->hw->workqueue, -- &sc->rf_kill.rfkill_poll, 0); --#endif -- -- return 0; --} -- --#endif /* CONFIG_PM */ -- --MODULE_DEVICE_TABLE(pci, ath_pci_id_table); -- --static struct pci_driver ath_pci_driver = { -- .name = "ath9k", -- .id_table = ath_pci_id_table, -- .probe = ath_pci_probe, -- .remove = ath_pci_remove, --#ifdef CONFIG_PM -- .suspend = ath_pci_suspend, -- .resume = ath_pci_resume, --#endif /* CONFIG_PM */ --}; -- --static int __init init_ath_pci(void) -+static int __init ath9k_init(void) - { - int error; - -@@ -2780,26 +2520,30 @@ static int __init init_ath_pci(void) - printk(KERN_ERR - "Unable to register rate control algorithm: %d\n", - error); -- ath_rate_control_unregister(); -- return error; -+ goto err_out; - } - -- if (pci_register_driver(&ath_pci_driver) < 0) { -+ error = ath_pci_init(); -+ if (error < 0) { - printk(KERN_ERR - "ath_pci: No devices found, driver not installed.\n"); -- ath_rate_control_unregister(); -- pci_unregister_driver(&ath_pci_driver); -- return -ENODEV; -+ error = -ENODEV; -+ goto err_rate_unregister; - } - - return 0; -+ -+ err_rate_unregister: -+ ath_rate_control_unregister(); -+ err_out: -+ return error; - } --module_init(init_ath_pci); -+module_init(ath9k_init); - --static void __exit exit_ath_pci(void) -+static void __exit ath9k_exit(void) - { -+ ath_pci_exit(); - ath_rate_control_unregister(); -- pci_unregister_driver(&ath_pci_driver); - printk(KERN_INFO "%s: Driver unloaded\n", dev_info); - } --module_exit(exit_ath_pci); -+module_exit(ath9k_exit); ---- /dev/null -+++ b/drivers/net/wireless/ath9k/pci.c -@@ -0,0 +1,287 @@ -+/* -+ * Copyright (c) 2008 Atheros Communications Inc. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include "core.h" -+#include "reg.h" -+#include "hw.h" -+ -+static struct pci_device_id ath_pci_id_table[] __devinitdata = { -+ { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ -+ { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ -+ { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ -+ { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ -+ { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ -+ { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ -+ { 0 } -+}; -+ -+/* return bus cachesize in 4B word units */ -+static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) -+{ -+ u8 u8tmp; -+ -+ pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, -+ (u8 *)&u8tmp); -+ *csz = (int)u8tmp; -+ -+ /* -+ * This check was put in to avoid "unplesant" consequences if -+ * the bootrom has not fully initialized all PCI devices. -+ * Sometimes the cache line size register is not set -+ */ -+ -+ if (*csz == 0) -+ *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ -+} -+ -+static void ath_pci_cleanup(struct ath_softc *sc) -+{ -+ struct pci_dev *pdev = to_pci_dev(sc->dev); -+ -+ pci_iounmap(pdev, sc->mem); -+ pci_release_region(pdev, 0); -+ pci_disable_device(pdev); -+} -+ -+static struct ath_bus_ops ath_pci_bus_ops = { -+ .read_cachesize = ath_pci_read_cachesize, -+ .cleanup = ath_pci_cleanup, -+}; -+ -+static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ void __iomem *mem; -+ struct ath_softc *sc; -+ struct ieee80211_hw *hw; -+ u8 csz; -+ u32 val; -+ int ret = 0; -+ struct ath_hal *ah; -+ -+ if (pci_enable_device(pdev)) -+ return -EIO; -+ -+ ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); -+ -+ if (ret) { -+ printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); -+ goto bad; -+ } -+ -+ ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); -+ -+ if (ret) { -+ printk(KERN_ERR "ath9k: 32-bit DMA consistent " -+ "DMA enable failed\n"); -+ goto bad; -+ } -+ -+ /* -+ * Cache line size is used to size and align various -+ * structures used to communicate with the hardware. -+ */ -+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); -+ if (csz == 0) { -+ /* -+ * Linux 2.4.18 (at least) writes the cache line size -+ * register as a 16-bit wide register which is wrong. -+ * We must have this setup properly for rx buffer -+ * DMA to work so force a reasonable value here if it -+ * comes up zero. -+ */ -+ csz = L1_CACHE_BYTES / sizeof(u32); -+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); -+ } -+ /* -+ * The default setting of latency timer yields poor results, -+ * set it to the value used by other systems. It may be worth -+ * tweaking this setting more. -+ */ -+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); -+ -+ pci_set_master(pdev); -+ -+ /* -+ * Disable the RETRY_TIMEOUT register (0x41) to keep -+ * PCI Tx retries from interfering with C3 CPU state. -+ */ -+ pci_read_config_dword(pdev, 0x40, &val); -+ if ((val & 0x0000ff00) != 0) -+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); -+ -+ ret = pci_request_region(pdev, 0, "ath9k"); -+ if (ret) { -+ dev_err(&pdev->dev, "PCI memory region reserve error\n"); -+ ret = -ENODEV; -+ goto bad; -+ } -+ -+ mem = pci_iomap(pdev, 0, 0); -+ if (!mem) { -+ printk(KERN_ERR "PCI memory map error\n") ; -+ ret = -EIO; -+ goto bad1; -+ } -+ -+ hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); -+ if (hw == NULL) { -+ printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n"); -+ goto bad2; -+ } -+ -+ SET_IEEE80211_DEV(hw, &pdev->dev); -+ pci_set_drvdata(pdev, hw); -+ -+ sc = hw->priv; -+ sc->hw = hw; -+ sc->dev = &pdev->dev; -+ sc->mem = mem; -+ sc->bus_ops = &ath_pci_bus_ops; -+ -+ if (ath_attach(id->device, sc) != 0) { -+ ret = -ENODEV; -+ goto bad3; -+ } -+ -+ /* setup interrupt service routine */ -+ -+ if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) { -+ printk(KERN_ERR "%s: request_irq failed\n", -+ wiphy_name(hw->wiphy)); -+ ret = -EIO; -+ goto bad4; -+ } -+ -+ sc->irq = pdev->irq; -+ -+ ah = sc->sc_ah; -+ printk(KERN_INFO -+ "%s: Atheros AR%s MAC/BB Rev:%x " -+ "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", -+ wiphy_name(hw->wiphy), -+ ath_mac_bb_name(ah->ah_macVersion), -+ ah->ah_macRev, -+ ath_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)), -+ ah->ah_phyRev, -+ (unsigned long)mem, pdev->irq); -+ -+ return 0; -+bad4: -+ ath_detach(sc); -+bad3: -+ ieee80211_free_hw(hw); -+bad2: -+ pci_iounmap(pdev, mem); -+bad1: -+ pci_release_region(pdev, 0); -+bad: -+ pci_disable_device(pdev); -+ return ret; -+} -+ -+static void ath_pci_remove(struct pci_dev *pdev) -+{ -+ struct ieee80211_hw *hw = pci_get_drvdata(pdev); -+ struct ath_softc *sc = hw->priv; -+ -+ ath_cleanup(sc); -+} -+ -+#ifdef CONFIG_PM -+ -+static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) -+{ -+ struct ieee80211_hw *hw = pci_get_drvdata(pdev); -+ struct ath_softc *sc = hw->priv; -+ -+ ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); -+ -+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) -+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) -+ cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); -+#endif -+ -+ pci_save_state(pdev); -+ pci_disable_device(pdev); -+ pci_set_power_state(pdev, 3); -+ -+ return 0; -+} -+ -+static int ath_pci_resume(struct pci_dev *pdev) -+{ -+ struct ieee80211_hw *hw = pci_get_drvdata(pdev); -+ struct ath_softc *sc = hw->priv; -+ u32 val; -+ int err; -+ -+ err = pci_enable_device(pdev); -+ if (err) -+ return err; -+ pci_restore_state(pdev); -+ /* -+ * Suspend/Resume resets the PCI configuration space, so we have to -+ * re-disable the RETRY_TIMEOUT register (0x41) to keep -+ * PCI Tx retries from interfering with C3 CPU state -+ */ -+ pci_read_config_dword(pdev, 0x40, &val); -+ if ((val & 0x0000ff00) != 0) -+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); -+ -+ /* Enable LED */ -+ ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, -+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -+ ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); -+ -+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) -+ /* -+ * check the h/w rfkill state on resume -+ * and start the rfkill poll timer -+ */ -+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) -+ queue_delayed_work(sc->hw->workqueue, -+ &sc->rf_kill.rfkill_poll, 0); -+#endif -+ -+ return 0; -+} -+ -+#endif /* CONFIG_PM */ -+ -+MODULE_DEVICE_TABLE(pci, ath_pci_id_table); -+ -+static struct pci_driver ath_pci_driver = { -+ .name = "ath9k", -+ .id_table = ath_pci_id_table, -+ .probe = ath_pci_probe, -+ .remove = ath_pci_remove, -+#ifdef CONFIG_PM -+ .suspend = ath_pci_suspend, -+ .resume = ath_pci_resume, -+#endif /* CONFIG_PM */ -+}; -+ -+int __init ath_pci_init(void) -+{ -+ return pci_register_driver(&ath_pci_driver); -+} -+ -+void ath_pci_exit(void) -+{ -+ pci_unregister_driver(&ath_pci_driver); -+}