diff options
author | Felix Fietkau <nbd@openwrt.org> | 2010-12-02 04:27:01 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-12-02 15:17:50 -0500 |
commit | e5b046d86fac609f636d127a38de94a175c7e83b (patch) | |
tree | e76c838f1e8f65ee97483677ecb9ddb99f6bdf4e /drivers | |
parent | 132b1c3ee38ea6fa0501004fd0f19acb554e5a44 (diff) |
ath5k: Move PCI bus functions to separate file.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Wojciech Dubowik <Wojciech.Dubowik@neratec.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ath5k.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 267 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pci.c | 284 |
4 files changed, 289 insertions, 266 deletions
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index 2242a140e4fe..dae881cd7dd1 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile | |||
@@ -15,4 +15,5 @@ ath5k-y += rfkill.o | |||
15 | ath5k-y += ani.o | 15 | ath5k-y += ani.o |
16 | ath5k-y += sysfs.o | 16 | ath5k-y += sysfs.o |
17 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o | 17 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o |
18 | ath5k-y += pci.o | ||
18 | obj-$(CONFIG_ATH5K) += ath5k.o | 19 | obj-$(CONFIG_ATH5K) += ath5k.o |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index a74f448f7d72..ee3c0af3ab3c 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -1145,6 +1145,7 @@ struct ath5k_hw { | |||
1145 | /* | 1145 | /* |
1146 | * Prototypes | 1146 | * Prototypes |
1147 | */ | 1147 | */ |
1148 | extern const struct ieee80211_ops ath5k_hw_ops; | ||
1148 | 1149 | ||
1149 | /* Initialization and detach functions */ | 1150 | /* Initialization and detach functions */ |
1150 | int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops); | 1151 | int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops); |
@@ -1155,6 +1156,8 @@ void ath5k_hw_deinit(struct ath5k_hw *ah); | |||
1155 | int ath5k_sysfs_register(struct ath5k_softc *sc); | 1156 | int ath5k_sysfs_register(struct ath5k_softc *sc); |
1156 | void ath5k_sysfs_unregister(struct ath5k_softc *sc); | 1157 | void ath5k_sysfs_unregister(struct ath5k_softc *sc); |
1157 | 1158 | ||
1159 | /*Chip id helper function */ | ||
1160 | const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val); | ||
1158 | 1161 | ||
1159 | /* LED functions */ | 1162 | /* LED functions */ |
1160 | int ath5k_init_leds(struct ath5k_softc *sc); | 1163 | int ath5k_init_leds(struct ath5k_softc *sc); |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b11ea3d2872d..9fcc4e14d1e5 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -47,8 +47,6 @@ | |||
47 | #include <linux/io.h> | 47 | #include <linux/io.h> |
48 | #include <linux/netdevice.h> | 48 | #include <linux/netdevice.h> |
49 | #include <linux/cache.h> | 49 | #include <linux/cache.h> |
50 | #include <linux/pci.h> | ||
51 | #include <linux/pci-aspm.h> | ||
52 | #include <linux/ethtool.h> | 50 | #include <linux/ethtool.h> |
53 | #include <linux/uaccess.h> | 51 | #include <linux/uaccess.h> |
54 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
@@ -87,30 +85,6 @@ static int ath5k_beacon_update(struct ieee80211_hw *hw, | |||
87 | struct ieee80211_vif *vif); | 85 | struct ieee80211_vif *vif); |
88 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | 86 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); |
89 | 87 | ||
90 | /* Known PCI ids */ | ||
91 | static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { | ||
92 | { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ | ||
93 | { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ | ||
94 | { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ | ||
95 | { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ | ||
96 | { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ | ||
97 | { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ | ||
98 | { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ | ||
99 | { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ | ||
100 | { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ | ||
101 | { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ | ||
102 | { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ | ||
103 | { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ | ||
104 | { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ | ||
105 | { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ | ||
106 | { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ | ||
107 | { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ | ||
108 | { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ | ||
109 | { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ | ||
110 | { 0 } | ||
111 | }; | ||
112 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); | ||
113 | |||
114 | /* Known SREVs */ | 88 | /* Known SREVs */ |
115 | static const struct ath5k_srev_name srev_names[] = { | 89 | static const struct ath5k_srev_name srev_names[] = { |
116 | { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, | 90 | { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, |
@@ -193,32 +167,6 @@ static const struct ieee80211_rate ath5k_rates[] = { | |||
193 | /* XR missing */ | 167 | /* XR missing */ |
194 | }; | 168 | }; |
195 | 169 | ||
196 | /* return bus cachesize in 4B word units */ | ||
197 | static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz) | ||
198 | { | ||
199 | struct ath5k_softc *sc = (struct ath5k_softc *) common->priv; | ||
200 | u8 u8tmp; | ||
201 | |||
202 | pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp); | ||
203 | *csz = (int)u8tmp; | ||
204 | |||
205 | /* | ||
206 | * This check was put in to avoid "unplesant" consequences if | ||
207 | * the bootrom has not fully initialized all PCI devices. | ||
208 | * Sometimes the cache line size register is not set | ||
209 | */ | ||
210 | |||
211 | if (*csz == 0) | ||
212 | *csz = L1_CACHE_BYTES >> 2; /* Use the default size */ | ||
213 | } | ||
214 | |||
215 | /* Common ath_bus_opts structure */ | ||
216 | static const struct ath_bus_ops ath_pci_bus_ops = { | ||
217 | .ath_bus_type = ATH_PCI, | ||
218 | .read_cachesize = ath5k_pci_read_cachesize, | ||
219 | }; | ||
220 | |||
221 | |||
222 | static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, | 170 | static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, |
223 | struct ath5k_buf *bf) | 171 | struct ath5k_buf *bf) |
224 | { | 172 | { |
@@ -261,7 +209,7 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | |||
261 | return (tsf & ~0x7fff) | rstamp; | 209 | return (tsf & ~0x7fff) | rstamp; |
262 | } | 210 | } |
263 | 211 | ||
264 | static const char * | 212 | const char * |
265 | ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) | 213 | ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) |
266 | { | 214 | { |
267 | const char *name = "xxxxx"; | 215 | const char *name = "xxxxx"; |
@@ -3627,216 +3575,3 @@ const struct ieee80211_ops ath5k_hw_ops = { | |||
3627 | .set_antenna = ath5k_set_antenna, | 3575 | .set_antenna = ath5k_set_antenna, |
3628 | .get_antenna = ath5k_get_antenna, | 3576 | .get_antenna = ath5k_get_antenna, |
3629 | }; | 3577 | }; |
3630 | |||
3631 | /********************\ | ||
3632 | * PCI Initialization * | ||
3633 | \********************/ | ||
3634 | |||
3635 | static int __devinit | ||
3636 | ath5k_pci_probe(struct pci_dev *pdev, | ||
3637 | const struct pci_device_id *id) | ||
3638 | { | ||
3639 | void __iomem *mem; | ||
3640 | struct ath5k_softc *sc; | ||
3641 | struct ieee80211_hw *hw; | ||
3642 | int ret; | ||
3643 | u8 csz; | ||
3644 | |||
3645 | /* | ||
3646 | * L0s needs to be disabled on all ath5k cards. | ||
3647 | * | ||
3648 | * For distributions shipping with CONFIG_PCIEASPM (this will be enabled | ||
3649 | * by default in the future in 2.6.36) this will also mean both L1 and | ||
3650 | * L0s will be disabled when a pre 1.1 PCIe device is detected. We do | ||
3651 | * know L1 works correctly even for all ath5k pre 1.1 PCIe devices | ||
3652 | * though but cannot currently undue the effect of a blacklist, for | ||
3653 | * details you can read pcie_aspm_sanity_check() and see how it adjusts | ||
3654 | * the device link capability. | ||
3655 | * | ||
3656 | * It may be possible in the future to implement some PCI API to allow | ||
3657 | * drivers to override blacklists for pre 1.1 PCIe but for now it is | ||
3658 | * best to accept that both L0s and L1 will be disabled completely for | ||
3659 | * distributions shipping with CONFIG_PCIEASPM rather than having this | ||
3660 | * issue present. Motivation for adding this new API will be to help | ||
3661 | * with power consumption for some of these devices. | ||
3662 | */ | ||
3663 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); | ||
3664 | |||
3665 | ret = pci_enable_device(pdev); | ||
3666 | if (ret) { | ||
3667 | dev_err(&pdev->dev, "can't enable device\n"); | ||
3668 | goto err; | ||
3669 | } | ||
3670 | |||
3671 | /* XXX 32-bit addressing only */ | ||
3672 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
3673 | if (ret) { | ||
3674 | dev_err(&pdev->dev, "32-bit DMA not available\n"); | ||
3675 | goto err_dis; | ||
3676 | } | ||
3677 | |||
3678 | /* | ||
3679 | * Cache line size is used to size and align various | ||
3680 | * structures used to communicate with the hardware. | ||
3681 | */ | ||
3682 | pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); | ||
3683 | if (csz == 0) { | ||
3684 | /* | ||
3685 | * Linux 2.4.18 (at least) writes the cache line size | ||
3686 | * register as a 16-bit wide register which is wrong. | ||
3687 | * We must have this setup properly for rx buffer | ||
3688 | * DMA to work so force a reasonable value here if it | ||
3689 | * comes up zero. | ||
3690 | */ | ||
3691 | csz = L1_CACHE_BYTES >> 2; | ||
3692 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | ||
3693 | } | ||
3694 | /* | ||
3695 | * The default setting of latency timer yields poor results, | ||
3696 | * set it to the value used by other systems. It may be worth | ||
3697 | * tweaking this setting more. | ||
3698 | */ | ||
3699 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); | ||
3700 | |||
3701 | /* Enable bus mastering */ | ||
3702 | pci_set_master(pdev); | ||
3703 | |||
3704 | /* | ||
3705 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
3706 | * PCI Tx retries from interfering with C3 CPU state. | ||
3707 | */ | ||
3708 | pci_write_config_byte(pdev, 0x41, 0); | ||
3709 | |||
3710 | ret = pci_request_region(pdev, 0, "ath5k"); | ||
3711 | if (ret) { | ||
3712 | dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); | ||
3713 | goto err_dis; | ||
3714 | } | ||
3715 | |||
3716 | mem = pci_iomap(pdev, 0, 0); | ||
3717 | if (!mem) { | ||
3718 | dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; | ||
3719 | ret = -EIO; | ||
3720 | goto err_reg; | ||
3721 | } | ||
3722 | |||
3723 | /* | ||
3724 | * Allocate hw (mac80211 main struct) | ||
3725 | * and hw->priv (driver private data) | ||
3726 | */ | ||
3727 | hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); | ||
3728 | if (hw == NULL) { | ||
3729 | dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); | ||
3730 | ret = -ENOMEM; | ||
3731 | goto err_map; | ||
3732 | } | ||
3733 | |||
3734 | dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); | ||
3735 | |||
3736 | sc = hw->priv; | ||
3737 | sc->hw = hw; | ||
3738 | sc->pdev = pdev; | ||
3739 | sc->dev = &pdev->dev; | ||
3740 | sc->irq = pdev->irq; | ||
3741 | sc->devid = id->device; | ||
3742 | sc->iobase = mem; /* So we can unmap it on detach */ | ||
3743 | |||
3744 | /* Initialize */ | ||
3745 | ret = ath5k_init_softc(sc, &ath_pci_bus_ops); | ||
3746 | if (ret) { | ||
3747 | goto err_free; | ||
3748 | } | ||
3749 | |||
3750 | /* Set private data */ | ||
3751 | pci_set_drvdata(pdev, hw); | ||
3752 | |||
3753 | return 0; | ||
3754 | err_free: | ||
3755 | ieee80211_free_hw(hw); | ||
3756 | err_map: | ||
3757 | pci_iounmap(pdev, mem); | ||
3758 | err_reg: | ||
3759 | pci_release_region(pdev, 0); | ||
3760 | err_dis: | ||
3761 | pci_disable_device(pdev); | ||
3762 | err: | ||
3763 | return ret; | ||
3764 | } | ||
3765 | |||
3766 | static void __devexit | ||
3767 | ath5k_pci_remove(struct pci_dev *pdev) | ||
3768 | { | ||
3769 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
3770 | struct ath5k_softc *sc = hw->priv; | ||
3771 | |||
3772 | ath5k_deinit_softc(sc); | ||
3773 | pci_iounmap(pdev, sc->iobase); | ||
3774 | pci_release_region(pdev, 0); | ||
3775 | pci_disable_device(pdev); | ||
3776 | ieee80211_free_hw(hw); | ||
3777 | } | ||
3778 | |||
3779 | #ifdef CONFIG_PM_SLEEP | ||
3780 | static int ath5k_pci_suspend(struct device *dev) | ||
3781 | { | ||
3782 | struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); | ||
3783 | |||
3784 | ath5k_led_off(sc); | ||
3785 | return 0; | ||
3786 | } | ||
3787 | |||
3788 | static int ath5k_pci_resume(struct device *dev) | ||
3789 | { | ||
3790 | struct pci_dev *pdev = to_pci_dev(dev); | ||
3791 | struct ath5k_softc *sc = pci_get_drvdata(pdev); | ||
3792 | |||
3793 | /* | ||
3794 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
3795 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
3796 | * PCI Tx retries from interfering with C3 CPU state | ||
3797 | */ | ||
3798 | pci_write_config_byte(pdev, 0x41, 0); | ||
3799 | |||
3800 | ath5k_led_enable(sc); | ||
3801 | return 0; | ||
3802 | } | ||
3803 | |||
3804 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | ||
3805 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | ||
3806 | #else | ||
3807 | #define ATH5K_PM_OPS NULL | ||
3808 | #endif /* CONFIG_PM_SLEEP */ | ||
3809 | |||
3810 | static struct pci_driver ath5k_pci_driver = { | ||
3811 | .name = KBUILD_MODNAME, | ||
3812 | .id_table = ath5k_pci_id_table, | ||
3813 | .probe = ath5k_pci_probe, | ||
3814 | .remove = __devexit_p(ath5k_pci_remove), | ||
3815 | .driver.pm = ATH5K_PM_OPS, | ||
3816 | }; | ||
3817 | |||
3818 | /* | ||
3819 | * Module init/exit functions | ||
3820 | */ | ||
3821 | static int __init | ||
3822 | init_ath5k_pci(void) | ||
3823 | { | ||
3824 | int ret; | ||
3825 | |||
3826 | ret = pci_register_driver(&ath5k_pci_driver); | ||
3827 | if (ret) { | ||
3828 | printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); | ||
3829 | return ret; | ||
3830 | } | ||
3831 | |||
3832 | return 0; | ||
3833 | } | ||
3834 | |||
3835 | static void __exit | ||
3836 | exit_ath5k_pci(void) | ||
3837 | { | ||
3838 | pci_unregister_driver(&ath5k_pci_driver); | ||
3839 | } | ||
3840 | |||
3841 | module_init(init_ath5k_pci); | ||
3842 | module_exit(exit_ath5k_pci); | ||
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c new file mode 100644 index 000000000000..9f7d3ca6ea21 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/pci.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/nl80211.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/pci-aspm.h> | ||
20 | #include "../ath.h" | ||
21 | #include "ath5k.h" | ||
22 | #include "debug.h" | ||
23 | #include "base.h" | ||
24 | #include "reg.h" | ||
25 | |||
26 | /* Known PCI ids */ | ||
27 | static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { | ||
28 | { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ | ||
29 | { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ | ||
30 | { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ | ||
31 | { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ | ||
32 | { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ | ||
33 | { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ | ||
34 | { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ | ||
35 | { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ | ||
36 | { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ | ||
37 | { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ | ||
38 | { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ | ||
39 | { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ | ||
40 | { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ | ||
41 | { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ | ||
42 | { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ | ||
43 | { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ | ||
44 | { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ | ||
45 | { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ | ||
46 | { 0 } | ||
47 | }; | ||
48 | |||
49 | /* return bus cachesize in 4B word units */ | ||
50 | static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz) | ||
51 | { | ||
52 | struct ath5k_softc *sc = (struct ath5k_softc *) common->priv; | ||
53 | u8 u8tmp; | ||
54 | |||
55 | pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp); | ||
56 | *csz = (int)u8tmp; | ||
57 | |||
58 | /* | ||
59 | * This check was put in to avoid "unplesant" consequences if | ||
60 | * the bootrom has not fully initialized all PCI devices. | ||
61 | * Sometimes the cache line size register is not set | ||
62 | */ | ||
63 | |||
64 | if (*csz == 0) | ||
65 | *csz = L1_CACHE_BYTES >> 2; /* Use the default size */ | ||
66 | } | ||
67 | |||
68 | /* Common ath_bus_opts structure */ | ||
69 | static const struct ath_bus_ops ath_pci_bus_ops = { | ||
70 | .ath_bus_type = ATH_PCI, | ||
71 | .read_cachesize = ath5k_pci_read_cachesize, | ||
72 | }; | ||
73 | |||
74 | /********************\ | ||
75 | * PCI Initialization * | ||
76 | \********************/ | ||
77 | |||
78 | static int __devinit | ||
79 | ath5k_pci_probe(struct pci_dev *pdev, | ||
80 | const struct pci_device_id *id) | ||
81 | { | ||
82 | void __iomem *mem; | ||
83 | struct ath5k_softc *sc; | ||
84 | struct ieee80211_hw *hw; | ||
85 | int ret; | ||
86 | u8 csz; | ||
87 | |||
88 | /* | ||
89 | * L0s needs to be disabled on all ath5k cards. | ||
90 | * | ||
91 | * For distributions shipping with CONFIG_PCIEASPM (this will be enabled | ||
92 | * by default in the future in 2.6.36) this will also mean both L1 and | ||
93 | * L0s will be disabled when a pre 1.1 PCIe device is detected. We do | ||
94 | * know L1 works correctly even for all ath5k pre 1.1 PCIe devices | ||
95 | * though but cannot currently undue the effect of a blacklist, for | ||
96 | * details you can read pcie_aspm_sanity_check() and see how it adjusts | ||
97 | * the device link capability. | ||
98 | * | ||
99 | * It may be possible in the future to implement some PCI API to allow | ||
100 | * drivers to override blacklists for pre 1.1 PCIe but for now it is | ||
101 | * best to accept that both L0s and L1 will be disabled completely for | ||
102 | * distributions shipping with CONFIG_PCIEASPM rather than having this | ||
103 | * issue present. Motivation for adding this new API will be to help | ||
104 | * with power consumption for some of these devices. | ||
105 | */ | ||
106 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); | ||
107 | |||
108 | ret = pci_enable_device(pdev); | ||
109 | if (ret) { | ||
110 | dev_err(&pdev->dev, "can't enable device\n"); | ||
111 | goto err; | ||
112 | } | ||
113 | |||
114 | /* XXX 32-bit addressing only */ | ||
115 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
116 | if (ret) { | ||
117 | dev_err(&pdev->dev, "32-bit DMA not available\n"); | ||
118 | goto err_dis; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Cache line size is used to size and align various | ||
123 | * structures used to communicate with the hardware. | ||
124 | */ | ||
125 | pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); | ||
126 | if (csz == 0) { | ||
127 | /* | ||
128 | * Linux 2.4.18 (at least) writes the cache line size | ||
129 | * register as a 16-bit wide register which is wrong. | ||
130 | * We must have this setup properly for rx buffer | ||
131 | * DMA to work so force a reasonable value here if it | ||
132 | * comes up zero. | ||
133 | */ | ||
134 | csz = L1_CACHE_BYTES >> 2; | ||
135 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | ||
136 | } | ||
137 | /* | ||
138 | * The default setting of latency timer yields poor results, | ||
139 | * set it to the value used by other systems. It may be worth | ||
140 | * tweaking this setting more. | ||
141 | */ | ||
142 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); | ||
143 | |||
144 | /* Enable bus mastering */ | ||
145 | pci_set_master(pdev); | ||
146 | |||
147 | /* | ||
148 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
149 | * PCI Tx retries from interfering with C3 CPU state. | ||
150 | */ | ||
151 | pci_write_config_byte(pdev, 0x41, 0); | ||
152 | |||
153 | ret = pci_request_region(pdev, 0, "ath5k"); | ||
154 | if (ret) { | ||
155 | dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); | ||
156 | goto err_dis; | ||
157 | } | ||
158 | |||
159 | mem = pci_iomap(pdev, 0, 0); | ||
160 | if (!mem) { | ||
161 | dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; | ||
162 | ret = -EIO; | ||
163 | goto err_reg; | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * Allocate hw (mac80211 main struct) | ||
168 | * and hw->priv (driver private data) | ||
169 | */ | ||
170 | hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); | ||
171 | if (hw == NULL) { | ||
172 | dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); | ||
173 | ret = -ENOMEM; | ||
174 | goto err_map; | ||
175 | } | ||
176 | |||
177 | dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); | ||
178 | |||
179 | sc = hw->priv; | ||
180 | sc->hw = hw; | ||
181 | sc->pdev = pdev; | ||
182 | sc->dev = &pdev->dev; | ||
183 | sc->irq = pdev->irq; | ||
184 | sc->devid = id->device; | ||
185 | sc->iobase = mem; /* So we can unmap it on detach */ | ||
186 | |||
187 | /* Initialize */ | ||
188 | ret = ath5k_init_softc(sc, &ath_pci_bus_ops); | ||
189 | if (ret) | ||
190 | goto err_free; | ||
191 | |||
192 | /* Set private data */ | ||
193 | pci_set_drvdata(pdev, hw); | ||
194 | |||
195 | return 0; | ||
196 | err_free: | ||
197 | ieee80211_free_hw(hw); | ||
198 | err_map: | ||
199 | pci_iounmap(pdev, mem); | ||
200 | err_reg: | ||
201 | pci_release_region(pdev, 0); | ||
202 | err_dis: | ||
203 | pci_disable_device(pdev); | ||
204 | err: | ||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static void __devexit | ||
209 | ath5k_pci_remove(struct pci_dev *pdev) | ||
210 | { | ||
211 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
212 | struct ath5k_softc *sc = hw->priv; | ||
213 | |||
214 | ath5k_deinit_softc(sc); | ||
215 | pci_iounmap(pdev, sc->iobase); | ||
216 | pci_release_region(pdev, 0); | ||
217 | pci_disable_device(pdev); | ||
218 | ieee80211_free_hw(hw); | ||
219 | } | ||
220 | |||
221 | #ifdef CONFIG_PM_SLEEP | ||
222 | static int ath5k_pci_suspend(struct device *dev) | ||
223 | { | ||
224 | struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); | ||
225 | |||
226 | ath5k_led_off(sc); | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int ath5k_pci_resume(struct device *dev) | ||
231 | { | ||
232 | struct pci_dev *pdev = to_pci_dev(dev); | ||
233 | struct ath5k_softc *sc = pci_get_drvdata(pdev); | ||
234 | |||
235 | /* | ||
236 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
237 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
238 | * PCI Tx retries from interfering with C3 CPU state | ||
239 | */ | ||
240 | pci_write_config_byte(pdev, 0x41, 0); | ||
241 | |||
242 | ath5k_led_enable(sc); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | ||
247 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | ||
248 | #else | ||
249 | #define ATH5K_PM_OPS NULL | ||
250 | #endif /* CONFIG_PM_SLEEP */ | ||
251 | |||
252 | static struct pci_driver ath5k_pci_driver = { | ||
253 | .name = KBUILD_MODNAME, | ||
254 | .id_table = ath5k_pci_id_table, | ||
255 | .probe = ath5k_pci_probe, | ||
256 | .remove = __devexit_p(ath5k_pci_remove), | ||
257 | .driver.pm = ATH5K_PM_OPS, | ||
258 | }; | ||
259 | |||
260 | /* | ||
261 | * Module init/exit functions | ||
262 | */ | ||
263 | static int __init | ||
264 | init_ath5k_pci(void) | ||
265 | { | ||
266 | int ret; | ||
267 | |||
268 | ret = pci_register_driver(&ath5k_pci_driver); | ||
269 | if (ret) { | ||
270 | printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static void __exit | ||
278 | exit_ath5k_pci(void) | ||
279 | { | ||
280 | pci_unregister_driver(&ath5k_pci_driver); | ||
281 | } | ||
282 | |||
283 | module_init(init_ath5k_pci); | ||
284 | module_exit(exit_ath5k_pci); | ||