diff options
author | David S. Miller <davem@davemloft.net> | 2012-02-21 17:47:33 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-02-21 17:47:33 -0500 |
commit | 4b0d1a0b1fd7248d0fc341d00ed908c7373c7788 (patch) | |
tree | 7ba1dad63482c9a3d4461ec324aef9f909e73f49 | |
parent | 8de65c2aaa1faf8e57e1b29b4265b6a57fae4136 (diff) | |
parent | a9802d43f205faa2fff422502a1336a50b9615c3 (diff) |
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
141 files changed, 7962 insertions, 6096 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 2014155c899d..c5ac6929c41c 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl | |||
@@ -129,7 +129,6 @@ | |||
129 | !Finclude/net/cfg80211.h cfg80211_pmksa | 129 | !Finclude/net/cfg80211.h cfg80211_pmksa |
130 | !Finclude/net/cfg80211.h cfg80211_send_rx_auth | 130 | !Finclude/net/cfg80211.h cfg80211_send_rx_auth |
131 | !Finclude/net/cfg80211.h cfg80211_send_auth_timeout | 131 | !Finclude/net/cfg80211.h cfg80211_send_auth_timeout |
132 | !Finclude/net/cfg80211.h __cfg80211_auth_canceled | ||
133 | !Finclude/net/cfg80211.h cfg80211_send_rx_assoc | 132 | !Finclude/net/cfg80211.h cfg80211_send_rx_assoc |
134 | !Finclude/net/cfg80211.h cfg80211_send_assoc_timeout | 133 | !Finclude/net/cfg80211.h cfg80211_send_assoc_timeout |
135 | !Finclude/net/cfg80211.h cfg80211_send_deauth | 134 | !Finclude/net/cfg80211.h cfg80211_send_deauth |
diff --git a/MAINTAINERS b/MAINTAINERS index 5f540bb733ce..ed48d55662c1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4914,8 +4914,6 @@ F: fs/ocfs2/ | |||
4914 | 4914 | ||
4915 | ORINOCO DRIVER | 4915 | ORINOCO DRIVER |
4916 | L: linux-wireless@vger.kernel.org | 4916 | L: linux-wireless@vger.kernel.org |
4917 | L: orinoco-users@lists.sourceforge.net | ||
4918 | L: orinoco-devel@lists.sourceforge.net | ||
4919 | W: http://linuxwireless.org/en/users/Drivers/orinoco | 4917 | W: http://linuxwireless.org/en/users/Drivers/orinoco |
4920 | W: http://www.nongnu.org/orinoco/ | 4918 | W: http://www.nongnu.org/orinoco/ |
4921 | S: Orphan | 4919 | S: Orphan |
diff --git a/arch/mips/pci/pci-bcm47xx.c b/arch/mips/pci/pci-bcm47xx.c index 400535a955d0..c682468010c5 100644 --- a/arch/mips/pci/pci-bcm47xx.c +++ b/arch/mips/pci/pci-bcm47xx.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/ssb/ssb.h> | 27 | #include <linux/ssb/ssb.h> |
28 | #include <linux/bcma/bcma.h> | ||
28 | #include <bcm47xx.h> | 29 | #include <bcm47xx.h> |
29 | 30 | ||
30 | int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | 31 | int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
@@ -32,15 +33,12 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | |||
32 | return 0; | 33 | return 0; |
33 | } | 34 | } |
34 | 35 | ||
35 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
36 | { | ||
37 | #ifdef CONFIG_BCM47XX_SSB | 36 | #ifdef CONFIG_BCM47XX_SSB |
37 | static int bcm47xx_pcibios_plat_dev_init_ssb(struct pci_dev *dev) | ||
38 | { | ||
38 | int res; | 39 | int res; |
39 | u8 slot, pin; | 40 | u8 slot, pin; |
40 | 41 | ||
41 | if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB) | ||
42 | return 0; | ||
43 | |||
44 | res = ssb_pcibios_plat_dev_init(dev); | 42 | res = ssb_pcibios_plat_dev_init(dev); |
45 | if (res < 0) { | 43 | if (res < 0) { |
46 | printk(KERN_ALERT "PCI: Failed to init device %s\n", | 44 | printk(KERN_ALERT "PCI: Failed to init device %s\n", |
@@ -60,6 +58,47 @@ int pcibios_plat_dev_init(struct pci_dev *dev) | |||
60 | } | 58 | } |
61 | 59 | ||
62 | dev->irq = res; | 60 | dev->irq = res; |
61 | return 0; | ||
62 | } | ||
63 | #endif | 63 | #endif |
64 | |||
65 | #ifdef CONFIG_BCM47XX_BCMA | ||
66 | static int bcm47xx_pcibios_plat_dev_init_bcma(struct pci_dev *dev) | ||
67 | { | ||
68 | int res; | ||
69 | |||
70 | res = bcma_core_pci_plat_dev_init(dev); | ||
71 | if (res < 0) { | ||
72 | printk(KERN_ALERT "PCI: Failed to init device %s\n", | ||
73 | pci_name(dev)); | ||
74 | return res; | ||
75 | } | ||
76 | |||
77 | res = bcma_core_pci_pcibios_map_irq(dev); | ||
78 | |||
79 | /* IRQ-0 and IRQ-1 are software interrupts. */ | ||
80 | if (res < 2) { | ||
81 | printk(KERN_ALERT "PCI: Failed to map IRQ of device %s\n", | ||
82 | pci_name(dev)); | ||
83 | return res; | ||
84 | } | ||
85 | |||
86 | dev->irq = res; | ||
64 | return 0; | 87 | return 0; |
65 | } | 88 | } |
89 | #endif | ||
90 | |||
91 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
92 | { | ||
93 | #ifdef CONFIG_BCM47XX_SSB | ||
94 | if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_SSB) | ||
95 | return bcm47xx_pcibios_plat_dev_init_ssb(dev); | ||
96 | else | ||
97 | #endif | ||
98 | #ifdef CONFIG_BCM47XX_BCMA | ||
99 | if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) | ||
100 | return bcm47xx_pcibios_plat_dev_init_bcma(dev); | ||
101 | else | ||
102 | #endif | ||
103 | return 0; | ||
104 | } | ||
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 0def898a1d15..b81755bb4798 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -13,7 +13,7 @@ | |||
13 | struct bcma_bus; | 13 | struct bcma_bus; |
14 | 14 | ||
15 | /* main.c */ | 15 | /* main.c */ |
16 | int bcma_bus_register(struct bcma_bus *bus); | 16 | int __devinit bcma_bus_register(struct bcma_bus *bus); |
17 | void bcma_bus_unregister(struct bcma_bus *bus); | 17 | void bcma_bus_unregister(struct bcma_bus *bus); |
18 | int __init bcma_bus_early_register(struct bcma_bus *bus, | 18 | int __init bcma_bus_early_register(struct bcma_bus *bus, |
19 | struct bcma_device *core_cc, | 19 | struct bcma_device *core_cc, |
@@ -48,8 +48,12 @@ extern int __init bcma_host_pci_init(void); | |||
48 | extern void __exit bcma_host_pci_exit(void); | 48 | extern void __exit bcma_host_pci_exit(void); |
49 | #endif /* CONFIG_BCMA_HOST_PCI */ | 49 | #endif /* CONFIG_BCMA_HOST_PCI */ |
50 | 50 | ||
51 | /* driver_pci.c */ | ||
52 | u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); | ||
53 | |||
51 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | 54 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE |
52 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); | 55 | bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); |
56 | void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); | ||
53 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ | 57 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ |
54 | 58 | ||
55 | #endif | 59 | #endif |
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index 4fde6254f04e..4d38ae179b48 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c | |||
@@ -2,8 +2,9 @@ | |||
2 | * Broadcom specific AMBA | 2 | * Broadcom specific AMBA |
3 | * PCI Core | 3 | * PCI Core |
4 | * | 4 | * |
5 | * Copyright 2005, Broadcom Corporation | 5 | * Copyright 2005, 2011, Broadcom Corporation |
6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> | 6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> |
7 | * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
7 | * | 8 | * |
8 | * Licensed under the GNU/GPL. See COPYING for details. | 9 | * Licensed under the GNU/GPL. See COPYING for details. |
9 | */ | 10 | */ |
@@ -16,40 +17,41 @@ | |||
16 | * R/W ops. | 17 | * R/W ops. |
17 | **************************************************/ | 18 | **************************************************/ |
18 | 19 | ||
19 | static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) | 20 | u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) |
20 | { | 21 | { |
21 | pcicore_write32(pc, 0x130, address); | 22 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address); |
22 | pcicore_read32(pc, 0x130); | 23 | pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR); |
23 | return pcicore_read32(pc, 0x134); | 24 | return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA); |
24 | } | 25 | } |
25 | 26 | ||
26 | #if 0 | 27 | #if 0 |
27 | static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) | 28 | static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) |
28 | { | 29 | { |
29 | pcicore_write32(pc, 0x130, address); | 30 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address); |
30 | pcicore_read32(pc, 0x130); | 31 | pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR); |
31 | pcicore_write32(pc, 0x134, data); | 32 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data); |
32 | } | 33 | } |
33 | #endif | 34 | #endif |
34 | 35 | ||
35 | static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) | 36 | static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) |
36 | { | 37 | { |
37 | const u16 mdio_control = 0x128; | ||
38 | const u16 mdio_data = 0x12C; | ||
39 | u32 v; | 38 | u32 v; |
40 | int i; | 39 | int i; |
41 | 40 | ||
42 | v = (1 << 30); /* Start of Transaction */ | 41 | v = BCMA_CORE_PCI_MDIODATA_START; |
43 | v |= (1 << 28); /* Write Transaction */ | 42 | v |= BCMA_CORE_PCI_MDIODATA_WRITE; |
44 | v |= (1 << 17); /* Turnaround */ | 43 | v |= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR << |
45 | v |= (0x1F << 18); | 44 | BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF); |
45 | v |= (BCMA_CORE_PCI_MDIODATA_BLK_ADDR << | ||
46 | BCMA_CORE_PCI_MDIODATA_REGADDR_SHF); | ||
47 | v |= BCMA_CORE_PCI_MDIODATA_TA; | ||
46 | v |= (phy << 4); | 48 | v |= (phy << 4); |
47 | pcicore_write32(pc, mdio_data, v); | 49 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v); |
48 | 50 | ||
49 | udelay(10); | 51 | udelay(10); |
50 | for (i = 0; i < 200; i++) { | 52 | for (i = 0; i < 200; i++) { |
51 | v = pcicore_read32(pc, mdio_control); | 53 | v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); |
52 | if (v & 0x100 /* Trans complete */) | 54 | if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) |
53 | break; | 55 | break; |
54 | msleep(1); | 56 | msleep(1); |
55 | } | 57 | } |
@@ -57,79 +59,84 @@ static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) | |||
57 | 59 | ||
58 | static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) | 60 | static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) |
59 | { | 61 | { |
60 | const u16 mdio_control = 0x128; | ||
61 | const u16 mdio_data = 0x12C; | ||
62 | int max_retries = 10; | 62 | int max_retries = 10; |
63 | u16 ret = 0; | 63 | u16 ret = 0; |
64 | u32 v; | 64 | u32 v; |
65 | int i; | 65 | int i; |
66 | 66 | ||
67 | v = 0x80; /* Enable Preamble Sequence */ | 67 | /* enable mdio access to SERDES */ |
68 | v |= 0x2; /* MDIO Clock Divisor */ | 68 | v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN; |
69 | pcicore_write32(pc, mdio_control, v); | 69 | v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL; |
70 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v); | ||
70 | 71 | ||
71 | if (pc->core->id.rev >= 10) { | 72 | if (pc->core->id.rev >= 10) { |
72 | max_retries = 200; | 73 | max_retries = 200; |
73 | bcma_pcie_mdio_set_phy(pc, device); | 74 | bcma_pcie_mdio_set_phy(pc, device); |
75 | v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR << | ||
76 | BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF); | ||
77 | v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF); | ||
78 | } else { | ||
79 | v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD); | ||
80 | v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); | ||
74 | } | 81 | } |
75 | 82 | ||
76 | v = (1 << 30); /* Start of Transaction */ | 83 | v = BCMA_CORE_PCI_MDIODATA_START; |
77 | v |= (1 << 29); /* Read Transaction */ | 84 | v |= BCMA_CORE_PCI_MDIODATA_READ; |
78 | v |= (1 << 17); /* Turnaround */ | 85 | v |= BCMA_CORE_PCI_MDIODATA_TA; |
79 | if (pc->core->id.rev < 10) | 86 | |
80 | v |= (u32)device << 22; | 87 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v); |
81 | v |= (u32)address << 18; | ||
82 | pcicore_write32(pc, mdio_data, v); | ||
83 | /* Wait for the device to complete the transaction */ | 88 | /* Wait for the device to complete the transaction */ |
84 | udelay(10); | 89 | udelay(10); |
85 | for (i = 0; i < max_retries; i++) { | 90 | for (i = 0; i < max_retries; i++) { |
86 | v = pcicore_read32(pc, mdio_control); | 91 | v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); |
87 | if (v & 0x100 /* Trans complete */) { | 92 | if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) { |
88 | udelay(10); | 93 | udelay(10); |
89 | ret = pcicore_read32(pc, mdio_data); | 94 | ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA); |
90 | break; | 95 | break; |
91 | } | 96 | } |
92 | msleep(1); | 97 | msleep(1); |
93 | } | 98 | } |
94 | pcicore_write32(pc, mdio_control, 0); | 99 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); |
95 | return ret; | 100 | return ret; |
96 | } | 101 | } |
97 | 102 | ||
98 | static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, | 103 | static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, |
99 | u8 address, u16 data) | 104 | u8 address, u16 data) |
100 | { | 105 | { |
101 | const u16 mdio_control = 0x128; | ||
102 | const u16 mdio_data = 0x12C; | ||
103 | int max_retries = 10; | 106 | int max_retries = 10; |
104 | u32 v; | 107 | u32 v; |
105 | int i; | 108 | int i; |
106 | 109 | ||
107 | v = 0x80; /* Enable Preamble Sequence */ | 110 | /* enable mdio access to SERDES */ |
108 | v |= 0x2; /* MDIO Clock Divisor */ | 111 | v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN; |
109 | pcicore_write32(pc, mdio_control, v); | 112 | v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL; |
113 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v); | ||
110 | 114 | ||
111 | if (pc->core->id.rev >= 10) { | 115 | if (pc->core->id.rev >= 10) { |
112 | max_retries = 200; | 116 | max_retries = 200; |
113 | bcma_pcie_mdio_set_phy(pc, device); | 117 | bcma_pcie_mdio_set_phy(pc, device); |
118 | v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR << | ||
119 | BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF); | ||
120 | v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF); | ||
121 | } else { | ||
122 | v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD); | ||
123 | v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); | ||
114 | } | 124 | } |
115 | 125 | ||
116 | v = (1 << 30); /* Start of Transaction */ | 126 | v = BCMA_CORE_PCI_MDIODATA_START; |
117 | v |= (1 << 28); /* Write Transaction */ | 127 | v |= BCMA_CORE_PCI_MDIODATA_WRITE; |
118 | v |= (1 << 17); /* Turnaround */ | 128 | v |= BCMA_CORE_PCI_MDIODATA_TA; |
119 | if (pc->core->id.rev < 10) | ||
120 | v |= (u32)device << 22; | ||
121 | v |= (u32)address << 18; | ||
122 | v |= data; | 129 | v |= data; |
123 | pcicore_write32(pc, mdio_data, v); | 130 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v); |
124 | /* Wait for the device to complete the transaction */ | 131 | /* Wait for the device to complete the transaction */ |
125 | udelay(10); | 132 | udelay(10); |
126 | for (i = 0; i < max_retries; i++) { | 133 | for (i = 0; i < max_retries; i++) { |
127 | v = pcicore_read32(pc, mdio_control); | 134 | v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); |
128 | if (v & 0x100 /* Trans complete */) | 135 | if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) |
129 | break; | 136 | break; |
130 | msleep(1); | 137 | msleep(1); |
131 | } | 138 | } |
132 | pcicore_write32(pc, mdio_control, 0); | 139 | pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); |
133 | } | 140 | } |
134 | 141 | ||
135 | /************************************************** | 142 | /************************************************** |
@@ -138,72 +145,53 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, | |||
138 | 145 | ||
139 | static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) | 146 | static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) |
140 | { | 147 | { |
141 | return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; | 148 | u32 tmp; |
149 | |||
150 | tmp = bcma_pcie_read(pc, BCMA_CORE_PCI_PLP_STATUSREG); | ||
151 | if (tmp & BCMA_CORE_PCI_PLP_POLARITYINV_STAT) | ||
152 | return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE | | ||
153 | BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY; | ||
154 | else | ||
155 | return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE; | ||
142 | } | 156 | } |
143 | 157 | ||
144 | static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) | 158 | static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) |
145 | { | 159 | { |
146 | const u8 serdes_pll_device = 0x1D; | ||
147 | const u8 serdes_rx_device = 0x1F; | ||
148 | u16 tmp; | 160 | u16 tmp; |
149 | 161 | ||
150 | bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, | 162 | bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_RX, |
151 | bcma_pcicore_polarity_workaround(pc)); | 163 | BCMA_CORE_PCI_SERDES_RX_CTRL, |
152 | tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); | 164 | bcma_pcicore_polarity_workaround(pc)); |
153 | if (tmp & 0x4000) | 165 | tmp = bcma_pcie_mdio_read(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL, |
154 | bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); | 166 | BCMA_CORE_PCI_SERDES_PLL_CTRL); |
167 | if (tmp & BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN) | ||
168 | bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL, | ||
169 | BCMA_CORE_PCI_SERDES_PLL_CTRL, | ||
170 | tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); | ||
155 | } | 171 | } |
156 | 172 | ||
157 | /************************************************** | 173 | /************************************************** |
158 | * Init. | 174 | * Init. |
159 | **************************************************/ | 175 | **************************************************/ |
160 | 176 | ||
161 | static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) | 177 | static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) |
162 | { | 178 | { |
163 | bcma_pcicore_serdes_workaround(pc); | 179 | bcma_pcicore_serdes_workaround(pc); |
164 | } | 180 | } |
165 | 181 | ||
166 | static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) | 182 | void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) |
167 | { | ||
168 | struct bcma_bus *bus = pc->core->bus; | ||
169 | u16 chipid_top; | ||
170 | |||
171 | chipid_top = (bus->chipinfo.id & 0xFF00); | ||
172 | if (chipid_top != 0x4700 && | ||
173 | chipid_top != 0x5300) | ||
174 | return false; | ||
175 | |||
176 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
177 | if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI) | ||
178 | return false; | ||
179 | #endif /* CONFIG_SSB_DRIVER_PCICORE */ | ||
180 | |||
181 | #if 0 | ||
182 | /* TODO: on BCMA we use address from EROM instead of magic formula */ | ||
183 | u32 tmp; | ||
184 | return !mips_busprobe32(tmp, (bus->mmio + | ||
185 | (pc->core->core_index * BCMA_CORE_SIZE))); | ||
186 | #endif | ||
187 | |||
188 | return true; | ||
189 | } | ||
190 | |||
191 | void bcma_core_pci_init(struct bcma_drv_pci *pc) | ||
192 | { | 183 | { |
193 | if (pc->setup_done) | 184 | if (pc->setup_done) |
194 | return; | 185 | return; |
195 | 186 | ||
196 | if (bcma_core_pci_is_in_hostmode(pc)) { | ||
197 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | 187 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE |
188 | pc->hostmode = bcma_core_pci_is_in_hostmode(pc); | ||
189 | if (pc->hostmode) | ||
198 | bcma_core_pci_hostmode_init(pc); | 190 | bcma_core_pci_hostmode_init(pc); |
199 | #else | ||
200 | pr_err("Driver compiled without support for hostmode PCI\n"); | ||
201 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ | 191 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ |
202 | } else { | ||
203 | bcma_core_pci_clientmode_init(pc); | ||
204 | } | ||
205 | 192 | ||
206 | pc->setup_done = true; | 193 | if (!pc->hostmode) |
194 | bcma_core_pci_clientmode_init(pc); | ||
207 | } | 195 | } |
208 | 196 | ||
209 | int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, | 197 | int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, |
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index eb332b75ce83..4e20bcfa7ec5 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -2,13 +2,587 @@ | |||
2 | * Broadcom specific AMBA | 2 | * Broadcom specific AMBA |
3 | * PCI Core in hostmode | 3 | * PCI Core in hostmode |
4 | * | 4 | * |
5 | * Copyright 2005 - 2011, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> | ||
7 | * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
8 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | 9 | * Licensed under the GNU/GPL. See COPYING for details. |
6 | */ | 10 | */ |
7 | 11 | ||
8 | #include "bcma_private.h" | 12 | #include "bcma_private.h" |
13 | #include <linux/export.h> | ||
9 | #include <linux/bcma/bcma.h> | 14 | #include <linux/bcma/bcma.h> |
15 | #include <asm/paccess.h> | ||
16 | |||
17 | /* Probe a 32bit value on the bus and catch bus exceptions. | ||
18 | * Returns nonzero on a bus exception. | ||
19 | * This is MIPS specific */ | ||
20 | #define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr))) | ||
21 | |||
22 | /* Assume one-hot slot wiring */ | ||
23 | #define BCMA_PCI_SLOT_MAX 16 | ||
24 | #define PCI_CONFIG_SPACE_SIZE 256 | ||
25 | |||
26 | bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) | ||
27 | { | ||
28 | struct bcma_bus *bus = pc->core->bus; | ||
29 | u16 chipid_top; | ||
30 | u32 tmp; | ||
31 | |||
32 | chipid_top = (bus->chipinfo.id & 0xFF00); | ||
33 | if (chipid_top != 0x4700 && | ||
34 | chipid_top != 0x5300) | ||
35 | return false; | ||
36 | |||
37 | if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { | ||
38 | pr_info("This PCI core is disabled and not working\n"); | ||
39 | return false; | ||
40 | } | ||
41 | |||
42 | bcma_core_enable(pc->core, 0); | ||
43 | |||
44 | return !mips_busprobe32(tmp, pc->core->io_addr); | ||
45 | } | ||
46 | |||
47 | static u32 bcma_pcie_read_config(struct bcma_drv_pci *pc, u32 address) | ||
48 | { | ||
49 | pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); | ||
50 | pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); | ||
51 | return pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_DATA); | ||
52 | } | ||
53 | |||
54 | static void bcma_pcie_write_config(struct bcma_drv_pci *pc, u32 address, | ||
55 | u32 data) | ||
56 | { | ||
57 | pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); | ||
58 | pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); | ||
59 | pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_DATA, data); | ||
60 | } | ||
61 | |||
62 | static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev, | ||
63 | unsigned int func, unsigned int off) | ||
64 | { | ||
65 | u32 addr = 0; | ||
66 | |||
67 | /* Issue config commands only when the data link is up (atleast | ||
68 | * one external pcie device is present). | ||
69 | */ | ||
70 | if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG) | ||
71 | & BCMA_CORE_PCI_DLLP_LSREG_LINKUP)) | ||
72 | goto out; | ||
73 | |||
74 | /* Type 0 transaction */ | ||
75 | /* Slide the PCI window to the appropriate slot */ | ||
76 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); | ||
77 | /* Calculate the address */ | ||
78 | addr = pc->host_controller->host_cfg_addr; | ||
79 | addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT); | ||
80 | addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT); | ||
81 | addr |= (off & ~3); | ||
82 | |||
83 | out: | ||
84 | return addr; | ||
85 | } | ||
10 | 86 | ||
11 | void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | 87 | static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, |
88 | unsigned int func, unsigned int off, | ||
89 | void *buf, int len) | ||
12 | { | 90 | { |
13 | pr_err("No support for PCI core in hostmode yet\n"); | 91 | int err = -EINVAL; |
92 | u32 addr, val; | ||
93 | void __iomem *mmio = 0; | ||
94 | |||
95 | WARN_ON(!pc->hostmode); | ||
96 | if (unlikely(len != 1 && len != 2 && len != 4)) | ||
97 | goto out; | ||
98 | if (dev == 0) { | ||
99 | /* we support only two functions on device 0 */ | ||
100 | if (func > 1) | ||
101 | return -EINVAL; | ||
102 | |||
103 | /* accesses to config registers with offsets >= 256 | ||
104 | * requires indirect access. | ||
105 | */ | ||
106 | if (off >= PCI_CONFIG_SPACE_SIZE) { | ||
107 | addr = (func << 12); | ||
108 | addr |= (off & 0x0FFF); | ||
109 | val = bcma_pcie_read_config(pc, addr); | ||
110 | } else { | ||
111 | addr = BCMA_CORE_PCI_PCICFG0; | ||
112 | addr |= (func << 8); | ||
113 | addr |= (off & 0xfc); | ||
114 | val = pcicore_read32(pc, addr); | ||
115 | } | ||
116 | } else { | ||
117 | addr = bcma_get_cfgspace_addr(pc, dev, func, off); | ||
118 | if (unlikely(!addr)) | ||
119 | goto out; | ||
120 | err = -ENOMEM; | ||
121 | mmio = ioremap_nocache(addr, len); | ||
122 | if (!mmio) | ||
123 | goto out; | ||
124 | |||
125 | if (mips_busprobe32(val, mmio)) { | ||
126 | val = 0xffffffff; | ||
127 | goto unmap; | ||
128 | } | ||
129 | |||
130 | val = readl(mmio); | ||
131 | } | ||
132 | val >>= (8 * (off & 3)); | ||
133 | |||
134 | switch (len) { | ||
135 | case 1: | ||
136 | *((u8 *)buf) = (u8)val; | ||
137 | break; | ||
138 | case 2: | ||
139 | *((u16 *)buf) = (u16)val; | ||
140 | break; | ||
141 | case 4: | ||
142 | *((u32 *)buf) = (u32)val; | ||
143 | break; | ||
144 | } | ||
145 | err = 0; | ||
146 | unmap: | ||
147 | if (mmio) | ||
148 | iounmap(mmio); | ||
149 | out: | ||
150 | return err; | ||
151 | } | ||
152 | |||
153 | static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | ||
154 | unsigned int func, unsigned int off, | ||
155 | const void *buf, int len) | ||
156 | { | ||
157 | int err = -EINVAL; | ||
158 | u32 addr = 0, val = 0; | ||
159 | void __iomem *mmio = 0; | ||
160 | u16 chipid = pc->core->bus->chipinfo.id; | ||
161 | |||
162 | WARN_ON(!pc->hostmode); | ||
163 | if (unlikely(len != 1 && len != 2 && len != 4)) | ||
164 | goto out; | ||
165 | if (dev == 0) { | ||
166 | /* accesses to config registers with offsets >= 256 | ||
167 | * requires indirect access. | ||
168 | */ | ||
169 | if (off < PCI_CONFIG_SPACE_SIZE) { | ||
170 | addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; | ||
171 | addr |= (func << 8); | ||
172 | addr |= (off & 0xfc); | ||
173 | mmio = ioremap_nocache(addr, len); | ||
174 | if (!mmio) | ||
175 | goto out; | ||
176 | } | ||
177 | } else { | ||
178 | addr = bcma_get_cfgspace_addr(pc, dev, func, off); | ||
179 | if (unlikely(!addr)) | ||
180 | goto out; | ||
181 | err = -ENOMEM; | ||
182 | mmio = ioremap_nocache(addr, len); | ||
183 | if (!mmio) | ||
184 | goto out; | ||
185 | |||
186 | if (mips_busprobe32(val, mmio)) { | ||
187 | val = 0xffffffff; | ||
188 | goto unmap; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | switch (len) { | ||
193 | case 1: | ||
194 | val = readl(mmio); | ||
195 | val &= ~(0xFF << (8 * (off & 3))); | ||
196 | val |= *((const u8 *)buf) << (8 * (off & 3)); | ||
197 | break; | ||
198 | case 2: | ||
199 | val = readl(mmio); | ||
200 | val &= ~(0xFFFF << (8 * (off & 3))); | ||
201 | val |= *((const u16 *)buf) << (8 * (off & 3)); | ||
202 | break; | ||
203 | case 4: | ||
204 | val = *((const u32 *)buf); | ||
205 | break; | ||
206 | } | ||
207 | if (dev == 0 && !addr) { | ||
208 | /* accesses to config registers with offsets >= 256 | ||
209 | * requires indirect access. | ||
210 | */ | ||
211 | addr = (func << 12); | ||
212 | addr |= (off & 0x0FFF); | ||
213 | bcma_pcie_write_config(pc, addr, val); | ||
214 | } else { | ||
215 | writel(val, mmio); | ||
216 | |||
217 | if (chipid == 0x4716 || chipid == 0x4748) | ||
218 | readl(mmio); | ||
219 | } | ||
220 | |||
221 | err = 0; | ||
222 | unmap: | ||
223 | if (mmio) | ||
224 | iounmap(mmio); | ||
225 | out: | ||
226 | return err; | ||
227 | } | ||
228 | |||
229 | static int bcma_core_pci_hostmode_read_config(struct pci_bus *bus, | ||
230 | unsigned int devfn, | ||
231 | int reg, int size, u32 *val) | ||
232 | { | ||
233 | unsigned long flags; | ||
234 | int err; | ||
235 | struct bcma_drv_pci *pc; | ||
236 | struct bcma_drv_pci_host *pc_host; | ||
237 | |||
238 | pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); | ||
239 | pc = pc_host->pdev; | ||
240 | |||
241 | spin_lock_irqsave(&pc_host->cfgspace_lock, flags); | ||
242 | err = bcma_extpci_read_config(pc, PCI_SLOT(devfn), | ||
243 | PCI_FUNC(devfn), reg, val, size); | ||
244 | spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); | ||
245 | |||
246 | return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
247 | } | ||
248 | |||
249 | static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus, | ||
250 | unsigned int devfn, | ||
251 | int reg, int size, u32 val) | ||
252 | { | ||
253 | unsigned long flags; | ||
254 | int err; | ||
255 | struct bcma_drv_pci *pc; | ||
256 | struct bcma_drv_pci_host *pc_host; | ||
257 | |||
258 | pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); | ||
259 | pc = pc_host->pdev; | ||
260 | |||
261 | spin_lock_irqsave(&pc_host->cfgspace_lock, flags); | ||
262 | err = bcma_extpci_write_config(pc, PCI_SLOT(devfn), | ||
263 | PCI_FUNC(devfn), reg, &val, size); | ||
264 | spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); | ||
265 | |||
266 | return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
267 | } | ||
268 | |||
269 | /* return cap_offset if requested capability exists in the PCI config space */ | ||
270 | static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc, | ||
271 | unsigned int dev, | ||
272 | unsigned int func, u8 req_cap_id, | ||
273 | unsigned char *buf, u32 *buflen) | ||
274 | { | ||
275 | u8 cap_id; | ||
276 | u8 cap_ptr = 0; | ||
277 | u32 bufsize; | ||
278 | u8 byte_val; | ||
279 | |||
280 | /* check for Header type 0 */ | ||
281 | bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, | ||
282 | sizeof(u8)); | ||
283 | if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) | ||
284 | return cap_ptr; | ||
285 | |||
286 | /* check if the capability pointer field exists */ | ||
287 | bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val, | ||
288 | sizeof(u8)); | ||
289 | if (!(byte_val & PCI_STATUS_CAP_LIST)) | ||
290 | return cap_ptr; | ||
291 | |||
292 | /* check if the capability pointer is 0x00 */ | ||
293 | bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr, | ||
294 | sizeof(u8)); | ||
295 | if (cap_ptr == 0x00) | ||
296 | return cap_ptr; | ||
297 | |||
298 | /* loop thr'u the capability list and see if the requested capabilty | ||
299 | * exists */ | ||
300 | bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8)); | ||
301 | while (cap_id != req_cap_id) { | ||
302 | bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr, | ||
303 | sizeof(u8)); | ||
304 | if (cap_ptr == 0x00) | ||
305 | return cap_ptr; | ||
306 | bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, | ||
307 | sizeof(u8)); | ||
308 | } | ||
309 | |||
310 | /* found the caller requested capability */ | ||
311 | if ((buf != NULL) && (buflen != NULL)) { | ||
312 | u8 cap_data; | ||
313 | |||
314 | bufsize = *buflen; | ||
315 | if (!bufsize) | ||
316 | return cap_ptr; | ||
317 | |||
318 | *buflen = 0; | ||
319 | |||
320 | /* copy the cpability data excluding cap ID and next ptr */ | ||
321 | cap_data = cap_ptr + 2; | ||
322 | if ((bufsize + cap_data) > PCI_CONFIG_SPACE_SIZE) | ||
323 | bufsize = PCI_CONFIG_SPACE_SIZE - cap_data; | ||
324 | *buflen = bufsize; | ||
325 | while (bufsize--) { | ||
326 | bcma_extpci_read_config(pc, dev, func, cap_data, buf, | ||
327 | sizeof(u8)); | ||
328 | cap_data++; | ||
329 | buf++; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | return cap_ptr; | ||
334 | } | ||
335 | |||
336 | /* If the root port is capable of returning Config Request | ||
337 | * Retry Status (CRS) Completion Status to software then | ||
338 | * enable the feature. | ||
339 | */ | ||
340 | static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc) | ||
341 | { | ||
342 | u8 cap_ptr, root_ctrl, root_cap, dev; | ||
343 | u16 val16; | ||
344 | int i; | ||
345 | |||
346 | cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL, | ||
347 | NULL); | ||
348 | root_cap = cap_ptr + PCI_EXP_RTCAP; | ||
349 | bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16)); | ||
350 | if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) { | ||
351 | /* Enable CRS software visibility */ | ||
352 | root_ctrl = cap_ptr + PCI_EXP_RTCTL; | ||
353 | val16 = PCI_EXP_RTCTL_CRSSVE; | ||
354 | bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16, | ||
355 | sizeof(u16)); | ||
356 | |||
357 | /* Initiate a configuration request to read the vendor id | ||
358 | * field of the device function's config space header after | ||
359 | * 100 ms wait time from the end of Reset. If the device is | ||
360 | * not done with its internal initialization, it must at | ||
361 | * least return a completion TLP, with a completion status | ||
362 | * of "Configuration Request Retry Status (CRS)". The root | ||
363 | * complex must complete the request to the host by returning | ||
364 | * a read-data value of 0001h for the Vendor ID field and | ||
365 | * all 1s for any additional bytes included in the request. | ||
366 | * Poll using the config reads for max wait time of 1 sec or | ||
367 | * until we receive the successful completion status. Repeat | ||
368 | * the procedure for all the devices. | ||
369 | */ | ||
370 | for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) { | ||
371 | for (i = 0; i < 100000; i++) { | ||
372 | bcma_extpci_read_config(pc, dev, 0, | ||
373 | PCI_VENDOR_ID, &val16, | ||
374 | sizeof(val16)); | ||
375 | if (val16 != 0x1) | ||
376 | break; | ||
377 | udelay(10); | ||
378 | } | ||
379 | if (val16 == 0x1) | ||
380 | pr_err("PCI: Broken device in slot %d\n", dev); | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | |||
385 | void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | ||
386 | { | ||
387 | struct bcma_bus *bus = pc->core->bus; | ||
388 | struct bcma_drv_pci_host *pc_host; | ||
389 | u32 tmp; | ||
390 | u32 pci_membase_1G; | ||
391 | unsigned long io_map_base; | ||
392 | |||
393 | pr_info("PCIEcore in host mode found\n"); | ||
394 | |||
395 | pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); | ||
396 | if (!pc_host) { | ||
397 | pr_err("can not allocate memory"); | ||
398 | return; | ||
399 | } | ||
400 | |||
401 | pc->host_controller = pc_host; | ||
402 | pc_host->pci_controller.io_resource = &pc_host->io_resource; | ||
403 | pc_host->pci_controller.mem_resource = &pc_host->mem_resource; | ||
404 | pc_host->pci_controller.pci_ops = &pc_host->pci_ops; | ||
405 | pc_host->pdev = pc; | ||
406 | |||
407 | pci_membase_1G = BCMA_SOC_PCI_DMA; | ||
408 | pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG; | ||
409 | |||
410 | pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config; | ||
411 | pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config; | ||
412 | |||
413 | pc_host->mem_resource.name = "BCMA PCIcore external memory", | ||
414 | pc_host->mem_resource.start = BCMA_SOC_PCI_DMA; | ||
415 | pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1; | ||
416 | pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED; | ||
417 | |||
418 | pc_host->io_resource.name = "BCMA PCIcore external I/O", | ||
419 | pc_host->io_resource.start = 0x100; | ||
420 | pc_host->io_resource.end = 0x7FF; | ||
421 | pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; | ||
422 | |||
423 | /* Reset RC */ | ||
424 | udelay(3000); | ||
425 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); | ||
426 | udelay(1000); | ||
427 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | | ||
428 | BCMA_CORE_PCI_CTL_RST_OE); | ||
429 | |||
430 | /* 64 MB I/O access window. On 4716, use | ||
431 | * sbtopcie0 to access the device registers. We | ||
432 | * can't use address match 2 (1 GB window) region | ||
433 | * as mips can't generate 64-bit address on the | ||
434 | * backplane. | ||
435 | */ | ||
436 | if (bus->chipinfo.id == 0x4716 || bus->chipinfo.id == 0x4748) { | ||
437 | pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; | ||
438 | pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + | ||
439 | BCMA_SOC_PCI_MEM_SZ - 1; | ||
440 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | ||
441 | BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM); | ||
442 | } else if (bus->chipinfo.id == 0x5300) { | ||
443 | tmp = BCMA_CORE_PCI_SBTOPCI_MEM; | ||
444 | tmp |= BCMA_CORE_PCI_SBTOPCI_PREF; | ||
445 | tmp |= BCMA_CORE_PCI_SBTOPCI_BURST; | ||
446 | if (pc->core->core_unit == 0) { | ||
447 | pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; | ||
448 | pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + | ||
449 | BCMA_SOC_PCI_MEM_SZ - 1; | ||
450 | pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; | ||
451 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | ||
452 | tmp | BCMA_SOC_PCI_MEM); | ||
453 | } else if (pc->core->core_unit == 1) { | ||
454 | pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; | ||
455 | pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + | ||
456 | BCMA_SOC_PCI_MEM_SZ - 1; | ||
457 | pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; | ||
458 | pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; | ||
459 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | ||
460 | tmp | BCMA_SOC_PCI1_MEM); | ||
461 | } | ||
462 | } else | ||
463 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | ||
464 | BCMA_CORE_PCI_SBTOPCI_IO); | ||
465 | |||
466 | /* 64 MB configuration access window */ | ||
467 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); | ||
468 | |||
469 | /* 1 GB memory access window */ | ||
470 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2, | ||
471 | BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G); | ||
472 | |||
473 | |||
474 | /* As per PCI Express Base Spec 1.1 we need to wait for | ||
475 | * at least 100 ms from the end of a reset (cold/warm/hot) | ||
476 | * before issuing configuration requests to PCI Express | ||
477 | * devices. | ||
478 | */ | ||
479 | udelay(100000); | ||
480 | |||
481 | bcma_core_pci_enable_crs(pc); | ||
482 | |||
483 | /* Enable PCI bridge BAR0 memory & master access */ | ||
484 | tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; | ||
485 | bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); | ||
486 | |||
487 | /* Enable PCI interrupts */ | ||
488 | pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA); | ||
489 | |||
490 | /* Ok, ready to run, register it to the system. | ||
491 | * The following needs change, if we want to port hostmode | ||
492 | * to non-MIPS platform. */ | ||
493 | io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM, | ||
494 | 0x04000000); | ||
495 | pc_host->pci_controller.io_map_base = io_map_base; | ||
496 | set_io_port_base(pc_host->pci_controller.io_map_base); | ||
497 | /* Give some time to the PCI controller to configure itself with the new | ||
498 | * values. Not waiting at this point causes crashes of the machine. */ | ||
499 | mdelay(10); | ||
500 | register_pci_controller(&pc_host->pci_controller); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | /* Early PCI fixup for a device on the PCI-core bridge. */ | ||
505 | static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev) | ||
506 | { | ||
507 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { | ||
508 | /* This is not a device on the PCI-core bridge. */ | ||
509 | return; | ||
510 | } | ||
511 | if (PCI_SLOT(dev->devfn) != 0) | ||
512 | return; | ||
513 | |||
514 | pr_info("PCI: Fixing up bridge %s\n", pci_name(dev)); | ||
515 | |||
516 | /* Enable PCI bridge bus mastering and memory space */ | ||
517 | pci_set_master(dev); | ||
518 | if (pcibios_enable_device(dev, ~0) < 0) { | ||
519 | pr_err("PCI: BCMA bridge enable failed\n"); | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | /* Enable PCI bridge BAR1 prefetch and burst */ | ||
524 | pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3); | ||
525 | } | ||
526 | DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge); | ||
527 | |||
528 | /* Early PCI fixup for all PCI-cores to set the correct memory address. */ | ||
529 | static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) | ||
530 | { | ||
531 | struct resource *res; | ||
532 | int pos; | ||
533 | |||
534 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { | ||
535 | /* This is not a device on the PCI-core bridge. */ | ||
536 | return; | ||
537 | } | ||
538 | if (PCI_SLOT(dev->devfn) == 0) | ||
539 | return; | ||
540 | |||
541 | pr_info("PCI: Fixing up addresses %s\n", pci_name(dev)); | ||
542 | |||
543 | for (pos = 0; pos < 6; pos++) { | ||
544 | res = &dev->resource[pos]; | ||
545 | if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) | ||
546 | pci_assign_resource(dev, pos); | ||
547 | } | ||
548 | } | ||
549 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); | ||
550 | |||
551 | /* This function is called when doing a pci_enable_device(). | ||
552 | * We must first check if the device is a device on the PCI-core bridge. */ | ||
553 | int bcma_core_pci_plat_dev_init(struct pci_dev *dev) | ||
554 | { | ||
555 | struct bcma_drv_pci_host *pc_host; | ||
556 | |||
557 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { | ||
558 | /* This is not a device on the PCI-core bridge. */ | ||
559 | return -ENODEV; | ||
560 | } | ||
561 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, | ||
562 | pci_ops); | ||
563 | |||
564 | pr_info("PCI: Fixing up device %s\n", pci_name(dev)); | ||
565 | |||
566 | /* Fix up interrupt lines */ | ||
567 | dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2; | ||
568 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | EXPORT_SYMBOL(bcma_core_pci_plat_dev_init); | ||
573 | |||
574 | /* PCI device IRQ mapping. */ | ||
575 | int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev) | ||
576 | { | ||
577 | struct bcma_drv_pci_host *pc_host; | ||
578 | |||
579 | if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { | ||
580 | /* This is not a device on the PCI-core bridge. */ | ||
581 | return -ENODEV; | ||
582 | } | ||
583 | |||
584 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, | ||
585 | pci_ops); | ||
586 | return bcma_core_mips_irq(pc_host->pdev->core) + 2; | ||
14 | } | 587 | } |
588 | EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); | ||
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index f59244e33971..e3928d68802b 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -154,8 +154,8 @@ const struct bcma_host_ops bcma_host_pci_ops = { | |||
154 | .awrite32 = bcma_host_pci_awrite32, | 154 | .awrite32 = bcma_host_pci_awrite32, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static int bcma_host_pci_probe(struct pci_dev *dev, | 157 | static int __devinit bcma_host_pci_probe(struct pci_dev *dev, |
158 | const struct pci_device_id *id) | 158 | const struct pci_device_id *id) |
159 | { | 159 | { |
160 | struct bcma_bus *bus; | 160 | struct bcma_bus *bus; |
161 | int err = -ENOMEM; | 161 | int err = -ENOMEM; |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index ec31f7dd5549..b8379b90d045 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -13,6 +13,12 @@ | |||
13 | MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); | 13 | MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); |
14 | MODULE_LICENSE("GPL"); | 14 | MODULE_LICENSE("GPL"); |
15 | 15 | ||
16 | /* contains the number the next bus should get. */ | ||
17 | static unsigned int bcma_bus_next_num = 0; | ||
18 | |||
19 | /* bcma_buses_mutex locks the bcma_bus_next_num */ | ||
20 | static DEFINE_MUTEX(bcma_buses_mutex); | ||
21 | |||
16 | static int bcma_bus_match(struct device *dev, struct device_driver *drv); | 22 | static int bcma_bus_match(struct device *dev, struct device_driver *drv); |
17 | static int bcma_device_probe(struct device *dev); | 23 | static int bcma_device_probe(struct device *dev); |
18 | static int bcma_device_remove(struct device *dev); | 24 | static int bcma_device_remove(struct device *dev); |
@@ -93,7 +99,7 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
93 | 99 | ||
94 | core->dev.release = bcma_release_core_dev; | 100 | core->dev.release = bcma_release_core_dev; |
95 | core->dev.bus = &bcma_bus_type; | 101 | core->dev.bus = &bcma_bus_type; |
96 | dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id); | 102 | dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); |
97 | 103 | ||
98 | switch (bus->hosttype) { | 104 | switch (bus->hosttype) { |
99 | case BCMA_HOSTTYPE_PCI: | 105 | case BCMA_HOSTTYPE_PCI: |
@@ -132,11 +138,15 @@ static void bcma_unregister_cores(struct bcma_bus *bus) | |||
132 | } | 138 | } |
133 | } | 139 | } |
134 | 140 | ||
135 | int bcma_bus_register(struct bcma_bus *bus) | 141 | int __devinit bcma_bus_register(struct bcma_bus *bus) |
136 | { | 142 | { |
137 | int err; | 143 | int err; |
138 | struct bcma_device *core; | 144 | struct bcma_device *core; |
139 | 145 | ||
146 | mutex_lock(&bcma_buses_mutex); | ||
147 | bus->num = bcma_bus_next_num++; | ||
148 | mutex_unlock(&bcma_buses_mutex); | ||
149 | |||
140 | /* Scan for devices (cores) */ | 150 | /* Scan for devices (cores) */ |
141 | err = bcma_bus_scan(bus); | 151 | err = bcma_bus_scan(bus); |
142 | if (err) { | 152 | if (err) { |
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 3a2f672db9ad..f94cccccfa56 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c | |||
@@ -212,6 +212,17 @@ static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus, | |||
212 | return NULL; | 212 | return NULL; |
213 | } | 213 | } |
214 | 214 | ||
215 | static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid) | ||
216 | { | ||
217 | struct bcma_device *core; | ||
218 | |||
219 | list_for_each_entry_reverse(core, &bus->cores, list) { | ||
220 | if (core->id.id == coreid) | ||
221 | return core; | ||
222 | } | ||
223 | return NULL; | ||
224 | } | ||
225 | |||
215 | static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, | 226 | static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, |
216 | struct bcma_device_id *match, int core_num, | 227 | struct bcma_device_id *match, int core_num, |
217 | struct bcma_device *core) | 228 | struct bcma_device *core) |
@@ -353,6 +364,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, | |||
353 | void bcma_init_bus(struct bcma_bus *bus) | 364 | void bcma_init_bus(struct bcma_bus *bus) |
354 | { | 365 | { |
355 | s32 tmp; | 366 | s32 tmp; |
367 | struct bcma_chipinfo *chipinfo = &(bus->chipinfo); | ||
356 | 368 | ||
357 | if (bus->init_done) | 369 | if (bus->init_done) |
358 | return; | 370 | return; |
@@ -363,9 +375,12 @@ void bcma_init_bus(struct bcma_bus *bus) | |||
363 | bcma_scan_switch_core(bus, BCMA_ADDR_BASE); | 375 | bcma_scan_switch_core(bus, BCMA_ADDR_BASE); |
364 | 376 | ||
365 | tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); | 377 | tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); |
366 | bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; | 378 | chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; |
367 | bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; | 379 | chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; |
368 | bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; | 380 | chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; |
381 | pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", | ||
382 | chipinfo->id, chipinfo->rev, chipinfo->pkg); | ||
383 | |||
369 | bus->init_done = true; | 384 | bus->init_done = true; |
370 | } | 385 | } |
371 | 386 | ||
@@ -392,6 +407,7 @@ int bcma_bus_scan(struct bcma_bus *bus) | |||
392 | bcma_scan_switch_core(bus, erombase); | 407 | bcma_scan_switch_core(bus, erombase); |
393 | 408 | ||
394 | while (eromptr < eromend) { | 409 | while (eromptr < eromend) { |
410 | struct bcma_device *other_core; | ||
395 | struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); | 411 | struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); |
396 | if (!core) | 412 | if (!core) |
397 | return -ENOMEM; | 413 | return -ENOMEM; |
@@ -414,6 +430,8 @@ int bcma_bus_scan(struct bcma_bus *bus) | |||
414 | 430 | ||
415 | core->core_index = core_num++; | 431 | core->core_index = core_num++; |
416 | bus->nr_cores++; | 432 | bus->nr_cores++; |
433 | other_core = bcma_find_core_reverse(bus, core->id.id); | ||
434 | core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1; | ||
417 | 435 | ||
418 | pr_info("Core %d found: %s " | 436 | pr_info("Core %d found: %s " |
419 | "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", | 437 | "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", |
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index e35134f724f6..ca7752510d5b 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -250,6 +250,7 @@ int bcma_sprom_get(struct bcma_bus *bus) | |||
250 | { | 250 | { |
251 | u16 offset; | 251 | u16 offset; |
252 | u16 *sprom; | 252 | u16 *sprom; |
253 | u32 sromctrl; | ||
253 | int err = 0; | 254 | int err = 0; |
254 | 255 | ||
255 | if (!bus->drv_cc.core) | 256 | if (!bus->drv_cc.core) |
@@ -258,6 +259,12 @@ int bcma_sprom_get(struct bcma_bus *bus) | |||
258 | if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) | 259 | if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) |
259 | return -ENOENT; | 260 | return -ENOENT; |
260 | 261 | ||
262 | if (bus->drv_cc.core->id.rev >= 32) { | ||
263 | sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); | ||
264 | if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT)) | ||
265 | return -ENOENT; | ||
266 | } | ||
267 | |||
261 | sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), | 268 | sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), |
262 | GFP_KERNEL); | 269 | GFP_KERNEL); |
263 | if (!sprom) | 270 | if (!sprom) |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f00f596c1029..789c9b579aea 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -102,6 +102,7 @@ static struct usb_device_id btusb_table[] = { | |||
102 | 102 | ||
103 | /* Broadcom BCM20702A0 */ | 103 | /* Broadcom BCM20702A0 */ |
104 | { USB_DEVICE(0x0a5c, 0x21e3) }, | 104 | { USB_DEVICE(0x0a5c, 0x21e3) }, |
105 | { USB_DEVICE(0x0a5c, 0x21f3) }, | ||
105 | { USB_DEVICE(0x413c, 0x8197) }, | 106 | { USB_DEVICE(0x413c, 0x8197) }, |
106 | 107 | ||
107 | { } /* Terminating entry */ | 108 | { } /* Terminating entry */ |
@@ -726,9 +727,6 @@ static int btusb_send_frame(struct sk_buff *skb) | |||
726 | usb_fill_bulk_urb(urb, data->udev, pipe, | 727 | usb_fill_bulk_urb(urb, data->udev, pipe, |
727 | skb->data, skb->len, btusb_tx_complete, skb); | 728 | skb->data, skb->len, btusb_tx_complete, skb); |
728 | 729 | ||
729 | if (skb->priority >= HCI_PRIO_MAX - 1) | ||
730 | urb->transfer_flags = URB_ISO_ASAP; | ||
731 | |||
732 | hdev->stat.acl_tx++; | 730 | hdev->stat.acl_tx++; |
733 | break; | 731 | break; |
734 | 732 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index 3d5f8be20eac..d755a5e7ed20 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig | |||
@@ -1,12 +1,29 @@ | |||
1 | config ATH6KL | 1 | config ATH6KL |
2 | tristate "Atheros ath6kl support" | 2 | tristate "Atheros mobile chipsets support" |
3 | |||
4 | config ATH6KL_SDIO | ||
5 | tristate "Atheros ath6kl SDIO support" | ||
6 | depends on ATH6KL | ||
3 | depends on MMC | 7 | depends on MMC |
4 | depends on CFG80211 | 8 | depends on CFG80211 |
5 | ---help--- | 9 | ---help--- |
6 | This module adds support for wireless adapters based on | 10 | This module adds support for wireless adapters based on |
7 | Atheros AR6003 chipset running over SDIO. If you choose to | 11 | Atheros AR6003 and AR6004 chipsets running over SDIO. If you |
8 | build it as a module, it will be called ath6kl. Pls note | 12 | choose to build it as a module, it will be called ath6kl_sdio. |
9 | that AR6002 and AR6001 are not supported by this driver. | 13 | Please note that AR6002 and AR6001 are not supported by this |
14 | driver. | ||
15 | |||
16 | config ATH6KL_USB | ||
17 | tristate "Atheros ath6kl USB support" | ||
18 | depends on ATH6KL | ||
19 | depends on USB | ||
20 | depends on CFG80211 | ||
21 | depends on EXPERIMENTAL | ||
22 | ---help--- | ||
23 | This module adds support for wireless adapters based on | ||
24 | Atheros AR6004 chipset running over USB. This is still under | ||
25 | implementation and it isn't functional. If you choose to | ||
26 | build it as a module, it will be called ath6kl_usb. | ||
10 | 27 | ||
11 | config ATH6KL_DEBUG | 28 | config ATH6KL_DEBUG |
12 | bool "Atheros ath6kl debugging" | 29 | bool "Atheros ath6kl debugging" |
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index 707069303550..9ba42fa04962 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile | |||
@@ -21,17 +21,21 @@ | |||
21 | # Author(s): ="Atheros" | 21 | # Author(s): ="Atheros" |
22 | #------------------------------------------------------------------------------ | 22 | #------------------------------------------------------------------------------ |
23 | 23 | ||
24 | obj-$(CONFIG_ATH6KL) := ath6kl.o | 24 | obj-$(CONFIG_ATH6KL) += ath6kl_core.o |
25 | ath6kl-y += debug.o | 25 | ath6kl_core-y += debug.o |
26 | ath6kl-y += hif.o | 26 | ath6kl_core-y += hif.o |
27 | ath6kl-y += htc.o | 27 | ath6kl_core-y += htc.o |
28 | ath6kl-y += bmi.o | 28 | ath6kl_core-y += bmi.o |
29 | ath6kl-y += cfg80211.o | 29 | ath6kl_core-y += cfg80211.o |
30 | ath6kl-y += init.o | 30 | ath6kl_core-y += init.o |
31 | ath6kl-y += main.o | 31 | ath6kl_core-y += main.o |
32 | ath6kl-y += txrx.o | 32 | ath6kl_core-y += txrx.o |
33 | ath6kl-y += wmi.o | 33 | ath6kl_core-y += wmi.o |
34 | ath6kl-y += sdio.o | 34 | ath6kl_core-y += core.o |
35 | ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o | 35 | ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o |
36 | 36 | ||
37 | ccflags-y += -D__CHECK_ENDIAN__ | 37 | obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o |
38 | ath6kl_sdio-y += sdio.o | ||
39 | |||
40 | obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o | ||
41 | ath6kl_usb-y += usb.o | ||
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c index bce3575c310a..aef00d5a1438 100644 --- a/drivers/net/wireless/ath/ath6kl/bmi.c +++ b/drivers/net/wireless/ath/ath6kl/bmi.c | |||
@@ -57,8 +57,14 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, | |||
57 | return ret; | 57 | return ret; |
58 | } | 58 | } |
59 | 59 | ||
60 | ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version, | 60 | if (ar->hif_type == ATH6KL_HIF_TYPE_USB) { |
61 | sizeof(targ_info->version)); | 61 | ret = ath6kl_hif_bmi_read(ar, (u8 *)targ_info, |
62 | sizeof(*targ_info)); | ||
63 | } else { | ||
64 | ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version, | ||
65 | sizeof(targ_info->version)); | ||
66 | } | ||
67 | |||
62 | if (ret) { | 68 | if (ret) { |
63 | ath6kl_err("Unable to recv target info: %d\n", ret); | 69 | ath6kl_err("Unable to recv target info: %d\n", ret); |
64 | return ret; | 70 | return ret; |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 6c59a217b1a1..d1922d8eb3bb 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -15,6 +15,8 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
18 | #include <linux/inetdevice.h> | ||
19 | #include <linux/export.h> | ||
18 | 20 | ||
19 | #include "core.h" | 21 | #include "core.h" |
20 | #include "cfg80211.h" | 22 | #include "cfg80211.h" |
@@ -22,10 +24,6 @@ | |||
22 | #include "hif-ops.h" | 24 | #include "hif-ops.h" |
23 | #include "testmode.h" | 25 | #include "testmode.h" |
24 | 26 | ||
25 | static unsigned int ath6kl_p2p; | ||
26 | |||
27 | module_param(ath6kl_p2p, uint, 0644); | ||
28 | |||
29 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ | 27 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ |
30 | .bitrate = (_rate), \ | 28 | .bitrate = (_rate), \ |
31 | .flags = (_flags), \ | 29 | .flags = (_flags), \ |
@@ -196,7 +194,7 @@ static int ath6kl_set_auth_type(struct ath6kl_vif *vif, | |||
196 | break; | 194 | break; |
197 | 195 | ||
198 | default: | 196 | default: |
199 | ath6kl_err("%s: 0x%x not spported\n", __func__, auth_type); | 197 | ath6kl_err("%s: 0x%x not supported\n", __func__, auth_type); |
200 | return -ENOTSUPP; | 198 | return -ENOTSUPP; |
201 | } | 199 | } |
202 | 200 | ||
@@ -461,13 +459,13 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
461 | } | 459 | } |
462 | } | 460 | } |
463 | 461 | ||
464 | if (sme->ie && (sme->ie_len > 0)) { | 462 | status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len); |
465 | status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len); | 463 | if (status) { |
466 | if (status) { | 464 | up(&ar->sem); |
467 | up(&ar->sem); | 465 | return status; |
468 | return status; | 466 | } |
469 | } | 467 | |
470 | } else | 468 | if (sme->ie == NULL || sme->ie_len == 0) |
471 | ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG; | 469 | ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG; |
472 | 470 | ||
473 | if (test_bit(CONNECTED, &vif->flags) && | 471 | if (test_bit(CONNECTED, &vif->flags) && |
@@ -523,8 +521,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
523 | (vif->prwise_crypto == WEP_CRYPT)) { | 521 | (vif->prwise_crypto == WEP_CRYPT)) { |
524 | struct ath6kl_key *key = NULL; | 522 | struct ath6kl_key *key = NULL; |
525 | 523 | ||
526 | if (sme->key_idx < WMI_MIN_KEY_INDEX || | 524 | if (sme->key_idx > WMI_MAX_KEY_INDEX) { |
527 | sme->key_idx > WMI_MAX_KEY_INDEX) { | ||
528 | ath6kl_err("key index %d out of bounds\n", | 525 | ath6kl_err("key index %d out of bounds\n", |
529 | sme->key_idx); | 526 | sme->key_idx); |
530 | up(&ar->sem); | 527 | up(&ar->sem); |
@@ -605,11 +602,13 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
605 | return 0; | 602 | return 0; |
606 | } | 603 | } |
607 | 604 | ||
608 | static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, | 605 | static struct cfg80211_bss * |
609 | enum network_type nw_type, | 606 | ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, |
610 | const u8 *bssid, | 607 | enum network_type nw_type, |
611 | struct ieee80211_channel *chan, | 608 | const u8 *bssid, |
612 | const u8 *beacon_ie, size_t beacon_ie_len) | 609 | struct ieee80211_channel *chan, |
610 | const u8 *beacon_ie, | ||
611 | size_t beacon_ie_len) | ||
613 | { | 612 | { |
614 | struct ath6kl *ar = vif->ar; | 613 | struct ath6kl *ar = vif->ar; |
615 | struct cfg80211_bss *bss; | 614 | struct cfg80211_bss *bss; |
@@ -638,7 +637,7 @@ static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, | |||
638 | */ | 637 | */ |
639 | ie = kmalloc(2 + vif->ssid_len + beacon_ie_len, GFP_KERNEL); | 638 | ie = kmalloc(2 + vif->ssid_len + beacon_ie_len, GFP_KERNEL); |
640 | if (ie == NULL) | 639 | if (ie == NULL) |
641 | return -ENOMEM; | 640 | return NULL; |
642 | ie[0] = WLAN_EID_SSID; | 641 | ie[0] = WLAN_EID_SSID; |
643 | ie[1] = vif->ssid_len; | 642 | ie[1] = vif->ssid_len; |
644 | memcpy(ie + 2, vif->ssid, vif->ssid_len); | 643 | memcpy(ie + 2, vif->ssid, vif->ssid_len); |
@@ -652,15 +651,9 @@ static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, | |||
652 | "cfg80211\n", bssid); | 651 | "cfg80211\n", bssid); |
653 | kfree(ie); | 652 | kfree(ie); |
654 | } else | 653 | } else |
655 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss " | 654 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); |
656 | "entry\n"); | ||
657 | |||
658 | if (bss == NULL) | ||
659 | return -ENOMEM; | ||
660 | 655 | ||
661 | cfg80211_put_bss(bss); | 656 | return bss; |
662 | |||
663 | return 0; | ||
664 | } | 657 | } |
665 | 658 | ||
666 | void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | 659 | void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, |
@@ -672,6 +665,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
672 | { | 665 | { |
673 | struct ieee80211_channel *chan; | 666 | struct ieee80211_channel *chan; |
674 | struct ath6kl *ar = vif->ar; | 667 | struct ath6kl *ar = vif->ar; |
668 | struct cfg80211_bss *bss; | ||
675 | 669 | ||
676 | /* capinfo + listen interval */ | 670 | /* capinfo + listen interval */ |
677 | u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16); | 671 | u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16); |
@@ -712,8 +706,9 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
712 | 706 | ||
713 | chan = ieee80211_get_channel(ar->wiphy, (int) channel); | 707 | chan = ieee80211_get_channel(ar->wiphy, (int) channel); |
714 | 708 | ||
715 | if (ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan, assoc_info, | 709 | bss = ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan, |
716 | beacon_ie_len) < 0) { | 710 | assoc_info, beacon_ie_len); |
711 | if (!bss) { | ||
717 | ath6kl_err("could not add cfg80211 bss entry\n"); | 712 | ath6kl_err("could not add cfg80211 bss entry\n"); |
718 | return; | 713 | return; |
719 | } | 714 | } |
@@ -722,6 +717,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
722 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", | 717 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", |
723 | nw_type & ADHOC_CREATOR ? "creator" : "joiner"); | 718 | nw_type & ADHOC_CREATOR ? "creator" : "joiner"); |
724 | cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); | 719 | cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); |
720 | cfg80211_put_bss(bss); | ||
725 | return; | 721 | return; |
726 | } | 722 | } |
727 | 723 | ||
@@ -732,11 +728,11 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
732 | assoc_req_ie, assoc_req_len, | 728 | assoc_req_ie, assoc_req_len, |
733 | assoc_resp_ie, assoc_resp_len, | 729 | assoc_resp_ie, assoc_resp_len, |
734 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | 730 | WLAN_STATUS_SUCCESS, GFP_KERNEL); |
731 | cfg80211_put_bss(bss); | ||
735 | } else if (vif->sme_state == SME_CONNECTED) { | 732 | } else if (vif->sme_state == SME_CONNECTED) { |
736 | /* inform roam event to cfg80211 */ | 733 | /* inform roam event to cfg80211 */ |
737 | cfg80211_roamed(vif->ndev, chan, bssid, | 734 | cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len, |
738 | assoc_req_ie, assoc_req_len, | 735 | assoc_resp_ie, assoc_resp_len, GFP_KERNEL); |
739 | assoc_resp_ie, assoc_resp_len, GFP_KERNEL); | ||
740 | } | 736 | } |
741 | } | 737 | } |
742 | 738 | ||
@@ -984,6 +980,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
984 | struct ath6kl *ar = ath6kl_priv(ndev); | 980 | struct ath6kl *ar = ath6kl_priv(ndev); |
985 | struct ath6kl_vif *vif = netdev_priv(ndev); | 981 | struct ath6kl_vif *vif = netdev_priv(ndev); |
986 | struct ath6kl_key *key = NULL; | 982 | struct ath6kl_key *key = NULL; |
983 | int seq_len; | ||
987 | u8 key_usage; | 984 | u8 key_usage; |
988 | u8 key_type; | 985 | u8 key_type; |
989 | 986 | ||
@@ -997,7 +994,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
997 | params->key); | 994 | params->key); |
998 | } | 995 | } |
999 | 996 | ||
1000 | if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { | 997 | if (key_index > WMI_MAX_KEY_INDEX) { |
1001 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 998 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1002 | "%s: key index %d out of bounds\n", __func__, | 999 | "%s: key index %d out of bounds\n", __func__, |
1003 | key_index); | 1000 | key_index); |
@@ -1012,23 +1009,21 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1012 | else | 1009 | else |
1013 | key_usage = GROUP_USAGE; | 1010 | key_usage = GROUP_USAGE; |
1014 | 1011 | ||
1015 | if (params) { | 1012 | seq_len = params->seq_len; |
1016 | int seq_len = params->seq_len; | 1013 | if (params->cipher == WLAN_CIPHER_SUITE_SMS4 && |
1017 | if (params->cipher == WLAN_CIPHER_SUITE_SMS4 && | 1014 | seq_len > ATH6KL_KEY_SEQ_LEN) { |
1018 | seq_len > ATH6KL_KEY_SEQ_LEN) { | 1015 | /* Only first half of the WPI PN is configured */ |
1019 | /* Only first half of the WPI PN is configured */ | 1016 | seq_len = ATH6KL_KEY_SEQ_LEN; |
1020 | seq_len = ATH6KL_KEY_SEQ_LEN; | ||
1021 | } | ||
1022 | if (params->key_len > WLAN_MAX_KEY_LEN || | ||
1023 | seq_len > sizeof(key->seq)) | ||
1024 | return -EINVAL; | ||
1025 | |||
1026 | key->key_len = params->key_len; | ||
1027 | memcpy(key->key, params->key, key->key_len); | ||
1028 | key->seq_len = seq_len; | ||
1029 | memcpy(key->seq, params->seq, key->seq_len); | ||
1030 | key->cipher = params->cipher; | ||
1031 | } | 1017 | } |
1018 | if (params->key_len > WLAN_MAX_KEY_LEN || | ||
1019 | seq_len > sizeof(key->seq)) | ||
1020 | return -EINVAL; | ||
1021 | |||
1022 | key->key_len = params->key_len; | ||
1023 | memcpy(key->key, params->key, key->key_len); | ||
1024 | key->seq_len = seq_len; | ||
1025 | memcpy(key->seq, params->seq, key->seq_len); | ||
1026 | key->cipher = params->cipher; | ||
1032 | 1027 | ||
1033 | switch (key->cipher) { | 1028 | switch (key->cipher) { |
1034 | case WLAN_CIPHER_SUITE_WEP40: | 1029 | case WLAN_CIPHER_SUITE_WEP40: |
@@ -1115,7 +1110,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1115 | if (!ath6kl_cfg80211_ready(vif)) | 1110 | if (!ath6kl_cfg80211_ready(vif)) |
1116 | return -EIO; | 1111 | return -EIO; |
1117 | 1112 | ||
1118 | if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { | 1113 | if (key_index > WMI_MAX_KEY_INDEX) { |
1119 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 1114 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1120 | "%s: key index %d out of bounds\n", __func__, | 1115 | "%s: key index %d out of bounds\n", __func__, |
1121 | key_index); | 1116 | key_index); |
@@ -1148,7 +1143,7 @@ static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1148 | if (!ath6kl_cfg80211_ready(vif)) | 1143 | if (!ath6kl_cfg80211_ready(vif)) |
1149 | return -EIO; | 1144 | return -EIO; |
1150 | 1145 | ||
1151 | if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { | 1146 | if (key_index > WMI_MAX_KEY_INDEX) { |
1152 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 1147 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1153 | "%s: key index %d out of bounds\n", __func__, | 1148 | "%s: key index %d out of bounds\n", __func__, |
1154 | key_index); | 1149 | key_index); |
@@ -1184,7 +1179,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, | |||
1184 | if (!ath6kl_cfg80211_ready(vif)) | 1179 | if (!ath6kl_cfg80211_ready(vif)) |
1185 | return -EIO; | 1180 | return -EIO; |
1186 | 1181 | ||
1187 | if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { | 1182 | if (key_index > WMI_MAX_KEY_INDEX) { |
1188 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 1183 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1189 | "%s: key index %d out of bounds\n", | 1184 | "%s: key index %d out of bounds\n", |
1190 | __func__, key_index); | 1185 | __func__, key_index); |
@@ -1403,7 +1398,7 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, | |||
1403 | 1398 | ||
1404 | ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); | 1399 | ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); |
1405 | 1400 | ||
1406 | ath6kl_deinit_if_data(vif); | 1401 | ath6kl_cfg80211_vif_cleanup(vif); |
1407 | 1402 | ||
1408 | return 0; | 1403 | return 0; |
1409 | } | 1404 | } |
@@ -1728,29 +1723,14 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) | |||
1728 | return 0; | 1723 | return 0; |
1729 | } | 1724 | } |
1730 | 1725 | ||
1731 | static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | 1726 | static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif, |
1727 | struct cfg80211_wowlan *wow, u32 *filter) | ||
1732 | { | 1728 | { |
1733 | struct ath6kl_vif *vif; | 1729 | int ret, pos; |
1734 | int ret, pos, left; | ||
1735 | u32 filter = 0; | ||
1736 | u16 i; | ||
1737 | u8 mask[WOW_MASK_SIZE]; | 1730 | u8 mask[WOW_MASK_SIZE]; |
1731 | u16 i; | ||
1738 | 1732 | ||
1739 | vif = ath6kl_vif_first(ar); | 1733 | /* Configure the patterns that we received from the user. */ |
1740 | if (!vif) | ||
1741 | return -EIO; | ||
1742 | |||
1743 | if (!ath6kl_cfg80211_ready(vif)) | ||
1744 | return -EIO; | ||
1745 | |||
1746 | if (!test_bit(CONNECTED, &vif->flags)) | ||
1747 | return -EINVAL; | ||
1748 | |||
1749 | /* Clear existing WOW patterns */ | ||
1750 | for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) | ||
1751 | ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, | ||
1752 | WOW_LIST_ID, i); | ||
1753 | /* Configure new WOW patterns */ | ||
1754 | for (i = 0; i < wow->n_patterns; i++) { | 1734 | for (i = 0; i < wow->n_patterns; i++) { |
1755 | 1735 | ||
1756 | /* | 1736 | /* |
@@ -1773,29 +1753,221 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
1773 | * matched from the first byte of received pkt in the firmware. | 1753 | * matched from the first byte of received pkt in the firmware. |
1774 | */ | 1754 | */ |
1775 | ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, | 1755 | ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, |
1776 | vif->fw_vif_idx, WOW_LIST_ID, | 1756 | vif->fw_vif_idx, WOW_LIST_ID, |
1777 | wow->patterns[i].pattern_len, | 1757 | wow->patterns[i].pattern_len, |
1778 | 0 /* pattern offset */, | 1758 | 0 /* pattern offset */, |
1779 | wow->patterns[i].pattern, mask); | 1759 | wow->patterns[i].pattern, mask); |
1780 | if (ret) | 1760 | if (ret) |
1781 | return ret; | 1761 | return ret; |
1782 | } | 1762 | } |
1783 | 1763 | ||
1784 | if (wow->disconnect) | 1764 | if (wow->disconnect) |
1785 | filter |= WOW_FILTER_OPTION_NWK_DISASSOC; | 1765 | *filter |= WOW_FILTER_OPTION_NWK_DISASSOC; |
1786 | 1766 | ||
1787 | if (wow->magic_pkt) | 1767 | if (wow->magic_pkt) |
1788 | filter |= WOW_FILTER_OPTION_MAGIC_PACKET; | 1768 | *filter |= WOW_FILTER_OPTION_MAGIC_PACKET; |
1789 | 1769 | ||
1790 | if (wow->gtk_rekey_failure) | 1770 | if (wow->gtk_rekey_failure) |
1791 | filter |= WOW_FILTER_OPTION_GTK_ERROR; | 1771 | *filter |= WOW_FILTER_OPTION_GTK_ERROR; |
1792 | 1772 | ||
1793 | if (wow->eap_identity_req) | 1773 | if (wow->eap_identity_req) |
1794 | filter |= WOW_FILTER_OPTION_EAP_REQ; | 1774 | *filter |= WOW_FILTER_OPTION_EAP_REQ; |
1795 | 1775 | ||
1796 | if (wow->four_way_handshake) | 1776 | if (wow->four_way_handshake) |
1797 | filter |= WOW_FILTER_OPTION_8021X_4WAYHS; | 1777 | *filter |= WOW_FILTER_OPTION_8021X_4WAYHS; |
1778 | |||
1779 | return 0; | ||
1780 | } | ||
1781 | |||
1782 | static int ath6kl_wow_ap(struct ath6kl *ar, struct ath6kl_vif *vif) | ||
1783 | { | ||
1784 | static const u8 unicst_pattern[] = { 0x00, 0x00, 0x00, | ||
1785 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1786 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1787 | 0x00, 0x08 }; | ||
1788 | static const u8 unicst_mask[] = { 0x01, 0x00, 0x00, | ||
1789 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1790 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1791 | 0x00, 0x7f }; | ||
1792 | u8 unicst_offset = 0; | ||
1793 | static const u8 arp_pattern[] = { 0x08, 0x06 }; | ||
1794 | static const u8 arp_mask[] = { 0xff, 0xff }; | ||
1795 | u8 arp_offset = 20; | ||
1796 | static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 }; | ||
1797 | static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 }; | ||
1798 | u8 discvr_offset = 38; | ||
1799 | static const u8 dhcp_pattern[] = { 0xff, 0xff, 0xff, 0xff, | ||
1800 | 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1801 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, | ||
1802 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1803 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1804 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 /* port 67 */ }; | ||
1805 | static const u8 dhcp_mask[] = { 0xff, 0xff, 0xff, 0xff, | ||
1806 | 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1807 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | ||
1808 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1809 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1810 | 0x00, 0x00, 0x00, 0x00, 0xff, 0xff /* port 67 */ }; | ||
1811 | u8 dhcp_offset = 0; | ||
1812 | int ret; | ||
1813 | |||
1814 | /* Setup unicast IP, EAPOL-like and ARP pkt pattern */ | ||
1815 | ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, | ||
1816 | vif->fw_vif_idx, WOW_LIST_ID, | ||
1817 | sizeof(unicst_pattern), unicst_offset, | ||
1818 | unicst_pattern, unicst_mask); | ||
1819 | if (ret) { | ||
1820 | ath6kl_err("failed to add WOW unicast IP pattern\n"); | ||
1821 | return ret; | ||
1822 | } | ||
1823 | |||
1824 | /* Setup all ARP pkt pattern */ | ||
1825 | ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, | ||
1826 | vif->fw_vif_idx, WOW_LIST_ID, | ||
1827 | sizeof(arp_pattern), arp_offset, | ||
1828 | arp_pattern, arp_mask); | ||
1829 | if (ret) { | ||
1830 | ath6kl_err("failed to add WOW ARP pattern\n"); | ||
1831 | return ret; | ||
1832 | } | ||
1798 | 1833 | ||
1834 | /* | ||
1835 | * Setup multicast pattern for mDNS 224.0.0.251, | ||
1836 | * SSDP 239.255.255.250 and LLMNR 224.0.0.252 | ||
1837 | */ | ||
1838 | ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, | ||
1839 | vif->fw_vif_idx, WOW_LIST_ID, | ||
1840 | sizeof(discvr_pattern), discvr_offset, | ||
1841 | discvr_pattern, discvr_mask); | ||
1842 | if (ret) { | ||
1843 | ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n"); | ||
1844 | return ret; | ||
1845 | } | ||
1846 | |||
1847 | /* Setup all DHCP broadcast pkt pattern */ | ||
1848 | ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, | ||
1849 | vif->fw_vif_idx, WOW_LIST_ID, | ||
1850 | sizeof(dhcp_pattern), dhcp_offset, | ||
1851 | dhcp_pattern, dhcp_mask); | ||
1852 | if (ret) { | ||
1853 | ath6kl_err("failed to add WOW DHCP broadcast pattern\n"); | ||
1854 | return ret; | ||
1855 | } | ||
1856 | |||
1857 | return 0; | ||
1858 | } | ||
1859 | |||
1860 | static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif) | ||
1861 | { | ||
1862 | struct net_device *ndev = vif->ndev; | ||
1863 | static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 }; | ||
1864 | static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 }; | ||
1865 | u8 discvr_offset = 38; | ||
1866 | u8 mac_mask[ETH_ALEN]; | ||
1867 | int ret; | ||
1868 | |||
1869 | /* Setup unicast pkt pattern */ | ||
1870 | memset(mac_mask, 0xff, ETH_ALEN); | ||
1871 | ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, | ||
1872 | vif->fw_vif_idx, WOW_LIST_ID, | ||
1873 | ETH_ALEN, 0, ndev->dev_addr, | ||
1874 | mac_mask); | ||
1875 | if (ret) { | ||
1876 | ath6kl_err("failed to add WOW unicast pattern\n"); | ||
1877 | return ret; | ||
1878 | } | ||
1879 | |||
1880 | /* | ||
1881 | * Setup multicast pattern for mDNS 224.0.0.251, | ||
1882 | * SSDP 239.255.255.250 and LLMNR 224.0.0.252 | ||
1883 | */ | ||
1884 | if ((ndev->flags & IFF_ALLMULTI) || | ||
1885 | (ndev->flags & IFF_MULTICAST && netdev_mc_count(ndev) > 0)) { | ||
1886 | ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, | ||
1887 | vif->fw_vif_idx, WOW_LIST_ID, | ||
1888 | sizeof(discvr_pattern), discvr_offset, | ||
1889 | discvr_pattern, discvr_mask); | ||
1890 | if (ret) { | ||
1891 | ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR " | ||
1892 | "pattern\n"); | ||
1893 | return ret; | ||
1894 | } | ||
1895 | } | ||
1896 | |||
1897 | return 0; | ||
1898 | } | ||
1899 | |||
1900 | static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | ||
1901 | { | ||
1902 | struct in_device *in_dev; | ||
1903 | struct in_ifaddr *ifa; | ||
1904 | struct ath6kl_vif *vif; | ||
1905 | int ret, left; | ||
1906 | u32 filter = 0; | ||
1907 | u16 i; | ||
1908 | u8 index = 0; | ||
1909 | __be32 ips[MAX_IP_ADDRS]; | ||
1910 | |||
1911 | vif = ath6kl_vif_first(ar); | ||
1912 | if (!vif) | ||
1913 | return -EIO; | ||
1914 | |||
1915 | if (!ath6kl_cfg80211_ready(vif)) | ||
1916 | return -EIO; | ||
1917 | |||
1918 | if (!test_bit(CONNECTED, &vif->flags)) | ||
1919 | return -ENOTCONN; | ||
1920 | |||
1921 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) | ||
1922 | return -EINVAL; | ||
1923 | |||
1924 | /* Clear existing WOW patterns */ | ||
1925 | for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) | ||
1926 | ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, | ||
1927 | WOW_LIST_ID, i); | ||
1928 | |||
1929 | /* | ||
1930 | * Skip the default WOW pattern configuration | ||
1931 | * if the driver receives any WOW patterns from | ||
1932 | * the user. | ||
1933 | */ | ||
1934 | if (wow) | ||
1935 | ret = ath6kl_wow_usr(ar, vif, wow, &filter); | ||
1936 | else if (vif->nw_type == AP_NETWORK) | ||
1937 | ret = ath6kl_wow_ap(ar, vif); | ||
1938 | else | ||
1939 | ret = ath6kl_wow_sta(ar, vif); | ||
1940 | |||
1941 | if (ret) | ||
1942 | return ret; | ||
1943 | |||
1944 | /* Setup own IP addr for ARP agent. */ | ||
1945 | in_dev = __in_dev_get_rtnl(vif->ndev); | ||
1946 | if (!in_dev) | ||
1947 | goto skip_arp; | ||
1948 | |||
1949 | ifa = in_dev->ifa_list; | ||
1950 | memset(&ips, 0, sizeof(ips)); | ||
1951 | |||
1952 | /* Configure IP addr only if IP address count < MAX_IP_ADDRS */ | ||
1953 | while (index < MAX_IP_ADDRS && ifa) { | ||
1954 | ips[index] = ifa->ifa_local; | ||
1955 | ifa = ifa->ifa_next; | ||
1956 | index++; | ||
1957 | } | ||
1958 | |||
1959 | if (ifa) { | ||
1960 | ath6kl_err("total IP addr count is exceeding fw limit\n"); | ||
1961 | return -EINVAL; | ||
1962 | } | ||
1963 | |||
1964 | ret = ath6kl_wmi_set_ip_cmd(ar->wmi, vif->fw_vif_idx, ips[0], ips[1]); | ||
1965 | if (ret) { | ||
1966 | ath6kl_err("fail to setup ip for arp agent\n"); | ||
1967 | return ret; | ||
1968 | } | ||
1969 | |||
1970 | skip_arp: | ||
1799 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, | 1971 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, |
1800 | ATH6KL_WOW_MODE_ENABLE, | 1972 | ATH6KL_WOW_MODE_ENABLE, |
1801 | filter, | 1973 | filter, |
@@ -1803,11 +1975,26 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
1803 | if (ret) | 1975 | if (ret) |
1804 | return ret; | 1976 | return ret; |
1805 | 1977 | ||
1978 | clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags); | ||
1979 | |||
1806 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | 1980 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, |
1807 | ATH6KL_HOST_MODE_ASLEEP); | 1981 | ATH6KL_HOST_MODE_ASLEEP); |
1808 | if (ret) | 1982 | if (ret) |
1809 | return ret; | 1983 | return ret; |
1810 | 1984 | ||
1985 | left = wait_event_interruptible_timeout(ar->event_wq, | ||
1986 | test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags), | ||
1987 | WMI_TIMEOUT); | ||
1988 | if (left == 0) { | ||
1989 | ath6kl_warn("timeout, didn't get host sleep cmd " | ||
1990 | "processed event\n"); | ||
1991 | ret = -ETIMEDOUT; | ||
1992 | } else if (left < 0) { | ||
1993 | ath6kl_warn("error while waiting for host sleep cmd " | ||
1994 | "processed event %d\n", left); | ||
1995 | ret = left; | ||
1996 | } | ||
1997 | |||
1811 | if (ar->tx_pending[ar->ctrl_ep]) { | 1998 | if (ar->tx_pending[ar->ctrl_ep]) { |
1812 | left = wait_event_interruptible_timeout(ar->event_wq, | 1999 | left = wait_event_interruptible_timeout(ar->event_wq, |
1813 | ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT); | 2000 | ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT); |
@@ -1911,6 +2098,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, | |||
1911 | 2098 | ||
1912 | return 0; | 2099 | return 0; |
1913 | } | 2100 | } |
2101 | EXPORT_SYMBOL(ath6kl_cfg80211_suspend); | ||
1914 | 2102 | ||
1915 | int ath6kl_cfg80211_resume(struct ath6kl *ar) | 2103 | int ath6kl_cfg80211_resume(struct ath6kl *ar) |
1916 | { | 2104 | { |
@@ -1962,6 +2150,7 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar) | |||
1962 | 2150 | ||
1963 | return 0; | 2151 | return 0; |
1964 | } | 2152 | } |
2153 | EXPORT_SYMBOL(ath6kl_cfg80211_resume); | ||
1965 | 2154 | ||
1966 | #ifdef CONFIG_PM | 2155 | #ifdef CONFIG_PM |
1967 | 2156 | ||
@@ -2014,7 +2203,18 @@ static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, | |||
2014 | struct ieee80211_channel *chan, | 2203 | struct ieee80211_channel *chan, |
2015 | enum nl80211_channel_type channel_type) | 2204 | enum nl80211_channel_type channel_type) |
2016 | { | 2205 | { |
2017 | struct ath6kl_vif *vif = netdev_priv(dev); | 2206 | struct ath6kl_vif *vif; |
2207 | |||
2208 | /* | ||
2209 | * 'dev' could be NULL if a channel change is required for the hardware | ||
2210 | * device itself, instead of a particular VIF. | ||
2211 | * | ||
2212 | * FIXME: To be handled properly when monitor mode is supported. | ||
2213 | */ | ||
2214 | if (!dev) | ||
2215 | return -EBUSY; | ||
2216 | |||
2217 | vif = netdev_priv(dev); | ||
2018 | 2218 | ||
2019 | if (!ath6kl_cfg80211_ready(vif)) | 2219 | if (!ath6kl_cfg80211_ready(vif)) |
2020 | return -EIO; | 2220 | return -EIO; |
@@ -2214,6 +2414,11 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
2214 | p.dot11_auth_mode = vif->dot11_auth_mode; | 2414 | p.dot11_auth_mode = vif->dot11_auth_mode; |
2215 | p.ch = cpu_to_le16(vif->next_chan); | 2415 | p.ch = cpu_to_le16(vif->next_chan); |
2216 | 2416 | ||
2417 | /* Enable uAPSD support by default */ | ||
2418 | res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true); | ||
2419 | if (res < 0) | ||
2420 | return res; | ||
2421 | |||
2217 | if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { | 2422 | if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { |
2218 | p.nw_subtype = SUBTYPE_P2PGO; | 2423 | p.nw_subtype = SUBTYPE_P2PGO; |
2219 | } else { | 2424 | } else { |
@@ -2259,6 +2464,19 @@ static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
2259 | return 0; | 2464 | return 0; |
2260 | } | 2465 | } |
2261 | 2466 | ||
2467 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
2468 | |||
2469 | static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, | ||
2470 | u8 *mac) | ||
2471 | { | ||
2472 | struct ath6kl *ar = ath6kl_priv(dev); | ||
2473 | struct ath6kl_vif *vif = netdev_priv(dev); | ||
2474 | const u8 *addr = mac ? mac : bcast_addr; | ||
2475 | |||
2476 | return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH, | ||
2477 | addr, WLAN_REASON_PREV_AUTH_NOT_VALID); | ||
2478 | } | ||
2479 | |||
2262 | static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, | 2480 | static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, |
2263 | u8 *mac, struct station_parameters *params) | 2481 | u8 *mac, struct station_parameters *params) |
2264 | { | 2482 | { |
@@ -2518,6 +2736,12 @@ ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
2518 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | 2736 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | |
2519 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | 2737 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
2520 | }, | 2738 | }, |
2739 | [NL80211_IFTYPE_AP] = { | ||
2740 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
2741 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
2742 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
2743 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
2744 | }, | ||
2521 | [NL80211_IFTYPE_P2P_CLIENT] = { | 2745 | [NL80211_IFTYPE_P2P_CLIENT] = { |
2522 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | 2746 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | |
2523 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | 2747 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), |
@@ -2562,6 +2786,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { | |||
2562 | .add_beacon = ath6kl_add_beacon, | 2786 | .add_beacon = ath6kl_add_beacon, |
2563 | .set_beacon = ath6kl_set_beacon, | 2787 | .set_beacon = ath6kl_set_beacon, |
2564 | .del_beacon = ath6kl_del_beacon, | 2788 | .del_beacon = ath6kl_del_beacon, |
2789 | .del_station = ath6kl_del_station, | ||
2565 | .change_station = ath6kl_change_station, | 2790 | .change_station = ath6kl_change_station, |
2566 | .remain_on_channel = ath6kl_remain_on_channel, | 2791 | .remain_on_channel = ath6kl_remain_on_channel, |
2567 | .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, | 2792 | .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, |
@@ -2629,122 +2854,9 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar) | |||
2629 | ath6kl_cfg80211_stop(vif); | 2854 | ath6kl_cfg80211_stop(vif); |
2630 | } | 2855 | } |
2631 | 2856 | ||
2632 | struct ath6kl *ath6kl_core_alloc(struct device *dev) | 2857 | static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) |
2633 | { | ||
2634 | struct ath6kl *ar; | ||
2635 | struct wiphy *wiphy; | ||
2636 | u8 ctr; | ||
2637 | |||
2638 | /* create a new wiphy for use with cfg80211 */ | ||
2639 | wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl)); | ||
2640 | |||
2641 | if (!wiphy) { | ||
2642 | ath6kl_err("couldn't allocate wiphy device\n"); | ||
2643 | return NULL; | ||
2644 | } | ||
2645 | |||
2646 | ar = wiphy_priv(wiphy); | ||
2647 | ar->p2p = !!ath6kl_p2p; | ||
2648 | ar->wiphy = wiphy; | ||
2649 | ar->dev = dev; | ||
2650 | |||
2651 | ar->vif_max = 1; | ||
2652 | |||
2653 | ar->max_norm_iface = 1; | ||
2654 | |||
2655 | spin_lock_init(&ar->lock); | ||
2656 | spin_lock_init(&ar->mcastpsq_lock); | ||
2657 | spin_lock_init(&ar->list_lock); | ||
2658 | |||
2659 | init_waitqueue_head(&ar->event_wq); | ||
2660 | sema_init(&ar->sem, 1); | ||
2661 | |||
2662 | INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue); | ||
2663 | INIT_LIST_HEAD(&ar->vif_list); | ||
2664 | |||
2665 | clear_bit(WMI_ENABLED, &ar->flag); | ||
2666 | clear_bit(SKIP_SCAN, &ar->flag); | ||
2667 | clear_bit(DESTROY_IN_PROGRESS, &ar->flag); | ||
2668 | |||
2669 | ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL; | ||
2670 | ar->listen_intvl_b = 0; | ||
2671 | ar->tx_pwr = 0; | ||
2672 | |||
2673 | ar->intra_bss = 1; | ||
2674 | ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; | ||
2675 | |||
2676 | ar->state = ATH6KL_STATE_OFF; | ||
2677 | |||
2678 | memset((u8 *)ar->sta_list, 0, | ||
2679 | AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); | ||
2680 | |||
2681 | /* Init the PS queues */ | ||
2682 | for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { | ||
2683 | spin_lock_init(&ar->sta_list[ctr].psq_lock); | ||
2684 | skb_queue_head_init(&ar->sta_list[ctr].psq); | ||
2685 | } | ||
2686 | |||
2687 | skb_queue_head_init(&ar->mcastpsq); | ||
2688 | |||
2689 | memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); | ||
2690 | |||
2691 | return ar; | ||
2692 | } | ||
2693 | |||
2694 | int ath6kl_register_ieee80211_hw(struct ath6kl *ar) | ||
2695 | { | ||
2696 | struct wiphy *wiphy = ar->wiphy; | ||
2697 | int ret; | ||
2698 | |||
2699 | wiphy->mgmt_stypes = ath6kl_mgmt_stypes; | ||
2700 | |||
2701 | wiphy->max_remain_on_channel_duration = 5000; | ||
2702 | |||
2703 | /* set device pointer for wiphy */ | ||
2704 | set_wiphy_dev(wiphy, ar->dev); | ||
2705 | |||
2706 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
2707 | BIT(NL80211_IFTYPE_ADHOC) | | ||
2708 | BIT(NL80211_IFTYPE_AP); | ||
2709 | if (ar->p2p) { | ||
2710 | wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) | | ||
2711 | BIT(NL80211_IFTYPE_P2P_CLIENT); | ||
2712 | } | ||
2713 | |||
2714 | /* max num of ssids that can be probed during scanning */ | ||
2715 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; | ||
2716 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ | ||
2717 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | ||
2718 | wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; | ||
2719 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
2720 | |||
2721 | wiphy->cipher_suites = cipher_suites; | ||
2722 | wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
2723 | |||
2724 | wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | | ||
2725 | WIPHY_WOWLAN_DISCONNECT | | ||
2726 | WIPHY_WOWLAN_GTK_REKEY_FAILURE | | ||
2727 | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | | ||
2728 | WIPHY_WOWLAN_EAP_IDENTITY_REQ | | ||
2729 | WIPHY_WOWLAN_4WAY_HANDSHAKE; | ||
2730 | wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; | ||
2731 | wiphy->wowlan.pattern_min_len = 1; | ||
2732 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; | ||
2733 | |||
2734 | wiphy->max_sched_scan_ssids = 10; | ||
2735 | |||
2736 | ret = wiphy_register(wiphy); | ||
2737 | if (ret < 0) { | ||
2738 | ath6kl_err("couldn't register wiphy device\n"); | ||
2739 | return ret; | ||
2740 | } | ||
2741 | |||
2742 | return 0; | ||
2743 | } | ||
2744 | |||
2745 | static int ath6kl_init_if_data(struct ath6kl_vif *vif) | ||
2746 | { | 2858 | { |
2747 | vif->aggr_cntxt = aggr_init(vif->ndev); | 2859 | vif->aggr_cntxt = aggr_init(vif); |
2748 | if (!vif->aggr_cntxt) { | 2860 | if (!vif->aggr_cntxt) { |
2749 | ath6kl_err("failed to initialize aggr\n"); | 2861 | ath6kl_err("failed to initialize aggr\n"); |
2750 | return -ENOMEM; | 2862 | return -ENOMEM; |
@@ -2758,12 +2870,15 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif) | |||
2758 | set_bit(WMM_ENABLED, &vif->flags); | 2870 | set_bit(WMM_ENABLED, &vif->flags); |
2759 | spin_lock_init(&vif->if_lock); | 2871 | spin_lock_init(&vif->if_lock); |
2760 | 2872 | ||
2873 | INIT_LIST_HEAD(&vif->mc_filter); | ||
2874 | |||
2761 | return 0; | 2875 | return 0; |
2762 | } | 2876 | } |
2763 | 2877 | ||
2764 | void ath6kl_deinit_if_data(struct ath6kl_vif *vif) | 2878 | void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif) |
2765 | { | 2879 | { |
2766 | struct ath6kl *ar = vif->ar; | 2880 | struct ath6kl *ar = vif->ar; |
2881 | struct ath6kl_mc_filter *mc_filter, *tmp; | ||
2767 | 2882 | ||
2768 | aggr_module_destroy(vif->aggr_cntxt); | 2883 | aggr_module_destroy(vif->aggr_cntxt); |
2769 | 2884 | ||
@@ -2772,6 +2887,11 @@ void ath6kl_deinit_if_data(struct ath6kl_vif *vif) | |||
2772 | if (vif->nw_type == ADHOC_NETWORK) | 2887 | if (vif->nw_type == ADHOC_NETWORK) |
2773 | ar->ibss_if_active = false; | 2888 | ar->ibss_if_active = false; |
2774 | 2889 | ||
2890 | list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { | ||
2891 | list_del(&mc_filter->list); | ||
2892 | kfree(mc_filter); | ||
2893 | } | ||
2894 | |||
2775 | unregister_netdevice(vif->ndev); | 2895 | unregister_netdevice(vif->ndev); |
2776 | 2896 | ||
2777 | ar->num_vif--; | 2897 | ar->num_vif--; |
@@ -2808,8 +2928,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | |||
2808 | 2928 | ||
2809 | ath6kl_init_control_info(vif); | 2929 | ath6kl_init_control_info(vif); |
2810 | 2930 | ||
2811 | /* TODO: Pass interface specific pointer instead of ar */ | 2931 | if (ath6kl_cfg80211_vif_init(vif)) |
2812 | if (ath6kl_init_if_data(vif)) | ||
2813 | goto err; | 2932 | goto err; |
2814 | 2933 | ||
2815 | if (register_netdevice(ndev)) | 2934 | if (register_netdevice(ndev)) |
@@ -2836,8 +2955,89 @@ err: | |||
2836 | return NULL; | 2955 | return NULL; |
2837 | } | 2956 | } |
2838 | 2957 | ||
2839 | void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar) | 2958 | int ath6kl_cfg80211_init(struct ath6kl *ar) |
2959 | { | ||
2960 | struct wiphy *wiphy = ar->wiphy; | ||
2961 | int ret; | ||
2962 | |||
2963 | wiphy->mgmt_stypes = ath6kl_mgmt_stypes; | ||
2964 | |||
2965 | wiphy->max_remain_on_channel_duration = 5000; | ||
2966 | |||
2967 | /* set device pointer for wiphy */ | ||
2968 | set_wiphy_dev(wiphy, ar->dev); | ||
2969 | |||
2970 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
2971 | BIT(NL80211_IFTYPE_ADHOC) | | ||
2972 | BIT(NL80211_IFTYPE_AP); | ||
2973 | if (ar->p2p) { | ||
2974 | wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) | | ||
2975 | BIT(NL80211_IFTYPE_P2P_CLIENT); | ||
2976 | } | ||
2977 | |||
2978 | /* max num of ssids that can be probed during scanning */ | ||
2979 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; | ||
2980 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ | ||
2981 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | ||
2982 | wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; | ||
2983 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
2984 | |||
2985 | wiphy->cipher_suites = cipher_suites; | ||
2986 | wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
2987 | |||
2988 | wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | | ||
2989 | WIPHY_WOWLAN_DISCONNECT | | ||
2990 | WIPHY_WOWLAN_GTK_REKEY_FAILURE | | ||
2991 | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | | ||
2992 | WIPHY_WOWLAN_EAP_IDENTITY_REQ | | ||
2993 | WIPHY_WOWLAN_4WAY_HANDSHAKE; | ||
2994 | wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; | ||
2995 | wiphy->wowlan.pattern_min_len = 1; | ||
2996 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; | ||
2997 | |||
2998 | wiphy->max_sched_scan_ssids = 10; | ||
2999 | |||
3000 | ret = wiphy_register(wiphy); | ||
3001 | if (ret < 0) { | ||
3002 | ath6kl_err("couldn't register wiphy device\n"); | ||
3003 | return ret; | ||
3004 | } | ||
3005 | |||
3006 | return 0; | ||
3007 | } | ||
3008 | |||
3009 | void ath6kl_cfg80211_cleanup(struct ath6kl *ar) | ||
2840 | { | 3010 | { |
2841 | wiphy_unregister(ar->wiphy); | 3011 | wiphy_unregister(ar->wiphy); |
3012 | } | ||
3013 | |||
3014 | struct ath6kl *ath6kl_cfg80211_create(void) | ||
3015 | { | ||
3016 | struct ath6kl *ar; | ||
3017 | struct wiphy *wiphy; | ||
3018 | |||
3019 | /* create a new wiphy for use with cfg80211 */ | ||
3020 | wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl)); | ||
3021 | |||
3022 | if (!wiphy) { | ||
3023 | ath6kl_err("couldn't allocate wiphy device\n"); | ||
3024 | return NULL; | ||
3025 | } | ||
3026 | |||
3027 | ar = wiphy_priv(wiphy); | ||
3028 | ar->wiphy = wiphy; | ||
3029 | |||
3030 | return ar; | ||
3031 | } | ||
3032 | |||
3033 | /* Note: ar variable must not be accessed after calling this! */ | ||
3034 | void ath6kl_cfg80211_destroy(struct ath6kl *ar) | ||
3035 | { | ||
3036 | int i; | ||
3037 | |||
3038 | for (i = 0; i < AP_MAX_NUM_STA; i++) | ||
3039 | kfree(ar->sta_list[i].aggr_conn); | ||
3040 | |||
2842 | wiphy_free(ar->wiphy); | 3041 | wiphy_free(ar->wiphy); |
2843 | } | 3042 | } |
3043 | |||
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index 81f20a572315..3c693b7c0efd 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h | |||
@@ -27,10 +27,6 @@ enum ath6kl_cfg_suspend_mode { | |||
27 | struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | 27 | struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, |
28 | enum nl80211_iftype type, | 28 | enum nl80211_iftype type, |
29 | u8 fw_vif_idx, u8 nw_type); | 29 | u8 fw_vif_idx, u8 nw_type); |
30 | int ath6kl_register_ieee80211_hw(struct ath6kl *ar); | ||
31 | struct ath6kl *ath6kl_core_alloc(struct device *dev); | ||
32 | void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar); | ||
33 | |||
34 | void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); | 30 | void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); |
35 | 31 | ||
36 | void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | 32 | void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, |
@@ -53,7 +49,15 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, | |||
53 | 49 | ||
54 | int ath6kl_cfg80211_resume(struct ath6kl *ar); | 50 | int ath6kl_cfg80211_resume(struct ath6kl *ar); |
55 | 51 | ||
52 | void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif); | ||
53 | |||
56 | void ath6kl_cfg80211_stop(struct ath6kl_vif *vif); | 54 | void ath6kl_cfg80211_stop(struct ath6kl_vif *vif); |
57 | void ath6kl_cfg80211_stop_all(struct ath6kl *ar); | 55 | void ath6kl_cfg80211_stop_all(struct ath6kl *ar); |
58 | 56 | ||
57 | int ath6kl_cfg80211_init(struct ath6kl *ar); | ||
58 | void ath6kl_cfg80211_cleanup(struct ath6kl *ar); | ||
59 | |||
60 | struct ath6kl *ath6kl_cfg80211_create(void); | ||
61 | void ath6kl_cfg80211_destroy(struct ath6kl *ar); | ||
62 | |||
59 | #endif /* ATH6KL_CFG80211_H */ | 63 | #endif /* ATH6KL_CFG80211_H */ |
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index bfd6597763da..f89f1e180da3 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h | |||
@@ -79,8 +79,5 @@ struct ath6kl; | |||
79 | enum htc_credit_dist_reason; | 79 | enum htc_credit_dist_reason; |
80 | struct ath6kl_htc_credit_info; | 80 | struct ath6kl_htc_credit_info; |
81 | 81 | ||
82 | struct ath6kl *ath6kl_core_alloc(struct device *sdev); | ||
83 | int ath6kl_core_init(struct ath6kl *ar); | ||
84 | void ath6kl_core_cleanup(struct ath6kl *ar); | ||
85 | struct sk_buff *ath6kl_buf_alloc(int size); | 82 | struct sk_buff *ath6kl_buf_alloc(int size); |
86 | #endif /* COMMON_H */ | 83 | #endif /* COMMON_H */ |
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c new file mode 100644 index 000000000000..722ca59b88ce --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/core.c | |||
@@ -0,0 +1,316 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004-2011 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 "core.h" | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/moduleparam.h> | ||
21 | #include <linux/export.h> | ||
22 | |||
23 | #include "debug.h" | ||
24 | #include "hif-ops.h" | ||
25 | #include "cfg80211.h" | ||
26 | |||
27 | unsigned int debug_mask; | ||
28 | static unsigned int suspend_mode; | ||
29 | static unsigned int uart_debug; | ||
30 | static unsigned int ath6kl_p2p; | ||
31 | static unsigned int testmode; | ||
32 | |||
33 | module_param(debug_mask, uint, 0644); | ||
34 | module_param(suspend_mode, uint, 0644); | ||
35 | module_param(uart_debug, uint, 0644); | ||
36 | module_param(ath6kl_p2p, uint, 0644); | ||
37 | module_param(testmode, uint, 0644); | ||
38 | |||
39 | int ath6kl_core_init(struct ath6kl *ar) | ||
40 | { | ||
41 | struct ath6kl_bmi_target_info targ_info; | ||
42 | struct net_device *ndev; | ||
43 | int ret = 0, i; | ||
44 | |||
45 | ar->ath6kl_wq = create_singlethread_workqueue("ath6kl"); | ||
46 | if (!ar->ath6kl_wq) | ||
47 | return -ENOMEM; | ||
48 | |||
49 | ret = ath6kl_bmi_init(ar); | ||
50 | if (ret) | ||
51 | goto err_wq; | ||
52 | |||
53 | /* | ||
54 | * Turn on power to get hardware (target) version and leave power | ||
55 | * on delibrately as we will boot the hardware anyway within few | ||
56 | * seconds. | ||
57 | */ | ||
58 | ret = ath6kl_hif_power_on(ar); | ||
59 | if (ret) | ||
60 | goto err_bmi_cleanup; | ||
61 | |||
62 | ret = ath6kl_bmi_get_target_info(ar, &targ_info); | ||
63 | if (ret) | ||
64 | goto err_power_off; | ||
65 | |||
66 | ar->version.target_ver = le32_to_cpu(targ_info.version); | ||
67 | ar->target_type = le32_to_cpu(targ_info.type); | ||
68 | ar->wiphy->hw_version = le32_to_cpu(targ_info.version); | ||
69 | |||
70 | ret = ath6kl_init_hw_params(ar); | ||
71 | if (ret) | ||
72 | goto err_power_off; | ||
73 | |||
74 | ar->htc_target = ath6kl_htc_create(ar); | ||
75 | |||
76 | if (!ar->htc_target) { | ||
77 | ret = -ENOMEM; | ||
78 | goto err_power_off; | ||
79 | } | ||
80 | |||
81 | ar->testmode = testmode; | ||
82 | |||
83 | ret = ath6kl_init_fetch_firmwares(ar); | ||
84 | if (ret) | ||
85 | goto err_htc_cleanup; | ||
86 | |||
87 | /* FIXME: we should free all firmwares in the error cases below */ | ||
88 | |||
89 | /* Indicate that WMI is enabled (although not ready yet) */ | ||
90 | set_bit(WMI_ENABLED, &ar->flag); | ||
91 | ar->wmi = ath6kl_wmi_init(ar); | ||
92 | if (!ar->wmi) { | ||
93 | ath6kl_err("failed to initialize wmi\n"); | ||
94 | ret = -EIO; | ||
95 | goto err_htc_cleanup; | ||
96 | } | ||
97 | |||
98 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); | ||
99 | |||
100 | ret = ath6kl_cfg80211_init(ar); | ||
101 | if (ret) | ||
102 | goto err_node_cleanup; | ||
103 | |||
104 | ret = ath6kl_debug_init(ar); | ||
105 | if (ret) { | ||
106 | wiphy_unregister(ar->wiphy); | ||
107 | goto err_node_cleanup; | ||
108 | } | ||
109 | |||
110 | for (i = 0; i < ar->vif_max; i++) | ||
111 | ar->avail_idx_map |= BIT(i); | ||
112 | |||
113 | rtnl_lock(); | ||
114 | |||
115 | /* Add an initial station interface */ | ||
116 | ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0, | ||
117 | INFRA_NETWORK); | ||
118 | |||
119 | rtnl_unlock(); | ||
120 | |||
121 | if (!ndev) { | ||
122 | ath6kl_err("Failed to instantiate a network device\n"); | ||
123 | ret = -ENOMEM; | ||
124 | wiphy_unregister(ar->wiphy); | ||
125 | goto err_debug_init; | ||
126 | } | ||
127 | |||
128 | |||
129 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n", | ||
130 | __func__, ndev->name, ndev, ar); | ||
131 | |||
132 | /* setup access class priority mappings */ | ||
133 | ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */ | ||
134 | ar->ac_stream_pri_map[WMM_AC_BE] = 1; | ||
135 | ar->ac_stream_pri_map[WMM_AC_VI] = 2; | ||
136 | ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */ | ||
137 | |||
138 | /* give our connected endpoints some buffers */ | ||
139 | ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep); | ||
140 | ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]); | ||
141 | |||
142 | /* allocate some buffers that handle larger AMSDU frames */ | ||
143 | ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS); | ||
144 | |||
145 | ath6kl_cookie_init(ar); | ||
146 | |||
147 | ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | | ||
148 | ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; | ||
149 | |||
150 | if (suspend_mode && | ||
151 | suspend_mode >= WLAN_POWER_STATE_CUT_PWR && | ||
152 | suspend_mode <= WLAN_POWER_STATE_WOW) | ||
153 | ar->suspend_mode = suspend_mode; | ||
154 | else | ||
155 | ar->suspend_mode = 0; | ||
156 | |||
157 | if (uart_debug) | ||
158 | ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; | ||
159 | |||
160 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | ||
161 | WIPHY_FLAG_HAVE_AP_SME | | ||
162 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
163 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
164 | |||
165 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) | ||
166 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
167 | |||
168 | ar->wiphy->probe_resp_offload = | ||
169 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | ||
170 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | ||
171 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | | ||
172 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; | ||
173 | |||
174 | set_bit(FIRST_BOOT, &ar->flag); | ||
175 | |||
176 | ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; | ||
177 | |||
178 | ret = ath6kl_init_hw_start(ar); | ||
179 | if (ret) { | ||
180 | ath6kl_err("Failed to start hardware: %d\n", ret); | ||
181 | goto err_rxbuf_cleanup; | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * Set mac address which is received in ready event | ||
186 | * FIXME: Move to ath6kl_interface_add() | ||
187 | */ | ||
188 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); | ||
189 | |||
190 | return ret; | ||
191 | |||
192 | err_rxbuf_cleanup: | ||
193 | ath6kl_htc_flush_rx_buf(ar->htc_target); | ||
194 | ath6kl_cleanup_amsdu_rxbufs(ar); | ||
195 | rtnl_lock(); | ||
196 | ath6kl_cfg80211_vif_cleanup(netdev_priv(ndev)); | ||
197 | rtnl_unlock(); | ||
198 | wiphy_unregister(ar->wiphy); | ||
199 | err_debug_init: | ||
200 | ath6kl_debug_cleanup(ar); | ||
201 | err_node_cleanup: | ||
202 | ath6kl_wmi_shutdown(ar->wmi); | ||
203 | clear_bit(WMI_ENABLED, &ar->flag); | ||
204 | ar->wmi = NULL; | ||
205 | err_htc_cleanup: | ||
206 | ath6kl_htc_cleanup(ar->htc_target); | ||
207 | err_power_off: | ||
208 | ath6kl_hif_power_off(ar); | ||
209 | err_bmi_cleanup: | ||
210 | ath6kl_bmi_cleanup(ar); | ||
211 | err_wq: | ||
212 | destroy_workqueue(ar->ath6kl_wq); | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | EXPORT_SYMBOL(ath6kl_core_init); | ||
217 | |||
218 | struct ath6kl *ath6kl_core_create(struct device *dev) | ||
219 | { | ||
220 | struct ath6kl *ar; | ||
221 | u8 ctr; | ||
222 | |||
223 | ar = ath6kl_cfg80211_create(); | ||
224 | if (!ar) | ||
225 | return NULL; | ||
226 | |||
227 | ar->p2p = !!ath6kl_p2p; | ||
228 | ar->dev = dev; | ||
229 | |||
230 | ar->vif_max = 1; | ||
231 | |||
232 | ar->max_norm_iface = 1; | ||
233 | |||
234 | spin_lock_init(&ar->lock); | ||
235 | spin_lock_init(&ar->mcastpsq_lock); | ||
236 | spin_lock_init(&ar->list_lock); | ||
237 | |||
238 | init_waitqueue_head(&ar->event_wq); | ||
239 | sema_init(&ar->sem, 1); | ||
240 | |||
241 | INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue); | ||
242 | INIT_LIST_HEAD(&ar->vif_list); | ||
243 | |||
244 | clear_bit(WMI_ENABLED, &ar->flag); | ||
245 | clear_bit(SKIP_SCAN, &ar->flag); | ||
246 | clear_bit(DESTROY_IN_PROGRESS, &ar->flag); | ||
247 | |||
248 | ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL; | ||
249 | ar->tx_pwr = 0; | ||
250 | |||
251 | ar->intra_bss = 1; | ||
252 | ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; | ||
253 | |||
254 | ar->state = ATH6KL_STATE_OFF; | ||
255 | |||
256 | memset((u8 *)ar->sta_list, 0, | ||
257 | AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); | ||
258 | |||
259 | /* Init the PS queues */ | ||
260 | for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { | ||
261 | spin_lock_init(&ar->sta_list[ctr].psq_lock); | ||
262 | skb_queue_head_init(&ar->sta_list[ctr].psq); | ||
263 | skb_queue_head_init(&ar->sta_list[ctr].apsdq); | ||
264 | ar->sta_list[ctr].aggr_conn = | ||
265 | kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL); | ||
266 | if (!ar->sta_list[ctr].aggr_conn) { | ||
267 | ath6kl_err("Failed to allocate memory for sta aggregation information\n"); | ||
268 | ath6kl_core_destroy(ar); | ||
269 | return NULL; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | skb_queue_head_init(&ar->mcastpsq); | ||
274 | |||
275 | memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); | ||
276 | |||
277 | return ar; | ||
278 | } | ||
279 | EXPORT_SYMBOL(ath6kl_core_create); | ||
280 | |||
281 | void ath6kl_core_cleanup(struct ath6kl *ar) | ||
282 | { | ||
283 | ath6kl_hif_power_off(ar); | ||
284 | |||
285 | destroy_workqueue(ar->ath6kl_wq); | ||
286 | |||
287 | if (ar->htc_target) | ||
288 | ath6kl_htc_cleanup(ar->htc_target); | ||
289 | |||
290 | ath6kl_cookie_cleanup(ar); | ||
291 | |||
292 | ath6kl_cleanup_amsdu_rxbufs(ar); | ||
293 | |||
294 | ath6kl_bmi_cleanup(ar); | ||
295 | |||
296 | ath6kl_debug_cleanup(ar); | ||
297 | |||
298 | kfree(ar->fw_board); | ||
299 | kfree(ar->fw_otp); | ||
300 | kfree(ar->fw); | ||
301 | kfree(ar->fw_patch); | ||
302 | kfree(ar->fw_testscript); | ||
303 | |||
304 | ath6kl_cfg80211_cleanup(ar); | ||
305 | } | ||
306 | EXPORT_SYMBOL(ath6kl_core_cleanup); | ||
307 | |||
308 | void ath6kl_core_destroy(struct ath6kl *ar) | ||
309 | { | ||
310 | ath6kl_cfg80211_destroy(ar); | ||
311 | } | ||
312 | EXPORT_SYMBOL(ath6kl_core_destroy); | ||
313 | |||
314 | MODULE_AUTHOR("Qualcomm Atheros"); | ||
315 | MODULE_DESCRIPTION("Core module for AR600x SDIO and USB devices."); | ||
316 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index c863a28f2e0c..c4d66e066dc9 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -44,6 +44,10 @@ | |||
44 | #define ATH6KL_MAX_ENDPOINTS 4 | 44 | #define ATH6KL_MAX_ENDPOINTS 4 |
45 | #define MAX_NODE_NUM 15 | 45 | #define MAX_NODE_NUM 15 |
46 | 46 | ||
47 | #define ATH6KL_APSD_ALL_FRAME 0xFFFF | ||
48 | #define ATH6KL_APSD_NUM_OF_AC 0x4 | ||
49 | #define ATH6KL_APSD_FRAME_MASK 0xF | ||
50 | |||
47 | /* Extra bytes for htc header alignment */ | 51 | /* Extra bytes for htc header alignment */ |
48 | #define ATH6KL_HTC_ALIGN_BYTES 3 | 52 | #define ATH6KL_HTC_ALIGN_BYTES 3 |
49 | 53 | ||
@@ -55,7 +59,7 @@ | |||
55 | #define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC) | 59 | #define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC) |
56 | 60 | ||
57 | #define DISCON_TIMER_INTVAL 10000 /* in msec */ | 61 | #define DISCON_TIMER_INTVAL 10000 /* in msec */ |
58 | #define A_DEFAULT_LISTEN_INTERVAL 100 | 62 | #define A_DEFAULT_LISTEN_INTERVAL 1 /* beacon intervals */ |
59 | #define A_MAX_WOW_LISTEN_INTERVAL 1000 | 63 | #define A_MAX_WOW_LISTEN_INTERVAL 1000 |
60 | 64 | ||
61 | /* includes also the null byte */ | 65 | /* includes also the null byte */ |
@@ -97,45 +101,49 @@ struct ath6kl_fw_ie { | |||
97 | u8 data[0]; | 101 | u8 data[0]; |
98 | }; | 102 | }; |
99 | 103 | ||
104 | #define ATH6KL_FW_API2_FILE "fw-2.bin" | ||
105 | #define ATH6KL_FW_API3_FILE "fw-3.bin" | ||
106 | |||
100 | /* AR6003 1.0 definitions */ | 107 | /* AR6003 1.0 definitions */ |
101 | #define AR6003_HW_1_0_VERSION 0x300002ba | 108 | #define AR6003_HW_1_0_VERSION 0x300002ba |
102 | 109 | ||
103 | /* AR6003 2.0 definitions */ | 110 | /* AR6003 2.0 definitions */ |
104 | #define AR6003_HW_2_0_VERSION 0x30000384 | 111 | #define AR6003_HW_2_0_VERSION 0x30000384 |
105 | #define AR6003_HW_2_0_PATCH_DOWNLOAD_ADDRESS 0x57e910 | 112 | #define AR6003_HW_2_0_PATCH_DOWNLOAD_ADDRESS 0x57e910 |
106 | #define AR6003_HW_2_0_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" | 113 | #define AR6003_HW_2_0_FW_DIR "ath6k/AR6003/hw2.0" |
107 | #define AR6003_HW_2_0_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" | 114 | #define AR6003_HW_2_0_OTP_FILE "otp.bin.z77" |
108 | #define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" | 115 | #define AR6003_HW_2_0_FIRMWARE_FILE "athwlan.bin.z77" |
109 | #define AR6003_HW_2_0_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" | 116 | #define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" |
110 | #define AR6003_HW_2_0_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin" | 117 | #define AR6003_HW_2_0_PATCH_FILE "data.patch.bin" |
111 | #define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" | 118 | #define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" |
112 | #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ | 119 | #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ |
113 | "ath6k/AR6003/hw2.0/bdata.SD31.bin" | 120 | "ath6k/AR6003/hw2.0/bdata.SD31.bin" |
114 | 121 | ||
115 | /* AR6003 3.0 definitions */ | 122 | /* AR6003 3.0 definitions */ |
116 | #define AR6003_HW_2_1_1_VERSION 0x30000582 | 123 | #define AR6003_HW_2_1_1_VERSION 0x30000582 |
117 | #define AR6003_HW_2_1_1_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" | 124 | #define AR6003_HW_2_1_1_FW_DIR "ath6k/AR6003/hw2.1.1" |
118 | #define AR6003_HW_2_1_1_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" | 125 | #define AR6003_HW_2_1_1_OTP_FILE "otp.bin" |
119 | #define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE \ | 126 | #define AR6003_HW_2_1_1_FIRMWARE_FILE "athwlan.bin" |
120 | "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" | 127 | #define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" |
121 | #define AR6003_HW_2_1_1_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" | 128 | #define AR6003_HW_2_1_1_UTF_FIRMWARE_FILE "utf.bin" |
122 | #define AR6003_HW_2_1_1_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin" | 129 | #define AR6003_HW_2_1_1_TESTSCRIPT_FILE "nullTestFlow.bin" |
130 | #define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin" | ||
123 | #define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" | 131 | #define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" |
124 | #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ | 132 | #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ |
125 | "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" | 133 | "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" |
126 | 134 | ||
127 | /* AR6004 1.0 definitions */ | 135 | /* AR6004 1.0 definitions */ |
128 | #define AR6004_HW_1_0_VERSION 0x30000623 | 136 | #define AR6004_HW_1_0_VERSION 0x30000623 |
129 | #define AR6004_HW_1_0_FIRMWARE_2_FILE "ath6k/AR6004/hw1.0/fw-2.bin" | 137 | #define AR6004_HW_1_0_FW_DIR "ath6k/AR6004/hw1.0" |
130 | #define AR6004_HW_1_0_FIRMWARE_FILE "ath6k/AR6004/hw1.0/fw.ram.bin" | 138 | #define AR6004_HW_1_0_FIRMWARE_FILE "fw.ram.bin" |
131 | #define AR6004_HW_1_0_BOARD_DATA_FILE "ath6k/AR6004/hw1.0/bdata.bin" | 139 | #define AR6004_HW_1_0_BOARD_DATA_FILE "ath6k/AR6004/hw1.0/bdata.bin" |
132 | #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ | 140 | #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ |
133 | "ath6k/AR6004/hw1.0/bdata.DB132.bin" | 141 | "ath6k/AR6004/hw1.0/bdata.DB132.bin" |
134 | 142 | ||
135 | /* AR6004 1.1 definitions */ | 143 | /* AR6004 1.1 definitions */ |
136 | #define AR6004_HW_1_1_VERSION 0x30000001 | 144 | #define AR6004_HW_1_1_VERSION 0x30000001 |
137 | #define AR6004_HW_1_1_FIRMWARE_2_FILE "ath6k/AR6004/hw1.1/fw-2.bin" | 145 | #define AR6004_HW_1_1_FW_DIR "ath6k/AR6004/hw1.1" |
138 | #define AR6004_HW_1_1_FIRMWARE_FILE "ath6k/AR6004/hw1.1/fw.ram.bin" | 146 | #define AR6004_HW_1_1_FIRMWARE_FILE "fw.ram.bin" |
139 | #define AR6004_HW_1_1_BOARD_DATA_FILE "ath6k/AR6004/hw1.1/bdata.bin" | 147 | #define AR6004_HW_1_1_BOARD_DATA_FILE "ath6k/AR6004/hw1.1/bdata.bin" |
140 | #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ | 148 | #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ |
141 | "ath6k/AR6004/hw1.1/bdata.DB132.bin" | 149 | "ath6k/AR6004/hw1.1/bdata.DB132.bin" |
@@ -144,6 +152,8 @@ struct ath6kl_fw_ie { | |||
144 | #define STA_PS_AWAKE BIT(0) | 152 | #define STA_PS_AWAKE BIT(0) |
145 | #define STA_PS_SLEEP BIT(1) | 153 | #define STA_PS_SLEEP BIT(1) |
146 | #define STA_PS_POLLED BIT(2) | 154 | #define STA_PS_POLLED BIT(2) |
155 | #define STA_PS_APSD_TRIGGER BIT(3) | ||
156 | #define STA_PS_APSD_EOSP BIT(4) | ||
147 | 157 | ||
148 | /* HTC TX packet tagging definitions */ | 158 | /* HTC TX packet tagging definitions */ |
149 | #define ATH6KL_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED | 159 | #define ATH6KL_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED |
@@ -186,7 +196,7 @@ struct ath6kl_fw_ie { | |||
186 | #define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1) | 196 | #define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1) |
187 | #define ATH6KL_CONF_ENABLE_11N BIT(2) | 197 | #define ATH6KL_CONF_ENABLE_11N BIT(2) |
188 | #define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) | 198 | #define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) |
189 | #define ATH6KL_CONF_SUSPEND_CUTPOWER BIT(4) | 199 | #define ATH6KL_CONF_UART_DEBUG BIT(4) |
190 | 200 | ||
191 | enum wlan_low_pwr_state { | 201 | enum wlan_low_pwr_state { |
192 | WLAN_POWER_STATE_ON, | 202 | WLAN_POWER_STATE_ON, |
@@ -231,14 +241,19 @@ struct rxtid_stats { | |||
231 | u32 num_bar; | 241 | u32 num_bar; |
232 | }; | 242 | }; |
233 | 243 | ||
234 | struct aggr_info { | 244 | struct aggr_info_conn { |
235 | u8 aggr_sz; | 245 | u8 aggr_sz; |
236 | u8 timer_scheduled; | 246 | u8 timer_scheduled; |
237 | struct timer_list timer; | 247 | struct timer_list timer; |
238 | struct net_device *dev; | 248 | struct net_device *dev; |
239 | struct rxtid rx_tid[NUM_OF_TIDS]; | 249 | struct rxtid rx_tid[NUM_OF_TIDS]; |
240 | struct sk_buff_head free_q; | ||
241 | struct rxtid_stats stat[NUM_OF_TIDS]; | 250 | struct rxtid_stats stat[NUM_OF_TIDS]; |
251 | struct aggr_info *aggr_info; | ||
252 | }; | ||
253 | |||
254 | struct aggr_info { | ||
255 | struct aggr_info_conn *aggr_conn; | ||
256 | struct sk_buff_head rx_amsdu_freeq; | ||
242 | }; | 257 | }; |
243 | 258 | ||
244 | struct ath6kl_wep_key { | 259 | struct ath6kl_wep_key { |
@@ -280,6 +295,9 @@ struct ath6kl_sta { | |||
280 | u8 wpa_ie[ATH6KL_MAX_IE]; | 295 | u8 wpa_ie[ATH6KL_MAX_IE]; |
281 | struct sk_buff_head psq; | 296 | struct sk_buff_head psq; |
282 | spinlock_t psq_lock; | 297 | spinlock_t psq_lock; |
298 | u8 apsd_info; | ||
299 | struct sk_buff_head apsdq; | ||
300 | struct aggr_info_conn *aggr_conn; | ||
283 | }; | 301 | }; |
284 | 302 | ||
285 | struct ath6kl_version { | 303 | struct ath6kl_version { |
@@ -408,6 +426,13 @@ enum ath6kl_hif_type { | |||
408 | ATH6KL_HIF_TYPE_USB, | 426 | ATH6KL_HIF_TYPE_USB, |
409 | }; | 427 | }; |
410 | 428 | ||
429 | /* Max number of filters that hw supports */ | ||
430 | #define ATH6K_MAX_MC_FILTERS_PER_LIST 7 | ||
431 | struct ath6kl_mc_filter { | ||
432 | struct list_head list; | ||
433 | char hw_addr[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; | ||
434 | }; | ||
435 | |||
411 | /* | 436 | /* |
412 | * Driver's maximum limit, note that some firmwares support only one vif | 437 | * Driver's maximum limit, note that some firmwares support only one vif |
413 | * and the runtime (current) limit must be checked from ar->vif_max. | 438 | * and the runtime (current) limit must be checked from ar->vif_max. |
@@ -426,6 +451,7 @@ enum ath6kl_vif_state { | |||
426 | DTIM_PERIOD_AVAIL, | 451 | DTIM_PERIOD_AVAIL, |
427 | WLAN_ENABLED, | 452 | WLAN_ENABLED, |
428 | STATS_UPDATE_PEND, | 453 | STATS_UPDATE_PEND, |
454 | HOST_SLEEP_MODE_CMD_PROCESSED, | ||
429 | }; | 455 | }; |
430 | 456 | ||
431 | struct ath6kl_vif { | 457 | struct ath6kl_vif { |
@@ -471,6 +497,8 @@ struct ath6kl_vif { | |||
471 | u8 assoc_bss_dtim_period; | 497 | u8 assoc_bss_dtim_period; |
472 | struct net_device_stats net_stats; | 498 | struct net_device_stats net_stats; |
473 | struct target_stats target_stats; | 499 | struct target_stats target_stats; |
500 | |||
501 | struct list_head mc_filter; | ||
474 | }; | 502 | }; |
475 | 503 | ||
476 | #define WOW_LIST_ID 0 | 504 | #define WOW_LIST_ID 0 |
@@ -504,6 +532,7 @@ struct ath6kl { | |||
504 | struct wiphy *wiphy; | 532 | struct wiphy *wiphy; |
505 | 533 | ||
506 | enum ath6kl_state state; | 534 | enum ath6kl_state state; |
535 | unsigned int testmode; | ||
507 | 536 | ||
508 | struct ath6kl_bmi bmi; | 537 | struct ath6kl_bmi bmi; |
509 | const struct ath6kl_hif_ops *hif_ops; | 538 | const struct ath6kl_hif_ops *hif_ops; |
@@ -523,7 +552,6 @@ struct ath6kl { | |||
523 | spinlock_t lock; | 552 | spinlock_t lock; |
524 | struct semaphore sem; | 553 | struct semaphore sem; |
525 | u16 listen_intvl_b; | 554 | u16 listen_intvl_b; |
526 | u16 listen_intvl_t; | ||
527 | u8 lrssi_roam_threshold; | 555 | u8 lrssi_roam_threshold; |
528 | struct ath6kl_version version; | 556 | struct ath6kl_version version; |
529 | u32 target_type; | 557 | u32 target_type; |
@@ -574,17 +602,24 @@ struct ath6kl { | |||
574 | u32 board_addr; | 602 | u32 board_addr; |
575 | u32 refclk_hz; | 603 | u32 refclk_hz; |
576 | u32 uarttx_pin; | 604 | u32 uarttx_pin; |
605 | u32 testscript_addr; | ||
606 | |||
607 | struct ath6kl_hw_fw { | ||
608 | const char *dir; | ||
609 | const char *otp; | ||
610 | const char *fw; | ||
611 | const char *tcmd; | ||
612 | const char *patch; | ||
613 | const char *utf; | ||
614 | const char *testscript; | ||
615 | } fw; | ||
577 | 616 | ||
578 | const char *fw_otp; | ||
579 | const char *fw; | ||
580 | const char *fw_tcmd; | ||
581 | const char *fw_patch; | ||
582 | const char *fw_api2; | ||
583 | const char *fw_board; | 617 | const char *fw_board; |
584 | const char *fw_default_board; | 618 | const char *fw_default_board; |
585 | } hw; | 619 | } hw; |
586 | 620 | ||
587 | u16 conf_flags; | 621 | u16 conf_flags; |
622 | u16 suspend_mode; | ||
588 | wait_queue_head_t event_wq; | 623 | wait_queue_head_t event_wq; |
589 | struct ath6kl_mbox_info mbox_info; | 624 | struct ath6kl_mbox_info mbox_info; |
590 | 625 | ||
@@ -603,6 +638,10 @@ struct ath6kl { | |||
603 | u8 *fw_patch; | 638 | u8 *fw_patch; |
604 | size_t fw_patch_len; | 639 | size_t fw_patch_len; |
605 | 640 | ||
641 | u8 *fw_testscript; | ||
642 | size_t fw_testscript_len; | ||
643 | |||
644 | unsigned int fw_api; | ||
606 | unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN]; | 645 | unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN]; |
607 | 646 | ||
608 | struct workqueue_struct *ath6kl_wq; | 647 | struct workqueue_struct *ath6kl_wq; |
@@ -676,7 +715,9 @@ struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar); | |||
676 | void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); | 715 | void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); |
677 | int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); | 716 | int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); |
678 | 717 | ||
679 | struct aggr_info *aggr_init(struct net_device *dev); | 718 | struct aggr_info *aggr_init(struct ath6kl_vif *vif); |
719 | void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info, | ||
720 | struct aggr_info_conn *aggr_conn); | ||
680 | void ath6kl_rx_refill(struct htc_target *target, | 721 | void ath6kl_rx_refill(struct htc_target *target, |
681 | enum htc_endpoint_id endpoint); | 722 | enum htc_endpoint_id endpoint); |
682 | void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); | 723 | void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); |
@@ -684,7 +725,7 @@ struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target, | |||
684 | enum htc_endpoint_id endpoint, | 725 | enum htc_endpoint_id endpoint, |
685 | int len); | 726 | int len); |
686 | void aggr_module_destroy(struct aggr_info *aggr_info); | 727 | void aggr_module_destroy(struct aggr_info *aggr_info); |
687 | void aggr_reset_state(struct aggr_info *aggr_info); | 728 | void aggr_reset_state(struct aggr_info_conn *aggr_conn); |
688 | 729 | ||
689 | struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr); | 730 | struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr); |
690 | struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); | 731 | struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); |
@@ -700,7 +741,7 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
700 | void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel); | 741 | void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel); |
701 | void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, | 742 | void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, |
702 | u8 keymgmt, u8 ucipher, u8 auth, | 743 | u8 keymgmt, u8 ucipher, u8 auth, |
703 | u8 assoc_req_len, u8 *assoc_info); | 744 | u8 assoc_req_len, u8 *assoc_info, u8 apsd_info); |
704 | void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, | 745 | void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, |
705 | u8 *bssid, u8 assoc_resp_len, | 746 | u8 *bssid, u8 assoc_resp_len, |
706 | u8 *assoc_info, u16 prot_reason_status); | 747 | u8 *assoc_info, u16 prot_reason_status); |
@@ -723,12 +764,18 @@ void ath6kl_wakeup_event(void *dev); | |||
723 | void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, | 764 | void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, |
724 | bool wait_fot_compltn, bool cold_reset); | 765 | bool wait_fot_compltn, bool cold_reset); |
725 | void ath6kl_init_control_info(struct ath6kl_vif *vif); | 766 | void ath6kl_init_control_info(struct ath6kl_vif *vif); |
726 | void ath6kl_deinit_if_data(struct ath6kl_vif *vif); | ||
727 | void ath6kl_core_free(struct ath6kl *ar); | ||
728 | struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); | 767 | struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); |
729 | void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready); | 768 | void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready); |
730 | int ath6kl_init_hw_start(struct ath6kl *ar); | 769 | int ath6kl_init_hw_start(struct ath6kl *ar); |
731 | int ath6kl_init_hw_stop(struct ath6kl *ar); | 770 | int ath6kl_init_hw_stop(struct ath6kl *ar); |
771 | int ath6kl_init_fetch_firmwares(struct ath6kl *ar); | ||
772 | int ath6kl_init_hw_params(struct ath6kl *ar); | ||
773 | |||
732 | void ath6kl_check_wow_status(struct ath6kl *ar); | 774 | void ath6kl_check_wow_status(struct ath6kl *ar); |
733 | 775 | ||
776 | struct ath6kl *ath6kl_core_create(struct device *dev); | ||
777 | int ath6kl_core_init(struct ath6kl *ar); | ||
778 | void ath6kl_core_cleanup(struct ath6kl *ar); | ||
779 | void ath6kl_core_destroy(struct ath6kl *ar); | ||
780 | |||
734 | #endif /* CORE_H */ | 781 | #endif /* CORE_H */ |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index eb808b46f94c..d832058816fe 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -54,9 +54,42 @@ int ath6kl_printk(const char *level, const char *fmt, ...) | |||
54 | 54 | ||
55 | return rtn; | 55 | return rtn; |
56 | } | 56 | } |
57 | EXPORT_SYMBOL(ath6kl_printk); | ||
57 | 58 | ||
58 | #ifdef CONFIG_ATH6KL_DEBUG | 59 | #ifdef CONFIG_ATH6KL_DEBUG |
59 | 60 | ||
61 | void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) | ||
62 | { | ||
63 | struct va_format vaf; | ||
64 | va_list args; | ||
65 | |||
66 | if (!(debug_mask & mask)) | ||
67 | return; | ||
68 | |||
69 | va_start(args, fmt); | ||
70 | |||
71 | vaf.fmt = fmt; | ||
72 | vaf.va = &args; | ||
73 | |||
74 | ath6kl_printk(KERN_DEBUG, "%pV", &vaf); | ||
75 | |||
76 | va_end(args); | ||
77 | } | ||
78 | EXPORT_SYMBOL(ath6kl_dbg); | ||
79 | |||
80 | void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, | ||
81 | const char *msg, const char *prefix, | ||
82 | const void *buf, size_t len) | ||
83 | { | ||
84 | if (debug_mask & mask) { | ||
85 | if (msg) | ||
86 | ath6kl_dbg(mask, "%s\n", msg); | ||
87 | |||
88 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); | ||
89 | } | ||
90 | } | ||
91 | EXPORT_SYMBOL(ath6kl_dbg_dump); | ||
92 | |||
60 | #define REG_OUTPUT_LEN_PER_LINE 25 | 93 | #define REG_OUTPUT_LEN_PER_LINE 25 |
61 | #define REGTYPE_STR_LEN 100 | 94 | #define REGTYPE_STR_LEN 100 |
62 | 95 | ||
@@ -82,31 +115,31 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, | |||
82 | struct ath6kl_irq_enable_reg *irq_enable_reg) | 115 | struct ath6kl_irq_enable_reg *irq_enable_reg) |
83 | { | 116 | { |
84 | 117 | ||
85 | ath6kl_dbg(ATH6KL_DBG_ANY, ("<------- Register Table -------->\n")); | 118 | ath6kl_dbg(ATH6KL_DBG_IRQ, ("<------- Register Table -------->\n")); |
86 | 119 | ||
87 | if (irq_proc_reg != NULL) { | 120 | if (irq_proc_reg != NULL) { |
88 | ath6kl_dbg(ATH6KL_DBG_ANY, | 121 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
89 | "Host Int status: 0x%x\n", | 122 | "Host Int status: 0x%x\n", |
90 | irq_proc_reg->host_int_status); | 123 | irq_proc_reg->host_int_status); |
91 | ath6kl_dbg(ATH6KL_DBG_ANY, | 124 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
92 | "CPU Int status: 0x%x\n", | 125 | "CPU Int status: 0x%x\n", |
93 | irq_proc_reg->cpu_int_status); | 126 | irq_proc_reg->cpu_int_status); |
94 | ath6kl_dbg(ATH6KL_DBG_ANY, | 127 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
95 | "Error Int status: 0x%x\n", | 128 | "Error Int status: 0x%x\n", |
96 | irq_proc_reg->error_int_status); | 129 | irq_proc_reg->error_int_status); |
97 | ath6kl_dbg(ATH6KL_DBG_ANY, | 130 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
98 | "Counter Int status: 0x%x\n", | 131 | "Counter Int status: 0x%x\n", |
99 | irq_proc_reg->counter_int_status); | 132 | irq_proc_reg->counter_int_status); |
100 | ath6kl_dbg(ATH6KL_DBG_ANY, | 133 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
101 | "Mbox Frame: 0x%x\n", | 134 | "Mbox Frame: 0x%x\n", |
102 | irq_proc_reg->mbox_frame); | 135 | irq_proc_reg->mbox_frame); |
103 | ath6kl_dbg(ATH6KL_DBG_ANY, | 136 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
104 | "Rx Lookahead Valid: 0x%x\n", | 137 | "Rx Lookahead Valid: 0x%x\n", |
105 | irq_proc_reg->rx_lkahd_valid); | 138 | irq_proc_reg->rx_lkahd_valid); |
106 | ath6kl_dbg(ATH6KL_DBG_ANY, | 139 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
107 | "Rx Lookahead 0: 0x%x\n", | 140 | "Rx Lookahead 0: 0x%x\n", |
108 | irq_proc_reg->rx_lkahd[0]); | 141 | irq_proc_reg->rx_lkahd[0]); |
109 | ath6kl_dbg(ATH6KL_DBG_ANY, | 142 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
110 | "Rx Lookahead 1: 0x%x\n", | 143 | "Rx Lookahead 1: 0x%x\n", |
111 | irq_proc_reg->rx_lkahd[1]); | 144 | irq_proc_reg->rx_lkahd[1]); |
112 | 145 | ||
@@ -115,16 +148,16 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, | |||
115 | * If the target supports GMBOX hardware, dump some | 148 | * If the target supports GMBOX hardware, dump some |
116 | * additional state. | 149 | * additional state. |
117 | */ | 150 | */ |
118 | ath6kl_dbg(ATH6KL_DBG_ANY, | 151 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
119 | "GMBOX Host Int status 2: 0x%x\n", | 152 | "GMBOX Host Int status 2: 0x%x\n", |
120 | irq_proc_reg->host_int_status2); | 153 | irq_proc_reg->host_int_status2); |
121 | ath6kl_dbg(ATH6KL_DBG_ANY, | 154 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
122 | "GMBOX RX Avail: 0x%x\n", | 155 | "GMBOX RX Avail: 0x%x\n", |
123 | irq_proc_reg->gmbox_rx_avail); | 156 | irq_proc_reg->gmbox_rx_avail); |
124 | ath6kl_dbg(ATH6KL_DBG_ANY, | 157 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
125 | "GMBOX lookahead alias 0: 0x%x\n", | 158 | "GMBOX lookahead alias 0: 0x%x\n", |
126 | irq_proc_reg->rx_gmbox_lkahd_alias[0]); | 159 | irq_proc_reg->rx_gmbox_lkahd_alias[0]); |
127 | ath6kl_dbg(ATH6KL_DBG_ANY, | 160 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
128 | "GMBOX lookahead alias 1: 0x%x\n", | 161 | "GMBOX lookahead alias 1: 0x%x\n", |
129 | irq_proc_reg->rx_gmbox_lkahd_alias[1]); | 162 | irq_proc_reg->rx_gmbox_lkahd_alias[1]); |
130 | } | 163 | } |
@@ -132,13 +165,13 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, | |||
132 | } | 165 | } |
133 | 166 | ||
134 | if (irq_enable_reg != NULL) { | 167 | if (irq_enable_reg != NULL) { |
135 | ath6kl_dbg(ATH6KL_DBG_ANY, | 168 | ath6kl_dbg(ATH6KL_DBG_IRQ, |
136 | "Int status Enable: 0x%x\n", | 169 | "Int status Enable: 0x%x\n", |
137 | irq_enable_reg->int_status_en); | 170 | irq_enable_reg->int_status_en); |
138 | ath6kl_dbg(ATH6KL_DBG_ANY, "Counter Int status Enable: 0x%x\n", | 171 | ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n", |
139 | irq_enable_reg->cntr_int_status_en); | 172 | irq_enable_reg->cntr_int_status_en); |
140 | } | 173 | } |
141 | ath6kl_dbg(ATH6KL_DBG_ANY, "<------------------------------->\n"); | 174 | ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n"); |
142 | } | 175 | } |
143 | 176 | ||
144 | static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist) | 177 | static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist) |
@@ -175,9 +208,6 @@ void dump_cred_dist_stats(struct htc_target *target) | |||
175 | { | 208 | { |
176 | struct htc_endpoint_credit_dist *ep_list; | 209 | struct htc_endpoint_credit_dist *ep_list; |
177 | 210 | ||
178 | if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_CREDIT)) | ||
179 | return; | ||
180 | |||
181 | list_for_each_entry(ep_list, &target->cred_dist_list, list) | 211 | list_for_each_entry(ep_list, &target->cred_dist_list, list) |
182 | dump_cred_dist(ep_list); | 212 | dump_cred_dist(ep_list); |
183 | 213 | ||
@@ -1411,6 +1441,8 @@ static ssize_t ath6kl_create_qos_write(struct file *file, | |||
1411 | return -EINVAL; | 1441 | return -EINVAL; |
1412 | pstream.medium_time = cpu_to_le32(val32); | 1442 | pstream.medium_time = cpu_to_le32(val32); |
1413 | 1443 | ||
1444 | pstream.nominal_phy = le32_to_cpu(pstream.min_phy_rate) / 1000000; | ||
1445 | |||
1414 | ath6kl_wmi_create_pstream_cmd(ar->wmi, vif->fw_vif_idx, &pstream); | 1446 | ath6kl_wmi_create_pstream_cmd(ar->wmi, vif->fw_vif_idx, &pstream); |
1415 | 1447 | ||
1416 | return count; | 1448 | return count; |
@@ -1505,57 +1537,46 @@ static const struct file_operations fops_bgscan_int = { | |||
1505 | }; | 1537 | }; |
1506 | 1538 | ||
1507 | static ssize_t ath6kl_listen_int_write(struct file *file, | 1539 | static ssize_t ath6kl_listen_int_write(struct file *file, |
1508 | const char __user *user_buf, | 1540 | const char __user *user_buf, |
1509 | size_t count, loff_t *ppos) | 1541 | size_t count, loff_t *ppos) |
1510 | { | 1542 | { |
1511 | struct ath6kl *ar = file->private_data; | 1543 | struct ath6kl *ar = file->private_data; |
1512 | u16 listen_int_t, listen_int_b; | 1544 | struct ath6kl_vif *vif; |
1545 | u16 listen_interval; | ||
1513 | char buf[32]; | 1546 | char buf[32]; |
1514 | char *sptr, *token; | ||
1515 | ssize_t len; | 1547 | ssize_t len; |
1516 | 1548 | ||
1549 | vif = ath6kl_vif_first(ar); | ||
1550 | if (!vif) | ||
1551 | return -EIO; | ||
1552 | |||
1517 | len = min(count, sizeof(buf) - 1); | 1553 | len = min(count, sizeof(buf) - 1); |
1518 | if (copy_from_user(buf, user_buf, len)) | 1554 | if (copy_from_user(buf, user_buf, len)) |
1519 | return -EFAULT; | 1555 | return -EFAULT; |
1520 | 1556 | ||
1521 | buf[len] = '\0'; | 1557 | buf[len] = '\0'; |
1522 | sptr = buf; | 1558 | if (kstrtou16(buf, 0, &listen_interval)) |
1523 | |||
1524 | token = strsep(&sptr, " "); | ||
1525 | if (!token) | ||
1526 | return -EINVAL; | ||
1527 | |||
1528 | if (kstrtou16(token, 0, &listen_int_t)) | ||
1529 | return -EINVAL; | ||
1530 | |||
1531 | if (kstrtou16(sptr, 0, &listen_int_b)) | ||
1532 | return -EINVAL; | ||
1533 | |||
1534 | if ((listen_int_t < 15) || (listen_int_t > 5000)) | ||
1535 | return -EINVAL; | 1559 | return -EINVAL; |
1536 | 1560 | ||
1537 | if ((listen_int_b < 1) || (listen_int_b > 50)) | 1561 | if ((listen_interval < 1) || (listen_interval > 50)) |
1538 | return -EINVAL; | 1562 | return -EINVAL; |
1539 | 1563 | ||
1540 | ar->listen_intvl_t = listen_int_t; | 1564 | ar->listen_intvl_b = listen_interval; |
1541 | ar->listen_intvl_b = listen_int_b; | 1565 | ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 0, |
1542 | |||
1543 | ath6kl_wmi_listeninterval_cmd(ar->wmi, 0, ar->listen_intvl_t, | ||
1544 | ar->listen_intvl_b); | 1566 | ar->listen_intvl_b); |
1545 | 1567 | ||
1546 | return count; | 1568 | return count; |
1547 | } | 1569 | } |
1548 | 1570 | ||
1549 | static ssize_t ath6kl_listen_int_read(struct file *file, | 1571 | static ssize_t ath6kl_listen_int_read(struct file *file, |
1550 | char __user *user_buf, | 1572 | char __user *user_buf, |
1551 | size_t count, loff_t *ppos) | 1573 | size_t count, loff_t *ppos) |
1552 | { | 1574 | { |
1553 | struct ath6kl *ar = file->private_data; | 1575 | struct ath6kl *ar = file->private_data; |
1554 | char buf[32]; | 1576 | char buf[32]; |
1555 | int len; | 1577 | int len; |
1556 | 1578 | ||
1557 | len = scnprintf(buf, sizeof(buf), "%u %u\n", ar->listen_intvl_t, | 1579 | len = scnprintf(buf, sizeof(buf), "%u\n", ar->listen_intvl_b); |
1558 | ar->listen_intvl_b); | ||
1559 | 1580 | ||
1560 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 1581 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
1561 | } | 1582 | } |
@@ -1710,6 +1731,9 @@ int ath6kl_debug_init(struct ath6kl *ar) | |||
1710 | debugfs_create_file("bgscan_interval", S_IWUSR, | 1731 | debugfs_create_file("bgscan_interval", S_IWUSR, |
1711 | ar->debugfs_phy, ar, &fops_bgscan_int); | 1732 | ar->debugfs_phy, ar, &fops_bgscan_int); |
1712 | 1733 | ||
1734 | debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR, | ||
1735 | ar->debugfs_phy, ar, &fops_listen_int); | ||
1736 | |||
1713 | debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar, | 1737 | debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar, |
1714 | &fops_power_params); | 1738 | &fops_power_params); |
1715 | 1739 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 9853c9c125c1..c4be6e50996b 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -41,6 +41,7 @@ enum ATH6K_DEBUG_MASK { | |||
41 | ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ | 41 | ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ |
42 | ATH6KL_DBG_WMI_DUMP = BIT(19), | 42 | ATH6KL_DBG_WMI_DUMP = BIT(19), |
43 | ATH6KL_DBG_SUSPEND = BIT(20), | 43 | ATH6KL_DBG_SUSPEND = BIT(20), |
44 | ATH6KL_DBG_USB = BIT(21), | ||
44 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ | 45 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ |
45 | }; | 46 | }; |
46 | 47 | ||
@@ -55,35 +56,16 @@ int ath6kl_printk(const char *level, const char *fmt, ...); | |||
55 | #define ath6kl_warn(fmt, ...) \ | 56 | #define ath6kl_warn(fmt, ...) \ |
56 | ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__) | 57 | ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__) |
57 | 58 | ||
58 | #define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) | ||
59 | |||
60 | enum ath6kl_war { | 59 | enum ath6kl_war { |
61 | ATH6KL_WAR_INVALID_RATE, | 60 | ATH6KL_WAR_INVALID_RATE, |
62 | }; | 61 | }; |
63 | 62 | ||
64 | #ifdef CONFIG_ATH6KL_DEBUG | 63 | #ifdef CONFIG_ATH6KL_DEBUG |
65 | #define ath6kl_dbg(mask, fmt, ...) \ | ||
66 | ({ \ | ||
67 | int rtn; \ | ||
68 | if (debug_mask & mask) \ | ||
69 | rtn = ath6kl_printk(KERN_DEBUG, fmt, ##__VA_ARGS__); \ | ||
70 | else \ | ||
71 | rtn = 0; \ | ||
72 | \ | ||
73 | rtn; \ | ||
74 | }) | ||
75 | 64 | ||
76 | static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, | 65 | void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...); |
77 | const char *msg, const char *prefix, | 66 | void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, |
78 | const void *buf, size_t len) | 67 | const char *msg, const char *prefix, |
79 | { | 68 | const void *buf, size_t len); |
80 | if (debug_mask & mask) { | ||
81 | if (msg) | ||
82 | ath6kl_dbg(mask, "%s\n", msg); | ||
83 | |||
84 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); | ||
85 | } | ||
86 | } | ||
87 | 69 | ||
88 | void ath6kl_dump_registers(struct ath6kl_device *dev, | 70 | void ath6kl_dump_registers(struct ath6kl_device *dev, |
89 | struct ath6kl_irq_proc_registers *irq_proc_reg, | 71 | struct ath6kl_irq_proc_registers *irq_proc_reg, |
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index e57da35e59fa..e911737ab345 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c | |||
@@ -15,6 +15,8 @@ | |||
15 | */ | 15 | */ |
16 | #include "hif.h" | 16 | #include "hif.h" |
17 | 17 | ||
18 | #include <linux/export.h> | ||
19 | |||
18 | #include "core.h" | 20 | #include "core.h" |
19 | #include "target.h" | 21 | #include "target.h" |
20 | #include "hif-ops.h" | 22 | #include "hif-ops.h" |
@@ -59,6 +61,8 @@ int ath6kl_hif_rw_comp_handler(void *context, int status) | |||
59 | 61 | ||
60 | return 0; | 62 | return 0; |
61 | } | 63 | } |
64 | EXPORT_SYMBOL(ath6kl_hif_rw_comp_handler); | ||
65 | |||
62 | #define REG_DUMP_COUNT_AR6003 60 | 66 | #define REG_DUMP_COUNT_AR6003 60 |
63 | #define REGISTER_DUMP_LEN_MAX 60 | 67 | #define REGISTER_DUMP_LEN_MAX 60 |
64 | 68 | ||
@@ -429,9 +433,8 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) | |||
429 | if (status) | 433 | if (status) |
430 | goto out; | 434 | goto out; |
431 | 435 | ||
432 | if (AR_DBG_LVL_CHECK(ATH6KL_DBG_IRQ)) | 436 | ath6kl_dump_registers(dev, &dev->irq_proc_reg, |
433 | ath6kl_dump_registers(dev, &dev->irq_proc_reg, | 437 | &dev->irq_en_reg); |
434 | &dev->irq_en_reg); | ||
435 | 438 | ||
436 | /* Update only those registers that are enabled */ | 439 | /* Update only those registers that are enabled */ |
437 | host_int_status = dev->irq_proc_reg.host_int_status & | 440 | host_int_status = dev->irq_proc_reg.host_int_status & |
@@ -561,6 +564,7 @@ int ath6kl_hif_intr_bh_handler(struct ath6kl *ar) | |||
561 | 564 | ||
562 | return status; | 565 | return status; |
563 | } | 566 | } |
567 | EXPORT_SYMBOL(ath6kl_hif_intr_bh_handler); | ||
564 | 568 | ||
565 | static int ath6kl_hif_enable_intrs(struct ath6kl_device *dev) | 569 | static int ath6kl_hif_enable_intrs(struct ath6kl_device *dev) |
566 | { | 570 | { |
@@ -689,6 +693,11 @@ int ath6kl_hif_setup(struct ath6kl_device *dev) | |||
689 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n", | 693 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n", |
690 | dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); | 694 | dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); |
691 | 695 | ||
696 | /* usb doesn't support enabling interrupts */ | ||
697 | /* FIXME: remove check once USB support is implemented */ | ||
698 | if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) | ||
699 | return 0; | ||
700 | |||
692 | status = ath6kl_hif_disable_intrs(dev); | 701 | status = ath6kl_hif_disable_intrs(dev); |
693 | 702 | ||
694 | fail_setup: | 703 | fail_setup: |
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index f3b63ca25c7e..2d721903640b 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c | |||
@@ -2062,6 +2062,7 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, | |||
2062 | enum htc_endpoint_id id; | 2062 | enum htc_endpoint_id id; |
2063 | int n_fetched = 0; | 2063 | int n_fetched = 0; |
2064 | 2064 | ||
2065 | INIT_LIST_HEAD(&comp_pktq); | ||
2065 | *num_pkts = 0; | 2066 | *num_pkts = 0; |
2066 | 2067 | ||
2067 | /* | 2068 | /* |
@@ -2543,6 +2544,12 @@ int ath6kl_htc_wait_target(struct htc_target *target) | |||
2543 | struct htc_service_connect_resp resp; | 2544 | struct htc_service_connect_resp resp; |
2544 | int status; | 2545 | int status; |
2545 | 2546 | ||
2547 | /* FIXME: remove once USB support is implemented */ | ||
2548 | if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) { | ||
2549 | ath6kl_err("HTC doesn't support USB yet. Patience!\n"); | ||
2550 | return -EOPNOTSUPP; | ||
2551 | } | ||
2552 | |||
2546 | /* we should be getting 1 control message that the target is ready */ | 2553 | /* we should be getting 1 control message that the target is ready */ |
2547 | packet = htc_wait_for_ctrl_msg(target); | 2554 | packet = htc_wait_for_ctrl_msg(target); |
2548 | 2555 | ||
@@ -2772,7 +2779,9 @@ void ath6kl_htc_cleanup(struct htc_target *target) | |||
2772 | { | 2779 | { |
2773 | struct htc_packet *packet, *tmp_packet; | 2780 | struct htc_packet *packet, *tmp_packet; |
2774 | 2781 | ||
2775 | ath6kl_hif_cleanup_scatter(target->dev->ar); | 2782 | /* FIXME: remove check once USB support is implemented */ |
2783 | if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB) | ||
2784 | ath6kl_hif_cleanup_scatter(target->dev->ar); | ||
2776 | 2785 | ||
2777 | list_for_each_entry_safe(packet, tmp_packet, | 2786 | list_for_each_entry_safe(packet, tmp_packet, |
2778 | &target->free_ctrl_txbuf, list) { | 2787 | &target->free_ctrl_txbuf, list) { |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 7f55be3092d1..0d76c3778106 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -17,22 +17,16 @@ | |||
17 | 17 | ||
18 | #include <linux/moduleparam.h> | 18 | #include <linux/moduleparam.h> |
19 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
20 | #include <linux/export.h> | ||
20 | #include <linux/of.h> | 21 | #include <linux/of.h> |
21 | #include <linux/mmc/sdio_func.h> | 22 | #include <linux/mmc/sdio_func.h> |
23 | |||
22 | #include "core.h" | 24 | #include "core.h" |
23 | #include "cfg80211.h" | 25 | #include "cfg80211.h" |
24 | #include "target.h" | 26 | #include "target.h" |
25 | #include "debug.h" | 27 | #include "debug.h" |
26 | #include "hif-ops.h" | 28 | #include "hif-ops.h" |
27 | 29 | ||
28 | unsigned int debug_mask; | ||
29 | static unsigned int testmode; | ||
30 | static bool suspend_cutpower; | ||
31 | |||
32 | module_param(debug_mask, uint, 0644); | ||
33 | module_param(testmode, uint, 0644); | ||
34 | module_param(suspend_cutpower, bool, 0444); | ||
35 | |||
36 | static const struct ath6kl_hw hw_list[] = { | 30 | static const struct ath6kl_hw hw_list[] = { |
37 | { | 31 | { |
38 | .id = AR6003_HW_2_0_VERSION, | 32 | .id = AR6003_HW_2_0_VERSION, |
@@ -47,11 +41,14 @@ static const struct ath6kl_hw hw_list[] = { | |||
47 | /* hw2.0 needs override address hardcoded */ | 41 | /* hw2.0 needs override address hardcoded */ |
48 | .app_start_override_addr = 0x944C00, | 42 | .app_start_override_addr = 0x944C00, |
49 | 43 | ||
50 | .fw_otp = AR6003_HW_2_0_OTP_FILE, | 44 | .fw = { |
51 | .fw = AR6003_HW_2_0_FIRMWARE_FILE, | 45 | .dir = AR6003_HW_2_0_FW_DIR, |
52 | .fw_tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, | 46 | .otp = AR6003_HW_2_0_OTP_FILE, |
53 | .fw_patch = AR6003_HW_2_0_PATCH_FILE, | 47 | .fw = AR6003_HW_2_0_FIRMWARE_FILE, |
54 | .fw_api2 = AR6003_HW_2_0_FIRMWARE_2_FILE, | 48 | .tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, |
49 | .patch = AR6003_HW_2_0_PATCH_FILE, | ||
50 | }, | ||
51 | |||
55 | .fw_board = AR6003_HW_2_0_BOARD_DATA_FILE, | 52 | .fw_board = AR6003_HW_2_0_BOARD_DATA_FILE, |
56 | .fw_default_board = AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE, | 53 | .fw_default_board = AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE, |
57 | }, | 54 | }, |
@@ -64,12 +61,18 @@ static const struct ath6kl_hw hw_list[] = { | |||
64 | .reserved_ram_size = 512, | 61 | .reserved_ram_size = 512, |
65 | .refclk_hz = 26000000, | 62 | .refclk_hz = 26000000, |
66 | .uarttx_pin = 8, | 63 | .uarttx_pin = 8, |
64 | .testscript_addr = 0x57ef74, | ||
65 | |||
66 | .fw = { | ||
67 | .dir = AR6003_HW_2_1_1_FW_DIR, | ||
68 | .otp = AR6003_HW_2_1_1_OTP_FILE, | ||
69 | .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, | ||
70 | .tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, | ||
71 | .patch = AR6003_HW_2_1_1_PATCH_FILE, | ||
72 | .utf = AR6003_HW_2_1_1_UTF_FIRMWARE_FILE, | ||
73 | .testscript = AR6003_HW_2_1_1_TESTSCRIPT_FILE, | ||
74 | }, | ||
67 | 75 | ||
68 | .fw_otp = AR6003_HW_2_1_1_OTP_FILE, | ||
69 | .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, | ||
70 | .fw_tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, | ||
71 | .fw_patch = AR6003_HW_2_1_1_PATCH_FILE, | ||
72 | .fw_api2 = AR6003_HW_2_1_1_FIRMWARE_2_FILE, | ||
73 | .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, | 76 | .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, |
74 | .fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE, | 77 | .fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE, |
75 | }, | 78 | }, |
@@ -84,8 +87,11 @@ static const struct ath6kl_hw hw_list[] = { | |||
84 | .refclk_hz = 26000000, | 87 | .refclk_hz = 26000000, |
85 | .uarttx_pin = 11, | 88 | .uarttx_pin = 11, |
86 | 89 | ||
87 | .fw = AR6004_HW_1_0_FIRMWARE_FILE, | 90 | .fw = { |
88 | .fw_api2 = AR6004_HW_1_0_FIRMWARE_2_FILE, | 91 | .dir = AR6004_HW_1_0_FW_DIR, |
92 | .fw = AR6004_HW_1_0_FIRMWARE_FILE, | ||
93 | }, | ||
94 | |||
89 | .fw_board = AR6004_HW_1_0_BOARD_DATA_FILE, | 95 | .fw_board = AR6004_HW_1_0_BOARD_DATA_FILE, |
90 | .fw_default_board = AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE, | 96 | .fw_default_board = AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE, |
91 | }, | 97 | }, |
@@ -100,8 +106,11 @@ static const struct ath6kl_hw hw_list[] = { | |||
100 | .refclk_hz = 40000000, | 106 | .refclk_hz = 40000000, |
101 | .uarttx_pin = 11, | 107 | .uarttx_pin = 11, |
102 | 108 | ||
103 | .fw = AR6004_HW_1_1_FIRMWARE_FILE, | 109 | .fw = { |
104 | .fw_api2 = AR6004_HW_1_1_FIRMWARE_2_FILE, | 110 | .dir = AR6004_HW_1_1_FW_DIR, |
111 | .fw = AR6004_HW_1_1_FIRMWARE_FILE, | ||
112 | }, | ||
113 | |||
105 | .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, | 114 | .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, |
106 | .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, | 115 | .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, |
107 | }, | 116 | }, |
@@ -452,6 +461,13 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
452 | u8 fw_iftype, fw_mode = 0, fw_submode = 0; | 461 | u8 fw_iftype, fw_mode = 0, fw_submode = 0; |
453 | int i, status; | 462 | int i, status; |
454 | 463 | ||
464 | param = !!(ar->conf_flags & ATH6KL_CONF_UART_DEBUG); | ||
465 | if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, | ||
466 | HI_ITEM(hi_serial_enable)), (u8 *)¶m, 4)) { | ||
467 | ath6kl_err("bmi_write_memory for uart debug failed\n"); | ||
468 | return -EIO; | ||
469 | } | ||
470 | |||
455 | /* | 471 | /* |
456 | * Note: Even though the firmware interface type is | 472 | * Note: Even though the firmware interface type is |
457 | * chosen as BSS_STA for all three interfaces, can | 473 | * chosen as BSS_STA for all three interfaces, can |
@@ -573,36 +589,6 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
573 | return 0; | 589 | return 0; |
574 | } | 590 | } |
575 | 591 | ||
576 | void ath6kl_core_free(struct ath6kl *ar) | ||
577 | { | ||
578 | wiphy_free(ar->wiphy); | ||
579 | } | ||
580 | |||
581 | void ath6kl_core_cleanup(struct ath6kl *ar) | ||
582 | { | ||
583 | ath6kl_hif_power_off(ar); | ||
584 | |||
585 | destroy_workqueue(ar->ath6kl_wq); | ||
586 | |||
587 | if (ar->htc_target) | ||
588 | ath6kl_htc_cleanup(ar->htc_target); | ||
589 | |||
590 | ath6kl_cookie_cleanup(ar); | ||
591 | |||
592 | ath6kl_cleanup_amsdu_rxbufs(ar); | ||
593 | |||
594 | ath6kl_bmi_cleanup(ar); | ||
595 | |||
596 | ath6kl_debug_cleanup(ar); | ||
597 | |||
598 | kfree(ar->fw_board); | ||
599 | kfree(ar->fw_otp); | ||
600 | kfree(ar->fw); | ||
601 | kfree(ar->fw_patch); | ||
602 | |||
603 | ath6kl_deinit_ieee80211_hw(ar); | ||
604 | } | ||
605 | |||
606 | /* firmware upload */ | 592 | /* firmware upload */ |
607 | static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, | 593 | static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, |
608 | u8 **fw, size_t *fw_len) | 594 | u8 **fw, size_t *fw_len) |
@@ -626,21 +612,6 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, | |||
626 | } | 612 | } |
627 | 613 | ||
628 | #ifdef CONFIG_OF | 614 | #ifdef CONFIG_OF |
629 | static const char *get_target_ver_dir(const struct ath6kl *ar) | ||
630 | { | ||
631 | switch (ar->version.target_ver) { | ||
632 | case AR6003_HW_1_0_VERSION: | ||
633 | return "ath6k/AR6003/hw1.0"; | ||
634 | case AR6003_HW_2_0_VERSION: | ||
635 | return "ath6k/AR6003/hw2.0"; | ||
636 | case AR6003_HW_2_1_1_VERSION: | ||
637 | return "ath6k/AR6003/hw2.1.1"; | ||
638 | } | ||
639 | ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__, | ||
640 | ar->version.target_ver); | ||
641 | return NULL; | ||
642 | } | ||
643 | |||
644 | /* | 615 | /* |
645 | * Check the device tree for a board-id and use it to construct | 616 | * Check the device tree for a board-id and use it to construct |
646 | * the pathname to the firmware file. Used (for now) to find a | 617 | * the pathname to the firmware file. Used (for now) to find a |
@@ -663,7 +634,7 @@ static bool check_device_tree(struct ath6kl *ar) | |||
663 | continue; | 634 | continue; |
664 | } | 635 | } |
665 | snprintf(board_filename, sizeof(board_filename), | 636 | snprintf(board_filename, sizeof(board_filename), |
666 | "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id); | 637 | "%s/bdata.%s.bin", ar->hw.fw.dir, board_id); |
667 | 638 | ||
668 | ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board, | 639 | ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board, |
669 | &ar->fw_board_len); | 640 | &ar->fw_board_len); |
@@ -730,19 +701,20 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) | |||
730 | 701 | ||
731 | static int ath6kl_fetch_otp_file(struct ath6kl *ar) | 702 | static int ath6kl_fetch_otp_file(struct ath6kl *ar) |
732 | { | 703 | { |
733 | const char *filename; | 704 | char filename[100]; |
734 | int ret; | 705 | int ret; |
735 | 706 | ||
736 | if (ar->fw_otp != NULL) | 707 | if (ar->fw_otp != NULL) |
737 | return 0; | 708 | return 0; |
738 | 709 | ||
739 | if (ar->hw.fw_otp == NULL) { | 710 | if (ar->hw.fw.otp == NULL) { |
740 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 711 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
741 | "no OTP file configured for this hw\n"); | 712 | "no OTP file configured for this hw\n"); |
742 | return 0; | 713 | return 0; |
743 | } | 714 | } |
744 | 715 | ||
745 | filename = ar->hw.fw_otp; | 716 | snprintf(filename, sizeof(filename), "%s/%s", |
717 | ar->hw.fw.dir, ar->hw.fw.otp); | ||
746 | 718 | ||
747 | ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, | 719 | ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, |
748 | &ar->fw_otp_len); | 720 | &ar->fw_otp_len); |
@@ -755,33 +727,61 @@ static int ath6kl_fetch_otp_file(struct ath6kl *ar) | |||
755 | return 0; | 727 | return 0; |
756 | } | 728 | } |
757 | 729 | ||
758 | static int ath6kl_fetch_fw_file(struct ath6kl *ar) | 730 | static int ath6kl_fetch_testmode_file(struct ath6kl *ar) |
759 | { | 731 | { |
760 | const char *filename; | 732 | char filename[100]; |
761 | int ret; | 733 | int ret; |
762 | 734 | ||
763 | if (ar->fw != NULL) | 735 | if (ar->testmode == 0) |
764 | return 0; | 736 | return 0; |
765 | 737 | ||
766 | if (testmode) { | 738 | ath6kl_dbg(ATH6KL_DBG_BOOT, "testmode %d\n", ar->testmode); |
767 | if (ar->hw.fw_tcmd == NULL) { | 739 | |
768 | ath6kl_warn("testmode not supported\n"); | 740 | if (ar->testmode == 2) { |
741 | if (ar->hw.fw.utf == NULL) { | ||
742 | ath6kl_warn("testmode 2 not supported\n"); | ||
743 | return -EOPNOTSUPP; | ||
744 | } | ||
745 | |||
746 | snprintf(filename, sizeof(filename), "%s/%s", | ||
747 | ar->hw.fw.dir, ar->hw.fw.utf); | ||
748 | } else { | ||
749 | if (ar->hw.fw.tcmd == NULL) { | ||
750 | ath6kl_warn("testmode 1 not supported\n"); | ||
769 | return -EOPNOTSUPP; | 751 | return -EOPNOTSUPP; |
770 | } | 752 | } |
771 | 753 | ||
772 | filename = ar->hw.fw_tcmd; | 754 | snprintf(filename, sizeof(filename), "%s/%s", |
755 | ar->hw.fw.dir, ar->hw.fw.tcmd); | ||
756 | } | ||
773 | 757 | ||
774 | set_bit(TESTMODE, &ar->flag); | 758 | set_bit(TESTMODE, &ar->flag); |
775 | 759 | ||
776 | goto get_fw; | 760 | ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); |
761 | if (ret) { | ||
762 | ath6kl_err("Failed to get testmode %d firmware file %s: %d\n", | ||
763 | ar->testmode, filename, ret); | ||
764 | return ret; | ||
777 | } | 765 | } |
778 | 766 | ||
779 | if (WARN_ON(ar->hw.fw == NULL)) | 767 | return 0; |
768 | } | ||
769 | |||
770 | static int ath6kl_fetch_fw_file(struct ath6kl *ar) | ||
771 | { | ||
772 | char filename[100]; | ||
773 | int ret; | ||
774 | |||
775 | if (ar->fw != NULL) | ||
776 | return 0; | ||
777 | |||
778 | /* FIXME: remove WARN_ON() as we won't support FW API 1 for long */ | ||
779 | if (WARN_ON(ar->hw.fw.fw == NULL)) | ||
780 | return -EINVAL; | 780 | return -EINVAL; |
781 | 781 | ||
782 | filename = ar->hw.fw; | 782 | snprintf(filename, sizeof(filename), "%s/%s", |
783 | ar->hw.fw.dir, ar->hw.fw.fw); | ||
783 | 784 | ||
784 | get_fw: | ||
785 | ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); | 785 | ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); |
786 | if (ret) { | 786 | if (ret) { |
787 | ath6kl_err("Failed to get firmware file %s: %d\n", | 787 | ath6kl_err("Failed to get firmware file %s: %d\n", |
@@ -794,16 +794,17 @@ get_fw: | |||
794 | 794 | ||
795 | static int ath6kl_fetch_patch_file(struct ath6kl *ar) | 795 | static int ath6kl_fetch_patch_file(struct ath6kl *ar) |
796 | { | 796 | { |
797 | const char *filename; | 797 | char filename[100]; |
798 | int ret; | 798 | int ret; |
799 | 799 | ||
800 | if (ar->fw_patch != NULL) | 800 | if (ar->fw_patch != NULL) |
801 | return 0; | 801 | return 0; |
802 | 802 | ||
803 | if (ar->hw.fw_patch == NULL) | 803 | if (ar->hw.fw.patch == NULL) |
804 | return 0; | 804 | return 0; |
805 | 805 | ||
806 | filename = ar->hw.fw_patch; | 806 | snprintf(filename, sizeof(filename), "%s/%s", |
807 | ar->hw.fw.dir, ar->hw.fw.patch); | ||
807 | 808 | ||
808 | ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, | 809 | ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, |
809 | &ar->fw_patch_len); | 810 | &ar->fw_patch_len); |
@@ -816,6 +817,34 @@ static int ath6kl_fetch_patch_file(struct ath6kl *ar) | |||
816 | return 0; | 817 | return 0; |
817 | } | 818 | } |
818 | 819 | ||
820 | static int ath6kl_fetch_testscript_file(struct ath6kl *ar) | ||
821 | { | ||
822 | char filename[100]; | ||
823 | int ret; | ||
824 | |||
825 | if (ar->testmode != 2) | ||
826 | return 0; | ||
827 | |||
828 | if (ar->fw_testscript != NULL) | ||
829 | return 0; | ||
830 | |||
831 | if (ar->hw.fw.testscript == NULL) | ||
832 | return 0; | ||
833 | |||
834 | snprintf(filename, sizeof(filename), "%s/%s", | ||
835 | ar->hw.fw.dir, ar->hw.fw.testscript); | ||
836 | |||
837 | ret = ath6kl_get_fw(ar, filename, &ar->fw_testscript, | ||
838 | &ar->fw_testscript_len); | ||
839 | if (ret) { | ||
840 | ath6kl_err("Failed to get testscript file %s: %d\n", | ||
841 | filename, ret); | ||
842 | return ret; | ||
843 | } | ||
844 | |||
845 | return 0; | ||
846 | } | ||
847 | |||
819 | static int ath6kl_fetch_fw_api1(struct ath6kl *ar) | 848 | static int ath6kl_fetch_fw_api1(struct ath6kl *ar) |
820 | { | 849 | { |
821 | int ret; | 850 | int ret; |
@@ -832,23 +861,24 @@ static int ath6kl_fetch_fw_api1(struct ath6kl *ar) | |||
832 | if (ret) | 861 | if (ret) |
833 | return ret; | 862 | return ret; |
834 | 863 | ||
864 | ret = ath6kl_fetch_testscript_file(ar); | ||
865 | if (ret) | ||
866 | return ret; | ||
867 | |||
835 | return 0; | 868 | return 0; |
836 | } | 869 | } |
837 | 870 | ||
838 | static int ath6kl_fetch_fw_api2(struct ath6kl *ar) | 871 | static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) |
839 | { | 872 | { |
840 | size_t magic_len, len, ie_len; | 873 | size_t magic_len, len, ie_len; |
841 | const struct firmware *fw; | 874 | const struct firmware *fw; |
842 | struct ath6kl_fw_ie *hdr; | 875 | struct ath6kl_fw_ie *hdr; |
843 | const char *filename; | 876 | char filename[100]; |
844 | const u8 *data; | 877 | const u8 *data; |
845 | int ret, ie_id, i, index, bit; | 878 | int ret, ie_id, i, index, bit; |
846 | __le32 *val; | 879 | __le32 *val; |
847 | 880 | ||
848 | if (ar->hw.fw_api2 == NULL) | 881 | snprintf(filename, sizeof(filename), "%s/%s", ar->hw.fw.dir, name); |
849 | return -EOPNOTSUPP; | ||
850 | |||
851 | filename = ar->hw.fw_api2; | ||
852 | 882 | ||
853 | ret = request_firmware(&fw, filename, ar->dev); | 883 | ret = request_firmware(&fw, filename, ar->dev); |
854 | if (ret) | 884 | if (ret) |
@@ -907,6 +937,10 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) | |||
907 | ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n", | 937 | ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n", |
908 | ie_len); | 938 | ie_len); |
909 | 939 | ||
940 | /* in testmode we already might have a fw file */ | ||
941 | if (ar->fw != NULL) | ||
942 | break; | ||
943 | |||
910 | ar->fw = kmemdup(data, ie_len, GFP_KERNEL); | 944 | ar->fw = kmemdup(data, ie_len, GFP_KERNEL); |
911 | 945 | ||
912 | if (ar->fw == NULL) { | 946 | if (ar->fw == NULL) { |
@@ -1010,7 +1044,7 @@ out: | |||
1010 | return ret; | 1044 | return ret; |
1011 | } | 1045 | } |
1012 | 1046 | ||
1013 | static int ath6kl_fetch_firmwares(struct ath6kl *ar) | 1047 | int ath6kl_init_fetch_firmwares(struct ath6kl *ar) |
1014 | { | 1048 | { |
1015 | int ret; | 1049 | int ret; |
1016 | 1050 | ||
@@ -1018,17 +1052,30 @@ static int ath6kl_fetch_firmwares(struct ath6kl *ar) | |||
1018 | if (ret) | 1052 | if (ret) |
1019 | return ret; | 1053 | return ret; |
1020 | 1054 | ||
1021 | ret = ath6kl_fetch_fw_api2(ar); | 1055 | ret = ath6kl_fetch_testmode_file(ar); |
1056 | if (ret) | ||
1057 | return ret; | ||
1058 | |||
1059 | ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE); | ||
1022 | if (ret == 0) { | 1060 | if (ret == 0) { |
1023 | ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 2\n"); | 1061 | ar->fw_api = 3; |
1024 | return 0; | 1062 | goto out; |
1063 | } | ||
1064 | |||
1065 | ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API2_FILE); | ||
1066 | if (ret == 0) { | ||
1067 | ar->fw_api = 2; | ||
1068 | goto out; | ||
1025 | } | 1069 | } |
1026 | 1070 | ||
1027 | ret = ath6kl_fetch_fw_api1(ar); | 1071 | ret = ath6kl_fetch_fw_api1(ar); |
1028 | if (ret) | 1072 | if (ret) |
1029 | return ret; | 1073 | return ret; |
1030 | 1074 | ||
1031 | ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 1\n"); | 1075 | ar->fw_api = 1; |
1076 | |||
1077 | out: | ||
1078 | ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api %d\n", ar->fw_api); | ||
1032 | 1079 | ||
1033 | return 0; | 1080 | return 0; |
1034 | } | 1081 | } |
@@ -1249,6 +1296,50 @@ static int ath6kl_upload_patch(struct ath6kl *ar) | |||
1249 | return 0; | 1296 | return 0; |
1250 | } | 1297 | } |
1251 | 1298 | ||
1299 | static int ath6kl_upload_testscript(struct ath6kl *ar) | ||
1300 | { | ||
1301 | u32 address, param; | ||
1302 | int ret; | ||
1303 | |||
1304 | if (ar->testmode != 2) | ||
1305 | return 0; | ||
1306 | |||
1307 | if (ar->fw_testscript == NULL) | ||
1308 | return 0; | ||
1309 | |||
1310 | address = ar->hw.testscript_addr; | ||
1311 | |||
1312 | ath6kl_dbg(ATH6KL_DBG_BOOT, "writing testscript to 0x%x (%zd B)\n", | ||
1313 | address, ar->fw_testscript_len); | ||
1314 | |||
1315 | ret = ath6kl_bmi_write(ar, address, ar->fw_testscript, | ||
1316 | ar->fw_testscript_len); | ||
1317 | if (ret) { | ||
1318 | ath6kl_err("Failed to write testscript file: %d\n", ret); | ||
1319 | return ret; | ||
1320 | } | ||
1321 | |||
1322 | param = address; | ||
1323 | ath6kl_bmi_write(ar, | ||
1324 | ath6kl_get_hi_item_addr(ar, | ||
1325 | HI_ITEM(hi_ota_testscript)), | ||
1326 | (unsigned char *) ¶m, 4); | ||
1327 | |||
1328 | param = 4096; | ||
1329 | ath6kl_bmi_write(ar, | ||
1330 | ath6kl_get_hi_item_addr(ar, | ||
1331 | HI_ITEM(hi_end_ram_reserve_sz)), | ||
1332 | (unsigned char *) ¶m, 4); | ||
1333 | |||
1334 | param = 1; | ||
1335 | ath6kl_bmi_write(ar, | ||
1336 | ath6kl_get_hi_item_addr(ar, | ||
1337 | HI_ITEM(hi_test_apps_related)), | ||
1338 | (unsigned char *) ¶m, 4); | ||
1339 | |||
1340 | return 0; | ||
1341 | } | ||
1342 | |||
1252 | static int ath6kl_init_upload(struct ath6kl *ar) | 1343 | static int ath6kl_init_upload(struct ath6kl *ar) |
1253 | { | 1344 | { |
1254 | u32 param, options, sleep, address; | 1345 | u32 param, options, sleep, address; |
@@ -1357,6 +1448,11 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
1357 | if (status) | 1448 | if (status) |
1358 | return status; | 1449 | return status; |
1359 | 1450 | ||
1451 | /* Download the test script */ | ||
1452 | status = ath6kl_upload_testscript(ar); | ||
1453 | if (status) | ||
1454 | return status; | ||
1455 | |||
1360 | /* Restore system sleep */ | 1456 | /* Restore system sleep */ |
1361 | address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; | 1457 | address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; |
1362 | status = ath6kl_bmi_reg_write(ar, address, sleep); | 1458 | status = ath6kl_bmi_reg_write(ar, address, sleep); |
@@ -1372,9 +1468,9 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
1372 | return status; | 1468 | return status; |
1373 | } | 1469 | } |
1374 | 1470 | ||
1375 | static int ath6kl_init_hw_params(struct ath6kl *ar) | 1471 | int ath6kl_init_hw_params(struct ath6kl *ar) |
1376 | { | 1472 | { |
1377 | const struct ath6kl_hw *hw; | 1473 | const struct ath6kl_hw *uninitialized_var(hw); |
1378 | int i; | 1474 | int i; |
1379 | 1475 | ||
1380 | for (i = 0; i < ARRAY_SIZE(hw_list); i++) { | 1476 | for (i = 0; i < ARRAY_SIZE(hw_list); i++) { |
@@ -1481,10 +1577,11 @@ int ath6kl_init_hw_start(struct ath6kl *ar) | |||
1481 | 1577 | ||
1482 | 1578 | ||
1483 | if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) { | 1579 | if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) { |
1484 | ath6kl_info("%s %s fw %s%s\n", | 1580 | ath6kl_info("%s %s fw %s api %d%s\n", |
1485 | ar->hw.name, | 1581 | ar->hw.name, |
1486 | ath6kl_init_get_hif_name(ar->hif_type), | 1582 | ath6kl_init_get_hif_name(ar->hif_type), |
1487 | ar->wiphy->fw_version, | 1583 | ar->wiphy->fw_version, |
1584 | ar->fw_api, | ||
1488 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); | 1585 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); |
1489 | } | 1586 | } |
1490 | 1587 | ||
@@ -1549,173 +1646,7 @@ int ath6kl_init_hw_stop(struct ath6kl *ar) | |||
1549 | return 0; | 1646 | return 0; |
1550 | } | 1647 | } |
1551 | 1648 | ||
1552 | int ath6kl_core_init(struct ath6kl *ar) | 1649 | /* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */ |
1553 | { | ||
1554 | struct ath6kl_bmi_target_info targ_info; | ||
1555 | struct net_device *ndev; | ||
1556 | int ret = 0, i; | ||
1557 | |||
1558 | ar->ath6kl_wq = create_singlethread_workqueue("ath6kl"); | ||
1559 | if (!ar->ath6kl_wq) | ||
1560 | return -ENOMEM; | ||
1561 | |||
1562 | ret = ath6kl_bmi_init(ar); | ||
1563 | if (ret) | ||
1564 | goto err_wq; | ||
1565 | |||
1566 | /* | ||
1567 | * Turn on power to get hardware (target) version and leave power | ||
1568 | * on delibrately as we will boot the hardware anyway within few | ||
1569 | * seconds. | ||
1570 | */ | ||
1571 | ret = ath6kl_hif_power_on(ar); | ||
1572 | if (ret) | ||
1573 | goto err_bmi_cleanup; | ||
1574 | |||
1575 | ret = ath6kl_bmi_get_target_info(ar, &targ_info); | ||
1576 | if (ret) | ||
1577 | goto err_power_off; | ||
1578 | |||
1579 | ar->version.target_ver = le32_to_cpu(targ_info.version); | ||
1580 | ar->target_type = le32_to_cpu(targ_info.type); | ||
1581 | ar->wiphy->hw_version = le32_to_cpu(targ_info.version); | ||
1582 | |||
1583 | ret = ath6kl_init_hw_params(ar); | ||
1584 | if (ret) | ||
1585 | goto err_power_off; | ||
1586 | |||
1587 | ar->htc_target = ath6kl_htc_create(ar); | ||
1588 | |||
1589 | if (!ar->htc_target) { | ||
1590 | ret = -ENOMEM; | ||
1591 | goto err_power_off; | ||
1592 | } | ||
1593 | |||
1594 | ret = ath6kl_fetch_firmwares(ar); | ||
1595 | if (ret) | ||
1596 | goto err_htc_cleanup; | ||
1597 | |||
1598 | /* FIXME: we should free all firmwares in the error cases below */ | ||
1599 | |||
1600 | /* Indicate that WMI is enabled (although not ready yet) */ | ||
1601 | set_bit(WMI_ENABLED, &ar->flag); | ||
1602 | ar->wmi = ath6kl_wmi_init(ar); | ||
1603 | if (!ar->wmi) { | ||
1604 | ath6kl_err("failed to initialize wmi\n"); | ||
1605 | ret = -EIO; | ||
1606 | goto err_htc_cleanup; | ||
1607 | } | ||
1608 | |||
1609 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); | ||
1610 | |||
1611 | ret = ath6kl_register_ieee80211_hw(ar); | ||
1612 | if (ret) | ||
1613 | goto err_node_cleanup; | ||
1614 | |||
1615 | ret = ath6kl_debug_init(ar); | ||
1616 | if (ret) { | ||
1617 | wiphy_unregister(ar->wiphy); | ||
1618 | goto err_node_cleanup; | ||
1619 | } | ||
1620 | |||
1621 | for (i = 0; i < ar->vif_max; i++) | ||
1622 | ar->avail_idx_map |= BIT(i); | ||
1623 | |||
1624 | rtnl_lock(); | ||
1625 | |||
1626 | /* Add an initial station interface */ | ||
1627 | ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0, | ||
1628 | INFRA_NETWORK); | ||
1629 | |||
1630 | rtnl_unlock(); | ||
1631 | |||
1632 | if (!ndev) { | ||
1633 | ath6kl_err("Failed to instantiate a network device\n"); | ||
1634 | ret = -ENOMEM; | ||
1635 | wiphy_unregister(ar->wiphy); | ||
1636 | goto err_debug_init; | ||
1637 | } | ||
1638 | |||
1639 | |||
1640 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n", | ||
1641 | __func__, ndev->name, ndev, ar); | ||
1642 | |||
1643 | /* setup access class priority mappings */ | ||
1644 | ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */ | ||
1645 | ar->ac_stream_pri_map[WMM_AC_BE] = 1; | ||
1646 | ar->ac_stream_pri_map[WMM_AC_VI] = 2; | ||
1647 | ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */ | ||
1648 | |||
1649 | /* give our connected endpoints some buffers */ | ||
1650 | ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep); | ||
1651 | ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]); | ||
1652 | |||
1653 | /* allocate some buffers that handle larger AMSDU frames */ | ||
1654 | ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS); | ||
1655 | |||
1656 | ath6kl_cookie_init(ar); | ||
1657 | |||
1658 | ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | | ||
1659 | ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; | ||
1660 | |||
1661 | if (suspend_cutpower) | ||
1662 | ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER; | ||
1663 | |||
1664 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | ||
1665 | WIPHY_FLAG_HAVE_AP_SME | | ||
1666 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
1667 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
1668 | |||
1669 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) | ||
1670 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
1671 | |||
1672 | ar->wiphy->probe_resp_offload = | ||
1673 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | ||
1674 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | ||
1675 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | | ||
1676 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; | ||
1677 | |||
1678 | set_bit(FIRST_BOOT, &ar->flag); | ||
1679 | |||
1680 | ret = ath6kl_init_hw_start(ar); | ||
1681 | if (ret) { | ||
1682 | ath6kl_err("Failed to start hardware: %d\n", ret); | ||
1683 | goto err_rxbuf_cleanup; | ||
1684 | } | ||
1685 | |||
1686 | /* | ||
1687 | * Set mac address which is received in ready event | ||
1688 | * FIXME: Move to ath6kl_interface_add() | ||
1689 | */ | ||
1690 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); | ||
1691 | |||
1692 | return ret; | ||
1693 | |||
1694 | err_rxbuf_cleanup: | ||
1695 | ath6kl_htc_flush_rx_buf(ar->htc_target); | ||
1696 | ath6kl_cleanup_amsdu_rxbufs(ar); | ||
1697 | rtnl_lock(); | ||
1698 | ath6kl_deinit_if_data(netdev_priv(ndev)); | ||
1699 | rtnl_unlock(); | ||
1700 | wiphy_unregister(ar->wiphy); | ||
1701 | err_debug_init: | ||
1702 | ath6kl_debug_cleanup(ar); | ||
1703 | err_node_cleanup: | ||
1704 | ath6kl_wmi_shutdown(ar->wmi); | ||
1705 | clear_bit(WMI_ENABLED, &ar->flag); | ||
1706 | ar->wmi = NULL; | ||
1707 | err_htc_cleanup: | ||
1708 | ath6kl_htc_cleanup(ar->htc_target); | ||
1709 | err_power_off: | ||
1710 | ath6kl_hif_power_off(ar); | ||
1711 | err_bmi_cleanup: | ||
1712 | ath6kl_bmi_cleanup(ar); | ||
1713 | err_wq: | ||
1714 | destroy_workqueue(ar->ath6kl_wq); | ||
1715 | |||
1716 | return ret; | ||
1717 | } | ||
1718 | |||
1719 | void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) | 1650 | void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) |
1720 | { | 1651 | { |
1721 | static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 1652 | static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
@@ -1747,6 +1678,7 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) | |||
1747 | void ath6kl_stop_txrx(struct ath6kl *ar) | 1678 | void ath6kl_stop_txrx(struct ath6kl *ar) |
1748 | { | 1679 | { |
1749 | struct ath6kl_vif *vif, *tmp_vif; | 1680 | struct ath6kl_vif *vif, *tmp_vif; |
1681 | int i; | ||
1750 | 1682 | ||
1751 | set_bit(DESTROY_IN_PROGRESS, &ar->flag); | 1683 | set_bit(DESTROY_IN_PROGRESS, &ar->flag); |
1752 | 1684 | ||
@@ -1755,13 +1687,16 @@ void ath6kl_stop_txrx(struct ath6kl *ar) | |||
1755 | return; | 1687 | return; |
1756 | } | 1688 | } |
1757 | 1689 | ||
1690 | for (i = 0; i < AP_MAX_NUM_STA; i++) | ||
1691 | aggr_reset_state(ar->sta_list[i].aggr_conn); | ||
1692 | |||
1758 | spin_lock_bh(&ar->list_lock); | 1693 | spin_lock_bh(&ar->list_lock); |
1759 | list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) { | 1694 | list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) { |
1760 | list_del(&vif->list); | 1695 | list_del(&vif->list); |
1761 | spin_unlock_bh(&ar->list_lock); | 1696 | spin_unlock_bh(&ar->list_lock); |
1762 | ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); | 1697 | ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); |
1763 | rtnl_lock(); | 1698 | rtnl_lock(); |
1764 | ath6kl_deinit_if_data(vif); | 1699 | ath6kl_cfg80211_vif_cleanup(vif); |
1765 | rtnl_unlock(); | 1700 | rtnl_unlock(); |
1766 | spin_lock_bh(&ar->list_lock); | 1701 | spin_lock_bh(&ar->list_lock); |
1767 | } | 1702 | } |
@@ -1796,3 +1731,4 @@ void ath6kl_stop_txrx(struct ath6kl *ar) | |||
1796 | 1731 | ||
1797 | clear_bit(WLAN_ENABLED, &ar->flag); | 1732 | clear_bit(WLAN_ENABLED, &ar->flag); |
1798 | } | 1733 | } |
1734 | EXPORT_SYMBOL(ath6kl_stop_txrx); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index eea3c747653e..b96d01a7919b 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -52,9 +52,11 @@ struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid) | |||
52 | return conn; | 52 | return conn; |
53 | } | 53 | } |
54 | 54 | ||
55 | static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, | 55 | static void ath6kl_add_new_sta(struct ath6kl_vif *vif, u8 *mac, u16 aid, |
56 | u8 ielen, u8 keymgmt, u8 ucipher, u8 auth) | 56 | u8 *wpaie, size_t ielen, u8 keymgmt, |
57 | u8 ucipher, u8 auth, u8 apsd_info) | ||
57 | { | 58 | { |
59 | struct ath6kl *ar = vif->ar; | ||
58 | struct ath6kl_sta *sta; | 60 | struct ath6kl_sta *sta; |
59 | u8 free_slot; | 61 | u8 free_slot; |
60 | 62 | ||
@@ -68,9 +70,11 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, | |||
68 | sta->keymgmt = keymgmt; | 70 | sta->keymgmt = keymgmt; |
69 | sta->ucipher = ucipher; | 71 | sta->ucipher = ucipher; |
70 | sta->auth = auth; | 72 | sta->auth = auth; |
73 | sta->apsd_info = apsd_info; | ||
71 | 74 | ||
72 | ar->sta_list_index = ar->sta_list_index | (1 << free_slot); | 75 | ar->sta_list_index = ar->sta_list_index | (1 << free_slot); |
73 | ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid); | 76 | ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid); |
77 | aggr_conn_init(vif, vif->aggr_cntxt, sta->aggr_conn); | ||
74 | } | 78 | } |
75 | 79 | ||
76 | static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) | 80 | static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) |
@@ -80,6 +84,7 @@ static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) | |||
80 | /* empty the queued pkts in the PS queue if any */ | 84 | /* empty the queued pkts in the PS queue if any */ |
81 | spin_lock_bh(&sta->psq_lock); | 85 | spin_lock_bh(&sta->psq_lock); |
82 | skb_queue_purge(&sta->psq); | 86 | skb_queue_purge(&sta->psq); |
87 | skb_queue_purge(&sta->apsdq); | ||
83 | spin_unlock_bh(&sta->psq_lock); | 88 | spin_unlock_bh(&sta->psq_lock); |
84 | 89 | ||
85 | memset(&ar->ap_stats.sta[sta->aid - 1], 0, | 90 | memset(&ar->ap_stats.sta[sta->aid - 1], 0, |
@@ -90,7 +95,7 @@ static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) | |||
90 | sta->sta_flags = 0; | 95 | sta->sta_flags = 0; |
91 | 96 | ||
92 | ar->sta_list_index = ar->sta_list_index & ~(1 << i); | 97 | ar->sta_list_index = ar->sta_list_index & ~(1 << i); |
93 | 98 | aggr_reset_state(sta->aggr_conn); | |
94 | } | 99 | } |
95 | 100 | ||
96 | static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason) | 101 | static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason) |
@@ -252,7 +257,7 @@ int ath6kl_read_fwlogs(struct ath6kl *ar) | |||
252 | struct ath6kl_dbglog_hdr debug_hdr; | 257 | struct ath6kl_dbglog_hdr debug_hdr; |
253 | struct ath6kl_dbglog_buf debug_buf; | 258 | struct ath6kl_dbglog_buf debug_buf; |
254 | u32 address, length, dropped, firstbuf, debug_hdr_addr; | 259 | u32 address, length, dropped, firstbuf, debug_hdr_addr; |
255 | int ret = 0, loop; | 260 | int ret, loop; |
256 | u8 *buf; | 261 | u8 *buf; |
257 | 262 | ||
258 | buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL); | 263 | buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL); |
@@ -347,9 +352,6 @@ void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, | |||
347 | case TARGET_TYPE_AR6004: | 352 | case TARGET_TYPE_AR6004: |
348 | address = AR6004_RESET_CONTROL_ADDRESS; | 353 | address = AR6004_RESET_CONTROL_ADDRESS; |
349 | break; | 354 | break; |
350 | default: | ||
351 | address = AR6003_RESET_CONTROL_ADDRESS; | ||
352 | break; | ||
353 | } | 355 | } |
354 | 356 | ||
355 | status = ath6kl_diag_write32(ar, address, data); | 357 | status = ath6kl_diag_write32(ar, address, data); |
@@ -363,7 +365,7 @@ static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif) | |||
363 | u8 index; | 365 | u8 index; |
364 | u8 keyusage; | 366 | u8 keyusage; |
365 | 367 | ||
366 | for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { | 368 | for (index = 0; index <= WMI_MAX_KEY_INDEX; index++) { |
367 | if (vif->wep_key_list[index].key_len) { | 369 | if (vif->wep_key_list[index].key_len) { |
368 | keyusage = GROUP_USAGE; | 370 | keyusage = GROUP_USAGE; |
369 | if (index == vif->def_txkey_index) | 371 | if (index == vif->def_txkey_index) |
@@ -428,9 +430,8 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel) | |||
428 | 430 | ||
429 | void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, | 431 | void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, |
430 | u8 keymgmt, u8 ucipher, u8 auth, | 432 | u8 keymgmt, u8 ucipher, u8 auth, |
431 | u8 assoc_req_len, u8 *assoc_info) | 433 | u8 assoc_req_len, u8 *assoc_info, u8 apsd_info) |
432 | { | 434 | { |
433 | struct ath6kl *ar = vif->ar; | ||
434 | u8 *ies = NULL, *wpa_ie = NULL, *pos; | 435 | u8 *ies = NULL, *wpa_ie = NULL, *pos; |
435 | size_t ies_len = 0; | 436 | size_t ies_len = 0; |
436 | struct station_info sinfo; | 437 | struct station_info sinfo; |
@@ -484,9 +485,9 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, | |||
484 | pos += 2 + pos[1]; | 485 | pos += 2 + pos[1]; |
485 | } | 486 | } |
486 | 487 | ||
487 | ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie, | 488 | ath6kl_add_new_sta(vif, mac_addr, aid, wpa_ie, |
488 | wpa_ie ? 2 + wpa_ie[1] : 0, | 489 | wpa_ie ? 2 + wpa_ie[1] : 0, |
489 | keymgmt, ucipher, auth); | 490 | keymgmt, ucipher, auth, apsd_info); |
490 | 491 | ||
491 | /* send event to application */ | 492 | /* send event to application */ |
492 | memset(&sinfo, 0, sizeof(sinfo)); | 493 | memset(&sinfo, 0, sizeof(sinfo)); |
@@ -587,10 +588,11 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, | |||
587 | memcpy(vif->bssid, bssid, sizeof(vif->bssid)); | 588 | memcpy(vif->bssid, bssid, sizeof(vif->bssid)); |
588 | vif->bss_ch = channel; | 589 | vif->bss_ch = channel; |
589 | 590 | ||
590 | if ((vif->nw_type == INFRA_NETWORK)) | 591 | if ((vif->nw_type == INFRA_NETWORK)) { |
592 | ar->listen_intvl_b = listen_int; | ||
591 | ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, | 593 | ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, |
592 | ar->listen_intvl_t, | 594 | 0, ar->listen_intvl_b); |
593 | ar->listen_intvl_b); | 595 | } |
594 | 596 | ||
595 | netif_wake_queue(vif->ndev); | 597 | netif_wake_queue(vif->ndev); |
596 | 598 | ||
@@ -601,7 +603,7 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, | |||
601 | netif_carrier_on(vif->ndev); | 603 | netif_carrier_on(vif->ndev); |
602 | spin_unlock_bh(&vif->if_lock); | 604 | spin_unlock_bh(&vif->if_lock); |
603 | 605 | ||
604 | aggr_reset_state(vif->aggr_cntxt); | 606 | aggr_reset_state(vif->aggr_cntxt->aggr_conn); |
605 | vif->reconnect_flag = 0; | 607 | vif->reconnect_flag = 0; |
606 | 608 | ||
607 | if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) { | 609 | if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) { |
@@ -923,7 +925,7 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, | |||
923 | assoc_resp_len, assoc_info, | 925 | assoc_resp_len, assoc_info, |
924 | prot_reason_status); | 926 | prot_reason_status); |
925 | 927 | ||
926 | aggr_reset_state(vif->aggr_cntxt); | 928 | aggr_reset_state(vif->aggr_cntxt->aggr_conn); |
927 | 929 | ||
928 | del_timer(&vif->disconnect_timer); | 930 | del_timer(&vif->disconnect_timer); |
929 | 931 | ||
@@ -1020,11 +1022,155 @@ static struct net_device_stats *ath6kl_get_stats(struct net_device *dev) | |||
1020 | return &vif->net_stats; | 1022 | return &vif->net_stats; |
1021 | } | 1023 | } |
1022 | 1024 | ||
1023 | static struct net_device_ops ath6kl_netdev_ops = { | 1025 | static int ath6kl_set_features(struct net_device *dev, |
1026 | netdev_features_t features) | ||
1027 | { | ||
1028 | struct ath6kl_vif *vif = netdev_priv(dev); | ||
1029 | struct ath6kl *ar = vif->ar; | ||
1030 | int err = 0; | ||
1031 | |||
1032 | if ((features & NETIF_F_RXCSUM) && | ||
1033 | (ar->rx_meta_ver != WMI_META_VERSION_2)) { | ||
1034 | ar->rx_meta_ver = WMI_META_VERSION_2; | ||
1035 | err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, | ||
1036 | vif->fw_vif_idx, | ||
1037 | ar->rx_meta_ver, 0, 0); | ||
1038 | if (err) { | ||
1039 | dev->features = features & ~NETIF_F_RXCSUM; | ||
1040 | return err; | ||
1041 | } | ||
1042 | } else if (!(features & NETIF_F_RXCSUM) && | ||
1043 | (ar->rx_meta_ver == WMI_META_VERSION_2)) { | ||
1044 | ar->rx_meta_ver = 0; | ||
1045 | err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, | ||
1046 | vif->fw_vif_idx, | ||
1047 | ar->rx_meta_ver, 0, 0); | ||
1048 | if (err) { | ||
1049 | dev->features = features | NETIF_F_RXCSUM; | ||
1050 | return err; | ||
1051 | } | ||
1052 | |||
1053 | } | ||
1054 | |||
1055 | return err; | ||
1056 | } | ||
1057 | |||
1058 | static void ath6kl_set_multicast_list(struct net_device *ndev) | ||
1059 | { | ||
1060 | struct ath6kl_vif *vif = netdev_priv(ndev); | ||
1061 | bool mc_all_on = false, mc_all_off = false; | ||
1062 | int mc_count = netdev_mc_count(ndev); | ||
1063 | struct netdev_hw_addr *ha; | ||
1064 | bool found; | ||
1065 | struct ath6kl_mc_filter *mc_filter, *tmp; | ||
1066 | struct list_head mc_filter_new; | ||
1067 | int ret; | ||
1068 | |||
1069 | if (!test_bit(WMI_READY, &vif->ar->flag) || | ||
1070 | !test_bit(WLAN_ENABLED, &vif->flags)) | ||
1071 | return; | ||
1072 | |||
1073 | mc_all_on = !!(ndev->flags & IFF_PROMISC) || | ||
1074 | !!(ndev->flags & IFF_ALLMULTI) || | ||
1075 | !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); | ||
1076 | |||
1077 | mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0; | ||
1078 | |||
1079 | if (mc_all_on || mc_all_off) { | ||
1080 | /* Enable/disable all multicast */ | ||
1081 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n", | ||
1082 | mc_all_on ? "enabling" : "disabling"); | ||
1083 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, | ||
1084 | mc_all_on); | ||
1085 | if (ret) | ||
1086 | ath6kl_warn("Failed to %s multicast receive\n", | ||
1087 | mc_all_on ? "enable" : "disable"); | ||
1088 | return; | ||
1089 | } | ||
1090 | |||
1091 | list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { | ||
1092 | found = false; | ||
1093 | netdev_for_each_mc_addr(ha, ndev) { | ||
1094 | if (memcmp(ha->addr, mc_filter->hw_addr, | ||
1095 | ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) { | ||
1096 | found = true; | ||
1097 | break; | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | if (!found) { | ||
1102 | /* | ||
1103 | * Delete the filter which was previously set | ||
1104 | * but not in the new request. | ||
1105 | */ | ||
1106 | ath6kl_dbg(ATH6KL_DBG_TRC, | ||
1107 | "Removing %pM from multicast filter\n", | ||
1108 | mc_filter->hw_addr); | ||
1109 | ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi, | ||
1110 | vif->fw_vif_idx, mc_filter->hw_addr, | ||
1111 | false); | ||
1112 | if (ret) { | ||
1113 | ath6kl_warn("Failed to remove multicast filter:%pM\n", | ||
1114 | mc_filter->hw_addr); | ||
1115 | return; | ||
1116 | } | ||
1117 | |||
1118 | list_del(&mc_filter->list); | ||
1119 | kfree(mc_filter); | ||
1120 | } | ||
1121 | } | ||
1122 | |||
1123 | INIT_LIST_HEAD(&mc_filter_new); | ||
1124 | |||
1125 | netdev_for_each_mc_addr(ha, ndev) { | ||
1126 | found = false; | ||
1127 | list_for_each_entry(mc_filter, &vif->mc_filter, list) { | ||
1128 | if (memcmp(ha->addr, mc_filter->hw_addr, | ||
1129 | ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) { | ||
1130 | found = true; | ||
1131 | break; | ||
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | if (!found) { | ||
1136 | mc_filter = kzalloc(sizeof(struct ath6kl_mc_filter), | ||
1137 | GFP_ATOMIC); | ||
1138 | if (!mc_filter) { | ||
1139 | WARN_ON(1); | ||
1140 | goto out; | ||
1141 | } | ||
1142 | |||
1143 | memcpy(mc_filter->hw_addr, ha->addr, | ||
1144 | ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE); | ||
1145 | /* Set the multicast filter */ | ||
1146 | ath6kl_dbg(ATH6KL_DBG_TRC, | ||
1147 | "Adding %pM to multicast filter list\n", | ||
1148 | mc_filter->hw_addr); | ||
1149 | ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi, | ||
1150 | vif->fw_vif_idx, mc_filter->hw_addr, | ||
1151 | true); | ||
1152 | if (ret) { | ||
1153 | ath6kl_warn("Failed to add multicast filter :%pM\n", | ||
1154 | mc_filter->hw_addr); | ||
1155 | kfree(mc_filter); | ||
1156 | goto out; | ||
1157 | } | ||
1158 | |||
1159 | list_add_tail(&mc_filter->list, &mc_filter_new); | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1163 | out: | ||
1164 | list_splice_tail(&mc_filter_new, &vif->mc_filter); | ||
1165 | } | ||
1166 | |||
1167 | static const struct net_device_ops ath6kl_netdev_ops = { | ||
1024 | .ndo_open = ath6kl_open, | 1168 | .ndo_open = ath6kl_open, |
1025 | .ndo_stop = ath6kl_close, | 1169 | .ndo_stop = ath6kl_close, |
1026 | .ndo_start_xmit = ath6kl_data_tx, | 1170 | .ndo_start_xmit = ath6kl_data_tx, |
1027 | .ndo_get_stats = ath6kl_get_stats, | 1171 | .ndo_get_stats = ath6kl_get_stats, |
1172 | .ndo_set_features = ath6kl_set_features, | ||
1173 | .ndo_set_rx_mode = ath6kl_set_multicast_list, | ||
1028 | }; | 1174 | }; |
1029 | 1175 | ||
1030 | void init_netdev(struct net_device *dev) | 1176 | void init_netdev(struct net_device *dev) |
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 9475e2d0d0b7..4febee723495 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -49,11 +49,13 @@ struct ath6kl_sdio { | |||
49 | /* scatter request list head */ | 49 | /* scatter request list head */ |
50 | struct list_head scat_req; | 50 | struct list_head scat_req; |
51 | 51 | ||
52 | /* Avoids disabling irq while the interrupts being handled */ | ||
53 | struct mutex mtx_irq; | ||
54 | |||
52 | spinlock_t scat_lock; | 55 | spinlock_t scat_lock; |
53 | bool scatter_enabled; | 56 | bool scatter_enabled; |
54 | 57 | ||
55 | bool is_disabled; | 58 | bool is_disabled; |
56 | atomic_t irq_handling; | ||
57 | const struct sdio_device_id *id; | 59 | const struct sdio_device_id *id; |
58 | struct work_struct wr_async_work; | 60 | struct work_struct wr_async_work; |
59 | struct list_head wr_asyncq; | 61 | struct list_head wr_asyncq; |
@@ -460,8 +462,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) | |||
460 | ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); | 462 | ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); |
461 | 463 | ||
462 | ar_sdio = sdio_get_drvdata(func); | 464 | ar_sdio = sdio_get_drvdata(func); |
463 | atomic_set(&ar_sdio->irq_handling, 1); | 465 | mutex_lock(&ar_sdio->mtx_irq); |
464 | |||
465 | /* | 466 | /* |
466 | * Release the host during interrups so we can pick it back up when | 467 | * Release the host during interrups so we can pick it back up when |
467 | * we process commands. | 468 | * we process commands. |
@@ -470,7 +471,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) | |||
470 | 471 | ||
471 | status = ath6kl_hif_intr_bh_handler(ar_sdio->ar); | 472 | status = ath6kl_hif_intr_bh_handler(ar_sdio->ar); |
472 | sdio_claim_host(ar_sdio->func); | 473 | sdio_claim_host(ar_sdio->func); |
473 | atomic_set(&ar_sdio->irq_handling, 0); | 474 | mutex_unlock(&ar_sdio->mtx_irq); |
474 | WARN_ON(status && status != -ECANCELED); | 475 | WARN_ON(status && status != -ECANCELED); |
475 | } | 476 | } |
476 | 477 | ||
@@ -578,17 +579,14 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar) | |||
578 | 579 | ||
579 | sdio_claim_host(ar_sdio->func); | 580 | sdio_claim_host(ar_sdio->func); |
580 | 581 | ||
581 | /* Mask our function IRQ */ | 582 | mutex_lock(&ar_sdio->mtx_irq); |
582 | while (atomic_read(&ar_sdio->irq_handling)) { | ||
583 | sdio_release_host(ar_sdio->func); | ||
584 | schedule_timeout(HZ / 10); | ||
585 | sdio_claim_host(ar_sdio->func); | ||
586 | } | ||
587 | 583 | ||
588 | ret = sdio_release_irq(ar_sdio->func); | 584 | ret = sdio_release_irq(ar_sdio->func); |
589 | if (ret) | 585 | if (ret) |
590 | ath6kl_err("Failed to release sdio irq: %d\n", ret); | 586 | ath6kl_err("Failed to release sdio irq: %d\n", ret); |
591 | 587 | ||
588 | mutex_unlock(&ar_sdio->mtx_irq); | ||
589 | |||
592 | sdio_release_host(ar_sdio->func); | 590 | sdio_release_host(ar_sdio->func); |
593 | } | 591 | } |
594 | 592 | ||
@@ -772,7 +770,6 @@ static int ath6kl_sdio_config(struct ath6kl *ar) | |||
772 | if (ret) { | 770 | if (ret) { |
773 | ath6kl_err("Set sdio block size %d failed: %d)\n", | 771 | ath6kl_err("Set sdio block size %d failed: %d)\n", |
774 | HIF_MBOX_BLOCK_SIZE, ret); | 772 | HIF_MBOX_BLOCK_SIZE, ret); |
775 | sdio_release_host(func); | ||
776 | goto out; | 773 | goto out; |
777 | } | 774 | } |
778 | 775 | ||
@@ -782,7 +779,7 @@ out: | |||
782 | return ret; | 779 | return ret; |
783 | } | 780 | } |
784 | 781 | ||
785 | static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | 782 | static int ath6kl_set_sdio_pm_caps(struct ath6kl *ar) |
786 | { | 783 | { |
787 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); | 784 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); |
788 | struct sdio_func *func = ar_sdio->func; | 785 | struct sdio_func *func = ar_sdio->func; |
@@ -793,60 +790,95 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
793 | 790 | ||
794 | ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio suspend pm_caps 0x%x\n", flags); | 791 | ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio suspend pm_caps 0x%x\n", flags); |
795 | 792 | ||
796 | if (!(flags & MMC_PM_KEEP_POWER) || | 793 | if (!(flags & MMC_PM_WAKE_SDIO_IRQ) || |
797 | (ar->conf_flags & ATH6KL_CONF_SUSPEND_CUTPOWER)) { | 794 | !(flags & MMC_PM_KEEP_POWER)) |
798 | /* as host doesn't support keep power we need to cut power */ | 795 | return -EINVAL; |
799 | return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, | ||
800 | NULL); | ||
801 | } | ||
802 | 796 | ||
803 | ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | 797 | ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); |
804 | if (ret) { | 798 | if (ret) { |
805 | printk(KERN_ERR "ath6kl: set sdio pm flags failed: %d\n", | 799 | ath6kl_err("set sdio keep pwr flag failed: %d\n", ret); |
806 | ret); | ||
807 | return ret; | 800 | return ret; |
808 | } | 801 | } |
809 | 802 | ||
810 | if (!(flags & MMC_PM_WAKE_SDIO_IRQ)) | ||
811 | goto deepsleep; | ||
812 | |||
813 | /* sdio irq wakes up host */ | 803 | /* sdio irq wakes up host */ |
804 | ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); | ||
805 | if (ret) | ||
806 | ath6kl_err("set sdio wake irq flag failed: %d\n", ret); | ||
807 | |||
808 | return ret; | ||
809 | } | ||
810 | |||
811 | static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | ||
812 | { | ||
813 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); | ||
814 | struct sdio_func *func = ar_sdio->func; | ||
815 | mmc_pm_flag_t flags; | ||
816 | int ret; | ||
814 | 817 | ||
815 | if (ar->state == ATH6KL_STATE_SCHED_SCAN) { | 818 | if (ar->state == ATH6KL_STATE_SCHED_SCAN) { |
819 | ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sched scan is in progress\n"); | ||
820 | |||
821 | ret = ath6kl_set_sdio_pm_caps(ar); | ||
822 | if (ret) | ||
823 | goto cut_pwr; | ||
824 | |||
816 | ret = ath6kl_cfg80211_suspend(ar, | 825 | ret = ath6kl_cfg80211_suspend(ar, |
817 | ATH6KL_CFG_SUSPEND_SCHED_SCAN, | 826 | ATH6KL_CFG_SUSPEND_SCHED_SCAN, |
818 | NULL); | 827 | NULL); |
819 | if (ret) { | 828 | if (ret) |
820 | ath6kl_warn("Schedule scan suspend failed: %d", ret); | 829 | goto cut_pwr; |
821 | return ret; | 830 | |
822 | } | 831 | return 0; |
832 | } | ||
833 | |||
834 | if (ar->suspend_mode == WLAN_POWER_STATE_WOW || | ||
835 | (!ar->suspend_mode && wow)) { | ||
823 | 836 | ||
824 | ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); | 837 | ret = ath6kl_set_sdio_pm_caps(ar); |
825 | if (ret) | 838 | if (ret) |
826 | ath6kl_warn("set sdio wake irq flag failed: %d\n", ret); | 839 | goto cut_pwr; |
827 | 840 | ||
828 | return ret; | 841 | ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow); |
842 | if (ret) | ||
843 | goto cut_pwr; | ||
844 | |||
845 | return 0; | ||
829 | } | 846 | } |
830 | 847 | ||
831 | if (wow) { | 848 | if (ar->suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP || |
849 | !ar->suspend_mode) { | ||
850 | |||
851 | flags = sdio_get_host_pm_caps(func); | ||
852 | if (!(flags & MMC_PM_KEEP_POWER)) | ||
853 | goto cut_pwr; | ||
854 | |||
855 | ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | ||
856 | if (ret) | ||
857 | goto cut_pwr; | ||
858 | |||
832 | /* | 859 | /* |
833 | * The host sdio controller is capable of keep power and | 860 | * Workaround to support Deep Sleep with MSM, set the host pm |
834 | * sdio irq wake up at this point. It's fine to continue | 861 | * flag as MMC_PM_WAKE_SDIO_IRQ to allow SDCC deiver to disable |
835 | * wow suspend operation. | 862 | * the sdc2_clock and internally allows MSM to enter |
863 | * TCXO shutdown properly. | ||
836 | */ | 864 | */ |
837 | ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow); | 865 | if ((flags & MMC_PM_WAKE_SDIO_IRQ)) { |
838 | if (ret) | 866 | ret = sdio_set_host_pm_flags(func, |
839 | return ret; | 867 | MMC_PM_WAKE_SDIO_IRQ); |
868 | if (ret) | ||
869 | goto cut_pwr; | ||
870 | } | ||
840 | 871 | ||
841 | ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); | 872 | ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, |
873 | NULL); | ||
842 | if (ret) | 874 | if (ret) |
843 | ath6kl_err("set sdio wake irq flag failed: %d\n", ret); | 875 | goto cut_pwr; |
844 | 876 | ||
845 | return ret; | 877 | return 0; |
846 | } | 878 | } |
847 | 879 | ||
848 | deepsleep: | 880 | cut_pwr: |
849 | return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, NULL); | 881 | return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL); |
850 | } | 882 | } |
851 | 883 | ||
852 | static int ath6kl_sdio_resume(struct ath6kl *ar) | 884 | static int ath6kl_sdio_resume(struct ath6kl *ar) |
@@ -1253,6 +1285,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
1253 | spin_lock_init(&ar_sdio->scat_lock); | 1285 | spin_lock_init(&ar_sdio->scat_lock); |
1254 | spin_lock_init(&ar_sdio->wr_async_lock); | 1286 | spin_lock_init(&ar_sdio->wr_async_lock); |
1255 | mutex_init(&ar_sdio->dma_buffer_mutex); | 1287 | mutex_init(&ar_sdio->dma_buffer_mutex); |
1288 | mutex_init(&ar_sdio->mtx_irq); | ||
1256 | 1289 | ||
1257 | INIT_LIST_HEAD(&ar_sdio->scat_req); | 1290 | INIT_LIST_HEAD(&ar_sdio->scat_req); |
1258 | INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); | 1291 | INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); |
@@ -1263,7 +1296,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
1263 | for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) | 1296 | for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) |
1264 | ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]); | 1297 | ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]); |
1265 | 1298 | ||
1266 | ar = ath6kl_core_alloc(&ar_sdio->func->dev); | 1299 | ar = ath6kl_core_create(&ar_sdio->func->dev); |
1267 | if (!ar) { | 1300 | if (!ar) { |
1268 | ath6kl_err("Failed to alloc ath6kl core\n"); | 1301 | ath6kl_err("Failed to alloc ath6kl core\n"); |
1269 | ret = -ENOMEM; | 1302 | ret = -ENOMEM; |
@@ -1293,7 +1326,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
1293 | return ret; | 1326 | return ret; |
1294 | 1327 | ||
1295 | err_core_alloc: | 1328 | err_core_alloc: |
1296 | ath6kl_core_free(ar_sdio->ar); | 1329 | ath6kl_core_destroy(ar_sdio->ar); |
1297 | err_dma: | 1330 | err_dma: |
1298 | kfree(ar_sdio->dma_buffer); | 1331 | kfree(ar_sdio->dma_buffer); |
1299 | err_hif: | 1332 | err_hif: |
@@ -1316,6 +1349,7 @@ static void ath6kl_sdio_remove(struct sdio_func *func) | |||
1316 | cancel_work_sync(&ar_sdio->wr_async_work); | 1349 | cancel_work_sync(&ar_sdio->wr_async_work); |
1317 | 1350 | ||
1318 | ath6kl_core_cleanup(ar_sdio->ar); | 1351 | ath6kl_core_cleanup(ar_sdio->ar); |
1352 | ath6kl_core_destroy(ar_sdio->ar); | ||
1319 | 1353 | ||
1320 | kfree(ar_sdio->dma_buffer); | 1354 | kfree(ar_sdio->dma_buffer); |
1321 | kfree(ar_sdio); | 1355 | kfree(ar_sdio); |
@@ -1332,7 +1366,7 @@ static const struct sdio_device_id ath6kl_sdio_devices[] = { | |||
1332 | MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices); | 1366 | MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices); |
1333 | 1367 | ||
1334 | static struct sdio_driver ath6kl_sdio_driver = { | 1368 | static struct sdio_driver ath6kl_sdio_driver = { |
1335 | .name = "ath6kl", | 1369 | .name = "ath6kl_sdio", |
1336 | .id_table = ath6kl_sdio_devices, | 1370 | .id_table = ath6kl_sdio_devices, |
1337 | .probe = ath6kl_sdio_probe, | 1371 | .probe = ath6kl_sdio_probe, |
1338 | .remove = ath6kl_sdio_remove, | 1372 | .remove = ath6kl_sdio_remove, |
@@ -1362,19 +1396,19 @@ MODULE_AUTHOR("Atheros Communications, Inc."); | |||
1362 | MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices"); | 1396 | MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices"); |
1363 | MODULE_LICENSE("Dual BSD/GPL"); | 1397 | MODULE_LICENSE("Dual BSD/GPL"); |
1364 | 1398 | ||
1365 | MODULE_FIRMWARE(AR6003_HW_2_0_OTP_FILE); | 1399 | MODULE_FIRMWARE(AR6003_HW_2_0_FW_DIR "/" AR6003_HW_2_0_OTP_FILE); |
1366 | MODULE_FIRMWARE(AR6003_HW_2_0_FIRMWARE_FILE); | 1400 | MODULE_FIRMWARE(AR6003_HW_2_0_FW_DIR "/" AR6003_HW_2_0_FIRMWARE_FILE); |
1367 | MODULE_FIRMWARE(AR6003_HW_2_0_PATCH_FILE); | 1401 | MODULE_FIRMWARE(AR6003_HW_2_0_FW_DIR "/" AR6003_HW_2_0_PATCH_FILE); |
1368 | MODULE_FIRMWARE(AR6003_HW_2_0_BOARD_DATA_FILE); | 1402 | MODULE_FIRMWARE(AR6003_HW_2_0_BOARD_DATA_FILE); |
1369 | MODULE_FIRMWARE(AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE); | 1403 | MODULE_FIRMWARE(AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE); |
1370 | MODULE_FIRMWARE(AR6003_HW_2_1_1_OTP_FILE); | 1404 | MODULE_FIRMWARE(AR6003_HW_2_1_1_FW_DIR "/" AR6003_HW_2_1_1_OTP_FILE); |
1371 | MODULE_FIRMWARE(AR6003_HW_2_1_1_FIRMWARE_FILE); | 1405 | MODULE_FIRMWARE(AR6003_HW_2_1_1_FW_DIR "/" AR6003_HW_2_1_1_FIRMWARE_FILE); |
1372 | MODULE_FIRMWARE(AR6003_HW_2_1_1_PATCH_FILE); | 1406 | MODULE_FIRMWARE(AR6003_HW_2_1_1_FW_DIR "/" AR6003_HW_2_1_1_PATCH_FILE); |
1373 | MODULE_FIRMWARE(AR6003_HW_2_1_1_BOARD_DATA_FILE); | 1407 | MODULE_FIRMWARE(AR6003_HW_2_1_1_BOARD_DATA_FILE); |
1374 | MODULE_FIRMWARE(AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE); | 1408 | MODULE_FIRMWARE(AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE); |
1375 | MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); | 1409 | MODULE_FIRMWARE(AR6004_HW_1_0_FW_DIR "/" AR6004_HW_1_0_FIRMWARE_FILE); |
1376 | MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); | 1410 | MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); |
1377 | MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); | 1411 | MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); |
1378 | MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); | 1412 | MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE); |
1379 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); | 1413 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); |
1380 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); | 1414 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); |
diff --git a/drivers/net/wireless/ath/ath6kl/testmode.c b/drivers/net/wireless/ath/ath6kl/testmode.c index 381eb66a605f..f0cd61d6188a 100644 --- a/drivers/net/wireless/ath/ath6kl/testmode.c +++ b/drivers/net/wireless/ath/ath6kl/testmode.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "testmode.h" | 17 | #include "testmode.h" |
18 | #include "debug.h" | ||
18 | 19 | ||
19 | #include <net/netlink.h> | 20 | #include <net/netlink.h> |
20 | 21 | ||
@@ -30,7 +31,7 @@ enum ath6kl_tm_attr { | |||
30 | 31 | ||
31 | enum ath6kl_tm_cmd { | 32 | enum ath6kl_tm_cmd { |
32 | ATH6KL_TM_CMD_TCMD = 0, | 33 | ATH6KL_TM_CMD_TCMD = 0, |
33 | ATH6KL_TM_CMD_RX_REPORT = 1, | 34 | ATH6KL_TM_CMD_RX_REPORT = 1, /* not used anymore */ |
34 | }; | 35 | }; |
35 | 36 | ||
36 | #define ATH6KL_TM_DATA_MAX_LEN 5000 | 37 | #define ATH6KL_TM_DATA_MAX_LEN 5000 |
@@ -41,84 +42,33 @@ static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = { | |||
41 | .len = ATH6KL_TM_DATA_MAX_LEN }, | 42 | .len = ATH6KL_TM_DATA_MAX_LEN }, |
42 | }; | 43 | }; |
43 | 44 | ||
44 | void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len) | 45 | void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, size_t buf_len) |
45 | { | 46 | { |
46 | if (down_interruptible(&ar->sem)) | 47 | struct sk_buff *skb; |
47 | return; | ||
48 | |||
49 | kfree(ar->tm.rx_report); | ||
50 | |||
51 | ar->tm.rx_report = kmemdup(buf, buf_len, GFP_KERNEL); | ||
52 | ar->tm.rx_report_len = buf_len; | ||
53 | |||
54 | up(&ar->sem); | ||
55 | |||
56 | wake_up(&ar->event_wq); | ||
57 | } | ||
58 | |||
59 | static int ath6kl_tm_rx_report(struct ath6kl *ar, void *buf, size_t buf_len, | ||
60 | struct sk_buff *skb) | ||
61 | { | ||
62 | int ret = 0; | ||
63 | long left; | ||
64 | |||
65 | if (down_interruptible(&ar->sem)) | ||
66 | return -ERESTARTSYS; | ||
67 | |||
68 | if (!test_bit(WMI_READY, &ar->flag)) { | ||
69 | ret = -EIO; | ||
70 | goto out; | ||
71 | } | ||
72 | |||
73 | if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { | ||
74 | ret = -EBUSY; | ||
75 | goto out; | ||
76 | } | ||
77 | |||
78 | if (ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len) < 0) { | ||
79 | up(&ar->sem); | ||
80 | return -EIO; | ||
81 | } | ||
82 | |||
83 | left = wait_event_interruptible_timeout(ar->event_wq, | ||
84 | ar->tm.rx_report != NULL, | ||
85 | WMI_TIMEOUT); | ||
86 | 48 | ||
87 | if (left == 0) { | 49 | if (!buf || buf_len == 0) |
88 | ret = -ETIMEDOUT; | 50 | return; |
89 | goto out; | ||
90 | } else if (left < 0) { | ||
91 | ret = left; | ||
92 | goto out; | ||
93 | } | ||
94 | 51 | ||
95 | if (ar->tm.rx_report == NULL || ar->tm.rx_report_len == 0) { | 52 | skb = cfg80211_testmode_alloc_event_skb(ar->wiphy, buf_len, GFP_KERNEL); |
96 | ret = -EINVAL; | 53 | if (!skb) { |
97 | goto out; | 54 | ath6kl_warn("failed to allocate testmode rx skb!\n"); |
55 | return; | ||
98 | } | 56 | } |
99 | 57 | NLA_PUT_U32(skb, ATH6KL_TM_ATTR_CMD, ATH6KL_TM_CMD_TCMD); | |
100 | NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, ar->tm.rx_report_len, | 58 | NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, buf_len, buf); |
101 | ar->tm.rx_report); | 59 | cfg80211_testmode_event(skb, GFP_KERNEL); |
102 | 60 | return; | |
103 | kfree(ar->tm.rx_report); | ||
104 | ar->tm.rx_report = NULL; | ||
105 | |||
106 | out: | ||
107 | up(&ar->sem); | ||
108 | |||
109 | return ret; | ||
110 | 61 | ||
111 | nla_put_failure: | 62 | nla_put_failure: |
112 | ret = -ENOBUFS; | 63 | kfree_skb(skb); |
113 | goto out; | 64 | ath6kl_warn("nla_put failed on testmode rx skb!\n"); |
114 | } | 65 | } |
115 | 66 | ||
116 | int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) | 67 | int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) |
117 | { | 68 | { |
118 | struct ath6kl *ar = wiphy_priv(wiphy); | 69 | struct ath6kl *ar = wiphy_priv(wiphy); |
119 | struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; | 70 | struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; |
120 | int err, buf_len, reply_len; | 71 | int err, buf_len; |
121 | struct sk_buff *skb; | ||
122 | void *buf; | 72 | void *buf; |
123 | 73 | ||
124 | err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, | 74 | err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, |
@@ -143,24 +93,6 @@ int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) | |||
143 | 93 | ||
144 | break; | 94 | break; |
145 | case ATH6KL_TM_CMD_RX_REPORT: | 95 | case ATH6KL_TM_CMD_RX_REPORT: |
146 | if (!tb[ATH6KL_TM_ATTR_DATA]) | ||
147 | return -EINVAL; | ||
148 | |||
149 | buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); | ||
150 | buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); | ||
151 | |||
152 | reply_len = nla_total_size(ATH6KL_TM_DATA_MAX_LEN); | ||
153 | skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); | ||
154 | if (!skb) | ||
155 | return -ENOMEM; | ||
156 | |||
157 | err = ath6kl_tm_rx_report(ar, buf, buf_len, skb); | ||
158 | if (err < 0) { | ||
159 | kfree_skb(skb); | ||
160 | return err; | ||
161 | } | ||
162 | |||
163 | return cfg80211_testmode_reply(skb); | ||
164 | default: | 96 | default: |
165 | return -EOPNOTSUPP; | 97 | return -EOPNOTSUPP; |
166 | } | 98 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/testmode.h b/drivers/net/wireless/ath/ath6kl/testmode.h index 43dffcc11fb1..7fd47a62d078 100644 --- a/drivers/net/wireless/ath/ath6kl/testmode.h +++ b/drivers/net/wireless/ath/ath6kl/testmode.h | |||
@@ -18,13 +18,13 @@ | |||
18 | 18 | ||
19 | #ifdef CONFIG_NL80211_TESTMODE | 19 | #ifdef CONFIG_NL80211_TESTMODE |
20 | 20 | ||
21 | void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len); | 21 | void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, size_t buf_len); |
22 | int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len); | 22 | int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len); |
23 | 23 | ||
24 | #else | 24 | #else |
25 | 25 | ||
26 | static inline void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, | 26 | static inline void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, |
27 | size_t buf_len) | 27 | size_t buf_len) |
28 | { | 28 | { |
29 | } | 29 | } |
30 | 30 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 506a3031a885..a3dc6943c7f7 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -17,6 +17,23 @@ | |||
17 | #include "core.h" | 17 | #include "core.h" |
18 | #include "debug.h" | 18 | #include "debug.h" |
19 | 19 | ||
20 | /* | ||
21 | * tid - tid_mux0..tid_mux3 | ||
22 | * aid - tid_mux4..tid_mux7 | ||
23 | */ | ||
24 | #define ATH6KL_TID_MASK 0xf | ||
25 | #define ATH6KL_AID_SHIFT 4 | ||
26 | |||
27 | static inline u8 ath6kl_get_tid(u8 tid_mux) | ||
28 | { | ||
29 | return tid_mux & ATH6KL_TID_MASK; | ||
30 | } | ||
31 | |||
32 | static inline u8 ath6kl_get_aid(u8 tid_mux) | ||
33 | { | ||
34 | return tid_mux >> ATH6KL_AID_SHIFT; | ||
35 | } | ||
36 | |||
20 | static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, | 37 | static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, |
21 | u32 *map_no) | 38 | u32 *map_no) |
22 | { | 39 | { |
@@ -77,12 +94,118 @@ static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, | |||
77 | return ar->node_map[ep_map].ep_id; | 94 | return ar->node_map[ep_map].ep_id; |
78 | } | 95 | } |
79 | 96 | ||
97 | static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn, | ||
98 | struct ath6kl_vif *vif, | ||
99 | struct sk_buff *skb, | ||
100 | u32 *flags) | ||
101 | { | ||
102 | struct ath6kl *ar = vif->ar; | ||
103 | bool is_apsdq_empty = false; | ||
104 | struct ethhdr *datap = (struct ethhdr *) skb->data; | ||
105 | u8 up = 0, traffic_class, *ip_hdr; | ||
106 | u16 ether_type; | ||
107 | struct ath6kl_llc_snap_hdr *llc_hdr; | ||
108 | |||
109 | if (conn->sta_flags & STA_PS_APSD_TRIGGER) { | ||
110 | /* | ||
111 | * This tx is because of a uAPSD trigger, determine | ||
112 | * more and EOSP bit. Set EOSP if queue is empty | ||
113 | * or sufficient frames are delivered for this trigger. | ||
114 | */ | ||
115 | spin_lock_bh(&conn->psq_lock); | ||
116 | if (!skb_queue_empty(&conn->apsdq)) | ||
117 | *flags |= WMI_DATA_HDR_FLAGS_MORE; | ||
118 | else if (conn->sta_flags & STA_PS_APSD_EOSP) | ||
119 | *flags |= WMI_DATA_HDR_FLAGS_EOSP; | ||
120 | *flags |= WMI_DATA_HDR_FLAGS_UAPSD; | ||
121 | spin_unlock_bh(&conn->psq_lock); | ||
122 | return false; | ||
123 | } else if (!conn->apsd_info) | ||
124 | return false; | ||
125 | |||
126 | if (test_bit(WMM_ENABLED, &vif->flags)) { | ||
127 | ether_type = be16_to_cpu(datap->h_proto); | ||
128 | if (is_ethertype(ether_type)) { | ||
129 | /* packet is in DIX format */ | ||
130 | ip_hdr = (u8 *)(datap + 1); | ||
131 | } else { | ||
132 | /* packet is in 802.3 format */ | ||
133 | llc_hdr = (struct ath6kl_llc_snap_hdr *) | ||
134 | (datap + 1); | ||
135 | ether_type = be16_to_cpu(llc_hdr->eth_type); | ||
136 | ip_hdr = (u8 *)(llc_hdr + 1); | ||
137 | } | ||
138 | |||
139 | if (ether_type == IP_ETHERTYPE) | ||
140 | up = ath6kl_wmi_determine_user_priority( | ||
141 | ip_hdr, 0); | ||
142 | } | ||
143 | |||
144 | traffic_class = ath6kl_wmi_get_traffic_class(up); | ||
145 | |||
146 | if ((conn->apsd_info & (1 << traffic_class)) == 0) | ||
147 | return false; | ||
148 | |||
149 | /* Queue the frames if the STA is sleeping */ | ||
150 | spin_lock_bh(&conn->psq_lock); | ||
151 | is_apsdq_empty = skb_queue_empty(&conn->apsdq); | ||
152 | skb_queue_tail(&conn->apsdq, skb); | ||
153 | spin_unlock_bh(&conn->psq_lock); | ||
154 | |||
155 | /* | ||
156 | * If this is the first pkt getting queued | ||
157 | * for this STA, update the PVB for this STA | ||
158 | */ | ||
159 | if (is_apsdq_empty) { | ||
160 | ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, | ||
161 | vif->fw_vif_idx, | ||
162 | conn->aid, 1, 0); | ||
163 | } | ||
164 | *flags |= WMI_DATA_HDR_FLAGS_UAPSD; | ||
165 | |||
166 | return true; | ||
167 | } | ||
168 | |||
169 | static bool ath6kl_process_psq(struct ath6kl_sta *conn, | ||
170 | struct ath6kl_vif *vif, | ||
171 | struct sk_buff *skb, | ||
172 | u32 *flags) | ||
173 | { | ||
174 | bool is_psq_empty = false; | ||
175 | struct ath6kl *ar = vif->ar; | ||
176 | |||
177 | if (conn->sta_flags & STA_PS_POLLED) { | ||
178 | spin_lock_bh(&conn->psq_lock); | ||
179 | if (!skb_queue_empty(&conn->psq)) | ||
180 | *flags |= WMI_DATA_HDR_FLAGS_MORE; | ||
181 | spin_unlock_bh(&conn->psq_lock); | ||
182 | return false; | ||
183 | } | ||
184 | |||
185 | /* Queue the frames if the STA is sleeping */ | ||
186 | spin_lock_bh(&conn->psq_lock); | ||
187 | is_psq_empty = skb_queue_empty(&conn->psq); | ||
188 | skb_queue_tail(&conn->psq, skb); | ||
189 | spin_unlock_bh(&conn->psq_lock); | ||
190 | |||
191 | /* | ||
192 | * If this is the first pkt getting queued | ||
193 | * for this STA, update the PVB for this | ||
194 | * STA. | ||
195 | */ | ||
196 | if (is_psq_empty) | ||
197 | ath6kl_wmi_set_pvb_cmd(ar->wmi, | ||
198 | vif->fw_vif_idx, | ||
199 | conn->aid, 1); | ||
200 | return true; | ||
201 | } | ||
202 | |||
80 | static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, | 203 | static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, |
81 | bool *more_data) | 204 | u32 *flags) |
82 | { | 205 | { |
83 | struct ethhdr *datap = (struct ethhdr *) skb->data; | 206 | struct ethhdr *datap = (struct ethhdr *) skb->data; |
84 | struct ath6kl_sta *conn = NULL; | 207 | struct ath6kl_sta *conn = NULL; |
85 | bool ps_queued = false, is_psq_empty = false; | 208 | bool ps_queued = false; |
86 | struct ath6kl *ar = vif->ar; | 209 | struct ath6kl *ar = vif->ar; |
87 | 210 | ||
88 | if (is_multicast_ether_addr(datap->h_dest)) { | 211 | if (is_multicast_ether_addr(datap->h_dest)) { |
@@ -128,7 +251,7 @@ static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, | |||
128 | */ | 251 | */ |
129 | spin_lock_bh(&ar->mcastpsq_lock); | 252 | spin_lock_bh(&ar->mcastpsq_lock); |
130 | if (!skb_queue_empty(&ar->mcastpsq)) | 253 | if (!skb_queue_empty(&ar->mcastpsq)) |
131 | *more_data = true; | 254 | *flags |= WMI_DATA_HDR_FLAGS_MORE; |
132 | spin_unlock_bh(&ar->mcastpsq_lock); | 255 | spin_unlock_bh(&ar->mcastpsq_lock); |
133 | } | 256 | } |
134 | } | 257 | } |
@@ -142,37 +265,13 @@ static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, | |||
142 | } | 265 | } |
143 | 266 | ||
144 | if (conn->sta_flags & STA_PS_SLEEP) { | 267 | if (conn->sta_flags & STA_PS_SLEEP) { |
145 | if (!(conn->sta_flags & STA_PS_POLLED)) { | 268 | ps_queued = ath6kl_process_uapsdq(conn, |
146 | /* Queue the frames if the STA is sleeping */ | 269 | vif, skb, flags); |
147 | spin_lock_bh(&conn->psq_lock); | 270 | if (!(*flags & WMI_DATA_HDR_FLAGS_UAPSD)) |
148 | is_psq_empty = skb_queue_empty(&conn->psq); | 271 | ps_queued = ath6kl_process_psq(conn, |
149 | skb_queue_tail(&conn->psq, skb); | 272 | vif, skb, flags); |
150 | spin_unlock_bh(&conn->psq_lock); | ||
151 | |||
152 | /* | ||
153 | * If this is the first pkt getting queued | ||
154 | * for this STA, update the PVB for this | ||
155 | * STA. | ||
156 | */ | ||
157 | if (is_psq_empty) | ||
158 | ath6kl_wmi_set_pvb_cmd(ar->wmi, | ||
159 | vif->fw_vif_idx, | ||
160 | conn->aid, 1); | ||
161 | |||
162 | ps_queued = true; | ||
163 | } else { | ||
164 | /* | ||
165 | * This tx is because of a PsPoll. | ||
166 | * Determine if MoreData bit has to be set. | ||
167 | */ | ||
168 | spin_lock_bh(&conn->psq_lock); | ||
169 | if (!skb_queue_empty(&conn->psq)) | ||
170 | *more_data = true; | ||
171 | spin_unlock_bh(&conn->psq_lock); | ||
172 | } | ||
173 | } | 273 | } |
174 | } | 274 | } |
175 | |||
176 | return ps_queued; | 275 | return ps_queued; |
177 | } | 276 | } |
178 | 277 | ||
@@ -242,8 +341,13 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) | |||
242 | u32 map_no = 0; | 341 | u32 map_no = 0; |
243 | u16 htc_tag = ATH6KL_DATA_PKT_TAG; | 342 | u16 htc_tag = ATH6KL_DATA_PKT_TAG; |
244 | u8 ac = 99 ; /* initialize to unmapped ac */ | 343 | u8 ac = 99 ; /* initialize to unmapped ac */ |
245 | bool chk_adhoc_ps_mapping = false, more_data = false; | 344 | bool chk_adhoc_ps_mapping = false; |
246 | int ret; | 345 | int ret; |
346 | struct wmi_tx_meta_v2 meta_v2; | ||
347 | void *meta; | ||
348 | u8 csum_start = 0, csum_dest = 0, csum = skb->ip_summed; | ||
349 | u8 meta_ver = 0; | ||
350 | u32 flags = 0; | ||
247 | 351 | ||
248 | ath6kl_dbg(ATH6KL_DBG_WLAN_TX, | 352 | ath6kl_dbg(ATH6KL_DBG_WLAN_TX, |
249 | "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__, | 353 | "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__, |
@@ -260,11 +364,19 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) | |||
260 | 364 | ||
261 | /* AP mode Power saving processing */ | 365 | /* AP mode Power saving processing */ |
262 | if (vif->nw_type == AP_NETWORK) { | 366 | if (vif->nw_type == AP_NETWORK) { |
263 | if (ath6kl_powersave_ap(vif, skb, &more_data)) | 367 | if (ath6kl_powersave_ap(vif, skb, &flags)) |
264 | return 0; | 368 | return 0; |
265 | } | 369 | } |
266 | 370 | ||
267 | if (test_bit(WMI_ENABLED, &ar->flag)) { | 371 | if (test_bit(WMI_ENABLED, &ar->flag)) { |
372 | if ((dev->features & NETIF_F_IP_CSUM) && | ||
373 | (csum == CHECKSUM_PARTIAL)) { | ||
374 | csum_start = skb->csum_start - | ||
375 | (skb_network_header(skb) - skb->head) + | ||
376 | sizeof(struct ath6kl_llc_snap_hdr); | ||
377 | csum_dest = skb->csum_offset + csum_start; | ||
378 | } | ||
379 | |||
268 | if (skb_headroom(skb) < dev->needed_headroom) { | 380 | if (skb_headroom(skb) < dev->needed_headroom) { |
269 | struct sk_buff *tmp_skb = skb; | 381 | struct sk_buff *tmp_skb = skb; |
270 | 382 | ||
@@ -281,10 +393,28 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) | |||
281 | goto fail_tx; | 393 | goto fail_tx; |
282 | } | 394 | } |
283 | 395 | ||
284 | if (ath6kl_wmi_data_hdr_add(ar->wmi, skb, DATA_MSGTYPE, | 396 | if ((dev->features & NETIF_F_IP_CSUM) && |
285 | more_data, 0, 0, NULL, | 397 | (csum == CHECKSUM_PARTIAL)) { |
286 | vif->fw_vif_idx)) { | 398 | meta_v2.csum_start = csum_start; |
287 | ath6kl_err("wmi_data_hdr_add failed\n"); | 399 | meta_v2.csum_dest = csum_dest; |
400 | |||
401 | /* instruct target to calculate checksum */ | ||
402 | meta_v2.csum_flags = WMI_META_V2_FLAG_CSUM_OFFLOAD; | ||
403 | meta_ver = WMI_META_VERSION_2; | ||
404 | meta = &meta_v2; | ||
405 | } else { | ||
406 | meta_ver = 0; | ||
407 | meta = NULL; | ||
408 | } | ||
409 | |||
410 | ret = ath6kl_wmi_data_hdr_add(ar->wmi, skb, | ||
411 | DATA_MSGTYPE, flags, 0, | ||
412 | meta_ver, | ||
413 | meta, vif->fw_vif_idx); | ||
414 | |||
415 | if (ret) { | ||
416 | ath6kl_warn("failed to add wmi data header:%d\n" | ||
417 | , ret); | ||
288 | goto fail_tx; | 418 | goto fail_tx; |
289 | } | 419 | } |
290 | 420 | ||
@@ -449,9 +579,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, | |||
449 | * WMI queue with too many commands the only exception to | 579 | * WMI queue with too many commands the only exception to |
450 | * this is during testing using endpointping. | 580 | * this is during testing using endpointping. |
451 | */ | 581 | */ |
452 | spin_lock_bh(&ar->lock); | ||
453 | set_bit(WMI_CTRL_EP_FULL, &ar->flag); | 582 | set_bit(WMI_CTRL_EP_FULL, &ar->flag); |
454 | spin_unlock_bh(&ar->lock); | ||
455 | ath6kl_err("wmi ctrl ep is full\n"); | 583 | ath6kl_err("wmi ctrl ep is full\n"); |
456 | return action; | 584 | return action; |
457 | } | 585 | } |
@@ -479,9 +607,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, | |||
479 | action != HTC_SEND_FULL_DROP) { | 607 | action != HTC_SEND_FULL_DROP) { |
480 | spin_unlock_bh(&ar->list_lock); | 608 | spin_unlock_bh(&ar->list_lock); |
481 | 609 | ||
482 | spin_lock_bh(&vif->if_lock); | ||
483 | set_bit(NETQ_STOPPED, &vif->flags); | 610 | set_bit(NETQ_STOPPED, &vif->flags); |
484 | spin_unlock_bh(&vif->if_lock); | ||
485 | netif_stop_queue(vif->ndev); | 611 | netif_stop_queue(vif->ndev); |
486 | 612 | ||
487 | return action; | 613 | return action; |
@@ -710,10 +836,12 @@ static struct sk_buff *aggr_get_free_skb(struct aggr_info *p_aggr) | |||
710 | { | 836 | { |
711 | struct sk_buff *skb = NULL; | 837 | struct sk_buff *skb = NULL; |
712 | 838 | ||
713 | if (skb_queue_len(&p_aggr->free_q) < (AGGR_NUM_OF_FREE_NETBUFS >> 2)) | 839 | if (skb_queue_len(&p_aggr->rx_amsdu_freeq) < |
714 | ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS); | 840 | (AGGR_NUM_OF_FREE_NETBUFS >> 2)) |
841 | ath6kl_alloc_netbufs(&p_aggr->rx_amsdu_freeq, | ||
842 | AGGR_NUM_OF_FREE_NETBUFS); | ||
715 | 843 | ||
716 | skb = skb_dequeue(&p_aggr->free_q); | 844 | skb = skb_dequeue(&p_aggr->rx_amsdu_freeq); |
717 | 845 | ||
718 | return skb; | 846 | return skb; |
719 | } | 847 | } |
@@ -881,7 +1009,7 @@ static void aggr_slice_amsdu(struct aggr_info *p_aggr, | |||
881 | dev_kfree_skb(skb); | 1009 | dev_kfree_skb(skb); |
882 | } | 1010 | } |
883 | 1011 | ||
884 | static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, | 1012 | static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, |
885 | u16 seq_no, u8 order) | 1013 | u16 seq_no, u8 order) |
886 | { | 1014 | { |
887 | struct sk_buff *skb; | 1015 | struct sk_buff *skb; |
@@ -890,11 +1018,8 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, | |||
890 | u16 idx, idx_end, seq_end; | 1018 | u16 idx, idx_end, seq_end; |
891 | struct rxtid_stats *stats; | 1019 | struct rxtid_stats *stats; |
892 | 1020 | ||
893 | if (!p_aggr) | 1021 | rxtid = &agg_conn->rx_tid[tid]; |
894 | return; | 1022 | stats = &agg_conn->stat[tid]; |
895 | |||
896 | rxtid = &p_aggr->rx_tid[tid]; | ||
897 | stats = &p_aggr->stat[tid]; | ||
898 | 1023 | ||
899 | idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); | 1024 | idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); |
900 | 1025 | ||
@@ -923,7 +1048,8 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, | |||
923 | 1048 | ||
924 | if (node->skb) { | 1049 | if (node->skb) { |
925 | if (node->is_amsdu) | 1050 | if (node->is_amsdu) |
926 | aggr_slice_amsdu(p_aggr, rxtid, node->skb); | 1051 | aggr_slice_amsdu(agg_conn->aggr_info, rxtid, |
1052 | node->skb); | ||
927 | else | 1053 | else |
928 | skb_queue_tail(&rxtid->q, node->skb); | 1054 | skb_queue_tail(&rxtid->q, node->skb); |
929 | node->skb = NULL; | 1055 | node->skb = NULL; |
@@ -939,10 +1065,10 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, | |||
939 | stats->num_delivered += skb_queue_len(&rxtid->q); | 1065 | stats->num_delivered += skb_queue_len(&rxtid->q); |
940 | 1066 | ||
941 | while ((skb = skb_dequeue(&rxtid->q))) | 1067 | while ((skb = skb_dequeue(&rxtid->q))) |
942 | ath6kl_deliver_frames_to_nw_stack(p_aggr->dev, skb); | 1068 | ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, skb); |
943 | } | 1069 | } |
944 | 1070 | ||
945 | static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | 1071 | static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, |
946 | u16 seq_no, | 1072 | u16 seq_no, |
947 | bool is_amsdu, struct sk_buff *frame) | 1073 | bool is_amsdu, struct sk_buff *frame) |
948 | { | 1074 | { |
@@ -954,18 +1080,18 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
954 | bool is_queued = false; | 1080 | bool is_queued = false; |
955 | u16 extended_end; | 1081 | u16 extended_end; |
956 | 1082 | ||
957 | rxtid = &agg_info->rx_tid[tid]; | 1083 | rxtid = &agg_conn->rx_tid[tid]; |
958 | stats = &agg_info->stat[tid]; | 1084 | stats = &agg_conn->stat[tid]; |
959 | 1085 | ||
960 | stats->num_into_aggr++; | 1086 | stats->num_into_aggr++; |
961 | 1087 | ||
962 | if (!rxtid->aggr) { | 1088 | if (!rxtid->aggr) { |
963 | if (is_amsdu) { | 1089 | if (is_amsdu) { |
964 | aggr_slice_amsdu(agg_info, rxtid, frame); | 1090 | aggr_slice_amsdu(agg_conn->aggr_info, rxtid, frame); |
965 | is_queued = true; | 1091 | is_queued = true; |
966 | stats->num_amsdu++; | 1092 | stats->num_amsdu++; |
967 | while ((skb = skb_dequeue(&rxtid->q))) | 1093 | while ((skb = skb_dequeue(&rxtid->q))) |
968 | ath6kl_deliver_frames_to_nw_stack(agg_info->dev, | 1094 | ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, |
969 | skb); | 1095 | skb); |
970 | } | 1096 | } |
971 | return is_queued; | 1097 | return is_queued; |
@@ -985,7 +1111,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
985 | (cur < end || cur > extended_end)) || | 1111 | (cur < end || cur > extended_end)) || |
986 | ((end > extended_end) && (cur > extended_end) && | 1112 | ((end > extended_end) && (cur > extended_end) && |
987 | (cur < end))) { | 1113 | (cur < end))) { |
988 | aggr_deque_frms(agg_info, tid, 0, 0); | 1114 | aggr_deque_frms(agg_conn, tid, 0, 0); |
989 | if (cur >= rxtid->hold_q_sz - 1) | 1115 | if (cur >= rxtid->hold_q_sz - 1) |
990 | rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); | 1116 | rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); |
991 | else | 1117 | else |
@@ -1002,7 +1128,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
1002 | st = ATH6KL_MAX_SEQ_NO - | 1128 | st = ATH6KL_MAX_SEQ_NO - |
1003 | (rxtid->hold_q_sz - 2 - cur); | 1129 | (rxtid->hold_q_sz - 2 - cur); |
1004 | 1130 | ||
1005 | aggr_deque_frms(agg_info, tid, st, 0); | 1131 | aggr_deque_frms(agg_conn, tid, st, 0); |
1006 | } | 1132 | } |
1007 | 1133 | ||
1008 | stats->num_oow++; | 1134 | stats->num_oow++; |
@@ -1041,9 +1167,9 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
1041 | 1167 | ||
1042 | spin_unlock_bh(&rxtid->lock); | 1168 | spin_unlock_bh(&rxtid->lock); |
1043 | 1169 | ||
1044 | aggr_deque_frms(agg_info, tid, 0, 1); | 1170 | aggr_deque_frms(agg_conn, tid, 0, 1); |
1045 | 1171 | ||
1046 | if (agg_info->timer_scheduled) | 1172 | if (agg_conn->timer_scheduled) |
1047 | rxtid->progress = true; | 1173 | rxtid->progress = true; |
1048 | else | 1174 | else |
1049 | for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { | 1175 | for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { |
@@ -1054,8 +1180,8 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
1054 | * the frame doesn't remain stuck | 1180 | * the frame doesn't remain stuck |
1055 | * forever. | 1181 | * forever. |
1056 | */ | 1182 | */ |
1057 | agg_info->timer_scheduled = true; | 1183 | agg_conn->timer_scheduled = true; |
1058 | mod_timer(&agg_info->timer, | 1184 | mod_timer(&agg_conn->timer, |
1059 | (jiffies + | 1185 | (jiffies + |
1060 | HZ * (AGGR_RX_TIMEOUT) / 1000)); | 1186 | HZ * (AGGR_RX_TIMEOUT) / 1000)); |
1061 | rxtid->progress = false; | 1187 | rxtid->progress = false; |
@@ -1067,6 +1193,76 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, | |||
1067 | return is_queued; | 1193 | return is_queued; |
1068 | } | 1194 | } |
1069 | 1195 | ||
1196 | static void ath6kl_uapsd_trigger_frame_rx(struct ath6kl_vif *vif, | ||
1197 | struct ath6kl_sta *conn) | ||
1198 | { | ||
1199 | struct ath6kl *ar = vif->ar; | ||
1200 | bool is_apsdq_empty, is_apsdq_empty_at_start; | ||
1201 | u32 num_frames_to_deliver, flags; | ||
1202 | struct sk_buff *skb = NULL; | ||
1203 | |||
1204 | /* | ||
1205 | * If the APSD q for this STA is not empty, dequeue and | ||
1206 | * send a pkt from the head of the q. Also update the | ||
1207 | * More data bit in the WMI_DATA_HDR if there are | ||
1208 | * more pkts for this STA in the APSD q. | ||
1209 | * If there are no more pkts for this STA, | ||
1210 | * update the APSD bitmap for this STA. | ||
1211 | */ | ||
1212 | |||
1213 | num_frames_to_deliver = (conn->apsd_info >> ATH6KL_APSD_NUM_OF_AC) & | ||
1214 | ATH6KL_APSD_FRAME_MASK; | ||
1215 | /* | ||
1216 | * Number of frames to send in a service period is | ||
1217 | * indicated by the station | ||
1218 | * in the QOS_INFO of the association request | ||
1219 | * If it is zero, send all frames | ||
1220 | */ | ||
1221 | if (!num_frames_to_deliver) | ||
1222 | num_frames_to_deliver = ATH6KL_APSD_ALL_FRAME; | ||
1223 | |||
1224 | spin_lock_bh(&conn->psq_lock); | ||
1225 | is_apsdq_empty = skb_queue_empty(&conn->apsdq); | ||
1226 | spin_unlock_bh(&conn->psq_lock); | ||
1227 | is_apsdq_empty_at_start = is_apsdq_empty; | ||
1228 | |||
1229 | while ((!is_apsdq_empty) && (num_frames_to_deliver)) { | ||
1230 | |||
1231 | spin_lock_bh(&conn->psq_lock); | ||
1232 | skb = skb_dequeue(&conn->apsdq); | ||
1233 | is_apsdq_empty = skb_queue_empty(&conn->apsdq); | ||
1234 | spin_unlock_bh(&conn->psq_lock); | ||
1235 | |||
1236 | /* | ||
1237 | * Set the STA flag to Trigger delivery, | ||
1238 | * so that the frame will go out | ||
1239 | */ | ||
1240 | conn->sta_flags |= STA_PS_APSD_TRIGGER; | ||
1241 | num_frames_to_deliver--; | ||
1242 | |||
1243 | /* Last frame in the service period, set EOSP or queue empty */ | ||
1244 | if ((is_apsdq_empty) || (!num_frames_to_deliver)) | ||
1245 | conn->sta_flags |= STA_PS_APSD_EOSP; | ||
1246 | |||
1247 | ath6kl_data_tx(skb, vif->ndev); | ||
1248 | conn->sta_flags &= ~(STA_PS_APSD_TRIGGER); | ||
1249 | conn->sta_flags &= ~(STA_PS_APSD_EOSP); | ||
1250 | } | ||
1251 | |||
1252 | if (is_apsdq_empty) { | ||
1253 | if (is_apsdq_empty_at_start) | ||
1254 | flags = WMI_AP_APSD_NO_DELIVERY_FRAMES; | ||
1255 | else | ||
1256 | flags = 0; | ||
1257 | |||
1258 | ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, | ||
1259 | vif->fw_vif_idx, | ||
1260 | conn->aid, 0, flags); | ||
1261 | } | ||
1262 | |||
1263 | return; | ||
1264 | } | ||
1265 | |||
1070 | void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | 1266 | void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) |
1071 | { | 1267 | { |
1072 | struct ath6kl *ar = target->dev->ar; | 1268 | struct ath6kl *ar = target->dev->ar; |
@@ -1078,10 +1274,12 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1078 | int status = packet->status; | 1274 | int status = packet->status; |
1079 | enum htc_endpoint_id ept = packet->endpoint; | 1275 | enum htc_endpoint_id ept = packet->endpoint; |
1080 | bool is_amsdu, prev_ps, ps_state = false; | 1276 | bool is_amsdu, prev_ps, ps_state = false; |
1277 | bool trig_state = false; | ||
1081 | struct ath6kl_sta *conn = NULL; | 1278 | struct ath6kl_sta *conn = NULL; |
1082 | struct sk_buff *skb1 = NULL; | 1279 | struct sk_buff *skb1 = NULL; |
1083 | struct ethhdr *datap = NULL; | 1280 | struct ethhdr *datap = NULL; |
1084 | struct ath6kl_vif *vif; | 1281 | struct ath6kl_vif *vif; |
1282 | struct aggr_info_conn *aggr_conn; | ||
1085 | u16 seq_no, offset; | 1283 | u16 seq_no, offset; |
1086 | u8 tid, if_idx; | 1284 | u8 tid, if_idx; |
1087 | 1285 | ||
@@ -1171,6 +1369,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1171 | WMI_DATA_HDR_PS_MASK); | 1369 | WMI_DATA_HDR_PS_MASK); |
1172 | 1370 | ||
1173 | offset = sizeof(struct wmi_data_hdr); | 1371 | offset = sizeof(struct wmi_data_hdr); |
1372 | trig_state = !!(le16_to_cpu(dhdr->info3) & WMI_DATA_HDR_TRIG); | ||
1174 | 1373 | ||
1175 | switch (meta_type) { | 1374 | switch (meta_type) { |
1176 | case 0: | 1375 | case 0: |
@@ -1209,18 +1408,36 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1209 | else | 1408 | else |
1210 | conn->sta_flags &= ~STA_PS_SLEEP; | 1409 | conn->sta_flags &= ~STA_PS_SLEEP; |
1211 | 1410 | ||
1411 | /* Accept trigger only when the station is in sleep */ | ||
1412 | if ((conn->sta_flags & STA_PS_SLEEP) && trig_state) | ||
1413 | ath6kl_uapsd_trigger_frame_rx(vif, conn); | ||
1414 | |||
1212 | if (prev_ps ^ !!(conn->sta_flags & STA_PS_SLEEP)) { | 1415 | if (prev_ps ^ !!(conn->sta_flags & STA_PS_SLEEP)) { |
1213 | if (!(conn->sta_flags & STA_PS_SLEEP)) { | 1416 | if (!(conn->sta_flags & STA_PS_SLEEP)) { |
1214 | struct sk_buff *skbuff = NULL; | 1417 | struct sk_buff *skbuff = NULL; |
1418 | bool is_apsdq_empty; | ||
1215 | 1419 | ||
1216 | spin_lock_bh(&conn->psq_lock); | 1420 | spin_lock_bh(&conn->psq_lock); |
1217 | while ((skbuff = skb_dequeue(&conn->psq)) | 1421 | while ((skbuff = skb_dequeue(&conn->psq))) { |
1218 | != NULL) { | 1422 | spin_unlock_bh(&conn->psq_lock); |
1423 | ath6kl_data_tx(skbuff, vif->ndev); | ||
1424 | spin_lock_bh(&conn->psq_lock); | ||
1425 | } | ||
1426 | |||
1427 | is_apsdq_empty = skb_queue_empty(&conn->apsdq); | ||
1428 | while ((skbuff = skb_dequeue(&conn->apsdq))) { | ||
1219 | spin_unlock_bh(&conn->psq_lock); | 1429 | spin_unlock_bh(&conn->psq_lock); |
1220 | ath6kl_data_tx(skbuff, vif->ndev); | 1430 | ath6kl_data_tx(skbuff, vif->ndev); |
1221 | spin_lock_bh(&conn->psq_lock); | 1431 | spin_lock_bh(&conn->psq_lock); |
1222 | } | 1432 | } |
1223 | spin_unlock_bh(&conn->psq_lock); | 1433 | spin_unlock_bh(&conn->psq_lock); |
1434 | |||
1435 | if (!is_apsdq_empty) | ||
1436 | ath6kl_wmi_set_apsd_bfrd_traf( | ||
1437 | ar->wmi, | ||
1438 | vif->fw_vif_idx, | ||
1439 | conn->aid, 0, 0); | ||
1440 | |||
1224 | /* Clear the PVB for this STA */ | 1441 | /* Clear the PVB for this STA */ |
1225 | ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx, | 1442 | ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx, |
1226 | conn->aid, 0); | 1443 | conn->aid, 0); |
@@ -1314,11 +1531,21 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1314 | 1531 | ||
1315 | datap = (struct ethhdr *) skb->data; | 1532 | datap = (struct ethhdr *) skb->data; |
1316 | 1533 | ||
1317 | if (is_unicast_ether_addr(datap->h_dest) && | 1534 | if (is_unicast_ether_addr(datap->h_dest)) { |
1318 | aggr_process_recv_frm(vif->aggr_cntxt, tid, seq_no, | 1535 | if (vif->nw_type == AP_NETWORK) { |
1319 | is_amsdu, skb)) | 1536 | conn = ath6kl_find_sta(vif, datap->h_source); |
1320 | /* aggregation code will handle the skb */ | 1537 | if (!conn) |
1321 | return; | 1538 | return; |
1539 | aggr_conn = conn->aggr_conn; | ||
1540 | } else | ||
1541 | aggr_conn = vif->aggr_cntxt->aggr_conn; | ||
1542 | |||
1543 | if (aggr_process_recv_frm(aggr_conn, tid, seq_no, | ||
1544 | is_amsdu, skb)) { | ||
1545 | /* aggregation code will handle the skb */ | ||
1546 | return; | ||
1547 | } | ||
1548 | } | ||
1322 | 1549 | ||
1323 | ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb); | 1550 | ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb); |
1324 | } | 1551 | } |
@@ -1326,13 +1553,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) | |||
1326 | static void aggr_timeout(unsigned long arg) | 1553 | static void aggr_timeout(unsigned long arg) |
1327 | { | 1554 | { |
1328 | u8 i, j; | 1555 | u8 i, j; |
1329 | struct aggr_info *p_aggr = (struct aggr_info *) arg; | 1556 | struct aggr_info_conn *aggr_conn = (struct aggr_info_conn *) arg; |
1330 | struct rxtid *rxtid; | 1557 | struct rxtid *rxtid; |
1331 | struct rxtid_stats *stats; | 1558 | struct rxtid_stats *stats; |
1332 | 1559 | ||
1333 | for (i = 0; i < NUM_OF_TIDS; i++) { | 1560 | for (i = 0; i < NUM_OF_TIDS; i++) { |
1334 | rxtid = &p_aggr->rx_tid[i]; | 1561 | rxtid = &aggr_conn->rx_tid[i]; |
1335 | stats = &p_aggr->stat[i]; | 1562 | stats = &aggr_conn->stat[i]; |
1336 | 1563 | ||
1337 | if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) | 1564 | if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) |
1338 | continue; | 1565 | continue; |
@@ -1343,18 +1570,18 @@ static void aggr_timeout(unsigned long arg) | |||
1343 | rxtid->seq_next, | 1570 | rxtid->seq_next, |
1344 | ((rxtid->seq_next + rxtid->hold_q_sz-1) & | 1571 | ((rxtid->seq_next + rxtid->hold_q_sz-1) & |
1345 | ATH6KL_MAX_SEQ_NO)); | 1572 | ATH6KL_MAX_SEQ_NO)); |
1346 | aggr_deque_frms(p_aggr, i, 0, 0); | 1573 | aggr_deque_frms(aggr_conn, i, 0, 0); |
1347 | } | 1574 | } |
1348 | 1575 | ||
1349 | p_aggr->timer_scheduled = false; | 1576 | aggr_conn->timer_scheduled = false; |
1350 | 1577 | ||
1351 | for (i = 0; i < NUM_OF_TIDS; i++) { | 1578 | for (i = 0; i < NUM_OF_TIDS; i++) { |
1352 | rxtid = &p_aggr->rx_tid[i]; | 1579 | rxtid = &aggr_conn->rx_tid[i]; |
1353 | 1580 | ||
1354 | if (rxtid->aggr && rxtid->hold_q) { | 1581 | if (rxtid->aggr && rxtid->hold_q) { |
1355 | for (j = 0; j < rxtid->hold_q_sz; j++) { | 1582 | for (j = 0; j < rxtid->hold_q_sz; j++) { |
1356 | if (rxtid->hold_q[j].skb) { | 1583 | if (rxtid->hold_q[j].skb) { |
1357 | p_aggr->timer_scheduled = true; | 1584 | aggr_conn->timer_scheduled = true; |
1358 | rxtid->timer_mon = true; | 1585 | rxtid->timer_mon = true; |
1359 | rxtid->progress = false; | 1586 | rxtid->progress = false; |
1360 | break; | 1587 | break; |
@@ -1366,24 +1593,24 @@ static void aggr_timeout(unsigned long arg) | |||
1366 | } | 1593 | } |
1367 | } | 1594 | } |
1368 | 1595 | ||
1369 | if (p_aggr->timer_scheduled) | 1596 | if (aggr_conn->timer_scheduled) |
1370 | mod_timer(&p_aggr->timer, | 1597 | mod_timer(&aggr_conn->timer, |
1371 | jiffies + msecs_to_jiffies(AGGR_RX_TIMEOUT)); | 1598 | jiffies + msecs_to_jiffies(AGGR_RX_TIMEOUT)); |
1372 | } | 1599 | } |
1373 | 1600 | ||
1374 | static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid) | 1601 | static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) |
1375 | { | 1602 | { |
1376 | struct rxtid *rxtid; | 1603 | struct rxtid *rxtid; |
1377 | struct rxtid_stats *stats; | 1604 | struct rxtid_stats *stats; |
1378 | 1605 | ||
1379 | if (!p_aggr || tid >= NUM_OF_TIDS) | 1606 | if (!aggr_conn || tid >= NUM_OF_TIDS) |
1380 | return; | 1607 | return; |
1381 | 1608 | ||
1382 | rxtid = &p_aggr->rx_tid[tid]; | 1609 | rxtid = &aggr_conn->rx_tid[tid]; |
1383 | stats = &p_aggr->stat[tid]; | 1610 | stats = &aggr_conn->stat[tid]; |
1384 | 1611 | ||
1385 | if (rxtid->aggr) | 1612 | if (rxtid->aggr) |
1386 | aggr_deque_frms(p_aggr, tid, 0, 0); | 1613 | aggr_deque_frms(aggr_conn, tid, 0, 0); |
1387 | 1614 | ||
1388 | rxtid->aggr = false; | 1615 | rxtid->aggr = false; |
1389 | rxtid->progress = false; | 1616 | rxtid->progress = false; |
@@ -1398,26 +1625,40 @@ static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid) | |||
1398 | memset(stats, 0, sizeof(struct rxtid_stats)); | 1625 | memset(stats, 0, sizeof(struct rxtid_stats)); |
1399 | } | 1626 | } |
1400 | 1627 | ||
1401 | void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, | 1628 | void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no, |
1402 | u8 win_sz) | 1629 | u8 win_sz) |
1403 | { | 1630 | { |
1404 | struct aggr_info *p_aggr = vif->aggr_cntxt; | 1631 | struct ath6kl_sta *sta; |
1632 | struct aggr_info_conn *aggr_conn = NULL; | ||
1405 | struct rxtid *rxtid; | 1633 | struct rxtid *rxtid; |
1406 | struct rxtid_stats *stats; | 1634 | struct rxtid_stats *stats; |
1407 | u16 hold_q_size; | 1635 | u16 hold_q_size; |
1636 | u8 tid, aid; | ||
1408 | 1637 | ||
1409 | if (!p_aggr) | 1638 | if (vif->nw_type == AP_NETWORK) { |
1639 | aid = ath6kl_get_aid(tid_mux); | ||
1640 | sta = ath6kl_find_sta_by_aid(vif->ar, aid); | ||
1641 | if (sta) | ||
1642 | aggr_conn = sta->aggr_conn; | ||
1643 | } else | ||
1644 | aggr_conn = vif->aggr_cntxt->aggr_conn; | ||
1645 | |||
1646 | if (!aggr_conn) | ||
1647 | return; | ||
1648 | |||
1649 | tid = ath6kl_get_tid(tid_mux); | ||
1650 | if (tid >= NUM_OF_TIDS) | ||
1410 | return; | 1651 | return; |
1411 | 1652 | ||
1412 | rxtid = &p_aggr->rx_tid[tid]; | 1653 | rxtid = &aggr_conn->rx_tid[tid]; |
1413 | stats = &p_aggr->stat[tid]; | 1654 | stats = &aggr_conn->stat[tid]; |
1414 | 1655 | ||
1415 | if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) | 1656 | if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) |
1416 | ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n", | 1657 | ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n", |
1417 | __func__, win_sz, tid); | 1658 | __func__, win_sz, tid); |
1418 | 1659 | ||
1419 | if (rxtid->aggr) | 1660 | if (rxtid->aggr) |
1420 | aggr_delete_tid_state(p_aggr, tid); | 1661 | aggr_delete_tid_state(aggr_conn, tid); |
1421 | 1662 | ||
1422 | rxtid->seq_next = seq_no; | 1663 | rxtid->seq_next = seq_no; |
1423 | hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q); | 1664 | hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q); |
@@ -1433,31 +1674,23 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, | |||
1433 | rxtid->aggr = true; | 1674 | rxtid->aggr = true; |
1434 | } | 1675 | } |
1435 | 1676 | ||
1436 | struct aggr_info *aggr_init(struct net_device *dev) | 1677 | void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info, |
1678 | struct aggr_info_conn *aggr_conn) | ||
1437 | { | 1679 | { |
1438 | struct aggr_info *p_aggr = NULL; | ||
1439 | struct rxtid *rxtid; | 1680 | struct rxtid *rxtid; |
1440 | u8 i; | 1681 | u8 i; |
1441 | 1682 | ||
1442 | p_aggr = kzalloc(sizeof(struct aggr_info), GFP_KERNEL); | 1683 | aggr_conn->aggr_sz = AGGR_SZ_DEFAULT; |
1443 | if (!p_aggr) { | 1684 | aggr_conn->dev = vif->ndev; |
1444 | ath6kl_err("failed to alloc memory for aggr_node\n"); | 1685 | init_timer(&aggr_conn->timer); |
1445 | return NULL; | 1686 | aggr_conn->timer.function = aggr_timeout; |
1446 | } | 1687 | aggr_conn->timer.data = (unsigned long) aggr_conn; |
1447 | 1688 | aggr_conn->aggr_info = aggr_info; | |
1448 | p_aggr->aggr_sz = AGGR_SZ_DEFAULT; | ||
1449 | p_aggr->dev = dev; | ||
1450 | init_timer(&p_aggr->timer); | ||
1451 | p_aggr->timer.function = aggr_timeout; | ||
1452 | p_aggr->timer.data = (unsigned long) p_aggr; | ||
1453 | 1689 | ||
1454 | p_aggr->timer_scheduled = false; | 1690 | aggr_conn->timer_scheduled = false; |
1455 | skb_queue_head_init(&p_aggr->free_q); | ||
1456 | |||
1457 | ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS); | ||
1458 | 1691 | ||
1459 | for (i = 0; i < NUM_OF_TIDS; i++) { | 1692 | for (i = 0; i < NUM_OF_TIDS; i++) { |
1460 | rxtid = &p_aggr->rx_tid[i]; | 1693 | rxtid = &aggr_conn->rx_tid[i]; |
1461 | rxtid->aggr = false; | 1694 | rxtid->aggr = false; |
1462 | rxtid->progress = false; | 1695 | rxtid->progress = false; |
1463 | rxtid->timer_mon = false; | 1696 | rxtid->timer_mon = false; |
@@ -1465,29 +1698,75 @@ struct aggr_info *aggr_init(struct net_device *dev) | |||
1465 | spin_lock_init(&rxtid->lock); | 1698 | spin_lock_init(&rxtid->lock); |
1466 | } | 1699 | } |
1467 | 1700 | ||
1701 | } | ||
1702 | |||
1703 | struct aggr_info *aggr_init(struct ath6kl_vif *vif) | ||
1704 | { | ||
1705 | struct aggr_info *p_aggr = NULL; | ||
1706 | |||
1707 | p_aggr = kzalloc(sizeof(struct aggr_info), GFP_KERNEL); | ||
1708 | if (!p_aggr) { | ||
1709 | ath6kl_err("failed to alloc memory for aggr_node\n"); | ||
1710 | return NULL; | ||
1711 | } | ||
1712 | |||
1713 | p_aggr->aggr_conn = kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL); | ||
1714 | if (!p_aggr->aggr_conn) { | ||
1715 | ath6kl_err("failed to alloc memory for connection specific aggr info\n"); | ||
1716 | kfree(p_aggr); | ||
1717 | return NULL; | ||
1718 | } | ||
1719 | |||
1720 | aggr_conn_init(vif, p_aggr, p_aggr->aggr_conn); | ||
1721 | |||
1722 | skb_queue_head_init(&p_aggr->rx_amsdu_freeq); | ||
1723 | ath6kl_alloc_netbufs(&p_aggr->rx_amsdu_freeq, AGGR_NUM_OF_FREE_NETBUFS); | ||
1724 | |||
1468 | return p_aggr; | 1725 | return p_aggr; |
1469 | } | 1726 | } |
1470 | 1727 | ||
1471 | void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid) | 1728 | void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid_mux) |
1472 | { | 1729 | { |
1473 | struct aggr_info *p_aggr = vif->aggr_cntxt; | 1730 | struct ath6kl_sta *sta; |
1474 | struct rxtid *rxtid; | 1731 | struct rxtid *rxtid; |
1732 | struct aggr_info_conn *aggr_conn = NULL; | ||
1733 | u8 tid, aid; | ||
1734 | |||
1735 | if (vif->nw_type == AP_NETWORK) { | ||
1736 | aid = ath6kl_get_aid(tid_mux); | ||
1737 | sta = ath6kl_find_sta_by_aid(vif->ar, aid); | ||
1738 | if (sta) | ||
1739 | aggr_conn = sta->aggr_conn; | ||
1740 | } else | ||
1741 | aggr_conn = vif->aggr_cntxt->aggr_conn; | ||
1742 | |||
1743 | if (!aggr_conn) | ||
1744 | return; | ||
1475 | 1745 | ||
1476 | if (!p_aggr) | 1746 | tid = ath6kl_get_tid(tid_mux); |
1747 | if (tid >= NUM_OF_TIDS) | ||
1477 | return; | 1748 | return; |
1478 | 1749 | ||
1479 | rxtid = &p_aggr->rx_tid[tid]; | 1750 | rxtid = &aggr_conn->rx_tid[tid]; |
1480 | 1751 | ||
1481 | if (rxtid->aggr) | 1752 | if (rxtid->aggr) |
1482 | aggr_delete_tid_state(p_aggr, tid); | 1753 | aggr_delete_tid_state(aggr_conn, tid); |
1483 | } | 1754 | } |
1484 | 1755 | ||
1485 | void aggr_reset_state(struct aggr_info *aggr_info) | 1756 | void aggr_reset_state(struct aggr_info_conn *aggr_conn) |
1486 | { | 1757 | { |
1487 | u8 tid; | 1758 | u8 tid; |
1488 | 1759 | ||
1760 | if (!aggr_conn) | ||
1761 | return; | ||
1762 | |||
1763 | if (aggr_conn->timer_scheduled) { | ||
1764 | del_timer(&aggr_conn->timer); | ||
1765 | aggr_conn->timer_scheduled = false; | ||
1766 | } | ||
1767 | |||
1489 | for (tid = 0; tid < NUM_OF_TIDS; tid++) | 1768 | for (tid = 0; tid < NUM_OF_TIDS; tid++) |
1490 | aggr_delete_tid_state(aggr_info, tid); | 1769 | aggr_delete_tid_state(aggr_conn, tid); |
1491 | } | 1770 | } |
1492 | 1771 | ||
1493 | /* clean up our amsdu buffer list */ | 1772 | /* clean up our amsdu buffer list */ |
@@ -1514,28 +1793,11 @@ void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar) | |||
1514 | 1793 | ||
1515 | void aggr_module_destroy(struct aggr_info *aggr_info) | 1794 | void aggr_module_destroy(struct aggr_info *aggr_info) |
1516 | { | 1795 | { |
1517 | struct rxtid *rxtid; | ||
1518 | u8 i, k; | ||
1519 | |||
1520 | if (!aggr_info) | 1796 | if (!aggr_info) |
1521 | return; | 1797 | return; |
1522 | 1798 | ||
1523 | if (aggr_info->timer_scheduled) { | 1799 | aggr_reset_state(aggr_info->aggr_conn); |
1524 | del_timer(&aggr_info->timer); | 1800 | skb_queue_purge(&aggr_info->rx_amsdu_freeq); |
1525 | aggr_info->timer_scheduled = false; | 1801 | kfree(aggr_info->aggr_conn); |
1526 | } | ||
1527 | |||
1528 | for (i = 0; i < NUM_OF_TIDS; i++) { | ||
1529 | rxtid = &aggr_info->rx_tid[i]; | ||
1530 | if (rxtid->hold_q) { | ||
1531 | for (k = 0; k < rxtid->hold_q_sz; k++) | ||
1532 | dev_kfree_skb(rxtid->hold_q[k].skb); | ||
1533 | kfree(rxtid->hold_q); | ||
1534 | } | ||
1535 | |||
1536 | skb_queue_purge(&rxtid->q); | ||
1537 | } | ||
1538 | |||
1539 | skb_queue_purge(&aggr_info->free_q); | ||
1540 | kfree(aggr_info); | 1802 | kfree(aggr_info); |
1541 | } | 1803 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c new file mode 100644 index 000000000000..c72567c6d338 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/usb.c | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007-2011 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/module.h> | ||
18 | #include <linux/usb.h> | ||
19 | |||
20 | #include "debug.h" | ||
21 | #include "core.h" | ||
22 | |||
23 | /* usb device object */ | ||
24 | struct ath6kl_usb { | ||
25 | struct usb_device *udev; | ||
26 | struct usb_interface *interface; | ||
27 | u8 *diag_cmd_buffer; | ||
28 | u8 *diag_resp_buffer; | ||
29 | struct ath6kl *ar; | ||
30 | }; | ||
31 | |||
32 | /* diagnostic command defnitions */ | ||
33 | #define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1 | ||
34 | #define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2 | ||
35 | #define ATH6KL_USB_CONTROL_REQ_DIAG_CMD 3 | ||
36 | #define ATH6KL_USB_CONTROL_REQ_DIAG_RESP 4 | ||
37 | |||
38 | #define ATH6KL_USB_CTRL_DIAG_CC_READ 0 | ||
39 | #define ATH6KL_USB_CTRL_DIAG_CC_WRITE 1 | ||
40 | |||
41 | struct ath6kl_usb_ctrl_diag_cmd_write { | ||
42 | __le32 cmd; | ||
43 | __le32 address; | ||
44 | __le32 value; | ||
45 | __le32 _pad[1]; | ||
46 | } __packed; | ||
47 | |||
48 | struct ath6kl_usb_ctrl_diag_cmd_read { | ||
49 | __le32 cmd; | ||
50 | __le32 address; | ||
51 | } __packed; | ||
52 | |||
53 | struct ath6kl_usb_ctrl_diag_resp_read { | ||
54 | __le32 value; | ||
55 | } __packed; | ||
56 | |||
57 | #define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)) | ||
58 | #define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read)) | ||
59 | |||
60 | static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb) | ||
61 | { | ||
62 | usb_set_intfdata(ar_usb->interface, NULL); | ||
63 | |||
64 | kfree(ar_usb->diag_cmd_buffer); | ||
65 | kfree(ar_usb->diag_resp_buffer); | ||
66 | |||
67 | kfree(ar_usb); | ||
68 | } | ||
69 | |||
70 | static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface) | ||
71 | { | ||
72 | struct ath6kl_usb *ar_usb = NULL; | ||
73 | struct usb_device *dev = interface_to_usbdev(interface); | ||
74 | int status = 0; | ||
75 | |||
76 | ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL); | ||
77 | if (ar_usb == NULL) | ||
78 | goto fail_ath6kl_usb_create; | ||
79 | |||
80 | memset(ar_usb, 0, sizeof(struct ath6kl_usb)); | ||
81 | usb_set_intfdata(interface, ar_usb); | ||
82 | ar_usb->udev = dev; | ||
83 | ar_usb->interface = interface; | ||
84 | |||
85 | ar_usb->diag_cmd_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_CMD, GFP_KERNEL); | ||
86 | if (ar_usb->diag_cmd_buffer == NULL) { | ||
87 | status = -ENOMEM; | ||
88 | goto fail_ath6kl_usb_create; | ||
89 | } | ||
90 | |||
91 | ar_usb->diag_resp_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_RESP, | ||
92 | GFP_KERNEL); | ||
93 | if (ar_usb->diag_resp_buffer == NULL) { | ||
94 | status = -ENOMEM; | ||
95 | goto fail_ath6kl_usb_create; | ||
96 | } | ||
97 | |||
98 | fail_ath6kl_usb_create: | ||
99 | if (status != 0) { | ||
100 | ath6kl_usb_destroy(ar_usb); | ||
101 | ar_usb = NULL; | ||
102 | } | ||
103 | return ar_usb; | ||
104 | } | ||
105 | |||
106 | static void ath6kl_usb_device_detached(struct usb_interface *interface) | ||
107 | { | ||
108 | struct ath6kl_usb *ar_usb; | ||
109 | |||
110 | ar_usb = usb_get_intfdata(interface); | ||
111 | if (ar_usb == NULL) | ||
112 | return; | ||
113 | |||
114 | ath6kl_stop_txrx(ar_usb->ar); | ||
115 | |||
116 | ath6kl_core_cleanup(ar_usb->ar); | ||
117 | |||
118 | ath6kl_usb_destroy(ar_usb); | ||
119 | } | ||
120 | |||
121 | static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, | ||
122 | u8 req, u16 value, u16 index, void *data, | ||
123 | u32 size) | ||
124 | { | ||
125 | u8 *buf = NULL; | ||
126 | int ret; | ||
127 | |||
128 | if (size > 0) { | ||
129 | buf = kmalloc(size, GFP_KERNEL); | ||
130 | if (buf == NULL) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | memcpy(buf, data, size); | ||
134 | } | ||
135 | |||
136 | /* note: if successful returns number of bytes transfered */ | ||
137 | ret = usb_control_msg(ar_usb->udev, | ||
138 | usb_sndctrlpipe(ar_usb->udev, 0), | ||
139 | req, | ||
140 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
141 | USB_RECIP_DEVICE, value, index, buf, | ||
142 | size, 1000); | ||
143 | |||
144 | if (ret < 0) { | ||
145 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | ||
146 | __func__, ret); | ||
147 | } | ||
148 | |||
149 | kfree(buf); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, | ||
155 | u8 req, u16 value, u16 index, void *data, | ||
156 | u32 size) | ||
157 | { | ||
158 | u8 *buf = NULL; | ||
159 | int ret; | ||
160 | |||
161 | if (size > 0) { | ||
162 | buf = kmalloc(size, GFP_KERNEL); | ||
163 | if (buf == NULL) | ||
164 | return -ENOMEM; | ||
165 | } | ||
166 | |||
167 | /* note: if successful returns number of bytes transfered */ | ||
168 | ret = usb_control_msg(ar_usb->udev, | ||
169 | usb_rcvctrlpipe(ar_usb->udev, 0), | ||
170 | req, | ||
171 | USB_DIR_IN | USB_TYPE_VENDOR | | ||
172 | USB_RECIP_DEVICE, value, index, buf, | ||
173 | size, 2 * HZ); | ||
174 | |||
175 | if (ret < 0) { | ||
176 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | ||
177 | __func__, ret); | ||
178 | } | ||
179 | |||
180 | memcpy((u8 *) data, buf, size); | ||
181 | |||
182 | kfree(buf); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int ath6kl_usb_ctrl_msg_exchange(struct ath6kl_usb *ar_usb, | ||
188 | u8 req_val, u8 *req_buf, u32 req_len, | ||
189 | u8 resp_val, u8 *resp_buf, u32 *resp_len) | ||
190 | { | ||
191 | int ret; | ||
192 | |||
193 | /* send command */ | ||
194 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, req_val, 0, 0, | ||
195 | req_buf, req_len); | ||
196 | |||
197 | if (ret != 0) | ||
198 | return ret; | ||
199 | |||
200 | if (resp_buf == NULL) { | ||
201 | /* no expected response */ | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | /* get response */ | ||
206 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, resp_val, 0, 0, | ||
207 | resp_buf, *resp_len); | ||
208 | |||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data) | ||
213 | { | ||
214 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
215 | struct ath6kl_usb_ctrl_diag_resp_read *resp; | ||
216 | struct ath6kl_usb_ctrl_diag_cmd_read *cmd; | ||
217 | u32 resp_len; | ||
218 | int ret; | ||
219 | |||
220 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_read *) ar_usb->diag_cmd_buffer; | ||
221 | |||
222 | memset(cmd, 0, sizeof(*cmd)); | ||
223 | cmd->cmd = ATH6KL_USB_CTRL_DIAG_CC_READ; | ||
224 | cmd->address = cpu_to_le32(address); | ||
225 | resp_len = sizeof(*resp); | ||
226 | |||
227 | ret = ath6kl_usb_ctrl_msg_exchange(ar_usb, | ||
228 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, | ||
229 | (u8 *) cmd, | ||
230 | sizeof(struct ath6kl_usb_ctrl_diag_cmd_write), | ||
231 | ATH6KL_USB_CONTROL_REQ_DIAG_RESP, | ||
232 | ar_usb->diag_resp_buffer, &resp_len); | ||
233 | |||
234 | if (ret) | ||
235 | return ret; | ||
236 | |||
237 | resp = (struct ath6kl_usb_ctrl_diag_resp_read *) | ||
238 | ar_usb->diag_resp_buffer; | ||
239 | |||
240 | *data = le32_to_cpu(resp->value); | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) | ||
246 | { | ||
247 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
248 | struct ath6kl_usb_ctrl_diag_cmd_write *cmd; | ||
249 | |||
250 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; | ||
251 | |||
252 | memset(cmd, 0, sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)); | ||
253 | cmd->cmd = cpu_to_le32(ATH6KL_USB_CTRL_DIAG_CC_WRITE); | ||
254 | cmd->address = cpu_to_le32(address); | ||
255 | cmd->value = data; | ||
256 | |||
257 | return ath6kl_usb_ctrl_msg_exchange(ar_usb, | ||
258 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, | ||
259 | (u8 *) cmd, | ||
260 | sizeof(*cmd), | ||
261 | 0, NULL, NULL); | ||
262 | |||
263 | } | ||
264 | |||
265 | static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | ||
266 | { | ||
267 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
268 | int ret; | ||
269 | |||
270 | /* get response */ | ||
271 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, | ||
272 | ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, | ||
273 | 0, 0, buf, len); | ||
274 | if (ret != 0) { | ||
275 | ath6kl_err("Unable to read the bmi data from the device: %d\n", | ||
276 | ret); | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | ||
284 | { | ||
285 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
286 | int ret; | ||
287 | |||
288 | /* send command */ | ||
289 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, | ||
290 | ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, | ||
291 | 0, 0, buf, len); | ||
292 | if (ret != 0) { | ||
293 | ath6kl_err("unable to send the bmi data to the device: %d\n", | ||
294 | ret); | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int ath6kl_usb_power_on(struct ath6kl *ar) | ||
302 | { | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int ath6kl_usb_power_off(struct ath6kl *ar) | ||
307 | { | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static const struct ath6kl_hif_ops ath6kl_usb_ops = { | ||
312 | .diag_read32 = ath6kl_usb_diag_read32, | ||
313 | .diag_write32 = ath6kl_usb_diag_write32, | ||
314 | .bmi_read = ath6kl_usb_bmi_read, | ||
315 | .bmi_write = ath6kl_usb_bmi_write, | ||
316 | .power_on = ath6kl_usb_power_on, | ||
317 | .power_off = ath6kl_usb_power_off, | ||
318 | }; | ||
319 | |||
320 | /* ath6kl usb driver registered functions */ | ||
321 | static int ath6kl_usb_probe(struct usb_interface *interface, | ||
322 | const struct usb_device_id *id) | ||
323 | { | ||
324 | struct usb_device *dev = interface_to_usbdev(interface); | ||
325 | struct ath6kl *ar; | ||
326 | struct ath6kl_usb *ar_usb = NULL; | ||
327 | int vendor_id, product_id; | ||
328 | int ret = 0; | ||
329 | |||
330 | usb_get_dev(dev); | ||
331 | |||
332 | vendor_id = le16_to_cpu(dev->descriptor.idVendor); | ||
333 | product_id = le16_to_cpu(dev->descriptor.idProduct); | ||
334 | |||
335 | ath6kl_dbg(ATH6KL_DBG_USB, "vendor_id = %04x\n", vendor_id); | ||
336 | ath6kl_dbg(ATH6KL_DBG_USB, "product_id = %04x\n", product_id); | ||
337 | |||
338 | if (interface->cur_altsetting) | ||
339 | ath6kl_dbg(ATH6KL_DBG_USB, "USB Interface %d\n", | ||
340 | interface->cur_altsetting->desc.bInterfaceNumber); | ||
341 | |||
342 | |||
343 | if (dev->speed == USB_SPEED_HIGH) | ||
344 | ath6kl_dbg(ATH6KL_DBG_USB, "USB 2.0 Host\n"); | ||
345 | else | ||
346 | ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n"); | ||
347 | |||
348 | ar_usb = ath6kl_usb_create(interface); | ||
349 | |||
350 | if (ar_usb == NULL) { | ||
351 | ret = -ENOMEM; | ||
352 | goto err_usb_put; | ||
353 | } | ||
354 | |||
355 | ar = ath6kl_core_create(&ar_usb->udev->dev); | ||
356 | if (ar == NULL) { | ||
357 | ath6kl_err("Failed to alloc ath6kl core\n"); | ||
358 | ret = -ENOMEM; | ||
359 | goto err_usb_destroy; | ||
360 | } | ||
361 | |||
362 | ar->hif_priv = ar_usb; | ||
363 | ar->hif_type = ATH6KL_HIF_TYPE_USB; | ||
364 | ar->hif_ops = &ath6kl_usb_ops; | ||
365 | ar->mbox_info.block_size = 16; | ||
366 | ar->bmi.max_data_size = 252; | ||
367 | |||
368 | ar_usb->ar = ar; | ||
369 | |||
370 | ret = ath6kl_core_init(ar); | ||
371 | if (ret) { | ||
372 | ath6kl_err("Failed to init ath6kl core: %d\n", ret); | ||
373 | goto err_core_free; | ||
374 | } | ||
375 | |||
376 | return ret; | ||
377 | |||
378 | err_core_free: | ||
379 | ath6kl_core_destroy(ar); | ||
380 | err_usb_destroy: | ||
381 | ath6kl_usb_destroy(ar_usb); | ||
382 | err_usb_put: | ||
383 | usb_put_dev(dev); | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | static void ath6kl_usb_remove(struct usb_interface *interface) | ||
389 | { | ||
390 | usb_put_dev(interface_to_usbdev(interface)); | ||
391 | ath6kl_usb_device_detached(interface); | ||
392 | } | ||
393 | |||
394 | /* table of devices that work with this driver */ | ||
395 | static struct usb_device_id ath6kl_usb_ids[] = { | ||
396 | {USB_DEVICE(0x0cf3, 0x9374)}, | ||
397 | { /* Terminating entry */ }, | ||
398 | }; | ||
399 | |||
400 | MODULE_DEVICE_TABLE(usb, ath6kl_usb_ids); | ||
401 | |||
402 | static struct usb_driver ath6kl_usb_driver = { | ||
403 | .name = "ath6kl_usb", | ||
404 | .probe = ath6kl_usb_probe, | ||
405 | .disconnect = ath6kl_usb_remove, | ||
406 | .id_table = ath6kl_usb_ids, | ||
407 | }; | ||
408 | |||
409 | static int ath6kl_usb_init(void) | ||
410 | { | ||
411 | usb_register(&ath6kl_usb_driver); | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static void ath6kl_usb_exit(void) | ||
416 | { | ||
417 | usb_deregister(&ath6kl_usb_driver); | ||
418 | } | ||
419 | |||
420 | module_init(ath6kl_usb_init); | ||
421 | module_exit(ath6kl_usb_exit); | ||
422 | |||
423 | MODULE_AUTHOR("Atheros Communications, Inc."); | ||
424 | MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices"); | ||
425 | MODULE_LICENSE("Dual BSD/GPL"); | ||
426 | MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); | ||
427 | MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); | ||
428 | MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); | ||
429 | MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); | ||
430 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); | ||
431 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index f6f2aa27fc20..18fa9aa8af92 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -180,7 +180,7 @@ static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb, | |||
180 | } | 180 | } |
181 | 181 | ||
182 | int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, | 182 | int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, |
183 | u8 msg_type, bool more_data, | 183 | u8 msg_type, u32 flags, |
184 | enum wmi_data_hdr_data_type data_type, | 184 | enum wmi_data_hdr_data_type data_type, |
185 | u8 meta_ver, void *tx_meta_info, u8 if_idx) | 185 | u8 meta_ver, void *tx_meta_info, u8 if_idx) |
186 | { | 186 | { |
@@ -204,17 +204,19 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, | |||
204 | data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT; | 204 | data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT; |
205 | data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT; | 205 | data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT; |
206 | 206 | ||
207 | if (more_data) | 207 | if (flags & WMI_DATA_HDR_FLAGS_MORE) |
208 | data_hdr->info |= | 208 | data_hdr->info |= WMI_DATA_HDR_MORE; |
209 | WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT; | ||
210 | 209 | ||
211 | data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); | 210 | if (flags & WMI_DATA_HDR_FLAGS_EOSP) |
212 | data_hdr->info3 = cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); | 211 | data_hdr->info3 |= cpu_to_le16(WMI_DATA_HDR_EOSP); |
212 | |||
213 | data_hdr->info2 |= cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); | ||
214 | data_hdr->info3 |= cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); | ||
213 | 215 | ||
214 | return 0; | 216 | return 0; |
215 | } | 217 | } |
216 | 218 | ||
217 | static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) | 219 | u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) |
218 | { | 220 | { |
219 | struct iphdr *ip_hdr = (struct iphdr *) pkt; | 221 | struct iphdr *ip_hdr = (struct iphdr *) pkt; |
220 | u8 ip_pri; | 222 | u8 ip_pri; |
@@ -236,6 +238,11 @@ static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) | |||
236 | return ip_pri; | 238 | return ip_pri; |
237 | } | 239 | } |
238 | 240 | ||
241 | u8 ath6kl_wmi_get_traffic_class(u8 user_priority) | ||
242 | { | ||
243 | return up_to_ac[user_priority & 0x7]; | ||
244 | } | ||
245 | |||
239 | int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, | 246 | int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, |
240 | struct sk_buff *skb, | 247 | struct sk_buff *skb, |
241 | u32 layer2_priority, bool wmm_enabled, | 248 | u32 layer2_priority, bool wmm_enabled, |
@@ -419,9 +426,6 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) | |||
419 | ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", | 426 | ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", |
420 | evt->num_msg, evt->msg_len, evt->msg_type); | 427 | evt->num_msg, evt->msg_len, evt->msg_type); |
421 | 428 | ||
422 | if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI)) | ||
423 | return 0; | ||
424 | |||
425 | for (index = 0; index < evt->num_msg; index++) { | 429 | for (index = 0; index < evt->num_msg; index++) { |
426 | size = sizeof(struct wmi_tx_complete_event) + | 430 | size = sizeof(struct wmi_tx_complete_event) + |
427 | (index * sizeof(struct tx_complete_msg_v1)); | 431 | (index * sizeof(struct tx_complete_msg_v1)); |
@@ -786,12 +790,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
786 | ev->u.ap_sta.keymgmt, | 790 | ev->u.ap_sta.keymgmt, |
787 | le16_to_cpu(ev->u.ap_sta.cipher), | 791 | le16_to_cpu(ev->u.ap_sta.cipher), |
788 | ev->u.ap_sta.apsd_info); | 792 | ev->u.ap_sta.apsd_info); |
793 | |||
789 | ath6kl_connect_ap_mode_sta( | 794 | ath6kl_connect_ap_mode_sta( |
790 | vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, | 795 | vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, |
791 | ev->u.ap_sta.keymgmt, | 796 | ev->u.ap_sta.keymgmt, |
792 | le16_to_cpu(ev->u.ap_sta.cipher), | 797 | le16_to_cpu(ev->u.ap_sta.cipher), |
793 | ev->u.ap_sta.auth, ev->assoc_req_len, | 798 | ev->u.ap_sta.auth, ev->assoc_req_len, |
794 | ev->assoc_info + ev->beacon_ie_len); | 799 | ev->assoc_info + ev->beacon_ie_len, |
800 | ev->u.ap_sta.apsd_info); | ||
795 | } | 801 | } |
796 | return 0; | 802 | return 0; |
797 | } | 803 | } |
@@ -1145,9 +1151,9 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len) | |||
1145 | return 0; | 1151 | return 0; |
1146 | } | 1152 | } |
1147 | 1153 | ||
1148 | static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len) | 1154 | static int ath6kl_wmi_test_rx(struct wmi *wmi, u8 *datap, int len) |
1149 | { | 1155 | { |
1150 | ath6kl_tm_rx_report_event(wmi->parent_dev, datap, len); | 1156 | ath6kl_tm_rx_event(wmi->parent_dev, datap, len); |
1151 | 1157 | ||
1152 | return 0; | 1158 | return 0; |
1153 | } | 1159 | } |
@@ -2479,15 +2485,16 @@ int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class, | |||
2479 | return ret; | 2485 | return ret; |
2480 | } | 2486 | } |
2481 | 2487 | ||
2482 | int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) | 2488 | int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, |
2489 | __be32 ips0, __be32 ips1) | ||
2483 | { | 2490 | { |
2484 | struct sk_buff *skb; | 2491 | struct sk_buff *skb; |
2485 | struct wmi_set_ip_cmd *cmd; | 2492 | struct wmi_set_ip_cmd *cmd; |
2486 | int ret; | 2493 | int ret; |
2487 | 2494 | ||
2488 | /* Multicast address are not valid */ | 2495 | /* Multicast address are not valid */ |
2489 | if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) || | 2496 | if (ipv4_is_multicast(ips0) || |
2490 | (*((u8 *) &ip_cmd->ips[1]) >= 0xE0)) | 2497 | ipv4_is_multicast(ips1)) |
2491 | return -EINVAL; | 2498 | return -EINVAL; |
2492 | 2499 | ||
2493 | skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd)); | 2500 | skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd)); |
@@ -2495,9 +2502,10 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) | |||
2495 | return -ENOMEM; | 2502 | return -ENOMEM; |
2496 | 2503 | ||
2497 | cmd = (struct wmi_set_ip_cmd *) skb->data; | 2504 | cmd = (struct wmi_set_ip_cmd *) skb->data; |
2498 | memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd)); | 2505 | cmd->ips[0] = ips0; |
2506 | cmd->ips[1] = ips1; | ||
2499 | 2507 | ||
2500 | ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_IP_CMDID, | 2508 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IP_CMDID, |
2501 | NO_SYNC_WMIFLAG); | 2509 | NO_SYNC_WMIFLAG); |
2502 | return ret; | 2510 | return ret; |
2503 | } | 2511 | } |
@@ -2582,6 +2590,18 @@ int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, | |||
2582 | return ret; | 2590 | return ret; |
2583 | } | 2591 | } |
2584 | 2592 | ||
2593 | /* This command has zero length payload */ | ||
2594 | static int ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(struct wmi *wmi, | ||
2595 | struct ath6kl_vif *vif) | ||
2596 | { | ||
2597 | struct ath6kl *ar = wmi->parent_dev; | ||
2598 | |||
2599 | set_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags); | ||
2600 | wake_up(&ar->event_wq); | ||
2601 | |||
2602 | return 0; | ||
2603 | } | ||
2604 | |||
2585 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, | 2605 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, |
2586 | enum ath6kl_wow_mode wow_mode, | 2606 | enum ath6kl_wow_mode wow_mode, |
2587 | u32 filter, u16 host_req_delay) | 2607 | u32 filter, u16 host_req_delay) |
@@ -2612,7 +2632,8 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, | |||
2612 | 2632 | ||
2613 | int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, | 2633 | int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, |
2614 | u8 list_id, u8 filter_size, | 2634 | u8 list_id, u8 filter_size, |
2615 | u8 filter_offset, u8 *filter, u8 *mask) | 2635 | u8 filter_offset, const u8 *filter, |
2636 | const u8 *mask) | ||
2616 | { | 2637 | { |
2617 | struct sk_buff *skb; | 2638 | struct sk_buff *skb; |
2618 | struct wmi_add_wow_pattern_cmd *cmd; | 2639 | struct wmi_add_wow_pattern_cmd *cmd; |
@@ -2853,6 +2874,51 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) | |||
2853 | return ret; | 2874 | return ret; |
2854 | } | 2875 | } |
2855 | 2876 | ||
2877 | int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on) | ||
2878 | { | ||
2879 | struct sk_buff *skb; | ||
2880 | struct wmi_mcast_filter_cmd *cmd; | ||
2881 | int ret; | ||
2882 | |||
2883 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
2884 | if (!skb) | ||
2885 | return -ENOMEM; | ||
2886 | |||
2887 | cmd = (struct wmi_mcast_filter_cmd *) skb->data; | ||
2888 | cmd->mcast_all_enable = mc_all_on; | ||
2889 | |||
2890 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_MCAST_FILTER_CMDID, | ||
2891 | NO_SYNC_WMIFLAG); | ||
2892 | return ret; | ||
2893 | } | ||
2894 | |||
2895 | int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, | ||
2896 | u8 *filter, bool add_filter) | ||
2897 | { | ||
2898 | struct sk_buff *skb; | ||
2899 | struct wmi_mcast_filter_add_del_cmd *cmd; | ||
2900 | int ret; | ||
2901 | |||
2902 | if ((filter[0] != 0x33 || filter[1] != 0x33) && | ||
2903 | (filter[0] != 0x01 || filter[1] != 0x00 || | ||
2904 | filter[2] != 0x5e || filter[3] > 0x7f)) { | ||
2905 | ath6kl_warn("invalid multicast filter address\n"); | ||
2906 | return -EINVAL; | ||
2907 | } | ||
2908 | |||
2909 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
2910 | if (!skb) | ||
2911 | return -ENOMEM; | ||
2912 | |||
2913 | cmd = (struct wmi_mcast_filter_add_del_cmd *) skb->data; | ||
2914 | memcpy(cmd->mcast_mac, filter, ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE); | ||
2915 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
2916 | add_filter ? WMI_SET_MCAST_FILTER_CMDID : | ||
2917 | WMI_DEL_MCAST_FILTER_CMDID, | ||
2918 | NO_SYNC_WMIFLAG); | ||
2919 | |||
2920 | return ret; | ||
2921 | } | ||
2856 | 2922 | ||
2857 | s32 ath6kl_wmi_get_rate(s8 rate_index) | 2923 | s32 ath6kl_wmi_get_rate(s8 rate_index) |
2858 | { | 2924 | { |
@@ -2946,6 +3012,43 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac, | |||
2946 | NO_SYNC_WMIFLAG); | 3012 | NO_SYNC_WMIFLAG); |
2947 | } | 3013 | } |
2948 | 3014 | ||
3015 | /* This command will be used to enable/disable AP uAPSD feature */ | ||
3016 | int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable) | ||
3017 | { | ||
3018 | struct wmi_ap_set_apsd_cmd *cmd; | ||
3019 | struct sk_buff *skb; | ||
3020 | |||
3021 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
3022 | if (!skb) | ||
3023 | return -ENOMEM; | ||
3024 | |||
3025 | cmd = (struct wmi_ap_set_apsd_cmd *)skb->data; | ||
3026 | cmd->enable = enable; | ||
3027 | |||
3028 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_SET_APSD_CMDID, | ||
3029 | NO_SYNC_WMIFLAG); | ||
3030 | } | ||
3031 | |||
3032 | int ath6kl_wmi_set_apsd_bfrd_traf(struct wmi *wmi, u8 if_idx, | ||
3033 | u16 aid, u16 bitmap, u32 flags) | ||
3034 | { | ||
3035 | struct wmi_ap_apsd_buffered_traffic_cmd *cmd; | ||
3036 | struct sk_buff *skb; | ||
3037 | |||
3038 | skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); | ||
3039 | if (!skb) | ||
3040 | return -ENOMEM; | ||
3041 | |||
3042 | cmd = (struct wmi_ap_apsd_buffered_traffic_cmd *)skb->data; | ||
3043 | cmd->aid = cpu_to_le16(aid); | ||
3044 | cmd->bitmap = cpu_to_le16(bitmap); | ||
3045 | cmd->flags = cpu_to_le32(flags); | ||
3046 | |||
3047 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, | ||
3048 | WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID, | ||
3049 | NO_SYNC_WMIFLAG); | ||
3050 | } | ||
3051 | |||
2949 | static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len, | 3052 | static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len, |
2950 | struct ath6kl_vif *vif) | 3053 | struct ath6kl_vif *vif) |
2951 | { | 3054 | { |
@@ -3400,7 +3503,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
3400 | break; | 3503 | break; |
3401 | case WMI_TEST_EVENTID: | 3504 | case WMI_TEST_EVENTID: |
3402 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n"); | 3505 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n"); |
3403 | ret = ath6kl_wmi_tcmd_test_report_rx(wmi, datap, len); | 3506 | ret = ath6kl_wmi_test_rx(wmi, datap, len); |
3404 | break; | 3507 | break; |
3405 | case WMI_GET_FIXRATES_CMDID: | 3508 | case WMI_GET_FIXRATES_CMDID: |
3406 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); | 3509 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); |
@@ -3465,6 +3568,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) | |||
3465 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); | 3568 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); |
3466 | ret = ath6kl_wmi_tx_complete_event_rx(datap, len); | 3569 | ret = ath6kl_wmi_tx_complete_event_rx(datap, len); |
3467 | break; | 3570 | break; |
3571 | case WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID: | ||
3572 | ath6kl_dbg(ATH6KL_DBG_WMI, | ||
3573 | "WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID"); | ||
3574 | ret = ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(wmi, vif); | ||
3575 | break; | ||
3468 | case WMI_REMAIN_ON_CHNL_EVENTID: | 3576 | case WMI_REMAIN_ON_CHNL_EVENTID: |
3469 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n"); | 3577 | ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n"); |
3470 | ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif); | 3578 | ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif); |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 42ac311eda4e..e7919869725e 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -149,8 +149,7 @@ enum wmi_msg_type { | |||
149 | #define WMI_DATA_HDR_PS_MASK 0x1 | 149 | #define WMI_DATA_HDR_PS_MASK 0x1 |
150 | #define WMI_DATA_HDR_PS_SHIFT 5 | 150 | #define WMI_DATA_HDR_PS_SHIFT 5 |
151 | 151 | ||
152 | #define WMI_DATA_HDR_MORE_MASK 0x1 | 152 | #define WMI_DATA_HDR_MORE 0x20 |
153 | #define WMI_DATA_HDR_MORE_SHIFT 5 | ||
154 | 153 | ||
155 | enum wmi_data_hdr_data_type { | 154 | enum wmi_data_hdr_data_type { |
156 | WMI_DATA_HDR_DATA_TYPE_802_3 = 0, | 155 | WMI_DATA_HDR_DATA_TYPE_802_3 = 0, |
@@ -160,6 +159,13 @@ enum wmi_data_hdr_data_type { | |||
160 | WMI_DATA_HDR_DATA_TYPE_ACL, | 159 | WMI_DATA_HDR_DATA_TYPE_ACL, |
161 | }; | 160 | }; |
162 | 161 | ||
162 | /* Bitmap of data header flags */ | ||
163 | enum wmi_data_hdr_flags { | ||
164 | WMI_DATA_HDR_FLAGS_MORE = 0x1, | ||
165 | WMI_DATA_HDR_FLAGS_EOSP = 0x2, | ||
166 | WMI_DATA_HDR_FLAGS_UAPSD = 0x4, | ||
167 | }; | ||
168 | |||
163 | #define WMI_DATA_HDR_DATA_TYPE_MASK 0x3 | 169 | #define WMI_DATA_HDR_DATA_TYPE_MASK 0x3 |
164 | #define WMI_DATA_HDR_DATA_TYPE_SHIFT 6 | 170 | #define WMI_DATA_HDR_DATA_TYPE_SHIFT 6 |
165 | 171 | ||
@@ -173,8 +179,12 @@ enum wmi_data_hdr_data_type { | |||
173 | #define WMI_DATA_HDR_META_MASK 0x7 | 179 | #define WMI_DATA_HDR_META_MASK 0x7 |
174 | #define WMI_DATA_HDR_META_SHIFT 13 | 180 | #define WMI_DATA_HDR_META_SHIFT 13 |
175 | 181 | ||
182 | /* Macros for operating on WMI_DATA_HDR (info3) field */ | ||
176 | #define WMI_DATA_HDR_IF_IDX_MASK 0xF | 183 | #define WMI_DATA_HDR_IF_IDX_MASK 0xF |
177 | 184 | ||
185 | #define WMI_DATA_HDR_TRIG 0x10 | ||
186 | #define WMI_DATA_HDR_EOSP 0x10 | ||
187 | |||
178 | struct wmi_data_hdr { | 188 | struct wmi_data_hdr { |
179 | s8 rssi; | 189 | s8 rssi; |
180 | 190 | ||
@@ -203,7 +213,8 @@ struct wmi_data_hdr { | |||
203 | /* | 213 | /* |
204 | * usage of info3, 16-bit: | 214 | * usage of info3, 16-bit: |
205 | * b3:b0 - Interface index | 215 | * b3:b0 - Interface index |
206 | * b15:b4 - Reserved | 216 | * b4 - uAPSD trigger in rx & EOSP in tx |
217 | * b15:b5 - Reserved | ||
207 | */ | 218 | */ |
208 | __le16 info3; | 219 | __le16 info3; |
209 | } __packed; | 220 | } __packed; |
@@ -257,6 +268,9 @@ static inline u8 wmi_data_hdr_get_if_idx(struct wmi_data_hdr *dhdr) | |||
257 | #define WMI_META_VERSION_1 0x01 | 268 | #define WMI_META_VERSION_1 0x01 |
258 | #define WMI_META_VERSION_2 0x02 | 269 | #define WMI_META_VERSION_2 0x02 |
259 | 270 | ||
271 | /* Flag to signal to FW to calculate TCP checksum */ | ||
272 | #define WMI_META_V2_FLAG_CSUM_OFFLOAD 0x01 | ||
273 | |||
260 | struct wmi_tx_meta_v1 { | 274 | struct wmi_tx_meta_v1 { |
261 | /* packet ID to identify the tx request */ | 275 | /* packet ID to identify the tx request */ |
262 | u8 pkt_id; | 276 | u8 pkt_id; |
@@ -646,7 +660,6 @@ enum auth_mode { | |||
646 | WPA2_AUTH_CCKM = 0x40, | 660 | WPA2_AUTH_CCKM = 0x40, |
647 | }; | 661 | }; |
648 | 662 | ||
649 | #define WMI_MIN_KEY_INDEX 0 | ||
650 | #define WMI_MAX_KEY_INDEX 3 | 663 | #define WMI_MAX_KEY_INDEX 3 |
651 | 664 | ||
652 | #define WMI_MAX_KEY_LEN 32 | 665 | #define WMI_MAX_KEY_LEN 32 |
@@ -1237,6 +1250,15 @@ enum target_event_report_config { | |||
1237 | NO_DISCONN_EVT_IN_RECONN | 1250 | NO_DISCONN_EVT_IN_RECONN |
1238 | }; | 1251 | }; |
1239 | 1252 | ||
1253 | struct wmi_mcast_filter_cmd { | ||
1254 | u8 mcast_all_enable; | ||
1255 | } __packed; | ||
1256 | |||
1257 | #define ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE 6 | ||
1258 | struct wmi_mcast_filter_add_del_cmd { | ||
1259 | u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; | ||
1260 | } __packed; | ||
1261 | |||
1240 | /* Command Replies */ | 1262 | /* Command Replies */ |
1241 | 1263 | ||
1242 | /* WMI_GET_CHANNEL_LIST_CMDID reply */ | 1264 | /* WMI_GET_CHANNEL_LIST_CMDID reply */ |
@@ -1335,6 +1357,8 @@ enum wmi_event_id { | |||
1335 | WMI_P2P_START_SDPD_EVENTID, | 1357 | WMI_P2P_START_SDPD_EVENTID, |
1336 | WMI_P2P_SDPD_RX_EVENTID, | 1358 | WMI_P2P_SDPD_RX_EVENTID, |
1337 | 1359 | ||
1360 | WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID = 0x1047, | ||
1361 | |||
1338 | WMI_THIN_RESERVED_START_EVENTID = 0x8000, | 1362 | WMI_THIN_RESERVED_START_EVENTID = 0x8000, |
1339 | /* Events in this range are reserved for thinmode */ | 1363 | /* Events in this range are reserved for thinmode */ |
1340 | WMI_THIN_RESERVED_END_EVENTID = 0x8fff, | 1364 | WMI_THIN_RESERVED_END_EVENTID = 0x8fff, |
@@ -1903,7 +1927,7 @@ struct wow_filter { | |||
1903 | 1927 | ||
1904 | struct wmi_set_ip_cmd { | 1928 | struct wmi_set_ip_cmd { |
1905 | /* IP in network byte order */ | 1929 | /* IP in network byte order */ |
1906 | __le32 ips[MAX_IP_ADDRS]; | 1930 | __be32 ips[MAX_IP_ADDRS]; |
1907 | } __packed; | 1931 | } __packed; |
1908 | 1932 | ||
1909 | enum ath6kl_wow_filters { | 1933 | enum ath6kl_wow_filters { |
@@ -2105,6 +2129,19 @@ struct wmi_rx_frame_format_cmd { | |||
2105 | } __packed; | 2129 | } __packed; |
2106 | 2130 | ||
2107 | /* AP mode events */ | 2131 | /* AP mode events */ |
2132 | struct wmi_ap_set_apsd_cmd { | ||
2133 | u8 enable; | ||
2134 | } __packed; | ||
2135 | |||
2136 | enum wmi_ap_apsd_buffered_traffic_flags { | ||
2137 | WMI_AP_APSD_NO_DELIVERY_FRAMES = 0x1, | ||
2138 | }; | ||
2139 | |||
2140 | struct wmi_ap_apsd_buffered_traffic_cmd { | ||
2141 | __le16 aid; | ||
2142 | __le16 bitmap; | ||
2143 | __le32 flags; | ||
2144 | } __packed; | ||
2108 | 2145 | ||
2109 | /* WMI_PS_POLL_EVENT */ | 2146 | /* WMI_PS_POLL_EVENT */ |
2110 | struct wmi_pspoll_event { | 2147 | struct wmi_pspoll_event { |
@@ -2321,7 +2358,7 @@ enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi); | |||
2321 | void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id); | 2358 | void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id); |
2322 | int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb); | 2359 | int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb); |
2323 | int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, | 2360 | int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, |
2324 | u8 msg_type, bool more_data, | 2361 | u8 msg_type, u32 flags, |
2325 | enum wmi_data_hdr_data_type data_type, | 2362 | enum wmi_data_hdr_data_type data_type, |
2326 | u8 meta_ver, void *tx_meta_info, u8 if_idx); | 2363 | u8 meta_ver, void *tx_meta_info, u8 if_idx); |
2327 | 2364 | ||
@@ -2417,7 +2454,8 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); | |||
2417 | 2454 | ||
2418 | s32 ath6kl_wmi_get_rate(s8 rate_index); | 2455 | s32 ath6kl_wmi_get_rate(s8 rate_index); |
2419 | 2456 | ||
2420 | int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd); | 2457 | int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, |
2458 | __be32 ips0, __be32 ips1); | ||
2421 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, | 2459 | int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, |
2422 | enum ath6kl_host_mode host_mode); | 2460 | enum ath6kl_host_mode host_mode); |
2423 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, | 2461 | int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, |
@@ -2425,13 +2463,26 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, | |||
2425 | u32 filter, u16 host_req_delay); | 2463 | u32 filter, u16 host_req_delay); |
2426 | int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, | 2464 | int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, |
2427 | u8 list_id, u8 filter_size, | 2465 | u8 list_id, u8 filter_size, |
2428 | u8 filter_offset, u8 *filter, u8 *mask); | 2466 | u8 filter_offset, const u8 *filter, |
2467 | const u8 *mask); | ||
2429 | int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, | 2468 | int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, |
2430 | u16 list_id, u16 filter_id); | 2469 | u16 list_id, u16 filter_id); |
2431 | int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); | 2470 | int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); |
2432 | int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); | 2471 | int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); |
2433 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); | 2472 | int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); |
2473 | int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); | ||
2474 | int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, | ||
2475 | u8 *filter, bool add_filter); | ||
2476 | /* AP mode uAPSD */ | ||
2477 | int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); | ||
2478 | |||
2479 | int ath6kl_wmi_set_apsd_bfrd_traf(struct wmi *wmi, | ||
2480 | u8 if_idx, u16 aid, | ||
2481 | u16 bitmap, u32 flags); | ||
2482 | |||
2483 | u8 ath6kl_wmi_get_traffic_class(u8 user_priority); | ||
2434 | 2484 | ||
2485 | u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri); | ||
2435 | /* AP mode */ | 2486 | /* AP mode */ |
2436 | int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, | 2487 | int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, |
2437 | struct wmi_connect_cmd *p); | 2488 | struct wmi_connect_cmd *p); |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index f317515d8bf3..424aabb2c730 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -981,7 +981,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
981 | return -ENOMEM; | 981 | return -ENOMEM; |
982 | 982 | ||
983 | while (len) { | 983 | while (len) { |
984 | transfer = min_t(int, len, 4096); | 984 | transfer = min_t(size_t, len, 4096); |
985 | memcpy(buf, data, transfer); | 985 | memcpy(buf, data, transfer); |
986 | 986 | ||
987 | err = usb_control_msg(hif_dev->udev, | 987 | err = usb_control_msg(hif_dev->udev, |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 635b592ad961..a427a16bb739 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1346,7 +1346,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1346 | fc = hdr->frame_control; | 1346 | fc = hdr->frame_control; |
1347 | for (i = 0; i < sc->hw->max_rates; i++) { | 1347 | for (i = 0; i < sc->hw->max_rates; i++) { |
1348 | struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; | 1348 | struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; |
1349 | if (!rate->count) | 1349 | if (rate->idx < 0 || !rate->count) |
1350 | break; | 1350 | break; |
1351 | 1351 | ||
1352 | final_ts_idx = i; | 1352 | final_ts_idx = i; |
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 32a9966c3bf6..c4955d25a19a 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c | |||
@@ -172,7 +172,7 @@ libipw_rx_frame_mgmt(struct libipw_device *ieee, struct sk_buff *skb, | |||
172 | u16 stype) | 172 | u16 stype) |
173 | { | 173 | { |
174 | if (ieee->iw_mode == IW_MODE_MASTER) { | 174 | if (ieee->iw_mode == IW_MODE_MASTER) { |
175 | printk(KERN_DEBUG "%s: Master mode not yet suppported.\n", | 175 | printk(KERN_DEBUG "%s: Master mode not yet supported.\n", |
176 | ieee->dev->name); | 176 | ieee->dev->name); |
177 | return 0; | 177 | return 0; |
178 | /* | 178 | /* |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 54b2d391e91a..aa8f5c0bd642 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -140,7 +140,7 @@ il3945_set_ccmp_dynamic_key_info(struct il_priv *il, | |||
140 | key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); | 140 | key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); |
141 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | 141 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); |
142 | 142 | ||
143 | if (sta_id == il->ctx.bcast_sta_id) | 143 | if (sta_id == il->hw_params.bcast_id) |
144 | key_flags |= STA_KEY_MULTICAST_MSK; | 144 | key_flags |= STA_KEY_MULTICAST_MSK; |
145 | 145 | ||
146 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 146 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
@@ -341,7 +341,7 @@ il3945_send_beacon_cmd(struct il_priv *il) | |||
341 | return -ENOMEM; | 341 | return -ENOMEM; |
342 | } | 342 | } |
343 | 343 | ||
344 | rate = il_get_lowest_plcp(il, &il->ctx); | 344 | rate = il_get_lowest_plcp(il); |
345 | 345 | ||
346 | frame_size = il3945_hw_get_beacon_cmd(il, frame, rate); | 346 | frame_size = il3945_hw_get_beacon_cmd(il, frame, rate); |
347 | 347 | ||
@@ -512,7 +512,7 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
512 | hdr_len = ieee80211_hdrlen(fc); | 512 | hdr_len = ieee80211_hdrlen(fc); |
513 | 513 | ||
514 | /* Find idx into station table for destination station */ | 514 | /* Find idx into station table for destination station */ |
515 | sta_id = il_sta_id_or_broadcast(il, &il->ctx, info->control.sta); | 515 | sta_id = il_sta_id_or_broadcast(il, info->control.sta); |
516 | if (sta_id == IL_INVALID_STATION) { | 516 | if (sta_id == IL_INVALID_STATION) { |
517 | D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1); | 517 | D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1); |
518 | goto drop; | 518 | goto drop; |
@@ -538,10 +538,7 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
538 | 538 | ||
539 | idx = il_get_cmd_idx(q, q->write_ptr, 0); | 539 | idx = il_get_cmd_idx(q, q->write_ptr, 0); |
540 | 540 | ||
541 | /* Set up driver data for this TFD */ | 541 | txq->skbs[q->write_ptr] = skb; |
542 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info)); | ||
543 | txq->txb[q->write_ptr].skb = skb; | ||
544 | txq->txb[q->write_ptr].ctx = &il->ctx; | ||
545 | 542 | ||
546 | /* Init first empty entry in queue's array of Tx/cmd buffers */ | 543 | /* Init first empty entry in queue's array of Tx/cmd buffers */ |
547 | out_cmd = txq->cmd[idx]; | 544 | out_cmd = txq->cmd[idx]; |
@@ -619,8 +616,7 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
619 | 616 | ||
620 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 617 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
621 | * first entry */ | 618 | * first entry */ |
622 | il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, | 619 | il->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); |
623 | 0); | ||
624 | 620 | ||
625 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 621 | /* Set up TFD's 2nd entry to point directly to remainder of skb, |
626 | * if any (802.11 null frames have no payload). */ | 622 | * if any (802.11 null frames have no payload). */ |
@@ -629,8 +625,8 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
629 | phys_addr = | 625 | phys_addr = |
630 | pci_map_single(il->pci_dev, skb->data + hdr_len, len, | 626 | pci_map_single(il->pci_dev, skb->data + hdr_len, len, |
631 | PCI_DMA_TODEVICE); | 627 | PCI_DMA_TODEVICE); |
632 | il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, | 628 | il->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0, |
633 | len, 0, U32_PAD(len)); | 629 | U32_PAD(len)); |
634 | } | 630 | } |
635 | 631 | ||
636 | /* Tell device the write idx *just past* this latest filled TFD */ | 632 | /* Tell device the write idx *just past* this latest filled TFD */ |
@@ -672,15 +668,13 @@ il3945_get_measurement(struct il_priv *il, | |||
672 | int rc; | 668 | int rc; |
673 | int spectrum_resp_status; | 669 | int spectrum_resp_status; |
674 | int duration = le16_to_cpu(params->duration); | 670 | int duration = le16_to_cpu(params->duration); |
675 | struct il_rxon_context *ctx = &il->ctx; | ||
676 | 671 | ||
677 | if (il_is_associated(il)) | 672 | if (il_is_associated(il)) |
678 | add_time = | 673 | add_time = |
679 | il_usecs_to_beacons(il, | 674 | il_usecs_to_beacons(il, |
680 | le64_to_cpu(params->start_time) - | 675 | le64_to_cpu(params->start_time) - |
681 | il->_3945.last_tsf, | 676 | il->_3945.last_tsf, |
682 | le16_to_cpu(ctx->timing. | 677 | le16_to_cpu(il->timing.beacon_interval)); |
683 | beacon_interval)); | ||
684 | 678 | ||
685 | memset(&spectrum, 0, sizeof(spectrum)); | 679 | memset(&spectrum, 0, sizeof(spectrum)); |
686 | 680 | ||
@@ -694,15 +688,14 @@ il3945_get_measurement(struct il_priv *il, | |||
694 | if (il_is_associated(il)) | 688 | if (il_is_associated(il)) |
695 | spectrum.start_time = | 689 | spectrum.start_time = |
696 | il_add_beacon_time(il, il->_3945.last_beacon_time, add_time, | 690 | il_add_beacon_time(il, il->_3945.last_beacon_time, add_time, |
697 | le16_to_cpu(ctx->timing. | 691 | le16_to_cpu(il->timing.beacon_interval)); |
698 | beacon_interval)); | ||
699 | else | 692 | else |
700 | spectrum.start_time = 0; | 693 | spectrum.start_time = 0; |
701 | 694 | ||
702 | spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); | 695 | spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); |
703 | spectrum.channels[0].channel = params->channel; | 696 | spectrum.channels[0].channel = params->channel; |
704 | spectrum.channels[0].type = type; | 697 | spectrum.channels[0].type = type; |
705 | if (ctx->active.flags & RXON_FLG_BAND_24G_MSK) | 698 | if (il->active.flags & RXON_FLG_BAND_24G_MSK) |
706 | spectrum.flags |= | 699 | spectrum.flags |= |
707 | RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | | 700 | RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | |
708 | RXON_FLG_TGG_PROTECT_MSK; | 701 | RXON_FLG_TGG_PROTECT_MSK; |
@@ -2150,7 +2143,6 @@ il3945_alive_start(struct il_priv *il) | |||
2150 | { | 2143 | { |
2151 | int thermal_spin = 0; | 2144 | int thermal_spin = 0; |
2152 | u32 rfkill; | 2145 | u32 rfkill; |
2153 | struct il_rxon_context *ctx = &il->ctx; | ||
2154 | 2146 | ||
2155 | D_INFO("Runtime Alive received.\n"); | 2147 | D_INFO("Runtime Alive received.\n"); |
2156 | 2148 | ||
@@ -2206,13 +2198,13 @@ il3945_alive_start(struct il_priv *il) | |||
2206 | 2198 | ||
2207 | if (il_is_associated(il)) { | 2199 | if (il_is_associated(il)) { |
2208 | struct il3945_rxon_cmd *active_rxon = | 2200 | struct il3945_rxon_cmd *active_rxon = |
2209 | (struct il3945_rxon_cmd *)(&ctx->active); | 2201 | (struct il3945_rxon_cmd *)(&il->active); |
2210 | 2202 | ||
2211 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2203 | il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2212 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2204 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2213 | } else { | 2205 | } else { |
2214 | /* Initialize our rx_config data */ | 2206 | /* Initialize our rx_config data */ |
2215 | il_connection_init_rx_config(il, ctx); | 2207 | il_connection_init_rx_config(il); |
2216 | } | 2208 | } |
2217 | 2209 | ||
2218 | /* Configure Bluetooth device coexistence support */ | 2210 | /* Configure Bluetooth device coexistence support */ |
@@ -2221,7 +2213,7 @@ il3945_alive_start(struct il_priv *il) | |||
2221 | set_bit(S_READY, &il->status); | 2213 | set_bit(S_READY, &il->status); |
2222 | 2214 | ||
2223 | /* Configure the adapter for unassociated operation */ | 2215 | /* Configure the adapter for unassociated operation */ |
2224 | il3945_commit_rxon(il, ctx); | 2216 | il3945_commit_rxon(il); |
2225 | 2217 | ||
2226 | il3945_reg_txpower_periodic(il); | 2218 | il3945_reg_txpower_periodic(il); |
2227 | 2219 | ||
@@ -2253,7 +2245,7 @@ __il3945_down(struct il_priv *il) | |||
2253 | del_timer_sync(&il->watchdog); | 2245 | del_timer_sync(&il->watchdog); |
2254 | 2246 | ||
2255 | /* Station information will now be cleared in device */ | 2247 | /* Station information will now be cleared in device */ |
2256 | il_clear_ucode_stations(il, NULL); | 2248 | il_clear_ucode_stations(il); |
2257 | il_dealloc_bcast_stations(il); | 2249 | il_dealloc_bcast_stations(il); |
2258 | il_clear_driver_stations(il); | 2250 | il_clear_driver_stations(il); |
2259 | 2251 | ||
@@ -2339,12 +2331,11 @@ il3945_down(struct il_priv *il) | |||
2339 | static int | 2331 | static int |
2340 | il3945_alloc_bcast_station(struct il_priv *il) | 2332 | il3945_alloc_bcast_station(struct il_priv *il) |
2341 | { | 2333 | { |
2342 | struct il_rxon_context *ctx = &il->ctx; | ||
2343 | unsigned long flags; | 2334 | unsigned long flags; |
2344 | u8 sta_id; | 2335 | u8 sta_id; |
2345 | 2336 | ||
2346 | spin_lock_irqsave(&il->sta_lock, flags); | 2337 | spin_lock_irqsave(&il->sta_lock, flags); |
2347 | sta_id = il_prep_station(il, ctx, il_bcast_addr, false, NULL); | 2338 | sta_id = il_prep_station(il, il_bcast_addr, false, NULL); |
2348 | if (sta_id == IL_INVALID_STATION) { | 2339 | if (sta_id == IL_INVALID_STATION) { |
2349 | IL_ERR("Unable to prepare broadcast station\n"); | 2340 | IL_ERR("Unable to prepare broadcast station\n"); |
2350 | spin_unlock_irqrestore(&il->sta_lock, flags); | 2341 | spin_unlock_irqrestore(&il->sta_lock, flags); |
@@ -2422,7 +2413,7 @@ __il3945_up(struct il_priv *il) | |||
2422 | /* load bootstrap state machine, | 2413 | /* load bootstrap state machine, |
2423 | * load bootstrap program into processor's memory, | 2414 | * load bootstrap program into processor's memory, |
2424 | * prepare to load the "initialize" uCode */ | 2415 | * prepare to load the "initialize" uCode */ |
2425 | rc = il->cfg->ops->lib->load_ucode(il); | 2416 | rc = il->ops->lib->load_ucode(il); |
2426 | 2417 | ||
2427 | if (rc) { | 2418 | if (rc) { |
2428 | IL_ERR("Unable to set up bootstrap uCode: %d\n", rc); | 2419 | IL_ERR("Unable to set up bootstrap uCode: %d\n", rc); |
@@ -2602,7 +2593,7 @@ il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif) | |||
2602 | /* We don't build a direct scan probe request; the uCode will do | 2593 | /* We don't build a direct scan probe request; the uCode will do |
2603 | * that based on the direct_mask added to each channel entry */ | 2594 | * that based on the direct_mask added to each channel entry */ |
2604 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | 2595 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; |
2605 | scan->tx_cmd.sta_id = il->ctx.bcast_sta_id; | 2596 | scan->tx_cmd.sta_id = il->hw_params.bcast_id; |
2606 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 2597 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
2607 | 2598 | ||
2608 | /* flags + rate selection */ | 2599 | /* flags + rate selection */ |
@@ -2664,14 +2655,12 @@ il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif) | |||
2664 | void | 2655 | void |
2665 | il3945_post_scan(struct il_priv *il) | 2656 | il3945_post_scan(struct il_priv *il) |
2666 | { | 2657 | { |
2667 | struct il_rxon_context *ctx = &il->ctx; | ||
2668 | |||
2669 | /* | 2658 | /* |
2670 | * Since setting the RXON may have been deferred while | 2659 | * Since setting the RXON may have been deferred while |
2671 | * performing the scan, fire one off if needed | 2660 | * performing the scan, fire one off if needed |
2672 | */ | 2661 | */ |
2673 | if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) | 2662 | if (memcmp(&il->staging, &il->active, sizeof(il->staging))) |
2674 | il3945_commit_rxon(il, ctx); | 2663 | il3945_commit_rxon(il); |
2675 | } | 2664 | } |
2676 | 2665 | ||
2677 | static void | 2666 | static void |
@@ -2684,7 +2673,8 @@ il3945_bg_restart(struct work_struct *data) | |||
2684 | 2673 | ||
2685 | if (test_and_clear_bit(S_FW_ERROR, &il->status)) { | 2674 | if (test_and_clear_bit(S_FW_ERROR, &il->status)) { |
2686 | mutex_lock(&il->mutex); | 2675 | mutex_lock(&il->mutex); |
2687 | il->ctx.vif = NULL; | 2676 | /* FIXME: vif can be dereferenced */ |
2677 | il->vif = NULL; | ||
2688 | il->is_open = 0; | 2678 | il->is_open = 0; |
2689 | mutex_unlock(&il->mutex); | 2679 | mutex_unlock(&il->mutex); |
2690 | il3945_down(il); | 2680 | il3945_down(il); |
@@ -2722,13 +2712,12 @@ il3945_post_associate(struct il_priv *il) | |||
2722 | { | 2712 | { |
2723 | int rc = 0; | 2713 | int rc = 0; |
2724 | struct ieee80211_conf *conf = NULL; | 2714 | struct ieee80211_conf *conf = NULL; |
2725 | struct il_rxon_context *ctx = &il->ctx; | ||
2726 | 2715 | ||
2727 | if (!ctx->vif || !il->is_open) | 2716 | if (!il->vif || !il->is_open) |
2728 | return; | 2717 | return; |
2729 | 2718 | ||
2730 | D_ASSOC("Associated as %d to: %pM\n", ctx->vif->bss_conf.aid, | 2719 | D_ASSOC("Associated as %d to: %pM\n", il->vif->bss_conf.aid, |
2731 | ctx->active.bssid_addr); | 2720 | il->active.bssid_addr); |
2732 | 2721 | ||
2733 | if (test_bit(S_EXIT_PENDING, &il->status)) | 2722 | if (test_bit(S_EXIT_PENDING, &il->status)) |
2734 | return; | 2723 | return; |
@@ -2737,35 +2726,35 @@ il3945_post_associate(struct il_priv *il) | |||
2737 | 2726 | ||
2738 | conf = &il->hw->conf; | 2727 | conf = &il->hw->conf; |
2739 | 2728 | ||
2740 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2729 | il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2741 | il3945_commit_rxon(il, ctx); | 2730 | il3945_commit_rxon(il); |
2742 | 2731 | ||
2743 | rc = il_send_rxon_timing(il, ctx); | 2732 | rc = il_send_rxon_timing(il); |
2744 | if (rc) | 2733 | if (rc) |
2745 | IL_WARN("C_RXON_TIMING failed - " "Attempting to continue.\n"); | 2734 | IL_WARN("C_RXON_TIMING failed - " "Attempting to continue.\n"); |
2746 | 2735 | ||
2747 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2736 | il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2748 | 2737 | ||
2749 | ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid); | 2738 | il->staging.assoc_id = cpu_to_le16(il->vif->bss_conf.aid); |
2750 | 2739 | ||
2751 | D_ASSOC("assoc id %d beacon interval %d\n", ctx->vif->bss_conf.aid, | 2740 | D_ASSOC("assoc id %d beacon interval %d\n", il->vif->bss_conf.aid, |
2752 | ctx->vif->bss_conf.beacon_int); | 2741 | il->vif->bss_conf.beacon_int); |
2753 | 2742 | ||
2754 | if (ctx->vif->bss_conf.use_short_preamble) | 2743 | if (il->vif->bss_conf.use_short_preamble) |
2755 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 2744 | il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2756 | else | 2745 | else |
2757 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 2746 | il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2758 | 2747 | ||
2759 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { | 2748 | if (il->staging.flags & RXON_FLG_BAND_24G_MSK) { |
2760 | if (ctx->vif->bss_conf.use_short_slot) | 2749 | if (il->vif->bss_conf.use_short_slot) |
2761 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | 2750 | il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2762 | else | 2751 | else |
2763 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2752 | il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2764 | } | 2753 | } |
2765 | 2754 | ||
2766 | il3945_commit_rxon(il, ctx); | 2755 | il3945_commit_rxon(il); |
2767 | 2756 | ||
2768 | switch (ctx->vif->type) { | 2757 | switch (il->vif->type) { |
2769 | case NL80211_IFTYPE_STATION: | 2758 | case NL80211_IFTYPE_STATION: |
2770 | il3945_rate_scale_init(il->hw, IL_AP_ID); | 2759 | il3945_rate_scale_init(il->hw, IL_AP_ID); |
2771 | break; | 2760 | break; |
@@ -2774,7 +2763,7 @@ il3945_post_associate(struct il_priv *il) | |||
2774 | break; | 2763 | break; |
2775 | default: | 2764 | default: |
2776 | IL_ERR("%s Should not be called in %d mode\n", __func__, | 2765 | IL_ERR("%s Should not be called in %d mode\n", __func__, |
2777 | ctx->vif->type); | 2766 | il->vif->type); |
2778 | break; | 2767 | break; |
2779 | } | 2768 | } |
2780 | } | 2769 | } |
@@ -2891,8 +2880,7 @@ il3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2891 | void | 2880 | void |
2892 | il3945_config_ap(struct il_priv *il) | 2881 | il3945_config_ap(struct il_priv *il) |
2893 | { | 2882 | { |
2894 | struct il_rxon_context *ctx = &il->ctx; | 2883 | struct ieee80211_vif *vif = il->vif; |
2895 | struct ieee80211_vif *vif = ctx->vif; | ||
2896 | int rc = 0; | 2884 | int rc = 0; |
2897 | 2885 | ||
2898 | if (test_bit(S_EXIT_PENDING, &il->status)) | 2886 | if (test_bit(S_EXIT_PENDING, &il->status)) |
@@ -2902,31 +2890,31 @@ il3945_config_ap(struct il_priv *il) | |||
2902 | if (!(il_is_associated(il))) { | 2890 | if (!(il_is_associated(il))) { |
2903 | 2891 | ||
2904 | /* RXON - unassoc (to set timing command) */ | 2892 | /* RXON - unassoc (to set timing command) */ |
2905 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2893 | il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2906 | il3945_commit_rxon(il, ctx); | 2894 | il3945_commit_rxon(il); |
2907 | 2895 | ||
2908 | /* RXON Timing */ | 2896 | /* RXON Timing */ |
2909 | rc = il_send_rxon_timing(il, ctx); | 2897 | rc = il_send_rxon_timing(il); |
2910 | if (rc) | 2898 | if (rc) |
2911 | IL_WARN("C_RXON_TIMING failed - " | 2899 | IL_WARN("C_RXON_TIMING failed - " |
2912 | "Attempting to continue.\n"); | 2900 | "Attempting to continue.\n"); |
2913 | 2901 | ||
2914 | ctx->staging.assoc_id = 0; | 2902 | il->staging.assoc_id = 0; |
2915 | 2903 | ||
2916 | if (vif->bss_conf.use_short_preamble) | 2904 | if (vif->bss_conf.use_short_preamble) |
2917 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 2905 | il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2918 | else | 2906 | else |
2919 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 2907 | il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2920 | 2908 | ||
2921 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { | 2909 | if (il->staging.flags & RXON_FLG_BAND_24G_MSK) { |
2922 | if (vif->bss_conf.use_short_slot) | 2910 | if (vif->bss_conf.use_short_slot) |
2923 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | 2911 | il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2924 | else | 2912 | else |
2925 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2913 | il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2926 | } | 2914 | } |
2927 | /* restore RXON assoc */ | 2915 | /* restore RXON assoc */ |
2928 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2916 | il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2929 | il3945_commit_rxon(il, ctx); | 2917 | il3945_commit_rxon(il); |
2930 | } | 2918 | } |
2931 | il3945_send_beacon_cmd(il); | 2919 | il3945_send_beacon_cmd(il); |
2932 | } | 2920 | } |
@@ -2959,7 +2947,7 @@ il3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2959 | static_key = !il_is_associated(il); | 2947 | static_key = !il_is_associated(il); |
2960 | 2948 | ||
2961 | if (!static_key) { | 2949 | if (!static_key) { |
2962 | sta_id = il_sta_id_or_broadcast(il, &il->ctx, sta); | 2950 | sta_id = il_sta_id_or_broadcast(il, sta); |
2963 | if (sta_id == IL_INVALID_STATION) | 2951 | if (sta_id == IL_INVALID_STATION) |
2964 | return -EINVAL; | 2952 | return -EINVAL; |
2965 | } | 2953 | } |
@@ -3007,8 +2995,7 @@ il3945_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
3007 | D_INFO("proceeding to add station %pM\n", sta->addr); | 2995 | D_INFO("proceeding to add station %pM\n", sta->addr); |
3008 | sta_priv->common.sta_id = IL_INVALID_STATION; | 2996 | sta_priv->common.sta_id = IL_INVALID_STATION; |
3009 | 2997 | ||
3010 | ret = | 2998 | ret = il_add_station_common(il, sta->addr, is_ap, sta, &sta_id); |
3011 | il_add_station_common(il, &il->ctx, sta->addr, is_ap, sta, &sta_id); | ||
3012 | if (ret) { | 2999 | if (ret) { |
3013 | IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret); | 3000 | IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret); |
3014 | /* Should we return success if return code is EEXIST ? */ | 3001 | /* Should we return success if return code is EEXIST ? */ |
@@ -3032,7 +3019,6 @@ il3945_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, | |||
3032 | { | 3019 | { |
3033 | struct il_priv *il = hw->priv; | 3020 | struct il_priv *il = hw->priv; |
3034 | __le32 filter_or = 0, filter_nand = 0; | 3021 | __le32 filter_or = 0, filter_nand = 0; |
3035 | struct il_rxon_context *ctx = &il->ctx; | ||
3036 | 3022 | ||
3037 | #define CHK(test, flag) do { \ | 3023 | #define CHK(test, flag) do { \ |
3038 | if (*total_flags & (test)) \ | 3024 | if (*total_flags & (test)) \ |
@@ -3052,8 +3038,8 @@ il3945_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, | |||
3052 | 3038 | ||
3053 | mutex_lock(&il->mutex); | 3039 | mutex_lock(&il->mutex); |
3054 | 3040 | ||
3055 | ctx->staging.filter_flags &= ~filter_nand; | 3041 | il->staging.filter_flags &= ~filter_nand; |
3056 | ctx->staging.filter_flags |= filter_or; | 3042 | il->staging.filter_flags |= filter_or; |
3057 | 3043 | ||
3058 | /* | 3044 | /* |
3059 | * Not committing directly because hardware can perform a scan, | 3045 | * Not committing directly because hardware can perform a scan, |
@@ -3170,9 +3156,8 @@ static ssize_t | |||
3170 | il3945_show_flags(struct device *d, struct device_attribute *attr, char *buf) | 3156 | il3945_show_flags(struct device *d, struct device_attribute *attr, char *buf) |
3171 | { | 3157 | { |
3172 | struct il_priv *il = dev_get_drvdata(d); | 3158 | struct il_priv *il = dev_get_drvdata(d); |
3173 | struct il_rxon_context *ctx = &il->ctx; | ||
3174 | 3159 | ||
3175 | return sprintf(buf, "0x%04X\n", ctx->active.flags); | 3160 | return sprintf(buf, "0x%04X\n", il->active.flags); |
3176 | } | 3161 | } |
3177 | 3162 | ||
3178 | static ssize_t | 3163 | static ssize_t |
@@ -3181,17 +3166,16 @@ il3945_store_flags(struct device *d, struct device_attribute *attr, | |||
3181 | { | 3166 | { |
3182 | struct il_priv *il = dev_get_drvdata(d); | 3167 | struct il_priv *il = dev_get_drvdata(d); |
3183 | u32 flags = simple_strtoul(buf, NULL, 0); | 3168 | u32 flags = simple_strtoul(buf, NULL, 0); |
3184 | struct il_rxon_context *ctx = &il->ctx; | ||
3185 | 3169 | ||
3186 | mutex_lock(&il->mutex); | 3170 | mutex_lock(&il->mutex); |
3187 | if (le32_to_cpu(ctx->staging.flags) != flags) { | 3171 | if (le32_to_cpu(il->staging.flags) != flags) { |
3188 | /* Cancel any currently running scans... */ | 3172 | /* Cancel any currently running scans... */ |
3189 | if (il_scan_cancel_timeout(il, 100)) | 3173 | if (il_scan_cancel_timeout(il, 100)) |
3190 | IL_WARN("Could not cancel scan.\n"); | 3174 | IL_WARN("Could not cancel scan.\n"); |
3191 | else { | 3175 | else { |
3192 | D_INFO("Committing rxon.flags = 0x%04X\n", flags); | 3176 | D_INFO("Committing rxon.flags = 0x%04X\n", flags); |
3193 | ctx->staging.flags = cpu_to_le32(flags); | 3177 | il->staging.flags = cpu_to_le32(flags); |
3194 | il3945_commit_rxon(il, ctx); | 3178 | il3945_commit_rxon(il); |
3195 | } | 3179 | } |
3196 | } | 3180 | } |
3197 | mutex_unlock(&il->mutex); | 3181 | mutex_unlock(&il->mutex); |
@@ -3207,9 +3191,8 @@ il3945_show_filter_flags(struct device *d, struct device_attribute *attr, | |||
3207 | char *buf) | 3191 | char *buf) |
3208 | { | 3192 | { |
3209 | struct il_priv *il = dev_get_drvdata(d); | 3193 | struct il_priv *il = dev_get_drvdata(d); |
3210 | struct il_rxon_context *ctx = &il->ctx; | ||
3211 | 3194 | ||
3212 | return sprintf(buf, "0x%04X\n", le32_to_cpu(ctx->active.filter_flags)); | 3195 | return sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags)); |
3213 | } | 3196 | } |
3214 | 3197 | ||
3215 | static ssize_t | 3198 | static ssize_t |
@@ -3217,19 +3200,18 @@ il3945_store_filter_flags(struct device *d, struct device_attribute *attr, | |||
3217 | const char *buf, size_t count) | 3200 | const char *buf, size_t count) |
3218 | { | 3201 | { |
3219 | struct il_priv *il = dev_get_drvdata(d); | 3202 | struct il_priv *il = dev_get_drvdata(d); |
3220 | struct il_rxon_context *ctx = &il->ctx; | ||
3221 | u32 filter_flags = simple_strtoul(buf, NULL, 0); | 3203 | u32 filter_flags = simple_strtoul(buf, NULL, 0); |
3222 | 3204 | ||
3223 | mutex_lock(&il->mutex); | 3205 | mutex_lock(&il->mutex); |
3224 | if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) { | 3206 | if (le32_to_cpu(il->staging.filter_flags) != filter_flags) { |
3225 | /* Cancel any currently running scans... */ | 3207 | /* Cancel any currently running scans... */ |
3226 | if (il_scan_cancel_timeout(il, 100)) | 3208 | if (il_scan_cancel_timeout(il, 100)) |
3227 | IL_WARN("Could not cancel scan.\n"); | 3209 | IL_WARN("Could not cancel scan.\n"); |
3228 | else { | 3210 | else { |
3229 | D_INFO("Committing rxon.filter_flags = " "0x%04X\n", | 3211 | D_INFO("Committing rxon.filter_flags = " "0x%04X\n", |
3230 | filter_flags); | 3212 | filter_flags); |
3231 | ctx->staging.filter_flags = cpu_to_le32(filter_flags); | 3213 | il->staging.filter_flags = cpu_to_le32(filter_flags); |
3232 | il3945_commit_rxon(il, ctx); | 3214 | il3945_commit_rxon(il); |
3233 | } | 3215 | } |
3234 | } | 3216 | } |
3235 | mutex_unlock(&il->mutex); | 3217 | mutex_unlock(&il->mutex); |
@@ -3278,9 +3260,8 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr, | |||
3278 | const char *buf, size_t count) | 3260 | const char *buf, size_t count) |
3279 | { | 3261 | { |
3280 | struct il_priv *il = dev_get_drvdata(d); | 3262 | struct il_priv *il = dev_get_drvdata(d); |
3281 | struct il_rxon_context *ctx = &il->ctx; | ||
3282 | struct ieee80211_measurement_params params = { | 3263 | struct ieee80211_measurement_params params = { |
3283 | .channel = le16_to_cpu(ctx->active.channel), | 3264 | .channel = le16_to_cpu(il->active.channel), |
3284 | .start_time = cpu_to_le64(il->_3945.last_tsf), | 3265 | .start_time = cpu_to_le64(il->_3945.last_tsf), |
3285 | .duration = cpu_to_le16(1), | 3266 | .duration = cpu_to_le16(1), |
3286 | }; | 3267 | }; |
@@ -3474,7 +3455,7 @@ static struct attribute_group il3945_attribute_group = { | |||
3474 | .attrs = il3945_sysfs_entries, | 3455 | .attrs = il3945_sysfs_entries, |
3475 | }; | 3456 | }; |
3476 | 3457 | ||
3477 | struct ieee80211_ops il3945_hw_ops = { | 3458 | struct ieee80211_ops il3945_mac_ops = { |
3478 | .tx = il3945_mac_tx, | 3459 | .tx = il3945_mac_tx, |
3479 | .start = il3945_mac_start, | 3460 | .start = il3945_mac_start, |
3480 | .stop = il3945_mac_stop, | 3461 | .stop = il3945_mac_stop, |
@@ -3567,7 +3548,8 @@ il3945_setup_mac(struct il_priv *il) | |||
3567 | /* Tell mac80211 our characteristics */ | 3548 | /* Tell mac80211 our characteristics */ |
3568 | hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT; | 3549 | hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT; |
3569 | 3550 | ||
3570 | hw->wiphy->interface_modes = il->ctx.interface_modes; | 3551 | hw->wiphy->interface_modes = |
3552 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); | ||
3571 | 3553 | ||
3572 | hw->wiphy->flags |= | 3554 | hw->wiphy->flags |= |
3573 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 3555 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
@@ -3614,44 +3596,29 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3614 | * 1. Allocating HW data | 3596 | * 1. Allocating HW data |
3615 | * ********************/ | 3597 | * ********************/ |
3616 | 3598 | ||
3617 | /* mac80211 allocates memory for this device instance, including | 3599 | hw = ieee80211_alloc_hw(sizeof(struct il_priv), &il3945_mac_ops); |
3618 | * space for this driver's ilate structure */ | 3600 | if (!hw) { |
3619 | hw = il_alloc_all(cfg); | ||
3620 | if (hw == NULL) { | ||
3621 | pr_err("Can not allocate network device\n"); | ||
3622 | err = -ENOMEM; | 3601 | err = -ENOMEM; |
3623 | goto out; | 3602 | goto out; |
3624 | } | 3603 | } |
3625 | il = hw->priv; | 3604 | il = hw->priv; |
3605 | il->hw = hw; | ||
3626 | SET_IEEE80211_DEV(hw, &pdev->dev); | 3606 | SET_IEEE80211_DEV(hw, &pdev->dev); |
3627 | 3607 | ||
3628 | il->cmd_queue = IL39_CMD_QUEUE_NUM; | 3608 | il->cmd_queue = IL39_CMD_QUEUE_NUM; |
3629 | 3609 | ||
3630 | il->ctx.ctxid = 0; | ||
3631 | |||
3632 | il->ctx.rxon_cmd = C_RXON; | ||
3633 | il->ctx.rxon_timing_cmd = C_RXON_TIMING; | ||
3634 | il->ctx.rxon_assoc_cmd = C_RXON_ASSOC; | ||
3635 | il->ctx.qos_cmd = C_QOS_PARAM; | ||
3636 | il->ctx.ap_sta_id = IL_AP_ID; | ||
3637 | il->ctx.wep_key_cmd = C_WEPKEY; | ||
3638 | il->ctx.interface_modes = | ||
3639 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); | ||
3640 | il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS; | ||
3641 | il->ctx.station_devtype = RXON_DEV_TYPE_ESS; | ||
3642 | il->ctx.unused_devtype = RXON_DEV_TYPE_ESS; | ||
3643 | |||
3644 | /* | 3610 | /* |
3645 | * Disabling hardware scan means that mac80211 will perform scans | 3611 | * Disabling hardware scan means that mac80211 will perform scans |
3646 | * "the hard way", rather than using device's scan. | 3612 | * "the hard way", rather than using device's scan. |
3647 | */ | 3613 | */ |
3648 | if (il3945_mod_params.disable_hw_scan) { | 3614 | if (il3945_mod_params.disable_hw_scan) { |
3649 | D_INFO("Disabling hw_scan\n"); | 3615 | D_INFO("Disabling hw_scan\n"); |
3650 | il3945_hw_ops.hw_scan = NULL; | 3616 | il3945_mac_ops.hw_scan = NULL; |
3651 | } | 3617 | } |
3652 | 3618 | ||
3653 | D_INFO("*** LOAD DRIVER ***\n"); | 3619 | D_INFO("*** LOAD DRIVER ***\n"); |
3654 | il->cfg = cfg; | 3620 | il->cfg = cfg; |
3621 | il->ops = &il3945_ops; | ||
3655 | il->pci_dev = pdev; | 3622 | il->pci_dev = pdev; |
3656 | il->inta_mask = CSR_INI_SET_MASK; | 3623 | il->inta_mask = CSR_INI_SET_MASK; |
3657 | 3624 | ||
@@ -3773,8 +3740,7 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3773 | goto out_release_irq; | 3740 | goto out_release_irq; |
3774 | } | 3741 | } |
3775 | 3742 | ||
3776 | il_set_rxon_channel(il, &il->bands[IEEE80211_BAND_2GHZ].channels[5], | 3743 | il_set_rxon_channel(il, &il->bands[IEEE80211_BAND_2GHZ].channels[5]); |
3777 | &il->ctx); | ||
3778 | il3945_setup_deferred_work(il); | 3744 | il3945_setup_deferred_work(il); |
3779 | il3945_setup_handlers(il); | 3745 | il3945_setup_handlers(il); |
3780 | il_power_initialize(il); | 3746 | il_power_initialize(il); |
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c index d7a83f229190..70bee1a4d876 100644 --- a/drivers/net/wireless/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/iwlegacy/3945-rs.c | |||
@@ -342,7 +342,7 @@ il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id) | |||
342 | int i; | 342 | int i; |
343 | 343 | ||
344 | D_INFO("enter\n"); | 344 | D_INFO("enter\n"); |
345 | if (sta_id == il->ctx.bcast_sta_id) | 345 | if (sta_id == il->hw_params.bcast_id) |
346 | goto out; | 346 | goto out; |
347 | 347 | ||
348 | psta = (struct il3945_sta_priv *)sta->drv_priv; | 348 | psta = (struct il3945_sta_priv *)sta->drv_priv; |
@@ -927,8 +927,7 @@ il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | |||
927 | 927 | ||
928 | rcu_read_lock(); | 928 | rcu_read_lock(); |
929 | 929 | ||
930 | sta = | 930 | sta = ieee80211_find_sta(il->vif, il->stations[sta_id].sta.sta.addr); |
931 | ieee80211_find_sta(il->ctx.vif, il->stations[sta_id].sta.sta.addr); | ||
932 | if (!sta) { | 931 | if (!sta) { |
933 | D_RATE("Unable to find station to initialize rate scaling.\n"); | 932 | D_RATE("Unable to find station to initialize rate scaling.\n"); |
934 | rcu_read_unlock(); | 933 | rcu_read_unlock(); |
@@ -944,7 +943,7 @@ il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | |||
944 | switch (il->band) { | 943 | switch (il->band) { |
945 | case IEEE80211_BAND_2GHZ: | 944 | case IEEE80211_BAND_2GHZ: |
946 | /* TODO: this always does G, not a regression */ | 945 | /* TODO: this always does G, not a regression */ |
947 | if (il->ctx.active.flags & RXON_FLG_TGG_PROTECT_MSK) { | 946 | if (il->active.flags & RXON_FLG_TGG_PROTECT_MSK) { |
948 | rs_sta->tgg = 1; | 947 | rs_sta->tgg = 1; |
949 | rs_sta->expected_tpt = il3945_expected_tpt_g_prot; | 948 | rs_sta->expected_tpt = il3945_expected_tpt_g_prot; |
950 | } else | 949 | } else |
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index 1489b1573a6a..6c1ae5fab899 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c | |||
@@ -293,17 +293,17 @@ il3945_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) | |||
293 | { | 293 | { |
294 | struct il_tx_queue *txq = &il->txq[txq_id]; | 294 | struct il_tx_queue *txq = &il->txq[txq_id]; |
295 | struct il_queue *q = &txq->q; | 295 | struct il_queue *q = &txq->q; |
296 | struct il_tx_info *tx_info; | 296 | struct sk_buff *skb; |
297 | 297 | ||
298 | BUG_ON(txq_id == IL39_CMD_QUEUE_NUM); | 298 | BUG_ON(txq_id == IL39_CMD_QUEUE_NUM); |
299 | 299 | ||
300 | for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; | 300 | for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; |
301 | q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 301 | q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
302 | 302 | ||
303 | tx_info = &txq->txb[txq->q.read_ptr]; | 303 | skb = txq->skbs[txq->q.read_ptr]; |
304 | ieee80211_tx_status_irqsafe(il->hw, tx_info->skb); | 304 | ieee80211_tx_status_irqsafe(il->hw, skb); |
305 | tx_info->skb = NULL; | 305 | txq->skbs[txq->q.read_ptr] = NULL; |
306 | il->cfg->ops->lib->txq_free_tfd(il, txq); | 306 | il->ops->lib->txq_free_tfd(il, txq); |
307 | } | 307 | } |
308 | 308 | ||
309 | if (il_queue_space(q) > q->low_mark && txq_id >= 0 && | 309 | if (il_queue_space(q) > q->low_mark && txq_id >= 0 && |
@@ -336,7 +336,7 @@ il3945_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) | |||
336 | } | 336 | } |
337 | 337 | ||
338 | txq->time_stamp = jiffies; | 338 | txq->time_stamp = jiffies; |
339 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); | 339 | info = IEEE80211_SKB_CB(txq->skbs[txq->q.read_ptr]); |
340 | ieee80211_tx_info_clear_status(info); | 340 | ieee80211_tx_info_clear_status(info); |
341 | 341 | ||
342 | /* Fill the MRR chain with some info about on-chip retransmissions */ | 342 | /* Fill the MRR chain with some info about on-chip retransmissions */ |
@@ -660,15 +660,13 @@ il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq) | |||
660 | PCI_DMA_TODEVICE); | 660 | PCI_DMA_TODEVICE); |
661 | 661 | ||
662 | /* free SKB */ | 662 | /* free SKB */ |
663 | if (txq->txb) { | 663 | if (txq->skbs) { |
664 | struct sk_buff *skb; | 664 | struct sk_buff *skb = txq->skbs[txq->q.read_ptr]; |
665 | |||
666 | skb = txq->txb[txq->q.read_ptr].skb; | ||
667 | 665 | ||
668 | /* can be called from irqs-disabled context */ | 666 | /* can be called from irqs-disabled context */ |
669 | if (skb) { | 667 | if (skb) { |
670 | dev_kfree_skb_any(skb); | 668 | dev_kfree_skb_any(skb); |
671 | txq->txb[txq->q.read_ptr].skb = NULL; | 669 | txq->skbs[txq->q.read_ptr] = NULL; |
672 | } | 670 | } |
673 | } | 671 | } |
674 | } | 672 | } |
@@ -960,12 +958,12 @@ il3945_hw_nic_init(struct il_priv *il) | |||
960 | struct il_rx_queue *rxq = &il->rxq; | 958 | struct il_rx_queue *rxq = &il->rxq; |
961 | 959 | ||
962 | spin_lock_irqsave(&il->lock, flags); | 960 | spin_lock_irqsave(&il->lock, flags); |
963 | il->cfg->ops->lib->apm_ops.init(il); | 961 | il->ops->lib->apm_ops.init(il); |
964 | spin_unlock_irqrestore(&il->lock, flags); | 962 | spin_unlock_irqrestore(&il->lock, flags); |
965 | 963 | ||
966 | il3945_set_pwr_vmain(il); | 964 | il3945_set_pwr_vmain(il); |
967 | 965 | ||
968 | il->cfg->ops->lib->apm_ops.config(il); | 966 | il->ops->lib->apm_ops.config(il); |
969 | 967 | ||
970 | /* Allocate the RX queue, or reset if it is already allocated */ | 968 | /* Allocate the RX queue, or reset if it is already allocated */ |
971 | if (!rxq->bd) { | 969 | if (!rxq->bd) { |
@@ -1388,7 +1386,7 @@ il3945_send_tx_power(struct il_priv *il) | |||
1388 | int rate_idx, i; | 1386 | int rate_idx, i; |
1389 | const struct il_channel_info *ch_info = NULL; | 1387 | const struct il_channel_info *ch_info = NULL; |
1390 | struct il3945_txpowertable_cmd txpower = { | 1388 | struct il3945_txpowertable_cmd txpower = { |
1391 | .channel = il->ctx.active.channel, | 1389 | .channel = il->active.channel, |
1392 | }; | 1390 | }; |
1393 | u16 chan; | 1391 | u16 chan; |
1394 | 1392 | ||
@@ -1397,7 +1395,7 @@ il3945_send_tx_power(struct il_priv *il) | |||
1397 | "TX Power requested while scanning!\n")) | 1395 | "TX Power requested while scanning!\n")) |
1398 | return -EAGAIN; | 1396 | return -EAGAIN; |
1399 | 1397 | ||
1400 | chan = le16_to_cpu(il->ctx.active.channel); | 1398 | chan = le16_to_cpu(il->active.channel); |
1401 | 1399 | ||
1402 | txpower.band = (il->band == IEEE80211_BAND_5GHZ) ? 0 : 1; | 1400 | txpower.band = (il->band == IEEE80211_BAND_5GHZ) ? 0 : 1; |
1403 | ch_info = il_get_channel_info(il, il->band, chan); | 1401 | ch_info = il_get_channel_info(il, il->band, chan); |
@@ -1615,7 +1613,7 @@ il3945_hw_reg_comp_txpower_temp(struct il_priv *il) | |||
1615 | } | 1613 | } |
1616 | 1614 | ||
1617 | /* send Txpower command for current channel to ucode */ | 1615 | /* send Txpower command for current channel to ucode */ |
1618 | return il->cfg->ops->lib->send_tx_power(il); | 1616 | return il->ops->lib->send_tx_power(il); |
1619 | } | 1617 | } |
1620 | 1618 | ||
1621 | int | 1619 | int |
@@ -1662,7 +1660,7 @@ il3945_hw_reg_set_txpower(struct il_priv *il, s8 power) | |||
1662 | } | 1660 | } |
1663 | 1661 | ||
1664 | static int | 1662 | static int |
1665 | il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) | 1663 | il3945_send_rxon_assoc(struct il_priv *il) |
1666 | { | 1664 | { |
1667 | int rc = 0; | 1665 | int rc = 0; |
1668 | struct il_rx_pkt *pkt; | 1666 | struct il_rx_pkt *pkt; |
@@ -1673,8 +1671,8 @@ il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) | |||
1673 | .flags = CMD_WANT_SKB, | 1671 | .flags = CMD_WANT_SKB, |
1674 | .data = &rxon_assoc, | 1672 | .data = &rxon_assoc, |
1675 | }; | 1673 | }; |
1676 | const struct il_rxon_cmd *rxon1 = &ctx->staging; | 1674 | const struct il_rxon_cmd *rxon1 = &il->staging; |
1677 | const struct il_rxon_cmd *rxon2 = &ctx->active; | 1675 | const struct il_rxon_cmd *rxon2 = &il->active; |
1678 | 1676 | ||
1679 | if (rxon1->flags == rxon2->flags && | 1677 | if (rxon1->flags == rxon2->flags && |
1680 | rxon1->filter_flags == rxon2->filter_flags && | 1678 | rxon1->filter_flags == rxon2->filter_flags && |
@@ -1684,10 +1682,10 @@ il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) | |||
1684 | return 0; | 1682 | return 0; |
1685 | } | 1683 | } |
1686 | 1684 | ||
1687 | rxon_assoc.flags = ctx->staging.flags; | 1685 | rxon_assoc.flags = il->staging.flags; |
1688 | rxon_assoc.filter_flags = ctx->staging.filter_flags; | 1686 | rxon_assoc.filter_flags = il->staging.filter_flags; |
1689 | rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; | 1687 | rxon_assoc.ofdm_basic_rates = il->staging.ofdm_basic_rates; |
1690 | rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; | 1688 | rxon_assoc.cck_basic_rates = il->staging.cck_basic_rates; |
1691 | rxon_assoc.reserved = 0; | 1689 | rxon_assoc.reserved = 0; |
1692 | 1690 | ||
1693 | rc = il_send_cmd_sync(il, &cmd); | 1691 | rc = il_send_cmd_sync(il, &cmd); |
@@ -1714,11 +1712,11 @@ il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) | |||
1714 | * a HW tune is required based on the RXON structure changes. | 1712 | * a HW tune is required based on the RXON structure changes. |
1715 | */ | 1713 | */ |
1716 | int | 1714 | int |
1717 | il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | 1715 | il3945_commit_rxon(struct il_priv *il) |
1718 | { | 1716 | { |
1719 | /* cast away the const for active_rxon in this function */ | 1717 | /* cast away the const for active_rxon in this function */ |
1720 | struct il3945_rxon_cmd *active_rxon = (void *)&ctx->active; | 1718 | struct il3945_rxon_cmd *active_rxon = (void *)&il->active; |
1721 | struct il3945_rxon_cmd *staging_rxon = (void *)&ctx->staging; | 1719 | struct il3945_rxon_cmd *staging_rxon = (void *)&il->staging; |
1722 | int rc = 0; | 1720 | int rc = 0; |
1723 | bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK); | 1721 | bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK); |
1724 | 1722 | ||
@@ -1735,7 +1733,7 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1735 | staging_rxon->flags &= ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); | 1733 | staging_rxon->flags &= ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); |
1736 | staging_rxon->flags |= il3945_get_antenna_flags(il); | 1734 | staging_rxon->flags |= il3945_get_antenna_flags(il); |
1737 | 1735 | ||
1738 | rc = il_check_rxon_cmd(il, ctx); | 1736 | rc = il_check_rxon_cmd(il); |
1739 | if (rc) { | 1737 | if (rc) { |
1740 | IL_ERR("Invalid RXON configuration. Not committing.\n"); | 1738 | IL_ERR("Invalid RXON configuration. Not committing.\n"); |
1741 | return -EINVAL; | 1739 | return -EINVAL; |
@@ -1744,8 +1742,8 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1744 | /* If we don't need to send a full RXON, we can use | 1742 | /* If we don't need to send a full RXON, we can use |
1745 | * il3945_rxon_assoc_cmd which is used to reconfigure filter | 1743 | * il3945_rxon_assoc_cmd which is used to reconfigure filter |
1746 | * and other flags for the current radio configuration. */ | 1744 | * and other flags for the current radio configuration. */ |
1747 | if (!il_full_rxon_required(il, &il->ctx)) { | 1745 | if (!il_full_rxon_required(il)) { |
1748 | rc = il_send_rxon_assoc(il, &il->ctx); | 1746 | rc = il_send_rxon_assoc(il); |
1749 | if (rc) { | 1747 | if (rc) { |
1750 | IL_ERR("Error setting RXON_ASSOC " | 1748 | IL_ERR("Error setting RXON_ASSOC " |
1751 | "configuration (%d).\n", rc); | 1749 | "configuration (%d).\n", rc); |
@@ -1776,7 +1774,7 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1776 | active_rxon->reserved4 = 0; | 1774 | active_rxon->reserved4 = 0; |
1777 | active_rxon->reserved5 = 0; | 1775 | active_rxon->reserved5 = 0; |
1778 | rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd), | 1776 | rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd), |
1779 | &il->ctx.active); | 1777 | &il->active); |
1780 | 1778 | ||
1781 | /* If the mask clearing failed then we set | 1779 | /* If the mask clearing failed then we set |
1782 | * active_rxon back to what it was previously */ | 1780 | * active_rxon back to what it was previously */ |
@@ -1786,8 +1784,8 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1786 | "configuration (%d).\n", rc); | 1784 | "configuration (%d).\n", rc); |
1787 | return rc; | 1785 | return rc; |
1788 | } | 1786 | } |
1789 | il_clear_ucode_stations(il, &il->ctx); | 1787 | il_clear_ucode_stations(il); |
1790 | il_restore_stations(il, &il->ctx); | 1788 | il_restore_stations(il); |
1791 | } | 1789 | } |
1792 | 1790 | ||
1793 | D_INFO("Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n" | 1791 | D_INFO("Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n" |
@@ -1801,7 +1799,7 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1801 | staging_rxon->reserved4 = 0; | 1799 | staging_rxon->reserved4 = 0; |
1802 | staging_rxon->reserved5 = 0; | 1800 | staging_rxon->reserved5 = 0; |
1803 | 1801 | ||
1804 | il_set_rxon_hwcrypto(il, ctx, !il3945_mod_params.sw_crypto); | 1802 | il_set_rxon_hwcrypto(il, !il3945_mod_params.sw_crypto); |
1805 | 1803 | ||
1806 | /* Apply the new configuration */ | 1804 | /* Apply the new configuration */ |
1807 | rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd), | 1805 | rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd), |
@@ -1814,8 +1812,8 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1814 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); | 1812 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); |
1815 | 1813 | ||
1816 | if (!new_assoc) { | 1814 | if (!new_assoc) { |
1817 | il_clear_ucode_stations(il, &il->ctx); | 1815 | il_clear_ucode_stations(il); |
1818 | il_restore_stations(il, &il->ctx); | 1816 | il_restore_stations(il); |
1819 | } | 1817 | } |
1820 | 1818 | ||
1821 | /* If we issue a new RXON command which required a tune then we must | 1819 | /* If we issue a new RXON command which required a tune then we must |
@@ -2258,7 +2256,6 @@ il3945_build_addsta_hcmd(const struct il_addsta_cmd *cmd, u8 * data) | |||
2258 | static int | 2256 | static int |
2259 | il3945_add_bssid_station(struct il_priv *il, const u8 * addr, u8 * sta_id_r) | 2257 | il3945_add_bssid_station(struct il_priv *il, const u8 * addr, u8 * sta_id_r) |
2260 | { | 2258 | { |
2261 | struct il_rxon_context *ctx = &il->ctx; | ||
2262 | int ret; | 2259 | int ret; |
2263 | u8 sta_id; | 2260 | u8 sta_id; |
2264 | unsigned long flags; | 2261 | unsigned long flags; |
@@ -2266,7 +2263,7 @@ il3945_add_bssid_station(struct il_priv *il, const u8 * addr, u8 * sta_id_r) | |||
2266 | if (sta_id_r) | 2263 | if (sta_id_r) |
2267 | *sta_id_r = IL_INVALID_STATION; | 2264 | *sta_id_r = IL_INVALID_STATION; |
2268 | 2265 | ||
2269 | ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id); | 2266 | ret = il_add_station_common(il, addr, 0, NULL, &sta_id); |
2270 | if (ret) { | 2267 | if (ret) { |
2271 | IL_ERR("Unable to add station %pM\n", addr); | 2268 | IL_ERR("Unable to add station %pM\n", addr); |
2272 | return ret; | 2269 | return ret; |
@@ -2396,15 +2393,16 @@ il3945_hw_set_hw_params(struct il_priv *il) | |||
2396 | return -ENOMEM; | 2393 | return -ENOMEM; |
2397 | } | 2394 | } |
2398 | 2395 | ||
2396 | il->hw_params.bcast_id = IL3945_BROADCAST_ID; | ||
2397 | |||
2399 | /* Assign number of Usable TX queues */ | 2398 | /* Assign number of Usable TX queues */ |
2400 | il->hw_params.max_txq_num = il->cfg->base_params->num_of_queues; | 2399 | il->hw_params.max_txq_num = il->cfg->num_of_queues; |
2401 | 2400 | ||
2402 | il->hw_params.tfd_size = sizeof(struct il3945_tfd); | 2401 | il->hw_params.tfd_size = sizeof(struct il3945_tfd); |
2403 | il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_3K); | 2402 | il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_3K); |
2404 | il->hw_params.max_rxq_size = RX_QUEUE_SIZE; | 2403 | il->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
2405 | il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | 2404 | il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; |
2406 | il->hw_params.max_stations = IL3945_STATION_COUNT; | 2405 | il->hw_params.max_stations = IL3945_STATION_COUNT; |
2407 | il->ctx.bcast_sta_id = IL3945_BROADCAST_ID; | ||
2408 | 2406 | ||
2409 | il->sta_key_max_num = STA_KEY_MAX_NUM; | 2407 | il->sta_key_max_num = STA_KEY_MAX_NUM; |
2410 | 2408 | ||
@@ -2425,7 +2423,7 @@ il3945_hw_get_beacon_cmd(struct il_priv *il, struct il3945_frame *frame, | |||
2425 | tx_beacon_cmd = (struct il3945_tx_beacon_cmd *)&frame->u; | 2423 | tx_beacon_cmd = (struct il3945_tx_beacon_cmd *)&frame->u; |
2426 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); | 2424 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); |
2427 | 2425 | ||
2428 | tx_beacon_cmd->tx.sta_id = il->ctx.bcast_sta_id; | 2426 | tx_beacon_cmd->tx.sta_id = il->hw_params.bcast_id; |
2429 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 2427 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
2430 | 2428 | ||
2431 | frame_size = | 2429 | frame_size = |
@@ -2685,23 +2683,12 @@ static struct il_hcmd_utils_ops il3945_hcmd_utils = { | |||
2685 | .post_scan = il3945_post_scan, | 2683 | .post_scan = il3945_post_scan, |
2686 | }; | 2684 | }; |
2687 | 2685 | ||
2688 | static const struct il_ops il3945_ops = { | 2686 | const struct il_ops il3945_ops = { |
2689 | .lib = &il3945_lib, | 2687 | .lib = &il3945_lib, |
2690 | .hcmd = &il3945_hcmd, | 2688 | .hcmd = &il3945_hcmd, |
2691 | .utils = &il3945_hcmd_utils, | 2689 | .utils = &il3945_hcmd_utils, |
2692 | .led = &il3945_led_ops, | 2690 | .led = &il3945_led_ops, |
2693 | .legacy = &il3945_legacy_ops, | 2691 | .legacy = &il3945_legacy_ops, |
2694 | .ieee80211_ops = &il3945_hw_ops, | ||
2695 | }; | ||
2696 | |||
2697 | static struct il_base_params il3945_base_params = { | ||
2698 | .eeprom_size = IL3945_EEPROM_IMG_SIZE, | ||
2699 | .num_of_queues = IL39_NUM_QUEUES, | ||
2700 | .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, | ||
2701 | .set_l0s = false, | ||
2702 | .use_bsm = true, | ||
2703 | .led_compensation = 64, | ||
2704 | .wd_timeout = IL_DEF_WD_TIMEOUT, | ||
2705 | }; | 2692 | }; |
2706 | 2693 | ||
2707 | static struct il_cfg il3945_bg_cfg = { | 2694 | static struct il_cfg il3945_bg_cfg = { |
@@ -2711,10 +2698,16 @@ static struct il_cfg il3945_bg_cfg = { | |||
2711 | .ucode_api_min = IL3945_UCODE_API_MIN, | 2698 | .ucode_api_min = IL3945_UCODE_API_MIN, |
2712 | .sku = IL_SKU_G, | 2699 | .sku = IL_SKU_G, |
2713 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2700 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2714 | .ops = &il3945_ops, | ||
2715 | .mod_params = &il3945_mod_params, | 2701 | .mod_params = &il3945_mod_params, |
2716 | .base_params = &il3945_base_params, | ||
2717 | .led_mode = IL_LED_BLINK, | 2702 | .led_mode = IL_LED_BLINK, |
2703 | |||
2704 | .eeprom_size = IL3945_EEPROM_IMG_SIZE, | ||
2705 | .num_of_queues = IL39_NUM_QUEUES, | ||
2706 | .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, | ||
2707 | .set_l0s = false, | ||
2708 | .use_bsm = true, | ||
2709 | .led_compensation = 64, | ||
2710 | .wd_timeout = IL_DEF_WD_TIMEOUT | ||
2718 | }; | 2711 | }; |
2719 | 2712 | ||
2720 | static struct il_cfg il3945_abg_cfg = { | 2713 | static struct il_cfg il3945_abg_cfg = { |
@@ -2724,10 +2717,16 @@ static struct il_cfg il3945_abg_cfg = { | |||
2724 | .ucode_api_min = IL3945_UCODE_API_MIN, | 2717 | .ucode_api_min = IL3945_UCODE_API_MIN, |
2725 | .sku = IL_SKU_A | IL_SKU_G, | 2718 | .sku = IL_SKU_A | IL_SKU_G, |
2726 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2719 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2727 | .ops = &il3945_ops, | ||
2728 | .mod_params = &il3945_mod_params, | 2720 | .mod_params = &il3945_mod_params, |
2729 | .base_params = &il3945_base_params, | ||
2730 | .led_mode = IL_LED_BLINK, | 2721 | .led_mode = IL_LED_BLINK, |
2722 | |||
2723 | .eeprom_size = IL3945_EEPROM_IMG_SIZE, | ||
2724 | .num_of_queues = IL39_NUM_QUEUES, | ||
2725 | .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, | ||
2726 | .set_l0s = false, | ||
2727 | .use_bsm = true, | ||
2728 | .led_compensation = 64, | ||
2729 | .wd_timeout = IL_DEF_WD_TIMEOUT | ||
2731 | }; | 2730 | }; |
2732 | 2731 | ||
2733 | DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = { | 2732 | DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = { |
diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h index 9f42f79f8778..c00a8d30b6fe 100644 --- a/drivers/net/wireless/iwlegacy/3945.h +++ b/drivers/net/wireless/iwlegacy/3945.h | |||
@@ -36,6 +36,8 @@ extern const struct pci_device_id il3945_hw_card_ids[]; | |||
36 | 36 | ||
37 | #include "common.h" | 37 | #include "common.h" |
38 | 38 | ||
39 | extern const struct il_ops il3945_ops; | ||
40 | |||
39 | /* Highest firmware API version supported */ | 41 | /* Highest firmware API version supported */ |
40 | #define IL3945_UCODE_API_MAX 2 | 42 | #define IL3945_UCODE_API_MAX 2 |
41 | 43 | ||
@@ -249,7 +251,7 @@ extern int il4965_get_temperature(const struct il_priv *il); | |||
249 | extern void il3945_post_associate(struct il_priv *il); | 251 | extern void il3945_post_associate(struct il_priv *il); |
250 | extern void il3945_config_ap(struct il_priv *il); | 252 | extern void il3945_config_ap(struct il_priv *il); |
251 | 253 | ||
252 | extern int il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx); | 254 | extern int il3945_commit_rxon(struct il_priv *il); |
253 | 255 | ||
254 | /** | 256 | /** |
255 | * il3945_hw_find_station - Find station id for a given BSSID | 257 | * il3945_hw_find_station - Find station id for a given BSSID |
@@ -261,8 +263,6 @@ extern int il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx); | |||
261 | */ | 263 | */ |
262 | extern u8 il3945_hw_find_station(struct il_priv *il, const u8 * bssid); | 264 | extern u8 il3945_hw_find_station(struct il_priv *il, const u8 * bssid); |
263 | 265 | ||
264 | extern struct ieee80211_ops il3945_hw_ops; | ||
265 | |||
266 | extern __le32 il3945_get_antenna_flags(const struct il_priv *il); | 266 | extern __le32 il3945_get_antenna_flags(const struct il_priv *il); |
267 | extern int il3945_init_hw_rate_table(struct il_priv *il); | 267 | extern int il3945_init_hw_rate_table(struct il_priv *il); |
268 | extern void il3945_reg_txpower_periodic(struct il_priv *il); | 268 | extern void il3945_reg_txpower_periodic(struct il_priv *il); |
diff --git a/drivers/net/wireless/iwlegacy/4965-calib.c b/drivers/net/wireless/iwlegacy/4965-calib.c index d3248e3ef23b..fe9171506a91 100644 --- a/drivers/net/wireless/iwlegacy/4965-calib.c +++ b/drivers/net/wireless/iwlegacy/4965-calib.c | |||
@@ -627,13 +627,13 @@ il4965_find_disconn_antenna(struct il_priv *il, u32 * average_sig, | |||
627 | 627 | ||
628 | average_sig[0] = | 628 | average_sig[0] = |
629 | data->chain_signal_a / | 629 | data->chain_signal_a / |
630 | il->cfg->base_params->chain_noise_num_beacons; | 630 | il->cfg->chain_noise_num_beacons; |
631 | average_sig[1] = | 631 | average_sig[1] = |
632 | data->chain_signal_b / | 632 | data->chain_signal_b / |
633 | il->cfg->base_params->chain_noise_num_beacons; | 633 | il->cfg->chain_noise_num_beacons; |
634 | average_sig[2] = | 634 | average_sig[2] = |
635 | data->chain_signal_c / | 635 | data->chain_signal_c / |
636 | il->cfg->base_params->chain_noise_num_beacons; | 636 | il->cfg->chain_noise_num_beacons; |
637 | 637 | ||
638 | if (average_sig[0] >= average_sig[1]) { | 638 | if (average_sig[0] >= average_sig[1]) { |
639 | max_average_sig = average_sig[0]; | 639 | max_average_sig = average_sig[0]; |
@@ -806,8 +806,6 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) | |||
806 | unsigned long flags; | 806 | unsigned long flags; |
807 | struct stats_rx_non_phy *rx_info; | 807 | struct stats_rx_non_phy *rx_info; |
808 | 808 | ||
809 | struct il_rxon_context *ctx = &il->ctx; | ||
810 | |||
811 | if (il->disable_chain_noise_cal) | 809 | if (il->disable_chain_noise_cal) |
812 | return; | 810 | return; |
813 | 811 | ||
@@ -833,8 +831,8 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) | |||
833 | return; | 831 | return; |
834 | } | 832 | } |
835 | 833 | ||
836 | rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); | 834 | rxon_band24 = !!(il->staging.flags & RXON_FLG_BAND_24G_MSK); |
837 | rxon_chnum = le16_to_cpu(ctx->staging.channel); | 835 | rxon_chnum = le16_to_cpu(il->staging.channel); |
838 | 836 | ||
839 | stat_band24 = | 837 | stat_band24 = |
840 | !!(((struct il_notif_stats *)stat_resp)-> | 838 | !!(((struct il_notif_stats *)stat_resp)-> |
@@ -888,7 +886,7 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) | |||
888 | /* If this is the "chain_noise_num_beacons", determine: | 886 | /* If this is the "chain_noise_num_beacons", determine: |
889 | * 1) Disconnected antennas (using signal strengths) | 887 | * 1) Disconnected antennas (using signal strengths) |
890 | * 2) Differential gain (using silence noise) to balance receivers */ | 888 | * 2) Differential gain (using silence noise) to balance receivers */ |
891 | if (data->beacon_count != il->cfg->base_params->chain_noise_num_beacons) | 889 | if (data->beacon_count != il->cfg->chain_noise_num_beacons) |
892 | return; | 890 | return; |
893 | 891 | ||
894 | /* Analyze signal for disconnected antenna */ | 892 | /* Analyze signal for disconnected antenna */ |
@@ -896,11 +894,11 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) | |||
896 | 894 | ||
897 | /* Analyze noise for rx balance */ | 895 | /* Analyze noise for rx balance */ |
898 | average_noise[0] = | 896 | average_noise[0] = |
899 | data->chain_noise_a / il->cfg->base_params->chain_noise_num_beacons; | 897 | data->chain_noise_a / il->cfg->chain_noise_num_beacons; |
900 | average_noise[1] = | 898 | average_noise[1] = |
901 | data->chain_noise_b / il->cfg->base_params->chain_noise_num_beacons; | 899 | data->chain_noise_b / il->cfg->chain_noise_num_beacons; |
902 | average_noise[2] = | 900 | average_noise[2] = |
903 | data->chain_noise_c / il->cfg->base_params->chain_noise_num_beacons; | 901 | data->chain_noise_c / il->cfg->chain_noise_num_beacons; |
904 | 902 | ||
905 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 903 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
906 | if (!data->disconn_array[i] && | 904 | if (!data->disconn_array[i] && |
@@ -925,8 +923,8 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) | |||
925 | /* Some power changes may have been made during the calibration. | 923 | /* Some power changes may have been made during the calibration. |
926 | * Update and commit the RXON | 924 | * Update and commit the RXON |
927 | */ | 925 | */ |
928 | if (il->cfg->ops->lib->update_chain_flags) | 926 | if (il->ops->lib->update_chain_flags) |
929 | il->cfg->ops->lib->update_chain_flags(il); | 927 | il->ops->lib->update_chain_flags(il); |
930 | 928 | ||
931 | data->state = IL_CHAIN_NOISE_DONE; | 929 | data->state = IL_CHAIN_NOISE_DONE; |
932 | il_power_update_mode(il, false); | 930 | il_power_update_mode(il, false); |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 1667232af647..235812ac6a0d 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -201,7 +201,7 @@ il4965_hw_nic_init(struct il_priv *il) | |||
201 | 201 | ||
202 | /* nic_init */ | 202 | /* nic_init */ |
203 | spin_lock_irqsave(&il->lock, flags); | 203 | spin_lock_irqsave(&il->lock, flags); |
204 | il->cfg->ops->lib->apm_ops.init(il); | 204 | il->ops->lib->apm_ops.init(il); |
205 | 205 | ||
206 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | 206 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ |
207 | il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_CALIB_TIMEOUT_DEF); | 207 | il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_CALIB_TIMEOUT_DEF); |
@@ -210,7 +210,7 @@ il4965_hw_nic_init(struct il_priv *il) | |||
210 | 210 | ||
211 | il4965_set_pwr_vmain(il); | 211 | il4965_set_pwr_vmain(il); |
212 | 212 | ||
213 | il->cfg->ops->lib->apm_ops.config(il); | 213 | il->ops->lib->apm_ops.config(il); |
214 | 214 | ||
215 | /* Allocate the RX queue, or reset if it is already allocated */ | 215 | /* Allocate the RX queue, or reset if it is already allocated */ |
216 | if (!rxq->bd) { | 216 | if (!rxq->bd) { |
@@ -843,7 +843,6 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) | |||
843 | .flags = CMD_SIZE_HUGE, | 843 | .flags = CMD_SIZE_HUGE, |
844 | }; | 844 | }; |
845 | struct il_scan_cmd *scan; | 845 | struct il_scan_cmd *scan; |
846 | struct il_rxon_context *ctx = &il->ctx; | ||
847 | u32 rate_flags = 0; | 846 | u32 rate_flags = 0; |
848 | u16 cmd_len; | 847 | u16 cmd_len; |
849 | u16 rx_chain = 0; | 848 | u16 rx_chain = 0; |
@@ -859,8 +858,6 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) | |||
859 | 858 | ||
860 | lockdep_assert_held(&il->mutex); | 859 | lockdep_assert_held(&il->mutex); |
861 | 860 | ||
862 | ctx = il_rxon_ctx_from_vif(vif); | ||
863 | |||
864 | if (!il->scan_cmd) { | 861 | if (!il->scan_cmd) { |
865 | il->scan_cmd = | 862 | il->scan_cmd = |
866 | kmalloc(sizeof(struct il_scan_cmd) + IL_MAX_SCAN_SIZE, | 863 | kmalloc(sizeof(struct il_scan_cmd) + IL_MAX_SCAN_SIZE, |
@@ -919,15 +916,14 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) | |||
919 | D_SCAN("Start passive scan.\n"); | 916 | D_SCAN("Start passive scan.\n"); |
920 | 917 | ||
921 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | 918 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; |
922 | scan->tx_cmd.sta_id = ctx->bcast_sta_id; | 919 | scan->tx_cmd.sta_id = il->hw_params.bcast_id; |
923 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 920 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
924 | 921 | ||
925 | switch (il->scan_band) { | 922 | switch (il->scan_band) { |
926 | case IEEE80211_BAND_2GHZ: | 923 | case IEEE80211_BAND_2GHZ: |
927 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; | 924 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; |
928 | chan_mod = | 925 | chan_mod = |
929 | le32_to_cpu(il->ctx.active. | 926 | le32_to_cpu(il->active.flags & RXON_FLG_CHANNEL_MODE_MSK) >> |
930 | flags & RXON_FLG_CHANNEL_MODE_MSK) >> | ||
931 | RXON_FLG_CHANNEL_MODE_POS; | 927 | RXON_FLG_CHANNEL_MODE_POS; |
932 | if (chan_mod == CHANNEL_MODE_PURE_40) { | 928 | if (chan_mod == CHANNEL_MODE_PURE_40) { |
933 | rate = RATE_6M_PLCP; | 929 | rate = RATE_6M_PLCP; |
@@ -1034,8 +1030,7 @@ il4965_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif, | |||
1034 | struct il_vif_priv *vif_priv = (void *)vif->drv_priv; | 1030 | struct il_vif_priv *vif_priv = (void *)vif->drv_priv; |
1035 | 1031 | ||
1036 | if (add) | 1032 | if (add) |
1037 | return il4965_add_bssid_station(il, vif_priv->ctx, | 1033 | return il4965_add_bssid_station(il, vif->bss_conf.bssid, |
1038 | vif->bss_conf.bssid, | ||
1039 | &vif_priv->ibss_bssid_sta_id); | 1034 | &vif_priv->ibss_bssid_sta_id); |
1040 | return il_remove_station(il, vif_priv->ibss_bssid_sta_id, | 1035 | return il_remove_station(il, vif_priv->ibss_bssid_sta_id, |
1041 | vif->bss_conf.bssid); | 1036 | vif->bss_conf.bssid); |
@@ -1128,7 +1123,7 @@ il4965_count_chain_bitmap(u32 chain_bitmap) | |||
1128 | * This should not be used for scan command ... it puts data in wrong place. | 1123 | * This should not be used for scan command ... it puts data in wrong place. |
1129 | */ | 1124 | */ |
1130 | void | 1125 | void |
1131 | il4965_set_rxon_chain(struct il_priv *il, struct il_rxon_context *ctx) | 1126 | il4965_set_rxon_chain(struct il_priv *il) |
1132 | { | 1127 | { |
1133 | bool is_single = il4965_is_single_rx_stream(il); | 1128 | bool is_single = il4965_is_single_rx_stream(il); |
1134 | bool is_cam = !test_bit(S_POWER_PMI, &il->status); | 1129 | bool is_cam = !test_bit(S_POWER_PMI, &il->status); |
@@ -1164,14 +1159,14 @@ il4965_set_rxon_chain(struct il_priv *il, struct il_rxon_context *ctx) | |||
1164 | rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; | 1159 | rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; |
1165 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; | 1160 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; |
1166 | 1161 | ||
1167 | ctx->staging.rx_chain = cpu_to_le16(rx_chain); | 1162 | il->staging.rx_chain = cpu_to_le16(rx_chain); |
1168 | 1163 | ||
1169 | if (!is_single && active_rx_cnt >= IL_NUM_RX_CHAINS_SINGLE && is_cam) | 1164 | if (!is_single && active_rx_cnt >= IL_NUM_RX_CHAINS_SINGLE && is_cam) |
1170 | ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; | 1165 | il->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; |
1171 | else | 1166 | else |
1172 | ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; | 1167 | il->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; |
1173 | 1168 | ||
1174 | D_ASSOC("rx_chain=0x%X active=%d idle=%d\n", ctx->staging.rx_chain, | 1169 | D_ASSOC("rx_chain=0x%X active=%d idle=%d\n", il->staging.rx_chain, |
1175 | active_rx_cnt, idle_rx_cnt); | 1170 | active_rx_cnt, idle_rx_cnt); |
1176 | 1171 | ||
1177 | WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || | 1172 | WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || |
@@ -1386,8 +1381,8 @@ il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) | |||
1386 | il4965_rx_calc_noise(il); | 1381 | il4965_rx_calc_noise(il); |
1387 | queue_work(il->workqueue, &il->run_time_calib_work); | 1382 | queue_work(il->workqueue, &il->run_time_calib_work); |
1388 | } | 1383 | } |
1389 | if (il->cfg->ops->lib->temp_ops.temperature && change) | 1384 | if (il->ops->lib->temp_ops.temperature && change) |
1390 | il->cfg->ops->lib->temp_ops.temperature(il); | 1385 | il->ops->lib->temp_ops.temperature(il); |
1391 | } | 1386 | } |
1392 | 1387 | ||
1393 | void | 1388 | void |
@@ -1457,10 +1452,17 @@ il4965_get_ac_from_tid(u16 tid) | |||
1457 | } | 1452 | } |
1458 | 1453 | ||
1459 | static inline int | 1454 | static inline int |
1460 | il4965_get_fifo_from_tid(struct il_rxon_context *ctx, u16 tid) | 1455 | il4965_get_fifo_from_tid(u16 tid) |
1461 | { | 1456 | { |
1457 | const u8 ac_to_fifo[] = { | ||
1458 | IL_TX_FIFO_VO, | ||
1459 | IL_TX_FIFO_VI, | ||
1460 | IL_TX_FIFO_BE, | ||
1461 | IL_TX_FIFO_BK, | ||
1462 | }; | ||
1463 | |||
1462 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | 1464 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) |
1463 | return ctx->ac_to_fifo[tid_to_ac[tid]]; | 1465 | return ac_to_fifo[tid_to_ac[tid]]; |
1464 | 1466 | ||
1465 | /* no support for TIDs 8-15 yet */ | 1467 | /* no support for TIDs 8-15 yet */ |
1466 | return -EINVAL; | 1468 | return -EINVAL; |
@@ -1639,7 +1641,6 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
1639 | struct il_device_cmd *out_cmd; | 1641 | struct il_device_cmd *out_cmd; |
1640 | struct il_cmd_meta *out_meta; | 1642 | struct il_cmd_meta *out_meta; |
1641 | struct il_tx_cmd *tx_cmd; | 1643 | struct il_tx_cmd *tx_cmd; |
1642 | struct il_rxon_context *ctx = &il->ctx; | ||
1643 | int txq_id; | 1644 | int txq_id; |
1644 | dma_addr_t phys_addr; | 1645 | dma_addr_t phys_addr; |
1645 | dma_addr_t txcmd_phys; | 1646 | dma_addr_t txcmd_phys; |
@@ -1655,9 +1656,6 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
1655 | unsigned long flags; | 1656 | unsigned long flags; |
1656 | bool is_agg = false; | 1657 | bool is_agg = false; |
1657 | 1658 | ||
1658 | if (info->control.vif) | ||
1659 | ctx = il_rxon_ctx_from_vif(info->control.vif); | ||
1660 | |||
1661 | spin_lock_irqsave(&il->lock, flags); | 1659 | spin_lock_irqsave(&il->lock, flags); |
1662 | if (il_is_rfkill(il)) { | 1660 | if (il_is_rfkill(il)) { |
1663 | D_DROP("Dropping - RF KILL\n"); | 1661 | D_DROP("Dropping - RF KILL\n"); |
@@ -1679,10 +1677,10 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
1679 | 1677 | ||
1680 | /* For management frames use broadcast id to do not break aggregation */ | 1678 | /* For management frames use broadcast id to do not break aggregation */ |
1681 | if (!ieee80211_is_data(fc)) | 1679 | if (!ieee80211_is_data(fc)) |
1682 | sta_id = ctx->bcast_sta_id; | 1680 | sta_id = il->hw_params.bcast_id; |
1683 | else { | 1681 | else { |
1684 | /* Find idx into station table for destination station */ | 1682 | /* Find idx into station table for destination station */ |
1685 | sta_id = il_sta_id_or_broadcast(il, ctx, info->control.sta); | 1683 | sta_id = il_sta_id_or_broadcast(il, info->control.sta); |
1686 | 1684 | ||
1687 | if (sta_id == IL_INVALID_STATION) { | 1685 | if (sta_id == IL_INVALID_STATION) { |
1688 | D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1); | 1686 | D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1); |
@@ -1709,19 +1707,11 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
1709 | il4965_sta_modify_sleep_tx_count(il, sta_id, 1); | 1707 | il4965_sta_modify_sleep_tx_count(il, sta_id, 1); |
1710 | } | 1708 | } |
1711 | 1709 | ||
1712 | /* | 1710 | /* FIXME: remove me ? */ |
1713 | * Send this frame after DTIM -- there's a special queue | 1711 | WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM); |
1714 | * reserved for this for contexts that support AP mode. | 1712 | |
1715 | */ | 1713 | /* Access category (AC) is also the queue number */ |
1716 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | 1714 | txq_id = skb_get_queue_mapping(skb); |
1717 | txq_id = ctx->mcast_queue; | ||
1718 | /* | ||
1719 | * The microcode will clear the more data | ||
1720 | * bit in the last frame it transmits. | ||
1721 | */ | ||
1722 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
1723 | } else | ||
1724 | txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; | ||
1725 | 1715 | ||
1726 | /* irqs already disabled/saved above when locking il->lock */ | 1716 | /* irqs already disabled/saved above when locking il->lock */ |
1727 | spin_lock(&il->sta_lock); | 1717 | spin_lock(&il->sta_lock); |
@@ -1763,10 +1753,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
1763 | 1753 | ||
1764 | spin_unlock(&il->sta_lock); | 1754 | spin_unlock(&il->sta_lock); |
1765 | 1755 | ||
1766 | /* Set up driver data for this TFD */ | 1756 | txq->skbs[q->write_ptr] = skb; |
1767 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info)); | ||
1768 | txq->txb[q->write_ptr].skb = skb; | ||
1769 | txq->txb[q->write_ptr].ctx = ctx; | ||
1770 | 1757 | ||
1771 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | 1758 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ |
1772 | out_cmd = txq->cmd[q->write_ptr]; | 1759 | out_cmd = txq->cmd[q->write_ptr]; |
@@ -1828,8 +1815,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
1828 | dma_unmap_len_set(out_meta, len, firstlen); | 1815 | dma_unmap_len_set(out_meta, len, firstlen); |
1829 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 1816 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
1830 | * first entry */ | 1817 | * first entry */ |
1831 | il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, | 1818 | il->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0); |
1832 | 1, 0); | ||
1833 | 1819 | ||
1834 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 1820 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
1835 | txq->need_update = 1; | 1821 | txq->need_update = 1; |
@@ -1845,8 +1831,8 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
1845 | phys_addr = | 1831 | phys_addr = |
1846 | pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen, | 1832 | pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen, |
1847 | PCI_DMA_TODEVICE); | 1833 | PCI_DMA_TODEVICE); |
1848 | il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, | 1834 | il->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, |
1849 | secondlen, 0, 0); | 1835 | secondlen, 0, 0); |
1850 | } | 1836 | } |
1851 | 1837 | ||
1852 | scratch_phys = | 1838 | scratch_phys = |
@@ -1866,9 +1852,8 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) | |||
1866 | 1852 | ||
1867 | /* Set up entry for this TFD in Tx byte-count array */ | 1853 | /* Set up entry for this TFD in Tx byte-count array */ |
1868 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 1854 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
1869 | il->cfg->ops->lib->txq_update_byte_cnt_tbl(il, txq, | 1855 | il->ops->lib->txq_update_byte_cnt_tbl(il, txq, |
1870 | le16_to_cpu(tx_cmd-> | 1856 | le16_to_cpu(tx_cmd->len)); |
1871 | len)); | ||
1872 | 1857 | ||
1873 | pci_dma_sync_single_for_device(il->pci_dev, txcmd_phys, firstlen, | 1858 | pci_dma_sync_single_for_device(il->pci_dev, txcmd_phys, firstlen, |
1874 | PCI_DMA_BIDIRECTIONAL); | 1859 | PCI_DMA_BIDIRECTIONAL); |
@@ -2163,11 +2148,11 @@ il4965_txq_agg_enable(struct il_priv *il, int txq_id, int tx_fifo, int sta_id, | |||
2163 | 2148 | ||
2164 | if ((IL49_FIRST_AMPDU_QUEUE > txq_id) || | 2149 | if ((IL49_FIRST_AMPDU_QUEUE > txq_id) || |
2165 | (IL49_FIRST_AMPDU_QUEUE + | 2150 | (IL49_FIRST_AMPDU_QUEUE + |
2166 | il->cfg->base_params->num_of_ampdu_queues <= txq_id)) { | 2151 | il->cfg->num_of_ampdu_queues <= txq_id)) { |
2167 | IL_WARN("queue number out of range: %d, must be %d to %d\n", | 2152 | IL_WARN("queue number out of range: %d, must be %d to %d\n", |
2168 | txq_id, IL49_FIRST_AMPDU_QUEUE, | 2153 | txq_id, IL49_FIRST_AMPDU_QUEUE, |
2169 | IL49_FIRST_AMPDU_QUEUE + | 2154 | IL49_FIRST_AMPDU_QUEUE + |
2170 | il->cfg->base_params->num_of_ampdu_queues - 1); | 2155 | il->cfg->num_of_ampdu_queues - 1); |
2171 | return -EINVAL; | 2156 | return -EINVAL; |
2172 | } | 2157 | } |
2173 | 2158 | ||
@@ -2230,7 +2215,8 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif, | |||
2230 | unsigned long flags; | 2215 | unsigned long flags; |
2231 | struct il_tid_data *tid_data; | 2216 | struct il_tid_data *tid_data; |
2232 | 2217 | ||
2233 | tx_fifo = il4965_get_fifo_from_tid(il_rxon_ctx_from_vif(vif), tid); | 2218 | /* FIXME: warning if tx fifo not found ? */ |
2219 | tx_fifo = il4965_get_fifo_from_tid(tid); | ||
2234 | if (unlikely(tx_fifo < 0)) | 2220 | if (unlikely(tx_fifo < 0)) |
2235 | return tx_fifo; | 2221 | return tx_fifo; |
2236 | 2222 | ||
@@ -2290,11 +2276,11 @@ il4965_txq_agg_disable(struct il_priv *il, u16 txq_id, u16 ssn_idx, u8 tx_fifo) | |||
2290 | { | 2276 | { |
2291 | if ((IL49_FIRST_AMPDU_QUEUE > txq_id) || | 2277 | if ((IL49_FIRST_AMPDU_QUEUE > txq_id) || |
2292 | (IL49_FIRST_AMPDU_QUEUE + | 2278 | (IL49_FIRST_AMPDU_QUEUE + |
2293 | il->cfg->base_params->num_of_ampdu_queues <= txq_id)) { | 2279 | il->cfg->num_of_ampdu_queues <= txq_id)) { |
2294 | IL_WARN("queue number out of range: %d, must be %d to %d\n", | 2280 | IL_WARN("queue number out of range: %d, must be %d to %d\n", |
2295 | txq_id, IL49_FIRST_AMPDU_QUEUE, | 2281 | txq_id, IL49_FIRST_AMPDU_QUEUE, |
2296 | IL49_FIRST_AMPDU_QUEUE + | 2282 | IL49_FIRST_AMPDU_QUEUE + |
2297 | il->cfg->base_params->num_of_ampdu_queues - 1); | 2283 | il->cfg->num_of_ampdu_queues - 1); |
2298 | return -EINVAL; | 2284 | return -EINVAL; |
2299 | } | 2285 | } |
2300 | 2286 | ||
@@ -2323,7 +2309,8 @@ il4965_tx_agg_stop(struct il_priv *il, struct ieee80211_vif *vif, | |||
2323 | int write_ptr, read_ptr; | 2309 | int write_ptr, read_ptr; |
2324 | unsigned long flags; | 2310 | unsigned long flags; |
2325 | 2311 | ||
2326 | tx_fifo_id = il4965_get_fifo_from_tid(il_rxon_ctx_from_vif(vif), tid); | 2312 | /* FIXME: warning if tx_fifo_id not found ? */ |
2313 | tx_fifo_id = il4965_get_fifo_from_tid(tid); | ||
2327 | if (unlikely(tx_fifo_id < 0)) | 2314 | if (unlikely(tx_fifo_id < 0)) |
2328 | return tx_fifo_id; | 2315 | return tx_fifo_id; |
2329 | 2316 | ||
@@ -2397,9 +2384,6 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) | |||
2397 | struct il_queue *q = &il->txq[txq_id].q; | 2384 | struct il_queue *q = &il->txq[txq_id].q; |
2398 | u8 *addr = il->stations[sta_id].sta.sta.addr; | 2385 | u8 *addr = il->stations[sta_id].sta.sta.addr; |
2399 | struct il_tid_data *tid_data = &il->stations[sta_id].tid[tid]; | 2386 | struct il_tid_data *tid_data = &il->stations[sta_id].tid[tid]; |
2400 | struct il_rxon_context *ctx; | ||
2401 | |||
2402 | ctx = &il->ctx; | ||
2403 | 2387 | ||
2404 | lockdep_assert_held(&il->sta_lock); | 2388 | lockdep_assert_held(&il->sta_lock); |
2405 | 2389 | ||
@@ -2410,11 +2394,11 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) | |||
2410 | if (txq_id == tid_data->agg.txq_id && | 2394 | if (txq_id == tid_data->agg.txq_id && |
2411 | q->read_ptr == q->write_ptr) { | 2395 | q->read_ptr == q->write_ptr) { |
2412 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | 2396 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); |
2413 | int tx_fifo = il4965_get_fifo_from_tid(ctx, tid); | 2397 | int tx_fifo = il4965_get_fifo_from_tid(tid); |
2414 | D_HT("HW queue empty: continue DELBA flow\n"); | 2398 | D_HT("HW queue empty: continue DELBA flow\n"); |
2415 | il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo); | 2399 | il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo); |
2416 | tid_data->agg.state = IL_AGG_OFF; | 2400 | tid_data->agg.state = IL_AGG_OFF; |
2417 | ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); | 2401 | ieee80211_stop_tx_ba_cb_irqsafe(il->vif, addr, tid); |
2418 | } | 2402 | } |
2419 | break; | 2403 | break; |
2420 | case IL_EMPTYING_HW_QUEUE_ADDBA: | 2404 | case IL_EMPTYING_HW_QUEUE_ADDBA: |
@@ -2422,7 +2406,7 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) | |||
2422 | if (tid_data->tfds_in_queue == 0) { | 2406 | if (tid_data->tfds_in_queue == 0) { |
2423 | D_HT("HW queue empty: continue ADDBA flow\n"); | 2407 | D_HT("HW queue empty: continue ADDBA flow\n"); |
2424 | tid_data->agg.state = IL_AGG_ON; | 2408 | tid_data->agg.state = IL_AGG_ON; |
2425 | ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid); | 2409 | ieee80211_start_tx_ba_cb_irqsafe(il->vif, addr, tid); |
2426 | } | 2410 | } |
2427 | break; | 2411 | break; |
2428 | } | 2412 | } |
@@ -2431,14 +2415,13 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) | |||
2431 | } | 2415 | } |
2432 | 2416 | ||
2433 | static void | 2417 | static void |
2434 | il4965_non_agg_tx_status(struct il_priv *il, struct il_rxon_context *ctx, | 2418 | il4965_non_agg_tx_status(struct il_priv *il, const u8 *addr1) |
2435 | const u8 *addr1) | ||
2436 | { | 2419 | { |
2437 | struct ieee80211_sta *sta; | 2420 | struct ieee80211_sta *sta; |
2438 | struct il_station_priv *sta_priv; | 2421 | struct il_station_priv *sta_priv; |
2439 | 2422 | ||
2440 | rcu_read_lock(); | 2423 | rcu_read_lock(); |
2441 | sta = ieee80211_find_sta(ctx->vif, addr1); | 2424 | sta = ieee80211_find_sta(il->vif, addr1); |
2442 | if (sta) { | 2425 | if (sta) { |
2443 | sta_priv = (void *)sta->drv_priv; | 2426 | sta_priv = (void *)sta->drv_priv; |
2444 | /* avoid atomic ops if this isn't a client */ | 2427 | /* avoid atomic ops if this isn't a client */ |
@@ -2450,14 +2433,14 @@ il4965_non_agg_tx_status(struct il_priv *il, struct il_rxon_context *ctx, | |||
2450 | } | 2433 | } |
2451 | 2434 | ||
2452 | static void | 2435 | static void |
2453 | il4965_tx_status(struct il_priv *il, struct il_tx_info *tx_info, bool is_agg) | 2436 | il4965_tx_status(struct il_priv *il, struct sk_buff *skb, bool is_agg) |
2454 | { | 2437 | { |
2455 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; | 2438 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
2456 | 2439 | ||
2457 | if (!is_agg) | 2440 | if (!is_agg) |
2458 | il4965_non_agg_tx_status(il, tx_info->ctx, hdr->addr1); | 2441 | il4965_non_agg_tx_status(il, hdr->addr1); |
2459 | 2442 | ||
2460 | ieee80211_tx_status_irqsafe(il->hw, tx_info->skb); | 2443 | ieee80211_tx_status_irqsafe(il->hw, skb); |
2461 | } | 2444 | } |
2462 | 2445 | ||
2463 | int | 2446 | int |
@@ -2465,9 +2448,9 @@ il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) | |||
2465 | { | 2448 | { |
2466 | struct il_tx_queue *txq = &il->txq[txq_id]; | 2449 | struct il_tx_queue *txq = &il->txq[txq_id]; |
2467 | struct il_queue *q = &txq->q; | 2450 | struct il_queue *q = &txq->q; |
2468 | struct il_tx_info *tx_info; | ||
2469 | int nfreed = 0; | 2451 | int nfreed = 0; |
2470 | struct ieee80211_hdr *hdr; | 2452 | struct ieee80211_hdr *hdr; |
2453 | struct sk_buff *skb; | ||
2471 | 2454 | ||
2472 | if (idx >= q->n_bd || il_queue_used(q, idx) == 0) { | 2455 | if (idx >= q->n_bd || il_queue_used(q, idx) == 0) { |
2473 | IL_ERR("Read idx for DMA queue txq id (%d), idx %d, " | 2456 | IL_ERR("Read idx for DMA queue txq id (%d), idx %d, " |
@@ -2479,20 +2462,19 @@ il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) | |||
2479 | for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; | 2462 | for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; |
2480 | q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 2463 | q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
2481 | 2464 | ||
2482 | tx_info = &txq->txb[txq->q.read_ptr]; | 2465 | skb = txq->skbs[txq->q.read_ptr]; |
2483 | 2466 | ||
2484 | if (WARN_ON_ONCE(tx_info->skb == NULL)) | 2467 | if (WARN_ON_ONCE(skb == NULL)) |
2485 | continue; | 2468 | continue; |
2486 | 2469 | ||
2487 | hdr = (struct ieee80211_hdr *)tx_info->skb->data; | 2470 | hdr = (struct ieee80211_hdr *) skb->data; |
2488 | if (ieee80211_is_data_qos(hdr->frame_control)) | 2471 | if (ieee80211_is_data_qos(hdr->frame_control)) |
2489 | nfreed++; | 2472 | nfreed++; |
2490 | 2473 | ||
2491 | il4965_tx_status(il, tx_info, | 2474 | il4965_tx_status(il, skb, txq_id >= IL4965_FIRST_AMPDU_QUEUE); |
2492 | txq_id >= IL4965_FIRST_AMPDU_QUEUE); | ||
2493 | tx_info->skb = NULL; | ||
2494 | 2475 | ||
2495 | il->cfg->ops->lib->txq_free_tfd(il, txq); | 2476 | txq->skbs[txq->q.read_ptr] = NULL; |
2477 | il->ops->lib->txq_free_tfd(il, txq); | ||
2496 | } | 2478 | } |
2497 | return nfreed; | 2479 | return nfreed; |
2498 | } | 2480 | } |
@@ -2555,7 +2537,7 @@ il4965_tx_status_reply_compressed_ba(struct il_priv *il, struct il_ht_agg *agg, | |||
2555 | 2537 | ||
2556 | D_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); | 2538 | D_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); |
2557 | 2539 | ||
2558 | info = IEEE80211_SKB_CB(il->txq[scd_flow].txb[agg->start_idx].skb); | 2540 | info = IEEE80211_SKB_CB(il->txq[scd_flow].skbs[agg->start_idx]); |
2559 | memset(&info->status, 0, sizeof(info->status)); | 2541 | memset(&info->status, 0, sizeof(info->status)); |
2560 | info->flags |= IEEE80211_TX_STAT_ACK; | 2542 | info->flags |= IEEE80211_TX_STAT_ACK; |
2561 | info->flags |= IEEE80211_TX_STAT_AMPDU; | 2543 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
@@ -2771,8 +2753,7 @@ il4965_sta_alloc_lq(struct il_priv *il, u8 sta_id) | |||
2771 | * Function sleeps. | 2753 | * Function sleeps. |
2772 | */ | 2754 | */ |
2773 | int | 2755 | int |
2774 | il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, | 2756 | il4965_add_bssid_station(struct il_priv *il, const u8 *addr, u8 *sta_id_r) |
2775 | const u8 *addr, u8 *sta_id_r) | ||
2776 | { | 2757 | { |
2777 | int ret; | 2758 | int ret; |
2778 | u8 sta_id; | 2759 | u8 sta_id; |
@@ -2782,7 +2763,7 @@ il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, | |||
2782 | if (sta_id_r) | 2763 | if (sta_id_r) |
2783 | *sta_id_r = IL_INVALID_STATION; | 2764 | *sta_id_r = IL_INVALID_STATION; |
2784 | 2765 | ||
2785 | ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id); | 2766 | ret = il_add_station_common(il, addr, 0, NULL, &sta_id); |
2786 | if (ret) { | 2767 | if (ret) { |
2787 | IL_ERR("Unable to add station %pM\n", addr); | 2768 | IL_ERR("Unable to add station %pM\n", addr); |
2788 | return ret; | 2769 | return ret; |
@@ -2803,7 +2784,7 @@ il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, | |||
2803 | return -ENOMEM; | 2784 | return -ENOMEM; |
2804 | } | 2785 | } |
2805 | 2786 | ||
2806 | ret = il_send_lq_cmd(il, ctx, link_cmd, CMD_SYNC, true); | 2787 | ret = il_send_lq_cmd(il, link_cmd, CMD_SYNC, true); |
2807 | if (ret) | 2788 | if (ret) |
2808 | IL_ERR("Link quality command failed (%d)\n", ret); | 2789 | IL_ERR("Link quality command failed (%d)\n", ret); |
2809 | 2790 | ||
@@ -2815,19 +2796,19 @@ il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, | |||
2815 | } | 2796 | } |
2816 | 2797 | ||
2817 | static int | 2798 | static int |
2818 | il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx, | 2799 | il4965_static_wepkey_cmd(struct il_priv *il, bool send_if_empty) |
2819 | bool send_if_empty) | ||
2820 | { | 2800 | { |
2821 | int i, not_empty = 0; | 2801 | int i; |
2822 | u8 buff[sizeof(struct il_wep_cmd) + | 2802 | u8 buff[sizeof(struct il_wep_cmd) + |
2823 | sizeof(struct il_wep_key) * WEP_KEYS_MAX]; | 2803 | sizeof(struct il_wep_key) * WEP_KEYS_MAX]; |
2824 | struct il_wep_cmd *wep_cmd = (struct il_wep_cmd *)buff; | 2804 | struct il_wep_cmd *wep_cmd = (struct il_wep_cmd *)buff; |
2825 | size_t cmd_size = sizeof(struct il_wep_cmd); | 2805 | size_t cmd_size = sizeof(struct il_wep_cmd); |
2826 | struct il_host_cmd cmd = { | 2806 | struct il_host_cmd cmd = { |
2827 | .id = ctx->wep_key_cmd, | 2807 | .id = C_WEPKEY, |
2828 | .data = wep_cmd, | 2808 | .data = wep_cmd, |
2829 | .flags = CMD_SYNC, | 2809 | .flags = CMD_SYNC, |
2830 | }; | 2810 | }; |
2811 | bool not_empty = false; | ||
2831 | 2812 | ||
2832 | might_sleep(); | 2813 | might_sleep(); |
2833 | 2814 | ||
@@ -2835,24 +2816,23 @@ il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx, | |||
2835 | cmd_size + (sizeof(struct il_wep_key) * WEP_KEYS_MAX)); | 2816 | cmd_size + (sizeof(struct il_wep_key) * WEP_KEYS_MAX)); |
2836 | 2817 | ||
2837 | for (i = 0; i < WEP_KEYS_MAX; i++) { | 2818 | for (i = 0; i < WEP_KEYS_MAX; i++) { |
2819 | u8 key_size = il->_4965.wep_keys[i].key_size; | ||
2820 | |||
2838 | wep_cmd->key[i].key_idx = i; | 2821 | wep_cmd->key[i].key_idx = i; |
2839 | if (ctx->wep_keys[i].key_size) { | 2822 | if (key_size) { |
2840 | wep_cmd->key[i].key_offset = i; | 2823 | wep_cmd->key[i].key_offset = i; |
2841 | not_empty = 1; | 2824 | not_empty = true; |
2842 | } else { | 2825 | } else |
2843 | wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; | 2826 | wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; |
2844 | } | ||
2845 | 2827 | ||
2846 | wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size; | 2828 | wep_cmd->key[i].key_size = key_size; |
2847 | memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key, | 2829 | memcpy(&wep_cmd->key[i].key[3], il->_4965.wep_keys[i].key, key_size); |
2848 | ctx->wep_keys[i].key_size); | ||
2849 | } | 2830 | } |
2850 | 2831 | ||
2851 | wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; | 2832 | wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; |
2852 | wep_cmd->num_keys = WEP_KEYS_MAX; | 2833 | wep_cmd->num_keys = WEP_KEYS_MAX; |
2853 | 2834 | ||
2854 | cmd_size += sizeof(struct il_wep_key) * WEP_KEYS_MAX; | 2835 | cmd_size += sizeof(struct il_wep_key) * WEP_KEYS_MAX; |
2855 | |||
2856 | cmd.len = cmd_size; | 2836 | cmd.len = cmd_size; |
2857 | 2837 | ||
2858 | if (not_empty || send_if_empty) | 2838 | if (not_empty || send_if_empty) |
@@ -2862,66 +2842,66 @@ il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx, | |||
2862 | } | 2842 | } |
2863 | 2843 | ||
2864 | int | 2844 | int |
2865 | il4965_restore_default_wep_keys(struct il_priv *il, struct il_rxon_context *ctx) | 2845 | il4965_restore_default_wep_keys(struct il_priv *il) |
2866 | { | 2846 | { |
2867 | lockdep_assert_held(&il->mutex); | 2847 | lockdep_assert_held(&il->mutex); |
2868 | 2848 | ||
2869 | return il4965_static_wepkey_cmd(il, ctx, false); | 2849 | return il4965_static_wepkey_cmd(il, false); |
2870 | } | 2850 | } |
2871 | 2851 | ||
2872 | int | 2852 | int |
2873 | il4965_remove_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, | 2853 | il4965_remove_default_wep_key(struct il_priv *il, |
2874 | struct ieee80211_key_conf *keyconf) | 2854 | struct ieee80211_key_conf *keyconf) |
2875 | { | 2855 | { |
2876 | int ret; | 2856 | int ret; |
2857 | int idx = keyconf->keyidx; | ||
2877 | 2858 | ||
2878 | lockdep_assert_held(&il->mutex); | 2859 | lockdep_assert_held(&il->mutex); |
2879 | 2860 | ||
2880 | D_WEP("Removing default WEP key: idx=%d\n", keyconf->keyidx); | 2861 | D_WEP("Removing default WEP key: idx=%d\n", idx); |
2881 | 2862 | ||
2882 | memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); | 2863 | memset(&il->_4965.wep_keys[idx], 0, sizeof(struct il_wep_key)); |
2883 | if (il_is_rfkill(il)) { | 2864 | if (il_is_rfkill(il)) { |
2884 | D_WEP("Not sending C_WEPKEY command due to RFKILL.\n"); | 2865 | D_WEP("Not sending C_WEPKEY command due to RFKILL.\n"); |
2885 | /* but keys in device are clear anyway so return success */ | 2866 | /* but keys in device are clear anyway so return success */ |
2886 | return 0; | 2867 | return 0; |
2887 | } | 2868 | } |
2888 | ret = il4965_static_wepkey_cmd(il, ctx, 1); | 2869 | ret = il4965_static_wepkey_cmd(il, 1); |
2889 | D_WEP("Remove default WEP key: idx=%d ret=%d\n", keyconf->keyidx, ret); | 2870 | D_WEP("Remove default WEP key: idx=%d ret=%d\n", idx, ret); |
2890 | 2871 | ||
2891 | return ret; | 2872 | return ret; |
2892 | } | 2873 | } |
2893 | 2874 | ||
2894 | int | 2875 | int |
2895 | il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, | 2876 | il4965_set_default_wep_key(struct il_priv *il, |
2896 | struct ieee80211_key_conf *keyconf) | 2877 | struct ieee80211_key_conf *keyconf) |
2897 | { | 2878 | { |
2898 | int ret; | 2879 | int ret; |
2880 | int len = keyconf->keylen; | ||
2881 | int idx = keyconf->keyidx; | ||
2899 | 2882 | ||
2900 | lockdep_assert_held(&il->mutex); | 2883 | lockdep_assert_held(&il->mutex); |
2901 | 2884 | ||
2902 | if (keyconf->keylen != WEP_KEY_LEN_128 && | 2885 | if (len != WEP_KEY_LEN_128 && len != WEP_KEY_LEN_64) { |
2903 | keyconf->keylen != WEP_KEY_LEN_64) { | ||
2904 | D_WEP("Bad WEP key length %d\n", keyconf->keylen); | 2886 | D_WEP("Bad WEP key length %d\n", keyconf->keylen); |
2905 | return -EINVAL; | 2887 | return -EINVAL; |
2906 | } | 2888 | } |
2907 | 2889 | ||
2908 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; | 2890 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; |
2909 | keyconf->hw_key_idx = HW_KEY_DEFAULT; | 2891 | keyconf->hw_key_idx = HW_KEY_DEFAULT; |
2910 | il->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; | 2892 | il->stations[IL_AP_ID].keyinfo.cipher = keyconf->cipher; |
2911 | 2893 | ||
2912 | ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; | 2894 | il->_4965.wep_keys[idx].key_size = len; |
2913 | memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, | 2895 | memcpy(&il->_4965.wep_keys[idx].key, &keyconf->key, len); |
2914 | keyconf->keylen); | ||
2915 | 2896 | ||
2916 | ret = il4965_static_wepkey_cmd(il, ctx, false); | 2897 | ret = il4965_static_wepkey_cmd(il, false); |
2917 | D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", keyconf->keylen, | ||
2918 | keyconf->keyidx, ret); | ||
2919 | 2898 | ||
2899 | D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", len, idx, ret); | ||
2920 | return ret; | 2900 | return ret; |
2921 | } | 2901 | } |
2922 | 2902 | ||
2923 | static int | 2903 | static int |
2924 | il4965_set_wep_dynamic_key_info(struct il_priv *il, struct il_rxon_context *ctx, | 2904 | il4965_set_wep_dynamic_key_info(struct il_priv *il, |
2925 | struct ieee80211_key_conf *keyconf, u8 sta_id) | 2905 | struct ieee80211_key_conf *keyconf, u8 sta_id) |
2926 | { | 2906 | { |
2927 | unsigned long flags; | 2907 | unsigned long flags; |
@@ -2939,7 +2919,7 @@ il4965_set_wep_dynamic_key_info(struct il_priv *il, struct il_rxon_context *ctx, | |||
2939 | if (keyconf->keylen == WEP_KEY_LEN_128) | 2919 | if (keyconf->keylen == WEP_KEY_LEN_128) |
2940 | key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; | 2920 | key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; |
2941 | 2921 | ||
2942 | if (sta_id == ctx->bcast_sta_id) | 2922 | if (sta_id == il->hw_params.bcast_id) |
2943 | key_flags |= STA_KEY_MULTICAST_MSK; | 2923 | key_flags |= STA_KEY_MULTICAST_MSK; |
2944 | 2924 | ||
2945 | spin_lock_irqsave(&il->sta_lock, flags); | 2925 | spin_lock_irqsave(&il->sta_lock, flags); |
@@ -2976,7 +2956,6 @@ il4965_set_wep_dynamic_key_info(struct il_priv *il, struct il_rxon_context *ctx, | |||
2976 | 2956 | ||
2977 | static int | 2957 | static int |
2978 | il4965_set_ccmp_dynamic_key_info(struct il_priv *il, | 2958 | il4965_set_ccmp_dynamic_key_info(struct il_priv *il, |
2979 | struct il_rxon_context *ctx, | ||
2980 | struct ieee80211_key_conf *keyconf, u8 sta_id) | 2959 | struct ieee80211_key_conf *keyconf, u8 sta_id) |
2981 | { | 2960 | { |
2982 | unsigned long flags; | 2961 | unsigned long flags; |
@@ -2989,7 +2968,7 @@ il4965_set_ccmp_dynamic_key_info(struct il_priv *il, | |||
2989 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | 2968 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); |
2990 | key_flags &= ~STA_KEY_FLG_INVALID; | 2969 | key_flags &= ~STA_KEY_FLG_INVALID; |
2991 | 2970 | ||
2992 | if (sta_id == ctx->bcast_sta_id) | 2971 | if (sta_id == il->hw_params.bcast_id) |
2993 | key_flags |= STA_KEY_MULTICAST_MSK; | 2972 | key_flags |= STA_KEY_MULTICAST_MSK; |
2994 | 2973 | ||
2995 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 2974 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
@@ -3025,7 +3004,6 @@ il4965_set_ccmp_dynamic_key_info(struct il_priv *il, | |||
3025 | 3004 | ||
3026 | static int | 3005 | static int |
3027 | il4965_set_tkip_dynamic_key_info(struct il_priv *il, | 3006 | il4965_set_tkip_dynamic_key_info(struct il_priv *il, |
3028 | struct il_rxon_context *ctx, | ||
3029 | struct ieee80211_key_conf *keyconf, u8 sta_id) | 3007 | struct ieee80211_key_conf *keyconf, u8 sta_id) |
3030 | { | 3008 | { |
3031 | unsigned long flags; | 3009 | unsigned long flags; |
@@ -3036,7 +3014,7 @@ il4965_set_tkip_dynamic_key_info(struct il_priv *il, | |||
3036 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | 3014 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); |
3037 | key_flags &= ~STA_KEY_FLG_INVALID; | 3015 | key_flags &= ~STA_KEY_FLG_INVALID; |
3038 | 3016 | ||
3039 | if (sta_id == ctx->bcast_sta_id) | 3017 | if (sta_id == il->hw_params.bcast_id) |
3040 | key_flags |= STA_KEY_MULTICAST_MSK; | 3018 | key_flags |= STA_KEY_MULTICAST_MSK; |
3041 | 3019 | ||
3042 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 3020 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
@@ -3070,9 +3048,8 @@ il4965_set_tkip_dynamic_key_info(struct il_priv *il, | |||
3070 | } | 3048 | } |
3071 | 3049 | ||
3072 | void | 3050 | void |
3073 | il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx, | 3051 | il4965_update_tkip_key(struct il_priv *il, struct ieee80211_key_conf *keyconf, |
3074 | struct ieee80211_key_conf *keyconf, | 3052 | struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) |
3075 | struct ieee80211_sta *sta, u32 iv32, u16 * phase1key) | ||
3076 | { | 3053 | { |
3077 | u8 sta_id; | 3054 | u8 sta_id; |
3078 | unsigned long flags; | 3055 | unsigned long flags; |
@@ -3084,7 +3061,7 @@ il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx, | |||
3084 | return; | 3061 | return; |
3085 | } | 3062 | } |
3086 | 3063 | ||
3087 | sta_id = il_sta_id_or_broadcast(il, ctx, sta); | 3064 | sta_id = il_sta_id_or_broadcast(il, sta); |
3088 | if (sta_id == IL_INVALID_STATION) | 3065 | if (sta_id == IL_INVALID_STATION) |
3089 | return; | 3066 | return; |
3090 | 3067 | ||
@@ -3102,11 +3079,10 @@ il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx, | |||
3102 | il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC); | 3079 | il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC); |
3103 | 3080 | ||
3104 | spin_unlock_irqrestore(&il->sta_lock, flags); | 3081 | spin_unlock_irqrestore(&il->sta_lock, flags); |
3105 | |||
3106 | } | 3082 | } |
3107 | 3083 | ||
3108 | int | 3084 | int |
3109 | il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, | 3085 | il4965_remove_dynamic_key(struct il_priv *il, |
3110 | struct ieee80211_key_conf *keyconf, u8 sta_id) | 3086 | struct ieee80211_key_conf *keyconf, u8 sta_id) |
3111 | { | 3087 | { |
3112 | unsigned long flags; | 3088 | unsigned long flags; |
@@ -3116,7 +3092,7 @@ il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, | |||
3116 | 3092 | ||
3117 | lockdep_assert_held(&il->mutex); | 3093 | lockdep_assert_held(&il->mutex); |
3118 | 3094 | ||
3119 | ctx->key_mapping_keys--; | 3095 | il->_4965.key_mapping_keys--; |
3120 | 3096 | ||
3121 | spin_lock_irqsave(&il->sta_lock, flags); | 3097 | spin_lock_irqsave(&il->sta_lock, flags); |
3122 | key_flags = le16_to_cpu(il->stations[sta_id].sta.key.key_flags); | 3098 | key_flags = le16_to_cpu(il->stations[sta_id].sta.key.key_flags); |
@@ -3167,28 +3143,28 @@ il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, | |||
3167 | } | 3143 | } |
3168 | 3144 | ||
3169 | int | 3145 | int |
3170 | il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, | 3146 | il4965_set_dynamic_key(struct il_priv *il, struct ieee80211_key_conf *keyconf, |
3171 | struct ieee80211_key_conf *keyconf, u8 sta_id) | 3147 | u8 sta_id) |
3172 | { | 3148 | { |
3173 | int ret; | 3149 | int ret; |
3174 | 3150 | ||
3175 | lockdep_assert_held(&il->mutex); | 3151 | lockdep_assert_held(&il->mutex); |
3176 | 3152 | ||
3177 | ctx->key_mapping_keys++; | 3153 | il->_4965.key_mapping_keys++; |
3178 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; | 3154 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; |
3179 | 3155 | ||
3180 | switch (keyconf->cipher) { | 3156 | switch (keyconf->cipher) { |
3181 | case WLAN_CIPHER_SUITE_CCMP: | 3157 | case WLAN_CIPHER_SUITE_CCMP: |
3182 | ret = | 3158 | ret = |
3183 | il4965_set_ccmp_dynamic_key_info(il, ctx, keyconf, sta_id); | 3159 | il4965_set_ccmp_dynamic_key_info(il, keyconf, sta_id); |
3184 | break; | 3160 | break; |
3185 | case WLAN_CIPHER_SUITE_TKIP: | 3161 | case WLAN_CIPHER_SUITE_TKIP: |
3186 | ret = | 3162 | ret = |
3187 | il4965_set_tkip_dynamic_key_info(il, ctx, keyconf, sta_id); | 3163 | il4965_set_tkip_dynamic_key_info(il, keyconf, sta_id); |
3188 | break; | 3164 | break; |
3189 | case WLAN_CIPHER_SUITE_WEP40: | 3165 | case WLAN_CIPHER_SUITE_WEP40: |
3190 | case WLAN_CIPHER_SUITE_WEP104: | 3166 | case WLAN_CIPHER_SUITE_WEP104: |
3191 | ret = il4965_set_wep_dynamic_key_info(il, ctx, keyconf, sta_id); | 3167 | ret = il4965_set_wep_dynamic_key_info(il, keyconf, sta_id); |
3192 | break; | 3168 | break; |
3193 | default: | 3169 | default: |
3194 | IL_ERR("Unknown alg: %s cipher = %x\n", __func__, | 3170 | IL_ERR("Unknown alg: %s cipher = %x\n", __func__, |
@@ -3210,14 +3186,14 @@ il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, | |||
3210 | * device at the next best time. | 3186 | * device at the next best time. |
3211 | */ | 3187 | */ |
3212 | int | 3188 | int |
3213 | il4965_alloc_bcast_station(struct il_priv *il, struct il_rxon_context *ctx) | 3189 | il4965_alloc_bcast_station(struct il_priv *il) |
3214 | { | 3190 | { |
3215 | struct il_link_quality_cmd *link_cmd; | 3191 | struct il_link_quality_cmd *link_cmd; |
3216 | unsigned long flags; | 3192 | unsigned long flags; |
3217 | u8 sta_id; | 3193 | u8 sta_id; |
3218 | 3194 | ||
3219 | spin_lock_irqsave(&il->sta_lock, flags); | 3195 | spin_lock_irqsave(&il->sta_lock, flags); |
3220 | sta_id = il_prep_station(il, ctx, il_bcast_addr, false, NULL); | 3196 | sta_id = il_prep_station(il, il_bcast_addr, false, NULL); |
3221 | if (sta_id == IL_INVALID_STATION) { | 3197 | if (sta_id == IL_INVALID_STATION) { |
3222 | IL_ERR("Unable to prepare broadcast station\n"); | 3198 | IL_ERR("Unable to prepare broadcast station\n"); |
3223 | spin_unlock_irqrestore(&il->sta_lock, flags); | 3199 | spin_unlock_irqrestore(&il->sta_lock, flags); |
@@ -3250,11 +3226,11 @@ il4965_alloc_bcast_station(struct il_priv *il, struct il_rxon_context *ctx) | |||
3250 | * code together. | 3226 | * code together. |
3251 | */ | 3227 | */ |
3252 | static int | 3228 | static int |
3253 | il4965_update_bcast_station(struct il_priv *il, struct il_rxon_context *ctx) | 3229 | il4965_update_bcast_station(struct il_priv *il) |
3254 | { | 3230 | { |
3255 | unsigned long flags; | 3231 | unsigned long flags; |
3256 | struct il_link_quality_cmd *link_cmd; | 3232 | struct il_link_quality_cmd *link_cmd; |
3257 | u8 sta_id = ctx->bcast_sta_id; | 3233 | u8 sta_id = il->hw_params.bcast_id; |
3258 | 3234 | ||
3259 | link_cmd = il4965_sta_alloc_lq(il, sta_id); | 3235 | link_cmd = il4965_sta_alloc_lq(il, sta_id); |
3260 | if (!link_cmd) { | 3236 | if (!link_cmd) { |
@@ -3276,7 +3252,7 @@ il4965_update_bcast_station(struct il_priv *il, struct il_rxon_context *ctx) | |||
3276 | int | 3252 | int |
3277 | il4965_update_bcast_stations(struct il_priv *il) | 3253 | il4965_update_bcast_stations(struct il_priv *il) |
3278 | { | 3254 | { |
3279 | return il4965_update_bcast_station(il, &il->ctx); | 3255 | return il4965_update_bcast_station(il); |
3280 | } | 3256 | } |
3281 | 3257 | ||
3282 | /** | 3258 | /** |
@@ -3376,10 +3352,10 @@ il4965_sta_modify_sleep_tx_count(struct il_priv *il, int sta_id, int cnt) | |||
3376 | void | 3352 | void |
3377 | il4965_update_chain_flags(struct il_priv *il) | 3353 | il4965_update_chain_flags(struct il_priv *il) |
3378 | { | 3354 | { |
3379 | if (il->cfg->ops->hcmd->set_rxon_chain) { | 3355 | if (il->ops->hcmd->set_rxon_chain) { |
3380 | il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx); | 3356 | il->ops->hcmd->set_rxon_chain(il); |
3381 | if (il->ctx.active.rx_chain != il->ctx.staging.rx_chain) | 3357 | if (il->active.rx_chain != il->staging.rx_chain) |
3382 | il_commit_rxon(il, &il->ctx); | 3358 | il_commit_rxon(il); |
3383 | } | 3359 | } |
3384 | } | 3360 | } |
3385 | 3361 | ||
@@ -3491,8 +3467,8 @@ il4965_hw_get_beacon_cmd(struct il_priv *il, struct il_frame *frame) | |||
3491 | 3467 | ||
3492 | lockdep_assert_held(&il->mutex); | 3468 | lockdep_assert_held(&il->mutex); |
3493 | 3469 | ||
3494 | if (!il->beacon_ctx) { | 3470 | if (!il->beacon_enabled) { |
3495 | IL_ERR("trying to build beacon w/o beacon context!\n"); | 3471 | IL_ERR("Trying to build beacon without beaconing enabled\n"); |
3496 | return 0; | 3472 | return 0; |
3497 | } | 3473 | } |
3498 | 3474 | ||
@@ -3511,7 +3487,7 @@ il4965_hw_get_beacon_cmd(struct il_priv *il, struct il_frame *frame) | |||
3511 | 3487 | ||
3512 | /* Set up TX command fields */ | 3488 | /* Set up TX command fields */ |
3513 | tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size); | 3489 | tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size); |
3514 | tx_beacon_cmd->tx.sta_id = il->beacon_ctx->bcast_sta_id; | 3490 | tx_beacon_cmd->tx.sta_id = il->hw_params.bcast_id; |
3515 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 3491 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
3516 | tx_beacon_cmd->tx.tx_flags = | 3492 | tx_beacon_cmd->tx.tx_flags = |
3517 | TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK | | 3493 | TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK | |
@@ -3522,7 +3498,7 @@ il4965_hw_get_beacon_cmd(struct il_priv *il, struct il_frame *frame) | |||
3522 | frame_size); | 3498 | frame_size); |
3523 | 3499 | ||
3524 | /* Set up packet rate and flags */ | 3500 | /* Set up packet rate and flags */ |
3525 | rate = il_get_lowest_plcp(il, il->beacon_ctx); | 3501 | rate = il_get_lowest_plcp(il); |
3526 | il4965_toggle_tx_ant(il, &il->mgmt_tx_ant, il->hw_params.valid_tx_ant); | 3502 | il4965_toggle_tx_ant(il, &il->mgmt_tx_ant, il->hw_params.valid_tx_ant); |
3527 | rate_flags = BIT(il->mgmt_tx_ant) << RATE_MCS_ANT_POS; | 3503 | rate_flags = BIT(il->mgmt_tx_ant) << RATE_MCS_ANT_POS; |
3528 | if ((rate >= IL_FIRST_CCK_RATE) && (rate <= IL_LAST_CCK_RATE)) | 3504 | if ((rate >= IL_FIRST_CCK_RATE) && (rate <= IL_LAST_CCK_RATE)) |
@@ -3645,15 +3621,13 @@ il4965_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq) | |||
3645 | PCI_DMA_TODEVICE); | 3621 | PCI_DMA_TODEVICE); |
3646 | 3622 | ||
3647 | /* free SKB */ | 3623 | /* free SKB */ |
3648 | if (txq->txb) { | 3624 | if (txq->skbs) { |
3649 | struct sk_buff *skb; | 3625 | struct sk_buff *skb = txq->skbs[txq->q.read_ptr]; |
3650 | |||
3651 | skb = txq->txb[txq->q.read_ptr].skb; | ||
3652 | 3626 | ||
3653 | /* can be called from irqs-disabled context */ | 3627 | /* can be called from irqs-disabled context */ |
3654 | if (skb) { | 3628 | if (skb) { |
3655 | dev_kfree_skb_any(skb); | 3629 | dev_kfree_skb_any(skb); |
3656 | txq->txb[txq->q.read_ptr].skb = NULL; | 3630 | txq->skbs[txq->q.read_ptr] = NULL; |
3657 | } | 3631 | } |
3658 | } | 3632 | } |
3659 | } | 3633 | } |
@@ -3897,7 +3871,7 @@ il4965_setup_handlers(struct il_priv *il) | |||
3897 | /* block ack */ | 3871 | /* block ack */ |
3898 | il->handlers[N_COMPRESSED_BA] = il4965_hdl_compressed_ba; | 3872 | il->handlers[N_COMPRESSED_BA] = il4965_hdl_compressed_ba; |
3899 | /* Set up hardware specific Rx handlers */ | 3873 | /* Set up hardware specific Rx handlers */ |
3900 | il->cfg->ops->lib->handler_setup(il); | 3874 | il->ops->lib->handler_setup(il); |
3901 | } | 3875 | } |
3902 | 3876 | ||
3903 | /** | 3877 | /** |
@@ -4799,7 +4773,7 @@ il4965_dump_nic_error_log(struct il_priv *il) | |||
4799 | else | 4773 | else |
4800 | base = le32_to_cpu(il->card_alive.error_event_table_ptr); | 4774 | base = le32_to_cpu(il->card_alive.error_event_table_ptr); |
4801 | 4775 | ||
4802 | if (!il->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 4776 | if (!il->ops->lib->is_valid_rtc_data_addr(base)) { |
4803 | IL_ERR("Not valid error log pointer 0x%08X for %s uCode\n", | 4777 | IL_ERR("Not valid error log pointer 0x%08X for %s uCode\n", |
4804 | base, (il->ucode_type == UCODE_INIT) ? "Init" : "RT"); | 4778 | base, (il->ucode_type == UCODE_INIT) ? "Init" : "RT"); |
4805 | return; | 4779 | return; |
@@ -4979,7 +4953,6 @@ static void | |||
4979 | il4965_alive_start(struct il_priv *il) | 4953 | il4965_alive_start(struct il_priv *il) |
4980 | { | 4954 | { |
4981 | int ret = 0; | 4955 | int ret = 0; |
4982 | struct il_rxon_context *ctx = &il->ctx; | ||
4983 | 4956 | ||
4984 | D_INFO("Runtime Alive received.\n"); | 4957 | D_INFO("Runtime Alive received.\n"); |
4985 | 4958 | ||
@@ -5019,18 +4992,18 @@ il4965_alive_start(struct il_priv *il) | |||
5019 | 4992 | ||
5020 | il->active_rate = RATES_MASK; | 4993 | il->active_rate = RATES_MASK; |
5021 | 4994 | ||
5022 | if (il_is_associated_ctx(ctx)) { | 4995 | if (il_is_associated(il)) { |
5023 | struct il_rxon_cmd *active_rxon = | 4996 | struct il_rxon_cmd *active_rxon = |
5024 | (struct il_rxon_cmd *)&ctx->active; | 4997 | (struct il_rxon_cmd *)&il->active; |
5025 | /* apply any changes in staging */ | 4998 | /* apply any changes in staging */ |
5026 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | 4999 | il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
5027 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 5000 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
5028 | } else { | 5001 | } else { |
5029 | /* Initialize our rx_config data */ | 5002 | /* Initialize our rx_config data */ |
5030 | il_connection_init_rx_config(il, &il->ctx); | 5003 | il_connection_init_rx_config(il); |
5031 | 5004 | ||
5032 | if (il->cfg->ops->hcmd->set_rxon_chain) | 5005 | if (il->ops->hcmd->set_rxon_chain) |
5033 | il->cfg->ops->hcmd->set_rxon_chain(il, ctx); | 5006 | il->ops->hcmd->set_rxon_chain(il); |
5034 | } | 5007 | } |
5035 | 5008 | ||
5036 | /* Configure bluetooth coexistence if enabled */ | 5009 | /* Configure bluetooth coexistence if enabled */ |
@@ -5041,7 +5014,7 @@ il4965_alive_start(struct il_priv *il) | |||
5041 | set_bit(S_READY, &il->status); | 5014 | set_bit(S_READY, &il->status); |
5042 | 5015 | ||
5043 | /* Configure the adapter for unassociated operation */ | 5016 | /* Configure the adapter for unassociated operation */ |
5044 | il_commit_rxon(il, ctx); | 5017 | il_commit_rxon(il); |
5045 | 5018 | ||
5046 | /* At this point, the NIC is initialized and operational */ | 5019 | /* At this point, the NIC is initialized and operational */ |
5047 | il4965_rf_kill_ct_config(il); | 5020 | il4965_rf_kill_ct_config(il); |
@@ -5076,7 +5049,21 @@ __il4965_down(struct il_priv *il) | |||
5076 | * to prevent rearm timer */ | 5049 | * to prevent rearm timer */ |
5077 | del_timer_sync(&il->watchdog); | 5050 | del_timer_sync(&il->watchdog); |
5078 | 5051 | ||
5079 | il_clear_ucode_stations(il, NULL); | 5052 | il_clear_ucode_stations(il); |
5053 | |||
5054 | /* FIXME: race conditions ? */ | ||
5055 | spin_lock_irq(&il->sta_lock); | ||
5056 | /* | ||
5057 | * Remove all key information that is not stored as part | ||
5058 | * of station information since mac80211 may not have had | ||
5059 | * a chance to remove all the keys. When device is | ||
5060 | * reconfigured by mac80211 after an error all keys will | ||
5061 | * be reconfigured. | ||
5062 | */ | ||
5063 | memset(il->_4965.wep_keys, 0, sizeof(il->_4965.wep_keys)); | ||
5064 | il->_4965.key_mapping_keys = 0; | ||
5065 | spin_unlock_irq(&il->sta_lock); | ||
5066 | |||
5080 | il_dealloc_bcast_stations(il); | 5067 | il_dealloc_bcast_stations(il); |
5081 | il_clear_driver_stations(il); | 5068 | il_clear_driver_stations(il); |
5082 | 5069 | ||
@@ -5227,7 +5214,7 @@ __il4965_up(struct il_priv *il) | |||
5227 | return -EIO; | 5214 | return -EIO; |
5228 | } | 5215 | } |
5229 | 5216 | ||
5230 | ret = il4965_alloc_bcast_station(il, &il->ctx); | 5217 | ret = il4965_alloc_bcast_station(il); |
5231 | if (ret) { | 5218 | if (ret) { |
5232 | il_dealloc_bcast_stations(il); | 5219 | il_dealloc_bcast_stations(il); |
5233 | return ret; | 5220 | return ret; |
@@ -5288,7 +5275,7 @@ __il4965_up(struct il_priv *il) | |||
5288 | /* load bootstrap state machine, | 5275 | /* load bootstrap state machine, |
5289 | * load bootstrap program into processor's memory, | 5276 | * load bootstrap program into processor's memory, |
5290 | * prepare to load the "initialize" uCode */ | 5277 | * prepare to load the "initialize" uCode */ |
5291 | ret = il->cfg->ops->lib->load_ucode(il); | 5278 | ret = il->ops->lib->load_ucode(il); |
5292 | 5279 | ||
5293 | if (ret) { | 5280 | if (ret) { |
5294 | IL_ERR("Unable to set up bootstrap uCode: %d\n", ret); | 5281 | IL_ERR("Unable to set up bootstrap uCode: %d\n", ret); |
@@ -5329,7 +5316,7 @@ il4965_bg_init_alive_start(struct work_struct *data) | |||
5329 | if (test_bit(S_EXIT_PENDING, &il->status)) | 5316 | if (test_bit(S_EXIT_PENDING, &il->status)) |
5330 | goto out; | 5317 | goto out; |
5331 | 5318 | ||
5332 | il->cfg->ops->lib->init_alive_start(il); | 5319 | il->ops->lib->init_alive_start(il); |
5333 | out: | 5320 | out: |
5334 | mutex_unlock(&il->mutex); | 5321 | mutex_unlock(&il->mutex); |
5335 | } | 5322 | } |
@@ -5381,7 +5368,8 @@ il4965_bg_restart(struct work_struct *data) | |||
5381 | 5368 | ||
5382 | if (test_and_clear_bit(S_FW_ERROR, &il->status)) { | 5369 | if (test_and_clear_bit(S_FW_ERROR, &il->status)) { |
5383 | mutex_lock(&il->mutex); | 5370 | mutex_lock(&il->mutex); |
5384 | il->ctx.vif = NULL; | 5371 | /* FIXME: do we dereference vif without mutex locked ? */ |
5372 | il->vif = NULL; | ||
5385 | il->is_open = 0; | 5373 | il->is_open = 0; |
5386 | 5374 | ||
5387 | __il4965_down(il); | 5375 | __il4965_down(il); |
@@ -5450,8 +5438,8 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) | |||
5450 | hw->sta_data_size = sizeof(struct il_station_priv); | 5438 | hw->sta_data_size = sizeof(struct il_station_priv); |
5451 | hw->vif_data_size = sizeof(struct il_vif_priv); | 5439 | hw->vif_data_size = sizeof(struct il_vif_priv); |
5452 | 5440 | ||
5453 | hw->wiphy->interface_modes |= il->ctx.interface_modes; | 5441 | hw->wiphy->interface_modes = |
5454 | hw->wiphy->interface_modes |= il->ctx.exclusive_interface_modes; | 5442 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); |
5455 | 5443 | ||
5456 | hw->wiphy->flags |= | 5444 | hw->wiphy->flags |= |
5457 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS; | 5445 | WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS; |
@@ -5578,12 +5566,10 @@ il4965_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5578 | struct ieee80211_sta *sta, u32 iv32, u16 * phase1key) | 5566 | struct ieee80211_sta *sta, u32 iv32, u16 * phase1key) |
5579 | { | 5567 | { |
5580 | struct il_priv *il = hw->priv; | 5568 | struct il_priv *il = hw->priv; |
5581 | struct il_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
5582 | 5569 | ||
5583 | D_MAC80211("enter\n"); | 5570 | D_MAC80211("enter\n"); |
5584 | 5571 | ||
5585 | il4965_update_tkip_key(il, vif_priv->ctx, keyconf, sta, iv32, | 5572 | il4965_update_tkip_key(il, keyconf, sta, iv32, phase1key); |
5586 | phase1key); | ||
5587 | 5573 | ||
5588 | D_MAC80211("leave\n"); | 5574 | D_MAC80211("leave\n"); |
5589 | } | 5575 | } |
@@ -5594,8 +5580,6 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
5594 | struct ieee80211_key_conf *key) | 5580 | struct ieee80211_key_conf *key) |
5595 | { | 5581 | { |
5596 | struct il_priv *il = hw->priv; | 5582 | struct il_priv *il = hw->priv; |
5597 | struct il_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
5598 | struct il_rxon_context *ctx = vif_priv->ctx; | ||
5599 | int ret; | 5583 | int ret; |
5600 | u8 sta_id; | 5584 | u8 sta_id; |
5601 | bool is_default_wep_key = false; | 5585 | bool is_default_wep_key = false; |
@@ -5607,7 +5591,7 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
5607 | return -EOPNOTSUPP; | 5591 | return -EOPNOTSUPP; |
5608 | } | 5592 | } |
5609 | 5593 | ||
5610 | sta_id = il_sta_id_or_broadcast(il, vif_priv->ctx, sta); | 5594 | sta_id = il_sta_id_or_broadcast(il, sta); |
5611 | if (sta_id == IL_INVALID_STATION) | 5595 | if (sta_id == IL_INVALID_STATION) |
5612 | return -EINVAL; | 5596 | return -EINVAL; |
5613 | 5597 | ||
@@ -5623,7 +5607,7 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
5623 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || | 5607 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
5624 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) { | 5608 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) { |
5625 | if (cmd == SET_KEY) | 5609 | if (cmd == SET_KEY) |
5626 | is_default_wep_key = !ctx->key_mapping_keys; | 5610 | is_default_wep_key = !il->_4965.key_mapping_keys; |
5627 | else | 5611 | else |
5628 | is_default_wep_key = | 5612 | is_default_wep_key = |
5629 | (key->hw_key_idx == HW_KEY_DEFAULT); | 5613 | (key->hw_key_idx == HW_KEY_DEFAULT); |
@@ -5632,20 +5616,17 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
5632 | switch (cmd) { | 5616 | switch (cmd) { |
5633 | case SET_KEY: | 5617 | case SET_KEY: |
5634 | if (is_default_wep_key) | 5618 | if (is_default_wep_key) |
5635 | ret = | 5619 | ret = il4965_set_default_wep_key(il, key); |
5636 | il4965_set_default_wep_key(il, vif_priv->ctx, key); | ||
5637 | else | 5620 | else |
5638 | ret = | 5621 | ret = il4965_set_dynamic_key(il, key, sta_id); |
5639 | il4965_set_dynamic_key(il, vif_priv->ctx, key, | ||
5640 | sta_id); | ||
5641 | 5622 | ||
5642 | D_MAC80211("enable hwcrypto key\n"); | 5623 | D_MAC80211("enable hwcrypto key\n"); |
5643 | break; | 5624 | break; |
5644 | case DISABLE_KEY: | 5625 | case DISABLE_KEY: |
5645 | if (is_default_wep_key) | 5626 | if (is_default_wep_key) |
5646 | ret = il4965_remove_default_wep_key(il, ctx, key); | 5627 | ret = il4965_remove_default_wep_key(il, key); |
5647 | else | 5628 | else |
5648 | ret = il4965_remove_dynamic_key(il, ctx, key, sta_id); | 5629 | ret = il4965_remove_dynamic_key(il, key, sta_id); |
5649 | 5630 | ||
5650 | D_MAC80211("disable hwcrypto key\n"); | 5631 | D_MAC80211("disable hwcrypto key\n"); |
5651 | break; | 5632 | break; |
@@ -5711,7 +5692,6 @@ il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5711 | { | 5692 | { |
5712 | struct il_priv *il = hw->priv; | 5693 | struct il_priv *il = hw->priv; |
5713 | struct il_station_priv *sta_priv = (void *)sta->drv_priv; | 5694 | struct il_station_priv *sta_priv = (void *)sta->drv_priv; |
5714 | struct il_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
5715 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; | 5695 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; |
5716 | int ret; | 5696 | int ret; |
5717 | u8 sta_id; | 5697 | u8 sta_id; |
@@ -5724,8 +5704,7 @@ il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5724 | atomic_set(&sta_priv->pending_frames, 0); | 5704 | atomic_set(&sta_priv->pending_frames, 0); |
5725 | 5705 | ||
5726 | ret = | 5706 | ret = |
5727 | il_add_station_common(il, vif_priv->ctx, sta->addr, is_ap, sta, | 5707 | il_add_station_common(il, sta->addr, is_ap, sta, &sta_id); |
5728 | &sta_id); | ||
5729 | if (ret) { | 5708 | if (ret) { |
5730 | IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret); | 5709 | IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret); |
5731 | /* Should we return success if return code is EEXIST ? */ | 5710 | /* Should we return success if return code is EEXIST ? */ |
@@ -5752,8 +5731,6 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, | |||
5752 | struct ieee80211_conf *conf = &hw->conf; | 5731 | struct ieee80211_conf *conf = &hw->conf; |
5753 | struct ieee80211_channel *channel = ch_switch->channel; | 5732 | struct ieee80211_channel *channel = ch_switch->channel; |
5754 | struct il_ht_config *ht_conf = &il->current_ht_config; | 5733 | struct il_ht_config *ht_conf = &il->current_ht_config; |
5755 | |||
5756 | struct il_rxon_context *ctx = &il->ctx; | ||
5757 | u16 ch; | 5734 | u16 ch; |
5758 | 5735 | ||
5759 | D_MAC80211("enter\n"); | 5736 | D_MAC80211("enter\n"); |
@@ -5768,14 +5745,14 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, | |||
5768 | test_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) | 5745 | test_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) |
5769 | goto out; | 5746 | goto out; |
5770 | 5747 | ||
5771 | if (!il_is_associated_ctx(ctx)) | 5748 | if (!il_is_associated(il)) |
5772 | goto out; | 5749 | goto out; |
5773 | 5750 | ||
5774 | if (!il->cfg->ops->lib->set_channel_switch) | 5751 | if (!il->ops->lib->set_channel_switch) |
5775 | goto out; | 5752 | goto out; |
5776 | 5753 | ||
5777 | ch = channel->hw_value; | 5754 | ch = channel->hw_value; |
5778 | if (le16_to_cpu(ctx->active.channel) == ch) | 5755 | if (le16_to_cpu(il->active.channel) == ch) |
5779 | goto out; | 5756 | goto out; |
5780 | 5757 | ||
5781 | ch_info = il_get_channel_info(il, channel->band, ch); | 5758 | ch_info = il_get_channel_info(il, channel->band, ch); |
@@ -5789,30 +5766,30 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, | |||
5789 | il->current_ht_config.smps = conf->smps_mode; | 5766 | il->current_ht_config.smps = conf->smps_mode; |
5790 | 5767 | ||
5791 | /* Configure HT40 channels */ | 5768 | /* Configure HT40 channels */ |
5792 | ctx->ht.enabled = conf_is_ht(conf); | 5769 | il->ht.enabled = conf_is_ht(conf); |
5793 | if (ctx->ht.enabled) { | 5770 | if (il->ht.enabled) { |
5794 | if (conf_is_ht40_minus(conf)) { | 5771 | if (conf_is_ht40_minus(conf)) { |
5795 | ctx->ht.extension_chan_offset = | 5772 | il->ht.extension_chan_offset = |
5796 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | 5773 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; |
5797 | ctx->ht.is_40mhz = true; | 5774 | il->ht.is_40mhz = true; |
5798 | } else if (conf_is_ht40_plus(conf)) { | 5775 | } else if (conf_is_ht40_plus(conf)) { |
5799 | ctx->ht.extension_chan_offset = | 5776 | il->ht.extension_chan_offset = |
5800 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | 5777 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; |
5801 | ctx->ht.is_40mhz = true; | 5778 | il->ht.is_40mhz = true; |
5802 | } else { | 5779 | } else { |
5803 | ctx->ht.extension_chan_offset = | 5780 | il->ht.extension_chan_offset = |
5804 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | 5781 | IEEE80211_HT_PARAM_CHA_SEC_NONE; |
5805 | ctx->ht.is_40mhz = false; | 5782 | il->ht.is_40mhz = false; |
5806 | } | 5783 | } |
5807 | } else | 5784 | } else |
5808 | ctx->ht.is_40mhz = false; | 5785 | il->ht.is_40mhz = false; |
5809 | 5786 | ||
5810 | if ((le16_to_cpu(ctx->staging.channel) != ch)) | 5787 | if ((le16_to_cpu(il->staging.channel) != ch)) |
5811 | ctx->staging.flags = 0; | 5788 | il->staging.flags = 0; |
5812 | 5789 | ||
5813 | il_set_rxon_channel(il, channel, ctx); | 5790 | il_set_rxon_channel(il, channel); |
5814 | il_set_rxon_ht(il, ht_conf); | 5791 | il_set_rxon_ht(il, ht_conf); |
5815 | il_set_flags_for_band(il, ctx, channel->band, ctx->vif); | 5792 | il_set_flags_for_band(il, channel->band, il->vif); |
5816 | 5793 | ||
5817 | spin_unlock_irq(&il->lock); | 5794 | spin_unlock_irq(&il->lock); |
5818 | 5795 | ||
@@ -5823,10 +5800,10 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, | |||
5823 | */ | 5800 | */ |
5824 | set_bit(S_CHANNEL_SWITCH_PENDING, &il->status); | 5801 | set_bit(S_CHANNEL_SWITCH_PENDING, &il->status); |
5825 | il->switch_channel = cpu_to_le16(ch); | 5802 | il->switch_channel = cpu_to_le16(ch); |
5826 | if (il->cfg->ops->lib->set_channel_switch(il, ch_switch)) { | 5803 | if (il->ops->lib->set_channel_switch(il, ch_switch)) { |
5827 | clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status); | 5804 | clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status); |
5828 | il->switch_channel = 0; | 5805 | il->switch_channel = 0; |
5829 | ieee80211_chswitch_done(ctx->vif, false); | 5806 | ieee80211_chswitch_done(il->vif, false); |
5830 | } | 5807 | } |
5831 | 5808 | ||
5832 | out: | 5809 | out: |
@@ -5860,8 +5837,8 @@ il4965_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, | |||
5860 | 5837 | ||
5861 | mutex_lock(&il->mutex); | 5838 | mutex_lock(&il->mutex); |
5862 | 5839 | ||
5863 | il->ctx.staging.filter_flags &= ~filter_nand; | 5840 | il->staging.filter_flags &= ~filter_nand; |
5864 | il->ctx.staging.filter_flags |= filter_or; | 5841 | il->staging.filter_flags |= filter_or; |
5865 | 5842 | ||
5866 | /* | 5843 | /* |
5867 | * Not committing directly because hardware can perform a scan, | 5844 | * Not committing directly because hardware can perform a scan, |
@@ -5906,7 +5883,7 @@ il4965_bg_txpower_work(struct work_struct *work) | |||
5906 | /* Regardless of if we are associated, we must reconfigure the | 5883 | /* Regardless of if we are associated, we must reconfigure the |
5907 | * TX power since frames can be sent on non-radar channels while | 5884 | * TX power since frames can be sent on non-radar channels while |
5908 | * not associated */ | 5885 | * not associated */ |
5909 | il->cfg->ops->lib->send_tx_power(il); | 5886 | il->ops->lib->send_tx_power(il); |
5910 | 5887 | ||
5911 | /* Update last_temperature to keep is_calib_needed from running | 5888 | /* Update last_temperature to keep is_calib_needed from running |
5912 | * when it isn't needed... */ | 5889 | * when it isn't needed... */ |
@@ -6012,6 +5989,28 @@ il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq, | |||
6012 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | 5989 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); |
6013 | } | 5990 | } |
6014 | 5991 | ||
5992 | const struct ieee80211_ops il4965_mac_ops = { | ||
5993 | .tx = il4965_mac_tx, | ||
5994 | .start = il4965_mac_start, | ||
5995 | .stop = il4965_mac_stop, | ||
5996 | .add_interface = il_mac_add_interface, | ||
5997 | .remove_interface = il_mac_remove_interface, | ||
5998 | .change_interface = il_mac_change_interface, | ||
5999 | .config = il_mac_config, | ||
6000 | .configure_filter = il4965_configure_filter, | ||
6001 | .set_key = il4965_mac_set_key, | ||
6002 | .update_tkip_key = il4965_mac_update_tkip_key, | ||
6003 | .conf_tx = il_mac_conf_tx, | ||
6004 | .reset_tsf = il_mac_reset_tsf, | ||
6005 | .bss_info_changed = il_mac_bss_info_changed, | ||
6006 | .ampdu_action = il4965_mac_ampdu_action, | ||
6007 | .hw_scan = il_mac_hw_scan, | ||
6008 | .sta_add = il4965_mac_sta_add, | ||
6009 | .sta_remove = il_mac_sta_remove, | ||
6010 | .channel_switch = il4965_mac_channel_switch, | ||
6011 | .tx_last_beacon = il_mac_tx_last_beacon, | ||
6012 | }; | ||
6013 | |||
6015 | static int | 6014 | static int |
6016 | il4965_init_drv(struct il_priv *il) | 6015 | il4965_init_drv(struct il_priv *il) |
6017 | { | 6016 | { |
@@ -6036,8 +6035,8 @@ il4965_init_drv(struct il_priv *il) | |||
6036 | il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD; | 6035 | il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD; |
6037 | 6036 | ||
6038 | /* Choose which receivers/antennas to use */ | 6037 | /* Choose which receivers/antennas to use */ |
6039 | if (il->cfg->ops->hcmd->set_rxon_chain) | 6038 | if (il->ops->hcmd->set_rxon_chain) |
6040 | il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx); | 6039 | il->ops->hcmd->set_rxon_chain(il); |
6041 | 6040 | ||
6042 | il_init_scan_params(il); | 6041 | il_init_scan_params(il); |
6043 | 6042 | ||
@@ -6080,9 +6079,37 @@ il4965_hw_detect(struct il_priv *il) | |||
6080 | D_INFO("HW Revision ID = 0x%X\n", il->rev_id); | 6079 | D_INFO("HW Revision ID = 0x%X\n", il->rev_id); |
6081 | } | 6080 | } |
6082 | 6081 | ||
6083 | static int | 6082 | static struct il_sensitivity_ranges il4965_sensitivity = { |
6083 | .min_nrg_cck = 97, | ||
6084 | .max_nrg_cck = 0, /* not used, set to 0 */ | ||
6085 | |||
6086 | .auto_corr_min_ofdm = 85, | ||
6087 | .auto_corr_min_ofdm_mrc = 170, | ||
6088 | .auto_corr_min_ofdm_x1 = 105, | ||
6089 | .auto_corr_min_ofdm_mrc_x1 = 220, | ||
6090 | |||
6091 | .auto_corr_max_ofdm = 120, | ||
6092 | .auto_corr_max_ofdm_mrc = 210, | ||
6093 | .auto_corr_max_ofdm_x1 = 140, | ||
6094 | .auto_corr_max_ofdm_mrc_x1 = 270, | ||
6095 | |||
6096 | .auto_corr_min_cck = 125, | ||
6097 | .auto_corr_max_cck = 200, | ||
6098 | .auto_corr_min_cck_mrc = 200, | ||
6099 | .auto_corr_max_cck_mrc = 400, | ||
6100 | |||
6101 | .nrg_th_cck = 100, | ||
6102 | .nrg_th_ofdm = 100, | ||
6103 | |||
6104 | .barker_corr_th_min = 190, | ||
6105 | .barker_corr_th_min_mrc = 390, | ||
6106 | .nrg_th_cca = 62, | ||
6107 | }; | ||
6108 | |||
6109 | static void | ||
6084 | il4965_set_hw_params(struct il_priv *il) | 6110 | il4965_set_hw_params(struct il_priv *il) |
6085 | { | 6111 | { |
6112 | il->hw_params.bcast_id = IL4965_BROADCAST_ID; | ||
6086 | il->hw_params.max_rxq_size = RX_QUEUE_SIZE; | 6113 | il->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
6087 | il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | 6114 | il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; |
6088 | if (il->cfg->mod_params->amsdu_size_8K) | 6115 | if (il->cfg->mod_params->amsdu_size_8K) |
@@ -6095,20 +6122,37 @@ il4965_set_hw_params(struct il_priv *il) | |||
6095 | if (il->cfg->mod_params->disable_11n) | 6122 | if (il->cfg->mod_params->disable_11n) |
6096 | il->cfg->sku &= ~IL_SKU_N; | 6123 | il->cfg->sku &= ~IL_SKU_N; |
6097 | 6124 | ||
6098 | /* Device-specific setup */ | 6125 | if (il->cfg->mod_params->num_of_queues >= IL_MIN_NUM_QUEUES && |
6099 | return il->cfg->ops->lib->set_hw_params(il); | 6126 | il->cfg->mod_params->num_of_queues <= IL49_NUM_QUEUES) |
6100 | } | 6127 | il->cfg->num_of_queues = |
6128 | il->cfg->mod_params->num_of_queues; | ||
6101 | 6129 | ||
6102 | static const u8 il4965_bss_ac_to_fifo[] = { | 6130 | il->hw_params.max_txq_num = il->cfg->num_of_queues; |
6103 | IL_TX_FIFO_VO, | 6131 | il->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; |
6104 | IL_TX_FIFO_VI, | 6132 | il->hw_params.scd_bc_tbls_size = |
6105 | IL_TX_FIFO_BE, | 6133 | il->cfg->num_of_queues * |
6106 | IL_TX_FIFO_BK, | 6134 | sizeof(struct il4965_scd_bc_tbl); |
6107 | }; | ||
6108 | 6135 | ||
6109 | static const u8 il4965_bss_ac_to_queue[] = { | 6136 | il->hw_params.tfd_size = sizeof(struct il_tfd); |
6110 | 0, 1, 2, 3, | 6137 | il->hw_params.max_stations = IL4965_STATION_COUNT; |
6111 | }; | 6138 | il->hw_params.max_data_size = IL49_RTC_DATA_SIZE; |
6139 | il->hw_params.max_inst_size = IL49_RTC_INST_SIZE; | ||
6140 | il->hw_params.max_bsm_size = BSM_SRAM_SIZE; | ||
6141 | il->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ); | ||
6142 | |||
6143 | il->hw_params.rx_wrt_ptr_reg = FH49_RSCSR_CHNL0_WPTR; | ||
6144 | |||
6145 | il->hw_params.tx_chains_num = il4965_num_of_ant(il->cfg->valid_tx_ant); | ||
6146 | il->hw_params.rx_chains_num = il4965_num_of_ant(il->cfg->valid_rx_ant); | ||
6147 | il->hw_params.valid_tx_ant = il->cfg->valid_tx_ant; | ||
6148 | il->hw_params.valid_rx_ant = il->cfg->valid_rx_ant; | ||
6149 | |||
6150 | il->hw_params.ct_kill_threshold = | ||
6151 | CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY); | ||
6152 | |||
6153 | il->hw_params.sens = &il4965_sensitivity; | ||
6154 | il->hw_params.beacon_time_tsf_bits = IL4965_EXT_BEACON_TIME_POS; | ||
6155 | } | ||
6112 | 6156 | ||
6113 | static int | 6157 | static int |
6114 | il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 6158 | il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -6124,37 +6168,18 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6124 | * 1. Allocating HW data | 6168 | * 1. Allocating HW data |
6125 | ************************/ | 6169 | ************************/ |
6126 | 6170 | ||
6127 | hw = il_alloc_all(cfg); | 6171 | hw = ieee80211_alloc_hw(sizeof(struct il_priv), &il4965_mac_ops); |
6128 | if (!hw) { | 6172 | if (!hw) { |
6129 | err = -ENOMEM; | 6173 | err = -ENOMEM; |
6130 | goto out; | 6174 | goto out; |
6131 | } | 6175 | } |
6132 | il = hw->priv; | 6176 | il = hw->priv; |
6133 | /* At this point both hw and il are allocated. */ | 6177 | il->hw = hw; |
6134 | |||
6135 | il->ctx.ctxid = 0; | ||
6136 | |||
6137 | il->ctx.always_active = true; | ||
6138 | il->ctx.is_active = true; | ||
6139 | il->ctx.rxon_cmd = C_RXON; | ||
6140 | il->ctx.rxon_timing_cmd = C_RXON_TIMING; | ||
6141 | il->ctx.rxon_assoc_cmd = C_RXON_ASSOC; | ||
6142 | il->ctx.qos_cmd = C_QOS_PARAM; | ||
6143 | il->ctx.ap_sta_id = IL_AP_ID; | ||
6144 | il->ctx.wep_key_cmd = C_WEPKEY; | ||
6145 | il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo; | ||
6146 | il->ctx.ac_to_queue = il4965_bss_ac_to_queue; | ||
6147 | il->ctx.exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC); | ||
6148 | il->ctx.interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
6149 | il->ctx.ap_devtype = RXON_DEV_TYPE_AP; | ||
6150 | il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS; | ||
6151 | il->ctx.station_devtype = RXON_DEV_TYPE_ESS; | ||
6152 | il->ctx.unused_devtype = RXON_DEV_TYPE_ESS; | ||
6153 | |||
6154 | SET_IEEE80211_DEV(hw, &pdev->dev); | 6178 | SET_IEEE80211_DEV(hw, &pdev->dev); |
6155 | 6179 | ||
6156 | D_INFO("*** LOAD DRIVER ***\n"); | 6180 | D_INFO("*** LOAD DRIVER ***\n"); |
6157 | il->cfg = cfg; | 6181 | il->cfg = cfg; |
6182 | il->ops = &il4965_ops; | ||
6158 | il->pci_dev = pdev; | 6183 | il->pci_dev = pdev; |
6159 | il->inta_mask = CSR_INI_SET_MASK; | 6184 | il->inta_mask = CSR_INI_SET_MASK; |
6160 | 6185 | ||
@@ -6260,10 +6285,7 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6260 | /************************ | 6285 | /************************ |
6261 | * 5. Setup HW constants | 6286 | * 5. Setup HW constants |
6262 | ************************/ | 6287 | ************************/ |
6263 | if (il4965_set_hw_params(il)) { | 6288 | il4965_set_hw_params(il); |
6264 | IL_ERR("failed to set hw parameters\n"); | ||
6265 | goto out_free_eeprom; | ||
6266 | } | ||
6267 | 6289 | ||
6268 | /******************* | 6290 | /******************* |
6269 | * 6. Setup il | 6291 | * 6. Setup il |
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c index 467d0cb14ecd..d7e2856e41d3 100644 --- a/drivers/net/wireless/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/iwlegacy/4965-rs.c | |||
@@ -641,13 +641,10 @@ il4965_rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
641 | * there are no non-GF stations present in the BSS. | 641 | * there are no non-GF stations present in the BSS. |
642 | */ | 642 | */ |
643 | static bool | 643 | static bool |
644 | il4965_rs_use_green(struct ieee80211_sta *sta) | 644 | il4965_rs_use_green(struct il_priv *il, struct ieee80211_sta *sta) |
645 | { | 645 | { |
646 | struct il_station_priv *sta_priv = (void *)sta->drv_priv; | ||
647 | struct il_rxon_context *ctx = sta_priv->common.ctx; | ||
648 | |||
649 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && | 646 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && |
650 | !(ctx->ht.non_gf_sta_present); | 647 | !il->ht.non_gf_sta_present; |
651 | } | 648 | } |
652 | 649 | ||
653 | /** | 650 | /** |
@@ -823,8 +820,6 @@ il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband, | |||
823 | u32 tx_rate; | 820 | u32 tx_rate; |
824 | struct il_scale_tbl_info tbl_type; | 821 | struct il_scale_tbl_info tbl_type; |
825 | struct il_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; | 822 | struct il_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
826 | struct il_station_priv *sta_priv = (void *)sta->drv_priv; | ||
827 | struct il_rxon_context *ctx = sta_priv->common.ctx; | ||
828 | 823 | ||
829 | D_RATE("get frame ack response, update rate scale win\n"); | 824 | D_RATE("get frame ack response, update rate scale win\n"); |
830 | 825 | ||
@@ -892,7 +887,7 @@ il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband, | |||
892 | lq_sta->missed_rate_counter++; | 887 | lq_sta->missed_rate_counter++; |
893 | if (lq_sta->missed_rate_counter > IL_MISSED_RATE_MAX) { | 888 | if (lq_sta->missed_rate_counter > IL_MISSED_RATE_MAX) { |
894 | lq_sta->missed_rate_counter = 0; | 889 | lq_sta->missed_rate_counter = 0; |
895 | il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false); | 890 | il_send_lq_cmd(il, &lq_sta->lq, CMD_ASYNC, false); |
896 | } | 891 | } |
897 | /* Regardless, ignore this status info for outdated rate */ | 892 | /* Regardless, ignore this status info for outdated rate */ |
898 | return; | 893 | return; |
@@ -1184,8 +1179,6 @@ il4965_rs_switch_to_mimo2(struct il_priv *il, struct il_lq_sta *lq_sta, | |||
1184 | u16 rate_mask; | 1179 | u16 rate_mask; |
1185 | s32 rate; | 1180 | s32 rate; |
1186 | s8 is_green = lq_sta->is_green; | 1181 | s8 is_green = lq_sta->is_green; |
1187 | struct il_station_priv *sta_priv = (void *)sta->drv_priv; | ||
1188 | struct il_rxon_context *ctx = sta_priv->common.ctx; | ||
1189 | 1182 | ||
1190 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) | 1183 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) |
1191 | return -1; | 1184 | return -1; |
@@ -1206,7 +1199,7 @@ il4965_rs_switch_to_mimo2(struct il_priv *il, struct il_lq_sta *lq_sta, | |||
1206 | tbl->max_search = IL_MAX_SEARCH; | 1199 | tbl->max_search = IL_MAX_SEARCH; |
1207 | rate_mask = lq_sta->active_mimo2_rate; | 1200 | rate_mask = lq_sta->active_mimo2_rate; |
1208 | 1201 | ||
1209 | if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap)) | 1202 | if (il_is_ht40_tx_allowed(il, &sta->ht_cap)) |
1210 | tbl->is_ht40 = 1; | 1203 | tbl->is_ht40 = 1; |
1211 | else | 1204 | else |
1212 | tbl->is_ht40 = 0; | 1205 | tbl->is_ht40 = 0; |
@@ -1240,8 +1233,6 @@ il4965_rs_switch_to_siso(struct il_priv *il, struct il_lq_sta *lq_sta, | |||
1240 | u16 rate_mask; | 1233 | u16 rate_mask; |
1241 | u8 is_green = lq_sta->is_green; | 1234 | u8 is_green = lq_sta->is_green; |
1242 | s32 rate; | 1235 | s32 rate; |
1243 | struct il_station_priv *sta_priv = (void *)sta->drv_priv; | ||
1244 | struct il_rxon_context *ctx = sta_priv->common.ctx; | ||
1245 | 1236 | ||
1246 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) | 1237 | if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) |
1247 | return -1; | 1238 | return -1; |
@@ -1254,7 +1245,7 @@ il4965_rs_switch_to_siso(struct il_priv *il, struct il_lq_sta *lq_sta, | |||
1254 | tbl->max_search = IL_MAX_SEARCH; | 1245 | tbl->max_search = IL_MAX_SEARCH; |
1255 | rate_mask = lq_sta->active_siso_rate; | 1246 | rate_mask = lq_sta->active_siso_rate; |
1256 | 1247 | ||
1257 | if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap)) | 1248 | if (il_is_ht40_tx_allowed(il, &sta->ht_cap)) |
1258 | tbl->is_ht40 = 1; | 1249 | tbl->is_ht40 = 1; |
1259 | else | 1250 | else |
1260 | tbl->is_ht40 = 0; | 1251 | tbl->is_ht40 = 0; |
@@ -1733,8 +1724,7 @@ il4965_rs_stay_in_table(struct il_lq_sta *lq_sta, bool force_search) | |||
1733 | * setup rate table in uCode | 1724 | * setup rate table in uCode |
1734 | */ | 1725 | */ |
1735 | static void | 1726 | static void |
1736 | il4965_rs_update_rate_tbl(struct il_priv *il, struct il_rxon_context *ctx, | 1727 | il4965_rs_update_rate_tbl(struct il_priv *il, struct il_lq_sta *lq_sta, |
1737 | struct il_lq_sta *lq_sta, | ||
1738 | struct il_scale_tbl_info *tbl, int idx, u8 is_green) | 1728 | struct il_scale_tbl_info *tbl, int idx, u8 is_green) |
1739 | { | 1729 | { |
1740 | u32 rate; | 1730 | u32 rate; |
@@ -1742,7 +1732,7 @@ il4965_rs_update_rate_tbl(struct il_priv *il, struct il_rxon_context *ctx, | |||
1742 | /* Update uCode's rate table. */ | 1732 | /* Update uCode's rate table. */ |
1743 | rate = il4965_rate_n_flags_from_tbl(il, tbl, idx, is_green); | 1733 | rate = il4965_rate_n_flags_from_tbl(il, tbl, idx, is_green); |
1744 | il4965_rs_fill_link_cmd(il, lq_sta, rate); | 1734 | il4965_rs_fill_link_cmd(il, lq_sta, rate); |
1745 | il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false); | 1735 | il_send_lq_cmd(il, &lq_sta->lq, CMD_ASYNC, false); |
1746 | } | 1736 | } |
1747 | 1737 | ||
1748 | /* | 1738 | /* |
@@ -1778,8 +1768,6 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb, | |||
1778 | s32 sr; | 1768 | s32 sr; |
1779 | u8 tid = MAX_TID_COUNT; | 1769 | u8 tid = MAX_TID_COUNT; |
1780 | struct il_tid_data *tid_data; | 1770 | struct il_tid_data *tid_data; |
1781 | struct il_station_priv *sta_priv = (void *)sta->drv_priv; | ||
1782 | struct il_rxon_context *ctx = sta_priv->common.ctx; | ||
1783 | 1771 | ||
1784 | D_RATE("rate scale calculate new rate for skb\n"); | 1772 | D_RATE("rate scale calculate new rate for skb\n"); |
1785 | 1773 | ||
@@ -1815,7 +1803,7 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb, | |||
1815 | if (is_legacy(tbl->lq_type)) | 1803 | if (is_legacy(tbl->lq_type)) |
1816 | lq_sta->is_green = 0; | 1804 | lq_sta->is_green = 0; |
1817 | else | 1805 | else |
1818 | lq_sta->is_green = il4965_rs_use_green(sta); | 1806 | lq_sta->is_green = il4965_rs_use_green(il, sta); |
1819 | is_green = lq_sta->is_green; | 1807 | is_green = lq_sta->is_green; |
1820 | 1808 | ||
1821 | /* current tx rate */ | 1809 | /* current tx rate */ |
@@ -1854,7 +1842,7 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb, | |||
1854 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1842 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
1855 | /* get "active" rate info */ | 1843 | /* get "active" rate info */ |
1856 | idx = il4965_hwrate_to_plcp_idx(tbl->current_rate); | 1844 | idx = il4965_hwrate_to_plcp_idx(tbl->current_rate); |
1857 | il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx, | 1845 | il4965_rs_update_rate_tbl(il, lq_sta, tbl, idx, |
1858 | is_green); | 1846 | is_green); |
1859 | } | 1847 | } |
1860 | return; | 1848 | return; |
@@ -2057,8 +2045,7 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb, | |||
2057 | lq_update: | 2045 | lq_update: |
2058 | /* Replace uCode's rate table for the destination station. */ | 2046 | /* Replace uCode's rate table for the destination station. */ |
2059 | if (update_lq) | 2047 | if (update_lq) |
2060 | il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx, | 2048 | il4965_rs_update_rate_tbl(il, lq_sta, tbl, idx, is_green); |
2061 | is_green); | ||
2062 | 2049 | ||
2063 | /* Should we stay with this modulation mode, | 2050 | /* Should we stay with this modulation mode, |
2064 | * or search for a new one? */ | 2051 | * or search for a new one? */ |
@@ -2098,7 +2085,7 @@ lq_update: | |||
2098 | D_RATE("Switch current mcs: %X idx: %d\n", | 2085 | D_RATE("Switch current mcs: %X idx: %d\n", |
2099 | tbl->current_rate, idx); | 2086 | tbl->current_rate, idx); |
2100 | il4965_rs_fill_link_cmd(il, lq_sta, tbl->current_rate); | 2087 | il4965_rs_fill_link_cmd(il, lq_sta, tbl->current_rate); |
2101 | il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false); | 2088 | il_send_lq_cmd(il, &lq_sta->lq, CMD_ASYNC, false); |
2102 | } else | 2089 | } else |
2103 | done_search = 1; | 2090 | done_search = 1; |
2104 | } | 2091 | } |
@@ -2166,17 +2153,15 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf, | |||
2166 | int rate_idx; | 2153 | int rate_idx; |
2167 | int i; | 2154 | int i; |
2168 | u32 rate; | 2155 | u32 rate; |
2169 | u8 use_green = il4965_rs_use_green(sta); | 2156 | u8 use_green = il4965_rs_use_green(il, sta); |
2170 | u8 active_tbl = 0; | 2157 | u8 active_tbl = 0; |
2171 | u8 valid_tx_ant; | 2158 | u8 valid_tx_ant; |
2172 | struct il_station_priv *sta_priv; | 2159 | struct il_station_priv *sta_priv; |
2173 | struct il_rxon_context *ctx; | ||
2174 | 2160 | ||
2175 | if (!sta || !lq_sta) | 2161 | if (!sta || !lq_sta) |
2176 | return; | 2162 | return; |
2177 | 2163 | ||
2178 | sta_priv = (void *)sta->drv_priv; | 2164 | sta_priv = (void *)sta->drv_priv; |
2179 | ctx = sta_priv->common.ctx; | ||
2180 | 2165 | ||
2181 | i = lq_sta->last_txrate_idx; | 2166 | i = lq_sta->last_txrate_idx; |
2182 | 2167 | ||
@@ -2208,7 +2193,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf, | |||
2208 | il4965_rs_set_expected_tpt_table(lq_sta, tbl); | 2193 | il4965_rs_set_expected_tpt_table(lq_sta, tbl); |
2209 | il4965_rs_fill_link_cmd(NULL, lq_sta, rate); | 2194 | il4965_rs_fill_link_cmd(NULL, lq_sta, rate); |
2210 | il->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; | 2195 | il->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; |
2211 | il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_SYNC, true); | 2196 | il_send_lq_cmd(il, &lq_sta->lq, CMD_SYNC, true); |
2212 | } | 2197 | } |
2213 | 2198 | ||
2214 | static void | 2199 | static void |
@@ -2341,7 +2326,7 @@ il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id) | |||
2341 | lq_sta->is_dup = 0; | 2326 | lq_sta->is_dup = 0; |
2342 | lq_sta->max_rate_idx = -1; | 2327 | lq_sta->max_rate_idx = -1; |
2343 | lq_sta->missed_rate_counter = IL_MISSED_RATE_MAX; | 2328 | lq_sta->missed_rate_counter = IL_MISSED_RATE_MAX; |
2344 | lq_sta->is_green = il4965_rs_use_green(sta); | 2329 | lq_sta->is_green = il4965_rs_use_green(il, sta); |
2345 | lq_sta->active_legacy_rate = il->active_rate & ~(0x1000); | 2330 | lq_sta->active_legacy_rate = il->active_rate & ~(0x1000); |
2346 | lq_sta->band = il->band; | 2331 | lq_sta->band = il->band; |
2347 | /* | 2332 | /* |
@@ -2579,9 +2564,6 @@ il4965_rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2579 | char buf[64]; | 2564 | char buf[64]; |
2580 | size_t buf_size; | 2565 | size_t buf_size; |
2581 | u32 parsed_rate; | 2566 | u32 parsed_rate; |
2582 | struct il_station_priv *sta_priv = | ||
2583 | container_of(lq_sta, struct il_station_priv, lq_sta); | ||
2584 | struct il_rxon_context *ctx = sta_priv->common.ctx; | ||
2585 | 2567 | ||
2586 | il = lq_sta->drv; | 2568 | il = lq_sta->drv; |
2587 | memset(buf, 0, sizeof(buf)); | 2569 | memset(buf, 0, sizeof(buf)); |
@@ -2603,7 +2585,7 @@ il4965_rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2603 | 2585 | ||
2604 | if (lq_sta->dbg_fixed_rate) { | 2586 | if (lq_sta->dbg_fixed_rate) { |
2605 | il4965_rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); | 2587 | il4965_rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); |
2606 | il_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, false); | 2588 | il_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); |
2607 | } | 2589 | } |
2608 | 2590 | ||
2609 | return count; | 2591 | return count; |
diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index cacbc03880b0..79e4e7971338 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c | |||
@@ -569,82 +569,6 @@ il4965_chain_noise_reset(struct il_priv *il) | |||
569 | } | 569 | } |
570 | } | 570 | } |
571 | 571 | ||
572 | static struct il_sensitivity_ranges il4965_sensitivity = { | ||
573 | .min_nrg_cck = 97, | ||
574 | .max_nrg_cck = 0, /* not used, set to 0 */ | ||
575 | |||
576 | .auto_corr_min_ofdm = 85, | ||
577 | .auto_corr_min_ofdm_mrc = 170, | ||
578 | .auto_corr_min_ofdm_x1 = 105, | ||
579 | .auto_corr_min_ofdm_mrc_x1 = 220, | ||
580 | |||
581 | .auto_corr_max_ofdm = 120, | ||
582 | .auto_corr_max_ofdm_mrc = 210, | ||
583 | .auto_corr_max_ofdm_x1 = 140, | ||
584 | .auto_corr_max_ofdm_mrc_x1 = 270, | ||
585 | |||
586 | .auto_corr_min_cck = 125, | ||
587 | .auto_corr_max_cck = 200, | ||
588 | .auto_corr_min_cck_mrc = 200, | ||
589 | .auto_corr_max_cck_mrc = 400, | ||
590 | |||
591 | .nrg_th_cck = 100, | ||
592 | .nrg_th_ofdm = 100, | ||
593 | |||
594 | .barker_corr_th_min = 190, | ||
595 | .barker_corr_th_min_mrc = 390, | ||
596 | .nrg_th_cca = 62, | ||
597 | }; | ||
598 | |||
599 | static void | ||
600 | il4965_set_ct_threshold(struct il_priv *il) | ||
601 | { | ||
602 | /* want Kelvin */ | ||
603 | il->hw_params.ct_kill_threshold = | ||
604 | CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY); | ||
605 | } | ||
606 | |||
607 | /** | ||
608 | * il4965_hw_set_hw_params | ||
609 | * | ||
610 | * Called when initializing driver | ||
611 | */ | ||
612 | static int | ||
613 | il4965_hw_set_hw_params(struct il_priv *il) | ||
614 | { | ||
615 | if (il->cfg->mod_params->num_of_queues >= IL_MIN_NUM_QUEUES && | ||
616 | il->cfg->mod_params->num_of_queues <= IL49_NUM_QUEUES) | ||
617 | il->cfg->base_params->num_of_queues = | ||
618 | il->cfg->mod_params->num_of_queues; | ||
619 | |||
620 | il->hw_params.max_txq_num = il->cfg->base_params->num_of_queues; | ||
621 | il->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; | ||
622 | il->hw_params.scd_bc_tbls_size = | ||
623 | il->cfg->base_params->num_of_queues * | ||
624 | sizeof(struct il4965_scd_bc_tbl); | ||
625 | il->hw_params.tfd_size = sizeof(struct il_tfd); | ||
626 | il->hw_params.max_stations = IL4965_STATION_COUNT; | ||
627 | il->ctx.bcast_sta_id = IL4965_BROADCAST_ID; | ||
628 | il->hw_params.max_data_size = IL49_RTC_DATA_SIZE; | ||
629 | il->hw_params.max_inst_size = IL49_RTC_INST_SIZE; | ||
630 | il->hw_params.max_bsm_size = BSM_SRAM_SIZE; | ||
631 | il->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ); | ||
632 | |||
633 | il->hw_params.rx_wrt_ptr_reg = FH49_RSCSR_CHNL0_WPTR; | ||
634 | |||
635 | il->hw_params.tx_chains_num = il4965_num_of_ant(il->cfg->valid_tx_ant); | ||
636 | il->hw_params.rx_chains_num = il4965_num_of_ant(il->cfg->valid_rx_ant); | ||
637 | il->hw_params.valid_tx_ant = il->cfg->valid_tx_ant; | ||
638 | il->hw_params.valid_rx_ant = il->cfg->valid_rx_ant; | ||
639 | |||
640 | il4965_set_ct_threshold(il); | ||
641 | |||
642 | il->hw_params.sens = &il4965_sensitivity; | ||
643 | il->hw_params.beacon_time_tsf_bits = IL4965_EXT_BEACON_TIME_POS; | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | static s32 | 572 | static s32 |
649 | il4965_math_div_round(s32 num, s32 denom, s32 * res) | 573 | il4965_math_div_round(s32 num, s32 denom, s32 * res) |
650 | { | 574 | { |
@@ -1342,7 +1266,6 @@ il4965_send_tx_power(struct il_priv *il) | |||
1342 | u8 band = 0; | 1266 | u8 band = 0; |
1343 | bool is_ht40 = false; | 1267 | bool is_ht40 = false; |
1344 | u8 ctrl_chan_high = 0; | 1268 | u8 ctrl_chan_high = 0; |
1345 | struct il_rxon_context *ctx = &il->ctx; | ||
1346 | 1269 | ||
1347 | if (WARN_ONCE | 1270 | if (WARN_ONCE |
1348 | (test_bit(S_SCAN_HW, &il->status), | 1271 | (test_bit(S_SCAN_HW, &il->status), |
@@ -1351,16 +1274,16 @@ il4965_send_tx_power(struct il_priv *il) | |||
1351 | 1274 | ||
1352 | band = il->band == IEEE80211_BAND_2GHZ; | 1275 | band = il->band == IEEE80211_BAND_2GHZ; |
1353 | 1276 | ||
1354 | is_ht40 = iw4965_is_ht40_channel(ctx->active.flags); | 1277 | is_ht40 = iw4965_is_ht40_channel(il->active.flags); |
1355 | 1278 | ||
1356 | if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) | 1279 | if (is_ht40 && (il->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) |
1357 | ctrl_chan_high = 1; | 1280 | ctrl_chan_high = 1; |
1358 | 1281 | ||
1359 | cmd.band = band; | 1282 | cmd.band = band; |
1360 | cmd.channel = ctx->active.channel; | 1283 | cmd.channel = il->active.channel; |
1361 | 1284 | ||
1362 | ret = | 1285 | ret = |
1363 | il4965_fill_txpower_tbl(il, band, le16_to_cpu(ctx->active.channel), | 1286 | il4965_fill_txpower_tbl(il, band, le16_to_cpu(il->active.channel), |
1364 | is_ht40, ctrl_chan_high, &cmd.tx_power); | 1287 | is_ht40, ctrl_chan_high, &cmd.tx_power); |
1365 | if (ret) | 1288 | if (ret) |
1366 | goto out; | 1289 | goto out; |
@@ -1372,12 +1295,12 @@ out: | |||
1372 | } | 1295 | } |
1373 | 1296 | ||
1374 | static int | 1297 | static int |
1375 | il4965_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) | 1298 | il4965_send_rxon_assoc(struct il_priv *il) |
1376 | { | 1299 | { |
1377 | int ret = 0; | 1300 | int ret = 0; |
1378 | struct il4965_rxon_assoc_cmd rxon_assoc; | 1301 | struct il4965_rxon_assoc_cmd rxon_assoc; |
1379 | const struct il_rxon_cmd *rxon1 = &ctx->staging; | 1302 | const struct il_rxon_cmd *rxon1 = &il->staging; |
1380 | const struct il_rxon_cmd *rxon2 = &ctx->active; | 1303 | const struct il_rxon_cmd *rxon2 = &il->active; |
1381 | 1304 | ||
1382 | if (rxon1->flags == rxon2->flags && | 1305 | if (rxon1->flags == rxon2->flags && |
1383 | rxon1->filter_flags == rxon2->filter_flags && | 1306 | rxon1->filter_flags == rxon2->filter_flags && |
@@ -1392,16 +1315,16 @@ il4965_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) | |||
1392 | return 0; | 1315 | return 0; |
1393 | } | 1316 | } |
1394 | 1317 | ||
1395 | rxon_assoc.flags = ctx->staging.flags; | 1318 | rxon_assoc.flags = il->staging.flags; |
1396 | rxon_assoc.filter_flags = ctx->staging.filter_flags; | 1319 | rxon_assoc.filter_flags = il->staging.filter_flags; |
1397 | rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; | 1320 | rxon_assoc.ofdm_basic_rates = il->staging.ofdm_basic_rates; |
1398 | rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; | 1321 | rxon_assoc.cck_basic_rates = il->staging.cck_basic_rates; |
1399 | rxon_assoc.reserved = 0; | 1322 | rxon_assoc.reserved = 0; |
1400 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | 1323 | rxon_assoc.ofdm_ht_single_stream_basic_rates = |
1401 | ctx->staging.ofdm_ht_single_stream_basic_rates; | 1324 | il->staging.ofdm_ht_single_stream_basic_rates; |
1402 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | 1325 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = |
1403 | ctx->staging.ofdm_ht_dual_stream_basic_rates; | 1326 | il->staging.ofdm_ht_dual_stream_basic_rates; |
1404 | rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; | 1327 | rxon_assoc.rx_chain_select_flags = il->staging.rx_chain; |
1405 | 1328 | ||
1406 | ret = | 1329 | ret = |
1407 | il_send_cmd_pdu_async(il, C_RXON_ASSOC, sizeof(rxon_assoc), | 1330 | il_send_cmd_pdu_async(il, C_RXON_ASSOC, sizeof(rxon_assoc), |
@@ -1411,23 +1334,20 @@ il4965_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) | |||
1411 | } | 1334 | } |
1412 | 1335 | ||
1413 | static int | 1336 | static int |
1414 | il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | 1337 | il4965_commit_rxon(struct il_priv *il) |
1415 | { | 1338 | { |
1416 | /* cast away the const for active_rxon in this function */ | 1339 | /* cast away the const for active_rxon in this function */ |
1417 | struct il_rxon_cmd *active_rxon = (void *)&ctx->active; | 1340 | struct il_rxon_cmd *active_rxon = (void *)&il->active; |
1418 | int ret; | 1341 | int ret; |
1419 | bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); | 1342 | bool new_assoc = !!(il->staging.filter_flags & RXON_FILTER_ASSOC_MSK); |
1420 | 1343 | ||
1421 | if (!il_is_alive(il)) | 1344 | if (!il_is_alive(il)) |
1422 | return -EBUSY; | 1345 | return -EBUSY; |
1423 | 1346 | ||
1424 | if (!ctx->is_active) | ||
1425 | return 0; | ||
1426 | |||
1427 | /* always get timestamp with Rx frame */ | 1347 | /* always get timestamp with Rx frame */ |
1428 | ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; | 1348 | il->staging.flags |= RXON_FLG_TSF2HOST_MSK; |
1429 | 1349 | ||
1430 | ret = il_check_rxon_cmd(il, ctx); | 1350 | ret = il_check_rxon_cmd(il); |
1431 | if (ret) { | 1351 | if (ret) { |
1432 | IL_ERR("Invalid RXON configuration. Not committing.\n"); | 1352 | IL_ERR("Invalid RXON configuration. Not committing.\n"); |
1433 | return -EINVAL; | 1353 | return -EINVAL; |
@@ -1438,7 +1358,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1438 | * abort any previous channel switch if still in process | 1358 | * abort any previous channel switch if still in process |
1439 | */ | 1359 | */ |
1440 | if (test_bit(S_CHANNEL_SWITCH_PENDING, &il->status) && | 1360 | if (test_bit(S_CHANNEL_SWITCH_PENDING, &il->status) && |
1441 | il->switch_channel != ctx->staging.channel) { | 1361 | il->switch_channel != il->staging.channel) { |
1442 | D_11H("abort channel switch on %d\n", | 1362 | D_11H("abort channel switch on %d\n", |
1443 | le16_to_cpu(il->switch_channel)); | 1363 | le16_to_cpu(il->switch_channel)); |
1444 | il_chswitch_done(il, false); | 1364 | il_chswitch_done(il, false); |
@@ -1447,15 +1367,15 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1447 | /* If we don't need to send a full RXON, we can use | 1367 | /* If we don't need to send a full RXON, we can use |
1448 | * il_rxon_assoc_cmd which is used to reconfigure filter | 1368 | * il_rxon_assoc_cmd which is used to reconfigure filter |
1449 | * and other flags for the current radio configuration. */ | 1369 | * and other flags for the current radio configuration. */ |
1450 | if (!il_full_rxon_required(il, ctx)) { | 1370 | if (!il_full_rxon_required(il)) { |
1451 | ret = il_send_rxon_assoc(il, ctx); | 1371 | ret = il_send_rxon_assoc(il); |
1452 | if (ret) { | 1372 | if (ret) { |
1453 | IL_ERR("Error setting RXON_ASSOC (%d)\n", ret); | 1373 | IL_ERR("Error setting RXON_ASSOC (%d)\n", ret); |
1454 | return ret; | 1374 | return ret; |
1455 | } | 1375 | } |
1456 | 1376 | ||
1457 | memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); | 1377 | memcpy(active_rxon, &il->staging, sizeof(*active_rxon)); |
1458 | il_print_rx_config_cmd(il, ctx); | 1378 | il_print_rx_config_cmd(il); |
1459 | /* | 1379 | /* |
1460 | * We do not commit tx power settings while channel changing, | 1380 | * We do not commit tx power settings while channel changing, |
1461 | * do it now if tx power changed. | 1381 | * do it now if tx power changed. |
@@ -1468,12 +1388,12 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1468 | * an RXON_ASSOC and the new config wants the associated mask enabled, | 1388 | * an RXON_ASSOC and the new config wants the associated mask enabled, |
1469 | * we must clear the associated from the active configuration | 1389 | * we must clear the associated from the active configuration |
1470 | * before we apply the new config */ | 1390 | * before we apply the new config */ |
1471 | if (il_is_associated_ctx(ctx) && new_assoc) { | 1391 | if (il_is_associated(il) && new_assoc) { |
1472 | D_INFO("Toggling associated bit on current RXON\n"); | 1392 | D_INFO("Toggling associated bit on current RXON\n"); |
1473 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 1393 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
1474 | 1394 | ||
1475 | ret = | 1395 | ret = |
1476 | il_send_cmd_pdu(il, ctx->rxon_cmd, | 1396 | il_send_cmd_pdu(il, C_RXON, |
1477 | sizeof(struct il_rxon_cmd), active_rxon); | 1397 | sizeof(struct il_rxon_cmd), active_rxon); |
1478 | 1398 | ||
1479 | /* If the mask clearing failed then we set | 1399 | /* If the mask clearing failed then we set |
@@ -1483,9 +1403,9 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1483 | IL_ERR("Error clearing ASSOC_MSK (%d)\n", ret); | 1403 | IL_ERR("Error clearing ASSOC_MSK (%d)\n", ret); |
1484 | return ret; | 1404 | return ret; |
1485 | } | 1405 | } |
1486 | il_clear_ucode_stations(il, ctx); | 1406 | il_clear_ucode_stations(il); |
1487 | il_restore_stations(il, ctx); | 1407 | il_restore_stations(il); |
1488 | ret = il4965_restore_default_wep_keys(il, ctx); | 1408 | ret = il4965_restore_default_wep_keys(il); |
1489 | if (ret) { | 1409 | if (ret) { |
1490 | IL_ERR("Failed to restore WEP keys (%d)\n", ret); | 1410 | IL_ERR("Failed to restore WEP keys (%d)\n", ret); |
1491 | return ret; | 1411 | return ret; |
@@ -1494,9 +1414,9 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1494 | 1414 | ||
1495 | D_INFO("Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n" | 1415 | D_INFO("Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n" |
1496 | "* channel = %d\n" "* bssid = %pM\n", (new_assoc ? "" : "out"), | 1416 | "* channel = %d\n" "* bssid = %pM\n", (new_assoc ? "" : "out"), |
1497 | le16_to_cpu(ctx->staging.channel), ctx->staging.bssid_addr); | 1417 | le16_to_cpu(il->staging.channel), il->staging.bssid_addr); |
1498 | 1418 | ||
1499 | il_set_rxon_hwcrypto(il, ctx, !il->cfg->mod_params->sw_crypto); | 1419 | il_set_rxon_hwcrypto(il, !il->cfg->mod_params->sw_crypto); |
1500 | 1420 | ||
1501 | /* Apply the new configuration | 1421 | /* Apply the new configuration |
1502 | * RXON unassoc clears the station table in uCode so restoration of | 1422 | * RXON unassoc clears the station table in uCode so restoration of |
@@ -1504,17 +1424,17 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1504 | */ | 1424 | */ |
1505 | if (!new_assoc) { | 1425 | if (!new_assoc) { |
1506 | ret = | 1426 | ret = |
1507 | il_send_cmd_pdu(il, ctx->rxon_cmd, | 1427 | il_send_cmd_pdu(il, C_RXON, |
1508 | sizeof(struct il_rxon_cmd), &ctx->staging); | 1428 | sizeof(struct il_rxon_cmd), &il->staging); |
1509 | if (ret) { | 1429 | if (ret) { |
1510 | IL_ERR("Error setting new RXON (%d)\n", ret); | 1430 | IL_ERR("Error setting new RXON (%d)\n", ret); |
1511 | return ret; | 1431 | return ret; |
1512 | } | 1432 | } |
1513 | D_INFO("Return from !new_assoc RXON.\n"); | 1433 | D_INFO("Return from !new_assoc RXON.\n"); |
1514 | memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); | 1434 | memcpy(active_rxon, &il->staging, sizeof(*active_rxon)); |
1515 | il_clear_ucode_stations(il, ctx); | 1435 | il_clear_ucode_stations(il); |
1516 | il_restore_stations(il, ctx); | 1436 | il_restore_stations(il); |
1517 | ret = il4965_restore_default_wep_keys(il, ctx); | 1437 | ret = il4965_restore_default_wep_keys(il); |
1518 | if (ret) { | 1438 | if (ret) { |
1519 | IL_ERR("Failed to restore WEP keys (%d)\n", ret); | 1439 | IL_ERR("Failed to restore WEP keys (%d)\n", ret); |
1520 | return ret; | 1440 | return ret; |
@@ -1526,15 +1446,15 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | |||
1526 | * RXON assoc doesn't clear the station table in uCode, | 1446 | * RXON assoc doesn't clear the station table in uCode, |
1527 | */ | 1447 | */ |
1528 | ret = | 1448 | ret = |
1529 | il_send_cmd_pdu(il, ctx->rxon_cmd, | 1449 | il_send_cmd_pdu(il, C_RXON, |
1530 | sizeof(struct il_rxon_cmd), &ctx->staging); | 1450 | sizeof(struct il_rxon_cmd), &il->staging); |
1531 | if (ret) { | 1451 | if (ret) { |
1532 | IL_ERR("Error setting new RXON (%d)\n", ret); | 1452 | IL_ERR("Error setting new RXON (%d)\n", ret); |
1533 | return ret; | 1453 | return ret; |
1534 | } | 1454 | } |
1535 | memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); | 1455 | memcpy(active_rxon, &il->staging, sizeof(*active_rxon)); |
1536 | } | 1456 | } |
1537 | il_print_rx_config_cmd(il, ctx); | 1457 | il_print_rx_config_cmd(il); |
1538 | 1458 | ||
1539 | il4965_init_sensitivity(il); | 1459 | il4965_init_sensitivity(il); |
1540 | 1460 | ||
@@ -1553,7 +1473,6 @@ static int | |||
1553 | il4965_hw_channel_switch(struct il_priv *il, | 1473 | il4965_hw_channel_switch(struct il_priv *il, |
1554 | struct ieee80211_channel_switch *ch_switch) | 1474 | struct ieee80211_channel_switch *ch_switch) |
1555 | { | 1475 | { |
1556 | struct il_rxon_context *ctx = &il->ctx; | ||
1557 | int rc; | 1476 | int rc; |
1558 | u8 band = 0; | 1477 | u8 band = 0; |
1559 | bool is_ht40 = false; | 1478 | bool is_ht40 = false; |
@@ -1564,21 +1483,24 @@ il4965_hw_channel_switch(struct il_priv *il, | |||
1564 | u16 ch; | 1483 | u16 ch; |
1565 | u32 tsf_low; | 1484 | u32 tsf_low; |
1566 | u8 switch_count; | 1485 | u8 switch_count; |
1567 | u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); | 1486 | u16 beacon_interval = le16_to_cpu(il->timing.beacon_interval); |
1568 | struct ieee80211_vif *vif = ctx->vif; | 1487 | struct ieee80211_vif *vif = il->vif; |
1569 | band = il->band == IEEE80211_BAND_2GHZ; | 1488 | band = (il->band == IEEE80211_BAND_2GHZ); |
1570 | 1489 | ||
1571 | is_ht40 = iw4965_is_ht40_channel(ctx->staging.flags); | 1490 | if (WARN_ON_ONCE(vif == NULL)) |
1491 | return -EIO; | ||
1492 | |||
1493 | is_ht40 = iw4965_is_ht40_channel(il->staging.flags); | ||
1572 | 1494 | ||
1573 | if (is_ht40 && (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) | 1495 | if (is_ht40 && (il->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) |
1574 | ctrl_chan_high = 1; | 1496 | ctrl_chan_high = 1; |
1575 | 1497 | ||
1576 | cmd.band = band; | 1498 | cmd.band = band; |
1577 | cmd.expect_beacon = 0; | 1499 | cmd.expect_beacon = 0; |
1578 | ch = ch_switch->channel->hw_value; | 1500 | ch = ch_switch->channel->hw_value; |
1579 | cmd.channel = cpu_to_le16(ch); | 1501 | cmd.channel = cpu_to_le16(ch); |
1580 | cmd.rxon_flags = ctx->staging.flags; | 1502 | cmd.rxon_flags = il->staging.flags; |
1581 | cmd.rxon_filter_flags = ctx->staging.filter_flags; | 1503 | cmd.rxon_filter_flags = il->staging.filter_flags; |
1582 | switch_count = ch_switch->count; | 1504 | switch_count = ch_switch->count; |
1583 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | 1505 | tsf_low = ch_switch->timestamp & 0x0ffffffff; |
1584 | /* | 1506 | /* |
@@ -1611,7 +1533,7 @@ il4965_hw_channel_switch(struct il_priv *il, | |||
1611 | cmd.expect_beacon = il_is_channel_radar(ch_info); | 1533 | cmd.expect_beacon = il_is_channel_radar(ch_info); |
1612 | else { | 1534 | else { |
1613 | IL_ERR("invalid channel switch from %u to %u\n", | 1535 | IL_ERR("invalid channel switch from %u to %u\n", |
1614 | ctx->active.channel, ch); | 1536 | il->active.channel, ch); |
1615 | return -EFAULT; | 1537 | return -EFAULT; |
1616 | } | 1538 | } |
1617 | 1539 | ||
@@ -1876,7 +1798,7 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, | |||
1876 | D_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", | 1798 | D_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", |
1877 | agg->frame_count, agg->start_idx, idx); | 1799 | agg->frame_count, agg->start_idx, idx); |
1878 | 1800 | ||
1879 | info = IEEE80211_SKB_CB(il->txq[txq_id].txb[idx].skb); | 1801 | info = IEEE80211_SKB_CB(il->txq[txq_id].skbs[idx]); |
1880 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1802 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1881 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1803 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1882 | info->flags |= il4965_tx_status_to_mac80211(status); | 1804 | info->flags |= il4965_tx_status_to_mac80211(status); |
@@ -1891,6 +1813,7 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, | |||
1891 | /* Two or more frames were attempted; expect block-ack */ | 1813 | /* Two or more frames were attempted; expect block-ack */ |
1892 | u64 bitmap = 0; | 1814 | u64 bitmap = 0; |
1893 | int start = agg->start_idx; | 1815 | int start = agg->start_idx; |
1816 | struct sk_buff *skb; | ||
1894 | 1817 | ||
1895 | /* Construct bit-map of pending frames within Tx win */ | 1818 | /* Construct bit-map of pending frames within Tx win */ |
1896 | for (i = 0; i < agg->frame_count; i++) { | 1819 | for (i = 0; i < agg->frame_count; i++) { |
@@ -1908,12 +1831,10 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, | |||
1908 | D_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n", | 1831 | D_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n", |
1909 | agg->frame_count, txq_id, idx); | 1832 | agg->frame_count, txq_id, idx); |
1910 | 1833 | ||
1911 | hdr = il_tx_queue_get_hdr(il, txq_id, idx); | 1834 | skb = il->txq[txq_id].skbs[idx]; |
1912 | if (!hdr) { | 1835 | if (WARN_ON_ONCE(skb == NULL)) |
1913 | IL_ERR("BUG_ON idx doesn't point to valid skb" | ||
1914 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
1915 | return -1; | 1836 | return -1; |
1916 | } | 1837 | hdr = (struct ieee80211_hdr *) skb->data; |
1917 | 1838 | ||
1918 | sc = le16_to_cpu(hdr->seq_ctrl); | 1839 | sc = le16_to_cpu(hdr->seq_ctrl); |
1919 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | 1840 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { |
@@ -1969,7 +1890,7 @@ il4965_find_station(struct il_priv *il, const u8 * addr) | |||
1969 | start = IL_STA_ID; | 1890 | start = IL_STA_ID; |
1970 | 1891 | ||
1971 | if (is_broadcast_ether_addr(addr)) | 1892 | if (is_broadcast_ether_addr(addr)) |
1972 | return il->ctx.bcast_sta_id; | 1893 | return il->hw_params.bcast_id; |
1973 | 1894 | ||
1974 | spin_lock_irqsave(&il->sta_lock, flags); | 1895 | spin_lock_irqsave(&il->sta_lock, flags); |
1975 | for (i = start; i < il->hw_params.max_stations; i++) | 1896 | for (i = start; i < il->hw_params.max_stations; i++) |
@@ -2021,6 +1942,7 @@ il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) | |||
2021 | int txq_id = SEQ_TO_QUEUE(sequence); | 1942 | int txq_id = SEQ_TO_QUEUE(sequence); |
2022 | int idx = SEQ_TO_IDX(sequence); | 1943 | int idx = SEQ_TO_IDX(sequence); |
2023 | struct il_tx_queue *txq = &il->txq[txq_id]; | 1944 | struct il_tx_queue *txq = &il->txq[txq_id]; |
1945 | struct sk_buff *skb; | ||
2024 | struct ieee80211_hdr *hdr; | 1946 | struct ieee80211_hdr *hdr; |
2025 | struct ieee80211_tx_info *info; | 1947 | struct ieee80211_tx_info *info; |
2026 | struct il4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | 1948 | struct il4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; |
@@ -2039,10 +1961,12 @@ il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) | |||
2039 | } | 1961 | } |
2040 | 1962 | ||
2041 | txq->time_stamp = jiffies; | 1963 | txq->time_stamp = jiffies; |
2042 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); | 1964 | |
1965 | skb = txq->skbs[txq->q.read_ptr]; | ||
1966 | info = IEEE80211_SKB_CB(skb); | ||
2043 | memset(&info->status, 0, sizeof(info->status)); | 1967 | memset(&info->status, 0, sizeof(info->status)); |
2044 | 1968 | ||
2045 | hdr = il_tx_queue_get_hdr(il, txq_id, idx); | 1969 | hdr = (struct ieee80211_hdr *) skb->data; |
2046 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 1970 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
2047 | qc = ieee80211_get_qos_ctl(hdr); | 1971 | qc = ieee80211_get_qos_ctl(hdr); |
2048 | tid = qc[0] & 0xf; | 1972 | tid = qc[0] & 0xf; |
@@ -2133,21 +2057,18 @@ static struct il_hcmd_ops il4965_hcmd = { | |||
2133 | static void | 2057 | static void |
2134 | il4965_post_scan(struct il_priv *il) | 2058 | il4965_post_scan(struct il_priv *il) |
2135 | { | 2059 | { |
2136 | struct il_rxon_context *ctx = &il->ctx; | ||
2137 | |||
2138 | /* | 2060 | /* |
2139 | * Since setting the RXON may have been deferred while | 2061 | * Since setting the RXON may have been deferred while |
2140 | * performing the scan, fire one off if needed | 2062 | * performing the scan, fire one off if needed |
2141 | */ | 2063 | */ |
2142 | if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) | 2064 | if (memcmp(&il->staging, &il->active, sizeof(il->staging))) |
2143 | il_commit_rxon(il, ctx); | 2065 | il_commit_rxon(il); |
2144 | } | 2066 | } |
2145 | 2067 | ||
2146 | static void | 2068 | static void |
2147 | il4965_post_associate(struct il_priv *il) | 2069 | il4965_post_associate(struct il_priv *il) |
2148 | { | 2070 | { |
2149 | struct il_rxon_context *ctx = &il->ctx; | 2071 | struct ieee80211_vif *vif = il->vif; |
2150 | struct ieee80211_vif *vif = ctx->vif; | ||
2151 | struct ieee80211_conf *conf = NULL; | 2072 | struct ieee80211_conf *conf = NULL; |
2152 | int ret = 0; | 2073 | int ret = 0; |
2153 | 2074 | ||
@@ -2161,41 +2082,41 @@ il4965_post_associate(struct il_priv *il) | |||
2161 | 2082 | ||
2162 | conf = &il->hw->conf; | 2083 | conf = &il->hw->conf; |
2163 | 2084 | ||
2164 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2085 | il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2165 | il_commit_rxon(il, ctx); | 2086 | il_commit_rxon(il); |
2166 | 2087 | ||
2167 | ret = il_send_rxon_timing(il, ctx); | 2088 | ret = il_send_rxon_timing(il); |
2168 | if (ret) | 2089 | if (ret) |
2169 | IL_WARN("RXON timing - " "Attempting to continue.\n"); | 2090 | IL_WARN("RXON timing - " "Attempting to continue.\n"); |
2170 | 2091 | ||
2171 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2092 | il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2172 | 2093 | ||
2173 | il_set_rxon_ht(il, &il->current_ht_config); | 2094 | il_set_rxon_ht(il, &il->current_ht_config); |
2174 | 2095 | ||
2175 | if (il->cfg->ops->hcmd->set_rxon_chain) | 2096 | if (il->ops->hcmd->set_rxon_chain) |
2176 | il->cfg->ops->hcmd->set_rxon_chain(il, ctx); | 2097 | il->ops->hcmd->set_rxon_chain(il); |
2177 | 2098 | ||
2178 | ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); | 2099 | il->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); |
2179 | 2100 | ||
2180 | D_ASSOC("assoc id %d beacon interval %d\n", vif->bss_conf.aid, | 2101 | D_ASSOC("assoc id %d beacon interval %d\n", vif->bss_conf.aid, |
2181 | vif->bss_conf.beacon_int); | 2102 | vif->bss_conf.beacon_int); |
2182 | 2103 | ||
2183 | if (vif->bss_conf.use_short_preamble) | 2104 | if (vif->bss_conf.use_short_preamble) |
2184 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 2105 | il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2185 | else | 2106 | else |
2186 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 2107 | il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2187 | 2108 | ||
2188 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { | 2109 | if (il->staging.flags & RXON_FLG_BAND_24G_MSK) { |
2189 | if (vif->bss_conf.use_short_slot) | 2110 | if (vif->bss_conf.use_short_slot) |
2190 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | 2111 | il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2191 | else | 2112 | else |
2192 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2113 | il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2193 | } | 2114 | } |
2194 | 2115 | ||
2195 | il_commit_rxon(il, ctx); | 2116 | il_commit_rxon(il); |
2196 | 2117 | ||
2197 | D_ASSOC("Associated as %d to: %pM\n", vif->bss_conf.aid, | 2118 | D_ASSOC("Associated as %d to: %pM\n", vif->bss_conf.aid, |
2198 | ctx->active.bssid_addr); | 2119 | il->active.bssid_addr); |
2199 | 2120 | ||
2200 | switch (vif->type) { | 2121 | switch (vif->type) { |
2201 | case NL80211_IFTYPE_STATION: | 2122 | case NL80211_IFTYPE_STATION: |
@@ -2223,8 +2144,7 @@ il4965_post_associate(struct il_priv *il) | |||
2223 | static void | 2144 | static void |
2224 | il4965_config_ap(struct il_priv *il) | 2145 | il4965_config_ap(struct il_priv *il) |
2225 | { | 2146 | { |
2226 | struct il_rxon_context *ctx = &il->ctx; | 2147 | struct ieee80211_vif *vif = il->vif; |
2227 | struct ieee80211_vif *vif = ctx->vif; | ||
2228 | int ret = 0; | 2148 | int ret = 0; |
2229 | 2149 | ||
2230 | lockdep_assert_held(&il->mutex); | 2150 | lockdep_assert_held(&il->mutex); |
@@ -2233,14 +2153,14 @@ il4965_config_ap(struct il_priv *il) | |||
2233 | return; | 2153 | return; |
2234 | 2154 | ||
2235 | /* The following should be done only at AP bring up */ | 2155 | /* The following should be done only at AP bring up */ |
2236 | if (!il_is_associated_ctx(ctx)) { | 2156 | if (!il_is_associated(il)) { |
2237 | 2157 | ||
2238 | /* RXON - unassoc (to set timing command) */ | 2158 | /* RXON - unassoc (to set timing command) */ |
2239 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2159 | il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2240 | il_commit_rxon(il, ctx); | 2160 | il_commit_rxon(il); |
2241 | 2161 | ||
2242 | /* RXON Timing */ | 2162 | /* RXON Timing */ |
2243 | ret = il_send_rxon_timing(il, ctx); | 2163 | ret = il_send_rxon_timing(il); |
2244 | if (ret) | 2164 | if (ret) |
2245 | IL_WARN("RXON timing failed - " | 2165 | IL_WARN("RXON timing failed - " |
2246 | "Attempting to continue.\n"); | 2166 | "Attempting to continue.\n"); |
@@ -2248,27 +2168,27 @@ il4965_config_ap(struct il_priv *il) | |||
2248 | /* AP has all antennas */ | 2168 | /* AP has all antennas */ |
2249 | il->chain_noise_data.active_chains = il->hw_params.valid_rx_ant; | 2169 | il->chain_noise_data.active_chains = il->hw_params.valid_rx_ant; |
2250 | il_set_rxon_ht(il, &il->current_ht_config); | 2170 | il_set_rxon_ht(il, &il->current_ht_config); |
2251 | if (il->cfg->ops->hcmd->set_rxon_chain) | 2171 | if (il->ops->hcmd->set_rxon_chain) |
2252 | il->cfg->ops->hcmd->set_rxon_chain(il, ctx); | 2172 | il->ops->hcmd->set_rxon_chain(il); |
2253 | 2173 | ||
2254 | ctx->staging.assoc_id = 0; | 2174 | il->staging.assoc_id = 0; |
2255 | 2175 | ||
2256 | if (vif->bss_conf.use_short_preamble) | 2176 | if (vif->bss_conf.use_short_preamble) |
2257 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 2177 | il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2258 | else | 2178 | else |
2259 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 2179 | il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2260 | 2180 | ||
2261 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { | 2181 | if (il->staging.flags & RXON_FLG_BAND_24G_MSK) { |
2262 | if (vif->bss_conf.use_short_slot) | 2182 | if (vif->bss_conf.use_short_slot) |
2263 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | 2183 | il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2264 | else | 2184 | else |
2265 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2185 | il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2266 | } | 2186 | } |
2267 | /* need to send beacon cmd before committing assoc RXON! */ | 2187 | /* need to send beacon cmd before committing assoc RXON! */ |
2268 | il4965_send_beacon_cmd(il); | 2188 | il4965_send_beacon_cmd(il); |
2269 | /* restore RXON assoc */ | 2189 | /* restore RXON assoc */ |
2270 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2190 | il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2271 | il_commit_rxon(il, ctx); | 2191 | il_commit_rxon(il); |
2272 | } | 2192 | } |
2273 | il4965_send_beacon_cmd(il); | 2193 | il4965_send_beacon_cmd(il); |
2274 | } | 2194 | } |
@@ -2281,7 +2201,6 @@ static struct il_hcmd_utils_ops il4965_hcmd_utils = { | |||
2281 | }; | 2201 | }; |
2282 | 2202 | ||
2283 | static struct il_lib_ops il4965_lib = { | 2203 | static struct il_lib_ops il4965_lib = { |
2284 | .set_hw_params = il4965_hw_set_hw_params, | ||
2285 | .txq_update_byte_cnt_tbl = il4965_txq_update_byte_cnt_tbl, | 2204 | .txq_update_byte_cnt_tbl = il4965_txq_update_byte_cnt_tbl, |
2286 | .txq_attach_buf_to_tfd = il4965_hw_txq_attach_buf_to_tfd, | 2205 | .txq_attach_buf_to_tfd = il4965_hw_txq_attach_buf_to_tfd, |
2287 | .txq_free_tfd = il4965_hw_txq_free_tfd, | 2206 | .txq_free_tfd = il4965_hw_txq_free_tfd, |
@@ -2330,51 +2249,12 @@ static const struct il_legacy_ops il4965_legacy_ops = { | |||
2330 | .update_bcast_stations = il4965_update_bcast_stations, | 2249 | .update_bcast_stations = il4965_update_bcast_stations, |
2331 | }; | 2250 | }; |
2332 | 2251 | ||
2333 | struct ieee80211_ops il4965_hw_ops = { | 2252 | const struct il_ops il4965_ops = { |
2334 | .tx = il4965_mac_tx, | ||
2335 | .start = il4965_mac_start, | ||
2336 | .stop = il4965_mac_stop, | ||
2337 | .add_interface = il_mac_add_interface, | ||
2338 | .remove_interface = il_mac_remove_interface, | ||
2339 | .change_interface = il_mac_change_interface, | ||
2340 | .config = il_mac_config, | ||
2341 | .configure_filter = il4965_configure_filter, | ||
2342 | .set_key = il4965_mac_set_key, | ||
2343 | .update_tkip_key = il4965_mac_update_tkip_key, | ||
2344 | .conf_tx = il_mac_conf_tx, | ||
2345 | .reset_tsf = il_mac_reset_tsf, | ||
2346 | .bss_info_changed = il_mac_bss_info_changed, | ||
2347 | .ampdu_action = il4965_mac_ampdu_action, | ||
2348 | .hw_scan = il_mac_hw_scan, | ||
2349 | .sta_add = il4965_mac_sta_add, | ||
2350 | .sta_remove = il_mac_sta_remove, | ||
2351 | .channel_switch = il4965_mac_channel_switch, | ||
2352 | .tx_last_beacon = il_mac_tx_last_beacon, | ||
2353 | }; | ||
2354 | |||
2355 | static const struct il_ops il4965_ops = { | ||
2356 | .lib = &il4965_lib, | 2253 | .lib = &il4965_lib, |
2357 | .hcmd = &il4965_hcmd, | 2254 | .hcmd = &il4965_hcmd, |
2358 | .utils = &il4965_hcmd_utils, | 2255 | .utils = &il4965_hcmd_utils, |
2359 | .led = &il4965_led_ops, | 2256 | .led = &il4965_led_ops, |
2360 | .legacy = &il4965_legacy_ops, | 2257 | .legacy = &il4965_legacy_ops, |
2361 | .ieee80211_ops = &il4965_hw_ops, | ||
2362 | }; | ||
2363 | |||
2364 | static struct il_base_params il4965_base_params = { | ||
2365 | .eeprom_size = IL4965_EEPROM_IMG_SIZE, | ||
2366 | .num_of_queues = IL49_NUM_QUEUES, | ||
2367 | .num_of_ampdu_queues = IL49_NUM_AMPDU_QUEUES, | ||
2368 | .pll_cfg_val = 0, | ||
2369 | .set_l0s = true, | ||
2370 | .use_bsm = true, | ||
2371 | .led_compensation = 61, | ||
2372 | .chain_noise_num_beacons = IL4965_CAL_NUM_BEACONS, | ||
2373 | .wd_timeout = IL_DEF_WD_TIMEOUT, | ||
2374 | .temperature_kelvin = true, | ||
2375 | .ucode_tracing = true, | ||
2376 | .sensitivity_calib_by_driver = true, | ||
2377 | .chain_noise_calib_by_driver = true, | ||
2378 | }; | 2258 | }; |
2379 | 2259 | ||
2380 | struct il_cfg il4965_cfg = { | 2260 | struct il_cfg il4965_cfg = { |
@@ -2387,15 +2267,27 @@ struct il_cfg il4965_cfg = { | |||
2387 | .valid_rx_ant = ANT_ABC, | 2267 | .valid_rx_ant = ANT_ABC, |
2388 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, | 2268 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, |
2389 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, | 2269 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, |
2390 | .ops = &il4965_ops, | ||
2391 | .mod_params = &il4965_mod_params, | 2270 | .mod_params = &il4965_mod_params, |
2392 | .base_params = &il4965_base_params, | ||
2393 | .led_mode = IL_LED_BLINK, | 2271 | .led_mode = IL_LED_BLINK, |
2394 | /* | 2272 | /* |
2395 | * Force use of chains B and C for scan RX on 5 GHz band | 2273 | * Force use of chains B and C for scan RX on 5 GHz band |
2396 | * because the device has off-channel reception on chain A. | 2274 | * because the device has off-channel reception on chain A. |
2397 | */ | 2275 | */ |
2398 | .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, | 2276 | .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, |
2277 | |||
2278 | .eeprom_size = IL4965_EEPROM_IMG_SIZE, | ||
2279 | .num_of_queues = IL49_NUM_QUEUES, | ||
2280 | .num_of_ampdu_queues = IL49_NUM_AMPDU_QUEUES, | ||
2281 | .pll_cfg_val = 0, | ||
2282 | .set_l0s = true, | ||
2283 | .use_bsm = true, | ||
2284 | .led_compensation = 61, | ||
2285 | .chain_noise_num_beacons = IL4965_CAL_NUM_BEACONS, | ||
2286 | .wd_timeout = IL_DEF_WD_TIMEOUT, | ||
2287 | .temperature_kelvin = true, | ||
2288 | .ucode_tracing = true, | ||
2289 | .sensitivity_calib_by_driver = true, | ||
2290 | .chain_noise_calib_by_driver = true, | ||
2399 | }; | 2291 | }; |
2400 | 2292 | ||
2401 | /* Module firmware */ | 2293 | /* Module firmware */ |
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index f280e0161b17..83ab60496388 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h | |||
@@ -38,17 +38,16 @@ struct il_rxon_context; | |||
38 | 38 | ||
39 | /* configuration for the _4965 devices */ | 39 | /* configuration for the _4965 devices */ |
40 | extern struct il_cfg il4965_cfg; | 40 | extern struct il_cfg il4965_cfg; |
41 | extern const struct il_ops il4965_ops; | ||
41 | 42 | ||
42 | extern struct il_mod_params il4965_mod_params; | 43 | extern struct il_mod_params il4965_mod_params; |
43 | 44 | ||
44 | extern struct ieee80211_ops il4965_hw_ops; | ||
45 | |||
46 | /* tx queue */ | 45 | /* tx queue */ |
47 | void il4965_free_tfds_in_queue(struct il_priv *il, int sta_id, int tid, | 46 | void il4965_free_tfds_in_queue(struct il_priv *il, int sta_id, int tid, |
48 | int freed); | 47 | int freed); |
49 | 48 | ||
50 | /* RXON */ | 49 | /* RXON */ |
51 | void il4965_set_rxon_chain(struct il_priv *il, struct il_rxon_context *ctx); | 50 | void il4965_set_rxon_chain(struct il_priv *il); |
52 | 51 | ||
53 | /* uCode */ | 52 | /* uCode */ |
54 | int il4965_verify_ucode(struct il_priv *il); | 53 | int il4965_verify_ucode(struct il_priv *il); |
@@ -134,21 +133,18 @@ il4965_get_tx_fail_reason(u32 status) | |||
134 | #endif | 133 | #endif |
135 | 134 | ||
136 | /* station management */ | 135 | /* station management */ |
137 | int il4965_alloc_bcast_station(struct il_priv *il, struct il_rxon_context *ctx); | 136 | int il4965_alloc_bcast_station(struct il_priv *il); |
138 | int il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, | 137 | int il4965_add_bssid_station(struct il_priv *il, const u8 *addr, u8 *sta_id_r); |
139 | const u8 *addr, u8 *sta_id_r); | ||
140 | int il4965_remove_default_wep_key(struct il_priv *il, | 138 | int il4965_remove_default_wep_key(struct il_priv *il, |
141 | struct il_rxon_context *ctx, | ||
142 | struct ieee80211_key_conf *key); | 139 | struct ieee80211_key_conf *key); |
143 | int il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, | 140 | int il4965_set_default_wep_key(struct il_priv *il, |
144 | struct ieee80211_key_conf *key); | 141 | struct ieee80211_key_conf *key); |
145 | int il4965_restore_default_wep_keys(struct il_priv *il, | 142 | int il4965_restore_default_wep_keys(struct il_priv *il); |
146 | struct il_rxon_context *ctx); | 143 | int il4965_set_dynamic_key(struct il_priv *il, |
147 | int il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, | ||
148 | struct ieee80211_key_conf *key, u8 sta_id); | 144 | struct ieee80211_key_conf *key, u8 sta_id); |
149 | int il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, | 145 | int il4965_remove_dynamic_key(struct il_priv *il, |
150 | struct ieee80211_key_conf *key, u8 sta_id); | 146 | struct ieee80211_key_conf *key, u8 sta_id); |
151 | void il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx, | 147 | void il4965_update_tkip_key(struct il_priv *il, |
152 | struct ieee80211_key_conf *keyconf, | 148 | struct ieee80211_key_conf *keyconf, |
153 | struct ieee80211_sta *sta, u32 iv32, | 149 | struct ieee80211_sta *sta, u32 iv32, |
154 | u16 *phase1key); | 150 | u16 *phase1key); |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 36454d0bbeed..04ec38e5eaaf 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -512,15 +512,15 @@ il_led_cmd(struct il_priv *il, unsigned long on, unsigned long off) | |||
512 | } | 512 | } |
513 | 513 | ||
514 | D_LED("Led blink time compensation=%u\n", | 514 | D_LED("Led blink time compensation=%u\n", |
515 | il->cfg->base_params->led_compensation); | 515 | il->cfg->led_compensation); |
516 | led_cmd.on = | 516 | led_cmd.on = |
517 | il_blink_compensation(il, on, | 517 | il_blink_compensation(il, on, |
518 | il->cfg->base_params->led_compensation); | 518 | il->cfg->led_compensation); |
519 | led_cmd.off = | 519 | led_cmd.off = |
520 | il_blink_compensation(il, off, | 520 | il_blink_compensation(il, off, |
521 | il->cfg->base_params->led_compensation); | 521 | il->cfg->led_compensation); |
522 | 522 | ||
523 | ret = il->cfg->ops->led->cmd(il, &led_cmd); | 523 | ret = il->ops->led->cmd(il, &led_cmd); |
524 | if (!ret) { | 524 | if (!ret) { |
525 | il->blink_on = on; | 525 | il->blink_on = on; |
526 | il->blink_off = off; | 526 | il->blink_off = off; |
@@ -691,7 +691,7 @@ il_eeprom_verify_signature(struct il_priv *il) | |||
691 | const u8 * | 691 | const u8 * |
692 | il_eeprom_query_addr(const struct il_priv *il, size_t offset) | 692 | il_eeprom_query_addr(const struct il_priv *il, size_t offset) |
693 | { | 693 | { |
694 | BUG_ON(offset >= il->cfg->base_params->eeprom_size); | 694 | BUG_ON(offset >= il->cfg->eeprom_size); |
695 | return &il->eeprom[offset]; | 695 | return &il->eeprom[offset]; |
696 | } | 696 | } |
697 | EXPORT_SYMBOL(il_eeprom_query_addr); | 697 | EXPORT_SYMBOL(il_eeprom_query_addr); |
@@ -722,7 +722,7 @@ il_eeprom_init(struct il_priv *il) | |||
722 | u16 addr; | 722 | u16 addr; |
723 | 723 | ||
724 | /* allocate eeprom */ | 724 | /* allocate eeprom */ |
725 | sz = il->cfg->base_params->eeprom_size; | 725 | sz = il->cfg->eeprom_size; |
726 | D_EEPROM("NVM size = %d\n", sz); | 726 | D_EEPROM("NVM size = %d\n", sz); |
727 | il->eeprom = kzalloc(sz, GFP_KERNEL); | 727 | il->eeprom = kzalloc(sz, GFP_KERNEL); |
728 | if (!il->eeprom) { | 728 | if (!il->eeprom) { |
@@ -731,7 +731,7 @@ il_eeprom_init(struct il_priv *il) | |||
731 | } | 731 | } |
732 | e = (__le16 *) il->eeprom; | 732 | e = (__le16 *) il->eeprom; |
733 | 733 | ||
734 | il->cfg->ops->lib->apm_ops.init(il); | 734 | il->ops->lib->apm_ops.init(il); |
735 | 735 | ||
736 | ret = il_eeprom_verify_signature(il); | 736 | ret = il_eeprom_verify_signature(il); |
737 | if (ret < 0) { | 737 | if (ret < 0) { |
@@ -741,7 +741,7 @@ il_eeprom_init(struct il_priv *il) | |||
741 | } | 741 | } |
742 | 742 | ||
743 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ | 743 | /* Make sure driver (instead of uCode) is allowed to read EEPROM */ |
744 | ret = il->cfg->ops->lib->eeprom_ops.acquire_semaphore(il); | 744 | ret = il->ops->lib->eeprom_ops.acquire_semaphore(il); |
745 | if (ret < 0) { | 745 | if (ret < 0) { |
746 | IL_ERR("Failed to acquire EEPROM semaphore.\n"); | 746 | IL_ERR("Failed to acquire EEPROM semaphore.\n"); |
747 | ret = -ENOENT; | 747 | ret = -ENOENT; |
@@ -773,7 +773,7 @@ il_eeprom_init(struct il_priv *il) | |||
773 | 773 | ||
774 | ret = 0; | 774 | ret = 0; |
775 | done: | 775 | done: |
776 | il->cfg->ops->lib->eeprom_ops.release_semaphore(il); | 776 | il->ops->lib->eeprom_ops.release_semaphore(il); |
777 | 777 | ||
778 | err: | 778 | err: |
779 | if (ret) | 779 | if (ret) |
@@ -800,7 +800,7 @@ il_init_band_reference(const struct il_priv *il, int eep_band, | |||
800 | const u8 **eeprom_ch_idx) | 800 | const u8 **eeprom_ch_idx) |
801 | { | 801 | { |
802 | u32 offset = | 802 | u32 offset = |
803 | il->cfg->ops->lib->eeprom_ops.regulatory_bands[eep_band - 1]; | 803 | il->ops->lib->eeprom_ops.regulatory_bands[eep_band - 1]; |
804 | switch (eep_band) { | 804 | switch (eep_band) { |
805 | case 1: /* 2.4GHz band */ | 805 | case 1: /* 2.4GHz band */ |
806 | *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_1); | 806 | *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_1); |
@@ -1001,9 +1001,9 @@ il_init_channel_map(struct il_priv *il) | |||
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | /* Check if we do have HT40 channels */ | 1003 | /* Check if we do have HT40 channels */ |
1004 | if (il->cfg->ops->lib->eeprom_ops.regulatory_bands[5] == | 1004 | if (il->ops->lib->eeprom_ops.regulatory_bands[5] == |
1005 | EEPROM_REGULATORY_BAND_NO_HT40 && | 1005 | EEPROM_REGULATORY_BAND_NO_HT40 && |
1006 | il->cfg->ops->lib->eeprom_ops.regulatory_bands[6] == | 1006 | il->ops->lib->eeprom_ops.regulatory_bands[6] == |
1007 | EEPROM_REGULATORY_BAND_NO_HT40) | 1007 | EEPROM_REGULATORY_BAND_NO_HT40) |
1008 | return 0; | 1008 | return 0; |
1009 | 1009 | ||
@@ -1158,9 +1158,9 @@ il_power_set_mode(struct il_priv *il, struct il_powertable_cmd *cmd, bool force) | |||
1158 | if (!(cmd->flags & IL_POWER_DRIVER_ALLOW_SLEEP_MSK)) | 1158 | if (!(cmd->flags & IL_POWER_DRIVER_ALLOW_SLEEP_MSK)) |
1159 | clear_bit(S_POWER_PMI, &il->status); | 1159 | clear_bit(S_POWER_PMI, &il->status); |
1160 | 1160 | ||
1161 | if (il->cfg->ops->lib->update_chain_flags && update_chains) | 1161 | if (il->ops->lib->update_chain_flags && update_chains) |
1162 | il->cfg->ops->lib->update_chain_flags(il); | 1162 | il->ops->lib->update_chain_flags(il); |
1163 | else if (il->cfg->ops->lib->update_chain_flags) | 1163 | else if (il->ops->lib->update_chain_flags) |
1164 | D_POWER("Cannot update the power, chain noise " | 1164 | D_POWER("Cannot update the power, chain noise " |
1165 | "calibration running: %d\n", | 1165 | "calibration running: %d\n", |
1166 | il->chain_noise_data.state); | 1166 | il->chain_noise_data.state); |
@@ -1442,7 +1442,6 @@ u16 | |||
1442 | il_get_passive_dwell_time(struct il_priv *il, enum ieee80211_band band, | 1442 | il_get_passive_dwell_time(struct il_priv *il, enum ieee80211_band band, |
1443 | struct ieee80211_vif *vif) | 1443 | struct ieee80211_vif *vif) |
1444 | { | 1444 | { |
1445 | struct il_rxon_context *ctx = &il->ctx; | ||
1446 | u16 value; | 1445 | u16 value; |
1447 | 1446 | ||
1448 | u16 passive = | 1447 | u16 passive = |
@@ -1457,7 +1456,7 @@ il_get_passive_dwell_time(struct il_priv *il, enum ieee80211_band band, | |||
1457 | * dwell time to be 98% of the smallest beacon interval | 1456 | * dwell time to be 98% of the smallest beacon interval |
1458 | * (minus 2 * channel tune time) | 1457 | * (minus 2 * channel tune time) |
1459 | */ | 1458 | */ |
1460 | value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0; | 1459 | value = il->vif ? il->vif->bss_conf.beacon_int : 0; |
1461 | if (value > IL_PASSIVE_DWELL_BASE || !value) | 1460 | if (value > IL_PASSIVE_DWELL_BASE || !value) |
1462 | value = IL_PASSIVE_DWELL_BASE; | 1461 | value = IL_PASSIVE_DWELL_BASE; |
1463 | value = (value * 98) / 100 - IL_CHANNEL_TUNE_TIME * 2; | 1462 | value = (value * 98) / 100 - IL_CHANNEL_TUNE_TIME * 2; |
@@ -1486,7 +1485,7 @@ il_scan_initiate(struct il_priv *il, struct ieee80211_vif *vif) | |||
1486 | 1485 | ||
1487 | lockdep_assert_held(&il->mutex); | 1486 | lockdep_assert_held(&il->mutex); |
1488 | 1487 | ||
1489 | if (WARN_ON(!il->cfg->ops->utils->request_scan)) | 1488 | if (WARN_ON(!il->ops->utils->request_scan)) |
1490 | return -EOPNOTSUPP; | 1489 | return -EOPNOTSUPP; |
1491 | 1490 | ||
1492 | cancel_delayed_work(&il->scan_check); | 1491 | cancel_delayed_work(&il->scan_check); |
@@ -1511,7 +1510,7 @@ il_scan_initiate(struct il_priv *il, struct ieee80211_vif *vif) | |||
1511 | set_bit(S_SCANNING, &il->status); | 1510 | set_bit(S_SCANNING, &il->status); |
1512 | il->scan_start = jiffies; | 1511 | il->scan_start = jiffies; |
1513 | 1512 | ||
1514 | ret = il->cfg->ops->utils->request_scan(il, vif); | 1513 | ret = il->ops->utils->request_scan(il, vif); |
1515 | if (ret) { | 1514 | if (ret) { |
1516 | clear_bit(S_SCANNING, &il->status); | 1515 | clear_bit(S_SCANNING, &il->status); |
1517 | return ret; | 1516 | return ret; |
@@ -1673,7 +1672,7 @@ out_settings: | |||
1673 | il_power_set_mode(il, &il->power_data.sleep_cmd_next, false); | 1672 | il_power_set_mode(il, &il->power_data.sleep_cmd_next, false); |
1674 | il_set_tx_power(il, il->tx_power_next, false); | 1673 | il_set_tx_power(il, il->tx_power_next, false); |
1675 | 1674 | ||
1676 | il->cfg->ops->utils->post_scan(il); | 1675 | il->ops->utils->post_scan(il); |
1677 | 1676 | ||
1678 | out: | 1677 | out: |
1679 | mutex_unlock(&il->mutex); | 1678 | mutex_unlock(&il->mutex); |
@@ -1815,7 +1814,7 @@ il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags) | |||
1815 | might_sleep(); | 1814 | might_sleep(); |
1816 | } | 1815 | } |
1817 | 1816 | ||
1818 | cmd.len = il->cfg->ops->utils->build_addsta_hcmd(sta, data); | 1817 | cmd.len = il->ops->utils->build_addsta_hcmd(sta, data); |
1819 | ret = il_send_cmd(il, &cmd); | 1818 | ret = il_send_cmd(il, &cmd); |
1820 | 1819 | ||
1821 | if (ret || (flags & CMD_ASYNC)) | 1820 | if (ret || (flags & CMD_ASYNC)) |
@@ -1832,8 +1831,7 @@ il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags) | |||
1832 | EXPORT_SYMBOL(il_send_add_sta); | 1831 | EXPORT_SYMBOL(il_send_add_sta); |
1833 | 1832 | ||
1834 | static void | 1833 | static void |
1835 | il_set_ht_add_station(struct il_priv *il, u8 idx, struct ieee80211_sta *sta, | 1834 | il_set_ht_add_station(struct il_priv *il, u8 idx, struct ieee80211_sta *sta) |
1836 | struct il_rxon_context *ctx) | ||
1837 | { | 1835 | { |
1838 | struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap; | 1836 | struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap; |
1839 | __le32 sta_flags; | 1837 | __le32 sta_flags; |
@@ -1874,7 +1872,7 @@ il_set_ht_add_station(struct il_priv *il, u8 idx, struct ieee80211_sta *sta, | |||
1874 | cpu_to_le32((u32) sta_ht_inf-> | 1872 | cpu_to_le32((u32) sta_ht_inf-> |
1875 | ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); | 1873 | ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); |
1876 | 1874 | ||
1877 | if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap)) | 1875 | if (il_is_ht40_tx_allowed(il, &sta->ht_cap)) |
1878 | sta_flags |= STA_FLG_HT40_EN_MSK; | 1876 | sta_flags |= STA_FLG_HT40_EN_MSK; |
1879 | else | 1877 | else |
1880 | sta_flags &= ~STA_FLG_HT40_EN_MSK; | 1878 | sta_flags &= ~STA_FLG_HT40_EN_MSK; |
@@ -1890,8 +1888,8 @@ done: | |||
1890 | * should be called with sta_lock held | 1888 | * should be called with sta_lock held |
1891 | */ | 1889 | */ |
1892 | u8 | 1890 | u8 |
1893 | il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, | 1891 | il_prep_station(struct il_priv *il, const u8 *addr, bool is_ap, |
1894 | const u8 *addr, bool is_ap, struct ieee80211_sta *sta) | 1892 | struct ieee80211_sta *sta) |
1895 | { | 1893 | { |
1896 | struct il_station_entry *station; | 1894 | struct il_station_entry *station; |
1897 | int i; | 1895 | int i; |
@@ -1899,9 +1897,9 @@ il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, | |||
1899 | u16 rate; | 1897 | u16 rate; |
1900 | 1898 | ||
1901 | if (is_ap) | 1899 | if (is_ap) |
1902 | sta_id = ctx->ap_sta_id; | 1900 | sta_id = IL_AP_ID; |
1903 | else if (is_broadcast_ether_addr(addr)) | 1901 | else if (is_broadcast_ether_addr(addr)) |
1904 | sta_id = ctx->bcast_sta_id; | 1902 | sta_id = il->hw_params.bcast_id; |
1905 | else | 1903 | else |
1906 | for (i = IL_STA_ID; i < il->hw_params.max_stations; i++) { | 1904 | for (i = IL_STA_ID; i < il->hw_params.max_stations; i++) { |
1907 | if (!compare_ether_addr | 1905 | if (!compare_ether_addr |
@@ -1950,22 +1948,14 @@ il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, | |||
1950 | memcpy(station->sta.sta.addr, addr, ETH_ALEN); | 1948 | memcpy(station->sta.sta.addr, addr, ETH_ALEN); |
1951 | station->sta.mode = 0; | 1949 | station->sta.mode = 0; |
1952 | station->sta.sta.sta_id = sta_id; | 1950 | station->sta.sta.sta_id = sta_id; |
1953 | station->sta.station_flags = ctx->station_flags; | 1951 | station->sta.station_flags = 0; |
1954 | station->ctxid = ctx->ctxid; | ||
1955 | |||
1956 | if (sta) { | ||
1957 | struct il_station_priv_common *sta_priv; | ||
1958 | |||
1959 | sta_priv = (void *)sta->drv_priv; | ||
1960 | sta_priv->ctx = ctx; | ||
1961 | } | ||
1962 | 1952 | ||
1963 | /* | 1953 | /* |
1964 | * OK to call unconditionally, since local stations (IBSS BSSID | 1954 | * OK to call unconditionally, since local stations (IBSS BSSID |
1965 | * STA and broadcast STA) pass in a NULL sta, and mac80211 | 1955 | * STA and broadcast STA) pass in a NULL sta, and mac80211 |
1966 | * doesn't allow HT IBSS. | 1956 | * doesn't allow HT IBSS. |
1967 | */ | 1957 | */ |
1968 | il_set_ht_add_station(il, sta_id, sta, ctx); | 1958 | il_set_ht_add_station(il, sta_id, sta); |
1969 | 1959 | ||
1970 | /* 3945 only */ | 1960 | /* 3945 only */ |
1971 | rate = (il->band == IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP : RATE_1M_PLCP; | 1961 | rate = (il->band == IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP : RATE_1M_PLCP; |
@@ -1983,9 +1973,8 @@ EXPORT_SYMBOL_GPL(il_prep_station); | |||
1983 | * il_add_station_common - | 1973 | * il_add_station_common - |
1984 | */ | 1974 | */ |
1985 | int | 1975 | int |
1986 | il_add_station_common(struct il_priv *il, struct il_rxon_context *ctx, | 1976 | il_add_station_common(struct il_priv *il, const u8 *addr, bool is_ap, |
1987 | const u8 *addr, bool is_ap, struct ieee80211_sta *sta, | 1977 | struct ieee80211_sta *sta, u8 *sta_id_r) |
1988 | u8 *sta_id_r) | ||
1989 | { | 1978 | { |
1990 | unsigned long flags_spin; | 1979 | unsigned long flags_spin; |
1991 | int ret = 0; | 1980 | int ret = 0; |
@@ -1994,7 +1983,7 @@ il_add_station_common(struct il_priv *il, struct il_rxon_context *ctx, | |||
1994 | 1983 | ||
1995 | *sta_id_r = 0; | 1984 | *sta_id_r = 0; |
1996 | spin_lock_irqsave(&il->sta_lock, flags_spin); | 1985 | spin_lock_irqsave(&il->sta_lock, flags_spin); |
1997 | sta_id = il_prep_station(il, ctx, addr, is_ap, sta); | 1986 | sta_id = il_prep_station(il, addr, is_ap, sta); |
1998 | if (sta_id == IL_INVALID_STATION) { | 1987 | if (sta_id == IL_INVALID_STATION) { |
1999 | IL_ERR("Unable to prepare station %pM for addition\n", addr); | 1988 | IL_ERR("Unable to prepare station %pM for addition\n", addr); |
2000 | spin_unlock_irqrestore(&il->sta_lock, flags_spin); | 1989 | spin_unlock_irqrestore(&il->sta_lock, flags_spin); |
@@ -2181,7 +2170,7 @@ EXPORT_SYMBOL_GPL(il_remove_station); | |||
2181 | * the ucode, e.g. unassociated RXON. | 2170 | * the ucode, e.g. unassociated RXON. |
2182 | */ | 2171 | */ |
2183 | void | 2172 | void |
2184 | il_clear_ucode_stations(struct il_priv *il, struct il_rxon_context *ctx) | 2173 | il_clear_ucode_stations(struct il_priv *il) |
2185 | { | 2174 | { |
2186 | int i; | 2175 | int i; |
2187 | unsigned long flags_spin; | 2176 | unsigned long flags_spin; |
@@ -2191,9 +2180,6 @@ il_clear_ucode_stations(struct il_priv *il, struct il_rxon_context *ctx) | |||
2191 | 2180 | ||
2192 | spin_lock_irqsave(&il->sta_lock, flags_spin); | 2181 | spin_lock_irqsave(&il->sta_lock, flags_spin); |
2193 | for (i = 0; i < il->hw_params.max_stations; i++) { | 2182 | for (i = 0; i < il->hw_params.max_stations; i++) { |
2194 | if (ctx && ctx->ctxid != il->stations[i].ctxid) | ||
2195 | continue; | ||
2196 | |||
2197 | if (il->stations[i].used & IL_STA_UCODE_ACTIVE) { | 2183 | if (il->stations[i].used & IL_STA_UCODE_ACTIVE) { |
2198 | D_INFO("Clearing ucode active for station %d\n", i); | 2184 | D_INFO("Clearing ucode active for station %d\n", i); |
2199 | il->stations[i].used &= ~IL_STA_UCODE_ACTIVE; | 2185 | il->stations[i].used &= ~IL_STA_UCODE_ACTIVE; |
@@ -2216,7 +2202,7 @@ EXPORT_SYMBOL(il_clear_ucode_stations); | |||
2216 | * Function sleeps. | 2202 | * Function sleeps. |
2217 | */ | 2203 | */ |
2218 | void | 2204 | void |
2219 | il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx) | 2205 | il_restore_stations(struct il_priv *il) |
2220 | { | 2206 | { |
2221 | struct il_addsta_cmd sta_cmd; | 2207 | struct il_addsta_cmd sta_cmd; |
2222 | struct il_link_quality_cmd lq; | 2208 | struct il_link_quality_cmd lq; |
@@ -2234,8 +2220,6 @@ il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx) | |||
2234 | D_ASSOC("Restoring all known stations ... start.\n"); | 2220 | D_ASSOC("Restoring all known stations ... start.\n"); |
2235 | spin_lock_irqsave(&il->sta_lock, flags_spin); | 2221 | spin_lock_irqsave(&il->sta_lock, flags_spin); |
2236 | for (i = 0; i < il->hw_params.max_stations; i++) { | 2222 | for (i = 0; i < il->hw_params.max_stations; i++) { |
2237 | if (ctx->ctxid != il->stations[i].ctxid) | ||
2238 | continue; | ||
2239 | if ((il->stations[i].used & IL_STA_DRIVER_ACTIVE) && | 2223 | if ((il->stations[i].used & IL_STA_DRIVER_ACTIVE) && |
2240 | !(il->stations[i].used & IL_STA_UCODE_ACTIVE)) { | 2224 | !(il->stations[i].used & IL_STA_UCODE_ACTIVE)) { |
2241 | D_ASSOC("Restoring sta %pM\n", | 2225 | D_ASSOC("Restoring sta %pM\n", |
@@ -2273,7 +2257,7 @@ il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx) | |||
2273 | * current LQ command | 2257 | * current LQ command |
2274 | */ | 2258 | */ |
2275 | if (send_lq) | 2259 | if (send_lq) |
2276 | il_send_lq_cmd(il, ctx, &lq, CMD_SYNC, true); | 2260 | il_send_lq_cmd(il, &lq, CMD_SYNC, true); |
2277 | spin_lock_irqsave(&il->sta_lock, flags_spin); | 2261 | spin_lock_irqsave(&il->sta_lock, flags_spin); |
2278 | il->stations[i].used &= ~IL_STA_UCODE_INPROGRESS; | 2262 | il->stations[i].used &= ~IL_STA_UCODE_INPROGRESS; |
2279 | } | 2263 | } |
@@ -2353,15 +2337,14 @@ il_dump_lq_cmd(struct il_priv *il, struct il_link_quality_cmd *lq) | |||
2353 | * RXON flags are updated and when LQ command is updated. | 2337 | * RXON flags are updated and when LQ command is updated. |
2354 | */ | 2338 | */ |
2355 | static bool | 2339 | static bool |
2356 | il_is_lq_table_valid(struct il_priv *il, struct il_rxon_context *ctx, | 2340 | il_is_lq_table_valid(struct il_priv *il, struct il_link_quality_cmd *lq) |
2357 | struct il_link_quality_cmd *lq) | ||
2358 | { | 2341 | { |
2359 | int i; | 2342 | int i; |
2360 | 2343 | ||
2361 | if (ctx->ht.enabled) | 2344 | if (il->ht.enabled) |
2362 | return true; | 2345 | return true; |
2363 | 2346 | ||
2364 | D_INFO("Channel %u is not an HT channel\n", ctx->active.channel); | 2347 | D_INFO("Channel %u is not an HT channel\n", il->active.channel); |
2365 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | 2348 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { |
2366 | if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) { | 2349 | if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) { |
2367 | D_INFO("idx %d of LQ expects HT channel\n", i); | 2350 | D_INFO("idx %d of LQ expects HT channel\n", i); |
@@ -2382,8 +2365,8 @@ il_is_lq_table_valid(struct il_priv *il, struct il_rxon_context *ctx, | |||
2382 | * progress. | 2365 | * progress. |
2383 | */ | 2366 | */ |
2384 | int | 2367 | int |
2385 | il_send_lq_cmd(struct il_priv *il, struct il_rxon_context *ctx, | 2368 | il_send_lq_cmd(struct il_priv *il, struct il_link_quality_cmd *lq, |
2386 | struct il_link_quality_cmd *lq, u8 flags, bool init) | 2369 | u8 flags, bool init) |
2387 | { | 2370 | { |
2388 | int ret = 0; | 2371 | int ret = 0; |
2389 | unsigned long flags_spin; | 2372 | unsigned long flags_spin; |
@@ -2408,7 +2391,7 @@ il_send_lq_cmd(struct il_priv *il, struct il_rxon_context *ctx, | |||
2408 | il_dump_lq_cmd(il, lq); | 2391 | il_dump_lq_cmd(il, lq); |
2409 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); | 2392 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); |
2410 | 2393 | ||
2411 | if (il_is_lq_table_valid(il, ctx, lq)) | 2394 | if (il_is_lq_table_valid(il, lq)) |
2412 | ret = il_send_cmd(il, &cmd); | 2395 | ret = il_send_cmd(il, &cmd); |
2413 | else | 2396 | else |
2414 | ret = -EINVAL; | 2397 | ret = -EINVAL; |
@@ -2648,7 +2631,7 @@ il_set_decrypted_flag(struct il_priv *il, struct ieee80211_hdr *hdr, | |||
2648 | * All contexts have the same setting here due to it being | 2631 | * All contexts have the same setting here due to it being |
2649 | * a module parameter, so OK to check any context. | 2632 | * a module parameter, so OK to check any context. |
2650 | */ | 2633 | */ |
2651 | if (il->ctx.active.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) | 2634 | if (il->active.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) |
2652 | return 0; | 2635 | return 0; |
2653 | 2636 | ||
2654 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | 2637 | if (!(fc & IEEE80211_FCTL_PROTECTED)) |
@@ -2739,7 +2722,7 @@ il_tx_queue_unmap(struct il_priv *il, int txq_id) | |||
2739 | return; | 2722 | return; |
2740 | 2723 | ||
2741 | while (q->write_ptr != q->read_ptr) { | 2724 | while (q->write_ptr != q->read_ptr) { |
2742 | il->cfg->ops->lib->txq_free_tfd(il, txq); | 2725 | il->ops->lib->txq_free_tfd(il, txq); |
2743 | q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd); | 2726 | q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd); |
2744 | } | 2727 | } |
2745 | } | 2728 | } |
@@ -2772,8 +2755,8 @@ il_tx_queue_free(struct il_priv *il, int txq_id) | |||
2772 | txq->tfds, txq->q.dma_addr); | 2755 | txq->tfds, txq->q.dma_addr); |
2773 | 2756 | ||
2774 | /* De-alloc array of per-TFD driver data */ | 2757 | /* De-alloc array of per-TFD driver data */ |
2775 | kfree(txq->txb); | 2758 | kfree(txq->skbs); |
2776 | txq->txb = NULL; | 2759 | txq->skbs = NULL; |
2777 | 2760 | ||
2778 | /* deallocate arrays */ | 2761 | /* deallocate arrays */ |
2779 | kfree(txq->cmd); | 2762 | kfree(txq->cmd); |
@@ -2947,23 +2930,21 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id) | |||
2947 | /* Driver ilate data, only for Tx (not command) queues, | 2930 | /* Driver ilate data, only for Tx (not command) queues, |
2948 | * not shared with device. */ | 2931 | * not shared with device. */ |
2949 | if (id != il->cmd_queue) { | 2932 | if (id != il->cmd_queue) { |
2950 | txq->txb = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->txb[0]), | 2933 | txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(struct skb *), |
2951 | GFP_KERNEL); | 2934 | GFP_KERNEL); |
2952 | if (!txq->txb) { | 2935 | if (!txq->skbs) { |
2953 | IL_ERR("kmalloc for auxiliary BD " | 2936 | IL_ERR("Fail to alloc skbs\n"); |
2954 | "structures failed\n"); | ||
2955 | goto error; | 2937 | goto error; |
2956 | } | 2938 | } |
2957 | } else { | 2939 | } else |
2958 | txq->txb = NULL; | 2940 | txq->skbs = NULL; |
2959 | } | ||
2960 | 2941 | ||
2961 | /* Circular buffer of transmit frame descriptors (TFDs), | 2942 | /* Circular buffer of transmit frame descriptors (TFDs), |
2962 | * shared with device */ | 2943 | * shared with device */ |
2963 | txq->tfds = | 2944 | txq->tfds = |
2964 | dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, GFP_KERNEL); | 2945 | dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, GFP_KERNEL); |
2965 | if (!txq->tfds) { | 2946 | if (!txq->tfds) { |
2966 | IL_ERR("pci_alloc_consistent(%zd) failed\n", tfd_sz); | 2947 | IL_ERR("Fail to alloc TFDs\n"); |
2967 | goto error; | 2948 | goto error; |
2968 | } | 2949 | } |
2969 | txq->q.id = id; | 2950 | txq->q.id = id; |
@@ -2971,8 +2952,8 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id) | |||
2971 | return 0; | 2952 | return 0; |
2972 | 2953 | ||
2973 | error: | 2954 | error: |
2974 | kfree(txq->txb); | 2955 | kfree(txq->skbs); |
2975 | txq->txb = NULL; | 2956 | txq->skbs = NULL; |
2976 | 2957 | ||
2977 | return -ENOMEM; | 2958 | return -ENOMEM; |
2978 | } | 2959 | } |
@@ -3041,7 +3022,7 @@ il_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq, int slots_num, | |||
3041 | il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | 3022 | il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); |
3042 | 3023 | ||
3043 | /* Tell device where to find queue */ | 3024 | /* Tell device where to find queue */ |
3044 | il->cfg->ops->lib->txq_init(il, txq); | 3025 | il->ops->lib->txq_init(il, txq); |
3045 | 3026 | ||
3046 | return 0; | 3027 | return 0; |
3047 | err: | 3028 | err: |
@@ -3072,7 +3053,7 @@ il_tx_queue_reset(struct il_priv *il, struct il_tx_queue *txq, int slots_num, | |||
3072 | il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | 3053 | il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); |
3073 | 3054 | ||
3074 | /* Tell device where to find queue */ | 3055 | /* Tell device where to find queue */ |
3075 | il->cfg->ops->lib->txq_init(il, txq); | 3056 | il->ops->lib->txq_init(il, txq); |
3076 | } | 3057 | } |
3077 | EXPORT_SYMBOL(il_tx_queue_reset); | 3058 | EXPORT_SYMBOL(il_tx_queue_reset); |
3078 | 3059 | ||
@@ -3100,7 +3081,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) | |||
3100 | u32 idx; | 3081 | u32 idx; |
3101 | u16 fix_size; | 3082 | u16 fix_size; |
3102 | 3083 | ||
3103 | cmd->len = il->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); | 3084 | cmd->len = il->ops->utils->get_hcmd_size(cmd->id, cmd->len); |
3104 | fix_size = (u16) (cmd->len + sizeof(out_cmd->hdr)); | 3085 | fix_size = (u16) (cmd->len + sizeof(out_cmd->hdr)); |
3105 | 3086 | ||
3106 | /* If any of the command structures end up being larger than | 3087 | /* If any of the command structures end up being larger than |
@@ -3179,9 +3160,9 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) | |||
3179 | #endif | 3160 | #endif |
3180 | txq->need_update = 1; | 3161 | txq->need_update = 1; |
3181 | 3162 | ||
3182 | if (il->cfg->ops->lib->txq_update_byte_cnt_tbl) | 3163 | if (il->ops->lib->txq_update_byte_cnt_tbl) |
3183 | /* Set up entry in queue's byte count circular buffer */ | 3164 | /* Set up entry in queue's byte count circular buffer */ |
3184 | il->cfg->ops->lib->txq_update_byte_cnt_tbl(il, txq, 0); | 3165 | il->ops->lib->txq_update_byte_cnt_tbl(il, txq, 0); |
3185 | 3166 | ||
3186 | phys_addr = | 3167 | phys_addr = |
3187 | pci_map_single(il->pci_dev, &out_cmd->hdr, fix_size, | 3168 | pci_map_single(il->pci_dev, &out_cmd->hdr, fix_size, |
@@ -3189,8 +3170,8 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) | |||
3189 | dma_unmap_addr_set(out_meta, mapping, phys_addr); | 3170 | dma_unmap_addr_set(out_meta, mapping, phys_addr); |
3190 | dma_unmap_len_set(out_meta, len, fix_size); | 3171 | dma_unmap_len_set(out_meta, len, fix_size); |
3191 | 3172 | ||
3192 | il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, fix_size, | 3173 | il->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, fix_size, 1, |
3193 | 1, U32_PAD(cmd->len)); | 3174 | U32_PAD(cmd->len)); |
3194 | 3175 | ||
3195 | /* Increment and update queue's write idx */ | 3176 | /* Increment and update queue's write idx */ |
3196 | q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd); | 3177 | q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd); |
@@ -3332,30 +3313,6 @@ EXPORT_SYMBOL(il_debug_level); | |||
3332 | const u8 il_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 3313 | const u8 il_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
3333 | EXPORT_SYMBOL(il_bcast_addr); | 3314 | EXPORT_SYMBOL(il_bcast_addr); |
3334 | 3315 | ||
3335 | /* This function both allocates and initializes hw and il. */ | ||
3336 | struct ieee80211_hw * | ||
3337 | il_alloc_all(struct il_cfg *cfg) | ||
3338 | { | ||
3339 | struct il_priv *il; | ||
3340 | /* mac80211 allocates memory for this device instance, including | ||
3341 | * space for this driver's ilate structure */ | ||
3342 | struct ieee80211_hw *hw; | ||
3343 | |||
3344 | hw = ieee80211_alloc_hw(sizeof(struct il_priv), | ||
3345 | cfg->ops->ieee80211_ops); | ||
3346 | if (hw == NULL) { | ||
3347 | pr_err("%s: Can not allocate network device\n", cfg->name); | ||
3348 | goto out; | ||
3349 | } | ||
3350 | |||
3351 | il = hw->priv; | ||
3352 | il->hw = hw; | ||
3353 | |||
3354 | out: | ||
3355 | return hw; | ||
3356 | } | ||
3357 | EXPORT_SYMBOL(il_alloc_all); | ||
3358 | |||
3359 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | 3316 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ |
3360 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | 3317 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ |
3361 | static void | 3318 | static void |
@@ -3562,10 +3519,9 @@ il_is_channel_extension(struct il_priv *il, enum ieee80211_band band, | |||
3562 | } | 3519 | } |
3563 | 3520 | ||
3564 | bool | 3521 | bool |
3565 | il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx, | 3522 | il_is_ht40_tx_allowed(struct il_priv *il, struct ieee80211_sta_ht_cap *ht_cap) |
3566 | struct ieee80211_sta_ht_cap *ht_cap) | ||
3567 | { | 3523 | { |
3568 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) | 3524 | if (!il->ht.enabled || !il->ht.is_40mhz) |
3569 | return false; | 3525 | return false; |
3570 | 3526 | ||
3571 | /* | 3527 | /* |
@@ -3581,8 +3537,8 @@ il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx, | |||
3581 | #endif | 3537 | #endif |
3582 | 3538 | ||
3583 | return il_is_channel_extension(il, il->band, | 3539 | return il_is_channel_extension(il, il->band, |
3584 | le16_to_cpu(ctx->staging.channel), | 3540 | le16_to_cpu(il->staging.channel), |
3585 | ctx->ht.extension_chan_offset); | 3541 | il->ht.extension_chan_offset); |
3586 | } | 3542 | } |
3587 | EXPORT_SYMBOL(il_is_ht40_tx_allowed); | 3543 | EXPORT_SYMBOL(il_is_ht40_tx_allowed); |
3588 | 3544 | ||
@@ -3621,22 +3577,22 @@ il_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | |||
3621 | } | 3577 | } |
3622 | 3578 | ||
3623 | int | 3579 | int |
3624 | il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx) | 3580 | il_send_rxon_timing(struct il_priv *il) |
3625 | { | 3581 | { |
3626 | u64 tsf; | 3582 | u64 tsf; |
3627 | s32 interval_tm, rem; | 3583 | s32 interval_tm, rem; |
3628 | struct ieee80211_conf *conf = NULL; | 3584 | struct ieee80211_conf *conf = NULL; |
3629 | u16 beacon_int; | 3585 | u16 beacon_int; |
3630 | struct ieee80211_vif *vif = ctx->vif; | 3586 | struct ieee80211_vif *vif = il->vif; |
3631 | 3587 | ||
3632 | conf = &il->hw->conf; | 3588 | conf = &il->hw->conf; |
3633 | 3589 | ||
3634 | lockdep_assert_held(&il->mutex); | 3590 | lockdep_assert_held(&il->mutex); |
3635 | 3591 | ||
3636 | memset(&ctx->timing, 0, sizeof(struct il_rxon_time_cmd)); | 3592 | memset(&il->timing, 0, sizeof(struct il_rxon_time_cmd)); |
3637 | 3593 | ||
3638 | ctx->timing.timestamp = cpu_to_le64(il->timestamp); | 3594 | il->timing.timestamp = cpu_to_le64(il->timestamp); |
3639 | ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval); | 3595 | il->timing.listen_interval = cpu_to_le16(conf->listen_interval); |
3640 | 3596 | ||
3641 | beacon_int = vif ? vif->bss_conf.beacon_int : 0; | 3597 | beacon_int = vif ? vif->bss_conf.beacon_int : 0; |
3642 | 3598 | ||
@@ -3644,36 +3600,35 @@ il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx) | |||
3644 | * TODO: For IBSS we need to get atim_win from mac80211, | 3600 | * TODO: For IBSS we need to get atim_win from mac80211, |
3645 | * for now just always use 0 | 3601 | * for now just always use 0 |
3646 | */ | 3602 | */ |
3647 | ctx->timing.atim_win = 0; | 3603 | il->timing.atim_win = 0; |
3648 | 3604 | ||
3649 | beacon_int = | 3605 | beacon_int = |
3650 | il_adjust_beacon_interval(beacon_int, | 3606 | il_adjust_beacon_interval(beacon_int, |
3651 | il->hw_params.max_beacon_itrvl * | 3607 | il->hw_params.max_beacon_itrvl * |
3652 | TIME_UNIT); | 3608 | TIME_UNIT); |
3653 | ctx->timing.beacon_interval = cpu_to_le16(beacon_int); | 3609 | il->timing.beacon_interval = cpu_to_le16(beacon_int); |
3654 | 3610 | ||
3655 | tsf = il->timestamp; /* tsf is modifed by do_div: copy it */ | 3611 | tsf = il->timestamp; /* tsf is modifed by do_div: copy it */ |
3656 | interval_tm = beacon_int * TIME_UNIT; | 3612 | interval_tm = beacon_int * TIME_UNIT; |
3657 | rem = do_div(tsf, interval_tm); | 3613 | rem = do_div(tsf, interval_tm); |
3658 | ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); | 3614 | il->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); |
3659 | 3615 | ||
3660 | ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ? : 1) : 1; | 3616 | il->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ? : 1) : 1; |
3661 | 3617 | ||
3662 | D_ASSOC("beacon interval %d beacon timer %d beacon tim %d\n", | 3618 | D_ASSOC("beacon interval %d beacon timer %d beacon tim %d\n", |
3663 | le16_to_cpu(ctx->timing.beacon_interval), | 3619 | le16_to_cpu(il->timing.beacon_interval), |
3664 | le32_to_cpu(ctx->timing.beacon_init_val), | 3620 | le32_to_cpu(il->timing.beacon_init_val), |
3665 | le16_to_cpu(ctx->timing.atim_win)); | 3621 | le16_to_cpu(il->timing.atim_win)); |
3666 | 3622 | ||
3667 | return il_send_cmd_pdu(il, ctx->rxon_timing_cmd, sizeof(ctx->timing), | 3623 | return il_send_cmd_pdu(il, C_RXON_TIMING, sizeof(il->timing), |
3668 | &ctx->timing); | 3624 | &il->timing); |
3669 | } | 3625 | } |
3670 | EXPORT_SYMBOL(il_send_rxon_timing); | 3626 | EXPORT_SYMBOL(il_send_rxon_timing); |
3671 | 3627 | ||
3672 | void | 3628 | void |
3673 | il_set_rxon_hwcrypto(struct il_priv *il, struct il_rxon_context *ctx, | 3629 | il_set_rxon_hwcrypto(struct il_priv *il, int hw_decrypt) |
3674 | int hw_decrypt) | ||
3675 | { | 3630 | { |
3676 | struct il_rxon_cmd *rxon = &ctx->staging; | 3631 | struct il_rxon_cmd *rxon = &il->staging; |
3677 | 3632 | ||
3678 | if (hw_decrypt) | 3633 | if (hw_decrypt) |
3679 | rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; | 3634 | rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; |
@@ -3685,9 +3640,9 @@ EXPORT_SYMBOL(il_set_rxon_hwcrypto); | |||
3685 | 3640 | ||
3686 | /* validate RXON structure is valid */ | 3641 | /* validate RXON structure is valid */ |
3687 | int | 3642 | int |
3688 | il_check_rxon_cmd(struct il_priv *il, struct il_rxon_context *ctx) | 3643 | il_check_rxon_cmd(struct il_priv *il) |
3689 | { | 3644 | { |
3690 | struct il_rxon_cmd *rxon = &ctx->staging; | 3645 | struct il_rxon_cmd *rxon = &il->staging; |
3691 | bool error = false; | 3646 | bool error = false; |
3692 | 3647 | ||
3693 | if (rxon->flags & RXON_FLG_BAND_24G_MSK) { | 3648 | if (rxon->flags & RXON_FLG_BAND_24G_MSK) { |
@@ -3765,10 +3720,10 @@ EXPORT_SYMBOL(il_check_rxon_cmd); | |||
3765 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. | 3720 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. |
3766 | */ | 3721 | */ |
3767 | int | 3722 | int |
3768 | il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx) | 3723 | il_full_rxon_required(struct il_priv *il) |
3769 | { | 3724 | { |
3770 | const struct il_rxon_cmd *staging = &ctx->staging; | 3725 | const struct il_rxon_cmd *staging = &il->staging; |
3771 | const struct il_rxon_cmd *active = &ctx->active; | 3726 | const struct il_rxon_cmd *active = &il->active; |
3772 | 3727 | ||
3773 | #define CHK(cond) \ | 3728 | #define CHK(cond) \ |
3774 | if ((cond)) { \ | 3729 | if ((cond)) { \ |
@@ -3785,7 +3740,7 @@ il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx) | |||
3785 | } | 3740 | } |
3786 | 3741 | ||
3787 | /* These items are only settable from the full RXON command */ | 3742 | /* These items are only settable from the full RXON command */ |
3788 | CHK(!il_is_associated_ctx(ctx)); | 3743 | CHK(!il_is_associated(il)); |
3789 | CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr)); | 3744 | CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr)); |
3790 | CHK(compare_ether_addr(staging->node_addr, active->node_addr)); | 3745 | CHK(compare_ether_addr(staging->node_addr, active->node_addr)); |
3791 | CHK(compare_ether_addr | 3746 | CHK(compare_ether_addr |
@@ -3819,13 +3774,13 @@ il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx) | |||
3819 | EXPORT_SYMBOL(il_full_rxon_required); | 3774 | EXPORT_SYMBOL(il_full_rxon_required); |
3820 | 3775 | ||
3821 | u8 | 3776 | u8 |
3822 | il_get_lowest_plcp(struct il_priv *il, struct il_rxon_context *ctx) | 3777 | il_get_lowest_plcp(struct il_priv *il) |
3823 | { | 3778 | { |
3824 | /* | 3779 | /* |
3825 | * Assign the lowest rate -- should really get this from | 3780 | * Assign the lowest rate -- should really get this from |
3826 | * the beacon skb from mac80211. | 3781 | * the beacon skb from mac80211. |
3827 | */ | 3782 | */ |
3828 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) | 3783 | if (il->staging.flags & RXON_FLG_BAND_24G_MSK) |
3829 | return RATE_1M_PLCP; | 3784 | return RATE_1M_PLCP; |
3830 | else | 3785 | else |
3831 | return RATE_6M_PLCP; | 3786 | return RATE_6M_PLCP; |
@@ -3833,12 +3788,11 @@ il_get_lowest_plcp(struct il_priv *il, struct il_rxon_context *ctx) | |||
3833 | EXPORT_SYMBOL(il_get_lowest_plcp); | 3788 | EXPORT_SYMBOL(il_get_lowest_plcp); |
3834 | 3789 | ||
3835 | static void | 3790 | static void |
3836 | _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, | 3791 | _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf) |
3837 | struct il_rxon_context *ctx) | ||
3838 | { | 3792 | { |
3839 | struct il_rxon_cmd *rxon = &ctx->staging; | 3793 | struct il_rxon_cmd *rxon = &il->staging; |
3840 | 3794 | ||
3841 | if (!ctx->ht.enabled) { | 3795 | if (!il->ht.enabled) { |
3842 | rxon->flags &= | 3796 | rxon->flags &= |
3843 | ~(RXON_FLG_CHANNEL_MODE_MSK | | 3797 | ~(RXON_FLG_CHANNEL_MODE_MSK | |
3844 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | RXON_FLG_HT40_PROT_MSK | 3798 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | RXON_FLG_HT40_PROT_MSK |
@@ -3847,19 +3801,19 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, | |||
3847 | } | 3801 | } |
3848 | 3802 | ||
3849 | rxon->flags |= | 3803 | rxon->flags |= |
3850 | cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS); | 3804 | cpu_to_le32(il->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS); |
3851 | 3805 | ||
3852 | /* Set up channel bandwidth: | 3806 | /* Set up channel bandwidth: |
3853 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ | 3807 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ |
3854 | /* clear the HT channel mode before set the mode */ | 3808 | /* clear the HT channel mode before set the mode */ |
3855 | rxon->flags &= | 3809 | rxon->flags &= |
3856 | ~(RXON_FLG_CHANNEL_MODE_MSK | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | 3810 | ~(RXON_FLG_CHANNEL_MODE_MSK | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); |
3857 | if (il_is_ht40_tx_allowed(il, ctx, NULL)) { | 3811 | if (il_is_ht40_tx_allowed(il, NULL)) { |
3858 | /* pure ht40 */ | 3812 | /* pure ht40 */ |
3859 | if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { | 3813 | if (il->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { |
3860 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; | 3814 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; |
3861 | /* Note: control channel is opposite of extension channel */ | 3815 | /* Note: control channel is opposite of extension channel */ |
3862 | switch (ctx->ht.extension_chan_offset) { | 3816 | switch (il->ht.extension_chan_offset) { |
3863 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 3817 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
3864 | rxon->flags &= | 3818 | rxon->flags &= |
3865 | ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | 3819 | ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; |
@@ -3870,7 +3824,7 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, | |||
3870 | } | 3824 | } |
3871 | } else { | 3825 | } else { |
3872 | /* Note: control channel is opposite of extension channel */ | 3826 | /* Note: control channel is opposite of extension channel */ |
3873 | switch (ctx->ht.extension_chan_offset) { | 3827 | switch (il->ht.extension_chan_offset) { |
3874 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 3828 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
3875 | rxon->flags &= | 3829 | rxon->flags &= |
3876 | ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | 3830 | ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); |
@@ -3891,18 +3845,18 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, | |||
3891 | rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; | 3845 | rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; |
3892 | } | 3846 | } |
3893 | 3847 | ||
3894 | if (il->cfg->ops->hcmd->set_rxon_chain) | 3848 | if (il->ops->hcmd->set_rxon_chain) |
3895 | il->cfg->ops->hcmd->set_rxon_chain(il, ctx); | 3849 | il->ops->hcmd->set_rxon_chain(il); |
3896 | 3850 | ||
3897 | D_ASSOC("rxon flags 0x%X operation mode :0x%X " | 3851 | D_ASSOC("rxon flags 0x%X operation mode :0x%X " |
3898 | "extension channel offset 0x%x\n", le32_to_cpu(rxon->flags), | 3852 | "extension channel offset 0x%x\n", le32_to_cpu(rxon->flags), |
3899 | ctx->ht.protection, ctx->ht.extension_chan_offset); | 3853 | il->ht.protection, il->ht.extension_chan_offset); |
3900 | } | 3854 | } |
3901 | 3855 | ||
3902 | void | 3856 | void |
3903 | il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf) | 3857 | il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf) |
3904 | { | 3858 | { |
3905 | _il_set_rxon_ht(il, ht_conf, &il->ctx); | 3859 | _il_set_rxon_ht(il, ht_conf); |
3906 | } | 3860 | } |
3907 | EXPORT_SYMBOL(il_set_rxon_ht); | 3861 | EXPORT_SYMBOL(il_set_rxon_ht); |
3908 | 3862 | ||
@@ -3925,7 +3879,7 @@ il_get_single_channel_number(struct il_priv *il, enum ieee80211_band band) | |||
3925 | 3879 | ||
3926 | for (i = min; i < max; i++) { | 3880 | for (i = min; i < max; i++) { |
3927 | channel = il->channel_info[i].channel; | 3881 | channel = il->channel_info[i].channel; |
3928 | if (channel == le16_to_cpu(il->ctx.staging.channel)) | 3882 | if (channel == le16_to_cpu(il->staging.channel)) |
3929 | continue; | 3883 | continue; |
3930 | 3884 | ||
3931 | ch_info = il_get_channel_info(il, band, channel); | 3885 | ch_info = il_get_channel_info(il, band, channel); |
@@ -3945,20 +3899,19 @@ EXPORT_SYMBOL(il_get_single_channel_number); | |||
3945 | * in the staging RXON flag structure based on the ch->band | 3899 | * in the staging RXON flag structure based on the ch->band |
3946 | */ | 3900 | */ |
3947 | int | 3901 | int |
3948 | il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch, | 3902 | il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch) |
3949 | struct il_rxon_context *ctx) | ||
3950 | { | 3903 | { |
3951 | enum ieee80211_band band = ch->band; | 3904 | enum ieee80211_band band = ch->band; |
3952 | u16 channel = ch->hw_value; | 3905 | u16 channel = ch->hw_value; |
3953 | 3906 | ||
3954 | if (le16_to_cpu(ctx->staging.channel) == channel && il->band == band) | 3907 | if (le16_to_cpu(il->staging.channel) == channel && il->band == band) |
3955 | return 0; | 3908 | return 0; |
3956 | 3909 | ||
3957 | ctx->staging.channel = cpu_to_le16(channel); | 3910 | il->staging.channel = cpu_to_le16(channel); |
3958 | if (band == IEEE80211_BAND_5GHZ) | 3911 | if (band == IEEE80211_BAND_5GHZ) |
3959 | ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK; | 3912 | il->staging.flags &= ~RXON_FLG_BAND_24G_MSK; |
3960 | else | 3913 | else |
3961 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; | 3914 | il->staging.flags |= RXON_FLG_BAND_24G_MSK; |
3962 | 3915 | ||
3963 | il->band = band; | 3916 | il->band = band; |
3964 | 3917 | ||
@@ -3969,24 +3922,24 @@ il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch, | |||
3969 | EXPORT_SYMBOL(il_set_rxon_channel); | 3922 | EXPORT_SYMBOL(il_set_rxon_channel); |
3970 | 3923 | ||
3971 | void | 3924 | void |
3972 | il_set_flags_for_band(struct il_priv *il, struct il_rxon_context *ctx, | 3925 | il_set_flags_for_band(struct il_priv *il, enum ieee80211_band band, |
3973 | enum ieee80211_band band, struct ieee80211_vif *vif) | 3926 | struct ieee80211_vif *vif) |
3974 | { | 3927 | { |
3975 | if (band == IEEE80211_BAND_5GHZ) { | 3928 | if (band == IEEE80211_BAND_5GHZ) { |
3976 | ctx->staging.flags &= | 3929 | il->staging.flags &= |
3977 | ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | | 3930 | ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | |
3978 | RXON_FLG_CCK_MSK); | 3931 | RXON_FLG_CCK_MSK); |
3979 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | 3932 | il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
3980 | } else { | 3933 | } else { |
3981 | /* Copied from il_post_associate() */ | 3934 | /* Copied from il_post_associate() */ |
3982 | if (vif && vif->bss_conf.use_short_slot) | 3935 | if (vif && vif->bss_conf.use_short_slot) |
3983 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | 3936 | il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
3984 | else | 3937 | else |
3985 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 3938 | il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
3986 | 3939 | ||
3987 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; | 3940 | il->staging.flags |= RXON_FLG_BAND_24G_MSK; |
3988 | ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK; | 3941 | il->staging.flags |= RXON_FLG_AUTO_DETECT_MSK; |
3989 | ctx->staging.flags &= ~RXON_FLG_CCK_MSK; | 3942 | il->staging.flags &= ~RXON_FLG_CCK_MSK; |
3990 | } | 3943 | } |
3991 | } | 3944 | } |
3992 | EXPORT_SYMBOL(il_set_flags_for_band); | 3945 | EXPORT_SYMBOL(il_set_flags_for_band); |
@@ -3995,69 +3948,60 @@ EXPORT_SYMBOL(il_set_flags_for_band); | |||
3995 | * initialize rxon structure with default values from eeprom | 3948 | * initialize rxon structure with default values from eeprom |
3996 | */ | 3949 | */ |
3997 | void | 3950 | void |
3998 | il_connection_init_rx_config(struct il_priv *il, struct il_rxon_context *ctx) | 3951 | il_connection_init_rx_config(struct il_priv *il) |
3999 | { | 3952 | { |
4000 | const struct il_channel_info *ch_info; | 3953 | const struct il_channel_info *ch_info; |
4001 | 3954 | ||
4002 | memset(&ctx->staging, 0, sizeof(ctx->staging)); | 3955 | memset(&il->staging, 0, sizeof(il->staging)); |
4003 | 3956 | ||
4004 | if (!ctx->vif) { | 3957 | if (!il->vif) { |
4005 | ctx->staging.dev_type = ctx->unused_devtype; | 3958 | il->staging.dev_type = RXON_DEV_TYPE_ESS; |
4006 | } else | 3959 | } else if (il->vif->type == NL80211_IFTYPE_STATION) { |
4007 | switch (ctx->vif->type) { | 3960 | il->staging.dev_type = RXON_DEV_TYPE_ESS; |
4008 | 3961 | il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; | |
4009 | case NL80211_IFTYPE_STATION: | 3962 | } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { |
4010 | ctx->staging.dev_type = ctx->station_devtype; | 3963 | il->staging.dev_type = RXON_DEV_TYPE_IBSS; |
4011 | ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; | 3964 | il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; |
4012 | break; | 3965 | il->staging.filter_flags = |
4013 | 3966 | RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; | |
4014 | case NL80211_IFTYPE_ADHOC: | 3967 | } else { |
4015 | ctx->staging.dev_type = ctx->ibss_devtype; | 3968 | IL_ERR("Unsupported interface type %d\n", il->vif->type); |
4016 | ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; | 3969 | return; |
4017 | ctx->staging.filter_flags = | 3970 | } |
4018 | RXON_FILTER_BCON_AWARE_MSK | | ||
4019 | RXON_FILTER_ACCEPT_GRP_MSK; | ||
4020 | break; | ||
4021 | |||
4022 | default: | ||
4023 | IL_ERR("Unsupported interface type %d\n", | ||
4024 | ctx->vif->type); | ||
4025 | break; | ||
4026 | } | ||
4027 | 3971 | ||
4028 | #if 0 | 3972 | #if 0 |
4029 | /* TODO: Figure out when short_preamble would be set and cache from | 3973 | /* TODO: Figure out when short_preamble would be set and cache from |
4030 | * that */ | 3974 | * that */ |
4031 | if (!hw_to_local(il->hw)->short_preamble) | 3975 | if (!hw_to_local(il->hw)->short_preamble) |
4032 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3976 | il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
4033 | else | 3977 | else |
4034 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 3978 | il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
4035 | #endif | 3979 | #endif |
4036 | 3980 | ||
4037 | ch_info = | 3981 | ch_info = |
4038 | il_get_channel_info(il, il->band, le16_to_cpu(ctx->active.channel)); | 3982 | il_get_channel_info(il, il->band, le16_to_cpu(il->active.channel)); |
4039 | 3983 | ||
4040 | if (!ch_info) | 3984 | if (!ch_info) |
4041 | ch_info = &il->channel_info[0]; | 3985 | ch_info = &il->channel_info[0]; |
4042 | 3986 | ||
4043 | ctx->staging.channel = cpu_to_le16(ch_info->channel); | 3987 | il->staging.channel = cpu_to_le16(ch_info->channel); |
4044 | il->band = ch_info->band; | 3988 | il->band = ch_info->band; |
4045 | 3989 | ||
4046 | il_set_flags_for_band(il, ctx, il->band, ctx->vif); | 3990 | il_set_flags_for_band(il, il->band, il->vif); |
4047 | 3991 | ||
4048 | ctx->staging.ofdm_basic_rates = | 3992 | il->staging.ofdm_basic_rates = |
4049 | (IL_OFDM_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF; | 3993 | (IL_OFDM_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF; |
4050 | ctx->staging.cck_basic_rates = | 3994 | il->staging.cck_basic_rates = |
4051 | (IL_CCK_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF; | 3995 | (IL_CCK_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF; |
4052 | 3996 | ||
4053 | /* clear both MIX and PURE40 mode flag */ | 3997 | /* clear both MIX and PURE40 mode flag */ |
4054 | ctx->staging.flags &= | 3998 | il->staging.flags &= |
4055 | ~(RXON_FLG_CHANNEL_MODE_MIXED | RXON_FLG_CHANNEL_MODE_PURE_40); | 3999 | ~(RXON_FLG_CHANNEL_MODE_MIXED | RXON_FLG_CHANNEL_MODE_PURE_40); |
4056 | if (ctx->vif) | 4000 | if (il->vif) |
4057 | memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN); | 4001 | memcpy(il->staging.node_addr, il->vif->addr, ETH_ALEN); |
4058 | 4002 | ||
4059 | ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; | 4003 | il->staging.ofdm_ht_single_stream_basic_rates = 0xff; |
4060 | ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; | 4004 | il->staging.ofdm_ht_dual_stream_basic_rates = 0xff; |
4061 | } | 4005 | } |
4062 | EXPORT_SYMBOL(il_connection_init_rx_config); | 4006 | EXPORT_SYMBOL(il_connection_init_rx_config); |
4063 | 4007 | ||
@@ -4084,10 +4028,10 @@ il_set_rate(struct il_priv *il) | |||
4084 | 4028 | ||
4085 | D_RATE("Set active_rate = %0x\n", il->active_rate); | 4029 | D_RATE("Set active_rate = %0x\n", il->active_rate); |
4086 | 4030 | ||
4087 | il->ctx.staging.cck_basic_rates = | 4031 | il->staging.cck_basic_rates = |
4088 | (IL_CCK_BASIC_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF; | 4032 | (IL_CCK_BASIC_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF; |
4089 | 4033 | ||
4090 | il->ctx.staging.ofdm_basic_rates = | 4034 | il->staging.ofdm_basic_rates = |
4091 | (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF; | 4035 | (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF; |
4092 | } | 4036 | } |
4093 | EXPORT_SYMBOL(il_set_rate); | 4037 | EXPORT_SYMBOL(il_set_rate); |
@@ -4095,13 +4039,11 @@ EXPORT_SYMBOL(il_set_rate); | |||
4095 | void | 4039 | void |
4096 | il_chswitch_done(struct il_priv *il, bool is_success) | 4040 | il_chswitch_done(struct il_priv *il, bool is_success) |
4097 | { | 4041 | { |
4098 | struct il_rxon_context *ctx = &il->ctx; | ||
4099 | |||
4100 | if (test_bit(S_EXIT_PENDING, &il->status)) | 4042 | if (test_bit(S_EXIT_PENDING, &il->status)) |
4101 | return; | 4043 | return; |
4102 | 4044 | ||
4103 | if (test_and_clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) | 4045 | if (test_and_clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) |
4104 | ieee80211_chswitch_done(ctx->vif, is_success); | 4046 | ieee80211_chswitch_done(il->vif, is_success); |
4105 | } | 4047 | } |
4106 | EXPORT_SYMBOL(il_chswitch_done); | 4048 | EXPORT_SYMBOL(il_chswitch_done); |
4107 | 4049 | ||
@@ -4110,16 +4052,14 @@ il_hdl_csa(struct il_priv *il, struct il_rx_buf *rxb) | |||
4110 | { | 4052 | { |
4111 | struct il_rx_pkt *pkt = rxb_addr(rxb); | 4053 | struct il_rx_pkt *pkt = rxb_addr(rxb); |
4112 | struct il_csa_notification *csa = &(pkt->u.csa_notif); | 4054 | struct il_csa_notification *csa = &(pkt->u.csa_notif); |
4113 | 4055 | struct il_rxon_cmd *rxon = (void *)&il->active; | |
4114 | struct il_rxon_context *ctx = &il->ctx; | ||
4115 | struct il_rxon_cmd *rxon = (void *)&ctx->active; | ||
4116 | 4056 | ||
4117 | if (!test_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) | 4057 | if (!test_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) |
4118 | return; | 4058 | return; |
4119 | 4059 | ||
4120 | if (!le32_to_cpu(csa->status) && csa->channel == il->switch_channel) { | 4060 | if (!le32_to_cpu(csa->status) && csa->channel == il->switch_channel) { |
4121 | rxon->channel = csa->channel; | 4061 | rxon->channel = csa->channel; |
4122 | ctx->staging.channel = csa->channel; | 4062 | il->staging.channel = csa->channel; |
4123 | D_11H("CSA notif: channel %d\n", le16_to_cpu(csa->channel)); | 4063 | D_11H("CSA notif: channel %d\n", le16_to_cpu(csa->channel)); |
4124 | il_chswitch_done(il, true); | 4064 | il_chswitch_done(il, true); |
4125 | } else { | 4065 | } else { |
@@ -4132,9 +4072,9 @@ EXPORT_SYMBOL(il_hdl_csa); | |||
4132 | 4072 | ||
4133 | #ifdef CONFIG_IWLEGACY_DEBUG | 4073 | #ifdef CONFIG_IWLEGACY_DEBUG |
4134 | void | 4074 | void |
4135 | il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx) | 4075 | il_print_rx_config_cmd(struct il_priv *il) |
4136 | { | 4076 | { |
4137 | struct il_rxon_cmd *rxon = &ctx->staging; | 4077 | struct il_rxon_cmd *rxon = &il->staging; |
4138 | 4078 | ||
4139 | D_RADIO("RX CONFIG:\n"); | 4079 | D_RADIO("RX CONFIG:\n"); |
4140 | il_print_hex_dump(il, IL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); | 4080 | il_print_hex_dump(il, IL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); |
@@ -4164,12 +4104,12 @@ il_irq_handle_error(struct il_priv *il) | |||
4164 | 4104 | ||
4165 | IL_ERR("Loaded firmware version: %s\n", il->hw->wiphy->fw_version); | 4105 | IL_ERR("Loaded firmware version: %s\n", il->hw->wiphy->fw_version); |
4166 | 4106 | ||
4167 | il->cfg->ops->lib->dump_nic_error_log(il); | 4107 | il->ops->lib->dump_nic_error_log(il); |
4168 | if (il->cfg->ops->lib->dump_fh) | 4108 | if (il->ops->lib->dump_fh) |
4169 | il->cfg->ops->lib->dump_fh(il, NULL, false); | 4109 | il->ops->lib->dump_fh(il, NULL, false); |
4170 | #ifdef CONFIG_IWLEGACY_DEBUG | 4110 | #ifdef CONFIG_IWLEGACY_DEBUG |
4171 | if (il_get_debug_level(il) & IL_DL_FW_ERRORS) | 4111 | if (il_get_debug_level(il) & IL_DL_FW_ERRORS) |
4172 | il_print_rx_config_cmd(il, &il->ctx); | 4112 | il_print_rx_config_cmd(il); |
4173 | #endif | 4113 | #endif |
4174 | 4114 | ||
4175 | wake_up(&il->wait_command_queue); | 4115 | wake_up(&il->wait_command_queue); |
@@ -4276,7 +4216,7 @@ il_apm_init(struct il_priv *il) | |||
4276 | * If not (unlikely), enable L0S, so there is at least some | 4216 | * If not (unlikely), enable L0S, so there is at least some |
4277 | * power savings, even without L1. | 4217 | * power savings, even without L1. |
4278 | */ | 4218 | */ |
4279 | if (il->cfg->base_params->set_l0s) { | 4219 | if (il->cfg->set_l0s) { |
4280 | lctl = il_pcie_link_ctl(il); | 4220 | lctl = il_pcie_link_ctl(il); |
4281 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == | 4221 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == |
4282 | PCI_CFG_LINK_CTRL_VAL_L1_EN) { | 4222 | PCI_CFG_LINK_CTRL_VAL_L1_EN) { |
@@ -4293,9 +4233,9 @@ il_apm_init(struct il_priv *il) | |||
4293 | } | 4233 | } |
4294 | 4234 | ||
4295 | /* Configure analog phase-lock-loop before activating to D0A */ | 4235 | /* Configure analog phase-lock-loop before activating to D0A */ |
4296 | if (il->cfg->base_params->pll_cfg_val) | 4236 | if (il->cfg->pll_cfg_val) |
4297 | il_set_bit(il, CSR_ANA_PLL_CFG, | 4237 | il_set_bit(il, CSR_ANA_PLL_CFG, |
4298 | il->cfg->base_params->pll_cfg_val); | 4238 | il->cfg->pll_cfg_val); |
4299 | 4239 | ||
4300 | /* | 4240 | /* |
4301 | * Set "initialization complete" bit to move adapter from | 4241 | * Set "initialization complete" bit to move adapter from |
@@ -4325,7 +4265,7 @@ il_apm_init(struct il_priv *il) | |||
4325 | * do not disable clocks. This preserves any hardware bits already | 4265 | * do not disable clocks. This preserves any hardware bits already |
4326 | * set by default in "CLK_CTRL_REG" after reset. | 4266 | * set by default in "CLK_CTRL_REG" after reset. |
4327 | */ | 4267 | */ |
4328 | if (il->cfg->base_params->use_bsm) | 4268 | if (il->cfg->use_bsm) |
4329 | il_wr_prph(il, APMG_CLK_EN_REG, | 4269 | il_wr_prph(il, APMG_CLK_EN_REG, |
4330 | APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); | 4270 | APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); |
4331 | else | 4271 | else |
@@ -4347,14 +4287,13 @@ il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) | |||
4347 | int ret; | 4287 | int ret; |
4348 | s8 prev_tx_power; | 4288 | s8 prev_tx_power; |
4349 | bool defer; | 4289 | bool defer; |
4350 | struct il_rxon_context *ctx = &il->ctx; | ||
4351 | 4290 | ||
4352 | lockdep_assert_held(&il->mutex); | 4291 | lockdep_assert_held(&il->mutex); |
4353 | 4292 | ||
4354 | if (il->tx_power_user_lmt == tx_power && !force) | 4293 | if (il->tx_power_user_lmt == tx_power && !force) |
4355 | return 0; | 4294 | return 0; |
4356 | 4295 | ||
4357 | if (!il->cfg->ops->lib->send_tx_power) | 4296 | if (!il->ops->lib->send_tx_power) |
4358 | return -EOPNOTSUPP; | 4297 | return -EOPNOTSUPP; |
4359 | 4298 | ||
4360 | /* 0 dBm mean 1 milliwatt */ | 4299 | /* 0 dBm mean 1 milliwatt */ |
@@ -4378,7 +4317,7 @@ il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) | |||
4378 | 4317 | ||
4379 | /* do not set tx power when scanning or channel changing */ | 4318 | /* do not set tx power when scanning or channel changing */ |
4380 | defer = test_bit(S_SCANNING, &il->status) || | 4319 | defer = test_bit(S_SCANNING, &il->status) || |
4381 | memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); | 4320 | memcmp(&il->active, &il->staging, sizeof(il->staging)); |
4382 | if (defer && !force) { | 4321 | if (defer && !force) { |
4383 | D_INFO("Deferring tx power set\n"); | 4322 | D_INFO("Deferring tx power set\n"); |
4384 | return 0; | 4323 | return 0; |
@@ -4387,7 +4326,7 @@ il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) | |||
4387 | prev_tx_power = il->tx_power_user_lmt; | 4326 | prev_tx_power = il->tx_power_user_lmt; |
4388 | il->tx_power_user_lmt = tx_power; | 4327 | il->tx_power_user_lmt = tx_power; |
4389 | 4328 | ||
4390 | ret = il->cfg->ops->lib->send_tx_power(il); | 4329 | ret = il->ops->lib->send_tx_power(il); |
4391 | 4330 | ||
4392 | /* if fail to set tx_power, restore the orig. tx power */ | 4331 | /* if fail to set tx_power, restore the orig. tx power */ |
4393 | if (ret) { | 4332 | if (ret) { |
@@ -4505,15 +4444,15 @@ il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, | |||
4505 | 4444 | ||
4506 | spin_lock_irqsave(&il->lock, flags); | 4445 | spin_lock_irqsave(&il->lock, flags); |
4507 | 4446 | ||
4508 | il->ctx.qos_data.def_qos_parm.ac[q].cw_min = | 4447 | il->qos_data.def_qos_parm.ac[q].cw_min = |
4509 | cpu_to_le16(params->cw_min); | 4448 | cpu_to_le16(params->cw_min); |
4510 | il->ctx.qos_data.def_qos_parm.ac[q].cw_max = | 4449 | il->qos_data.def_qos_parm.ac[q].cw_max = |
4511 | cpu_to_le16(params->cw_max); | 4450 | cpu_to_le16(params->cw_max); |
4512 | il->ctx.qos_data.def_qos_parm.ac[q].aifsn = params->aifs; | 4451 | il->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; |
4513 | il->ctx.qos_data.def_qos_parm.ac[q].edca_txop = | 4452 | il->qos_data.def_qos_parm.ac[q].edca_txop = |
4514 | cpu_to_le16((params->txop * 32)); | 4453 | cpu_to_le16((params->txop * 32)); |
4515 | 4454 | ||
4516 | il->ctx.qos_data.def_qos_parm.ac[q].reserved1 = 0; | 4455 | il->qos_data.def_qos_parm.ac[q].reserved1 = 0; |
4517 | 4456 | ||
4518 | spin_unlock_irqrestore(&il->lock, flags); | 4457 | spin_unlock_irqrestore(&il->lock, flags); |
4519 | 4458 | ||
@@ -4532,50 +4471,21 @@ il_mac_tx_last_beacon(struct ieee80211_hw *hw) | |||
4532 | EXPORT_SYMBOL_GPL(il_mac_tx_last_beacon); | 4471 | EXPORT_SYMBOL_GPL(il_mac_tx_last_beacon); |
4533 | 4472 | ||
4534 | static int | 4473 | static int |
4535 | il_set_mode(struct il_priv *il, struct il_rxon_context *ctx) | 4474 | il_set_mode(struct il_priv *il) |
4536 | { | ||
4537 | il_connection_init_rx_config(il, ctx); | ||
4538 | |||
4539 | if (il->cfg->ops->hcmd->set_rxon_chain) | ||
4540 | il->cfg->ops->hcmd->set_rxon_chain(il, ctx); | ||
4541 | |||
4542 | return il_commit_rxon(il, ctx); | ||
4543 | } | ||
4544 | |||
4545 | static int | ||
4546 | il_setup_interface(struct il_priv *il, struct il_rxon_context *ctx) | ||
4547 | { | 4475 | { |
4548 | struct ieee80211_vif *vif = ctx->vif; | 4476 | il_connection_init_rx_config(il); |
4549 | int err; | ||
4550 | |||
4551 | lockdep_assert_held(&il->mutex); | ||
4552 | |||
4553 | /* | ||
4554 | * This variable will be correct only when there's just | ||
4555 | * a single context, but all code using it is for hardware | ||
4556 | * that supports only one context. | ||
4557 | */ | ||
4558 | il->iw_mode = vif->type; | ||
4559 | 4477 | ||
4560 | ctx->is_active = true; | 4478 | if (il->ops->hcmd->set_rxon_chain) |
4479 | il->ops->hcmd->set_rxon_chain(il); | ||
4561 | 4480 | ||
4562 | err = il_set_mode(il, ctx); | 4481 | return il_commit_rxon(il); |
4563 | if (err) { | ||
4564 | if (!ctx->always_active) | ||
4565 | ctx->is_active = false; | ||
4566 | return err; | ||
4567 | } | ||
4568 | |||
4569 | return 0; | ||
4570 | } | 4482 | } |
4571 | 4483 | ||
4572 | int | 4484 | int |
4573 | il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 4485 | il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
4574 | { | 4486 | { |
4575 | struct il_priv *il = hw->priv; | 4487 | struct il_priv *il = hw->priv; |
4576 | struct il_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
4577 | int err; | 4488 | int err; |
4578 | u32 modes; | ||
4579 | 4489 | ||
4580 | D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); | 4490 | D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); |
4581 | 4491 | ||
@@ -4587,25 +4497,17 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
4587 | goto out; | 4497 | goto out; |
4588 | } | 4498 | } |
4589 | 4499 | ||
4590 | /* check if busy context is exclusive */ | 4500 | if (il->vif) { |
4591 | if (il->ctx.vif && | ||
4592 | (il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type))) { | ||
4593 | err = -EINVAL; | ||
4594 | goto out; | ||
4595 | } | ||
4596 | |||
4597 | modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes; | ||
4598 | if (!(modes & BIT(vif->type))) { | ||
4599 | err = -EOPNOTSUPP; | 4501 | err = -EOPNOTSUPP; |
4600 | goto out; | 4502 | goto out; |
4601 | } | 4503 | } |
4602 | 4504 | ||
4603 | vif_priv->ctx = &il->ctx; | 4505 | il->vif = vif; |
4604 | il->ctx.vif = vif; | 4506 | il->iw_mode = vif->type; |
4605 | 4507 | ||
4606 | err = il_setup_interface(il, &il->ctx); | 4508 | err = il_set_mode(il); |
4607 | if (err) { | 4509 | if (err) { |
4608 | il->ctx.vif = NULL; | 4510 | il->vif = NULL; |
4609 | il->iw_mode = NL80211_IFTYPE_STATION; | 4511 | il->iw_mode = NL80211_IFTYPE_STATION; |
4610 | } | 4512 | } |
4611 | 4513 | ||
@@ -4621,8 +4523,6 @@ static void | |||
4621 | il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, | 4523 | il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, |
4622 | bool mode_change) | 4524 | bool mode_change) |
4623 | { | 4525 | { |
4624 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
4625 | |||
4626 | lockdep_assert_held(&il->mutex); | 4526 | lockdep_assert_held(&il->mutex); |
4627 | 4527 | ||
4628 | if (il->scan_vif == vif) { | 4528 | if (il->scan_vif == vif) { |
@@ -4630,25 +4530,22 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, | |||
4630 | il_force_scan_end(il); | 4530 | il_force_scan_end(il); |
4631 | } | 4531 | } |
4632 | 4532 | ||
4633 | if (!mode_change) { | 4533 | if (!mode_change) |
4634 | il_set_mode(il, ctx); | 4534 | il_set_mode(il); |
4635 | if (!ctx->always_active) | 4535 | |
4636 | ctx->is_active = false; | ||
4637 | } | ||
4638 | } | 4536 | } |
4639 | 4537 | ||
4640 | void | 4538 | void |
4641 | il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 4539 | il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
4642 | { | 4540 | { |
4643 | struct il_priv *il = hw->priv; | 4541 | struct il_priv *il = hw->priv; |
4644 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
4645 | 4542 | ||
4646 | D_MAC80211("enter\n"); | 4543 | D_MAC80211("enter\n"); |
4647 | 4544 | ||
4648 | mutex_lock(&il->mutex); | 4545 | mutex_lock(&il->mutex); |
4649 | 4546 | ||
4650 | WARN_ON(ctx->vif != vif); | 4547 | WARN_ON(il->vif != vif); |
4651 | ctx->vif = NULL; | 4548 | il->vif = NULL; |
4652 | 4549 | ||
4653 | il_teardown_interface(il, vif, false); | 4550 | il_teardown_interface(il, vif, false); |
4654 | 4551 | ||
@@ -4666,7 +4563,7 @@ il_alloc_txq_mem(struct il_priv *il) | |||
4666 | if (!il->txq) | 4563 | if (!il->txq) |
4667 | il->txq = | 4564 | il->txq = |
4668 | kzalloc(sizeof(struct il_tx_queue) * | 4565 | kzalloc(sizeof(struct il_tx_queue) * |
4669 | il->cfg->base_params->num_of_queues, GFP_KERNEL); | 4566 | il->cfg->num_of_queues, GFP_KERNEL); |
4670 | if (!il->txq) { | 4567 | if (!il->txq) { |
4671 | IL_ERR("Not enough memory for txq\n"); | 4568 | IL_ERR("Not enough memory for txq\n"); |
4672 | return -ENOMEM; | 4569 | return -ENOMEM; |
@@ -4987,15 +4884,14 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
4987 | enum nl80211_iftype newtype, bool newp2p) | 4884 | enum nl80211_iftype newtype, bool newp2p) |
4988 | { | 4885 | { |
4989 | struct il_priv *il = hw->priv; | 4886 | struct il_priv *il = hw->priv; |
4990 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
4991 | u32 modes; | ||
4992 | int err; | 4887 | int err; |
4993 | 4888 | ||
4994 | newtype = ieee80211_iftype_p2p(newtype, newp2p); | 4889 | if (newp2p) |
4890 | return -EOPNOTSUPP; | ||
4995 | 4891 | ||
4996 | mutex_lock(&il->mutex); | 4892 | mutex_lock(&il->mutex); |
4997 | 4893 | ||
4998 | if (!ctx->vif || !il_is_ready_rf(il)) { | 4894 | if (!il->vif || !il_is_ready_rf(il)) { |
4999 | /* | 4895 | /* |
5000 | * Huh? But wait ... this can maybe happen when | 4896 | * Huh? But wait ... this can maybe happen when |
5001 | * we're in the middle of a firmware restart! | 4897 | * we're in the middle of a firmware restart! |
@@ -5004,23 +4900,11 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5004 | goto out; | 4900 | goto out; |
5005 | } | 4901 | } |
5006 | 4902 | ||
5007 | modes = ctx->interface_modes | ctx->exclusive_interface_modes; | ||
5008 | if (!(modes & BIT(newtype))) { | ||
5009 | err = -EOPNOTSUPP; | ||
5010 | goto out; | ||
5011 | } | ||
5012 | |||
5013 | if ((il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type)) || | ||
5014 | (il->ctx.exclusive_interface_modes & BIT(newtype))) { | ||
5015 | err = -EINVAL; | ||
5016 | goto out; | ||
5017 | } | ||
5018 | |||
5019 | /* success */ | 4903 | /* success */ |
5020 | il_teardown_interface(il, vif, true); | 4904 | il_teardown_interface(il, vif, true); |
5021 | vif->type = newtype; | 4905 | vif->type = newtype; |
5022 | vif->p2p = newp2p; | 4906 | vif->p2p = false; |
5023 | err = il_setup_interface(il, ctx); | 4907 | err = il_set_mode(il); |
5024 | WARN_ON(err); | 4908 | WARN_ON(err); |
5025 | /* | 4909 | /* |
5026 | * We've switched internally, but submitting to the | 4910 | * We've switched internally, but submitting to the |
@@ -5056,11 +4940,11 @@ il_check_stuck_queue(struct il_priv *il, int cnt) | |||
5056 | 4940 | ||
5057 | timeout = | 4941 | timeout = |
5058 | txq->time_stamp + | 4942 | txq->time_stamp + |
5059 | msecs_to_jiffies(il->cfg->base_params->wd_timeout); | 4943 | msecs_to_jiffies(il->cfg->wd_timeout); |
5060 | 4944 | ||
5061 | if (time_after(jiffies, timeout)) { | 4945 | if (time_after(jiffies, timeout)) { |
5062 | IL_ERR("Queue %d stuck for %u ms.\n", q->id, | 4946 | IL_ERR("Queue %d stuck for %u ms.\n", q->id, |
5063 | il->cfg->base_params->wd_timeout); | 4947 | il->cfg->wd_timeout); |
5064 | ret = il_force_reset(il, false); | 4948 | ret = il_force_reset(il, false); |
5065 | return (ret == -EAGAIN) ? 0 : 1; | 4949 | return (ret == -EAGAIN) ? 0 : 1; |
5066 | } | 4950 | } |
@@ -5088,7 +4972,7 @@ il_bg_watchdog(unsigned long data) | |||
5088 | if (test_bit(S_EXIT_PENDING, &il->status)) | 4972 | if (test_bit(S_EXIT_PENDING, &il->status)) |
5089 | return; | 4973 | return; |
5090 | 4974 | ||
5091 | timeout = il->cfg->base_params->wd_timeout; | 4975 | timeout = il->cfg->wd_timeout; |
5092 | if (timeout == 0) | 4976 | if (timeout == 0) |
5093 | return; | 4977 | return; |
5094 | 4978 | ||
@@ -5115,7 +4999,7 @@ EXPORT_SYMBOL(il_bg_watchdog); | |||
5115 | void | 4999 | void |
5116 | il_setup_watchdog(struct il_priv *il) | 5000 | il_setup_watchdog(struct il_priv *il) |
5117 | { | 5001 | { |
5118 | unsigned int timeout = il->cfg->base_params->wd_timeout; | 5002 | unsigned int timeout = il->cfg->wd_timeout; |
5119 | 5003 | ||
5120 | if (timeout) | 5004 | if (timeout) |
5121 | mod_timer(&il->watchdog, | 5005 | mod_timer(&il->watchdog, |
@@ -5252,28 +5136,25 @@ EXPORT_SYMBOL(il_pm_ops); | |||
5252 | #endif /* CONFIG_PM */ | 5136 | #endif /* CONFIG_PM */ |
5253 | 5137 | ||
5254 | static void | 5138 | static void |
5255 | il_update_qos(struct il_priv *il, struct il_rxon_context *ctx) | 5139 | il_update_qos(struct il_priv *il) |
5256 | { | 5140 | { |
5257 | if (test_bit(S_EXIT_PENDING, &il->status)) | 5141 | if (test_bit(S_EXIT_PENDING, &il->status)) |
5258 | return; | 5142 | return; |
5259 | 5143 | ||
5260 | if (!ctx->is_active) | 5144 | il->qos_data.def_qos_parm.qos_flags = 0; |
5261 | return; | ||
5262 | 5145 | ||
5263 | ctx->qos_data.def_qos_parm.qos_flags = 0; | 5146 | if (il->qos_data.qos_active) |
5264 | 5147 | il->qos_data.def_qos_parm.qos_flags |= | |
5265 | if (ctx->qos_data.qos_active) | ||
5266 | ctx->qos_data.def_qos_parm.qos_flags |= | ||
5267 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; | 5148 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; |
5268 | 5149 | ||
5269 | if (ctx->ht.enabled) | 5150 | if (il->ht.enabled) |
5270 | ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; | 5151 | il->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; |
5271 | 5152 | ||
5272 | D_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", | 5153 | D_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", |
5273 | ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); | 5154 | il->qos_data.qos_active, il->qos_data.def_qos_parm.qos_flags); |
5274 | 5155 | ||
5275 | il_send_cmd_pdu_async(il, ctx->qos_cmd, sizeof(struct il_qosparam_cmd), | 5156 | il_send_cmd_pdu_async(il, C_QOS_PARAM, sizeof(struct il_qosparam_cmd), |
5276 | &ctx->qos_data.def_qos_parm, NULL); | 5157 | &il->qos_data.def_qos_parm, NULL); |
5277 | } | 5158 | } |
5278 | 5159 | ||
5279 | /** | 5160 | /** |
@@ -5287,14 +5168,13 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
5287 | struct ieee80211_conf *conf = &hw->conf; | 5168 | struct ieee80211_conf *conf = &hw->conf; |
5288 | struct ieee80211_channel *channel = conf->channel; | 5169 | struct ieee80211_channel *channel = conf->channel; |
5289 | struct il_ht_config *ht_conf = &il->current_ht_config; | 5170 | struct il_ht_config *ht_conf = &il->current_ht_config; |
5290 | struct il_rxon_context *ctx = &il->ctx; | ||
5291 | unsigned long flags = 0; | 5171 | unsigned long flags = 0; |
5292 | int ret = 0; | 5172 | int ret = 0; |
5293 | u16 ch; | 5173 | u16 ch; |
5294 | int scan_active = 0; | 5174 | int scan_active = 0; |
5295 | bool ht_changed = false; | 5175 | bool ht_changed = false; |
5296 | 5176 | ||
5297 | if (WARN_ON(!il->cfg->ops->legacy)) | 5177 | if (WARN_ON(!il->ops->legacy)) |
5298 | return -EOPNOTSUPP; | 5178 | return -EOPNOTSUPP; |
5299 | 5179 | ||
5300 | mutex_lock(&il->mutex); | 5180 | mutex_lock(&il->mutex); |
@@ -5319,8 +5199,8 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
5319 | * set up the SM PS mode to OFF if an HT channel is | 5199 | * set up the SM PS mode to OFF if an HT channel is |
5320 | * configured. | 5200 | * configured. |
5321 | */ | 5201 | */ |
5322 | if (il->cfg->ops->hcmd->set_rxon_chain) | 5202 | if (il->ops->hcmd->set_rxon_chain) |
5323 | il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx); | 5203 | il->ops->hcmd->set_rxon_chain(il); |
5324 | } | 5204 | } |
5325 | 5205 | ||
5326 | /* during scanning mac80211 will delay channel setting until | 5206 | /* during scanning mac80211 will delay channel setting until |
@@ -5349,48 +5229,48 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
5349 | spin_lock_irqsave(&il->lock, flags); | 5229 | spin_lock_irqsave(&il->lock, flags); |
5350 | 5230 | ||
5351 | /* Configure HT40 channels */ | 5231 | /* Configure HT40 channels */ |
5352 | if (ctx->ht.enabled != conf_is_ht(conf)) { | 5232 | if (il->ht.enabled != conf_is_ht(conf)) { |
5353 | ctx->ht.enabled = conf_is_ht(conf); | 5233 | il->ht.enabled = conf_is_ht(conf); |
5354 | ht_changed = true; | 5234 | ht_changed = true; |
5355 | } | 5235 | } |
5356 | if (ctx->ht.enabled) { | 5236 | if (il->ht.enabled) { |
5357 | if (conf_is_ht40_minus(conf)) { | 5237 | if (conf_is_ht40_minus(conf)) { |
5358 | ctx->ht.extension_chan_offset = | 5238 | il->ht.extension_chan_offset = |
5359 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | 5239 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; |
5360 | ctx->ht.is_40mhz = true; | 5240 | il->ht.is_40mhz = true; |
5361 | } else if (conf_is_ht40_plus(conf)) { | 5241 | } else if (conf_is_ht40_plus(conf)) { |
5362 | ctx->ht.extension_chan_offset = | 5242 | il->ht.extension_chan_offset = |
5363 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | 5243 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; |
5364 | ctx->ht.is_40mhz = true; | 5244 | il->ht.is_40mhz = true; |
5365 | } else { | 5245 | } else { |
5366 | ctx->ht.extension_chan_offset = | 5246 | il->ht.extension_chan_offset = |
5367 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | 5247 | IEEE80211_HT_PARAM_CHA_SEC_NONE; |
5368 | ctx->ht.is_40mhz = false; | 5248 | il->ht.is_40mhz = false; |
5369 | } | 5249 | } |
5370 | } else | 5250 | } else |
5371 | ctx->ht.is_40mhz = false; | 5251 | il->ht.is_40mhz = false; |
5372 | 5252 | ||
5373 | /* | 5253 | /* |
5374 | * Default to no protection. Protection mode will | 5254 | * Default to no protection. Protection mode will |
5375 | * later be set from BSS config in il_ht_conf | 5255 | * later be set from BSS config in il_ht_conf |
5376 | */ | 5256 | */ |
5377 | ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 5257 | il->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
5378 | 5258 | ||
5379 | /* if we are switching from ht to 2.4 clear flags | 5259 | /* if we are switching from ht to 2.4 clear flags |
5380 | * from any ht related info since 2.4 does not | 5260 | * from any ht related info since 2.4 does not |
5381 | * support ht */ | 5261 | * support ht */ |
5382 | if ((le16_to_cpu(ctx->staging.channel) != ch)) | 5262 | if ((le16_to_cpu(il->staging.channel) != ch)) |
5383 | ctx->staging.flags = 0; | 5263 | il->staging.flags = 0; |
5384 | 5264 | ||
5385 | il_set_rxon_channel(il, channel, ctx); | 5265 | il_set_rxon_channel(il, channel); |
5386 | il_set_rxon_ht(il, ht_conf); | 5266 | il_set_rxon_ht(il, ht_conf); |
5387 | 5267 | ||
5388 | il_set_flags_for_band(il, ctx, channel->band, ctx->vif); | 5268 | il_set_flags_for_band(il, channel->band, il->vif); |
5389 | 5269 | ||
5390 | spin_unlock_irqrestore(&il->lock, flags); | 5270 | spin_unlock_irqrestore(&il->lock, flags); |
5391 | 5271 | ||
5392 | if (il->cfg->ops->legacy->update_bcast_stations) | 5272 | if (il->ops->legacy->update_bcast_stations) |
5393 | ret = il->cfg->ops->legacy->update_bcast_stations(il); | 5273 | ret = il->ops->legacy->update_bcast_stations(il); |
5394 | 5274 | ||
5395 | set_ch_out: | 5275 | set_ch_out: |
5396 | /* The list of supported rates and rate mask can be different | 5276 | /* The list of supported rates and rate mask can be different |
@@ -5420,12 +5300,12 @@ set_ch_out: | |||
5420 | if (scan_active) | 5300 | if (scan_active) |
5421 | goto out; | 5301 | goto out; |
5422 | 5302 | ||
5423 | if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) | 5303 | if (memcmp(&il->active, &il->staging, sizeof(il->staging))) |
5424 | il_commit_rxon(il, ctx); | 5304 | il_commit_rxon(il); |
5425 | else | 5305 | else |
5426 | D_INFO("Not re-sending same RXON configuration.\n"); | 5306 | D_INFO("Not re-sending same RXON configuration.\n"); |
5427 | if (ht_changed) | 5307 | if (ht_changed) |
5428 | il_update_qos(il, ctx); | 5308 | il_update_qos(il); |
5429 | 5309 | ||
5430 | out: | 5310 | out: |
5431 | D_MAC80211("leave\n"); | 5311 | D_MAC80211("leave\n"); |
@@ -5439,9 +5319,8 @@ il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
5439 | { | 5319 | { |
5440 | struct il_priv *il = hw->priv; | 5320 | struct il_priv *il = hw->priv; |
5441 | unsigned long flags; | 5321 | unsigned long flags; |
5442 | struct il_rxon_context *ctx = &il->ctx; | ||
5443 | 5322 | ||
5444 | if (WARN_ON(!il->cfg->ops->legacy)) | 5323 | if (WARN_ON(!il->ops->legacy)) |
5445 | return; | 5324 | return; |
5446 | 5325 | ||
5447 | mutex_lock(&il->mutex); | 5326 | mutex_lock(&il->mutex); |
@@ -5473,8 +5352,8 @@ il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
5473 | /* we are restarting association process | 5352 | /* we are restarting association process |
5474 | * clear RXON_FILTER_ASSOC_MSK bit | 5353 | * clear RXON_FILTER_ASSOC_MSK bit |
5475 | */ | 5354 | */ |
5476 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 5355 | il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
5477 | il_commit_rxon(il, ctx); | 5356 | il_commit_rxon(il); |
5478 | 5357 | ||
5479 | il_set_rate(il); | 5358 | il_set_rate(il); |
5480 | 5359 | ||
@@ -5490,16 +5369,15 @@ il_ht_conf(struct il_priv *il, struct ieee80211_vif *vif) | |||
5490 | struct il_ht_config *ht_conf = &il->current_ht_config; | 5369 | struct il_ht_config *ht_conf = &il->current_ht_config; |
5491 | struct ieee80211_sta *sta; | 5370 | struct ieee80211_sta *sta; |
5492 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 5371 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
5493 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
5494 | 5372 | ||
5495 | D_ASSOC("enter:\n"); | 5373 | D_ASSOC("enter:\n"); |
5496 | 5374 | ||
5497 | if (!ctx->ht.enabled) | 5375 | if (!il->ht.enabled) |
5498 | return; | 5376 | return; |
5499 | 5377 | ||
5500 | ctx->ht.protection = | 5378 | il->ht.protection = |
5501 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | 5379 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; |
5502 | ctx->ht.non_gf_sta_present = | 5380 | il->ht.non_gf_sta_present = |
5503 | !!(bss_conf-> | 5381 | !!(bss_conf-> |
5504 | ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | 5382 | ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); |
5505 | 5383 | ||
@@ -5548,16 +5426,14 @@ il_ht_conf(struct il_priv *il, struct ieee80211_vif *vif) | |||
5548 | static inline void | 5426 | static inline void |
5549 | il_set_no_assoc(struct il_priv *il, struct ieee80211_vif *vif) | 5427 | il_set_no_assoc(struct il_priv *il, struct ieee80211_vif *vif) |
5550 | { | 5428 | { |
5551 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
5552 | |||
5553 | /* | 5429 | /* |
5554 | * inform the ucode that there is no longer an | 5430 | * inform the ucode that there is no longer an |
5555 | * association and that no more packets should be | 5431 | * association and that no more packets should be |
5556 | * sent | 5432 | * sent |
5557 | */ | 5433 | */ |
5558 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 5434 | il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
5559 | ctx->staging.assoc_id = 0; | 5435 | il->staging.assoc_id = 0; |
5560 | il_commit_rxon(il, ctx); | 5436 | il_commit_rxon(il); |
5561 | } | 5437 | } |
5562 | 5438 | ||
5563 | static void | 5439 | static void |
@@ -5575,8 +5451,8 @@ il_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
5575 | 5451 | ||
5576 | lockdep_assert_held(&il->mutex); | 5452 | lockdep_assert_held(&il->mutex); |
5577 | 5453 | ||
5578 | if (!il->beacon_ctx) { | 5454 | if (!il->beacon_enabled) { |
5579 | IL_ERR("update beacon but no beacon context!\n"); | 5455 | IL_ERR("update beacon with no beaconing enabled\n"); |
5580 | dev_kfree_skb(skb); | 5456 | dev_kfree_skb(skb); |
5581 | return; | 5457 | return; |
5582 | } | 5458 | } |
@@ -5599,7 +5475,7 @@ il_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
5599 | return; | 5475 | return; |
5600 | } | 5476 | } |
5601 | 5477 | ||
5602 | il->cfg->ops->legacy->post_associate(il); | 5478 | il->ops->legacy->post_associate(il); |
5603 | } | 5479 | } |
5604 | 5480 | ||
5605 | void | 5481 | void |
@@ -5607,10 +5483,9 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5607 | struct ieee80211_bss_conf *bss_conf, u32 changes) | 5483 | struct ieee80211_bss_conf *bss_conf, u32 changes) |
5608 | { | 5484 | { |
5609 | struct il_priv *il = hw->priv; | 5485 | struct il_priv *il = hw->priv; |
5610 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
5611 | int ret; | 5486 | int ret; |
5612 | 5487 | ||
5613 | if (WARN_ON(!il->cfg->ops->legacy)) | 5488 | if (WARN_ON(!il->ops->legacy)) |
5614 | return; | 5489 | return; |
5615 | 5490 | ||
5616 | D_MAC80211("changes = 0x%X\n", changes); | 5491 | D_MAC80211("changes = 0x%X\n", changes); |
@@ -5626,21 +5501,17 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5626 | unsigned long flags; | 5501 | unsigned long flags; |
5627 | 5502 | ||
5628 | spin_lock_irqsave(&il->lock, flags); | 5503 | spin_lock_irqsave(&il->lock, flags); |
5629 | ctx->qos_data.qos_active = bss_conf->qos; | 5504 | il->qos_data.qos_active = bss_conf->qos; |
5630 | il_update_qos(il, ctx); | 5505 | il_update_qos(il); |
5631 | spin_unlock_irqrestore(&il->lock, flags); | 5506 | spin_unlock_irqrestore(&il->lock, flags); |
5632 | } | 5507 | } |
5633 | 5508 | ||
5634 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | 5509 | if (changes & BSS_CHANGED_BEACON_ENABLED) { |
5635 | /* | 5510 | /* FIXME: can we remove beacon_enabled ? */ |
5636 | * the add_interface code must make sure we only ever | ||
5637 | * have a single interface that could be beaconing at | ||
5638 | * any time. | ||
5639 | */ | ||
5640 | if (vif->bss_conf.enable_beacon) | 5511 | if (vif->bss_conf.enable_beacon) |
5641 | il->beacon_ctx = ctx; | 5512 | il->beacon_enabled = true; |
5642 | else | 5513 | else |
5643 | il->beacon_ctx = NULL; | 5514 | il->beacon_enabled = false; |
5644 | } | 5515 | } |
5645 | 5516 | ||
5646 | if (changes & BSS_CHANGED_BSSID) { | 5517 | if (changes & BSS_CHANGED_BSSID) { |
@@ -5660,13 +5531,13 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5660 | 5531 | ||
5661 | /* mac80211 only sets assoc when in STATION mode */ | 5532 | /* mac80211 only sets assoc when in STATION mode */ |
5662 | if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { | 5533 | if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { |
5663 | memcpy(ctx->staging.bssid_addr, bss_conf->bssid, | 5534 | memcpy(il->staging.bssid_addr, bss_conf->bssid, |
5664 | ETH_ALEN); | 5535 | ETH_ALEN); |
5665 | 5536 | ||
5666 | /* currently needed in a few places */ | 5537 | /* currently needed in a few places */ |
5667 | memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); | 5538 | memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); |
5668 | } else { | 5539 | } else { |
5669 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 5540 | il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
5670 | } | 5541 | } |
5671 | 5542 | ||
5672 | } | 5543 | } |
@@ -5682,21 +5553,21 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5682 | if (changes & BSS_CHANGED_ERP_PREAMBLE) { | 5553 | if (changes & BSS_CHANGED_ERP_PREAMBLE) { |
5683 | D_MAC80211("ERP_PREAMBLE %d\n", bss_conf->use_short_preamble); | 5554 | D_MAC80211("ERP_PREAMBLE %d\n", bss_conf->use_short_preamble); |
5684 | if (bss_conf->use_short_preamble) | 5555 | if (bss_conf->use_short_preamble) |
5685 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 5556 | il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
5686 | else | 5557 | else |
5687 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 5558 | il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
5688 | } | 5559 | } |
5689 | 5560 | ||
5690 | if (changes & BSS_CHANGED_ERP_CTS_PROT) { | 5561 | if (changes & BSS_CHANGED_ERP_CTS_PROT) { |
5691 | D_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); | 5562 | D_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); |
5692 | if (bss_conf->use_cts_prot && il->band != IEEE80211_BAND_5GHZ) | 5563 | if (bss_conf->use_cts_prot && il->band != IEEE80211_BAND_5GHZ) |
5693 | ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; | 5564 | il->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; |
5694 | else | 5565 | else |
5695 | ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; | 5566 | il->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; |
5696 | if (bss_conf->use_cts_prot) | 5567 | if (bss_conf->use_cts_prot) |
5697 | ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; | 5568 | il->staging.flags |= RXON_FLG_SELF_CTS_EN; |
5698 | else | 5569 | else |
5699 | ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; | 5570 | il->staging.flags &= ~RXON_FLG_SELF_CTS_EN; |
5700 | } | 5571 | } |
5701 | 5572 | ||
5702 | if (changes & BSS_CHANGED_BASIC_RATES) { | 5573 | if (changes & BSS_CHANGED_BASIC_RATES) { |
@@ -5706,12 +5577,12 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5706 | * like this here: | 5577 | * like this here: |
5707 | * | 5578 | * |
5708 | if (A-band) | 5579 | if (A-band) |
5709 | ctx->staging.ofdm_basic_rates = | 5580 | il->staging.ofdm_basic_rates = |
5710 | bss_conf->basic_rates; | 5581 | bss_conf->basic_rates; |
5711 | else | 5582 | else |
5712 | ctx->staging.ofdm_basic_rates = | 5583 | il->staging.ofdm_basic_rates = |
5713 | bss_conf->basic_rates >> 4; | 5584 | bss_conf->basic_rates >> 4; |
5714 | ctx->staging.cck_basic_rates = | 5585 | il->staging.cck_basic_rates = |
5715 | bss_conf->basic_rates & 0xF; | 5586 | bss_conf->basic_rates & 0xF; |
5716 | */ | 5587 | */ |
5717 | } | 5588 | } |
@@ -5719,8 +5590,8 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5719 | if (changes & BSS_CHANGED_HT) { | 5590 | if (changes & BSS_CHANGED_HT) { |
5720 | il_ht_conf(il, vif); | 5591 | il_ht_conf(il, vif); |
5721 | 5592 | ||
5722 | if (il->cfg->ops->hcmd->set_rxon_chain) | 5593 | if (il->ops->hcmd->set_rxon_chain) |
5723 | il->cfg->ops->hcmd->set_rxon_chain(il, ctx); | 5594 | il->ops->hcmd->set_rxon_chain(il); |
5724 | } | 5595 | } |
5725 | 5596 | ||
5726 | if (changes & BSS_CHANGED_ASSOC) { | 5597 | if (changes & BSS_CHANGED_ASSOC) { |
@@ -5729,36 +5600,35 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5729 | il->timestamp = bss_conf->timestamp; | 5600 | il->timestamp = bss_conf->timestamp; |
5730 | 5601 | ||
5731 | if (!il_is_rfkill(il)) | 5602 | if (!il_is_rfkill(il)) |
5732 | il->cfg->ops->legacy->post_associate(il); | 5603 | il->ops->legacy->post_associate(il); |
5733 | } else | 5604 | } else |
5734 | il_set_no_assoc(il, vif); | 5605 | il_set_no_assoc(il, vif); |
5735 | } | 5606 | } |
5736 | 5607 | ||
5737 | if (changes && il_is_associated_ctx(ctx) && bss_conf->aid) { | 5608 | if (changes && il_is_associated(il) && bss_conf->aid) { |
5738 | D_MAC80211("Changes (%#x) while associated\n", changes); | 5609 | D_MAC80211("Changes (%#x) while associated\n", changes); |
5739 | ret = il_send_rxon_assoc(il, ctx); | 5610 | ret = il_send_rxon_assoc(il); |
5740 | if (!ret) { | 5611 | if (!ret) { |
5741 | /* Sync active_rxon with latest change. */ | 5612 | /* Sync active_rxon with latest change. */ |
5742 | memcpy((void *)&ctx->active, &ctx->staging, | 5613 | memcpy((void *)&il->active, &il->staging, |
5743 | sizeof(struct il_rxon_cmd)); | 5614 | sizeof(struct il_rxon_cmd)); |
5744 | } | 5615 | } |
5745 | } | 5616 | } |
5746 | 5617 | ||
5747 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | 5618 | if (changes & BSS_CHANGED_BEACON_ENABLED) { |
5748 | if (vif->bss_conf.enable_beacon) { | 5619 | if (vif->bss_conf.enable_beacon) { |
5749 | memcpy(ctx->staging.bssid_addr, bss_conf->bssid, | 5620 | memcpy(il->staging.bssid_addr, bss_conf->bssid, |
5750 | ETH_ALEN); | 5621 | ETH_ALEN); |
5751 | memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); | 5622 | memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); |
5752 | il->cfg->ops->legacy->config_ap(il); | 5623 | il->ops->legacy->config_ap(il); |
5753 | } else | 5624 | } else |
5754 | il_set_no_assoc(il, vif); | 5625 | il_set_no_assoc(il, vif); |
5755 | } | 5626 | } |
5756 | 5627 | ||
5757 | if (changes & BSS_CHANGED_IBSS) { | 5628 | if (changes & BSS_CHANGED_IBSS) { |
5758 | ret = | 5629 | ret = |
5759 | il->cfg->ops->legacy->manage_ibss_station(il, vif, | 5630 | il->ops->legacy->manage_ibss_station(il, vif, |
5760 | bss_conf-> | 5631 | bss_conf->ibss_joined); |
5761 | ibss_joined); | ||
5762 | if (ret) | 5632 | if (ret) |
5763 | IL_ERR("failed to %s IBSS station %pM\n", | 5633 | IL_ERR("failed to %s IBSS station %pM\n", |
5764 | bss_conf->ibss_joined ? "add" : "remove", | 5634 | bss_conf->ibss_joined ? "add" : "remove", |
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index abfa388588be..708095644f17 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h | |||
@@ -143,12 +143,6 @@ struct il_queue { | |||
143 | * space less than this */ | 143 | * space less than this */ |
144 | }; | 144 | }; |
145 | 145 | ||
146 | /* One for each TFD */ | ||
147 | struct il_tx_info { | ||
148 | struct sk_buff *skb; | ||
149 | struct il_rxon_context *ctx; | ||
150 | }; | ||
151 | |||
152 | /** | 146 | /** |
153 | * struct il_tx_queue - Tx Queue for DMA | 147 | * struct il_tx_queue - Tx Queue for DMA |
154 | * @q: generic Rx/Tx queue descriptor | 148 | * @q: generic Rx/Tx queue descriptor |
@@ -156,7 +150,7 @@ struct il_tx_info { | |||
156 | * @cmd: array of command/TX buffer pointers | 150 | * @cmd: array of command/TX buffer pointers |
157 | * @meta: array of meta data for each command/tx buffer | 151 | * @meta: array of meta data for each command/tx buffer |
158 | * @dma_addr_cmd: physical address of cmd/tx buffer array | 152 | * @dma_addr_cmd: physical address of cmd/tx buffer array |
159 | * @txb: array of per-TFD driver data | 153 | * @skbs: array of per-TFD socket buffer pointers |
160 | * @time_stamp: time (in jiffies) of last read_ptr change | 154 | * @time_stamp: time (in jiffies) of last read_ptr change |
161 | * @need_update: indicates need to update read/write idx | 155 | * @need_update: indicates need to update read/write idx |
162 | * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled | 156 | * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled |
@@ -172,7 +166,7 @@ struct il_tx_queue { | |||
172 | void *tfds; | 166 | void *tfds; |
173 | struct il_device_cmd **cmd; | 167 | struct il_device_cmd **cmd; |
174 | struct il_cmd_meta *meta; | 168 | struct il_cmd_meta *meta; |
175 | struct il_tx_info *txb; | 169 | struct sk_buff **skbs; |
176 | unsigned long time_stamp; | 170 | unsigned long time_stamp; |
177 | u8 need_update; | 171 | u8 need_update; |
178 | u8 sched_retry; | 172 | u8 sched_retry; |
@@ -735,13 +729,12 @@ struct il_qos_info { | |||
735 | struct il_station_entry { | 729 | struct il_station_entry { |
736 | struct il_addsta_cmd sta; | 730 | struct il_addsta_cmd sta; |
737 | struct il_tid_data tid[MAX_TID_COUNT]; | 731 | struct il_tid_data tid[MAX_TID_COUNT]; |
738 | u8 used, ctxid; | 732 | u8 used; |
739 | struct il_hw_key keyinfo; | 733 | struct il_hw_key keyinfo; |
740 | struct il_link_quality_cmd *lq; | 734 | struct il_link_quality_cmd *lq; |
741 | }; | 735 | }; |
742 | 736 | ||
743 | struct il_station_priv_common { | 737 | struct il_station_priv_common { |
744 | struct il_rxon_context *ctx; | ||
745 | u8 sta_id; | 738 | u8 sta_id; |
746 | }; | 739 | }; |
747 | 740 | ||
@@ -752,7 +745,6 @@ struct il_station_priv_common { | |||
752 | * space for us to put data into. | 745 | * space for us to put data into. |
753 | */ | 746 | */ |
754 | struct il_vif_priv { | 747 | struct il_vif_priv { |
755 | struct il_rxon_context *ctx; | ||
756 | u8 ibss_bssid_sta_id; | 748 | u8 ibss_bssid_sta_id; |
757 | }; | 749 | }; |
758 | 750 | ||
@@ -816,6 +808,7 @@ struct il_sensitivity_ranges { | |||
816 | 808 | ||
817 | /** | 809 | /** |
818 | * struct il_hw_params | 810 | * struct il_hw_params |
811 | * @bcast_id: f/w broadcast station ID | ||
819 | * @max_txq_num: Max # Tx queues supported | 812 | * @max_txq_num: Max # Tx queues supported |
820 | * @dma_chnl_num: Number of Tx DMA/FIFO channels | 813 | * @dma_chnl_num: Number of Tx DMA/FIFO channels |
821 | * @scd_bc_tbls_size: size of scheduler byte count tables | 814 | * @scd_bc_tbls_size: size of scheduler byte count tables |
@@ -836,6 +829,7 @@ struct il_sensitivity_ranges { | |||
836 | * @struct il_sensitivity_ranges: range of sensitivity values | 829 | * @struct il_sensitivity_ranges: range of sensitivity values |
837 | */ | 830 | */ |
838 | struct il_hw_params { | 831 | struct il_hw_params { |
832 | u8 bcast_id; | ||
839 | u8 max_txq_num; | 833 | u8 max_txq_num; |
840 | u8 dma_chnl_num; | 834 | u8 dma_chnl_num; |
841 | u16 scd_bc_tbls_size; | 835 | u16 scd_bc_tbls_size; |
@@ -1152,55 +1146,6 @@ struct il_force_reset { | |||
1152 | 1146 | ||
1153 | struct il_rxon_context { | 1147 | struct il_rxon_context { |
1154 | struct ieee80211_vif *vif; | 1148 | struct ieee80211_vif *vif; |
1155 | |||
1156 | const u8 *ac_to_fifo; | ||
1157 | const u8 *ac_to_queue; | ||
1158 | u8 mcast_queue; | ||
1159 | |||
1160 | /* | ||
1161 | * We could use the vif to indicate active, but we | ||
1162 | * also need it to be active during disabling when | ||
1163 | * we already removed the vif for type setting. | ||
1164 | */ | ||
1165 | bool always_active, is_active; | ||
1166 | |||
1167 | bool ht_need_multiple_chains; | ||
1168 | |||
1169 | int ctxid; | ||
1170 | |||
1171 | u32 interface_modes, exclusive_interface_modes; | ||
1172 | u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype; | ||
1173 | |||
1174 | /* | ||
1175 | * We declare this const so it can only be | ||
1176 | * changed via explicit cast within the | ||
1177 | * routines that actually update the physical | ||
1178 | * hardware. | ||
1179 | */ | ||
1180 | const struct il_rxon_cmd active; | ||
1181 | struct il_rxon_cmd staging; | ||
1182 | |||
1183 | struct il_rxon_time_cmd timing; | ||
1184 | |||
1185 | struct il_qos_info qos_data; | ||
1186 | |||
1187 | u8 bcast_sta_id, ap_sta_id; | ||
1188 | |||
1189 | u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd; | ||
1190 | u8 qos_cmd; | ||
1191 | u8 wep_key_cmd; | ||
1192 | |||
1193 | struct il_wep_key wep_keys[WEP_KEYS_MAX]; | ||
1194 | u8 key_mapping_keys; | ||
1195 | |||
1196 | __le32 station_flags; | ||
1197 | |||
1198 | struct { | ||
1199 | bool non_gf_sta_present; | ||
1200 | u8 protection; | ||
1201 | bool enabled, is_40mhz; | ||
1202 | u8 extension_chan_offset; | ||
1203 | } ht; | ||
1204 | }; | 1149 | }; |
1205 | 1150 | ||
1206 | struct il_power_mgr { | 1151 | struct il_power_mgr { |
@@ -1217,6 +1162,7 @@ struct il_priv { | |||
1217 | struct ieee80211_channel *ieee_channels; | 1162 | struct ieee80211_channel *ieee_channels; |
1218 | struct ieee80211_rate *ieee_rates; | 1163 | struct ieee80211_rate *ieee_rates; |
1219 | struct il_cfg *cfg; | 1164 | struct il_cfg *cfg; |
1165 | const struct il_ops *ops; | ||
1220 | 1166 | ||
1221 | /* temporary frame storage list */ | 1167 | /* temporary frame storage list */ |
1222 | struct list_head free_frames; | 1168 | struct list_head free_frames; |
@@ -1304,7 +1250,28 @@ struct il_priv { | |||
1304 | u8 ucode_write_complete; /* the image write is complete */ | 1250 | u8 ucode_write_complete; /* the image write is complete */ |
1305 | char firmware_name[25]; | 1251 | char firmware_name[25]; |
1306 | 1252 | ||
1307 | struct il_rxon_context ctx; | 1253 | struct ieee80211_vif *vif; |
1254 | |||
1255 | struct il_qos_info qos_data; | ||
1256 | |||
1257 | struct { | ||
1258 | bool enabled; | ||
1259 | bool is_40mhz; | ||
1260 | bool non_gf_sta_present; | ||
1261 | u8 protection; | ||
1262 | u8 extension_chan_offset; | ||
1263 | } ht; | ||
1264 | |||
1265 | /* | ||
1266 | * We declare this const so it can only be | ||
1267 | * changed via explicit cast within the | ||
1268 | * routines that actually update the physical | ||
1269 | * hardware. | ||
1270 | */ | ||
1271 | const struct il_rxon_cmd active; | ||
1272 | struct il_rxon_cmd staging; | ||
1273 | |||
1274 | struct il_rxon_time_cmd timing; | ||
1308 | 1275 | ||
1309 | __le16 switch_channel; | 1276 | __le16 switch_channel; |
1310 | 1277 | ||
@@ -1427,6 +1394,9 @@ struct il_priv { | |||
1427 | u8 phy_calib_chain_noise_reset_cmd; | 1394 | u8 phy_calib_chain_noise_reset_cmd; |
1428 | u8 phy_calib_chain_noise_gain_cmd; | 1395 | u8 phy_calib_chain_noise_gain_cmd; |
1429 | 1396 | ||
1397 | u8 key_mapping_keys; | ||
1398 | struct il_wep_key wep_keys[WEP_KEYS_MAX]; | ||
1399 | |||
1430 | struct il_notif_stats stats; | 1400 | struct il_notif_stats stats; |
1431 | #ifdef CONFIG_IWLEGACY_DEBUGFS | 1401 | #ifdef CONFIG_IWLEGACY_DEBUGFS |
1432 | struct il_notif_stats accum_stats; | 1402 | struct il_notif_stats accum_stats; |
@@ -1449,7 +1419,7 @@ struct il_priv { | |||
1449 | struct work_struct rx_replenish; | 1419 | struct work_struct rx_replenish; |
1450 | struct work_struct abort_scan; | 1420 | struct work_struct abort_scan; |
1451 | 1421 | ||
1452 | struct il_rxon_context *beacon_ctx; | 1422 | bool beacon_enabled; |
1453 | struct sk_buff *beacon_skb; | 1423 | struct sk_buff *beacon_skb; |
1454 | 1424 | ||
1455 | struct work_struct tx_flush; | 1425 | struct work_struct tx_flush; |
@@ -1507,30 +1477,10 @@ il_txq_ctx_deactivate(struct il_priv *il, int txq_id) | |||
1507 | clear_bit(txq_id, &il->txq_ctx_active_msk); | 1477 | clear_bit(txq_id, &il->txq_ctx_active_msk); |
1508 | } | 1478 | } |
1509 | 1479 | ||
1510 | static inline struct ieee80211_hdr * | ||
1511 | il_tx_queue_get_hdr(struct il_priv *il, int txq_id, int idx) | ||
1512 | { | ||
1513 | if (il->txq[txq_id].txb[idx].skb) | ||
1514 | return (struct ieee80211_hdr *)il->txq[txq_id].txb[idx].skb-> | ||
1515 | data; | ||
1516 | return NULL; | ||
1517 | } | ||
1518 | |||
1519 | static inline struct il_rxon_context * | ||
1520 | il_rxon_ctx_from_vif(struct ieee80211_vif *vif) | ||
1521 | { | ||
1522 | struct il_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
1523 | |||
1524 | return vif_priv->ctx; | ||
1525 | } | ||
1526 | |||
1527 | #define for_each_context(il, _ctx) \ | ||
1528 | for (_ctx = &il->ctx; _ctx == &il->ctx; _ctx++) | ||
1529 | |||
1530 | static inline int | 1480 | static inline int |
1531 | il_is_associated(struct il_priv *il) | 1481 | il_is_associated(struct il_priv *il) |
1532 | { | 1482 | { |
1533 | return (il->ctx.active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; | 1483 | return (il->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; |
1534 | } | 1484 | } |
1535 | 1485 | ||
1536 | static inline int | 1486 | static inline int |
@@ -1540,12 +1490,6 @@ il_is_any_associated(struct il_priv *il) | |||
1540 | } | 1490 | } |
1541 | 1491 | ||
1542 | static inline int | 1492 | static inline int |
1543 | il_is_associated_ctx(struct il_rxon_context *ctx) | ||
1544 | { | ||
1545 | return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; | ||
1546 | } | ||
1547 | |||
1548 | static inline int | ||
1549 | il_is_channel_valid(const struct il_channel_info *ch_info) | 1493 | il_is_channel_valid(const struct il_channel_info *ch_info) |
1550 | { | 1494 | { |
1551 | if (ch_info == NULL) | 1495 | if (ch_info == NULL) |
@@ -1614,10 +1558,9 @@ il_free_pages(struct il_priv *il, unsigned long page) | |||
1614 | #define IL_RX_BUF_SIZE_8K (8 * 1024) | 1558 | #define IL_RX_BUF_SIZE_8K (8 * 1024) |
1615 | 1559 | ||
1616 | struct il_hcmd_ops { | 1560 | struct il_hcmd_ops { |
1617 | int (*rxon_assoc) (struct il_priv *il, struct il_rxon_context *ctx); | 1561 | int (*rxon_assoc) (struct il_priv *il); |
1618 | int (*commit_rxon) (struct il_priv *il, struct il_rxon_context *ctx); | 1562 | int (*commit_rxon) (struct il_priv *il); |
1619 | void (*set_rxon_chain) (struct il_priv *il, | 1563 | void (*set_rxon_chain) (struct il_priv *il); |
1620 | struct il_rxon_context *ctx); | ||
1621 | }; | 1564 | }; |
1622 | 1565 | ||
1623 | struct il_hcmd_utils_ops { | 1566 | struct il_hcmd_utils_ops { |
@@ -1649,8 +1592,6 @@ struct il_temp_ops { | |||
1649 | }; | 1592 | }; |
1650 | 1593 | ||
1651 | struct il_lib_ops { | 1594 | struct il_lib_ops { |
1652 | /* set hw dependent parameters */ | ||
1653 | int (*set_hw_params) (struct il_priv *il); | ||
1654 | /* Handling TX */ | 1595 | /* Handling TX */ |
1655 | void (*txq_update_byte_cnt_tbl) (struct il_priv *il, | 1596 | void (*txq_update_byte_cnt_tbl) (struct il_priv *il, |
1656 | struct il_tx_queue *txq, | 1597 | struct il_tx_queue *txq, |
@@ -1712,7 +1653,6 @@ struct il_ops { | |||
1712 | const struct il_led_ops *led; | 1653 | const struct il_led_ops *led; |
1713 | const struct il_nic_ops *nic; | 1654 | const struct il_nic_ops *nic; |
1714 | const struct il_legacy_ops *legacy; | 1655 | const struct il_legacy_ops *legacy; |
1715 | const struct ieee80211_ops *ieee80211_ops; | ||
1716 | }; | 1656 | }; |
1717 | 1657 | ||
1718 | struct il_mod_params { | 1658 | struct il_mod_params { |
@@ -1739,21 +1679,6 @@ struct il_mod_params { | |||
1739 | * chain noise calibration operation | 1679 | * chain noise calibration operation |
1740 | */ | 1680 | */ |
1741 | struct il_base_params { | 1681 | struct il_base_params { |
1742 | int eeprom_size; | ||
1743 | int num_of_queues; /* def: HW dependent */ | ||
1744 | int num_of_ampdu_queues; /* def: HW dependent */ | ||
1745 | /* for il_apm_init() */ | ||
1746 | u32 pll_cfg_val; | ||
1747 | bool set_l0s; | ||
1748 | bool use_bsm; | ||
1749 | |||
1750 | u16 led_compensation; | ||
1751 | int chain_noise_num_beacons; | ||
1752 | unsigned int wd_timeout; | ||
1753 | bool temperature_kelvin; | ||
1754 | const bool ucode_tracing; | ||
1755 | const bool sensitivity_calib_by_driver; | ||
1756 | const bool chain_noise_calib_by_driver; | ||
1757 | }; | 1682 | }; |
1758 | 1683 | ||
1759 | #define IL_LED_SOLID 11 | 1684 | #define IL_LED_SOLID 11 |
@@ -1821,7 +1746,6 @@ struct il_cfg { | |||
1821 | unsigned int sku; | 1746 | unsigned int sku; |
1822 | u16 eeprom_ver; | 1747 | u16 eeprom_ver; |
1823 | u16 eeprom_calib_ver; | 1748 | u16 eeprom_calib_ver; |
1824 | const struct il_ops *ops; | ||
1825 | /* module based parameters which can be set from modprobe cmd */ | 1749 | /* module based parameters which can be set from modprobe cmd */ |
1826 | const struct il_mod_params *mod_params; | 1750 | const struct il_mod_params *mod_params; |
1827 | /* params not likely to change within a device family */ | 1751 | /* params not likely to change within a device family */ |
@@ -1829,31 +1753,43 @@ struct il_cfg { | |||
1829 | /* params likely to change within a device family */ | 1753 | /* params likely to change within a device family */ |
1830 | u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; | 1754 | u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; |
1831 | enum il_led_mode led_mode; | 1755 | enum il_led_mode led_mode; |
1756 | |||
1757 | int eeprom_size; | ||
1758 | int num_of_queues; /* def: HW dependent */ | ||
1759 | int num_of_ampdu_queues; /* def: HW dependent */ | ||
1760 | /* for il_apm_init() */ | ||
1761 | u32 pll_cfg_val; | ||
1762 | bool set_l0s; | ||
1763 | bool use_bsm; | ||
1764 | |||
1765 | u16 led_compensation; | ||
1766 | int chain_noise_num_beacons; | ||
1767 | unsigned int wd_timeout; | ||
1768 | bool temperature_kelvin; | ||
1769 | const bool ucode_tracing; | ||
1770 | const bool sensitivity_calib_by_driver; | ||
1771 | const bool chain_noise_calib_by_driver; | ||
1832 | }; | 1772 | }; |
1833 | 1773 | ||
1834 | /*************************** | 1774 | /*************************** |
1835 | * L i b * | 1775 | * L i b * |
1836 | ***************************/ | 1776 | ***************************/ |
1837 | 1777 | ||
1838 | struct ieee80211_hw *il_alloc_all(struct il_cfg *cfg); | ||
1839 | int il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1778 | int il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1840 | u16 queue, const struct ieee80211_tx_queue_params *params); | 1779 | u16 queue, const struct ieee80211_tx_queue_params *params); |
1841 | int il_mac_tx_last_beacon(struct ieee80211_hw *hw); | 1780 | int il_mac_tx_last_beacon(struct ieee80211_hw *hw); |
1842 | 1781 | ||
1843 | void il_set_rxon_hwcrypto(struct il_priv *il, struct il_rxon_context *ctx, | 1782 | void il_set_rxon_hwcrypto(struct il_priv *il, int hw_decrypt); |
1844 | int hw_decrypt); | 1783 | int il_check_rxon_cmd(struct il_priv *il); |
1845 | int il_check_rxon_cmd(struct il_priv *il, struct il_rxon_context *ctx); | 1784 | int il_full_rxon_required(struct il_priv *il); |
1846 | int il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx); | 1785 | int il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch); |
1847 | int il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch, | 1786 | void il_set_flags_for_band(struct il_priv *il, enum ieee80211_band band, |
1848 | struct il_rxon_context *ctx); | 1787 | struct ieee80211_vif *vif); |
1849 | void il_set_flags_for_band(struct il_priv *il, struct il_rxon_context *ctx, | ||
1850 | enum ieee80211_band band, struct ieee80211_vif *vif); | ||
1851 | u8 il_get_single_channel_number(struct il_priv *il, enum ieee80211_band band); | 1788 | u8 il_get_single_channel_number(struct il_priv *il, enum ieee80211_band band); |
1852 | void il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf); | 1789 | void il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf); |
1853 | bool il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx, | 1790 | bool il_is_ht40_tx_allowed(struct il_priv *il, |
1854 | struct ieee80211_sta_ht_cap *ht_cap); | 1791 | struct ieee80211_sta_ht_cap *ht_cap); |
1855 | void il_connection_init_rx_config(struct il_priv *il, | 1792 | void il_connection_init_rx_config(struct il_priv *il); |
1856 | struct il_rxon_context *ctx); | ||
1857 | void il_set_rate(struct il_priv *il); | 1793 | void il_set_rate(struct il_priv *il); |
1858 | int il_set_decrypted_flag(struct il_priv *il, struct ieee80211_hdr *hdr, | 1794 | int il_set_decrypted_flag(struct il_priv *il, struct ieee80211_hdr *hdr, |
1859 | u32 decrypt_res, struct ieee80211_rx_status *stats); | 1795 | u32 decrypt_res, struct ieee80211_rx_status *stats); |
@@ -1956,7 +1892,7 @@ int il_set_tx_power(struct il_priv *il, s8 tx_power, bool force); | |||
1956 | * Rate | 1892 | * Rate |
1957 | ******************************************************************************/ | 1893 | ******************************************************************************/ |
1958 | 1894 | ||
1959 | u8 il_get_lowest_plcp(struct il_priv *il, struct il_rxon_context *ctx); | 1895 | u8 il_get_lowest_plcp(struct il_priv *il); |
1960 | 1896 | ||
1961 | /******************************************************************************* | 1897 | /******************************************************************************* |
1962 | * Scanning | 1898 | * Scanning |
@@ -2043,10 +1979,10 @@ extern const struct dev_pm_ops il_pm_ops; | |||
2043 | ******************************************************/ | 1979 | ******************************************************/ |
2044 | void il4965_dump_nic_error_log(struct il_priv *il); | 1980 | void il4965_dump_nic_error_log(struct il_priv *il); |
2045 | #ifdef CONFIG_IWLEGACY_DEBUG | 1981 | #ifdef CONFIG_IWLEGACY_DEBUG |
2046 | void il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx); | 1982 | void il_print_rx_config_cmd(struct il_priv *il); |
2047 | #else | 1983 | #else |
2048 | static inline void | 1984 | static inline void |
2049 | il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx) | 1985 | il_print_rx_config_cmd(struct il_priv *il) |
2050 | { | 1986 | { |
2051 | } | 1987 | } |
2052 | #endif | 1988 | #endif |
@@ -2135,17 +2071,18 @@ extern int il_send_stats_request(struct il_priv *il, u8 flags, bool clear); | |||
2135 | void il_apm_stop(struct il_priv *il); | 2071 | void il_apm_stop(struct il_priv *il); |
2136 | int il_apm_init(struct il_priv *il); | 2072 | int il_apm_init(struct il_priv *il); |
2137 | 2073 | ||
2138 | int il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx); | 2074 | int il_send_rxon_timing(struct il_priv *il); |
2075 | |||
2139 | static inline int | 2076 | static inline int |
2140 | il_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) | 2077 | il_send_rxon_assoc(struct il_priv *il) |
2141 | { | 2078 | { |
2142 | return il->cfg->ops->hcmd->rxon_assoc(il, ctx); | 2079 | return il->ops->hcmd->rxon_assoc(il); |
2143 | } | 2080 | } |
2144 | 2081 | ||
2145 | static inline int | 2082 | static inline int |
2146 | il_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) | 2083 | il_commit_rxon(struct il_priv *il) |
2147 | { | 2084 | { |
2148 | return il->cfg->ops->hcmd->commit_rxon(il, ctx); | 2085 | return il->ops->hcmd->commit_rxon(il); |
2149 | } | 2086 | } |
2150 | 2087 | ||
2151 | static inline const struct ieee80211_supported_band * | 2088 | static inline const struct ieee80211_supported_band * |
@@ -2303,23 +2240,22 @@ il_clear_bits_prph(struct il_priv *il, u32 reg, u32 mask) | |||
2303 | (this is for the IBSS BSSID stations) */ | 2240 | (this is for the IBSS BSSID stations) */ |
2304 | #define IL_STA_BCAST BIT(4) /* this station is the special bcast station */ | 2241 | #define IL_STA_BCAST BIT(4) /* this station is the special bcast station */ |
2305 | 2242 | ||
2306 | void il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx); | 2243 | void il_restore_stations(struct il_priv *il); |
2307 | void il_clear_ucode_stations(struct il_priv *il, struct il_rxon_context *ctx); | 2244 | void il_clear_ucode_stations(struct il_priv *il); |
2308 | void il_dealloc_bcast_stations(struct il_priv *il); | 2245 | void il_dealloc_bcast_stations(struct il_priv *il); |
2309 | int il_get_free_ucode_key_idx(struct il_priv *il); | 2246 | int il_get_free_ucode_key_idx(struct il_priv *il); |
2310 | int il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags); | 2247 | int il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags); |
2311 | int il_add_station_common(struct il_priv *il, struct il_rxon_context *ctx, | 2248 | int il_add_station_common(struct il_priv *il, const u8 *addr, bool is_ap, |
2312 | const u8 *addr, bool is_ap, | ||
2313 | struct ieee80211_sta *sta, u8 *sta_id_r); | 2249 | struct ieee80211_sta *sta, u8 *sta_id_r); |
2314 | int il_remove_station(struct il_priv *il, const u8 sta_id, const u8 * addr); | 2250 | int il_remove_station(struct il_priv *il, const u8 sta_id, const u8 * addr); |
2315 | int il_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2251 | int il_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2316 | struct ieee80211_sta *sta); | 2252 | struct ieee80211_sta *sta); |
2317 | 2253 | ||
2318 | u8 il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, | 2254 | u8 il_prep_station(struct il_priv *il, const u8 *addr, bool is_ap, |
2319 | const u8 *addr, bool is_ap, struct ieee80211_sta *sta); | 2255 | struct ieee80211_sta *sta); |
2320 | 2256 | ||
2321 | int il_send_lq_cmd(struct il_priv *il, struct il_rxon_context *ctx, | 2257 | int il_send_lq_cmd(struct il_priv *il, struct il_link_quality_cmd *lq, |
2322 | struct il_link_quality_cmd *lq, u8 flags, bool init); | 2258 | u8 flags, bool init); |
2323 | 2259 | ||
2324 | /** | 2260 | /** |
2325 | * il_clear_driver_stations - clear knowledge of all stations from driver | 2261 | * il_clear_driver_stations - clear knowledge of all stations from driver |
@@ -2334,24 +2270,11 @@ static inline void | |||
2334 | il_clear_driver_stations(struct il_priv *il) | 2270 | il_clear_driver_stations(struct il_priv *il) |
2335 | { | 2271 | { |
2336 | unsigned long flags; | 2272 | unsigned long flags; |
2337 | struct il_rxon_context *ctx = &il->ctx; | ||
2338 | 2273 | ||
2339 | spin_lock_irqsave(&il->sta_lock, flags); | 2274 | spin_lock_irqsave(&il->sta_lock, flags); |
2340 | memset(il->stations, 0, sizeof(il->stations)); | 2275 | memset(il->stations, 0, sizeof(il->stations)); |
2341 | il->num_stations = 0; | 2276 | il->num_stations = 0; |
2342 | |||
2343 | il->ucode_key_table = 0; | 2277 | il->ucode_key_table = 0; |
2344 | |||
2345 | /* | ||
2346 | * Remove all key information that is not stored as part | ||
2347 | * of station information since mac80211 may not have had | ||
2348 | * a chance to remove all the keys. When device is | ||
2349 | * reconfigured by mac80211 after an error all keys will | ||
2350 | * be reconfigured. | ||
2351 | */ | ||
2352 | memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys)); | ||
2353 | ctx->key_mapping_keys = 0; | ||
2354 | |||
2355 | spin_unlock_irqrestore(&il->sta_lock, flags); | 2278 | spin_unlock_irqrestore(&il->sta_lock, flags); |
2356 | } | 2279 | } |
2357 | 2280 | ||
@@ -2376,13 +2299,12 @@ il_sta_id(struct ieee80211_sta *sta) | |||
2376 | * inline wraps that pattern. | 2299 | * inline wraps that pattern. |
2377 | */ | 2300 | */ |
2378 | static inline int | 2301 | static inline int |
2379 | il_sta_id_or_broadcast(struct il_priv *il, struct il_rxon_context *context, | 2302 | il_sta_id_or_broadcast(struct il_priv *il, struct ieee80211_sta *sta) |
2380 | struct ieee80211_sta *sta) | ||
2381 | { | 2303 | { |
2382 | int sta_id; | 2304 | int sta_id; |
2383 | 2305 | ||
2384 | if (!sta) | 2306 | if (!sta) |
2385 | return context->bcast_sta_id; | 2307 | return il->hw_params.bcast_id; |
2386 | 2308 | ||
2387 | sta_id = il_sta_id(sta); | 2309 | sta_id = il_sta_id(sta); |
2388 | 2310 | ||
diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c index b1b8926a9c7b..bb7c95607a69 100644 --- a/drivers/net/wireless/iwlegacy/debug.c +++ b/drivers/net/wireless/iwlegacy/debug.c | |||
@@ -361,7 +361,7 @@ il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count, | |||
361 | const u8 *ptr; | 361 | const u8 *ptr; |
362 | char *buf; | 362 | char *buf; |
363 | u16 eeprom_ver; | 363 | u16 eeprom_ver; |
364 | size_t eeprom_len = il->cfg->base_params->eeprom_size; | 364 | size_t eeprom_len = il->cfg->eeprom_size; |
365 | buf_size = 4 * eeprom_len + 256; | 365 | buf_size = 4 * eeprom_len + 256; |
366 | 366 | ||
367 | if (eeprom_len % 16) { | 367 | if (eeprom_len % 16) { |
@@ -644,12 +644,10 @@ il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, | |||
644 | loff_t *ppos) | 644 | loff_t *ppos) |
645 | { | 645 | { |
646 | struct il_priv *il = file->private_data; | 646 | struct il_priv *il = file->private_data; |
647 | struct il_rxon_context *ctx = &il->ctx; | ||
648 | int pos = 0, i; | 647 | int pos = 0, i; |
649 | char buf[256]; | 648 | char buf[256]; |
650 | const size_t bufsz = sizeof(buf); | 649 | const size_t bufsz = sizeof(buf); |
651 | 650 | ||
652 | pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n", ctx->ctxid); | ||
653 | for (i = 0; i < AC_NUM; i++) { | 651 | for (i = 0; i < AC_NUM; i++) { |
654 | pos += | 652 | pos += |
655 | scnprintf(buf + pos, bufsz - pos, | 653 | scnprintf(buf + pos, bufsz - pos, |
@@ -657,10 +655,10 @@ il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, | |||
657 | pos += | 655 | pos += |
658 | scnprintf(buf + pos, bufsz - pos, | 656 | scnprintf(buf + pos, bufsz - pos, |
659 | "AC[%d]\t%u\t%u\t%u\t%u\n", i, | 657 | "AC[%d]\t%u\t%u\t%u\t%u\n", i, |
660 | ctx->qos_data.def_qos_parm.ac[i].cw_min, | 658 | il->qos_data.def_qos_parm.ac[i].cw_min, |
661 | ctx->qos_data.def_qos_parm.ac[i].cw_max, | 659 | il->qos_data.def_qos_parm.ac[i].cw_max, |
662 | ctx->qos_data.def_qos_parm.ac[i].aifsn, | 660 | il->qos_data.def_qos_parm.ac[i].aifsn, |
663 | ctx->qos_data.def_qos_parm.ac[i].edca_txop); | 661 | il->qos_data.def_qos_parm.ac[i].edca_txop); |
664 | } | 662 | } |
665 | 663 | ||
666 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 664 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
@@ -729,7 +727,7 @@ il_dbgfs_traffic_log_read(struct file *file, char __user *user_buf, | |||
729 | char *buf; | 727 | char *buf; |
730 | int bufsz = | 728 | int bufsz = |
731 | ((IL_TRAFFIC_ENTRIES * IL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | 729 | ((IL_TRAFFIC_ENTRIES * IL_TRAFFIC_ENTRY_SIZE * 64) * 2) + |
732 | (il->cfg->base_params->num_of_queues * 32 * 8) + 400; | 730 | (il->cfg->num_of_queues * 32 * 8) + 400; |
733 | const u8 *ptr; | 731 | const u8 *ptr; |
734 | ssize_t ret; | 732 | ssize_t ret; |
735 | 733 | ||
@@ -835,7 +833,7 @@ il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count, | |||
835 | int cnt; | 833 | int cnt; |
836 | int ret; | 834 | int ret; |
837 | const size_t bufsz = | 835 | const size_t bufsz = |
838 | sizeof(char) * 64 * il->cfg->base_params->num_of_queues; | 836 | sizeof(char) * 64 * il->cfg->num_of_queues; |
839 | 837 | ||
840 | if (!il->txq) { | 838 | if (!il->txq) { |
841 | IL_ERR("txq not ready\n"); | 839 | IL_ERR("txq not ready\n"); |
@@ -903,8 +901,7 @@ il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, | |||
903 | size_t count, loff_t *ppos) | 901 | size_t count, loff_t *ppos) |
904 | { | 902 | { |
905 | struct il_priv *il = file->private_data; | 903 | struct il_priv *il = file->private_data; |
906 | return il->cfg->ops->lib->debugfs_ops.rx_stats_read(file, user_buf, | 904 | return il->ops->lib->debugfs_ops.rx_stats_read(file, user_buf, count, ppos); |
907 | count, ppos); | ||
908 | } | 905 | } |
909 | 906 | ||
910 | static ssize_t | 907 | static ssize_t |
@@ -912,8 +909,7 @@ il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf, | |||
912 | size_t count, loff_t *ppos) | 909 | size_t count, loff_t *ppos) |
913 | { | 910 | { |
914 | struct il_priv *il = file->private_data; | 911 | struct il_priv *il = file->private_data; |
915 | return il->cfg->ops->lib->debugfs_ops.tx_stats_read(file, user_buf, | 912 | return il->ops->lib->debugfs_ops.tx_stats_read(file, user_buf, count, ppos); |
916 | count, ppos); | ||
917 | } | 913 | } |
918 | 914 | ||
919 | static ssize_t | 915 | static ssize_t |
@@ -921,8 +917,7 @@ il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf, | |||
921 | size_t count, loff_t *ppos) | 917 | size_t count, loff_t *ppos) |
922 | { | 918 | { |
923 | struct il_priv *il = file->private_data; | 919 | struct il_priv *il = file->private_data; |
924 | return il->cfg->ops->lib->debugfs_ops.general_stats_read(file, user_buf, | 920 | return il->ops->lib->debugfs_ops.general_stats_read(file, user_buf, count, ppos); |
925 | count, ppos); | ||
926 | } | 921 | } |
927 | 922 | ||
928 | static ssize_t | 923 | static ssize_t |
@@ -1153,7 +1148,7 @@ il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf, | |||
1153 | int len = 0; | 1148 | int len = 0; |
1154 | char buf[20]; | 1149 | char buf[20]; |
1155 | 1150 | ||
1156 | len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->ctx.active.flags)); | 1151 | len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags)); |
1157 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 1152 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
1158 | } | 1153 | } |
1159 | 1154 | ||
@@ -1167,7 +1162,7 @@ il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf, | |||
1167 | char buf[20]; | 1162 | char buf[20]; |
1168 | 1163 | ||
1169 | len = | 1164 | len = |
1170 | sprintf(buf, "0x%04X\n", le32_to_cpu(il->ctx.active.filter_flags)); | 1165 | sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags)); |
1171 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 1166 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
1172 | } | 1167 | } |
1173 | 1168 | ||
@@ -1180,8 +1175,8 @@ il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count, | |||
1180 | int pos = 0; | 1175 | int pos = 0; |
1181 | ssize_t ret = -EFAULT; | 1176 | ssize_t ret = -EFAULT; |
1182 | 1177 | ||
1183 | if (il->cfg->ops->lib->dump_fh) { | 1178 | if (il->ops->lib->dump_fh) { |
1184 | ret = pos = il->cfg->ops->lib->dump_fh(il, &buf, true); | 1179 | ret = pos = il->ops->lib->dump_fh(il, &buf, true); |
1185 | if (buf) { | 1180 | if (buf) { |
1186 | ret = | 1181 | ret = |
1187 | simple_read_from_buffer(user_buf, count, ppos, buf, | 1182 | simple_read_from_buffer(user_buf, count, ppos, buf, |
@@ -1298,7 +1293,7 @@ il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf, | |||
1298 | if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT) | 1293 | if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT) |
1299 | timeout = IL_DEF_WD_TIMEOUT; | 1294 | timeout = IL_DEF_WD_TIMEOUT; |
1300 | 1295 | ||
1301 | il->cfg->base_params->wd_timeout = timeout; | 1296 | il->cfg->wd_timeout = timeout; |
1302 | il_setup_watchdog(il); | 1297 | il_setup_watchdog(il); |
1303 | return count; | 1298 | return count; |
1304 | } | 1299 | } |
@@ -1372,17 +1367,17 @@ il_dbgfs_register(struct il_priv *il, const char *name) | |||
1372 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); | 1367 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); |
1373 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); | 1368 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); |
1374 | 1369 | ||
1375 | if (il->cfg->base_params->sensitivity_calib_by_driver) | 1370 | if (il->cfg->sensitivity_calib_by_driver) |
1376 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); | 1371 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); |
1377 | if (il->cfg->base_params->chain_noise_calib_by_driver) | 1372 | if (il->cfg->chain_noise_calib_by_driver) |
1378 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); | 1373 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); |
1379 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | 1374 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); |
1380 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 1375 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); |
1381 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); | 1376 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); |
1382 | if (il->cfg->base_params->sensitivity_calib_by_driver) | 1377 | if (il->cfg->sensitivity_calib_by_driver) |
1383 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, | 1378 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, |
1384 | &il->disable_sens_cal); | 1379 | &il->disable_sens_cal); |
1385 | if (il->cfg->base_params->chain_noise_calib_by_driver) | 1380 | if (il->cfg->chain_noise_calib_by_driver) |
1386 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | 1381 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, |
1387 | &il->disable_chain_noise_cal); | 1382 | &il->disable_chain_noise_cal); |
1388 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal); | 1383 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index cc04cce11567..8c1466c907ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -84,13 +84,13 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | |||
84 | static void iwl1000_nic_config(struct iwl_priv *priv) | 84 | static void iwl1000_nic_config(struct iwl_priv *priv) |
85 | { | 85 | { |
86 | /* set CSR_HW_CONFIG_REG for uCode use */ | 86 | /* set CSR_HW_CONFIG_REG for uCode use */ |
87 | iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, | 87 | iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, |
88 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | 88 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | |
89 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | 89 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); |
90 | 90 | ||
91 | /* Setting digital SVR for 1000 card to 1.32V */ | 91 | /* Setting digital SVR for 1000 card to 1.32V */ |
92 | /* locking is acquired in iwl_set_bits_mask_prph() function */ | 92 | /* locking is acquired in iwl_set_bits_mask_prph() function */ |
93 | iwl_set_bits_mask_prph(bus(priv), APMG_DIGITAL_SVR_REG, | 93 | iwl_set_bits_mask_prph(trans(priv), APMG_DIGITAL_SVR_REG, |
94 | APMG_SVR_DIGITAL_VOLTAGE_1_32, | 94 | APMG_SVR_DIGITAL_VOLTAGE_1_32, |
95 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); | 95 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); |
96 | } | 96 | } |
@@ -128,8 +128,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
128 | iwlagn_mod_params.num_of_queues; | 128 | iwlagn_mod_params.num_of_queues; |
129 | 129 | ||
130 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; | 130 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; |
131 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; | ||
132 | |||
133 | hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; | 131 | hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; |
134 | hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; | 132 | hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; |
135 | 133 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 00db092d8cd0..d4f5f3b87578 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -87,7 +87,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv) | |||
87 | iwl_rf_config(priv); | 87 | iwl_rf_config(priv); |
88 | 88 | ||
89 | if (cfg(priv)->iq_invert) | 89 | if (cfg(priv)->iq_invert) |
90 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, | 90 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, |
91 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); | 91 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); |
92 | } | 92 | } |
93 | 93 | ||
@@ -124,8 +124,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) | |||
124 | iwlagn_mod_params.num_of_queues; | 124 | iwlagn_mod_params.num_of_queues; |
125 | 125 | ||
126 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; | 126 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; |
127 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; | ||
128 | |||
129 | hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; | 127 | hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; |
130 | hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; | 128 | hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; |
131 | 129 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 47fd98b3652c..dc9317d0343e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -73,7 +73,7 @@ static void iwl5000_nic_config(struct iwl_priv *priv) | |||
73 | * (PCIe power is lost before PERST# is asserted), | 73 | * (PCIe power is lost before PERST# is asserted), |
74 | * causing ME FW to lose ownership and not being able to obtain it back. | 74 | * causing ME FW to lose ownership and not being able to obtain it back. |
75 | */ | 75 | */ |
76 | iwl_set_bits_mask_prph(bus(priv), APMG_PS_CTRL_REG, | 76 | iwl_set_bits_mask_prph(trans(priv), APMG_PS_CTRL_REG, |
77 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, | 77 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, |
78 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); | 78 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); |
79 | 79 | ||
@@ -170,8 +170,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
170 | iwlagn_mod_params.num_of_queues; | 170 | iwlagn_mod_params.num_of_queues; |
171 | 171 | ||
172 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; | 172 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; |
173 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; | ||
174 | |||
175 | hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; | 173 | hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; |
176 | hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; | 174 | hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; |
177 | 175 | ||
@@ -199,8 +197,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) | |||
199 | iwlagn_mod_params.num_of_queues; | 197 | iwlagn_mod_params.num_of_queues; |
200 | 198 | ||
201 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; | 199 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; |
202 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; | ||
203 | |||
204 | hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; | 200 | hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; |
205 | hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; | 201 | hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; |
206 | 202 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index ab62c018fcdb..c36fb858a45b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -82,7 +82,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv) | |||
82 | { | 82 | { |
83 | /* Indicate calibration version to uCode. */ | 83 | /* Indicate calibration version to uCode. */ |
84 | if (iwl_eeprom_calib_version(priv->shrd) >= 6) | 84 | if (iwl_eeprom_calib_version(priv->shrd) >= 6) |
85 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, | 85 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, |
86 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 86 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
87 | } | 87 | } |
88 | 88 | ||
@@ -90,9 +90,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv) | |||
90 | { | 90 | { |
91 | /* Indicate calibration version to uCode. */ | 91 | /* Indicate calibration version to uCode. */ |
92 | if (iwl_eeprom_calib_version(priv->shrd) >= 6) | 92 | if (iwl_eeprom_calib_version(priv->shrd) >= 6) |
93 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, | 93 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, |
94 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 94 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
95 | iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, | 95 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, |
96 | CSR_GP_DRIVER_REG_BIT_6050_1x2); | 96 | CSR_GP_DRIVER_REG_BIT_6050_1x2); |
97 | } | 97 | } |
98 | 98 | ||
@@ -104,7 +104,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | |||
104 | /* no locking required for register write */ | 104 | /* no locking required for register write */ |
105 | if (cfg(priv)->pa_type == IWL_PA_INTERNAL) { | 105 | if (cfg(priv)->pa_type == IWL_PA_INTERNAL) { |
106 | /* 2x2 IPA phy type */ | 106 | /* 2x2 IPA phy type */ |
107 | iwl_write32(bus(priv), CSR_GP_DRIVER_REG, | 107 | iwl_write32(trans(priv), CSR_GP_DRIVER_REG, |
108 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); | 108 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); |
109 | } | 109 | } |
110 | /* do additional nic configuration if needed */ | 110 | /* do additional nic configuration if needed */ |
@@ -145,8 +145,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
145 | iwlagn_mod_params.num_of_queues; | 145 | iwlagn_mod_params.num_of_queues; |
146 | 146 | ||
147 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; | 147 | hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; |
148 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; | ||
149 | |||
150 | hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; | 148 | hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; |
151 | hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; | 149 | hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; |
152 | 150 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index f127f913e5a6..a14ddab783ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -628,16 +628,16 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv, | |||
628 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | | 628 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | |
629 | CT_CARD_DISABLED)) { | 629 | CT_CARD_DISABLED)) { |
630 | 630 | ||
631 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, | 631 | iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET, |
632 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | 632 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); |
633 | 633 | ||
634 | iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, | 634 | iwl_write_direct32(trans(priv), HBUS_TARG_MBX_C, |
635 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | 635 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); |
636 | 636 | ||
637 | if (!(flags & RXON_CARD_DISABLED)) { | 637 | if (!(flags & RXON_CARD_DISABLED)) { |
638 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, | 638 | iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, |
639 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | 639 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); |
640 | iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, | 640 | iwl_write_direct32(trans(priv), HBUS_TARG_MBX_C, |
641 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | 641 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); |
642 | } | 642 | } |
643 | if (flags & CT_CARD_DISABLED) | 643 | if (flags & CT_CARD_DISABLED) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 56c6def015a4..c728ed75584e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c | |||
@@ -178,19 +178,19 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) | |||
178 | 178 | ||
179 | if (tt->state == IWL_TI_CT_KILL) { | 179 | if (tt->state == IWL_TI_CT_KILL) { |
180 | if (priv->thermal_throttle.ct_kill_toggle) { | 180 | if (priv->thermal_throttle.ct_kill_toggle) { |
181 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, | 181 | iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, |
182 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | 182 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); |
183 | priv->thermal_throttle.ct_kill_toggle = false; | 183 | priv->thermal_throttle.ct_kill_toggle = false; |
184 | } else { | 184 | } else { |
185 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, | 185 | iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET, |
186 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | 186 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); |
187 | priv->thermal_throttle.ct_kill_toggle = true; | 187 | priv->thermal_throttle.ct_kill_toggle = true; |
188 | } | 188 | } |
189 | iwl_read32(bus(priv), CSR_UCODE_DRV_GP1); | 189 | iwl_read32(trans(priv), CSR_UCODE_DRV_GP1); |
190 | spin_lock_irqsave(&bus(priv)->reg_lock, flags); | 190 | spin_lock_irqsave(&trans(priv)->reg_lock, flags); |
191 | if (!iwl_grab_nic_access(bus(priv))) | 191 | if (!iwl_grab_nic_access(trans(priv))) |
192 | iwl_release_nic_access(bus(priv)); | 192 | iwl_release_nic_access(trans(priv)); |
193 | spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); | 193 | spin_unlock_irqrestore(&trans(priv)->reg_lock, flags); |
194 | 194 | ||
195 | /* Reschedule the ct_kill timer to occur in | 195 | /* Reschedule the ct_kill timer to occur in |
196 | * CT_KILL_EXIT_DURATION seconds to ensure we get a | 196 | * CT_KILL_EXIT_DURATION seconds to ensure we get a |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 90315c69cdf6..8837171ad553 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
35 | #include <linux/skbuff.h> | 35 | #include <linux/skbuff.h> |
36 | #include <linux/netdevice.h> | 36 | #include <linux/netdevice.h> |
37 | #include <linux/firmware.h> | ||
38 | #include <linux/etherdevice.h> | 37 | #include <linux/etherdevice.h> |
39 | #include <linux/if_arp.h> | 38 | #include <linux/if_arp.h> |
40 | 39 | ||
@@ -42,6 +41,7 @@ | |||
42 | 41 | ||
43 | #include <asm/div64.h> | 42 | #include <asm/div64.h> |
44 | 43 | ||
44 | #include "iwl-ucode.h" | ||
45 | #include "iwl-eeprom.h" | 45 | #include "iwl-eeprom.h" |
46 | #include "iwl-wifi.h" | 46 | #include "iwl-wifi.h" |
47 | #include "iwl-dev.h" | 47 | #include "iwl-dev.h" |
@@ -328,14 +328,14 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, | |||
328 | ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); | 328 | ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); |
329 | 329 | ||
330 | /* Make sure device is powered up for SRAM reads */ | 330 | /* Make sure device is powered up for SRAM reads */ |
331 | spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags); | 331 | spin_lock_irqsave(&trans(priv)->reg_lock, reg_flags); |
332 | if (iwl_grab_nic_access(bus(priv))) { | 332 | if (iwl_grab_nic_access(trans(priv))) { |
333 | spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); | 333 | spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags); |
334 | return; | 334 | return; |
335 | } | 335 | } |
336 | 336 | ||
337 | /* Set starting address; reads will auto-increment */ | 337 | /* Set starting address; reads will auto-increment */ |
338 | iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr); | 338 | iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr); |
339 | rmb(); | 339 | rmb(); |
340 | 340 | ||
341 | /* | 341 | /* |
@@ -352,19 +352,19 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, | |||
352 | * place event id # at far right for easier visual parsing. | 352 | * place event id # at far right for easier visual parsing. |
353 | */ | 353 | */ |
354 | for (i = 0; i < num_events; i++) { | 354 | for (i = 0; i < num_events; i++) { |
355 | ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); | 355 | ev = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); |
356 | time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); | 356 | time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); |
357 | if (mode == 0) { | 357 | if (mode == 0) { |
358 | trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); | 358 | trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); |
359 | } else { | 359 | } else { |
360 | data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); | 360 | data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); |
361 | trace_iwlwifi_dev_ucode_cont_event(priv, time, | 361 | trace_iwlwifi_dev_ucode_cont_event(priv, time, |
362 | data, ev); | 362 | data, ev); |
363 | } | 363 | } |
364 | } | 364 | } |
365 | /* Allow device to power down */ | 365 | /* Allow device to power down */ |
366 | iwl_release_nic_access(bus(priv)); | 366 | iwl_release_nic_access(trans(priv)); |
367 | spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); | 367 | spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags); |
368 | } | 368 | } |
369 | 369 | ||
370 | static void iwl_continuous_event_trace(struct iwl_priv *priv) | 370 | static void iwl_continuous_event_trace(struct iwl_priv *priv) |
@@ -383,7 +383,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) | |||
383 | 383 | ||
384 | base = priv->shrd->device_pointers.log_event_table; | 384 | base = priv->shrd->device_pointers.log_event_table; |
385 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 385 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
386 | iwl_read_targ_mem_words(bus(priv), base, &read, sizeof(read)); | 386 | iwl_read_targ_mem_words(trans(priv), base, &read, sizeof(read)); |
387 | 387 | ||
388 | capacity = read.capacity; | 388 | capacity = read.capacity; |
389 | mode = read.mode; | 389 | mode = read.mode; |
@@ -490,7 +490,7 @@ static void iwl_bg_tx_flush(struct work_struct *work) | |||
490 | iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); | 490 | iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); |
491 | } | 491 | } |
492 | 492 | ||
493 | static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | 493 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) |
494 | { | 494 | { |
495 | int i; | 495 | int i; |
496 | 496 | ||
@@ -513,6 +513,7 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
513 | priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; | 513 | priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; |
514 | priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; | 514 | priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; |
515 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; | 515 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; |
516 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; | ||
516 | priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = | 517 | priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = |
517 | BIT(NL80211_IFTYPE_ADHOC); | 518 | BIT(NL80211_IFTYPE_ADHOC); |
518 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = | 519 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = |
@@ -547,609 +548,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
547 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 548 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); |
548 | } | 549 | } |
549 | 550 | ||
550 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | ||
551 | |||
552 | #define UCODE_EXPERIMENTAL_INDEX 100 | ||
553 | #define UCODE_EXPERIMENTAL_TAG "exp" | ||
554 | |||
555 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | ||
556 | { | ||
557 | const char *name_pre = cfg(priv)->fw_name_pre; | ||
558 | char tag[8]; | ||
559 | |||
560 | if (first) { | ||
561 | #ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | ||
562 | priv->fw_index = UCODE_EXPERIMENTAL_INDEX; | ||
563 | strcpy(tag, UCODE_EXPERIMENTAL_TAG); | ||
564 | } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) { | ||
565 | #endif | ||
566 | priv->fw_index = cfg(priv)->ucode_api_max; | ||
567 | sprintf(tag, "%d", priv->fw_index); | ||
568 | } else { | ||
569 | priv->fw_index--; | ||
570 | sprintf(tag, "%d", priv->fw_index); | ||
571 | } | ||
572 | |||
573 | if (priv->fw_index < cfg(priv)->ucode_api_min) { | ||
574 | IWL_ERR(priv, "no suitable firmware found!\n"); | ||
575 | return -ENOENT; | ||
576 | } | ||
577 | |||
578 | sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); | ||
579 | |||
580 | IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n", | ||
581 | (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) | ||
582 | ? "EXPERIMENTAL " : "", | ||
583 | priv->firmware_name); | ||
584 | |||
585 | return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, | ||
586 | bus(priv)->dev, | ||
587 | GFP_KERNEL, priv, iwl_ucode_callback); | ||
588 | } | ||
589 | |||
590 | struct iwlagn_firmware_pieces { | ||
591 | const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data; | ||
592 | size_t inst_size, data_size, init_size, init_data_size, | ||
593 | wowlan_inst_size, wowlan_data_size; | ||
594 | |||
595 | u32 build; | ||
596 | |||
597 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | ||
598 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | ||
599 | }; | ||
600 | |||
601 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, | ||
602 | const struct firmware *ucode_raw, | ||
603 | struct iwlagn_firmware_pieces *pieces) | ||
604 | { | ||
605 | struct iwl_ucode_header *ucode = (void *)ucode_raw->data; | ||
606 | u32 api_ver, hdr_size; | ||
607 | const u8 *src; | ||
608 | |||
609 | priv->ucode_ver = le32_to_cpu(ucode->ver); | ||
610 | api_ver = IWL_UCODE_API(priv->ucode_ver); | ||
611 | |||
612 | switch (api_ver) { | ||
613 | default: | ||
614 | hdr_size = 28; | ||
615 | if (ucode_raw->size < hdr_size) { | ||
616 | IWL_ERR(priv, "File size too small!\n"); | ||
617 | return -EINVAL; | ||
618 | } | ||
619 | pieces->build = le32_to_cpu(ucode->u.v2.build); | ||
620 | pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); | ||
621 | pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); | ||
622 | pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); | ||
623 | pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); | ||
624 | src = ucode->u.v2.data; | ||
625 | break; | ||
626 | case 0: | ||
627 | case 1: | ||
628 | case 2: | ||
629 | hdr_size = 24; | ||
630 | if (ucode_raw->size < hdr_size) { | ||
631 | IWL_ERR(priv, "File size too small!\n"); | ||
632 | return -EINVAL; | ||
633 | } | ||
634 | pieces->build = 0; | ||
635 | pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size); | ||
636 | pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); | ||
637 | pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); | ||
638 | pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); | ||
639 | src = ucode->u.v1.data; | ||
640 | break; | ||
641 | } | ||
642 | |||
643 | /* Verify size of file vs. image size info in file's header */ | ||
644 | if (ucode_raw->size != hdr_size + pieces->inst_size + | ||
645 | pieces->data_size + pieces->init_size + | ||
646 | pieces->init_data_size) { | ||
647 | |||
648 | IWL_ERR(priv, | ||
649 | "uCode file size %d does not match expected size\n", | ||
650 | (int)ucode_raw->size); | ||
651 | return -EINVAL; | ||
652 | } | ||
653 | |||
654 | pieces->inst = src; | ||
655 | src += pieces->inst_size; | ||
656 | pieces->data = src; | ||
657 | src += pieces->data_size; | ||
658 | pieces->init = src; | ||
659 | src += pieces->init_size; | ||
660 | pieces->init_data = src; | ||
661 | src += pieces->init_data_size; | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static int iwlagn_load_firmware(struct iwl_priv *priv, | ||
667 | const struct firmware *ucode_raw, | ||
668 | struct iwlagn_firmware_pieces *pieces, | ||
669 | struct iwlagn_ucode_capabilities *capa) | ||
670 | { | ||
671 | struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data; | ||
672 | struct iwl_ucode_tlv *tlv; | ||
673 | size_t len = ucode_raw->size; | ||
674 | const u8 *data; | ||
675 | int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; | ||
676 | int tmp; | ||
677 | u64 alternatives; | ||
678 | u32 tlv_len; | ||
679 | enum iwl_ucode_tlv_type tlv_type; | ||
680 | const u8 *tlv_data; | ||
681 | |||
682 | if (len < sizeof(*ucode)) { | ||
683 | IWL_ERR(priv, "uCode has invalid length: %zd\n", len); | ||
684 | return -EINVAL; | ||
685 | } | ||
686 | |||
687 | if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) { | ||
688 | IWL_ERR(priv, "invalid uCode magic: 0X%x\n", | ||
689 | le32_to_cpu(ucode->magic)); | ||
690 | return -EINVAL; | ||
691 | } | ||
692 | |||
693 | /* | ||
694 | * Check which alternatives are present, and "downgrade" | ||
695 | * when the chosen alternative is not present, warning | ||
696 | * the user when that happens. Some files may not have | ||
697 | * any alternatives, so don't warn in that case. | ||
698 | */ | ||
699 | alternatives = le64_to_cpu(ucode->alternatives); | ||
700 | tmp = wanted_alternative; | ||
701 | if (wanted_alternative > 63) | ||
702 | wanted_alternative = 63; | ||
703 | while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) | ||
704 | wanted_alternative--; | ||
705 | if (wanted_alternative && wanted_alternative != tmp) | ||
706 | IWL_WARN(priv, | ||
707 | "uCode alternative %d not available, choosing %d\n", | ||
708 | tmp, wanted_alternative); | ||
709 | |||
710 | priv->ucode_ver = le32_to_cpu(ucode->ver); | ||
711 | pieces->build = le32_to_cpu(ucode->build); | ||
712 | data = ucode->data; | ||
713 | |||
714 | len -= sizeof(*ucode); | ||
715 | |||
716 | while (len >= sizeof(*tlv)) { | ||
717 | u16 tlv_alt; | ||
718 | |||
719 | len -= sizeof(*tlv); | ||
720 | tlv = (void *)data; | ||
721 | |||
722 | tlv_len = le32_to_cpu(tlv->length); | ||
723 | tlv_type = le16_to_cpu(tlv->type); | ||
724 | tlv_alt = le16_to_cpu(tlv->alternative); | ||
725 | tlv_data = tlv->data; | ||
726 | |||
727 | if (len < tlv_len) { | ||
728 | IWL_ERR(priv, "invalid TLV len: %zd/%u\n", | ||
729 | len, tlv_len); | ||
730 | return -EINVAL; | ||
731 | } | ||
732 | len -= ALIGN(tlv_len, 4); | ||
733 | data += sizeof(*tlv) + ALIGN(tlv_len, 4); | ||
734 | |||
735 | /* | ||
736 | * Alternative 0 is always valid. | ||
737 | * | ||
738 | * Skip alternative TLVs that are not selected. | ||
739 | */ | ||
740 | if (tlv_alt != 0 && tlv_alt != wanted_alternative) | ||
741 | continue; | ||
742 | |||
743 | switch (tlv_type) { | ||
744 | case IWL_UCODE_TLV_INST: | ||
745 | pieces->inst = tlv_data; | ||
746 | pieces->inst_size = tlv_len; | ||
747 | break; | ||
748 | case IWL_UCODE_TLV_DATA: | ||
749 | pieces->data = tlv_data; | ||
750 | pieces->data_size = tlv_len; | ||
751 | break; | ||
752 | case IWL_UCODE_TLV_INIT: | ||
753 | pieces->init = tlv_data; | ||
754 | pieces->init_size = tlv_len; | ||
755 | break; | ||
756 | case IWL_UCODE_TLV_INIT_DATA: | ||
757 | pieces->init_data = tlv_data; | ||
758 | pieces->init_data_size = tlv_len; | ||
759 | break; | ||
760 | case IWL_UCODE_TLV_BOOT: | ||
761 | IWL_ERR(priv, "Found unexpected BOOT ucode\n"); | ||
762 | break; | ||
763 | case IWL_UCODE_TLV_PROBE_MAX_LEN: | ||
764 | if (tlv_len != sizeof(u32)) | ||
765 | goto invalid_tlv_len; | ||
766 | capa->max_probe_length = | ||
767 | le32_to_cpup((__le32 *)tlv_data); | ||
768 | break; | ||
769 | case IWL_UCODE_TLV_PAN: | ||
770 | if (tlv_len) | ||
771 | goto invalid_tlv_len; | ||
772 | capa->flags |= IWL_UCODE_TLV_FLAGS_PAN; | ||
773 | break; | ||
774 | case IWL_UCODE_TLV_FLAGS: | ||
775 | /* must be at least one u32 */ | ||
776 | if (tlv_len < sizeof(u32)) | ||
777 | goto invalid_tlv_len; | ||
778 | /* and a proper number of u32s */ | ||
779 | if (tlv_len % sizeof(u32)) | ||
780 | goto invalid_tlv_len; | ||
781 | /* | ||
782 | * This driver only reads the first u32 as | ||
783 | * right now no more features are defined, | ||
784 | * if that changes then either the driver | ||
785 | * will not work with the new firmware, or | ||
786 | * it'll not take advantage of new features. | ||
787 | */ | ||
788 | capa->flags = le32_to_cpup((__le32 *)tlv_data); | ||
789 | break; | ||
790 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: | ||
791 | if (tlv_len != sizeof(u32)) | ||
792 | goto invalid_tlv_len; | ||
793 | pieces->init_evtlog_ptr = | ||
794 | le32_to_cpup((__le32 *)tlv_data); | ||
795 | break; | ||
796 | case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: | ||
797 | if (tlv_len != sizeof(u32)) | ||
798 | goto invalid_tlv_len; | ||
799 | pieces->init_evtlog_size = | ||
800 | le32_to_cpup((__le32 *)tlv_data); | ||
801 | break; | ||
802 | case IWL_UCODE_TLV_INIT_ERRLOG_PTR: | ||
803 | if (tlv_len != sizeof(u32)) | ||
804 | goto invalid_tlv_len; | ||
805 | pieces->init_errlog_ptr = | ||
806 | le32_to_cpup((__le32 *)tlv_data); | ||
807 | break; | ||
808 | case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: | ||
809 | if (tlv_len != sizeof(u32)) | ||
810 | goto invalid_tlv_len; | ||
811 | pieces->inst_evtlog_ptr = | ||
812 | le32_to_cpup((__le32 *)tlv_data); | ||
813 | break; | ||
814 | case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: | ||
815 | if (tlv_len != sizeof(u32)) | ||
816 | goto invalid_tlv_len; | ||
817 | pieces->inst_evtlog_size = | ||
818 | le32_to_cpup((__le32 *)tlv_data); | ||
819 | break; | ||
820 | case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: | ||
821 | if (tlv_len != sizeof(u32)) | ||
822 | goto invalid_tlv_len; | ||
823 | pieces->inst_errlog_ptr = | ||
824 | le32_to_cpup((__le32 *)tlv_data); | ||
825 | break; | ||
826 | case IWL_UCODE_TLV_ENHANCE_SENS_TBL: | ||
827 | if (tlv_len) | ||
828 | goto invalid_tlv_len; | ||
829 | priv->enhance_sensitivity_table = true; | ||
830 | break; | ||
831 | case IWL_UCODE_TLV_WOWLAN_INST: | ||
832 | pieces->wowlan_inst = tlv_data; | ||
833 | pieces->wowlan_inst_size = tlv_len; | ||
834 | break; | ||
835 | case IWL_UCODE_TLV_WOWLAN_DATA: | ||
836 | pieces->wowlan_data = tlv_data; | ||
837 | pieces->wowlan_data_size = tlv_len; | ||
838 | break; | ||
839 | case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: | ||
840 | if (tlv_len != sizeof(u32)) | ||
841 | goto invalid_tlv_len; | ||
842 | capa->standard_phy_calibration_size = | ||
843 | le32_to_cpup((__le32 *)tlv_data); | ||
844 | break; | ||
845 | default: | ||
846 | IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type); | ||
847 | break; | ||
848 | } | ||
849 | } | ||
850 | |||
851 | if (len) { | ||
852 | IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len); | ||
853 | iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len); | ||
854 | return -EINVAL; | ||
855 | } | ||
856 | |||
857 | return 0; | ||
858 | |||
859 | invalid_tlv_len: | ||
860 | IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); | ||
861 | iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len); | ||
862 | |||
863 | return -EINVAL; | ||
864 | } | ||
865 | |||
866 | /** | ||
867 | * iwl_ucode_callback - callback when firmware was loaded | ||
868 | * | ||
869 | * If loaded successfully, copies the firmware into buffers | ||
870 | * for the card to fetch (via DMA). | ||
871 | */ | ||
872 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | ||
873 | { | ||
874 | struct iwl_priv *priv = context; | ||
875 | struct iwl_ucode_header *ucode; | ||
876 | int err; | ||
877 | struct iwlagn_firmware_pieces pieces; | ||
878 | const unsigned int api_max = cfg(priv)->ucode_api_max; | ||
879 | unsigned int api_ok = cfg(priv)->ucode_api_ok; | ||
880 | const unsigned int api_min = cfg(priv)->ucode_api_min; | ||
881 | u32 api_ver; | ||
882 | char buildstr[25]; | ||
883 | u32 build; | ||
884 | struct iwlagn_ucode_capabilities ucode_capa = { | ||
885 | .max_probe_length = 200, | ||
886 | .standard_phy_calibration_size = | ||
887 | IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE, | ||
888 | }; | ||
889 | |||
890 | if (!api_ok) | ||
891 | api_ok = api_max; | ||
892 | |||
893 | memset(&pieces, 0, sizeof(pieces)); | ||
894 | |||
895 | if (!ucode_raw) { | ||
896 | if (priv->fw_index <= api_ok) | ||
897 | IWL_ERR(priv, | ||
898 | "request for firmware file '%s' failed.\n", | ||
899 | priv->firmware_name); | ||
900 | goto try_again; | ||
901 | } | ||
902 | |||
903 | IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", | ||
904 | priv->firmware_name, ucode_raw->size); | ||
905 | |||
906 | /* Make sure that we got at least the API version number */ | ||
907 | if (ucode_raw->size < 4) { | ||
908 | IWL_ERR(priv, "File size way too small!\n"); | ||
909 | goto try_again; | ||
910 | } | ||
911 | |||
912 | /* Data from ucode file: header followed by uCode images */ | ||
913 | ucode = (struct iwl_ucode_header *)ucode_raw->data; | ||
914 | |||
915 | if (ucode->ver) | ||
916 | err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces); | ||
917 | else | ||
918 | err = iwlagn_load_firmware(priv, ucode_raw, &pieces, | ||
919 | &ucode_capa); | ||
920 | |||
921 | if (err) | ||
922 | goto try_again; | ||
923 | |||
924 | api_ver = IWL_UCODE_API(priv->ucode_ver); | ||
925 | build = pieces.build; | ||
926 | |||
927 | /* | ||
928 | * api_ver should match the api version forming part of the | ||
929 | * firmware filename ... but we don't check for that and only rely | ||
930 | * on the API version read from firmware header from here on forward | ||
931 | */ | ||
932 | /* no api version check required for experimental uCode */ | ||
933 | if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) { | ||
934 | if (api_ver < api_min || api_ver > api_max) { | ||
935 | IWL_ERR(priv, | ||
936 | "Driver unable to support your firmware API. " | ||
937 | "Driver supports v%u, firmware is v%u.\n", | ||
938 | api_max, api_ver); | ||
939 | goto try_again; | ||
940 | } | ||
941 | |||
942 | if (api_ver < api_ok) { | ||
943 | if (api_ok != api_max) | ||
944 | IWL_ERR(priv, "Firmware has old API version, " | ||
945 | "expected v%u through v%u, got v%u.\n", | ||
946 | api_ok, api_max, api_ver); | ||
947 | else | ||
948 | IWL_ERR(priv, "Firmware has old API version, " | ||
949 | "expected v%u, got v%u.\n", | ||
950 | api_max, api_ver); | ||
951 | IWL_ERR(priv, "New firmware can be obtained from " | ||
952 | "http://www.intellinuxwireless.org/.\n"); | ||
953 | } | ||
954 | } | ||
955 | |||
956 | if (build) | ||
957 | sprintf(buildstr, " build %u%s", build, | ||
958 | (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) | ||
959 | ? " (EXP)" : ""); | ||
960 | else | ||
961 | buildstr[0] = '\0'; | ||
962 | |||
963 | IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n", | ||
964 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
965 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
966 | IWL_UCODE_API(priv->ucode_ver), | ||
967 | IWL_UCODE_SERIAL(priv->ucode_ver), | ||
968 | buildstr); | ||
969 | |||
970 | snprintf(priv->hw->wiphy->fw_version, | ||
971 | sizeof(priv->hw->wiphy->fw_version), | ||
972 | "%u.%u.%u.%u%s", | ||
973 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
974 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
975 | IWL_UCODE_API(priv->ucode_ver), | ||
976 | IWL_UCODE_SERIAL(priv->ucode_ver), | ||
977 | buildstr); | ||
978 | |||
979 | /* | ||
980 | * For any of the failures below (before allocating pci memory) | ||
981 | * we will try to load a version with a smaller API -- maybe the | ||
982 | * user just got a corrupted version of the latest API. | ||
983 | */ | ||
984 | |||
985 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", | ||
986 | priv->ucode_ver); | ||
987 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n", | ||
988 | pieces.inst_size); | ||
989 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n", | ||
990 | pieces.data_size); | ||
991 | IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n", | ||
992 | pieces.init_size); | ||
993 | IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", | ||
994 | pieces.init_data_size); | ||
995 | |||
996 | /* Verify that uCode images will fit in card's SRAM */ | ||
997 | if (pieces.inst_size > hw_params(priv).max_inst_size) { | ||
998 | IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", | ||
999 | pieces.inst_size); | ||
1000 | goto try_again; | ||
1001 | } | ||
1002 | |||
1003 | if (pieces.data_size > hw_params(priv).max_data_size) { | ||
1004 | IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", | ||
1005 | pieces.data_size); | ||
1006 | goto try_again; | ||
1007 | } | ||
1008 | |||
1009 | if (pieces.init_size > hw_params(priv).max_inst_size) { | ||
1010 | IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", | ||
1011 | pieces.init_size); | ||
1012 | goto try_again; | ||
1013 | } | ||
1014 | |||
1015 | if (pieces.init_data_size > hw_params(priv).max_data_size) { | ||
1016 | IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", | ||
1017 | pieces.init_data_size); | ||
1018 | goto try_again; | ||
1019 | } | ||
1020 | |||
1021 | /* Allocate ucode buffers for card's bus-master loading ... */ | ||
1022 | |||
1023 | /* Runtime instructions and 2 copies of data: | ||
1024 | * 1) unmodified from disk | ||
1025 | * 2) backup cache for save/restore during power-downs */ | ||
1026 | if (iwl_alloc_fw_desc(bus(priv), &trans(priv)->ucode_rt.code, | ||
1027 | pieces.inst, pieces.inst_size)) | ||
1028 | goto err_pci_alloc; | ||
1029 | if (iwl_alloc_fw_desc(bus(priv), &trans(priv)->ucode_rt.data, | ||
1030 | pieces.data, pieces.data_size)) | ||
1031 | goto err_pci_alloc; | ||
1032 | |||
1033 | /* Initialization instructions and data */ | ||
1034 | if (pieces.init_size && pieces.init_data_size) { | ||
1035 | if (iwl_alloc_fw_desc(bus(priv), &trans(priv)->ucode_init.code, | ||
1036 | pieces.init, pieces.init_size)) | ||
1037 | goto err_pci_alloc; | ||
1038 | if (iwl_alloc_fw_desc(bus(priv), &trans(priv)->ucode_init.data, | ||
1039 | pieces.init_data, pieces.init_data_size)) | ||
1040 | goto err_pci_alloc; | ||
1041 | } | ||
1042 | |||
1043 | /* WoWLAN instructions and data */ | ||
1044 | if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { | ||
1045 | if (iwl_alloc_fw_desc(bus(priv), | ||
1046 | &trans(priv)->ucode_wowlan.code, | ||
1047 | pieces.wowlan_inst, | ||
1048 | pieces.wowlan_inst_size)) | ||
1049 | goto err_pci_alloc; | ||
1050 | if (iwl_alloc_fw_desc(bus(priv), | ||
1051 | &trans(priv)->ucode_wowlan.data, | ||
1052 | pieces.wowlan_data, | ||
1053 | pieces.wowlan_data_size)) | ||
1054 | goto err_pci_alloc; | ||
1055 | } | ||
1056 | |||
1057 | /* Now that we can no longer fail, copy information */ | ||
1058 | |||
1059 | /* | ||
1060 | * The (size - 16) / 12 formula is based on the information recorded | ||
1061 | * for each event, which is of mode 1 (including timestamp) for all | ||
1062 | * new microcodes that include this information. | ||
1063 | */ | ||
1064 | priv->init_evtlog_ptr = pieces.init_evtlog_ptr; | ||
1065 | if (pieces.init_evtlog_size) | ||
1066 | priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; | ||
1067 | else | ||
1068 | priv->init_evtlog_size = | ||
1069 | cfg(priv)->base_params->max_event_log_size; | ||
1070 | priv->init_errlog_ptr = pieces.init_errlog_ptr; | ||
1071 | priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr; | ||
1072 | if (pieces.inst_evtlog_size) | ||
1073 | priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; | ||
1074 | else | ||
1075 | priv->inst_evtlog_size = | ||
1076 | cfg(priv)->base_params->max_event_log_size; | ||
1077 | priv->inst_errlog_ptr = pieces.inst_errlog_ptr; | ||
1078 | #ifndef CONFIG_IWLWIFI_P2P | ||
1079 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | ||
1080 | #endif | ||
1081 | |||
1082 | priv->new_scan_threshold_behaviour = | ||
1083 | !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); | ||
1084 | |||
1085 | if (!(cfg(priv)->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) | ||
1086 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | ||
1087 | |||
1088 | /* | ||
1089 | * if not PAN, then don't support P2P -- might be a uCode | ||
1090 | * packaging bug or due to the eeprom check above | ||
1091 | */ | ||
1092 | if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) | ||
1093 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P; | ||
1094 | |||
1095 | if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { | ||
1096 | priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; | ||
1097 | priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; | ||
1098 | } else { | ||
1099 | priv->sta_key_max_num = STA_KEY_MAX_NUM; | ||
1100 | priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; | ||
1101 | } | ||
1102 | /* | ||
1103 | * figure out the offset of chain noise reset and gain commands | ||
1104 | * base on the size of standard phy calibration commands table size | ||
1105 | */ | ||
1106 | if (ucode_capa.standard_phy_calibration_size > | ||
1107 | IWL_MAX_PHY_CALIBRATE_TBL_SIZE) | ||
1108 | ucode_capa.standard_phy_calibration_size = | ||
1109 | IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; | ||
1110 | |||
1111 | priv->phy_calib_chain_noise_reset_cmd = | ||
1112 | ucode_capa.standard_phy_calibration_size; | ||
1113 | priv->phy_calib_chain_noise_gain_cmd = | ||
1114 | ucode_capa.standard_phy_calibration_size + 1; | ||
1115 | |||
1116 | /* initialize all valid contexts */ | ||
1117 | iwl_init_context(priv, ucode_capa.flags); | ||
1118 | |||
1119 | /************************************************** | ||
1120 | * This is still part of probe() in a sense... | ||
1121 | * | ||
1122 | * 9. Setup and register with mac80211 and debugfs | ||
1123 | **************************************************/ | ||
1124 | err = iwlagn_mac_setup_register(priv, &ucode_capa); | ||
1125 | if (err) | ||
1126 | goto out_unbind; | ||
1127 | |||
1128 | err = iwl_dbgfs_register(priv, DRV_NAME); | ||
1129 | if (err) | ||
1130 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | ||
1131 | |||
1132 | /* We have our copies now, allow OS release its copies */ | ||
1133 | release_firmware(ucode_raw); | ||
1134 | complete(&priv->firmware_loading_complete); | ||
1135 | return; | ||
1136 | |||
1137 | try_again: | ||
1138 | /* try next, if any */ | ||
1139 | if (iwl_request_firmware(priv, false)) | ||
1140 | goto out_unbind; | ||
1141 | release_firmware(ucode_raw); | ||
1142 | return; | ||
1143 | |||
1144 | err_pci_alloc: | ||
1145 | IWL_ERR(priv, "failed to allocate pci memory\n"); | ||
1146 | iwl_dealloc_ucode(trans(priv)); | ||
1147 | out_unbind: | ||
1148 | complete(&priv->firmware_loading_complete); | ||
1149 | device_release_driver(bus(priv)->dev); | ||
1150 | release_firmware(ucode_raw); | ||
1151 | } | ||
1152 | |||
1153 | static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | 551 | static void iwl_rf_kill_ct_config(struct iwl_priv *priv) |
1154 | { | 552 | { |
1155 | struct iwl_ct_kill_config cmd; | 553 | struct iwl_ct_kill_config cmd; |
@@ -1158,7 +556,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
1158 | int ret = 0; | 556 | int ret = 0; |
1159 | 557 | ||
1160 | spin_lock_irqsave(&priv->shrd->lock, flags); | 558 | spin_lock_irqsave(&priv->shrd->lock, flags); |
1161 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, | 559 | iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, |
1162 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | 560 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); |
1163 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 561 | spin_unlock_irqrestore(&priv->shrd->lock, flags); |
1164 | priv->thermal_throttle.ct_kill_toggle = false; | 562 | priv->thermal_throttle.ct_kill_toggle = false; |
@@ -1243,9 +641,6 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
1243 | int ret = 0; | 641 | int ret = 0; |
1244 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 642 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
1245 | 643 | ||
1246 | /*TODO: this should go to the transport layer */ | ||
1247 | iwl_reset_ict(trans(priv)); | ||
1248 | |||
1249 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); | 644 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); |
1250 | 645 | ||
1251 | /* After the ALIVE response, we can send host commands to the uCode */ | 646 | /* After the ALIVE response, we can send host commands to the uCode */ |
@@ -1692,13 +1087,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
1692 | #endif | 1087 | #endif |
1693 | } | 1088 | } |
1694 | 1089 | ||
1695 | |||
1696 | |||
1697 | static u32 iwl_hw_detect(struct iwl_priv *priv) | ||
1698 | { | ||
1699 | return iwl_read32(bus(priv), CSR_HW_REV); | ||
1700 | } | ||
1701 | |||
1702 | /* Size of one Rx buffer in host DRAM */ | 1090 | /* Size of one Rx buffer in host DRAM */ |
1703 | #define IWL_RX_BUF_SIZE_4K (4 * 1024) | 1091 | #define IWL_RX_BUF_SIZE_4K (4 * 1024) |
1704 | #define IWL_RX_BUF_SIZE_8K (8 * 1024) | 1092 | #define IWL_RX_BUF_SIZE_8K (8 * 1024) |
@@ -1730,32 +1118,32 @@ static int iwl_set_hw_params(struct iwl_priv *priv) | |||
1730 | 1118 | ||
1731 | static void iwl_debug_config(struct iwl_priv *priv) | 1119 | static void iwl_debug_config(struct iwl_priv *priv) |
1732 | { | 1120 | { |
1733 | dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEBUG " | 1121 | dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEBUG " |
1734 | #ifdef CONFIG_IWLWIFI_DEBUG | 1122 | #ifdef CONFIG_IWLWIFI_DEBUG |
1735 | "enabled\n"); | 1123 | "enabled\n"); |
1736 | #else | 1124 | #else |
1737 | "disabled\n"); | 1125 | "disabled\n"); |
1738 | #endif | 1126 | #endif |
1739 | dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEBUGFS " | 1127 | dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEBUGFS " |
1740 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1128 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1741 | "enabled\n"); | 1129 | "enabled\n"); |
1742 | #else | 1130 | #else |
1743 | "disabled\n"); | 1131 | "disabled\n"); |
1744 | #endif | 1132 | #endif |
1745 | dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TRACING " | 1133 | dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TRACING " |
1746 | #ifdef CONFIG_IWLWIFI_DEVICE_TRACING | 1134 | #ifdef CONFIG_IWLWIFI_DEVICE_TRACING |
1747 | "enabled\n"); | 1135 | "enabled\n"); |
1748 | #else | 1136 | #else |
1749 | "disabled\n"); | 1137 | "disabled\n"); |
1750 | #endif | 1138 | #endif |
1751 | 1139 | ||
1752 | dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE " | 1140 | dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE " |
1753 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE | 1141 | #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE |
1754 | "enabled\n"); | 1142 | "enabled\n"); |
1755 | #else | 1143 | #else |
1756 | "disabled\n"); | 1144 | "disabled\n"); |
1757 | #endif | 1145 | #endif |
1758 | dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_P2P " | 1146 | dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_P2P " |
1759 | #ifdef CONFIG_IWLWIFI_P2P | 1147 | #ifdef CONFIG_IWLWIFI_P2P |
1760 | "enabled\n"); | 1148 | "enabled\n"); |
1761 | #else | 1149 | #else |
@@ -1770,7 +1158,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, | |||
1770 | struct iwl_priv *priv; | 1158 | struct iwl_priv *priv; |
1771 | struct ieee80211_hw *hw; | 1159 | struct ieee80211_hw *hw; |
1772 | u16 num_mac; | 1160 | u16 num_mac; |
1773 | u32 hw_rev; | ||
1774 | 1161 | ||
1775 | /************************ | 1162 | /************************ |
1776 | * 1. Allocating HW data | 1163 | * 1. Allocating HW data |
@@ -1783,22 +1170,14 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, | |||
1783 | } | 1170 | } |
1784 | 1171 | ||
1785 | priv = hw->priv; | 1172 | priv = hw->priv; |
1786 | priv->shrd = &priv->_shrd; | 1173 | priv->shrd = bus->shrd; |
1787 | bus->shrd = priv->shrd; | ||
1788 | priv->shrd->bus = bus; | ||
1789 | priv->shrd->priv = priv; | 1174 | priv->shrd->priv = priv; |
1790 | 1175 | ||
1791 | priv->shrd->trans = trans_ops->alloc(priv->shrd); | ||
1792 | if (priv->shrd->trans == NULL) { | ||
1793 | err = -ENOMEM; | ||
1794 | goto out_free_traffic_mem; | ||
1795 | } | ||
1796 | |||
1797 | /* At this point both hw and priv are allocated. */ | 1176 | /* At this point both hw and priv are allocated. */ |
1798 | 1177 | ||
1799 | SET_IEEE80211_DEV(hw, bus(priv)->dev); | 1178 | SET_IEEE80211_DEV(hw, trans(priv)->dev); |
1800 | 1179 | ||
1801 | /* what debugging capabilities we have */ | 1180 | /* show what debugging capabilities we have */ |
1802 | iwl_debug_config(priv); | 1181 | iwl_debug_config(priv); |
1803 | 1182 | ||
1804 | IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); | 1183 | IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); |
@@ -1821,41 +1200,29 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, | |||
1821 | /* these spin locks will be used in apm_ops.init and EEPROM access | 1200 | /* these spin locks will be used in apm_ops.init and EEPROM access |
1822 | * we should init now | 1201 | * we should init now |
1823 | */ | 1202 | */ |
1824 | spin_lock_init(&bus(priv)->reg_lock); | 1203 | spin_lock_init(&trans(priv)->reg_lock); |
1825 | spin_lock_init(&priv->shrd->lock); | 1204 | spin_lock_init(&priv->shrd->lock); |
1826 | 1205 | ||
1827 | /* | ||
1828 | * stop and reset the on-board processor just in case it is in a | ||
1829 | * strange state ... like being left stranded by a primary kernel | ||
1830 | * and this is now the kdump kernel trying to start up | ||
1831 | */ | ||
1832 | iwl_write32(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
1833 | |||
1834 | /*********************** | 1206 | /*********************** |
1835 | * 3. Read REV register | 1207 | * 3. Read REV register |
1836 | ***********************/ | 1208 | ***********************/ |
1837 | hw_rev = iwl_hw_detect(priv); | ||
1838 | IWL_INFO(priv, "Detected %s, REV=0x%X\n", | 1209 | IWL_INFO(priv, "Detected %s, REV=0x%X\n", |
1839 | cfg(priv)->name, hw_rev); | 1210 | cfg(priv)->name, trans(priv)->hw_rev); |
1840 | 1211 | ||
1841 | err = iwl_trans_request_irq(trans(priv)); | 1212 | err = iwl_trans_start_hw(trans(priv)); |
1842 | if (err) | 1213 | if (err) |
1843 | goto out_free_trans; | 1214 | goto out_free_traffic_mem; |
1844 | |||
1845 | if (iwl_trans_prepare_card_hw(trans(priv))) { | ||
1846 | err = -EIO; | ||
1847 | IWL_WARN(priv, "Failed, HW not ready\n"); | ||
1848 | goto out_free_trans; | ||
1849 | } | ||
1850 | 1215 | ||
1851 | /***************** | 1216 | /***************** |
1852 | * 4. Read EEPROM | 1217 | * 4. Read EEPROM |
1853 | *****************/ | 1218 | *****************/ |
1854 | /* Read the EEPROM */ | 1219 | /* Read the EEPROM */ |
1855 | err = iwl_eeprom_init(priv, hw_rev); | 1220 | err = iwl_eeprom_init(priv, trans(priv)->hw_rev); |
1221 | /* Reset chip to save power until we load uCode during "up". */ | ||
1222 | iwl_trans_stop_hw(trans(priv)); | ||
1856 | if (err) { | 1223 | if (err) { |
1857 | IWL_ERR(priv, "Unable to init EEPROM\n"); | 1224 | IWL_ERR(priv, "Unable to init EEPROM\n"); |
1858 | goto out_free_trans; | 1225 | goto out_free_traffic_mem; |
1859 | } | 1226 | } |
1860 | err = iwl_eeprom_check_version(priv); | 1227 | err = iwl_eeprom_check_version(priv); |
1861 | if (err) | 1228 | if (err) |
@@ -1903,22 +1270,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, | |||
1903 | iwl_setup_rx_handlers(priv); | 1270 | iwl_setup_rx_handlers(priv); |
1904 | iwl_testmode_init(priv); | 1271 | iwl_testmode_init(priv); |
1905 | 1272 | ||
1906 | /********************************************* | ||
1907 | * 8. Enable interrupts | ||
1908 | *********************************************/ | ||
1909 | |||
1910 | iwl_enable_rfkill_int(priv); | ||
1911 | |||
1912 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
1913 | if (iwl_read32(bus(priv), | ||
1914 | CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | ||
1915 | clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); | ||
1916 | else | ||
1917 | set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); | ||
1918 | |||
1919 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | ||
1920 | test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); | ||
1921 | |||
1922 | iwl_power_initialize(priv); | 1273 | iwl_power_initialize(priv); |
1923 | iwl_tt_initialize(priv); | 1274 | iwl_tt_initialize(priv); |
1924 | 1275 | ||
@@ -1936,8 +1287,6 @@ out_destroy_workqueue: | |||
1936 | iwl_uninit_drv(priv); | 1287 | iwl_uninit_drv(priv); |
1937 | out_free_eeprom: | 1288 | out_free_eeprom: |
1938 | iwl_eeprom_free(priv->shrd); | 1289 | iwl_eeprom_free(priv->shrd); |
1939 | out_free_trans: | ||
1940 | iwl_trans_free(trans(priv)); | ||
1941 | out_free_traffic_mem: | 1290 | out_free_traffic_mem: |
1942 | iwl_free_traffic_mem(priv); | 1291 | iwl_free_traffic_mem(priv); |
1943 | ieee80211_free_hw(priv->hw); | 1292 | ieee80211_free_hw(priv->hw); |
@@ -1981,8 +1330,6 @@ void __devexit iwl_remove(struct iwl_priv * priv) | |||
1981 | priv->shrd->workqueue = NULL; | 1330 | priv->shrd->workqueue = NULL; |
1982 | iwl_free_traffic_mem(priv); | 1331 | iwl_free_traffic_mem(priv); |
1983 | 1332 | ||
1984 | iwl_trans_free(trans(priv)); | ||
1985 | |||
1986 | iwl_uninit_drv(priv); | 1333 | iwl_uninit_drv(priv); |
1987 | 1334 | ||
1988 | dev_kfree_skb(priv->beacon_skb); | 1335 | dev_kfree_skb(priv->beacon_skb); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 39cbe1a1577c..37c325ff6e8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -73,8 +73,6 @@ struct iwlagn_ucode_capabilities { | |||
73 | 73 | ||
74 | extern struct ieee80211_ops iwlagn_hw_ops; | 74 | extern struct ieee80211_ops iwlagn_hw_ops; |
75 | 75 | ||
76 | int iwl_reset_ict(struct iwl_trans *trans); | ||
77 | |||
78 | static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) | 76 | static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) |
79 | { | 77 | { |
80 | hdr->op_code = cmd; | 78 | hdr->op_code = cmd; |
@@ -109,6 +107,7 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf, | |||
109 | int iwlagn_rx_calib_result(struct iwl_priv *priv, | 107 | int iwlagn_rx_calib_result(struct iwl_priv *priv, |
110 | struct iwl_rx_mem_buffer *rxb, | 108 | struct iwl_rx_mem_buffer *rxb, |
111 | struct iwl_device_cmd *cmd); | 109 | struct iwl_device_cmd *cmd); |
110 | void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); | ||
112 | 111 | ||
113 | /* lib */ | 112 | /* lib */ |
114 | int iwlagn_send_tx_power(struct iwl_priv *priv); | 113 | int iwlagn_send_tx_power(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 941b9cb23442..30965e0e8ab4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h | |||
@@ -119,87 +119,23 @@ struct iwl_shared; | |||
119 | struct iwl_bus; | 119 | struct iwl_bus; |
120 | 120 | ||
121 | /** | 121 | /** |
122 | * struct iwl_bus_ops - bus specific operations | ||
123 | * @get_pm_support: must returns true if the bus can go to sleep | ||
124 | * @apm_config: will be called during the config of the APM | ||
125 | * @get_hw_id_string: prints the hw_id in the provided buffer | ||
126 | * @get_hw_id: get hw_id in u32 | ||
127 | * @write8: write a byte to register at offset ofs | ||
128 | * @write32: write a dword to register at offset ofs | ||
129 | * @wread32: read a dword at register at offset ofs | ||
130 | */ | ||
131 | struct iwl_bus_ops { | ||
132 | bool (*get_pm_support)(struct iwl_bus *bus); | ||
133 | void (*apm_config)(struct iwl_bus *bus); | ||
134 | void (*get_hw_id_string)(struct iwl_bus *bus, char buf[], int buf_len); | ||
135 | u32 (*get_hw_id)(struct iwl_bus *bus); | ||
136 | void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); | ||
137 | void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); | ||
138 | u32 (*read32)(struct iwl_bus *bus, u32 ofs); | ||
139 | }; | ||
140 | |||
141 | /** | ||
142 | * struct iwl_bus - bus common data | 122 | * struct iwl_bus - bus common data |
143 | * | 123 | * |
144 | * This data is common to all bus layer implementations. | 124 | * This data is common to all bus layer implementations. |
145 | * | 125 | * |
146 | * @dev - pointer to struct device * that represents the device | ||
147 | * @ops - pointer to iwl_bus_ops | 126 | * @ops - pointer to iwl_bus_ops |
148 | * @shrd - pointer to iwl_shared which holds shared data from the upper layer | 127 | * @shrd - pointer to iwl_shared which holds shared data from the upper layer |
149 | * NB: for the time being this needs to be set by the upper layer since | 128 | * NB: for the time being this needs to be set by the upper layer since |
150 | * it allocates the shared data | 129 | * it allocates the shared data |
151 | * @irq - the irq number for the device | ||
152 | * @reg_lock - protect hw register access | ||
153 | */ | 130 | */ |
154 | struct iwl_bus { | 131 | struct iwl_bus { |
155 | struct device *dev; | ||
156 | const struct iwl_bus_ops *ops; | ||
157 | struct iwl_shared *shrd; | 132 | struct iwl_shared *shrd; |
158 | 133 | ||
159 | unsigned int irq; | ||
160 | spinlock_t reg_lock; | ||
161 | |||
162 | /* pointer to bus specific struct */ | 134 | /* pointer to bus specific struct */ |
163 | /*Ensure that this pointer will always be aligned to sizeof pointer */ | 135 | /*Ensure that this pointer will always be aligned to sizeof pointer */ |
164 | char bus_specific[0] __attribute__((__aligned__(sizeof(void *)))); | 136 | char bus_specific[0] __attribute__((__aligned__(sizeof(void *)))); |
165 | }; | 137 | }; |
166 | 138 | ||
167 | static inline bool bus_get_pm_support(struct iwl_bus *bus) | ||
168 | { | ||
169 | return bus->ops->get_pm_support(bus); | ||
170 | } | ||
171 | |||
172 | static inline void bus_apm_config(struct iwl_bus *bus) | ||
173 | { | ||
174 | bus->ops->apm_config(bus); | ||
175 | } | ||
176 | |||
177 | static inline void bus_get_hw_id_string(struct iwl_bus *bus, char buf[], | ||
178 | int buf_len) | ||
179 | { | ||
180 | bus->ops->get_hw_id_string(bus, buf, buf_len); | ||
181 | } | ||
182 | |||
183 | static inline u32 bus_get_hw_id(struct iwl_bus *bus) | ||
184 | { | ||
185 | return bus->ops->get_hw_id(bus); | ||
186 | } | ||
187 | |||
188 | static inline void bus_write8(struct iwl_bus *bus, u32 ofs, u8 val) | ||
189 | { | ||
190 | bus->ops->write8(bus, ofs, val); | ||
191 | } | ||
192 | |||
193 | static inline void bus_write32(struct iwl_bus *bus, u32 ofs, u32 val) | ||
194 | { | ||
195 | bus->ops->write32(bus, ofs, val); | ||
196 | } | ||
197 | |||
198 | static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs) | ||
199 | { | ||
200 | return bus->ops->read32(bus, ofs); | ||
201 | } | ||
202 | |||
203 | /***************************************************** | 139 | /***************************************************** |
204 | * Bus layer registration functions | 140 | * Bus layer registration functions |
205 | ******************************************************/ | 141 | ******************************************************/ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 7d6eef96454a..0677b3dfbfb2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -203,10 +203,9 @@ int iwl_init_geos(struct iwl_priv *priv) | |||
203 | 203 | ||
204 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && | 204 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && |
205 | cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) { | 205 | cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) { |
206 | char buf[32]; | ||
207 | bus_get_hw_id_string(bus(priv), buf, sizeof(buf)); | ||
208 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " | 206 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " |
209 | "Please send your %s to maintainer.\n", buf); | 207 | "Please send your %s to maintainer.\n", |
208 | trans(priv)->hw_id_str); | ||
210 | cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; | 209 | cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; |
211 | } | 210 | } |
212 | 211 | ||
@@ -883,129 +882,6 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
883 | } | 882 | } |
884 | } | 883 | } |
885 | 884 | ||
886 | static int iwl_apm_stop_master(struct iwl_priv *priv) | ||
887 | { | ||
888 | int ret = 0; | ||
889 | |||
890 | /* stop device's busmaster DMA activity */ | ||
891 | iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
892 | |||
893 | ret = iwl_poll_bit(bus(priv), CSR_RESET, | ||
894 | CSR_RESET_REG_FLAG_MASTER_DISABLED, | ||
895 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
896 | if (ret) | ||
897 | IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n"); | ||
898 | |||
899 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
900 | |||
901 | return ret; | ||
902 | } | ||
903 | |||
904 | void iwl_apm_stop(struct iwl_priv *priv) | ||
905 | { | ||
906 | IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); | ||
907 | |||
908 | clear_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); | ||
909 | |||
910 | /* Stop device's DMA activity */ | ||
911 | iwl_apm_stop_master(priv); | ||
912 | |||
913 | /* Reset the entire device */ | ||
914 | iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
915 | |||
916 | udelay(10); | ||
917 | |||
918 | /* | ||
919 | * Clear "initialization complete" bit to move adapter from | ||
920 | * D0A* (powered-up Active) --> D0U* (Uninitialized) state. | ||
921 | */ | ||
922 | iwl_clear_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
923 | } | ||
924 | |||
925 | |||
926 | /* | ||
927 | * Start up NIC's basic functionality after it has been reset | ||
928 | * (e.g. after platform boot, or shutdown via iwl_apm_stop()) | ||
929 | * NOTE: This does not load uCode nor start the embedded processor | ||
930 | */ | ||
931 | int iwl_apm_init(struct iwl_priv *priv) | ||
932 | { | ||
933 | int ret = 0; | ||
934 | IWL_DEBUG_INFO(priv, "Init card's basic functions\n"); | ||
935 | |||
936 | /* | ||
937 | * Use "set_bit" below rather than "write", to preserve any hardware | ||
938 | * bits already set by default after reset. | ||
939 | */ | ||
940 | |||
941 | /* Disable L0S exit timer (platform NMI Work/Around) */ | ||
942 | iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, | ||
943 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
944 | |||
945 | /* | ||
946 | * Disable L0s without affecting L1; | ||
947 | * don't wait for ICH L0s (ICH bug W/A) | ||
948 | */ | ||
949 | iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, | ||
950 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
951 | |||
952 | /* Set FH wait threshold to maximum (HW error during stress W/A) */ | ||
953 | iwl_set_bit(bus(priv), CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); | ||
954 | |||
955 | /* | ||
956 | * Enable HAP INTA (interrupt from management bus) to | ||
957 | * wake device's PCI Express link L1a -> L0s | ||
958 | */ | ||
959 | iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, | ||
960 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); | ||
961 | |||
962 | bus_apm_config(bus(priv)); | ||
963 | |||
964 | /* Configure analog phase-lock-loop before activating to D0A */ | ||
965 | if (cfg(priv)->base_params->pll_cfg_val) | ||
966 | iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG, | ||
967 | cfg(priv)->base_params->pll_cfg_val); | ||
968 | |||
969 | /* | ||
970 | * Set "initialization complete" bit to move adapter from | ||
971 | * D0U* --> D0A* (powered-up active) state. | ||
972 | */ | ||
973 | iwl_set_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
974 | |||
975 | /* | ||
976 | * Wait for clock stabilization; once stabilized, access to | ||
977 | * device-internal resources is supported, e.g. iwl_write_prph() | ||
978 | * and accesses to uCode SRAM. | ||
979 | */ | ||
980 | ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL, | ||
981 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
982 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
983 | if (ret < 0) { | ||
984 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
985 | goto out; | ||
986 | } | ||
987 | |||
988 | /* | ||
989 | * Enable DMA clock and wait for it to stabilize. | ||
990 | * | ||
991 | * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits | ||
992 | * do not disable clocks. This preserves any hardware bits already | ||
993 | * set by default in "CLK_CTRL_REG" after reset. | ||
994 | */ | ||
995 | iwl_write_prph(bus(priv), APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); | ||
996 | udelay(20); | ||
997 | |||
998 | /* Disable L1-Active */ | ||
999 | iwl_set_bits_prph(bus(priv), APMG_PCIDEV_STT_REG, | ||
1000 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
1001 | |||
1002 | set_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); | ||
1003 | |||
1004 | out: | ||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | |||
1009 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | 885 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) |
1010 | { | 886 | { |
1011 | int ret; | 887 | int ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 63f29111da13..8d60dcf6f2eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -297,12 +297,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) | |||
297 | cfg(priv)->bt_params->advanced_bt_coexist; | 297 | cfg(priv)->bt_params->advanced_bt_coexist; |
298 | } | 298 | } |
299 | 299 | ||
300 | static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) | ||
301 | { | ||
302 | IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); | ||
303 | iwl_write32(bus(priv), CSR_INT_MASK, CSR_INT_BIT_RF_KILL); | ||
304 | } | ||
305 | |||
306 | extern bool bt_siso_mode; | 300 | extern bool bt_siso_mode; |
307 | 301 | ||
308 | #endif /* __iwl_core_h__ */ | 302 | #endif /* __iwl_core_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 6f7612781e03..351b41d7f4fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -35,10 +35,10 @@ | |||
35 | struct iwl_priv; | 35 | struct iwl_priv; |
36 | 36 | ||
37 | /*No matter what is m (priv, bus, trans), this will work */ | 37 | /*No matter what is m (priv, bus, trans), this will work */ |
38 | #define IWL_ERR(m, f, a...) dev_err(bus(m)->dev, f, ## a) | 38 | #define IWL_ERR(m, f, a...) dev_err(trans(m)->dev, f, ## a) |
39 | #define IWL_WARN(m, f, a...) dev_warn(bus(m)->dev, f, ## a) | 39 | #define IWL_WARN(m, f, a...) dev_warn(trans(m)->dev, f, ## a) |
40 | #define IWL_INFO(m, f, a...) dev_info(bus(m)->dev, f, ## a) | 40 | #define IWL_INFO(m, f, a...) dev_info(trans(m)->dev, f, ## a) |
41 | #define IWL_CRIT(m, f, a...) dev_crit(bus(m)->dev, f, ## a) | 41 | #define IWL_CRIT(m, f, a...) dev_crit(trans(m)->dev, f, ## a) |
42 | 42 | ||
43 | #define iwl_print_hex_error(m, p, len) \ | 43 | #define iwl_print_hex_error(m, p, len) \ |
44 | do { \ | 44 | do { \ |
@@ -50,7 +50,7 @@ do { \ | |||
50 | #define IWL_DEBUG(m, level, fmt, ...) \ | 50 | #define IWL_DEBUG(m, level, fmt, ...) \ |
51 | do { \ | 51 | do { \ |
52 | if (iwl_get_debug_level((m)->shrd) & (level)) \ | 52 | if (iwl_get_debug_level((m)->shrd) & (level)) \ |
53 | dev_err(bus(m)->dev, "%c %s " fmt, \ | 53 | dev_err(trans(m)->dev, "%c %s " fmt, \ |
54 | in_interrupt() ? 'I' : 'U', __func__, \ | 54 | in_interrupt() ? 'I' : 'U', __func__, \ |
55 | ##__VA_ARGS__); \ | 55 | ##__VA_ARGS__); \ |
56 | } while (0) | 56 | } while (0) |
@@ -59,7 +59,7 @@ do { \ | |||
59 | do { \ | 59 | do { \ |
60 | if (iwl_get_debug_level((m)->shrd) & (level) && \ | 60 | if (iwl_get_debug_level((m)->shrd) & (level) && \ |
61 | net_ratelimit()) \ | 61 | net_ratelimit()) \ |
62 | dev_err(bus(m)->dev, "%c %s " fmt, \ | 62 | dev_err(trans(m)->dev, "%c %s " fmt, \ |
63 | in_interrupt() ? 'I' : 'U', __func__, \ | 63 | in_interrupt() ? 'I' : 'U', __func__, \ |
64 | ##__VA_ARGS__); \ | 64 | ##__VA_ARGS__); \ |
65 | } while (0) | 65 | } while (0) |
@@ -74,12 +74,12 @@ do { \ | |||
74 | #define IWL_DEBUG_QUIET_RFKILL(p, fmt, ...) \ | 74 | #define IWL_DEBUG_QUIET_RFKILL(p, fmt, ...) \ |
75 | do { \ | 75 | do { \ |
76 | if (!iwl_is_rfkill(p->shrd)) \ | 76 | if (!iwl_is_rfkill(p->shrd)) \ |
77 | dev_err(bus(p)->dev, "%s%c %s " fmt, \ | 77 | dev_err(trans(p)->dev, "%s%c %s " fmt, \ |
78 | "", \ | 78 | "", \ |
79 | in_interrupt() ? 'I' : 'U', __func__, \ | 79 | in_interrupt() ? 'I' : 'U', __func__, \ |
80 | ##__VA_ARGS__); \ | 80 | ##__VA_ARGS__); \ |
81 | else if (iwl_get_debug_level(p->shrd) & IWL_DL_RADIO) \ | 81 | else if (iwl_get_debug_level(p->shrd) & IWL_DL_RADIO) \ |
82 | dev_err(bus(p)->dev, "%s%c %s " fmt, \ | 82 | dev_err(trans(p)->dev, "%s%c %s " fmt, \ |
83 | "(RFKILL) ", \ | 83 | "(RFKILL) ", \ |
84 | in_interrupt() ? 'I' : 'U', __func__, \ | 84 | in_interrupt() ? 'I' : 'U', __func__, \ |
85 | ##__VA_ARGS__); \ | 85 | ##__VA_ARGS__); \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 978a1d4c6a0a..136de6fb3fa4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -263,7 +263,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
263 | sram = priv->dbgfs_sram_offset & ~0x3; | 263 | sram = priv->dbgfs_sram_offset & ~0x3; |
264 | 264 | ||
265 | /* read the first u32 from sram */ | 265 | /* read the first u32 from sram */ |
266 | val = iwl_read_targ_mem(bus(priv), sram); | 266 | val = iwl_read_targ_mem(trans(priv), sram); |
267 | 267 | ||
268 | for (; len; len--) { | 268 | for (; len; len--) { |
269 | /* put the address at the start of every line */ | 269 | /* put the address at the start of every line */ |
@@ -282,7 +282,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
282 | if (++offset == 4) { | 282 | if (++offset == 4) { |
283 | sram += 4; | 283 | sram += 4; |
284 | offset = 0; | 284 | offset = 0; |
285 | val = iwl_read_targ_mem(bus(priv), sram); | 285 | val = iwl_read_targ_mem(trans(priv), sram); |
286 | } | 286 | } |
287 | 287 | ||
288 | /* put in extra spaces and split lines for human readability */ | 288 | /* put in extra spaces and split lines for human readability */ |
@@ -2055,7 +2055,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, | |||
2055 | const size_t bufsz = sizeof(buf); | 2055 | const size_t bufsz = sizeof(buf); |
2056 | u32 pwrsave_status; | 2056 | u32 pwrsave_status; |
2057 | 2057 | ||
2058 | pwrsave_status = iwl_read32(bus(priv), CSR_GP_CNTRL) & | 2058 | pwrsave_status = iwl_read32(trans(priv), CSR_GP_CNTRL) & |
2059 | CSR_GP_REG_POWER_SAVE_STATUS_MSK; | 2059 | CSR_GP_REG_POWER_SAVE_STATUS_MSK; |
2060 | 2060 | ||
2061 | pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); | 2061 | pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index af846002150a..aa99457c3a52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -292,114 +292,6 @@ struct iwl_vif_priv { | |||
292 | u8 ibss_bssid_sta_id; | 292 | u8 ibss_bssid_sta_id; |
293 | }; | 293 | }; |
294 | 294 | ||
295 | /* v1/v2 uCode file layout */ | ||
296 | struct iwl_ucode_header { | ||
297 | __le32 ver; /* major/minor/API/serial */ | ||
298 | union { | ||
299 | struct { | ||
300 | __le32 inst_size; /* bytes of runtime code */ | ||
301 | __le32 data_size; /* bytes of runtime data */ | ||
302 | __le32 init_size; /* bytes of init code */ | ||
303 | __le32 init_data_size; /* bytes of init data */ | ||
304 | __le32 boot_size; /* bytes of bootstrap code */ | ||
305 | u8 data[0]; /* in same order as sizes */ | ||
306 | } v1; | ||
307 | struct { | ||
308 | __le32 build; /* build number */ | ||
309 | __le32 inst_size; /* bytes of runtime code */ | ||
310 | __le32 data_size; /* bytes of runtime data */ | ||
311 | __le32 init_size; /* bytes of init code */ | ||
312 | __le32 init_data_size; /* bytes of init data */ | ||
313 | __le32 boot_size; /* bytes of bootstrap code */ | ||
314 | u8 data[0]; /* in same order as sizes */ | ||
315 | } v2; | ||
316 | } u; | ||
317 | }; | ||
318 | |||
319 | /* | ||
320 | * new TLV uCode file layout | ||
321 | * | ||
322 | * The new TLV file format contains TLVs, that each specify | ||
323 | * some piece of data. To facilitate "groups", for example | ||
324 | * different instruction image with different capabilities, | ||
325 | * bundled with the same init image, an alternative mechanism | ||
326 | * is provided: | ||
327 | * When the alternative field is 0, that means that the item | ||
328 | * is always valid. When it is non-zero, then it is only | ||
329 | * valid in conjunction with items of the same alternative, | ||
330 | * in which case the driver (user) selects one alternative | ||
331 | * to use. | ||
332 | */ | ||
333 | |||
334 | enum iwl_ucode_tlv_type { | ||
335 | IWL_UCODE_TLV_INVALID = 0, /* unused */ | ||
336 | IWL_UCODE_TLV_INST = 1, | ||
337 | IWL_UCODE_TLV_DATA = 2, | ||
338 | IWL_UCODE_TLV_INIT = 3, | ||
339 | IWL_UCODE_TLV_INIT_DATA = 4, | ||
340 | IWL_UCODE_TLV_BOOT = 5, | ||
341 | IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ | ||
342 | IWL_UCODE_TLV_PAN = 7, | ||
343 | IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, | ||
344 | IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, | ||
345 | IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, | ||
346 | IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, | ||
347 | IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, | ||
348 | IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, | ||
349 | IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, | ||
350 | IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, | ||
351 | IWL_UCODE_TLV_WOWLAN_INST = 16, | ||
352 | IWL_UCODE_TLV_WOWLAN_DATA = 17, | ||
353 | IWL_UCODE_TLV_FLAGS = 18, | ||
354 | }; | ||
355 | |||
356 | /** | ||
357 | * enum iwl_ucode_tlv_flag - ucode API flags | ||
358 | * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously | ||
359 | * was a separate TLV but moved here to save space. | ||
360 | * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, | ||
361 | * treats good CRC threshold as a boolean | ||
362 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). | ||
363 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. | ||
364 | */ | ||
365 | enum iwl_ucode_tlv_flag { | ||
366 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | ||
367 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), | ||
368 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), | ||
369 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | ||
370 | }; | ||
371 | |||
372 | struct iwl_ucode_tlv { | ||
373 | __le16 type; /* see above */ | ||
374 | __le16 alternative; /* see comment */ | ||
375 | __le32 length; /* not including type/length fields */ | ||
376 | u8 data[0]; | ||
377 | } __packed; | ||
378 | |||
379 | #define IWL_TLV_UCODE_MAGIC 0x0a4c5749 | ||
380 | |||
381 | struct iwl_tlv_ucode_header { | ||
382 | /* | ||
383 | * The TLV style ucode header is distinguished from | ||
384 | * the v1/v2 style header by first four bytes being | ||
385 | * zero, as such is an invalid combination of | ||
386 | * major/minor/API/serial versions. | ||
387 | */ | ||
388 | __le32 zero; | ||
389 | __le32 magic; | ||
390 | u8 human_readable[64]; | ||
391 | __le32 ver; /* major/minor/API/serial */ | ||
392 | __le32 build; | ||
393 | __le64 alternatives; /* bitmask of valid alternatives */ | ||
394 | /* | ||
395 | * The data contained herein has a TLV layout, | ||
396 | * see above for the TLV header and types. | ||
397 | * Note that each TLV is padded to a length | ||
398 | * that is a multiple of 4 for alignment. | ||
399 | */ | ||
400 | u8 data[0]; | ||
401 | }; | ||
402 | |||
403 | struct iwl_sensitivity_ranges { | 295 | struct iwl_sensitivity_ranges { |
404 | u16 min_nrg_cck; | 296 | u16 min_nrg_cck; |
405 | u16 max_nrg_cck; | 297 | u16 max_nrg_cck; |
@@ -821,7 +713,6 @@ struct iwl_wipan_noa_data { | |||
821 | struct iwl_priv { | 713 | struct iwl_priv { |
822 | 714 | ||
823 | /*data shared among all the driver's layers */ | 715 | /*data shared among all the driver's layers */ |
824 | struct iwl_shared _shrd; | ||
825 | struct iwl_shared *shrd; | 716 | struct iwl_shared *shrd; |
826 | 717 | ||
827 | /* ieee device used by generic ieee processing code */ | 718 | /* ieee device used by generic ieee processing code */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index e27d9f55267b..d1fd1cdb29c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -156,16 +156,16 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus) | |||
156 | 156 | ||
157 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | 157 | for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { |
158 | /* Request semaphore */ | 158 | /* Request semaphore */ |
159 | iwl_set_bit(bus, CSR_HW_IF_CONFIG_REG, | 159 | iwl_set_bit(trans(bus), CSR_HW_IF_CONFIG_REG, |
160 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | 160 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); |
161 | 161 | ||
162 | /* See if we got it */ | 162 | /* See if we got it */ |
163 | ret = iwl_poll_bit(bus, CSR_HW_IF_CONFIG_REG, | 163 | ret = iwl_poll_bit(trans(bus), CSR_HW_IF_CONFIG_REG, |
164 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | 164 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, |
165 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | 165 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, |
166 | EEPROM_SEM_TIMEOUT); | 166 | EEPROM_SEM_TIMEOUT); |
167 | if (ret >= 0) { | 167 | if (ret >= 0) { |
168 | IWL_DEBUG_EEPROM(bus, | 168 | IWL_DEBUG_EEPROM(trans(bus), |
169 | "Acquired semaphore after %d tries.\n", | 169 | "Acquired semaphore after %d tries.\n", |
170 | count+1); | 170 | count+1); |
171 | return ret; | 171 | return ret; |
@@ -177,14 +177,15 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus) | |||
177 | 177 | ||
178 | static void iwl_eeprom_release_semaphore(struct iwl_bus *bus) | 178 | static void iwl_eeprom_release_semaphore(struct iwl_bus *bus) |
179 | { | 179 | { |
180 | iwl_clear_bit(bus, CSR_HW_IF_CONFIG_REG, | 180 | iwl_clear_bit(trans(bus), CSR_HW_IF_CONFIG_REG, |
181 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | 181 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); |
182 | 182 | ||
183 | } | 183 | } |
184 | 184 | ||
185 | static int iwl_eeprom_verify_signature(struct iwl_trans *trans) | 185 | static int iwl_eeprom_verify_signature(struct iwl_trans *trans) |
186 | { | 186 | { |
187 | u32 gp = iwl_read32(bus(trans), CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; | 187 | u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & |
188 | CSR_EEPROM_GP_VALID_MSK; | ||
188 | int ret = 0; | 189 | int ret = 0; |
189 | 190 | ||
190 | IWL_DEBUG_EEPROM(trans, "EEPROM signature=0x%08x\n", gp); | 191 | IWL_DEBUG_EEPROM(trans, "EEPROM signature=0x%08x\n", gp); |
@@ -305,13 +306,13 @@ void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac) | |||
305 | 306 | ||
306 | static void iwl_set_otp_access(struct iwl_bus *bus, enum iwl_access_mode mode) | 307 | static void iwl_set_otp_access(struct iwl_bus *bus, enum iwl_access_mode mode) |
307 | { | 308 | { |
308 | iwl_read32(bus, CSR_OTP_GP_REG); | 309 | iwl_read32(trans(bus), CSR_OTP_GP_REG); |
309 | 310 | ||
310 | if (mode == IWL_OTP_ACCESS_ABSOLUTE) | 311 | if (mode == IWL_OTP_ACCESS_ABSOLUTE) |
311 | iwl_clear_bit(bus, CSR_OTP_GP_REG, | 312 | iwl_clear_bit(trans(bus), CSR_OTP_GP_REG, |
312 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | 313 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); |
313 | else | 314 | else |
314 | iwl_set_bit(bus, CSR_OTP_GP_REG, | 315 | iwl_set_bit(trans(bus), CSR_OTP_GP_REG, |
315 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | 316 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); |
316 | } | 317 | } |
317 | 318 | ||
@@ -332,7 +333,7 @@ static int iwl_get_nvm_type(struct iwl_bus *bus, u32 hw_rev) | |||
332 | nvm_type = NVM_DEVICE_TYPE_EEPROM; | 333 | nvm_type = NVM_DEVICE_TYPE_EEPROM; |
333 | break; | 334 | break; |
334 | default: | 335 | default: |
335 | otpgp = iwl_read32(bus, CSR_OTP_GP_REG); | 336 | otpgp = iwl_read32(trans(bus), CSR_OTP_GP_REG); |
336 | if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) | 337 | if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) |
337 | nvm_type = NVM_DEVICE_TYPE_OTP; | 338 | nvm_type = NVM_DEVICE_TYPE_OTP; |
338 | else | 339 | else |
@@ -347,22 +348,22 @@ static int iwl_init_otp_access(struct iwl_bus *bus) | |||
347 | int ret; | 348 | int ret; |
348 | 349 | ||
349 | /* Enable 40MHz radio clock */ | 350 | /* Enable 40MHz radio clock */ |
350 | iwl_write32(bus, CSR_GP_CNTRL, | 351 | iwl_write32(trans(bus), CSR_GP_CNTRL, |
351 | iwl_read32(bus, CSR_GP_CNTRL) | | 352 | iwl_read32(trans(bus), CSR_GP_CNTRL) | |
352 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 353 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
353 | 354 | ||
354 | /* wait for clock to be ready */ | 355 | /* wait for clock to be ready */ |
355 | ret = iwl_poll_bit(bus, CSR_GP_CNTRL, | 356 | ret = iwl_poll_bit(trans(bus), CSR_GP_CNTRL, |
356 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | 357 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, |
357 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | 358 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, |
358 | 25000); | 359 | 25000); |
359 | if (ret < 0) | 360 | if (ret < 0) |
360 | IWL_ERR(bus, "Time out access OTP\n"); | 361 | IWL_ERR(bus, "Time out access OTP\n"); |
361 | else { | 362 | else { |
362 | iwl_set_bits_prph(bus, APMG_PS_CTRL_REG, | 363 | iwl_set_bits_prph(trans(bus), APMG_PS_CTRL_REG, |
363 | APMG_PS_CTRL_VAL_RESET_REQ); | 364 | APMG_PS_CTRL_VAL_RESET_REQ); |
364 | udelay(5); | 365 | udelay(5); |
365 | iwl_clear_bits_prph(bus, APMG_PS_CTRL_REG, | 366 | iwl_clear_bits_prph(trans(bus), APMG_PS_CTRL_REG, |
366 | APMG_PS_CTRL_VAL_RESET_REQ); | 367 | APMG_PS_CTRL_VAL_RESET_REQ); |
367 | 368 | ||
368 | /* | 369 | /* |
@@ -370,7 +371,7 @@ static int iwl_init_otp_access(struct iwl_bus *bus) | |||
370 | * this is only applicable for HW with OTP shadow RAM | 371 | * this is only applicable for HW with OTP shadow RAM |
371 | */ | 372 | */ |
372 | if (cfg(bus)->base_params->shadow_ram_support) | 373 | if (cfg(bus)->base_params->shadow_ram_support) |
373 | iwl_set_bit(bus, CSR_DBG_LINK_PWR_MGMT_REG, | 374 | iwl_set_bit(trans(bus), CSR_DBG_LINK_PWR_MGMT_REG, |
374 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | 375 | CSR_RESET_LINK_PWR_MGMT_DISABLED); |
375 | } | 376 | } |
376 | return ret; | 377 | return ret; |
@@ -382,9 +383,9 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data) | |||
382 | u32 r; | 383 | u32 r; |
383 | u32 otpgp; | 384 | u32 otpgp; |
384 | 385 | ||
385 | iwl_write32(bus, CSR_EEPROM_REG, | 386 | iwl_write32(trans(bus), CSR_EEPROM_REG, |
386 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | 387 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); |
387 | ret = iwl_poll_bit(bus, CSR_EEPROM_REG, | 388 | ret = iwl_poll_bit(trans(bus), CSR_EEPROM_REG, |
388 | CSR_EEPROM_REG_READ_VALID_MSK, | 389 | CSR_EEPROM_REG_READ_VALID_MSK, |
389 | CSR_EEPROM_REG_READ_VALID_MSK, | 390 | CSR_EEPROM_REG_READ_VALID_MSK, |
390 | IWL_EEPROM_ACCESS_TIMEOUT); | 391 | IWL_EEPROM_ACCESS_TIMEOUT); |
@@ -392,13 +393,13 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data) | |||
392 | IWL_ERR(bus, "Time out reading OTP[%d]\n", addr); | 393 | IWL_ERR(bus, "Time out reading OTP[%d]\n", addr); |
393 | return ret; | 394 | return ret; |
394 | } | 395 | } |
395 | r = iwl_read32(bus, CSR_EEPROM_REG); | 396 | r = iwl_read32(trans(bus), CSR_EEPROM_REG); |
396 | /* check for ECC errors: */ | 397 | /* check for ECC errors: */ |
397 | otpgp = iwl_read32(bus, CSR_OTP_GP_REG); | 398 | otpgp = iwl_read32(trans(bus), CSR_OTP_GP_REG); |
398 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | 399 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { |
399 | /* stop in this case */ | 400 | /* stop in this case */ |
400 | /* set the uncorrectable OTP ECC bit for acknowledgement */ | 401 | /* set the uncorrectable OTP ECC bit for acknowledgement */ |
401 | iwl_set_bit(bus, CSR_OTP_GP_REG, | 402 | iwl_set_bit(trans(bus), CSR_OTP_GP_REG, |
402 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | 403 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); |
403 | IWL_ERR(bus, "Uncorrectable OTP ECC error, abort OTP read\n"); | 404 | IWL_ERR(bus, "Uncorrectable OTP ECC error, abort OTP read\n"); |
404 | return -EINVAL; | 405 | return -EINVAL; |
@@ -406,7 +407,7 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data) | |||
406 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | 407 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { |
407 | /* continue in this case */ | 408 | /* continue in this case */ |
408 | /* set the correctable OTP ECC bit for acknowledgement */ | 409 | /* set the correctable OTP ECC bit for acknowledgement */ |
409 | iwl_set_bit(bus, CSR_OTP_GP_REG, | 410 | iwl_set_bit(trans(bus), CSR_OTP_GP_REG, |
410 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | 411 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); |
411 | IWL_ERR(bus, "Correctable OTP ECC error, continue read\n"); | 412 | IWL_ERR(bus, "Correctable OTP ECC error, continue read\n"); |
412 | } | 413 | } |
@@ -656,7 +657,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | |||
656 | { | 657 | { |
657 | struct iwl_shared *shrd = priv->shrd; | 658 | struct iwl_shared *shrd = priv->shrd; |
658 | __le16 *e; | 659 | __le16 *e; |
659 | u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP); | 660 | u32 gp = iwl_read32(trans(priv), CSR_EEPROM_GP); |
660 | int sz; | 661 | int sz; |
661 | int ret; | 662 | int ret; |
662 | u16 addr; | 663 | u16 addr; |
@@ -676,8 +677,6 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | |||
676 | } | 677 | } |
677 | e = (__le16 *)shrd->eeprom; | 678 | e = (__le16 *)shrd->eeprom; |
678 | 679 | ||
679 | iwl_apm_init(priv); | ||
680 | |||
681 | ret = iwl_eeprom_verify_signature(trans(priv)); | 680 | ret = iwl_eeprom_verify_signature(trans(priv)); |
682 | if (ret < 0) { | 681 | if (ret < 0) { |
683 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | 682 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); |
@@ -701,11 +700,11 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | |||
701 | ret = -ENOENT; | 700 | ret = -ENOENT; |
702 | goto done; | 701 | goto done; |
703 | } | 702 | } |
704 | iwl_write32(bus(priv), CSR_EEPROM_GP, | 703 | iwl_write32(trans(priv), CSR_EEPROM_GP, |
705 | iwl_read32(bus(priv), CSR_EEPROM_GP) & | 704 | iwl_read32(trans(priv), CSR_EEPROM_GP) & |
706 | ~CSR_EEPROM_GP_IF_OWNER_MSK); | 705 | ~CSR_EEPROM_GP_IF_OWNER_MSK); |
707 | 706 | ||
708 | iwl_set_bit(bus(priv), CSR_OTP_GP_REG, | 707 | iwl_set_bit(trans(priv), CSR_OTP_GP_REG, |
709 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | 708 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | |
710 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | 709 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); |
711 | /* traversing the linked list if no shadow ram supported */ | 710 | /* traversing the linked list if no shadow ram supported */ |
@@ -730,10 +729,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | |||
730 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | 729 | for (addr = 0; addr < sz; addr += sizeof(u16)) { |
731 | u32 r; | 730 | u32 r; |
732 | 731 | ||
733 | iwl_write32(bus(priv), CSR_EEPROM_REG, | 732 | iwl_write32(trans(priv), CSR_EEPROM_REG, |
734 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | 733 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); |
735 | 734 | ||
736 | ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG, | 735 | ret = iwl_poll_bit(trans(priv), CSR_EEPROM_REG, |
737 | CSR_EEPROM_REG_READ_VALID_MSK, | 736 | CSR_EEPROM_REG_READ_VALID_MSK, |
738 | CSR_EEPROM_REG_READ_VALID_MSK, | 737 | CSR_EEPROM_REG_READ_VALID_MSK, |
739 | IWL_EEPROM_ACCESS_TIMEOUT); | 738 | IWL_EEPROM_ACCESS_TIMEOUT); |
@@ -741,7 +740,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) | |||
741 | IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); | 740 | IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); |
742 | goto done; | 741 | goto done; |
743 | } | 742 | } |
744 | r = iwl_read32(bus(priv), CSR_EEPROM_REG); | 743 | r = iwl_read32(trans(priv), CSR_EEPROM_REG); |
745 | e[addr / 2] = cpu_to_le16(r >> 16); | 744 | e[addr / 2] = cpu_to_le16(r >> 16); |
746 | } | 745 | } |
747 | } | 746 | } |
@@ -758,8 +757,6 @@ done: | |||
758 | err: | 757 | err: |
759 | if (ret) | 758 | if (ret) |
760 | iwl_eeprom_free(priv->shrd); | 759 | iwl_eeprom_free(priv->shrd); |
761 | /* Reset chip to save power until we load uCode during "up". */ | ||
762 | iwl_apm_stop(priv); | ||
763 | alloc_err: | 760 | alloc_err: |
764 | return ret; | 761 | return ret; |
765 | } | 762 | } |
@@ -1072,7 +1069,7 @@ void iwl_rf_config(struct iwl_priv *priv) | |||
1072 | 1069 | ||
1073 | /* write radio config values to register */ | 1070 | /* write radio config values to register */ |
1074 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | 1071 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { |
1075 | iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, | 1072 | iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, |
1076 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | 1073 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | |
1077 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | 1074 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | |
1078 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | 1075 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); |
@@ -1084,7 +1081,7 @@ void iwl_rf_config(struct iwl_priv *priv) | |||
1084 | WARN_ON(1); | 1081 | WARN_ON(1); |
1085 | 1082 | ||
1086 | /* set CSR_HW_CONFIG_REG for uCode use */ | 1083 | /* set CSR_HW_CONFIG_REG for uCode use */ |
1087 | iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, | 1084 | iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, |
1088 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | 1085 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | |
1089 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | 1086 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); |
1090 | } | 1087 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 83fdff381150..e2e3b5c9cf7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -34,41 +34,41 @@ | |||
34 | 34 | ||
35 | #define IWL_POLL_INTERVAL 10 /* microseconds */ | 35 | #define IWL_POLL_INTERVAL 10 /* microseconds */ |
36 | 36 | ||
37 | static inline void __iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) | 37 | static inline void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) |
38 | { | 38 | { |
39 | iwl_write32(bus, reg, iwl_read32(bus, reg) | mask); | 39 | iwl_write32(trans, reg, iwl_read32(trans, reg) | mask); |
40 | } | 40 | } |
41 | 41 | ||
42 | static inline void __iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) | 42 | static inline void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) |
43 | { | 43 | { |
44 | iwl_write32(bus, reg, iwl_read32(bus, reg) & ~mask); | 44 | iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask); |
45 | } | 45 | } |
46 | 46 | ||
47 | void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) | 47 | void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) |
48 | { | 48 | { |
49 | unsigned long flags; | 49 | unsigned long flags; |
50 | 50 | ||
51 | spin_lock_irqsave(&bus->reg_lock, flags); | 51 | spin_lock_irqsave(&trans->reg_lock, flags); |
52 | __iwl_set_bit(bus, reg, mask); | 52 | __iwl_set_bit(trans, reg, mask); |
53 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 53 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
54 | } | 54 | } |
55 | 55 | ||
56 | void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) | 56 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) |
57 | { | 57 | { |
58 | unsigned long flags; | 58 | unsigned long flags; |
59 | 59 | ||
60 | spin_lock_irqsave(&bus->reg_lock, flags); | 60 | spin_lock_irqsave(&trans->reg_lock, flags); |
61 | __iwl_clear_bit(bus, reg, mask); | 61 | __iwl_clear_bit(trans, reg, mask); |
62 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 62 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
63 | } | 63 | } |
64 | 64 | ||
65 | int iwl_poll_bit(struct iwl_bus *bus, u32 addr, | 65 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, |
66 | u32 bits, u32 mask, int timeout) | 66 | u32 bits, u32 mask, int timeout) |
67 | { | 67 | { |
68 | int t = 0; | 68 | int t = 0; |
69 | 69 | ||
70 | do { | 70 | do { |
71 | if ((iwl_read32(bus, addr) & mask) == (bits & mask)) | 71 | if ((iwl_read32(trans, addr) & mask) == (bits & mask)) |
72 | return t; | 72 | return t; |
73 | udelay(IWL_POLL_INTERVAL); | 73 | udelay(IWL_POLL_INTERVAL); |
74 | t += IWL_POLL_INTERVAL; | 74 | t += IWL_POLL_INTERVAL; |
@@ -77,14 +77,15 @@ int iwl_poll_bit(struct iwl_bus *bus, u32 addr, | |||
77 | return -ETIMEDOUT; | 77 | return -ETIMEDOUT; |
78 | } | 78 | } |
79 | 79 | ||
80 | int iwl_grab_nic_access_silent(struct iwl_bus *bus) | 80 | int iwl_grab_nic_access_silent(struct iwl_trans *trans) |
81 | { | 81 | { |
82 | int ret; | 82 | int ret; |
83 | 83 | ||
84 | lockdep_assert_held(&bus->reg_lock); | 84 | lockdep_assert_held(&trans->reg_lock); |
85 | 85 | ||
86 | /* this bit wakes up the NIC */ | 86 | /* this bit wakes up the NIC */ |
87 | __iwl_set_bit(bus, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 87 | __iwl_set_bit(trans, CSR_GP_CNTRL, |
88 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
88 | 89 | ||
89 | /* | 90 | /* |
90 | * These bits say the device is running, and should keep running for | 91 | * These bits say the device is running, and should keep running for |
@@ -105,70 +106,70 @@ int iwl_grab_nic_access_silent(struct iwl_bus *bus) | |||
105 | * 5000 series and later (including 1000 series) have non-volatile SRAM, | 106 | * 5000 series and later (including 1000 series) have non-volatile SRAM, |
106 | * and do not save/restore SRAM when power cycling. | 107 | * and do not save/restore SRAM when power cycling. |
107 | */ | 108 | */ |
108 | ret = iwl_poll_bit(bus, CSR_GP_CNTRL, | 109 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, |
109 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, | 110 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, |
110 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | 111 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | |
111 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); | 112 | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); |
112 | if (ret < 0) { | 113 | if (ret < 0) { |
113 | iwl_write32(bus, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); | 114 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); |
114 | return -EIO; | 115 | return -EIO; |
115 | } | 116 | } |
116 | 117 | ||
117 | return 0; | 118 | return 0; |
118 | } | 119 | } |
119 | 120 | ||
120 | int iwl_grab_nic_access(struct iwl_bus *bus) | 121 | int iwl_grab_nic_access(struct iwl_trans *trans) |
121 | { | 122 | { |
122 | int ret = iwl_grab_nic_access_silent(bus); | 123 | int ret = iwl_grab_nic_access_silent(trans); |
123 | if (ret) { | 124 | if (ret) { |
124 | u32 val = iwl_read32(bus, CSR_GP_CNTRL); | 125 | u32 val = iwl_read32(trans, CSR_GP_CNTRL); |
125 | IWL_ERR(bus, | 126 | IWL_ERR(trans, |
126 | "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); | 127 | "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); |
127 | } | 128 | } |
128 | 129 | ||
129 | return ret; | 130 | return ret; |
130 | } | 131 | } |
131 | 132 | ||
132 | void iwl_release_nic_access(struct iwl_bus *bus) | 133 | void iwl_release_nic_access(struct iwl_trans *trans) |
133 | { | 134 | { |
134 | lockdep_assert_held(&bus->reg_lock); | 135 | lockdep_assert_held(&trans->reg_lock); |
135 | __iwl_clear_bit(bus, CSR_GP_CNTRL, | 136 | __iwl_clear_bit(trans, CSR_GP_CNTRL, |
136 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 137 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
137 | } | 138 | } |
138 | 139 | ||
139 | u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg) | 140 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) |
140 | { | 141 | { |
141 | u32 value; | 142 | u32 value; |
142 | unsigned long flags; | 143 | unsigned long flags; |
143 | 144 | ||
144 | spin_lock_irqsave(&bus->reg_lock, flags); | 145 | spin_lock_irqsave(&trans->reg_lock, flags); |
145 | iwl_grab_nic_access(bus); | 146 | iwl_grab_nic_access(trans); |
146 | value = iwl_read32(bus, reg); | 147 | value = iwl_read32(trans, reg); |
147 | iwl_release_nic_access(bus); | 148 | iwl_release_nic_access(trans); |
148 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 149 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
149 | 150 | ||
150 | return value; | 151 | return value; |
151 | } | 152 | } |
152 | 153 | ||
153 | void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value) | 154 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) |
154 | { | 155 | { |
155 | unsigned long flags; | 156 | unsigned long flags; |
156 | 157 | ||
157 | spin_lock_irqsave(&bus->reg_lock, flags); | 158 | spin_lock_irqsave(&trans->reg_lock, flags); |
158 | if (!iwl_grab_nic_access(bus)) { | 159 | if (!iwl_grab_nic_access(trans)) { |
159 | iwl_write32(bus, reg, value); | 160 | iwl_write32(trans, reg, value); |
160 | iwl_release_nic_access(bus); | 161 | iwl_release_nic_access(trans); |
161 | } | 162 | } |
162 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 163 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
163 | } | 164 | } |
164 | 165 | ||
165 | int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, | 166 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, |
166 | int timeout) | 167 | int timeout) |
167 | { | 168 | { |
168 | int t = 0; | 169 | int t = 0; |
169 | 170 | ||
170 | do { | 171 | do { |
171 | if ((iwl_read_direct32(bus, addr) & mask) == mask) | 172 | if ((iwl_read_direct32(trans, addr) & mask) == mask) |
172 | return t; | 173 | return t; |
173 | udelay(IWL_POLL_INTERVAL); | 174 | udelay(IWL_POLL_INTERVAL); |
174 | t += IWL_POLL_INTERVAL; | 175 | t += IWL_POLL_INTERVAL; |
@@ -177,135 +178,135 @@ int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, | |||
177 | return -ETIMEDOUT; | 178 | return -ETIMEDOUT; |
178 | } | 179 | } |
179 | 180 | ||
180 | static inline u32 __iwl_read_prph(struct iwl_bus *bus, u32 reg) | 181 | static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg) |
181 | { | 182 | { |
182 | iwl_write32(bus, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); | 183 | iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); |
183 | rmb(); | 184 | rmb(); |
184 | return iwl_read32(bus, HBUS_TARG_PRPH_RDAT); | 185 | return iwl_read32(trans, HBUS_TARG_PRPH_RDAT); |
185 | } | 186 | } |
186 | 187 | ||
187 | static inline void __iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) | 188 | static inline void __iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val) |
188 | { | 189 | { |
189 | iwl_write32(bus, HBUS_TARG_PRPH_WADDR, | 190 | iwl_write32(trans, HBUS_TARG_PRPH_WADDR, |
190 | ((addr & 0x0000FFFF) | (3 << 24))); | 191 | ((addr & 0x0000FFFF) | (3 << 24))); |
191 | wmb(); | 192 | wmb(); |
192 | iwl_write32(bus, HBUS_TARG_PRPH_WDAT, val); | 193 | iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); |
193 | } | 194 | } |
194 | 195 | ||
195 | u32 iwl_read_prph(struct iwl_bus *bus, u32 reg) | 196 | u32 iwl_read_prph(struct iwl_trans *trans, u32 reg) |
196 | { | 197 | { |
197 | unsigned long flags; | 198 | unsigned long flags; |
198 | u32 val; | 199 | u32 val; |
199 | 200 | ||
200 | spin_lock_irqsave(&bus->reg_lock, flags); | 201 | spin_lock_irqsave(&trans->reg_lock, flags); |
201 | iwl_grab_nic_access(bus); | 202 | iwl_grab_nic_access(trans); |
202 | val = __iwl_read_prph(bus, reg); | 203 | val = __iwl_read_prph(trans, reg); |
203 | iwl_release_nic_access(bus); | 204 | iwl_release_nic_access(trans); |
204 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 205 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
205 | return val; | 206 | return val; |
206 | } | 207 | } |
207 | 208 | ||
208 | void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) | 209 | void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val) |
209 | { | 210 | { |
210 | unsigned long flags; | 211 | unsigned long flags; |
211 | 212 | ||
212 | spin_lock_irqsave(&bus->reg_lock, flags); | 213 | spin_lock_irqsave(&trans->reg_lock, flags); |
213 | if (!iwl_grab_nic_access(bus)) { | 214 | if (!iwl_grab_nic_access(trans)) { |
214 | __iwl_write_prph(bus, addr, val); | 215 | __iwl_write_prph(trans, addr, val); |
215 | iwl_release_nic_access(bus); | 216 | iwl_release_nic_access(trans); |
216 | } | 217 | } |
217 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 218 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
218 | } | 219 | } |
219 | 220 | ||
220 | void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) | 221 | void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) |
221 | { | 222 | { |
222 | unsigned long flags; | 223 | unsigned long flags; |
223 | 224 | ||
224 | spin_lock_irqsave(&bus->reg_lock, flags); | 225 | spin_lock_irqsave(&trans->reg_lock, flags); |
225 | iwl_grab_nic_access(bus); | 226 | iwl_grab_nic_access(trans); |
226 | __iwl_write_prph(bus, reg, __iwl_read_prph(bus, reg) | mask); | 227 | __iwl_write_prph(trans, reg, __iwl_read_prph(trans, reg) | mask); |
227 | iwl_release_nic_access(bus); | 228 | iwl_release_nic_access(trans); |
228 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 229 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
229 | } | 230 | } |
230 | 231 | ||
231 | void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, | 232 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg, |
232 | u32 bits, u32 mask) | 233 | u32 bits, u32 mask) |
233 | { | 234 | { |
234 | unsigned long flags; | 235 | unsigned long flags; |
235 | 236 | ||
236 | spin_lock_irqsave(&bus->reg_lock, flags); | 237 | spin_lock_irqsave(&trans->reg_lock, flags); |
237 | iwl_grab_nic_access(bus); | 238 | iwl_grab_nic_access(trans); |
238 | __iwl_write_prph(bus, reg, | 239 | __iwl_write_prph(trans, reg, |
239 | (__iwl_read_prph(bus, reg) & mask) | bits); | 240 | (__iwl_read_prph(trans, reg) & mask) | bits); |
240 | iwl_release_nic_access(bus); | 241 | iwl_release_nic_access(trans); |
241 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 242 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
242 | } | 243 | } |
243 | 244 | ||
244 | void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) | 245 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) |
245 | { | 246 | { |
246 | unsigned long flags; | 247 | unsigned long flags; |
247 | u32 val; | 248 | u32 val; |
248 | 249 | ||
249 | spin_lock_irqsave(&bus->reg_lock, flags); | 250 | spin_lock_irqsave(&trans->reg_lock, flags); |
250 | iwl_grab_nic_access(bus); | 251 | iwl_grab_nic_access(trans); |
251 | val = __iwl_read_prph(bus, reg); | 252 | val = __iwl_read_prph(trans, reg); |
252 | __iwl_write_prph(bus, reg, (val & ~mask)); | 253 | __iwl_write_prph(trans, reg, (val & ~mask)); |
253 | iwl_release_nic_access(bus); | 254 | iwl_release_nic_access(trans); |
254 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 255 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
255 | } | 256 | } |
256 | 257 | ||
257 | void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, | 258 | void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, |
258 | void *buf, int words) | 259 | void *buf, int words) |
259 | { | 260 | { |
260 | unsigned long flags; | 261 | unsigned long flags; |
261 | int offs; | 262 | int offs; |
262 | u32 *vals = buf; | 263 | u32 *vals = buf; |
263 | 264 | ||
264 | spin_lock_irqsave(&bus->reg_lock, flags); | 265 | spin_lock_irqsave(&trans->reg_lock, flags); |
265 | iwl_grab_nic_access(bus); | 266 | iwl_grab_nic_access(trans); |
266 | 267 | ||
267 | iwl_write32(bus, HBUS_TARG_MEM_RADDR, addr); | 268 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); |
268 | rmb(); | 269 | rmb(); |
269 | 270 | ||
270 | for (offs = 0; offs < words; offs++) | 271 | for (offs = 0; offs < words; offs++) |
271 | vals[offs] = iwl_read32(bus, HBUS_TARG_MEM_RDAT); | 272 | vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); |
272 | 273 | ||
273 | iwl_release_nic_access(bus); | 274 | iwl_release_nic_access(trans); |
274 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 275 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
275 | } | 276 | } |
276 | 277 | ||
277 | u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr) | 278 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) |
278 | { | 279 | { |
279 | u32 value; | 280 | u32 value; |
280 | 281 | ||
281 | _iwl_read_targ_mem_words(bus, addr, &value, 1); | 282 | _iwl_read_targ_mem_words(trans, addr, &value, 1); |
282 | 283 | ||
283 | return value; | 284 | return value; |
284 | } | 285 | } |
285 | 286 | ||
286 | int _iwl_write_targ_mem_words(struct iwl_bus *bus, u32 addr, | 287 | int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, |
287 | void *buf, int words) | 288 | void *buf, int words) |
288 | { | 289 | { |
289 | unsigned long flags; | 290 | unsigned long flags; |
290 | int offs, result = 0; | 291 | int offs, result = 0; |
291 | u32 *vals = buf; | 292 | u32 *vals = buf; |
292 | 293 | ||
293 | spin_lock_irqsave(&bus->reg_lock, flags); | 294 | spin_lock_irqsave(&trans->reg_lock, flags); |
294 | if (!iwl_grab_nic_access(bus)) { | 295 | if (!iwl_grab_nic_access(trans)) { |
295 | iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr); | 296 | iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); |
296 | wmb(); | 297 | wmb(); |
297 | 298 | ||
298 | for (offs = 0; offs < words; offs++) | 299 | for (offs = 0; offs < words; offs++) |
299 | iwl_write32(bus, HBUS_TARG_MEM_WDAT, vals[offs]); | 300 | iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]); |
300 | iwl_release_nic_access(bus); | 301 | iwl_release_nic_access(trans); |
301 | } else | 302 | } else |
302 | result = -EBUSY; | 303 | result = -EBUSY; |
303 | spin_unlock_irqrestore(&bus->reg_lock, flags); | 304 | spin_unlock_irqrestore(&trans->reg_lock, flags); |
304 | 305 | ||
305 | return result; | 306 | return result; |
306 | } | 307 | } |
307 | 308 | ||
308 | int iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val) | 309 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val) |
309 | { | 310 | { |
310 | return _iwl_write_targ_mem_words(bus, addr, &val, 1); | 311 | return _iwl_write_targ_mem_words(trans, addr, &val, 1); |
311 | } | 312 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 427d065435c8..782486fc2f8f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -31,63 +31,63 @@ | |||
31 | 31 | ||
32 | #include "iwl-devtrace.h" | 32 | #include "iwl-devtrace.h" |
33 | #include "iwl-shared.h" | 33 | #include "iwl-shared.h" |
34 | #include "iwl-bus.h" | 34 | #include "iwl-trans.h" |
35 | 35 | ||
36 | static inline void iwl_write8(struct iwl_bus *bus, u32 ofs, u8 val) | 36 | static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) |
37 | { | 37 | { |
38 | trace_iwlwifi_dev_iowrite8(priv(bus), ofs, val); | 38 | trace_iwlwifi_dev_iowrite8(priv(trans), ofs, val); |
39 | bus_write8(bus, ofs, val); | 39 | iwl_trans_write8(trans, ofs, val); |
40 | } | 40 | } |
41 | 41 | ||
42 | static inline void iwl_write32(struct iwl_bus *bus, u32 ofs, u32 val) | 42 | static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) |
43 | { | 43 | { |
44 | trace_iwlwifi_dev_iowrite32(priv(bus), ofs, val); | 44 | trace_iwlwifi_dev_iowrite32(priv(trans), ofs, val); |
45 | bus_write32(bus, ofs, val); | 45 | iwl_trans_write32(trans, ofs, val); |
46 | } | 46 | } |
47 | 47 | ||
48 | static inline u32 iwl_read32(struct iwl_bus *bus, u32 ofs) | 48 | static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) |
49 | { | 49 | { |
50 | u32 val = bus_read32(bus, ofs); | 50 | u32 val = iwl_trans_read32(trans, ofs); |
51 | trace_iwlwifi_dev_ioread32(priv(bus), ofs, val); | 51 | trace_iwlwifi_dev_ioread32(priv(trans), ofs, val); |
52 | return val; | 52 | return val; |
53 | } | 53 | } |
54 | 54 | ||
55 | void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask); | 55 | void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); |
56 | void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask); | 56 | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); |
57 | 57 | ||
58 | int iwl_poll_bit(struct iwl_bus *bus, u32 addr, | 58 | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, |
59 | u32 bits, u32 mask, int timeout); | 59 | u32 bits, u32 mask, int timeout); |
60 | int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, | 60 | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, |
61 | int timeout); | 61 | int timeout); |
62 | 62 | ||
63 | int iwl_grab_nic_access_silent(struct iwl_bus *bus); | 63 | int iwl_grab_nic_access_silent(struct iwl_trans *trans); |
64 | int iwl_grab_nic_access(struct iwl_bus *bus); | 64 | int iwl_grab_nic_access(struct iwl_trans *trans); |
65 | void iwl_release_nic_access(struct iwl_bus *bus); | 65 | void iwl_release_nic_access(struct iwl_trans *trans); |
66 | 66 | ||
67 | u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg); | 67 | u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg); |
68 | void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value); | 68 | void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); |
69 | 69 | ||
70 | 70 | ||
71 | u32 iwl_read_prph(struct iwl_bus *bus, u32 reg); | 71 | u32 iwl_read_prph(struct iwl_trans *trans, u32 reg); |
72 | void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val); | 72 | void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val); |
73 | void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); | 73 | void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask); |
74 | void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, | 74 | void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg, |
75 | u32 bits, u32 mask); | 75 | u32 bits, u32 mask); |
76 | void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); | 76 | void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask); |
77 | 77 | ||
78 | void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, | 78 | void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, |
79 | void *buf, int words); | 79 | void *buf, int words); |
80 | 80 | ||
81 | #define iwl_read_targ_mem_words(bus, addr, buf, bufsize) \ | 81 | #define iwl_read_targ_mem_words(trans, addr, buf, bufsize) \ |
82 | do { \ | 82 | do { \ |
83 | BUILD_BUG_ON((bufsize) % sizeof(u32)); \ | 83 | BUILD_BUG_ON((bufsize) % sizeof(u32)); \ |
84 | _iwl_read_targ_mem_words(bus, addr, buf, \ | 84 | _iwl_read_targ_mem_words(trans, addr, buf, \ |
85 | (bufsize) / sizeof(u32));\ | 85 | (bufsize) / sizeof(u32));\ |
86 | } while (0) | 86 | } while (0) |
87 | 87 | ||
88 | int _iwl_write_targ_mem_words(struct iwl_bus *bus, u32 addr, | 88 | int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, |
89 | void *buf, int words); | 89 | void *buf, int words); |
90 | 90 | ||
91 | u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr); | 91 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr); |
92 | int iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val); | 92 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val); |
93 | #endif | 93 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 8761438f1532..5c7741f07aa0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -71,7 +71,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { | |||
71 | /* Set led register off */ | 71 | /* Set led register off */ |
72 | void iwlagn_led_enable(struct iwl_priv *priv) | 72 | void iwlagn_led_enable(struct iwl_priv *priv) |
73 | { | 73 | { |
74 | iwl_write32(bus(priv), CSR_LED_REG, CSR_LED_REG_TRUN_ON); | 74 | iwl_write32(trans(priv), CSR_LED_REG, CSR_LED_REG_TRUN_ON); |
75 | } | 75 | } |
76 | 76 | ||
77 | /* | 77 | /* |
@@ -107,9 +107,10 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) | |||
107 | }; | 107 | }; |
108 | u32 reg; | 108 | u32 reg; |
109 | 109 | ||
110 | reg = iwl_read32(bus(priv), CSR_LED_REG); | 110 | reg = iwl_read32(trans(priv), CSR_LED_REG); |
111 | if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) | 111 | if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) |
112 | iwl_write32(bus(priv), CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); | 112 | iwl_write32(trans(priv), CSR_LED_REG, |
113 | reg & CSR_LED_BSM_CTRL_MSK); | ||
113 | 114 | ||
114 | return iwl_trans_send_cmd(trans(priv), &cmd); | 115 | return iwl_trans_send_cmd(trans(priv), &cmd); |
115 | } | 116 | } |
@@ -206,7 +207,7 @@ void iwl_leds_init(struct iwl_priv *priv) | |||
206 | break; | 207 | break; |
207 | } | 208 | } |
208 | 209 | ||
209 | ret = led_classdev_register(bus(priv)->dev, &priv->led); | 210 | ret = led_classdev_register(trans(priv)->dev, &priv->led); |
210 | if (ret) { | 211 | if (ret) { |
211 | kfree(priv->led.name); | 212 | kfree(priv->led.name); |
212 | return; | 213 | return; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 965d0475affd..d8025fee7e0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/skbuff.h> | 36 | #include <linux/skbuff.h> |
37 | #include <linux/netdevice.h> | 37 | #include <linux/netdevice.h> |
38 | #include <linux/firmware.h> | ||
39 | #include <linux/etherdevice.h> | 38 | #include <linux/etherdevice.h> |
40 | #include <linux/if_arp.h> | 39 | #include <linux/if_arp.h> |
41 | 40 | ||
@@ -43,6 +42,7 @@ | |||
43 | 42 | ||
44 | #include <asm/div64.h> | 43 | #include <asm/div64.h> |
45 | 44 | ||
45 | #include "iwl-ucode.h" | ||
46 | #include "iwl-eeprom.h" | 46 | #include "iwl-eeprom.h" |
47 | #include "iwl-wifi.h" | 47 | #include "iwl-wifi.h" |
48 | #include "iwl-dev.h" | 48 | #include "iwl-dev.h" |
@@ -196,7 +196,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
196 | WIPHY_FLAG_IBSS_RSN; | 196 | WIPHY_FLAG_IBSS_RSN; |
197 | 197 | ||
198 | if (trans(priv)->ucode_wowlan.code.len && | 198 | if (trans(priv)->ucode_wowlan.code.len && |
199 | device_can_wakeup(bus(priv)->dev)) { | 199 | device_can_wakeup(trans(priv)->dev)) { |
200 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | | 200 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | |
201 | WIPHY_WOWLAN_DISCONNECT | | 201 | WIPHY_WOWLAN_DISCONNECT | |
202 | WIPHY_WOWLAN_EAP_IDENTITY_REQ | | 202 | WIPHY_WOWLAN_EAP_IDENTITY_REQ | |
@@ -234,7 +234,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
234 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 234 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
235 | &priv->bands[IEEE80211_BAND_5GHZ]; | 235 | &priv->bands[IEEE80211_BAND_5GHZ]; |
236 | 236 | ||
237 | hw->wiphy->hw_version = bus_get_hw_id(bus(priv)); | 237 | hw->wiphy->hw_version = trans(priv)->hw_id; |
238 | 238 | ||
239 | iwl_leds_init(priv); | 239 | iwl_leds_init(priv); |
240 | 240 | ||
@@ -346,9 +346,10 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) | |||
346 | flush_workqueue(priv->shrd->workqueue); | 346 | flush_workqueue(priv->shrd->workqueue); |
347 | 347 | ||
348 | /* User space software may expect getting rfkill changes | 348 | /* User space software may expect getting rfkill changes |
349 | * even if interface is down */ | 349 | * even if interface is down, trans->down will leave the RF |
350 | iwl_write32(bus(priv), CSR_INT, 0xFFFFFFFF); | 350 | * kill interrupt enabled |
351 | iwl_enable_rfkill_int(priv); | 351 | */ |
352 | iwl_trans_stop_hw(trans(priv)); | ||
352 | 353 | ||
353 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 354 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
354 | } | 355 | } |
@@ -405,10 +406,10 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, | |||
405 | if (ret) | 406 | if (ret) |
406 | goto error; | 407 | goto error; |
407 | 408 | ||
408 | device_set_wakeup_enable(bus(priv)->dev, true); | 409 | device_set_wakeup_enable(trans(priv)->dev, true); |
409 | 410 | ||
410 | /* Now let the ucode operate on its own */ | 411 | /* Now let the ucode operate on its own */ |
411 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, | 412 | iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET, |
412 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | 413 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); |
413 | 414 | ||
414 | goto out; | 415 | goto out; |
@@ -436,19 +437,19 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
436 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 437 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
437 | mutex_lock(&priv->shrd->mutex); | 438 | mutex_lock(&priv->shrd->mutex); |
438 | 439 | ||
439 | iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, | 440 | iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, |
440 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | 441 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); |
441 | 442 | ||
442 | base = priv->shrd->device_pointers.error_event_table; | 443 | base = priv->shrd->device_pointers.error_event_table; |
443 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 444 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
444 | spin_lock_irqsave(&bus(priv)->reg_lock, flags); | 445 | spin_lock_irqsave(&trans(priv)->reg_lock, flags); |
445 | ret = iwl_grab_nic_access_silent(bus(priv)); | 446 | ret = iwl_grab_nic_access_silent(trans(priv)); |
446 | if (ret == 0) { | 447 | if (ret == 0) { |
447 | iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, base); | 448 | iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, base); |
448 | status = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); | 449 | status = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); |
449 | iwl_release_nic_access(bus(priv)); | 450 | iwl_release_nic_access(trans(priv)); |
450 | } | 451 | } |
451 | spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); | 452 | spin_unlock_irqrestore(&trans(priv)->reg_lock, flags); |
452 | 453 | ||
453 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 454 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
454 | if (ret == 0) { | 455 | if (ret == 0) { |
@@ -460,7 +461,8 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
460 | 461 | ||
461 | if (priv->wowlan_sram) | 462 | if (priv->wowlan_sram) |
462 | _iwl_read_targ_mem_words( | 463 | _iwl_read_targ_mem_words( |
463 | bus(priv), 0x800000, priv->wowlan_sram, | 464 | trans(priv), 0x800000, |
465 | priv->wowlan_sram, | ||
464 | trans->ucode_wowlan.data.len / 4); | 466 | trans->ucode_wowlan.data.len / 4); |
465 | } | 467 | } |
466 | #endif | 468 | #endif |
@@ -471,7 +473,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
471 | 473 | ||
472 | priv->shrd->wowlan = false; | 474 | priv->shrd->wowlan = false; |
473 | 475 | ||
474 | device_set_wakeup_enable(bus(priv)->dev, false); | 476 | device_set_wakeup_enable(trans(priv)->dev, false); |
475 | 477 | ||
476 | iwlagn_prepare_restart(priv); | 478 | iwlagn_prepare_restart(priv); |
477 | 479 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 03702a2e913a..3e2fce4ce00c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c | |||
@@ -71,112 +71,6 @@ | |||
71 | #include "iwl-csr.h" | 71 | #include "iwl-csr.h" |
72 | #include "iwl-cfg.h" | 72 | #include "iwl-cfg.h" |
73 | 73 | ||
74 | /* PCI registers */ | ||
75 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | ||
76 | #define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 | ||
77 | #define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 | ||
78 | |||
79 | struct iwl_pci_bus { | ||
80 | /* basic pci-network driver stuff */ | ||
81 | struct pci_dev *pci_dev; | ||
82 | |||
83 | /* pci hardware address support */ | ||
84 | void __iomem *hw_base; | ||
85 | }; | ||
86 | |||
87 | #define IWL_BUS_GET_PCI_BUS(_iwl_bus) \ | ||
88 | ((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific)) | ||
89 | |||
90 | #define IWL_BUS_GET_PCI_DEV(_iwl_bus) \ | ||
91 | ((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev) | ||
92 | |||
93 | static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus) | ||
94 | { | ||
95 | int pos; | ||
96 | u16 pci_lnk_ctl; | ||
97 | |||
98 | struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); | ||
99 | |||
100 | pos = pci_pcie_cap(pci_dev); | ||
101 | pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); | ||
102 | return pci_lnk_ctl; | ||
103 | } | ||
104 | |||
105 | static bool iwl_pci_is_pm_supported(struct iwl_bus *bus) | ||
106 | { | ||
107 | u16 lctl = iwl_pciexp_link_ctrl(bus); | ||
108 | |||
109 | return !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); | ||
110 | } | ||
111 | |||
112 | static void iwl_pci_apm_config(struct iwl_bus *bus) | ||
113 | { | ||
114 | /* | ||
115 | * HW bug W/A for instability in PCIe bus L0S->L1 transition. | ||
116 | * Check if BIOS (or OS) enabled L1-ASPM on this device. | ||
117 | * If so (likely), disable L0S, so device moves directly L0->L1; | ||
118 | * costs negligible amount of power savings. | ||
119 | * If not (unlikely), enable L0S, so there is at least some | ||
120 | * power savings, even without L1. | ||
121 | */ | ||
122 | u16 lctl = iwl_pciexp_link_ctrl(bus); | ||
123 | |||
124 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == | ||
125 | PCI_CFG_LINK_CTRL_VAL_L1_EN) { | ||
126 | /* L1-ASPM enabled; disable(!) L0S */ | ||
127 | iwl_set_bit(bus, CSR_GIO_REG, | ||
128 | CSR_GIO_REG_VAL_L0S_ENABLED); | ||
129 | dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n"); | ||
130 | } else { | ||
131 | /* L1-ASPM disabled; enable(!) L0S */ | ||
132 | iwl_clear_bit(bus, CSR_GIO_REG, | ||
133 | CSR_GIO_REG_VAL_L0S_ENABLED); | ||
134 | dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n"); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | static void iwl_pci_get_hw_id_string(struct iwl_bus *bus, char buf[], | ||
139 | int buf_len) | ||
140 | { | ||
141 | struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); | ||
142 | |||
143 | snprintf(buf, buf_len, "PCI ID: 0x%04X:0x%04X", pci_dev->device, | ||
144 | pci_dev->subsystem_device); | ||
145 | } | ||
146 | |||
147 | static u32 iwl_pci_get_hw_id(struct iwl_bus *bus) | ||
148 | { | ||
149 | struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); | ||
150 | |||
151 | return (pci_dev->device << 16) + pci_dev->subsystem_device; | ||
152 | } | ||
153 | |||
154 | static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val) | ||
155 | { | ||
156 | iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); | ||
157 | } | ||
158 | |||
159 | static void iwl_pci_write32(struct iwl_bus *bus, u32 ofs, u32 val) | ||
160 | { | ||
161 | iowrite32(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); | ||
162 | } | ||
163 | |||
164 | static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs) | ||
165 | { | ||
166 | u32 val = ioread32(IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); | ||
167 | return val; | ||
168 | } | ||
169 | |||
170 | static const struct iwl_bus_ops bus_ops_pci = { | ||
171 | .get_pm_support = iwl_pci_is_pm_supported, | ||
172 | .apm_config = iwl_pci_apm_config, | ||
173 | .get_hw_id_string = iwl_pci_get_hw_id_string, | ||
174 | .get_hw_id = iwl_pci_get_hw_id, | ||
175 | .write8 = iwl_pci_write8, | ||
176 | .write32 = iwl_pci_write32, | ||
177 | .read32 = iwl_pci_read32, | ||
178 | }; | ||
179 | |||
180 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | 74 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ |
181 | .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ | 75 | .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ |
182 | .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ | 76 | .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ |
@@ -362,112 +256,61 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
362 | }; | 256 | }; |
363 | MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); | 257 | MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); |
364 | 258 | ||
259 | /* PCI registers */ | ||
260 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | ||
261 | |||
365 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 262 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
366 | { | 263 | { |
367 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | 264 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); |
368 | struct iwl_bus *bus; | 265 | struct iwl_bus *bus; |
369 | struct iwl_pci_bus *pci_bus; | ||
370 | u16 pci_cmd; | ||
371 | int err; | 266 | int err; |
372 | 267 | ||
373 | bus = kzalloc(sizeof(*bus) + sizeof(*pci_bus), GFP_KERNEL); | 268 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); |
374 | if (!bus) { | 269 | if (!bus) { |
375 | dev_printk(KERN_ERR, &pdev->dev, | 270 | dev_printk(KERN_ERR, &pdev->dev, |
376 | "Couldn't allocate iwl_pci_bus"); | 271 | "Couldn't allocate iwl_pci_bus"); |
377 | err = -ENOMEM; | 272 | return -ENOMEM; |
378 | goto out_no_pci; | ||
379 | } | 273 | } |
380 | 274 | ||
381 | pci_bus = IWL_BUS_GET_PCI_BUS(bus); | 275 | bus->shrd = kzalloc(sizeof(*bus->shrd), GFP_KERNEL); |
382 | pci_bus->pci_dev = pdev; | 276 | if (!bus->shrd) { |
383 | 277 | dev_printk(KERN_ERR, &pdev->dev, | |
384 | pci_set_drvdata(pdev, bus); | 278 | "Couldn't allocate iwl_shared"); |
385 | 279 | err = -ENOMEM; | |
386 | /* W/A - seems to solve weird behavior. We need to remove this if we | 280 | goto out_free_bus; |
387 | * don't want to stay in L1 all the time. This wastes a lot of power */ | ||
388 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | ||
389 | PCIE_LINK_STATE_CLKPM); | ||
390 | |||
391 | if (pci_enable_device(pdev)) { | ||
392 | err = -ENODEV; | ||
393 | goto out_no_pci; | ||
394 | } | 281 | } |
395 | 282 | ||
396 | pci_set_master(pdev); | 283 | bus->shrd->bus = bus; |
397 | |||
398 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); | ||
399 | if (!err) | ||
400 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); | ||
401 | if (err) { | ||
402 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
403 | if (!err) | ||
404 | err = pci_set_consistent_dma_mask(pdev, | ||
405 | DMA_BIT_MASK(32)); | ||
406 | /* both attempts failed: */ | ||
407 | if (err) { | ||
408 | dev_printk(KERN_ERR, bus->dev, | ||
409 | "No suitable DMA available.\n"); | ||
410 | goto out_pci_disable_device; | ||
411 | } | ||
412 | } | ||
413 | 284 | ||
414 | err = pci_request_regions(pdev, DRV_NAME); | 285 | pci_set_drvdata(pdev, bus); |
415 | if (err) { | ||
416 | dev_printk(KERN_ERR, bus->dev, "pci_request_regions failed"); | ||
417 | goto out_pci_disable_device; | ||
418 | } | ||
419 | 286 | ||
420 | pci_bus->hw_base = pci_iomap(pdev, 0, 0); | 287 | #ifdef CONFIG_IWLWIFI_IDI |
421 | if (!pci_bus->hw_base) { | 288 | trans(bus) = iwl_trans_idi_alloc(bus->shrd, pdev, ent); |
422 | dev_printk(KERN_ERR, bus->dev, "pci_iomap failed"); | 289 | if (trans(bus) == NULL) { |
423 | err = -ENODEV; | 290 | err = -ENOMEM; |
424 | goto out_pci_release_regions; | 291 | goto out_free_bus; |
425 | } | 292 | } |
426 | 293 | ||
427 | dev_printk(KERN_INFO, &pdev->dev, | 294 | err = iwl_probe(bus, &trans_ops_idi, cfg); |
428 | "pci_resource_len = 0x%08llx\n", | 295 | #else |
429 | (unsigned long long) pci_resource_len(pdev, 0)); | 296 | trans(bus) = iwl_trans_pcie_alloc(bus->shrd, pdev, ent); |
430 | dev_printk(KERN_INFO, &pdev->dev, | 297 | if (trans(bus) == NULL) { |
431 | "pci_resource_base = %p\n", pci_bus->hw_base); | 298 | err = -ENOMEM; |
432 | 299 | goto out_free_bus; | |
433 | dev_printk(KERN_INFO, &pdev->dev, | ||
434 | "HW Revision ID = 0x%X\n", pdev->revision); | ||
435 | |||
436 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | ||
437 | * PCI Tx retries from interfering with C3 CPU state */ | ||
438 | pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); | ||
439 | |||
440 | err = pci_enable_msi(pdev); | ||
441 | if (err) | ||
442 | dev_printk(KERN_ERR, &pdev->dev, | ||
443 | "pci_enable_msi failed(0X%x)", err); | ||
444 | |||
445 | /* TODO: Move this away, not needed if not MSI */ | ||
446 | /* enable rfkill interrupt: hw bug w/a */ | ||
447 | pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); | ||
448 | if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { | ||
449 | pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; | ||
450 | pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); | ||
451 | } | 300 | } |
452 | 301 | ||
453 | bus->dev = &pdev->dev; | ||
454 | bus->irq = pdev->irq; | ||
455 | bus->ops = &bus_ops_pci; | ||
456 | |||
457 | err = iwl_probe(bus, &trans_ops_pcie, cfg); | 302 | err = iwl_probe(bus, &trans_ops_pcie, cfg); |
303 | #endif | ||
458 | if (err) | 304 | if (err) |
459 | goto out_disable_msi; | 305 | goto out_free_trans; |
306 | |||
460 | return 0; | 307 | return 0; |
461 | 308 | ||
462 | out_disable_msi: | 309 | out_free_trans: |
463 | pci_disable_msi(pdev); | 310 | iwl_trans_free(trans(bus)); |
464 | pci_iounmap(pdev, pci_bus->hw_base); | ||
465 | out_pci_release_regions: | ||
466 | pci_set_drvdata(pdev, NULL); | 311 | pci_set_drvdata(pdev, NULL); |
467 | pci_release_regions(pdev); | 312 | out_free_bus: |
468 | out_pci_disable_device: | 313 | kfree(bus->shrd); |
469 | pci_disable_device(pdev); | ||
470 | out_no_pci: | ||
471 | kfree(bus); | 314 | kfree(bus); |
472 | return err; | 315 | return err; |
473 | } | 316 | } |
@@ -475,18 +318,14 @@ out_no_pci: | |||
475 | static void __devexit iwl_pci_remove(struct pci_dev *pdev) | 318 | static void __devexit iwl_pci_remove(struct pci_dev *pdev) |
476 | { | 319 | { |
477 | struct iwl_bus *bus = pci_get_drvdata(pdev); | 320 | struct iwl_bus *bus = pci_get_drvdata(pdev); |
478 | struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus); | ||
479 | struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); | ||
480 | struct iwl_shared *shrd = bus->shrd; | 321 | struct iwl_shared *shrd = bus->shrd; |
481 | 322 | ||
482 | iwl_remove(shrd->priv); | 323 | iwl_remove(shrd->priv); |
324 | iwl_trans_free(shrd->trans); | ||
483 | 325 | ||
484 | pci_disable_msi(pci_dev); | 326 | pci_set_drvdata(pdev, NULL); |
485 | pci_iounmap(pci_dev, pci_bus->hw_base); | ||
486 | pci_release_regions(pci_dev); | ||
487 | pci_disable_device(pci_dev); | ||
488 | pci_set_drvdata(pci_dev, NULL); | ||
489 | 327 | ||
328 | kfree(bus->shrd); | ||
490 | kfree(bus); | 329 | kfree(bus); |
491 | } | 330 | } |
492 | 331 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index c7394ef2e490..fd008c4e41fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -436,7 +436,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
436 | /* initialize to default */ | 436 | /* initialize to default */ |
437 | void iwl_power_initialize(struct iwl_priv *priv) | 437 | void iwl_power_initialize(struct iwl_priv *priv) |
438 | { | 438 | { |
439 | priv->power_data.bus_pm = bus_get_pm_support(bus(priv)); | 439 | priv->power_data.bus_pm = trans(priv)->pm_support; |
440 | 440 | ||
441 | priv->power_data.debug_sleep_level_override = -1; | 441 | priv->power_data.debug_sleep_level_override = -1; |
442 | 442 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 04975b7b65b3..63d4a4fc5b9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h | |||
@@ -543,8 +543,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); | |||
543 | void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state); | 543 | void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state); |
544 | void iwl_nic_config(struct iwl_priv *priv); | 544 | void iwl_nic_config(struct iwl_priv *priv); |
545 | void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb); | 545 | void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb); |
546 | void iwl_apm_stop(struct iwl_priv *priv); | ||
547 | int iwl_apm_init(struct iwl_priv *priv); | ||
548 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); | 546 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); |
549 | const char *get_cmd_string(u8 cmd); | 547 | const char *get_cmd_string(u8 cmd); |
550 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); | 548 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index a56a77b8f926..df7ab332c833 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c | |||
@@ -79,6 +79,7 @@ | |||
79 | #include "iwl-testmode.h" | 79 | #include "iwl-testmode.h" |
80 | #include "iwl-trans.h" | 80 | #include "iwl-trans.h" |
81 | #include "iwl-bus.h" | 81 | #include "iwl-bus.h" |
82 | #include "iwl-fh.h" | ||
82 | 83 | ||
83 | /* The TLVs used in the gnl message policy between the kernel module and | 84 | /* The TLVs used in the gnl message policy between the kernel module and |
84 | * user space application. iwl_testmode_gnl_msg_policy is to be carried | 85 | * user space application. iwl_testmode_gnl_msg_policy is to be carried |
@@ -208,7 +209,7 @@ static void iwl_trace_cleanup(struct iwl_priv *priv) | |||
208 | if (priv->testmode_trace.trace_enabled) { | 209 | if (priv->testmode_trace.trace_enabled) { |
209 | if (priv->testmode_trace.cpu_addr && | 210 | if (priv->testmode_trace.cpu_addr && |
210 | priv->testmode_trace.dma_addr) | 211 | priv->testmode_trace.dma_addr) |
211 | dma_free_coherent(bus(priv)->dev, | 212 | dma_free_coherent(trans(priv)->dev, |
212 | priv->testmode_trace.total_size, | 213 | priv->testmode_trace.total_size, |
213 | priv->testmode_trace.cpu_addr, | 214 | priv->testmode_trace.cpu_addr, |
214 | priv->testmode_trace.dma_addr); | 215 | priv->testmode_trace.dma_addr); |
@@ -288,7 +289,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) | |||
288 | static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) | 289 | static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) |
289 | { | 290 | { |
290 | struct iwl_priv *priv = hw->priv; | 291 | struct iwl_priv *priv = hw->priv; |
291 | u32 ofs, val32; | 292 | u32 ofs, val32, cmd; |
292 | u8 val8; | 293 | u8 val8; |
293 | struct sk_buff *skb; | 294 | struct sk_buff *skb; |
294 | int status = 0; | 295 | int status = 0; |
@@ -300,9 +301,22 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) | |||
300 | ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); | 301 | ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); |
301 | IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs); | 302 | IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs); |
302 | 303 | ||
303 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | 304 | /* Allow access only to FH/CSR/HBUS in direct mode. |
305 | Since we don't have the upper bounds for the CSR and HBUS segments, | ||
306 | we will use only the upper bound of FH for sanity check. */ | ||
307 | cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); | ||
308 | if ((cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32 || | ||
309 | cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 || | ||
310 | cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8) && | ||
311 | (ofs >= FH_MEM_UPPER_BOUND)) { | ||
312 | IWL_DEBUG_INFO(priv, "offset out of segment (0x0 - 0x%x)\n", | ||
313 | FH_MEM_UPPER_BOUND); | ||
314 | return -EINVAL; | ||
315 | } | ||
316 | |||
317 | switch (cmd) { | ||
304 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: | 318 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: |
305 | val32 = iwl_read_direct32(bus(priv), ofs); | 319 | val32 = iwl_read_direct32(trans(priv), ofs); |
306 | IWL_INFO(priv, "32bit value to read 0x%x\n", val32); | 320 | IWL_INFO(priv, "32bit value to read 0x%x\n", val32); |
307 | 321 | ||
308 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); | 322 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); |
@@ -324,7 +338,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) | |||
324 | } else { | 338 | } else { |
325 | val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); | 339 | val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); |
326 | IWL_INFO(priv, "32bit value to write 0x%x\n", val32); | 340 | IWL_INFO(priv, "32bit value to write 0x%x\n", val32); |
327 | iwl_write_direct32(bus(priv), ofs, val32); | 341 | iwl_write_direct32(trans(priv), ofs, val32); |
328 | } | 342 | } |
329 | break; | 343 | break; |
330 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: | 344 | case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: |
@@ -334,11 +348,11 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) | |||
334 | } else { | 348 | } else { |
335 | val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); | 349 | val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); |
336 | IWL_INFO(priv, "8bit value to write 0x%x\n", val8); | 350 | IWL_INFO(priv, "8bit value to write 0x%x\n", val8); |
337 | iwl_write8(bus(priv), ofs, val8); | 351 | iwl_write8(trans(priv), ofs, val8); |
338 | } | 352 | } |
339 | break; | 353 | break; |
340 | case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: | 354 | case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: |
341 | val32 = iwl_read_prph(bus(priv), ofs); | 355 | val32 = iwl_read_prph(trans(priv), ofs); |
342 | IWL_INFO(priv, "32bit value to read 0x%x\n", val32); | 356 | IWL_INFO(priv, "32bit value to read 0x%x\n", val32); |
343 | 357 | ||
344 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); | 358 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); |
@@ -360,7 +374,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) | |||
360 | } else { | 374 | } else { |
361 | val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); | 375 | val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); |
362 | IWL_INFO(priv, "32bit value to write 0x%x\n", val32); | 376 | IWL_INFO(priv, "32bit value to write 0x%x\n", val32); |
363 | iwl_write_prph(bus(priv), ofs, val32); | 377 | iwl_write_prph(trans(priv), ofs, val32); |
364 | } | 378 | } |
365 | break; | 379 | break; |
366 | default: | 380 | default: |
@@ -536,7 +550,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
536 | break; | 550 | break; |
537 | 551 | ||
538 | case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: | 552 | case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: |
539 | devid = bus_get_hw_id(bus(priv)); | 553 | devid = trans(priv)->hw_id; |
540 | IWL_INFO(priv, "hw version: 0x%x\n", devid); | 554 | IWL_INFO(priv, "hw version: 0x%x\n", devid); |
541 | 555 | ||
542 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); | 556 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); |
@@ -615,7 +629,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) | |||
615 | struct iwl_priv *priv = hw->priv; | 629 | struct iwl_priv *priv = hw->priv; |
616 | struct sk_buff *skb; | 630 | struct sk_buff *skb; |
617 | int status = 0; | 631 | int status = 0; |
618 | struct device *dev = bus(priv)->dev; | 632 | struct device *dev = trans(priv)->dev; |
619 | 633 | ||
620 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | 634 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { |
621 | case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: | 635 | case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: |
@@ -814,7 +828,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) | |||
814 | IWL_ERR(priv, "Error allocating memory\n"); | 828 | IWL_ERR(priv, "Error allocating memory\n"); |
815 | return -ENOMEM; | 829 | return -ENOMEM; |
816 | } | 830 | } |
817 | _iwl_read_targ_mem_words(bus(priv), ofs, | 831 | _iwl_read_targ_mem_words(trans(priv), ofs, |
818 | priv->testmode_sram.buff_addr, | 832 | priv->testmode_sram.buff_addr, |
819 | priv->testmode_sram.buff_size / 4); | 833 | priv->testmode_sram.buff_size / 4); |
820 | priv->testmode_sram.num_chunks = | 834 | priv->testmode_sram.num_chunks = |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 0ac9b4d30271..561865f29d56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | |||
@@ -201,6 +201,7 @@ struct iwl_tx_queue { | |||
201 | * @rxq: all the RX queue data | 201 | * @rxq: all the RX queue data |
202 | * @rx_replenish: work that will be called when buffers need to be allocated | 202 | * @rx_replenish: work that will be called when buffers need to be allocated |
203 | * @trans: pointer to the generic transport area | 203 | * @trans: pointer to the generic transport area |
204 | * @irq_requested: true when the irq has been requested | ||
204 | * @scd_base_addr: scheduler sram base address in SRAM | 205 | * @scd_base_addr: scheduler sram base address in SRAM |
205 | * @scd_bc_tbls: pointer to the byte count table of the scheduler | 206 | * @scd_bc_tbls: pointer to the byte count table of the scheduler |
206 | * @kw: keep warm address | 207 | * @kw: keep warm address |
@@ -211,6 +212,8 @@ struct iwl_tx_queue { | |||
211 | * @txq_ctx_active_msk: what queue is active | 212 | * @txq_ctx_active_msk: what queue is active |
212 | * queue_stopped: tracks what queue is stopped | 213 | * queue_stopped: tracks what queue is stopped |
213 | * queue_stop_count: tracks what SW queue is stopped | 214 | * queue_stop_count: tracks what SW queue is stopped |
215 | * @pci_dev: basic pci-network driver stuff | ||
216 | * @hw_base: pci hardware address support | ||
214 | */ | 217 | */ |
215 | struct iwl_trans_pcie { | 218 | struct iwl_trans_pcie { |
216 | struct iwl_rx_queue rxq; | 219 | struct iwl_rx_queue rxq; |
@@ -223,6 +226,7 @@ struct iwl_trans_pcie { | |||
223 | int ict_index; | 226 | int ict_index; |
224 | u32 inta; | 227 | u32 inta; |
225 | bool use_ict; | 228 | bool use_ict; |
229 | bool irq_requested; | ||
226 | struct tasklet_struct irq_tasklet; | 230 | struct tasklet_struct irq_tasklet; |
227 | struct isr_statistics isr_stats; | 231 | struct isr_statistics isr_stats; |
228 | 232 | ||
@@ -241,6 +245,10 @@ struct iwl_trans_pcie { | |||
241 | #define IWL_MAX_HW_QUEUES 32 | 245 | #define IWL_MAX_HW_QUEUES 32 |
242 | unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; | 246 | unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; |
243 | atomic_t queue_stop_count[4]; | 247 | atomic_t queue_stop_count[4]; |
248 | |||
249 | /* PCI bus related data */ | ||
250 | struct pci_dev *pci_dev; | ||
251 | void __iomem *hw_base; | ||
244 | }; | 252 | }; |
245 | 253 | ||
246 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 254 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
@@ -258,7 +266,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | |||
258 | /***************************************************** | 266 | /***************************************************** |
259 | * ICT | 267 | * ICT |
260 | ******************************************************/ | 268 | ******************************************************/ |
261 | int iwl_reset_ict(struct iwl_trans *trans); | 269 | void iwl_reset_ict(struct iwl_trans *trans); |
262 | void iwl_disable_ict(struct iwl_trans *trans); | 270 | void iwl_disable_ict(struct iwl_trans *trans); |
263 | int iwl_alloc_isr_ict(struct iwl_trans *trans); | 271 | int iwl_alloc_isr_ict(struct iwl_trans *trans); |
264 | void iwl_free_isr_ict(struct iwl_trans *trans); | 272 | void iwl_free_isr_ict(struct iwl_trans *trans); |
@@ -311,12 +319,12 @@ static inline void iwl_disable_interrupts(struct iwl_trans *trans) | |||
311 | clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); | 319 | clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); |
312 | 320 | ||
313 | /* disable interrupts from uCode/NIC to host */ | 321 | /* disable interrupts from uCode/NIC to host */ |
314 | iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); | 322 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); |
315 | 323 | ||
316 | /* acknowledge/clear/reset any interrupts still pending | 324 | /* acknowledge/clear/reset any interrupts still pending |
317 | * from uCode or flow handler (Rx/Tx DMA) */ | 325 | * from uCode or flow handler (Rx/Tx DMA) */ |
318 | iwl_write32(bus(trans), CSR_INT, 0xffffffff); | 326 | iwl_write32(trans, CSR_INT, 0xffffffff); |
319 | iwl_write32(bus(trans), CSR_FH_INT_STATUS, 0xffffffff); | 327 | iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff); |
320 | IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); | 328 | IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); |
321 | } | 329 | } |
322 | 330 | ||
@@ -327,7 +335,7 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) | |||
327 | 335 | ||
328 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); | 336 | IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); |
329 | set_bit(STATUS_INT_ENABLED, &trans->shrd->status); | 337 | set_bit(STATUS_INT_ENABLED, &trans->shrd->status); |
330 | iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask); | 338 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); |
331 | } | 339 | } |
332 | 340 | ||
333 | /* | 341 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 2900db973aaa..3826852ec5f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | |||
@@ -35,6 +35,10 @@ | |||
35 | #include "iwl-io.h" | 35 | #include "iwl-io.h" |
36 | #include "iwl-trans-pcie-int.h" | 36 | #include "iwl-trans-pcie-int.h" |
37 | 37 | ||
38 | #ifdef CONFIG_IWLWIFI_IDI | ||
39 | #include "iwl-amfh.h" | ||
40 | #endif | ||
41 | |||
38 | /****************************************************************************** | 42 | /****************************************************************************** |
39 | * | 43 | * |
40 | * RX path functions | 44 | * RX path functions |
@@ -140,30 +144,30 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | |||
140 | /* shadow register enabled */ | 144 | /* shadow register enabled */ |
141 | /* Device expects a multiple of 8 */ | 145 | /* Device expects a multiple of 8 */ |
142 | q->write_actual = (q->write & ~0x7); | 146 | q->write_actual = (q->write & ~0x7); |
143 | iwl_write32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual); | 147 | iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, q->write_actual); |
144 | } else { | 148 | } else { |
145 | /* If power-saving is in use, make sure device is awake */ | 149 | /* If power-saving is in use, make sure device is awake */ |
146 | if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { | 150 | if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { |
147 | reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); | 151 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); |
148 | 152 | ||
149 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 153 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
150 | IWL_DEBUG_INFO(trans, | 154 | IWL_DEBUG_INFO(trans, |
151 | "Rx queue requesting wakeup," | 155 | "Rx queue requesting wakeup," |
152 | " GP1 = 0x%x\n", reg); | 156 | " GP1 = 0x%x\n", reg); |
153 | iwl_set_bit(bus(trans), CSR_GP_CNTRL, | 157 | iwl_set_bit(trans, CSR_GP_CNTRL, |
154 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 158 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
155 | goto exit_unlock; | 159 | goto exit_unlock; |
156 | } | 160 | } |
157 | 161 | ||
158 | q->write_actual = (q->write & ~0x7); | 162 | q->write_actual = (q->write & ~0x7); |
159 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, | 163 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, |
160 | q->write_actual); | 164 | q->write_actual); |
161 | 165 | ||
162 | /* Else device is assumed to be awake */ | 166 | /* Else device is assumed to be awake */ |
163 | } else { | 167 | } else { |
164 | /* Device expects a multiple of 8 */ | 168 | /* Device expects a multiple of 8 */ |
165 | q->write_actual = (q->write & ~0x7); | 169 | q->write_actual = (q->write & ~0x7); |
166 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, | 170 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, |
167 | q->write_actual); | 171 | q->write_actual); |
168 | } | 172 | } |
169 | } | 173 | } |
@@ -308,7 +312,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
308 | BUG_ON(rxb->page); | 312 | BUG_ON(rxb->page); |
309 | rxb->page = page; | 313 | rxb->page = page; |
310 | /* Get physical address of the RB */ | 314 | /* Get physical address of the RB */ |
311 | rxb->page_dma = dma_map_page(bus(trans)->dev, page, 0, | 315 | rxb->page_dma = dma_map_page(trans->dev, page, 0, |
312 | PAGE_SIZE << hw_params(trans).rx_page_order, | 316 | PAGE_SIZE << hw_params(trans).rx_page_order, |
313 | DMA_FROM_DEVICE); | 317 | DMA_FROM_DEVICE); |
314 | /* dma address must be no more than 36 bits */ | 318 | /* dma address must be no more than 36 bits */ |
@@ -414,7 +418,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
414 | 418 | ||
415 | rxq->queue[i] = NULL; | 419 | rxq->queue[i] = NULL; |
416 | 420 | ||
417 | dma_unmap_page(bus(trans)->dev, rxb->page_dma, | 421 | dma_unmap_page(trans->dev, rxb->page_dma, |
418 | PAGE_SIZE << hw_params(trans).rx_page_order, | 422 | PAGE_SIZE << hw_params(trans).rx_page_order, |
419 | DMA_FROM_DEVICE); | 423 | DMA_FROM_DEVICE); |
420 | pkt = rxb_addr(rxb); | 424 | pkt = rxb_addr(rxb); |
@@ -485,7 +489,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
485 | * rx_free list for reuse later. */ | 489 | * rx_free list for reuse later. */ |
486 | spin_lock_irqsave(&rxq->lock, flags); | 490 | spin_lock_irqsave(&rxq->lock, flags); |
487 | if (rxb->page != NULL) { | 491 | if (rxb->page != NULL) { |
488 | rxb->page_dma = dma_map_page(bus(trans)->dev, rxb->page, | 492 | rxb->page_dma = dma_map_page(trans->dev, rxb->page, |
489 | 0, PAGE_SIZE << | 493 | 0, PAGE_SIZE << |
490 | hw_params(trans).rx_page_order, | 494 | hw_params(trans).rx_page_order, |
491 | DMA_FROM_DEVICE); | 495 | DMA_FROM_DEVICE); |
@@ -612,7 +616,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) | |||
612 | return; | 616 | return; |
613 | } | 617 | } |
614 | 618 | ||
615 | iwl_read_targ_mem_words(bus(priv), base, &table, sizeof(table)); | 619 | iwl_read_targ_mem_words(trans(priv), base, &table, sizeof(table)); |
616 | 620 | ||
617 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { | 621 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { |
618 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); | 622 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); |
@@ -673,9 +677,9 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) | |||
673 | struct iwl_priv *priv = priv(trans); | 677 | struct iwl_priv *priv = priv(trans); |
674 | /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ | 678 | /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ |
675 | if (cfg(priv)->internal_wimax_coex && | 679 | if (cfg(priv)->internal_wimax_coex && |
676 | (!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) & | 680 | (!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) & |
677 | APMS_CLK_VAL_MRB_FUNC_MODE) || | 681 | APMS_CLK_VAL_MRB_FUNC_MODE) || |
678 | (iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) & | 682 | (iwl_read_prph(trans, APMG_PS_CTRL_REG) & |
679 | APMG_PS_CTRL_VAL_RESET_REQ))) { | 683 | APMG_PS_CTRL_VAL_RESET_REQ))) { |
680 | /* | 684 | /* |
681 | * Keep the restart process from trying to send host | 685 | * Keep the restart process from trying to send host |
@@ -741,18 +745,18 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, | |||
741 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | 745 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); |
742 | 746 | ||
743 | /* Make sure device is powered up for SRAM reads */ | 747 | /* Make sure device is powered up for SRAM reads */ |
744 | spin_lock_irqsave(&bus(trans)->reg_lock, reg_flags); | 748 | spin_lock_irqsave(&trans->reg_lock, reg_flags); |
745 | iwl_grab_nic_access(bus(trans)); | 749 | iwl_grab_nic_access(trans); |
746 | 750 | ||
747 | /* Set starting address; reads will auto-increment */ | 751 | /* Set starting address; reads will auto-increment */ |
748 | iwl_write32(bus(trans), HBUS_TARG_MEM_RADDR, ptr); | 752 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); |
749 | rmb(); | 753 | rmb(); |
750 | 754 | ||
751 | /* "time" is actually "data" for mode 0 (no timestamp). | 755 | /* "time" is actually "data" for mode 0 (no timestamp). |
752 | * place event id # at far right for easier visual parsing. */ | 756 | * place event id # at far right for easier visual parsing. */ |
753 | for (i = 0; i < num_events; i++) { | 757 | for (i = 0; i < num_events; i++) { |
754 | ev = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT); | 758 | ev = iwl_read32(trans, HBUS_TARG_MEM_RDAT); |
755 | time = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT); | 759 | time = iwl_read32(trans, HBUS_TARG_MEM_RDAT); |
756 | if (mode == 0) { | 760 | if (mode == 0) { |
757 | /* data, ev */ | 761 | /* data, ev */ |
758 | if (bufsz) { | 762 | if (bufsz) { |
@@ -766,7 +770,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, | |||
766 | time, ev); | 770 | time, ev); |
767 | } | 771 | } |
768 | } else { | 772 | } else { |
769 | data = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT); | 773 | data = iwl_read32(trans, HBUS_TARG_MEM_RDAT); |
770 | if (bufsz) { | 774 | if (bufsz) { |
771 | pos += scnprintf(*buf + pos, bufsz - pos, | 775 | pos += scnprintf(*buf + pos, bufsz - pos, |
772 | "EVT_LOGT:%010u:0x%08x:%04u\n", | 776 | "EVT_LOGT:%010u:0x%08x:%04u\n", |
@@ -781,8 +785,8 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, | |||
781 | } | 785 | } |
782 | 786 | ||
783 | /* Allow device to power down */ | 787 | /* Allow device to power down */ |
784 | iwl_release_nic_access(bus(trans)); | 788 | iwl_release_nic_access(trans); |
785 | spin_unlock_irqrestore(&bus(trans)->reg_lock, reg_flags); | 789 | spin_unlock_irqrestore(&trans->reg_lock, reg_flags); |
786 | return pos; | 790 | return pos; |
787 | } | 791 | } |
788 | 792 | ||
@@ -859,10 +863,10 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, | |||
859 | } | 863 | } |
860 | 864 | ||
861 | /* event log header */ | 865 | /* event log header */ |
862 | capacity = iwl_read_targ_mem(bus(trans), base); | 866 | capacity = iwl_read_targ_mem(trans, base); |
863 | mode = iwl_read_targ_mem(bus(trans), base + (1 * sizeof(u32))); | 867 | mode = iwl_read_targ_mem(trans, base + (1 * sizeof(u32))); |
864 | num_wraps = iwl_read_targ_mem(bus(trans), base + (2 * sizeof(u32))); | 868 | num_wraps = iwl_read_targ_mem(trans, base + (2 * sizeof(u32))); |
865 | next_entry = iwl_read_targ_mem(bus(trans), base + (3 * sizeof(u32))); | 869 | next_entry = iwl_read_targ_mem(trans, base + (3 * sizeof(u32))); |
866 | 870 | ||
867 | if (capacity > logsize) { | 871 | if (capacity > logsize) { |
868 | IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " | 872 | IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " |
@@ -958,7 +962,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
958 | * hardware bugs here by ACKing all the possible interrupts so that | 962 | * hardware bugs here by ACKing all the possible interrupts so that |
959 | * interrupt coalescing can still be achieved. | 963 | * interrupt coalescing can still be achieved. |
960 | */ | 964 | */ |
961 | iwl_write32(bus(trans), CSR_INT, | 965 | iwl_write32(trans, CSR_INT, |
962 | trans_pcie->inta | ~trans_pcie->inta_mask); | 966 | trans_pcie->inta | ~trans_pcie->inta_mask); |
963 | 967 | ||
964 | inta = trans_pcie->inta; | 968 | inta = trans_pcie->inta; |
@@ -966,7 +970,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
966 | #ifdef CONFIG_IWLWIFI_DEBUG | 970 | #ifdef CONFIG_IWLWIFI_DEBUG |
967 | if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) { | 971 | if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) { |
968 | /* just for debug */ | 972 | /* just for debug */ |
969 | inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); | 973 | inta_mask = iwl_read32(trans, CSR_INT_MASK); |
970 | IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", | 974 | IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", |
971 | inta, inta_mask); | 975 | inta, inta_mask); |
972 | } | 976 | } |
@@ -1014,7 +1018,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
1014 | /* HW RF KILL switch toggled */ | 1018 | /* HW RF KILL switch toggled */ |
1015 | if (inta & CSR_INT_BIT_RF_KILL) { | 1019 | if (inta & CSR_INT_BIT_RF_KILL) { |
1016 | int hw_rf_kill = 0; | 1020 | int hw_rf_kill = 0; |
1017 | if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & | 1021 | if (!(iwl_read32(trans, CSR_GP_CNTRL) & |
1018 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) | 1022 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) |
1019 | hw_rf_kill = 1; | 1023 | hw_rf_kill = 1; |
1020 | 1024 | ||
@@ -1078,12 +1082,12 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
1078 | IWL_DEBUG_ISR(trans, "Rx interrupt\n"); | 1082 | IWL_DEBUG_ISR(trans, "Rx interrupt\n"); |
1079 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { | 1083 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { |
1080 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); | 1084 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); |
1081 | iwl_write32(bus(trans), CSR_FH_INT_STATUS, | 1085 | iwl_write32(trans, CSR_FH_INT_STATUS, |
1082 | CSR_FH_INT_RX_MASK); | 1086 | CSR_FH_INT_RX_MASK); |
1083 | } | 1087 | } |
1084 | if (inta & CSR_INT_BIT_RX_PERIODIC) { | 1088 | if (inta & CSR_INT_BIT_RX_PERIODIC) { |
1085 | handled |= CSR_INT_BIT_RX_PERIODIC; | 1089 | handled |= CSR_INT_BIT_RX_PERIODIC; |
1086 | iwl_write32(bus(trans), | 1090 | iwl_write32(trans, |
1087 | CSR_INT, CSR_INT_BIT_RX_PERIODIC); | 1091 | CSR_INT, CSR_INT_BIT_RX_PERIODIC); |
1088 | } | 1092 | } |
1089 | /* Sending RX interrupt require many steps to be done in the | 1093 | /* Sending RX interrupt require many steps to be done in the |
@@ -1098,10 +1102,13 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
1098 | */ | 1102 | */ |
1099 | 1103 | ||
1100 | /* Disable periodic interrupt; we use it as just a one-shot. */ | 1104 | /* Disable periodic interrupt; we use it as just a one-shot. */ |
1101 | iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, | 1105 | iwl_write8(trans, CSR_INT_PERIODIC_REG, |
1102 | CSR_INT_PERIODIC_DIS); | 1106 | CSR_INT_PERIODIC_DIS); |
1107 | #ifdef CONFIG_IWLWIFI_IDI | ||
1108 | iwl_amfh_rx_handler(); | ||
1109 | #else | ||
1103 | iwl_rx_handle(trans); | 1110 | iwl_rx_handle(trans); |
1104 | 1111 | #endif | |
1105 | /* | 1112 | /* |
1106 | * Enable periodic interrupt in 8 msec only if we received | 1113 | * Enable periodic interrupt in 8 msec only if we received |
1107 | * real RX interrupt (instead of just periodic int), to catch | 1114 | * real RX interrupt (instead of just periodic int), to catch |
@@ -1110,7 +1117,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
1110 | * to extend the periodic interrupt; one-shot is enough. | 1117 | * to extend the periodic interrupt; one-shot is enough. |
1111 | */ | 1118 | */ |
1112 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) | 1119 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) |
1113 | iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, | 1120 | iwl_write8(trans, CSR_INT_PERIODIC_REG, |
1114 | CSR_INT_PERIODIC_ENA); | 1121 | CSR_INT_PERIODIC_ENA); |
1115 | 1122 | ||
1116 | isr_stats->rx++; | 1123 | isr_stats->rx++; |
@@ -1118,7 +1125,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
1118 | 1125 | ||
1119 | /* This "Tx" DMA channel is used only for loading uCode */ | 1126 | /* This "Tx" DMA channel is used only for loading uCode */ |
1120 | if (inta & CSR_INT_BIT_FH_TX) { | 1127 | if (inta & CSR_INT_BIT_FH_TX) { |
1121 | iwl_write32(bus(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); | 1128 | iwl_write32(trans, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); |
1122 | IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); | 1129 | IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); |
1123 | isr_stats->tx++; | 1130 | isr_stats->tx++; |
1124 | handled |= CSR_INT_BIT_FH_TX; | 1131 | handled |= CSR_INT_BIT_FH_TX; |
@@ -1142,8 +1149,10 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
1142 | if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status)) | 1149 | if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status)) |
1143 | iwl_enable_interrupts(trans); | 1150 | iwl_enable_interrupts(trans); |
1144 | /* Re-enable RF_KILL if it occurred */ | 1151 | /* Re-enable RF_KILL if it occurred */ |
1145 | else if (handled & CSR_INT_BIT_RF_KILL) | 1152 | else if (handled & CSR_INT_BIT_RF_KILL) { |
1146 | iwl_enable_rfkill_int(priv(trans)); | 1153 | IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); |
1154 | iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); | ||
1155 | } | ||
1147 | } | 1156 | } |
1148 | 1157 | ||
1149 | /****************************************************************************** | 1158 | /****************************************************************************** |
@@ -1164,7 +1173,7 @@ void iwl_free_isr_ict(struct iwl_trans *trans) | |||
1164 | IWL_TRANS_GET_PCIE_TRANS(trans); | 1173 | IWL_TRANS_GET_PCIE_TRANS(trans); |
1165 | 1174 | ||
1166 | if (trans_pcie->ict_tbl) { | 1175 | if (trans_pcie->ict_tbl) { |
1167 | dma_free_coherent(bus(trans)->dev, ICT_SIZE, | 1176 | dma_free_coherent(trans->dev, ICT_SIZE, |
1168 | trans_pcie->ict_tbl, | 1177 | trans_pcie->ict_tbl, |
1169 | trans_pcie->ict_tbl_dma); | 1178 | trans_pcie->ict_tbl_dma); |
1170 | trans_pcie->ict_tbl = NULL; | 1179 | trans_pcie->ict_tbl = NULL; |
@@ -1184,7 +1193,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans) | |||
1184 | IWL_TRANS_GET_PCIE_TRANS(trans); | 1193 | IWL_TRANS_GET_PCIE_TRANS(trans); |
1185 | 1194 | ||
1186 | trans_pcie->ict_tbl = | 1195 | trans_pcie->ict_tbl = |
1187 | dma_alloc_coherent(bus(trans)->dev, ICT_SIZE, | 1196 | dma_alloc_coherent(trans->dev, ICT_SIZE, |
1188 | &trans_pcie->ict_tbl_dma, | 1197 | &trans_pcie->ict_tbl_dma, |
1189 | GFP_KERNEL); | 1198 | GFP_KERNEL); |
1190 | if (!trans_pcie->ict_tbl) | 1199 | if (!trans_pcie->ict_tbl) |
@@ -1213,7 +1222,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans) | |||
1213 | /* Device is going up inform it about using ICT interrupt table, | 1222 | /* Device is going up inform it about using ICT interrupt table, |
1214 | * also we need to tell the driver to start using ICT interrupt. | 1223 | * also we need to tell the driver to start using ICT interrupt. |
1215 | */ | 1224 | */ |
1216 | int iwl_reset_ict(struct iwl_trans *trans) | 1225 | void iwl_reset_ict(struct iwl_trans *trans) |
1217 | { | 1226 | { |
1218 | u32 val; | 1227 | u32 val; |
1219 | unsigned long flags; | 1228 | unsigned long flags; |
@@ -1221,7 +1230,7 @@ int iwl_reset_ict(struct iwl_trans *trans) | |||
1221 | IWL_TRANS_GET_PCIE_TRANS(trans); | 1230 | IWL_TRANS_GET_PCIE_TRANS(trans); |
1222 | 1231 | ||
1223 | if (!trans_pcie->ict_tbl) | 1232 | if (!trans_pcie->ict_tbl) |
1224 | return 0; | 1233 | return; |
1225 | 1234 | ||
1226 | spin_lock_irqsave(&trans->shrd->lock, flags); | 1235 | spin_lock_irqsave(&trans->shrd->lock, flags); |
1227 | iwl_disable_interrupts(trans); | 1236 | iwl_disable_interrupts(trans); |
@@ -1235,14 +1244,12 @@ int iwl_reset_ict(struct iwl_trans *trans) | |||
1235 | 1244 | ||
1236 | IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val); | 1245 | IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val); |
1237 | 1246 | ||
1238 | iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val); | 1247 | iwl_write32(trans, CSR_DRAM_INT_TBL_REG, val); |
1239 | trans_pcie->use_ict = true; | 1248 | trans_pcie->use_ict = true; |
1240 | trans_pcie->ict_index = 0; | 1249 | trans_pcie->ict_index = 0; |
1241 | iwl_write32(bus(trans), CSR_INT, trans_pcie->inta_mask); | 1250 | iwl_write32(trans, CSR_INT, trans_pcie->inta_mask); |
1242 | iwl_enable_interrupts(trans); | 1251 | iwl_enable_interrupts(trans); |
1243 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | 1252 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
1244 | |||
1245 | return 0; | ||
1246 | } | 1253 | } |
1247 | 1254 | ||
1248 | /* Device is going down disable ict interrupt usage */ | 1255 | /* Device is going down disable ict interrupt usage */ |
@@ -1280,11 +1287,11 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
1280 | * back-to-back ISRs and sporadic interrupts from our NIC. | 1287 | * back-to-back ISRs and sporadic interrupts from our NIC. |
1281 | * If we have something to service, the tasklet will re-enable ints. | 1288 | * If we have something to service, the tasklet will re-enable ints. |
1282 | * If we *don't* have something, we'll re-enable before leaving here. */ | 1289 | * If we *don't* have something, we'll re-enable before leaving here. */ |
1283 | inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ | 1290 | inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ |
1284 | iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); | 1291 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); |
1285 | 1292 | ||
1286 | /* Discover which interrupts are active/pending */ | 1293 | /* Discover which interrupts are active/pending */ |
1287 | inta = iwl_read32(bus(trans), CSR_INT); | 1294 | inta = iwl_read32(trans, CSR_INT); |
1288 | 1295 | ||
1289 | /* Ignore interrupt if there's nothing in NIC to service. | 1296 | /* Ignore interrupt if there's nothing in NIC to service. |
1290 | * This may be due to IRQ shared with another device, | 1297 | * This may be due to IRQ shared with another device, |
@@ -1303,7 +1310,7 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
1303 | 1310 | ||
1304 | #ifdef CONFIG_IWLWIFI_DEBUG | 1311 | #ifdef CONFIG_IWLWIFI_DEBUG |
1305 | if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { | 1312 | if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { |
1306 | inta_fh = iwl_read32(bus(trans), CSR_FH_INT_STATUS); | 1313 | inta_fh = iwl_read32(trans, CSR_FH_INT_STATUS); |
1307 | IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " | 1314 | IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " |
1308 | "fh 0x%08x\n", inta, inta_mask, inta_fh); | 1315 | "fh 0x%08x\n", inta, inta_mask, inta_fh); |
1309 | } | 1316 | } |
@@ -1369,8 +1376,8 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
1369 | * If we have something to service, the tasklet will re-enable ints. | 1376 | * If we have something to service, the tasklet will re-enable ints. |
1370 | * If we *don't* have something, we'll re-enable before leaving here. | 1377 | * If we *don't* have something, we'll re-enable before leaving here. |
1371 | */ | 1378 | */ |
1372 | inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ | 1379 | inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ |
1373 | iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); | 1380 | iwl_write32(trans, CSR_INT_MASK, 0x00000000); |
1374 | 1381 | ||
1375 | 1382 | ||
1376 | /* Ignore interrupt if there's nothing in NIC to service. | 1383 | /* Ignore interrupt if there's nothing in NIC to service. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index dfc75c172475..a8dfecadea11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | |||
@@ -100,7 +100,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) | |||
100 | 100 | ||
101 | if (hw_params(trans).shadow_reg_enable) { | 101 | if (hw_params(trans).shadow_reg_enable) { |
102 | /* shadow register enabled */ | 102 | /* shadow register enabled */ |
103 | iwl_write32(bus(trans), HBUS_TARG_WRPTR, | 103 | iwl_write32(trans, HBUS_TARG_WRPTR, |
104 | txq->q.write_ptr | (txq_id << 8)); | 104 | txq->q.write_ptr | (txq_id << 8)); |
105 | } else { | 105 | } else { |
106 | /* if we're trying to save power */ | 106 | /* if we're trying to save power */ |
@@ -108,18 +108,18 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) | |||
108 | /* wake up nic if it's powered down ... | 108 | /* wake up nic if it's powered down ... |
109 | * uCode will wake up, and interrupt us again, so next | 109 | * uCode will wake up, and interrupt us again, so next |
110 | * time we'll skip this part. */ | 110 | * time we'll skip this part. */ |
111 | reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); | 111 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); |
112 | 112 | ||
113 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 113 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
114 | IWL_DEBUG_INFO(trans, | 114 | IWL_DEBUG_INFO(trans, |
115 | "Tx queue %d requesting wakeup," | 115 | "Tx queue %d requesting wakeup," |
116 | " GP1 = 0x%x\n", txq_id, reg); | 116 | " GP1 = 0x%x\n", txq_id, reg); |
117 | iwl_set_bit(bus(trans), CSR_GP_CNTRL, | 117 | iwl_set_bit(trans, CSR_GP_CNTRL, |
118 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 118 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
119 | return; | 119 | return; |
120 | } | 120 | } |
121 | 121 | ||
122 | iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, | 122 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, |
123 | txq->q.write_ptr | (txq_id << 8)); | 123 | txq->q.write_ptr | (txq_id << 8)); |
124 | 124 | ||
125 | /* | 125 | /* |
@@ -128,7 +128,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) | |||
128 | * trying to tx (during RFKILL, we're not trying to tx). | 128 | * trying to tx (during RFKILL, we're not trying to tx). |
129 | */ | 129 | */ |
130 | } else | 130 | } else |
131 | iwl_write32(bus(trans), HBUS_TARG_WRPTR, | 131 | iwl_write32(trans, HBUS_TARG_WRPTR, |
132 | txq->q.write_ptr | (txq_id << 8)); | 132 | txq->q.write_ptr | (txq_id << 8)); |
133 | } | 133 | } |
134 | txq->need_update = 0; | 134 | txq->need_update = 0; |
@@ -190,14 +190,14 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, | |||
190 | 190 | ||
191 | /* Unmap tx_cmd */ | 191 | /* Unmap tx_cmd */ |
192 | if (num_tbs) | 192 | if (num_tbs) |
193 | dma_unmap_single(bus(trans)->dev, | 193 | dma_unmap_single(trans->dev, |
194 | dma_unmap_addr(meta, mapping), | 194 | dma_unmap_addr(meta, mapping), |
195 | dma_unmap_len(meta, len), | 195 | dma_unmap_len(meta, len), |
196 | DMA_BIDIRECTIONAL); | 196 | DMA_BIDIRECTIONAL); |
197 | 197 | ||
198 | /* Unmap chunks, if any. */ | 198 | /* Unmap chunks, if any. */ |
199 | for (i = 1; i < num_tbs; i++) | 199 | for (i = 1; i < num_tbs; i++) |
200 | dma_unmap_single(bus(trans)->dev, iwl_tfd_tb_get_addr(tfd, i), | 200 | dma_unmap_single(trans->dev, iwl_tfd_tb_get_addr(tfd, i), |
201 | iwl_tfd_tb_get_len(tfd, i), dma_dir); | 201 | iwl_tfd_tb_get_len(tfd, i), dma_dir); |
202 | } | 202 | } |
203 | 203 | ||
@@ -383,14 +383,14 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, | |||
383 | tbl_dw_addr = trans_pcie->scd_base_addr + | 383 | tbl_dw_addr = trans_pcie->scd_base_addr + |
384 | SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); | 384 | SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); |
385 | 385 | ||
386 | tbl_dw = iwl_read_targ_mem(bus(trans), tbl_dw_addr); | 386 | tbl_dw = iwl_read_targ_mem(trans, tbl_dw_addr); |
387 | 387 | ||
388 | if (txq_id & 0x1) | 388 | if (txq_id & 0x1) |
389 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); | 389 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); |
390 | else | 390 | else |
391 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); | 391 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); |
392 | 392 | ||
393 | iwl_write_targ_mem(bus(trans), tbl_dw_addr, tbl_dw); | 393 | iwl_write_targ_mem(trans, tbl_dw_addr, tbl_dw); |
394 | 394 | ||
395 | return 0; | 395 | return 0; |
396 | } | 396 | } |
@@ -399,7 +399,7 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) | |||
399 | { | 399 | { |
400 | /* Simply stop the queue, but don't change any configuration; | 400 | /* Simply stop the queue, but don't change any configuration; |
401 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ | 401 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ |
402 | iwl_write_prph(bus(trans), | 402 | iwl_write_prph(trans, |
403 | SCD_QUEUE_STATUS_BITS(txq_id), | 403 | SCD_QUEUE_STATUS_BITS(txq_id), |
404 | (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| | 404 | (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| |
405 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | 405 | (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); |
@@ -409,9 +409,9 @@ void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, | |||
409 | int txq_id, u32 index) | 409 | int txq_id, u32 index) |
410 | { | 410 | { |
411 | IWL_DEBUG_TX_QUEUES(trans, "Q %d WrPtr: %d", txq_id, index & 0xff); | 411 | IWL_DEBUG_TX_QUEUES(trans, "Q %d WrPtr: %d", txq_id, index & 0xff); |
412 | iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, | 412 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, |
413 | (index & 0xff) | (txq_id << 8)); | 413 | (index & 0xff) | (txq_id << 8)); |
414 | iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index); | 414 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), index); |
415 | } | 415 | } |
416 | 416 | ||
417 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | 417 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, |
@@ -423,7 +423,7 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | |||
423 | int active = | 423 | int active = |
424 | test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0; | 424 | test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0; |
425 | 425 | ||
426 | iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id), | 426 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), |
427 | (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | | 427 | (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | |
428 | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | | 428 | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | |
429 | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | | 429 | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | |
@@ -431,9 +431,12 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | |||
431 | 431 | ||
432 | txq->sched_retry = scd_retry; | 432 | txq->sched_retry = scd_retry; |
433 | 433 | ||
434 | IWL_DEBUG_TX_QUEUES(trans, "%s %s Queue %d on FIFO %d\n", | 434 | if (active) |
435 | active ? "Activate" : "Deactivate", | 435 | IWL_DEBUG_TX_QUEUES(trans, "Activate %s Queue %d on FIFO %d\n", |
436 | scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); | 436 | scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); |
437 | else | ||
438 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate %s Queue %d\n", | ||
439 | scd_retry ? "BA" : "AC/CMD", txq_id); | ||
437 | } | 440 | } |
438 | 441 | ||
439 | static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, | 442 | static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, |
@@ -498,10 +501,10 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, | |||
498 | iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); | 501 | iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); |
499 | 502 | ||
500 | /* Set this queue as a chain-building queue */ | 503 | /* Set this queue as a chain-building queue */ |
501 | iwl_set_bits_prph(bus(trans), SCD_QUEUECHAIN_SEL, (1<<txq_id)); | 504 | iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, (1<<txq_id)); |
502 | 505 | ||
503 | /* enable aggregations for the queue */ | 506 | /* enable aggregations for the queue */ |
504 | iwl_set_bits_prph(bus(trans), SCD_AGGR_SEL, (1<<txq_id)); | 507 | iwl_set_bits_prph(trans, SCD_AGGR_SEL, (1<<txq_id)); |
505 | 508 | ||
506 | /* Place first TFD at index corresponding to start sequence number. | 509 | /* Place first TFD at index corresponding to start sequence number. |
507 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | 510 | * Assumes that ssn_idx is valid (!= 0xFFF) */ |
@@ -510,7 +513,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, | |||
510 | iwl_trans_set_wr_ptrs(trans, txq_id, ssn); | 513 | iwl_trans_set_wr_ptrs(trans, txq_id, ssn); |
511 | 514 | ||
512 | /* Set up Tx window size and frame limit for this queue */ | 515 | /* Set up Tx window size and frame limit for this queue */ |
513 | iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + | 516 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + |
514 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + | 517 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + |
515 | sizeof(u32), | 518 | sizeof(u32), |
516 | ((frame_limit << | 519 | ((frame_limit << |
@@ -520,7 +523,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, | |||
520 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | 523 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & |
521 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | 524 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); |
522 | 525 | ||
523 | iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); | 526 | iwl_set_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); |
524 | 527 | ||
525 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | 528 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ |
526 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | 529 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], |
@@ -584,7 +587,7 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid) | |||
584 | 587 | ||
585 | iwlagn_tx_queue_stop_scheduler(trans, txq_id); | 588 | iwlagn_tx_queue_stop_scheduler(trans, txq_id); |
586 | 589 | ||
587 | iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id)); | 590 | iwl_clear_bits_prph(trans, SCD_AGGR_SEL, (1 << txq_id)); |
588 | 591 | ||
589 | trans_pcie->agg_txq[sta_id][tid] = 0; | 592 | trans_pcie->agg_txq[sta_id][tid] = 0; |
590 | trans_pcie->txq[txq_id].q.read_ptr = 0; | 593 | trans_pcie->txq[txq_id].q.read_ptr = 0; |
@@ -592,7 +595,7 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid) | |||
592 | /* supposes that ssn_idx is valid (!= 0xFFF) */ | 595 | /* supposes that ssn_idx is valid (!= 0xFFF) */ |
593 | iwl_trans_set_wr_ptrs(trans, txq_id, 0); | 596 | iwl_trans_set_wr_ptrs(trans, txq_id, 0); |
594 | 597 | ||
595 | iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); | 598 | iwl_clear_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); |
596 | iwl_txq_ctx_deactivate(trans_pcie, txq_id); | 599 | iwl_txq_ctx_deactivate(trans_pcie, txq_id); |
597 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0); | 600 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0); |
598 | return 0; | 601 | return 0; |
@@ -725,9 +728,9 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
725 | le16_to_cpu(out_cmd->hdr.sequence), cmd_size, | 728 | le16_to_cpu(out_cmd->hdr.sequence), cmd_size, |
726 | q->write_ptr, idx, trans->shrd->cmd_queue); | 729 | q->write_ptr, idx, trans->shrd->cmd_queue); |
727 | 730 | ||
728 | phys_addr = dma_map_single(bus(trans)->dev, &out_cmd->hdr, copy_size, | 731 | phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, |
729 | DMA_BIDIRECTIONAL); | 732 | DMA_BIDIRECTIONAL); |
730 | if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { | 733 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { |
731 | idx = -ENOMEM; | 734 | idx = -ENOMEM; |
732 | goto out; | 735 | goto out; |
733 | } | 736 | } |
@@ -748,10 +751,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
748 | continue; | 751 | continue; |
749 | if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) | 752 | if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) |
750 | continue; | 753 | continue; |
751 | phys_addr = dma_map_single(bus(trans)->dev, | 754 | phys_addr = dma_map_single(trans->dev, |
752 | (void *)cmd->data[i], | 755 | (void *)cmd->data[i], |
753 | cmd->len[i], DMA_BIDIRECTIONAL); | 756 | cmd->len[i], DMA_BIDIRECTIONAL); |
754 | if (dma_mapping_error(bus(trans)->dev, phys_addr)) { | 757 | if (dma_mapping_error(trans->dev, phys_addr)) { |
755 | iwlagn_unmap_tfd(trans, out_meta, | 758 | iwlagn_unmap_tfd(trans, out_meta, |
756 | &txq->tfds[q->write_ptr], | 759 | &txq->tfds[q->write_ptr], |
757 | DMA_BIDIRECTIONAL); | 760 | DMA_BIDIRECTIONAL); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 3c64c4e5885b..f5cb5d3cd926 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | |||
@@ -60,8 +60,11 @@ | |||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #include <linux/pci.h> | ||
64 | #include <linux/pci-aspm.h> | ||
63 | #include <linux/interrupt.h> | 65 | #include <linux/interrupt.h> |
64 | #include <linux/debugfs.h> | 66 | #include <linux/debugfs.h> |
67 | #include <linux/sched.h> | ||
65 | #include <linux/bitops.h> | 68 | #include <linux/bitops.h> |
66 | #include <linux/gfp.h> | 69 | #include <linux/gfp.h> |
67 | 70 | ||
@@ -72,13 +75,14 @@ | |||
72 | #include "iwl-shared.h" | 75 | #include "iwl-shared.h" |
73 | #include "iwl-eeprom.h" | 76 | #include "iwl-eeprom.h" |
74 | #include "iwl-agn-hw.h" | 77 | #include "iwl-agn-hw.h" |
78 | #include "iwl-core.h" | ||
75 | 79 | ||
76 | static int iwl_trans_rx_alloc(struct iwl_trans *trans) | 80 | static int iwl_trans_rx_alloc(struct iwl_trans *trans) |
77 | { | 81 | { |
78 | struct iwl_trans_pcie *trans_pcie = | 82 | struct iwl_trans_pcie *trans_pcie = |
79 | IWL_TRANS_GET_PCIE_TRANS(trans); | 83 | IWL_TRANS_GET_PCIE_TRANS(trans); |
80 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 84 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
81 | struct device *dev = bus(trans)->dev; | 85 | struct device *dev = trans->dev; |
82 | 86 | ||
83 | memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); | 87 | memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); |
84 | 88 | ||
@@ -122,7 +126,7 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) | |||
122 | /* In the reset function, these buffers may have been allocated | 126 | /* In the reset function, these buffers may have been allocated |
123 | * to an SKB, so we need to unmap and free potential storage */ | 127 | * to an SKB, so we need to unmap and free potential storage */ |
124 | if (rxq->pool[i].page != NULL) { | 128 | if (rxq->pool[i].page != NULL) { |
125 | dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma, | 129 | dma_unmap_page(trans->dev, rxq->pool[i].page_dma, |
126 | PAGE_SIZE << hw_params(trans).rx_page_order, | 130 | PAGE_SIZE << hw_params(trans).rx_page_order, |
127 | DMA_FROM_DEVICE); | 131 | DMA_FROM_DEVICE); |
128 | __free_pages(rxq->pool[i].page, | 132 | __free_pages(rxq->pool[i].page, |
@@ -146,17 +150,17 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, | |||
146 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | 150 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; |
147 | 151 | ||
148 | /* Stop Rx DMA */ | 152 | /* Stop Rx DMA */ |
149 | iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | 153 | iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); |
150 | 154 | ||
151 | /* Reset driver's Rx queue write index */ | 155 | /* Reset driver's Rx queue write index */ |
152 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | 156 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); |
153 | 157 | ||
154 | /* Tell device where to find RBD circular buffer in DRAM */ | 158 | /* Tell device where to find RBD circular buffer in DRAM */ |
155 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_BASE_REG, | 159 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG, |
156 | (u32)(rxq->bd_dma >> 8)); | 160 | (u32)(rxq->bd_dma >> 8)); |
157 | 161 | ||
158 | /* Tell device where in DRAM to update its Rx status */ | 162 | /* Tell device where in DRAM to update its Rx status */ |
159 | iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_STTS_WPTR_REG, | 163 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG, |
160 | rxq->rb_stts_dma >> 4); | 164 | rxq->rb_stts_dma >> 4); |
161 | 165 | ||
162 | /* Enable Rx DMA | 166 | /* Enable Rx DMA |
@@ -167,7 +171,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, | |||
167 | * RB timeout 0x10 | 171 | * RB timeout 0x10 |
168 | * 256 RBDs | 172 | * 256 RBDs |
169 | */ | 173 | */ |
170 | iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, | 174 | iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, |
171 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | 175 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | |
172 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | 176 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | |
173 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | 177 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | |
@@ -177,7 +181,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, | |||
177 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | 181 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); |
178 | 182 | ||
179 | /* Set interrupt coalescing timer to default (2048 usecs) */ | 183 | /* Set interrupt coalescing timer to default (2048 usecs) */ |
180 | iwl_write8(bus(trans), CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | 184 | iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); |
181 | } | 185 | } |
182 | 186 | ||
183 | static int iwl_rx_init(struct iwl_trans *trans) | 187 | static int iwl_rx_init(struct iwl_trans *trans) |
@@ -242,13 +246,13 @@ static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) | |||
242 | iwl_trans_rxq_free_rx_bufs(trans); | 246 | iwl_trans_rxq_free_rx_bufs(trans); |
243 | spin_unlock_irqrestore(&rxq->lock, flags); | 247 | spin_unlock_irqrestore(&rxq->lock, flags); |
244 | 248 | ||
245 | dma_free_coherent(bus(trans)->dev, sizeof(__le32) * RX_QUEUE_SIZE, | 249 | dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, |
246 | rxq->bd, rxq->bd_dma); | 250 | rxq->bd, rxq->bd_dma); |
247 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | 251 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); |
248 | rxq->bd = NULL; | 252 | rxq->bd = NULL; |
249 | 253 | ||
250 | if (rxq->rb_stts) | 254 | if (rxq->rb_stts) |
251 | dma_free_coherent(bus(trans)->dev, | 255 | dma_free_coherent(trans->dev, |
252 | sizeof(struct iwl_rb_status), | 256 | sizeof(struct iwl_rb_status), |
253 | rxq->rb_stts, rxq->rb_stts_dma); | 257 | rxq->rb_stts, rxq->rb_stts_dma); |
254 | else | 258 | else |
@@ -261,8 +265,8 @@ static int iwl_trans_rx_stop(struct iwl_trans *trans) | |||
261 | { | 265 | { |
262 | 266 | ||
263 | /* stop Rx DMA */ | 267 | /* stop Rx DMA */ |
264 | iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | 268 | iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); |
265 | return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG, | 269 | return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG, |
266 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | 270 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); |
267 | } | 271 | } |
268 | 272 | ||
@@ -272,7 +276,7 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, | |||
272 | if (WARN_ON(ptr->addr)) | 276 | if (WARN_ON(ptr->addr)) |
273 | return -EINVAL; | 277 | return -EINVAL; |
274 | 278 | ||
275 | ptr->addr = dma_alloc_coherent(bus(trans)->dev, size, | 279 | ptr->addr = dma_alloc_coherent(trans->dev, size, |
276 | &ptr->dma, GFP_KERNEL); | 280 | &ptr->dma, GFP_KERNEL); |
277 | if (!ptr->addr) | 281 | if (!ptr->addr) |
278 | return -ENOMEM; | 282 | return -ENOMEM; |
@@ -286,7 +290,7 @@ static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans, | |||
286 | if (unlikely(!ptr->addr)) | 290 | if (unlikely(!ptr->addr)) |
287 | return; | 291 | return; |
288 | 292 | ||
289 | dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma); | 293 | dma_free_coherent(trans->dev, ptr->size, ptr->addr, ptr->dma); |
290 | memset(ptr, 0, sizeof(*ptr)); | 294 | memset(ptr, 0, sizeof(*ptr)); |
291 | } | 295 | } |
292 | 296 | ||
@@ -333,7 +337,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, | |||
333 | 337 | ||
334 | /* Circular buffer of transmit frame descriptors (TFDs), | 338 | /* Circular buffer of transmit frame descriptors (TFDs), |
335 | * shared with device */ | 339 | * shared with device */ |
336 | txq->tfds = dma_alloc_coherent(bus(trans)->dev, tfd_sz, | 340 | txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz, |
337 | &txq->q.dma_addr, GFP_KERNEL); | 341 | &txq->q.dma_addr, GFP_KERNEL); |
338 | if (!txq->tfds) { | 342 | if (!txq->tfds) { |
339 | IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); | 343 | IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); |
@@ -389,7 +393,7 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, | |||
389 | * Tell nic where to find circular buffer of Tx Frame Descriptors for | 393 | * Tell nic where to find circular buffer of Tx Frame Descriptors for |
390 | * given Tx queue, and enable the DMA channel used for that queue. | 394 | * given Tx queue, and enable the DMA channel used for that queue. |
391 | * Circular buffer (TFD queue in DRAM) physical base address */ | 395 | * Circular buffer (TFD queue in DRAM) physical base address */ |
392 | iwl_write_direct32(bus(trans), FH_MEM_CBBC_QUEUE(txq_id), | 396 | iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id), |
393 | txq->q.dma_addr >> 8); | 397 | txq->q.dma_addr >> 8); |
394 | 398 | ||
395 | return 0; | 399 | return 0; |
@@ -443,7 +447,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) | |||
443 | { | 447 | { |
444 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 448 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
445 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | 449 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; |
446 | struct device *dev = bus(trans)->dev; | 450 | struct device *dev = trans->dev; |
447 | int i; | 451 | int i; |
448 | if (WARN_ON(!txq)) | 452 | if (WARN_ON(!txq)) |
449 | return; | 453 | return; |
@@ -584,10 +588,10 @@ static int iwl_tx_init(struct iwl_trans *trans) | |||
584 | spin_lock_irqsave(&trans->shrd->lock, flags); | 588 | spin_lock_irqsave(&trans->shrd->lock, flags); |
585 | 589 | ||
586 | /* Turn off all Tx DMA fifos */ | 590 | /* Turn off all Tx DMA fifos */ |
587 | iwl_write_prph(bus(trans), SCD_TXFACT, 0); | 591 | iwl_write_prph(trans, SCD_TXFACT, 0); |
588 | 592 | ||
589 | /* Tell NIC where to find the "keep warm" buffer */ | 593 | /* Tell NIC where to find the "keep warm" buffer */ |
590 | iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG, | 594 | iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, |
591 | trans_pcie->kw.dma >> 4); | 595 | trans_pcie->kw.dma >> 4); |
592 | 596 | ||
593 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | 597 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
@@ -619,26 +623,194 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans) | |||
619 | * to set power to V_AUX, do: | 623 | * to set power to V_AUX, do: |
620 | 624 | ||
621 | if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) | 625 | if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) |
622 | iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, | 626 | iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, |
623 | APMG_PS_CTRL_VAL_PWR_SRC_VAUX, | 627 | APMG_PS_CTRL_VAL_PWR_SRC_VAUX, |
624 | ~APMG_PS_CTRL_MSK_PWR_SRC); | 628 | ~APMG_PS_CTRL_MSK_PWR_SRC); |
625 | */ | 629 | */ |
626 | 630 | ||
627 | iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, | 631 | iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, |
628 | APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, | 632 | APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, |
629 | ~APMG_PS_CTRL_MSK_PWR_SRC); | 633 | ~APMG_PS_CTRL_MSK_PWR_SRC); |
630 | } | 634 | } |
631 | 635 | ||
636 | /* PCI registers */ | ||
637 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | ||
638 | #define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 | ||
639 | #define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 | ||
640 | |||
641 | static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans) | ||
642 | { | ||
643 | int pos; | ||
644 | u16 pci_lnk_ctl; | ||
645 | struct iwl_trans_pcie *trans_pcie = | ||
646 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
647 | |||
648 | struct pci_dev *pci_dev = trans_pcie->pci_dev; | ||
649 | |||
650 | pos = pci_pcie_cap(pci_dev); | ||
651 | pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); | ||
652 | return pci_lnk_ctl; | ||
653 | } | ||
654 | |||
655 | static void iwl_apm_config(struct iwl_trans *trans) | ||
656 | { | ||
657 | /* | ||
658 | * HW bug W/A for instability in PCIe bus L0S->L1 transition. | ||
659 | * Check if BIOS (or OS) enabled L1-ASPM on this device. | ||
660 | * If so (likely), disable L0S, so device moves directly L0->L1; | ||
661 | * costs negligible amount of power savings. | ||
662 | * If not (unlikely), enable L0S, so there is at least some | ||
663 | * power savings, even without L1. | ||
664 | */ | ||
665 | u16 lctl = iwl_pciexp_link_ctrl(trans); | ||
666 | |||
667 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == | ||
668 | PCI_CFG_LINK_CTRL_VAL_L1_EN) { | ||
669 | /* L1-ASPM enabled; disable(!) L0S */ | ||
670 | iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
671 | dev_printk(KERN_INFO, trans->dev, | ||
672 | "L1 Enabled; Disabling L0S\n"); | ||
673 | } else { | ||
674 | /* L1-ASPM disabled; enable(!) L0S */ | ||
675 | iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
676 | dev_printk(KERN_INFO, trans->dev, | ||
677 | "L1 Disabled; Enabling L0S\n"); | ||
678 | } | ||
679 | trans->pm_support = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); | ||
680 | } | ||
681 | |||
682 | /* | ||
683 | * Start up NIC's basic functionality after it has been reset | ||
684 | * (e.g. after platform boot, or shutdown via iwl_apm_stop()) | ||
685 | * NOTE: This does not load uCode nor start the embedded processor | ||
686 | */ | ||
687 | static int iwl_apm_init(struct iwl_trans *trans) | ||
688 | { | ||
689 | int ret = 0; | ||
690 | IWL_DEBUG_INFO(trans, "Init card's basic functions\n"); | ||
691 | |||
692 | /* | ||
693 | * Use "set_bit" below rather than "write", to preserve any hardware | ||
694 | * bits already set by default after reset. | ||
695 | */ | ||
696 | |||
697 | /* Disable L0S exit timer (platform NMI Work/Around) */ | ||
698 | iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, | ||
699 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
700 | |||
701 | /* | ||
702 | * Disable L0s without affecting L1; | ||
703 | * don't wait for ICH L0s (ICH bug W/A) | ||
704 | */ | ||
705 | iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, | ||
706 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
707 | |||
708 | /* Set FH wait threshold to maximum (HW error during stress W/A) */ | ||
709 | iwl_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); | ||
710 | |||
711 | /* | ||
712 | * Enable HAP INTA (interrupt from management bus) to | ||
713 | * wake device's PCI Express link L1a -> L0s | ||
714 | */ | ||
715 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | ||
716 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); | ||
717 | |||
718 | iwl_apm_config(trans); | ||
719 | |||
720 | /* Configure analog phase-lock-loop before activating to D0A */ | ||
721 | if (cfg(trans)->base_params->pll_cfg_val) | ||
722 | iwl_set_bit(trans, CSR_ANA_PLL_CFG, | ||
723 | cfg(trans)->base_params->pll_cfg_val); | ||
724 | |||
725 | /* | ||
726 | * Set "initialization complete" bit to move adapter from | ||
727 | * D0U* --> D0A* (powered-up active) state. | ||
728 | */ | ||
729 | iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
730 | |||
731 | /* | ||
732 | * Wait for clock stabilization; once stabilized, access to | ||
733 | * device-internal resources is supported, e.g. iwl_write_prph() | ||
734 | * and accesses to uCode SRAM. | ||
735 | */ | ||
736 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
737 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
738 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
739 | if (ret < 0) { | ||
740 | IWL_DEBUG_INFO(trans, "Failed to init the card\n"); | ||
741 | goto out; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * Enable DMA clock and wait for it to stabilize. | ||
746 | * | ||
747 | * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits | ||
748 | * do not disable clocks. This preserves any hardware bits already | ||
749 | * set by default in "CLK_CTRL_REG" after reset. | ||
750 | */ | ||
751 | iwl_write_prph(trans, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); | ||
752 | udelay(20); | ||
753 | |||
754 | /* Disable L1-Active */ | ||
755 | iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, | ||
756 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
757 | |||
758 | set_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status); | ||
759 | |||
760 | out: | ||
761 | return ret; | ||
762 | } | ||
763 | |||
764 | static int iwl_apm_stop_master(struct iwl_trans *trans) | ||
765 | { | ||
766 | int ret = 0; | ||
767 | |||
768 | /* stop device's busmaster DMA activity */ | ||
769 | iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
770 | |||
771 | ret = iwl_poll_bit(trans, CSR_RESET, | ||
772 | CSR_RESET_REG_FLAG_MASTER_DISABLED, | ||
773 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
774 | if (ret) | ||
775 | IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n"); | ||
776 | |||
777 | IWL_DEBUG_INFO(trans, "stop master\n"); | ||
778 | |||
779 | return ret; | ||
780 | } | ||
781 | |||
782 | static void iwl_apm_stop(struct iwl_trans *trans) | ||
783 | { | ||
784 | IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n"); | ||
785 | |||
786 | clear_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status); | ||
787 | |||
788 | /* Stop device's DMA activity */ | ||
789 | iwl_apm_stop_master(trans); | ||
790 | |||
791 | /* Reset the entire device */ | ||
792 | iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
793 | |||
794 | udelay(10); | ||
795 | |||
796 | /* | ||
797 | * Clear "initialization complete" bit to move adapter from | ||
798 | * D0A* (powered-up Active) --> D0U* (Uninitialized) state. | ||
799 | */ | ||
800 | iwl_clear_bit(trans, CSR_GP_CNTRL, | ||
801 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
802 | } | ||
803 | |||
632 | static int iwl_nic_init(struct iwl_trans *trans) | 804 | static int iwl_nic_init(struct iwl_trans *trans) |
633 | { | 805 | { |
634 | unsigned long flags; | 806 | unsigned long flags; |
635 | 807 | ||
636 | /* nic_init */ | 808 | /* nic_init */ |
637 | spin_lock_irqsave(&trans->shrd->lock, flags); | 809 | spin_lock_irqsave(&trans->shrd->lock, flags); |
638 | iwl_apm_init(priv(trans)); | 810 | iwl_apm_init(trans); |
639 | 811 | ||
640 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | 812 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ |
641 | iwl_write8(bus(trans), CSR_INT_COALESCING, | 813 | iwl_write8(trans, CSR_INT_COALESCING, |
642 | IWL_HOST_INT_CALIB_TIMEOUT_DEF); | 814 | IWL_HOST_INT_CALIB_TIMEOUT_DEF); |
643 | 815 | ||
644 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | 816 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
@@ -647,8 +819,10 @@ static int iwl_nic_init(struct iwl_trans *trans) | |||
647 | 819 | ||
648 | iwl_nic_config(priv(trans)); | 820 | iwl_nic_config(priv(trans)); |
649 | 821 | ||
822 | #ifndef CONFIG_IWLWIFI_IDI | ||
650 | /* Allocate the RX queue, or reset if it is already allocated */ | 823 | /* Allocate the RX queue, or reset if it is already allocated */ |
651 | iwl_rx_init(trans); | 824 | iwl_rx_init(trans); |
825 | #endif | ||
652 | 826 | ||
653 | /* Allocate or reset and init all Tx and Command queues */ | 827 | /* Allocate or reset and init all Tx and Command queues */ |
654 | if (iwl_tx_init(trans)) | 828 | if (iwl_tx_init(trans)) |
@@ -656,7 +830,7 @@ static int iwl_nic_init(struct iwl_trans *trans) | |||
656 | 830 | ||
657 | if (hw_params(trans).shadow_reg_enable) { | 831 | if (hw_params(trans).shadow_reg_enable) { |
658 | /* enable shadow regs in HW */ | 832 | /* enable shadow regs in HW */ |
659 | iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL, | 833 | iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, |
660 | 0x800FFFFF); | 834 | 0x800FFFFF); |
661 | } | 835 | } |
662 | 836 | ||
@@ -672,11 +846,11 @@ static int iwl_set_hw_ready(struct iwl_trans *trans) | |||
672 | { | 846 | { |
673 | int ret; | 847 | int ret; |
674 | 848 | ||
675 | iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | 849 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, |
676 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); | 850 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); |
677 | 851 | ||
678 | /* See if we got it */ | 852 | /* See if we got it */ |
679 | ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | 853 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, |
680 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | 854 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, |
681 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, | 855 | CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, |
682 | HW_READY_TIMEOUT); | 856 | HW_READY_TIMEOUT); |
@@ -686,21 +860,22 @@ static int iwl_set_hw_ready(struct iwl_trans *trans) | |||
686 | } | 860 | } |
687 | 861 | ||
688 | /* Note: returns standard 0/-ERROR code */ | 862 | /* Note: returns standard 0/-ERROR code */ |
689 | static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) | 863 | static int iwl_prepare_card_hw(struct iwl_trans *trans) |
690 | { | 864 | { |
691 | int ret; | 865 | int ret; |
692 | 866 | ||
693 | IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); | 867 | IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); |
694 | 868 | ||
695 | ret = iwl_set_hw_ready(trans); | 869 | ret = iwl_set_hw_ready(trans); |
870 | /* If the card is ready, exit 0 */ | ||
696 | if (ret >= 0) | 871 | if (ret >= 0) |
697 | return 0; | 872 | return 0; |
698 | 873 | ||
699 | /* If HW is not ready, prepare the conditions to check again */ | 874 | /* If HW is not ready, prepare the conditions to check again */ |
700 | iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | 875 | iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, |
701 | CSR_HW_IF_CONFIG_REG_PREPARE); | 876 | CSR_HW_IF_CONFIG_REG_PREPARE); |
702 | 877 | ||
703 | ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, | 878 | ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, |
704 | ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, | 879 | ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, |
705 | CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); | 880 | CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); |
706 | 881 | ||
@@ -767,7 +942,79 @@ static const u8 iwlagn_pan_ac_to_queue[] = { | |||
767 | 7, 6, 5, 4, | 942 | 7, 6, 5, 4, |
768 | }; | 943 | }; |
769 | 944 | ||
770 | static int iwl_trans_pcie_start_device(struct iwl_trans *trans) | 945 | /* |
946 | * ucode | ||
947 | */ | ||
948 | static int iwl_load_section(struct iwl_trans *trans, const char *name, | ||
949 | struct fw_desc *image, u32 dst_addr) | ||
950 | { | ||
951 | dma_addr_t phy_addr = image->p_addr; | ||
952 | u32 byte_cnt = image->len; | ||
953 | int ret; | ||
954 | |||
955 | trans->ucode_write_complete = 0; | ||
956 | |||
957 | iwl_write_direct32(trans, | ||
958 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
959 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
960 | |||
961 | iwl_write_direct32(trans, | ||
962 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | ||
963 | |||
964 | iwl_write_direct32(trans, | ||
965 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | ||
966 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
967 | |||
968 | iwl_write_direct32(trans, | ||
969 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | ||
970 | (iwl_get_dma_hi_addr(phy_addr) | ||
971 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | ||
972 | |||
973 | iwl_write_direct32(trans, | ||
974 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | ||
975 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | ||
976 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | ||
977 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
978 | |||
979 | iwl_write_direct32(trans, | ||
980 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
981 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
982 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | ||
983 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | ||
984 | |||
985 | IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name); | ||
986 | ret = wait_event_timeout(trans->shrd->wait_command_queue, | ||
987 | trans->ucode_write_complete, 5 * HZ); | ||
988 | if (!ret) { | ||
989 | IWL_ERR(trans, "Could not load the %s uCode section\n", | ||
990 | name); | ||
991 | return -ETIMEDOUT; | ||
992 | } | ||
993 | |||
994 | return 0; | ||
995 | } | ||
996 | |||
997 | static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image) | ||
998 | { | ||
999 | int ret = 0; | ||
1000 | |||
1001 | ret = iwl_load_section(trans, "INST", &image->code, | ||
1002 | IWLAGN_RTC_INST_LOWER_BOUND); | ||
1003 | if (ret) | ||
1004 | return ret; | ||
1005 | |||
1006 | ret = iwl_load_section(trans, "DATA", &image->data, | ||
1007 | IWLAGN_RTC_DATA_LOWER_BOUND); | ||
1008 | if (ret) | ||
1009 | return ret; | ||
1010 | |||
1011 | /* Remove all resets to allow NIC to operate */ | ||
1012 | iwl_write32(trans, CSR_RESET, 0); | ||
1013 | |||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
1017 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw) | ||
771 | { | 1018 | { |
772 | int ret; | 1019 | int ret; |
773 | struct iwl_trans_pcie *trans_pcie = | 1020 | struct iwl_trans_pcie *trans_pcie = |
@@ -784,13 +1031,13 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) | |||
784 | trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; | 1031 | trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; |
785 | 1032 | ||
786 | if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) && | 1033 | if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) && |
787 | iwl_trans_pcie_prepare_card_hw(trans)) { | 1034 | iwl_prepare_card_hw(trans)) { |
788 | IWL_WARN(trans, "Exit HW not ready\n"); | 1035 | IWL_WARN(trans, "Exit HW not ready\n"); |
789 | return -EIO; | 1036 | return -EIO; |
790 | } | 1037 | } |
791 | 1038 | ||
792 | /* If platform's RF_KILL switch is NOT set to KILL */ | 1039 | /* If platform's RF_KILL switch is NOT set to KILL */ |
793 | if (iwl_read32(bus(trans), CSR_GP_CNTRL) & | 1040 | if (iwl_read32(trans, CSR_GP_CNTRL) & |
794 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | 1041 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) |
795 | clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | 1042 | clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); |
796 | else | 1043 | else |
@@ -802,7 +1049,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) | |||
802 | return -ERFKILL; | 1049 | return -ERFKILL; |
803 | } | 1050 | } |
804 | 1051 | ||
805 | iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); | 1052 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); |
806 | 1053 | ||
807 | ret = iwl_nic_init(trans); | 1054 | ret = iwl_nic_init(trans); |
808 | if (ret) { | 1055 | if (ret) { |
@@ -811,17 +1058,20 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) | |||
811 | } | 1058 | } |
812 | 1059 | ||
813 | /* make sure rfkill handshake bits are cleared */ | 1060 | /* make sure rfkill handshake bits are cleared */ |
814 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | 1061 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); |
815 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, | 1062 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, |
816 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | 1063 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); |
817 | 1064 | ||
818 | /* clear (again), then enable host interrupts */ | 1065 | /* clear (again), then enable host interrupts */ |
819 | iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); | 1066 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); |
820 | iwl_enable_interrupts(trans); | 1067 | iwl_enable_interrupts(trans); |
821 | 1068 | ||
822 | /* really make sure rfkill handshake bits are cleared */ | 1069 | /* really make sure rfkill handshake bits are cleared */ |
823 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | 1070 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); |
824 | iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | 1071 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); |
1072 | |||
1073 | /* Load the given image to the HW */ | ||
1074 | iwl_load_given_ucode(trans, fw); | ||
825 | 1075 | ||
826 | return 0; | 1076 | return 0; |
827 | } | 1077 | } |
@@ -832,10 +1082,10 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) | |||
832 | */ | 1082 | */ |
833 | static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) | 1083 | static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) |
834 | { | 1084 | { |
835 | iwl_write_prph(bus(trans), SCD_TXFACT, mask); | 1085 | iwl_write_prph(trans, SCD_TXFACT, mask); |
836 | } | 1086 | } |
837 | 1087 | ||
838 | static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) | 1088 | static void iwl_tx_start(struct iwl_trans *trans) |
839 | { | 1089 | { |
840 | const struct queue_to_fifo_ac *queue_to_fifo; | 1090 | const struct queue_to_fifo_ac *queue_to_fifo; |
841 | struct iwl_trans_pcie *trans_pcie = | 1091 | struct iwl_trans_pcie *trans_pcie = |
@@ -848,46 +1098,46 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) | |||
848 | spin_lock_irqsave(&trans->shrd->lock, flags); | 1098 | spin_lock_irqsave(&trans->shrd->lock, flags); |
849 | 1099 | ||
850 | trans_pcie->scd_base_addr = | 1100 | trans_pcie->scd_base_addr = |
851 | iwl_read_prph(bus(trans), SCD_SRAM_BASE_ADDR); | 1101 | iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); |
852 | a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; | 1102 | a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; |
853 | /* reset conext data memory */ | 1103 | /* reset conext data memory */ |
854 | for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; | 1104 | for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; |
855 | a += 4) | 1105 | a += 4) |
856 | iwl_write_targ_mem(bus(trans), a, 0); | 1106 | iwl_write_targ_mem(trans, a, 0); |
857 | /* reset tx status memory */ | 1107 | /* reset tx status memory */ |
858 | for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; | 1108 | for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; |
859 | a += 4) | 1109 | a += 4) |
860 | iwl_write_targ_mem(bus(trans), a, 0); | 1110 | iwl_write_targ_mem(trans, a, 0); |
861 | for (; a < trans_pcie->scd_base_addr + | 1111 | for (; a < trans_pcie->scd_base_addr + |
862 | SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num); | 1112 | SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num); |
863 | a += 4) | 1113 | a += 4) |
864 | iwl_write_targ_mem(bus(trans), a, 0); | 1114 | iwl_write_targ_mem(trans, a, 0); |
865 | 1115 | ||
866 | iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR, | 1116 | iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, |
867 | trans_pcie->scd_bc_tbls.dma >> 10); | 1117 | trans_pcie->scd_bc_tbls.dma >> 10); |
868 | 1118 | ||
869 | /* Enable DMA channel */ | 1119 | /* Enable DMA channel */ |
870 | for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) | 1120 | for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) |
871 | iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(chan), | 1121 | iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), |
872 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | 1122 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | |
873 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | 1123 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); |
874 | 1124 | ||
875 | /* Update FH chicken bits */ | 1125 | /* Update FH chicken bits */ |
876 | reg_val = iwl_read_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG); | 1126 | reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); |
877 | iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG, | 1127 | iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, |
878 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | 1128 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); |
879 | 1129 | ||
880 | iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL, | 1130 | iwl_write_prph(trans, SCD_QUEUECHAIN_SEL, |
881 | SCD_QUEUECHAIN_SEL_ALL(trans)); | 1131 | SCD_QUEUECHAIN_SEL_ALL(trans)); |
882 | iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0); | 1132 | iwl_write_prph(trans, SCD_AGGR_SEL, 0); |
883 | 1133 | ||
884 | /* initiate the queues */ | 1134 | /* initiate the queues */ |
885 | for (i = 0; i < hw_params(trans).max_txq_num; i++) { | 1135 | for (i = 0; i < hw_params(trans).max_txq_num; i++) { |
886 | iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0); | 1136 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(i), 0); |
887 | iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8)); | 1137 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, 0 | (i << 8)); |
888 | iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + | 1138 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + |
889 | SCD_CONTEXT_QUEUE_OFFSET(i), 0); | 1139 | SCD_CONTEXT_QUEUE_OFFSET(i), 0); |
890 | iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + | 1140 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + |
891 | SCD_CONTEXT_QUEUE_OFFSET(i) + | 1141 | SCD_CONTEXT_QUEUE_OFFSET(i) + |
892 | sizeof(u32), | 1142 | sizeof(u32), |
893 | ((SCD_WIN_SIZE << | 1143 | ((SCD_WIN_SIZE << |
@@ -898,7 +1148,7 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) | |||
898 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | 1148 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); |
899 | } | 1149 | } |
900 | 1150 | ||
901 | iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK, | 1151 | iwl_write_prph(trans, SCD_INTERRUPT_MASK, |
902 | IWL_MASK(0, hw_params(trans).max_txq_num)); | 1152 | IWL_MASK(0, hw_params(trans).max_txq_num)); |
903 | 1153 | ||
904 | /* Activate all Tx DMA/FIFO channels */ | 1154 | /* Activate all Tx DMA/FIFO channels */ |
@@ -944,10 +1194,16 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) | |||
944 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | 1194 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
945 | 1195 | ||
946 | /* Enable L1-Active */ | 1196 | /* Enable L1-Active */ |
947 | iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG, | 1197 | iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, |
948 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 1198 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); |
949 | } | 1199 | } |
950 | 1200 | ||
1201 | static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans) | ||
1202 | { | ||
1203 | iwl_reset_ict(trans); | ||
1204 | iwl_tx_start(trans); | ||
1205 | } | ||
1206 | |||
951 | /** | 1207 | /** |
952 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels | 1208 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels |
953 | */ | 1209 | */ |
@@ -964,14 +1220,14 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) | |||
964 | 1220 | ||
965 | /* Stop each Tx DMA channel, and wait for it to be idle */ | 1221 | /* Stop each Tx DMA channel, and wait for it to be idle */ |
966 | for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { | 1222 | for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { |
967 | iwl_write_direct32(bus(trans), | 1223 | iwl_write_direct32(trans, |
968 | FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | 1224 | FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); |
969 | if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG, | 1225 | if (iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG, |
970 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | 1226 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), |
971 | 1000)) | 1227 | 1000)) |
972 | IWL_ERR(trans, "Failing on timeout while stopping" | 1228 | IWL_ERR(trans, "Failing on timeout while stopping" |
973 | " DMA channel %d [0x%08x]", ch, | 1229 | " DMA channel %d [0x%08x]", ch, |
974 | iwl_read_direct32(bus(trans), | 1230 | iwl_read_direct32(trans, |
975 | FH_TSSR_TX_STATUS_REG)); | 1231 | FH_TSSR_TX_STATUS_REG)); |
976 | } | 1232 | } |
977 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | 1233 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
@@ -1010,20 +1266,21 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
1010 | */ | 1266 | */ |
1011 | if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) { | 1267 | if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) { |
1012 | iwl_trans_tx_stop(trans); | 1268 | iwl_trans_tx_stop(trans); |
1269 | #ifndef CONFIG_IWLWIFI_IDI | ||
1013 | iwl_trans_rx_stop(trans); | 1270 | iwl_trans_rx_stop(trans); |
1014 | 1271 | #endif | |
1015 | /* Power-down device's busmaster DMA clocks */ | 1272 | /* Power-down device's busmaster DMA clocks */ |
1016 | iwl_write_prph(bus(trans), APMG_CLK_DIS_REG, | 1273 | iwl_write_prph(trans, APMG_CLK_DIS_REG, |
1017 | APMG_CLK_VAL_DMA_CLK_RQT); | 1274 | APMG_CLK_VAL_DMA_CLK_RQT); |
1018 | udelay(5); | 1275 | udelay(5); |
1019 | } | 1276 | } |
1020 | 1277 | ||
1021 | /* Make sure (redundant) we've released our request to stay awake */ | 1278 | /* Make sure (redundant) we've released our request to stay awake */ |
1022 | iwl_clear_bit(bus(trans), CSR_GP_CNTRL, | 1279 | iwl_clear_bit(trans, CSR_GP_CNTRL, |
1023 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 1280 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
1024 | 1281 | ||
1025 | /* Stop the device, and put it in low power state */ | 1282 | /* Stop the device, and put it in low power state */ |
1026 | iwl_apm_stop(priv(trans)); | 1283 | iwl_apm_stop(trans); |
1027 | 1284 | ||
1028 | /* Upon stop, the APM issues an interrupt if HW RF kill is set. | 1285 | /* Upon stop, the APM issues an interrupt if HW RF kill is set. |
1029 | * Clean again the interrupt here | 1286 | * Clean again the interrupt here |
@@ -1033,11 +1290,11 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
1033 | spin_unlock_irqrestore(&trans->shrd->lock, flags); | 1290 | spin_unlock_irqrestore(&trans->shrd->lock, flags); |
1034 | 1291 | ||
1035 | /* wait to make sure we flush pending tasklet*/ | 1292 | /* wait to make sure we flush pending tasklet*/ |
1036 | synchronize_irq(bus(trans)->irq); | 1293 | synchronize_irq(trans->irq); |
1037 | tasklet_kill(&trans_pcie->irq_tasklet); | 1294 | tasklet_kill(&trans_pcie->irq_tasklet); |
1038 | 1295 | ||
1039 | /* stop and reset the on-board processor */ | 1296 | /* stop and reset the on-board processor */ |
1040 | iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 1297 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
1041 | } | 1298 | } |
1042 | 1299 | ||
1043 | static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | 1300 | static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, |
@@ -1134,10 +1391,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1134 | 1391 | ||
1135 | /* Physical address of this Tx command's header (not MAC header!), | 1392 | /* Physical address of this Tx command's header (not MAC header!), |
1136 | * within command buffer array. */ | 1393 | * within command buffer array. */ |
1137 | txcmd_phys = dma_map_single(bus(trans)->dev, | 1394 | txcmd_phys = dma_map_single(trans->dev, |
1138 | &dev_cmd->hdr, firstlen, | 1395 | &dev_cmd->hdr, firstlen, |
1139 | DMA_BIDIRECTIONAL); | 1396 | DMA_BIDIRECTIONAL); |
1140 | if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys))) | 1397 | if (unlikely(dma_mapping_error(trans->dev, txcmd_phys))) |
1141 | return -1; | 1398 | return -1; |
1142 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | 1399 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
1143 | dma_unmap_len_set(out_meta, len, firstlen); | 1400 | dma_unmap_len_set(out_meta, len, firstlen); |
@@ -1153,10 +1410,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1153 | * if any (802.11 null frames have no payload). */ | 1410 | * if any (802.11 null frames have no payload). */ |
1154 | secondlen = skb->len - hdr_len; | 1411 | secondlen = skb->len - hdr_len; |
1155 | if (secondlen > 0) { | 1412 | if (secondlen > 0) { |
1156 | phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len, | 1413 | phys_addr = dma_map_single(trans->dev, skb->data + hdr_len, |
1157 | secondlen, DMA_TO_DEVICE); | 1414 | secondlen, DMA_TO_DEVICE); |
1158 | if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { | 1415 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { |
1159 | dma_unmap_single(bus(trans)->dev, | 1416 | dma_unmap_single(trans->dev, |
1160 | dma_unmap_addr(out_meta, mapping), | 1417 | dma_unmap_addr(out_meta, mapping), |
1161 | dma_unmap_len(out_meta, len), | 1418 | dma_unmap_len(out_meta, len), |
1162 | DMA_BIDIRECTIONAL); | 1419 | DMA_BIDIRECTIONAL); |
@@ -1174,7 +1431,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1174 | offsetof(struct iwl_tx_cmd, scratch); | 1431 | offsetof(struct iwl_tx_cmd, scratch); |
1175 | 1432 | ||
1176 | /* take back ownership of DMA buffer to enable update */ | 1433 | /* take back ownership of DMA buffer to enable update */ |
1177 | dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen, | 1434 | dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen, |
1178 | DMA_BIDIRECTIONAL); | 1435 | DMA_BIDIRECTIONAL); |
1179 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | 1436 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); |
1180 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | 1437 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); |
@@ -1188,7 +1445,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1188 | /* Set up entry for this TFD in Tx byte-count array */ | 1445 | /* Set up entry for this TFD in Tx byte-count array */ |
1189 | iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); | 1446 | iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); |
1190 | 1447 | ||
1191 | dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, | 1448 | dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, |
1192 | DMA_BIDIRECTIONAL); | 1449 | DMA_BIDIRECTIONAL); |
1193 | 1450 | ||
1194 | trace_iwlwifi_dev_tx(priv(trans), | 1451 | trace_iwlwifi_dev_tx(priv(trans), |
@@ -1218,13 +1475,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1218 | return 0; | 1475 | return 0; |
1219 | } | 1476 | } |
1220 | 1477 | ||
1221 | static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) | 1478 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) |
1222 | { | ||
1223 | /* Remove all resets to allow NIC to operate */ | ||
1224 | iwl_write32(bus(trans), CSR_RESET, 0); | ||
1225 | } | ||
1226 | |||
1227 | static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) | ||
1228 | { | 1479 | { |
1229 | struct iwl_trans_pcie *trans_pcie = | 1480 | struct iwl_trans_pcie *trans_pcie = |
1230 | IWL_TRANS_GET_PCIE_TRANS(trans); | 1481 | IWL_TRANS_GET_PCIE_TRANS(trans); |
@@ -1232,21 +1483,62 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) | |||
1232 | 1483 | ||
1233 | trans_pcie->inta_mask = CSR_INI_SET_MASK; | 1484 | trans_pcie->inta_mask = CSR_INI_SET_MASK; |
1234 | 1485 | ||
1235 | tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) | 1486 | if (!trans_pcie->irq_requested) { |
1236 | iwl_irq_tasklet, (unsigned long)trans); | 1487 | tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) |
1488 | iwl_irq_tasklet, (unsigned long)trans); | ||
1237 | 1489 | ||
1238 | iwl_alloc_isr_ict(trans); | 1490 | iwl_alloc_isr_ict(trans); |
1491 | |||
1492 | err = request_irq(trans->irq, iwl_isr_ict, IRQF_SHARED, | ||
1493 | DRV_NAME, trans); | ||
1494 | if (err) { | ||
1495 | IWL_ERR(trans, "Error allocating IRQ %d\n", | ||
1496 | trans->irq); | ||
1497 | goto error; | ||
1498 | } | ||
1239 | 1499 | ||
1240 | err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, | 1500 | INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); |
1241 | DRV_NAME, trans); | 1501 | trans_pcie->irq_requested = true; |
1502 | } | ||
1503 | |||
1504 | err = iwl_prepare_card_hw(trans); | ||
1242 | if (err) { | 1505 | if (err) { |
1243 | IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq); | 1506 | IWL_ERR(trans, "Error while preparing HW: %d", err); |
1244 | iwl_free_isr_ict(trans); | 1507 | goto err_free_irq; |
1245 | return err; | ||
1246 | } | 1508 | } |
1247 | 1509 | ||
1248 | INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); | 1510 | iwl_apm_init(trans); |
1249 | return 0; | 1511 | |
1512 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
1513 | if (iwl_read32(trans, | ||
1514 | CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | ||
1515 | clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
1516 | else | ||
1517 | set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); | ||
1518 | |||
1519 | iwl_set_hw_rfkill_state(priv(trans), | ||
1520 | test_bit(STATUS_RF_KILL_HW, | ||
1521 | &trans->shrd->status)); | ||
1522 | |||
1523 | return err; | ||
1524 | |||
1525 | err_free_irq: | ||
1526 | free_irq(trans->irq, trans); | ||
1527 | error: | ||
1528 | iwl_free_isr_ict(trans); | ||
1529 | tasklet_kill(&trans_pcie->irq_tasklet); | ||
1530 | return err; | ||
1531 | } | ||
1532 | |||
1533 | static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans) | ||
1534 | { | ||
1535 | iwl_apm_stop(trans); | ||
1536 | |||
1537 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
1538 | |||
1539 | /* Even if we stop the HW, we still want the RF kill interrupt */ | ||
1540 | IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); | ||
1541 | iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); | ||
1250 | } | 1542 | } |
1251 | 1543 | ||
1252 | static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, | 1544 | static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, |
@@ -1289,13 +1581,42 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, | |||
1289 | return 0; | 1581 | return 0; |
1290 | } | 1582 | } |
1291 | 1583 | ||
1584 | static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) | ||
1585 | { | ||
1586 | iowrite8(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); | ||
1587 | } | ||
1588 | |||
1589 | static void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val) | ||
1590 | { | ||
1591 | iowrite32(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); | ||
1592 | } | ||
1593 | |||
1594 | static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs) | ||
1595 | { | ||
1596 | u32 val = ioread32(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); | ||
1597 | return val; | ||
1598 | } | ||
1599 | |||
1292 | static void iwl_trans_pcie_free(struct iwl_trans *trans) | 1600 | static void iwl_trans_pcie_free(struct iwl_trans *trans) |
1293 | { | 1601 | { |
1602 | struct iwl_trans_pcie *trans_pcie = | ||
1603 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1604 | |||
1294 | iwl_calib_free_results(trans); | 1605 | iwl_calib_free_results(trans); |
1295 | iwl_trans_pcie_tx_free(trans); | 1606 | iwl_trans_pcie_tx_free(trans); |
1607 | #ifndef CONFIG_IWLWIFI_IDI | ||
1296 | iwl_trans_pcie_rx_free(trans); | 1608 | iwl_trans_pcie_rx_free(trans); |
1297 | free_irq(bus(trans)->irq, trans); | 1609 | #endif |
1298 | iwl_free_isr_ict(trans); | 1610 | if (trans_pcie->irq_requested == true) { |
1611 | free_irq(trans->irq, trans); | ||
1612 | iwl_free_isr_ict(trans); | ||
1613 | } | ||
1614 | |||
1615 | pci_disable_msi(trans_pcie->pci_dev); | ||
1616 | pci_iounmap(trans_pcie->pci_dev, trans_pcie->hw_base); | ||
1617 | pci_release_regions(trans_pcie->pci_dev); | ||
1618 | pci_disable_device(trans_pcie->pci_dev); | ||
1619 | |||
1299 | trans->shrd->trans = NULL; | 1620 | trans->shrd->trans = NULL; |
1300 | kfree(trans); | 1621 | kfree(trans); |
1301 | } | 1622 | } |
@@ -1315,10 +1636,10 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans) | |||
1315 | * things already :-) | 1636 | * things already :-) |
1316 | */ | 1637 | */ |
1317 | if (!trans->shrd->wowlan) { | 1638 | if (!trans->shrd->wowlan) { |
1318 | iwl_apm_stop(priv(trans)); | 1639 | iwl_apm_stop(trans); |
1319 | } else { | 1640 | } else { |
1320 | iwl_disable_interrupts(trans); | 1641 | iwl_disable_interrupts(trans); |
1321 | iwl_clear_bit(bus(trans), CSR_GP_CNTRL, | 1642 | iwl_clear_bit(trans, CSR_GP_CNTRL, |
1322 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 1643 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
1323 | } | 1644 | } |
1324 | 1645 | ||
@@ -1331,7 +1652,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) | |||
1331 | 1652 | ||
1332 | iwl_enable_interrupts(trans); | 1653 | iwl_enable_interrupts(trans); |
1333 | 1654 | ||
1334 | if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & | 1655 | if (!(iwl_read32(trans, CSR_GP_CNTRL) & |
1335 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) | 1656 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) |
1336 | hw_rfkill = true; | 1657 | hw_rfkill = true; |
1337 | 1658 | ||
@@ -1364,25 +1685,6 @@ static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, | |||
1364 | } | 1685 | } |
1365 | } | 1686 | } |
1366 | 1687 | ||
1367 | const struct iwl_trans_ops trans_ops_pcie; | ||
1368 | |||
1369 | static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) | ||
1370 | { | ||
1371 | struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) + | ||
1372 | sizeof(struct iwl_trans_pcie), | ||
1373 | GFP_KERNEL); | ||
1374 | if (iwl_trans) { | ||
1375 | struct iwl_trans_pcie *trans_pcie = | ||
1376 | IWL_TRANS_GET_PCIE_TRANS(iwl_trans); | ||
1377 | iwl_trans->ops = &trans_ops_pcie; | ||
1378 | iwl_trans->shrd = shrd; | ||
1379 | trans_pcie->trans = iwl_trans; | ||
1380 | spin_lock_init(&iwl_trans->hcmd_lock); | ||
1381 | } | ||
1382 | |||
1383 | return iwl_trans; | ||
1384 | } | ||
1385 | |||
1386 | static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id, | 1688 | static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id, |
1387 | const char *msg) | 1689 | const char *msg) |
1388 | { | 1690 | { |
@@ -1446,9 +1748,9 @@ static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt) | |||
1446 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", | 1748 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", |
1447 | q->read_ptr, q->write_ptr); | 1749 | q->read_ptr, q->write_ptr); |
1448 | IWL_ERR(trans, "Current HW read_ptr %d write_ptr %d\n", | 1750 | IWL_ERR(trans, "Current HW read_ptr %d write_ptr %d\n", |
1449 | iwl_read_prph(bus(trans), SCD_QUEUE_RDPTR(cnt)) | 1751 | iwl_read_prph(trans, SCD_QUEUE_RDPTR(cnt)) |
1450 | & (TFD_QUEUE_SIZE_MAX - 1), | 1752 | & (TFD_QUEUE_SIZE_MAX - 1), |
1451 | iwl_read_prph(bus(trans), SCD_QUEUE_WRPTR(cnt))); | 1753 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt))); |
1452 | return 1; | 1754 | return 1; |
1453 | } | 1755 | } |
1454 | 1756 | ||
@@ -1502,7 +1804,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) | |||
1502 | pos += scnprintf(*buf + pos, bufsz - pos, | 1804 | pos += scnprintf(*buf + pos, bufsz - pos, |
1503 | " %34s: 0X%08x\n", | 1805 | " %34s: 0X%08x\n", |
1504 | get_fh_string(fh_tbl[i]), | 1806 | get_fh_string(fh_tbl[i]), |
1505 | iwl_read_direct32(bus(trans), fh_tbl[i])); | 1807 | iwl_read_direct32(trans, fh_tbl[i])); |
1506 | } | 1808 | } |
1507 | return pos; | 1809 | return pos; |
1508 | } | 1810 | } |
@@ -1511,7 +1813,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) | |||
1511 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | 1813 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { |
1512 | IWL_ERR(trans, " %34s: 0X%08x\n", | 1814 | IWL_ERR(trans, " %34s: 0X%08x\n", |
1513 | get_fh_string(fh_tbl[i]), | 1815 | get_fh_string(fh_tbl[i]), |
1514 | iwl_read_direct32(bus(trans), fh_tbl[i])); | 1816 | iwl_read_direct32(trans, fh_tbl[i])); |
1515 | } | 1817 | } |
1516 | return 0; | 1818 | return 0; |
1517 | } | 1819 | } |
@@ -1581,7 +1883,7 @@ void iwl_dump_csr(struct iwl_trans *trans) | |||
1581 | for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { | 1883 | for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { |
1582 | IWL_ERR(trans, " %25s: 0X%08x\n", | 1884 | IWL_ERR(trans, " %25s: 0X%08x\n", |
1583 | get_csr_string(csr_tbl[i]), | 1885 | get_csr_string(csr_tbl[i]), |
1584 | iwl_read32(bus(trans), csr_tbl[i])); | 1886 | iwl_read32(trans, csr_tbl[i])); |
1585 | } | 1887 | } |
1586 | } | 1888 | } |
1587 | 1889 | ||
@@ -1902,13 +2204,12 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | |||
1902 | #endif /*CONFIG_IWLWIFI_DEBUGFS */ | 2204 | #endif /*CONFIG_IWLWIFI_DEBUGFS */ |
1903 | 2205 | ||
1904 | const struct iwl_trans_ops trans_ops_pcie = { | 2206 | const struct iwl_trans_ops trans_ops_pcie = { |
1905 | .alloc = iwl_trans_pcie_alloc, | 2207 | .start_hw = iwl_trans_pcie_start_hw, |
1906 | .request_irq = iwl_trans_pcie_request_irq, | 2208 | .stop_hw = iwl_trans_pcie_stop_hw, |
1907 | .start_device = iwl_trans_pcie_start_device, | 2209 | .fw_alive = iwl_trans_pcie_fw_alive, |
1908 | .prepare_card_hw = iwl_trans_pcie_prepare_card_hw, | 2210 | .start_fw = iwl_trans_pcie_start_fw, |
1909 | .stop_device = iwl_trans_pcie_stop_device, | 2211 | .stop_device = iwl_trans_pcie_stop_device, |
1910 | 2212 | ||
1911 | .tx_start = iwl_trans_pcie_tx_start, | ||
1912 | .wake_any_queue = iwl_trans_pcie_wake_any_queue, | 2213 | .wake_any_queue = iwl_trans_pcie_wake_any_queue, |
1913 | 2214 | ||
1914 | .send_cmd = iwl_trans_pcie_send_cmd, | 2215 | .send_cmd = iwl_trans_pcie_send_cmd, |
@@ -1920,8 +2221,6 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
1920 | .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, | 2221 | .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, |
1921 | .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, | 2222 | .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, |
1922 | 2223 | ||
1923 | .kick_nic = iwl_trans_pcie_kick_nic, | ||
1924 | |||
1925 | .free = iwl_trans_pcie_free, | 2224 | .free = iwl_trans_pcie_free, |
1926 | .stop_queue = iwl_trans_pcie_stop_queue, | 2225 | .stop_queue = iwl_trans_pcie_stop_queue, |
1927 | 2226 | ||
@@ -1934,4 +2233,116 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
1934 | .suspend = iwl_trans_pcie_suspend, | 2233 | .suspend = iwl_trans_pcie_suspend, |
1935 | .resume = iwl_trans_pcie_resume, | 2234 | .resume = iwl_trans_pcie_resume, |
1936 | #endif | 2235 | #endif |
2236 | .write8 = iwl_trans_pcie_write8, | ||
2237 | .write32 = iwl_trans_pcie_write32, | ||
2238 | .read32 = iwl_trans_pcie_read32, | ||
1937 | }; | 2239 | }; |
2240 | |||
2241 | struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, | ||
2242 | struct pci_dev *pdev, | ||
2243 | const struct pci_device_id *ent) | ||
2244 | { | ||
2245 | struct iwl_trans_pcie *trans_pcie; | ||
2246 | struct iwl_trans *trans; | ||
2247 | u16 pci_cmd; | ||
2248 | int err; | ||
2249 | |||
2250 | trans = kzalloc(sizeof(struct iwl_trans) + | ||
2251 | sizeof(struct iwl_trans_pcie), GFP_KERNEL); | ||
2252 | |||
2253 | if (WARN_ON(!trans)) | ||
2254 | return NULL; | ||
2255 | |||
2256 | trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
2257 | |||
2258 | trans->ops = &trans_ops_pcie; | ||
2259 | trans->shrd = shrd; | ||
2260 | trans_pcie->trans = trans; | ||
2261 | spin_lock_init(&trans->hcmd_lock); | ||
2262 | |||
2263 | /* W/A - seems to solve weird behavior. We need to remove this if we | ||
2264 | * don't want to stay in L1 all the time. This wastes a lot of power */ | ||
2265 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | ||
2266 | PCIE_LINK_STATE_CLKPM); | ||
2267 | |||
2268 | if (pci_enable_device(pdev)) { | ||
2269 | err = -ENODEV; | ||
2270 | goto out_no_pci; | ||
2271 | } | ||
2272 | |||
2273 | pci_set_master(pdev); | ||
2274 | |||
2275 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); | ||
2276 | if (!err) | ||
2277 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); | ||
2278 | if (err) { | ||
2279 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
2280 | if (!err) | ||
2281 | err = pci_set_consistent_dma_mask(pdev, | ||
2282 | DMA_BIT_MASK(32)); | ||
2283 | /* both attempts failed: */ | ||
2284 | if (err) { | ||
2285 | dev_printk(KERN_ERR, &pdev->dev, | ||
2286 | "No suitable DMA available.\n"); | ||
2287 | goto out_pci_disable_device; | ||
2288 | } | ||
2289 | } | ||
2290 | |||
2291 | err = pci_request_regions(pdev, DRV_NAME); | ||
2292 | if (err) { | ||
2293 | dev_printk(KERN_ERR, &pdev->dev, "pci_request_regions failed"); | ||
2294 | goto out_pci_disable_device; | ||
2295 | } | ||
2296 | |||
2297 | trans_pcie->hw_base = pci_iomap(pdev, 0, 0); | ||
2298 | if (!trans_pcie->hw_base) { | ||
2299 | dev_printk(KERN_ERR, &pdev->dev, "pci_iomap failed"); | ||
2300 | err = -ENODEV; | ||
2301 | goto out_pci_release_regions; | ||
2302 | } | ||
2303 | |||
2304 | dev_printk(KERN_INFO, &pdev->dev, | ||
2305 | "pci_resource_len = 0x%08llx\n", | ||
2306 | (unsigned long long) pci_resource_len(pdev, 0)); | ||
2307 | dev_printk(KERN_INFO, &pdev->dev, | ||
2308 | "pci_resource_base = %p\n", trans_pcie->hw_base); | ||
2309 | |||
2310 | dev_printk(KERN_INFO, &pdev->dev, | ||
2311 | "HW Revision ID = 0x%X\n", pdev->revision); | ||
2312 | |||
2313 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | ||
2314 | * PCI Tx retries from interfering with C3 CPU state */ | ||
2315 | pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); | ||
2316 | |||
2317 | err = pci_enable_msi(pdev); | ||
2318 | if (err) | ||
2319 | dev_printk(KERN_ERR, &pdev->dev, | ||
2320 | "pci_enable_msi failed(0X%x)", err); | ||
2321 | |||
2322 | trans->dev = &pdev->dev; | ||
2323 | trans->irq = pdev->irq; | ||
2324 | trans_pcie->pci_dev = pdev; | ||
2325 | trans->hw_rev = iwl_read32(trans, CSR_HW_REV); | ||
2326 | trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; | ||
2327 | snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), | ||
2328 | "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); | ||
2329 | |||
2330 | /* TODO: Move this away, not needed if not MSI */ | ||
2331 | /* enable rfkill interrupt: hw bug w/a */ | ||
2332 | pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); | ||
2333 | if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { | ||
2334 | pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; | ||
2335 | pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); | ||
2336 | } | ||
2337 | |||
2338 | return trans; | ||
2339 | |||
2340 | out_pci_release_regions: | ||
2341 | pci_release_regions(pdev); | ||
2342 | out_pci_disable_device: | ||
2343 | pci_disable_device(pdev); | ||
2344 | out_no_pci: | ||
2345 | kfree(trans); | ||
2346 | return NULL; | ||
2347 | } | ||
2348 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 42a9f303f543..ae68c51e5327 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -131,16 +131,26 @@ struct iwl_host_cmd { | |||
131 | u8 id; | 131 | u8 id; |
132 | }; | 132 | }; |
133 | 133 | ||
134 | /* one for each uCode image (inst/data, boot/init/runtime) */ | ||
135 | struct fw_desc { | ||
136 | dma_addr_t p_addr; /* hardware address */ | ||
137 | void *v_addr; /* software address */ | ||
138 | u32 len; /* size in bytes */ | ||
139 | }; | ||
140 | |||
141 | struct fw_img { | ||
142 | struct fw_desc code; /* firmware code image */ | ||
143 | struct fw_desc data; /* firmware data image */ | ||
144 | }; | ||
145 | |||
134 | /** | 146 | /** |
135 | * struct iwl_trans_ops - transport specific operations | 147 | * struct iwl_trans_ops - transport specific operations |
136 | * @alloc: allocates the meta data (not the queues themselves) | 148 | * @start_hw: starts the HW- from that point on, the HW can send interrupts |
137 | * @request_irq: requests IRQ - will be called before the FW load in probe flow | 149 | * @stop_hw: stops the HW- from that point on, the HW will be in low power but |
138 | * @start_device: allocates and inits all the resources for the transport | 150 | * will still issue interrupt if the HW RF kill is triggered. |
139 | * layer. | 151 | * @start_fw: allocates and inits all the resources for the transport |
140 | * @prepare_card_hw: claim the ownership on the HW. Will be called during | 152 | * layer. Also kick a fw image. This handler may sleep. |
141 | * probe. | 153 | * @fw_alive: called when the fw sends alive notification |
142 | * @tx_start: starts and configures all the Tx fifo - usually done once the fw | ||
143 | * is alive. | ||
144 | * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* | 154 | * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* |
145 | * @stop_device:stops the whole device (embedded CPU put to reset) | 155 | * @stop_device:stops the whole device (embedded CPU put to reset) |
146 | * @send_cmd:send a host command | 156 | * @send_cmd:send a host command |
@@ -150,7 +160,6 @@ struct iwl_host_cmd { | |||
150 | * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is | 160 | * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is |
151 | * ready and a successful ADDBA response has been received. | 161 | * ready and a successful ADDBA response has been received. |
152 | * @tx_agg_disable: de-configure a Tx queue to send AMPDUs | 162 | * @tx_agg_disable: de-configure a Tx queue to send AMPDUs |
153 | * @kick_nic: remove the RESET from the embedded CPU and let it run | ||
154 | * @free: release all the ressource for the transport layer itself such as | 163 | * @free: release all the ressource for the transport layer itself such as |
155 | * irq, tasklet etc... | 164 | * irq, tasklet etc... |
156 | * @stop_queue: stop a specific queue | 165 | * @stop_queue: stop a specific queue |
@@ -160,15 +169,17 @@ struct iwl_host_cmd { | |||
160 | * automatically deleted. | 169 | * automatically deleted. |
161 | * @suspend: stop the device unless WoWLAN is configured | 170 | * @suspend: stop the device unless WoWLAN is configured |
162 | * @resume: resume activity of the device | 171 | * @resume: resume activity of the device |
172 | * @write8: write a u8 to a register at offset ofs from the BAR | ||
173 | * @write32: write a u32 to a register at offset ofs from the BAR | ||
174 | * @read32: read a u32 register at offset ofs from the BAR | ||
163 | */ | 175 | */ |
164 | struct iwl_trans_ops { | 176 | struct iwl_trans_ops { |
165 | 177 | ||
166 | struct iwl_trans *(*alloc)(struct iwl_shared *shrd); | 178 | int (*start_hw)(struct iwl_trans *iwl_trans); |
167 | int (*request_irq)(struct iwl_trans *iwl_trans); | 179 | void (*stop_hw)(struct iwl_trans *iwl_trans); |
168 | int (*start_device)(struct iwl_trans *trans); | 180 | int (*start_fw)(struct iwl_trans *trans, struct fw_img *fw); |
169 | int (*prepare_card_hw)(struct iwl_trans *trans); | 181 | void (*fw_alive)(struct iwl_trans *trans); |
170 | void (*stop_device)(struct iwl_trans *trans); | 182 | void (*stop_device)(struct iwl_trans *trans); |
171 | void (*tx_start)(struct iwl_trans *trans); | ||
172 | 183 | ||
173 | void (*wake_any_queue)(struct iwl_trans *trans, | 184 | void (*wake_any_queue)(struct iwl_trans *trans, |
174 | enum iwl_rxon_context_id ctx, | 185 | enum iwl_rxon_context_id ctx, |
@@ -191,8 +202,6 @@ struct iwl_trans_ops { | |||
191 | enum iwl_rxon_context_id ctx, int sta_id, int tid, | 202 | enum iwl_rxon_context_id ctx, int sta_id, int tid, |
192 | int frame_limit, u16 ssn); | 203 | int frame_limit, u16 ssn); |
193 | 204 | ||
194 | void (*kick_nic)(struct iwl_trans *trans); | ||
195 | |||
196 | void (*free)(struct iwl_trans *trans); | 205 | void (*free)(struct iwl_trans *trans); |
197 | 206 | ||
198 | void (*stop_queue)(struct iwl_trans *trans, int q, const char *msg); | 207 | void (*stop_queue)(struct iwl_trans *trans, int q, const char *msg); |
@@ -204,18 +213,9 @@ struct iwl_trans_ops { | |||
204 | int (*suspend)(struct iwl_trans *trans); | 213 | int (*suspend)(struct iwl_trans *trans); |
205 | int (*resume)(struct iwl_trans *trans); | 214 | int (*resume)(struct iwl_trans *trans); |
206 | #endif | 215 | #endif |
207 | }; | 216 | void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); |
208 | 217 | void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); | |
209 | /* one for each uCode image (inst/data, boot/init/runtime) */ | 218 | u32 (*read32)(struct iwl_trans *trans, u32 ofs); |
210 | struct fw_desc { | ||
211 | dma_addr_t p_addr; /* hardware address */ | ||
212 | void *v_addr; /* software address */ | ||
213 | u32 len; /* size in bytes */ | ||
214 | }; | ||
215 | |||
216 | struct fw_img { | ||
217 | struct fw_desc code; /* firmware code image */ | ||
218 | struct fw_desc data; /* firmware data image */ | ||
219 | }; | 219 | }; |
220 | 220 | ||
221 | /* Opaque calibration results */ | 221 | /* Opaque calibration results */ |
@@ -231,17 +231,31 @@ struct iwl_calib_result { | |||
231 | * @ops - pointer to iwl_trans_ops | 231 | * @ops - pointer to iwl_trans_ops |
232 | * @shrd - pointer to iwl_shared which holds shared data from the upper layer | 232 | * @shrd - pointer to iwl_shared which holds shared data from the upper layer |
233 | * @hcmd_lock: protects HCMD | 233 | * @hcmd_lock: protects HCMD |
234 | * @reg_lock - protect hw register access | ||
235 | * @dev - pointer to struct device * that represents the device | ||
236 | * @irq - the irq number for the device | ||
237 | * @hw_id: a u32 with the ID of the device / subdevice. | ||
238 | * Set during transport alloaction. | ||
239 | * @hw_id_str: a string with info about HW ID. Set during transport allocation. | ||
234 | * @ucode_write_complete: indicates that the ucode has been copied. | 240 | * @ucode_write_complete: indicates that the ucode has been copied. |
235 | * @ucode_rt: run time ucode image | 241 | * @ucode_rt: run time ucode image |
236 | * @ucode_init: init ucode image | 242 | * @ucode_init: init ucode image |
237 | * @ucode_wowlan: wake on wireless ucode image (optional) | 243 | * @ucode_wowlan: wake on wireless ucode image (optional) |
238 | * @nvm_device_type: indicates OTP or eeprom | 244 | * @nvm_device_type: indicates OTP or eeprom |
245 | * @pm_support: set to true in start_hw if link pm is supported | ||
239 | * @calib_results: list head for init calibration results | 246 | * @calib_results: list head for init calibration results |
240 | */ | 247 | */ |
241 | struct iwl_trans { | 248 | struct iwl_trans { |
242 | const struct iwl_trans_ops *ops; | 249 | const struct iwl_trans_ops *ops; |
243 | struct iwl_shared *shrd; | 250 | struct iwl_shared *shrd; |
244 | spinlock_t hcmd_lock; | 251 | spinlock_t hcmd_lock; |
252 | spinlock_t reg_lock; | ||
253 | |||
254 | struct device *dev; | ||
255 | unsigned int irq; | ||
256 | u32 hw_rev; | ||
257 | u32 hw_id; | ||
258 | char hw_id_str[52]; | ||
245 | 259 | ||
246 | u8 ucode_write_complete; /* the image write is complete */ | 260 | u8 ucode_write_complete; /* the image write is complete */ |
247 | struct fw_img ucode_rt; | 261 | struct fw_img ucode_rt; |
@@ -250,6 +264,7 @@ struct iwl_trans { | |||
250 | 264 | ||
251 | /* eeprom related variables */ | 265 | /* eeprom related variables */ |
252 | int nvm_device_type; | 266 | int nvm_device_type; |
267 | bool pm_support; | ||
253 | 268 | ||
254 | /* init calibration results */ | 269 | /* init calibration results */ |
255 | struct list_head calib_results; | 270 | struct list_head calib_results; |
@@ -259,29 +274,31 @@ struct iwl_trans { | |||
259 | char trans_specific[0] __attribute__((__aligned__(sizeof(void *)))); | 274 | char trans_specific[0] __attribute__((__aligned__(sizeof(void *)))); |
260 | }; | 275 | }; |
261 | 276 | ||
262 | static inline int iwl_trans_request_irq(struct iwl_trans *trans) | 277 | static inline int iwl_trans_start_hw(struct iwl_trans *trans) |
263 | { | 278 | { |
264 | return trans->ops->request_irq(trans); | 279 | return trans->ops->start_hw(trans); |
265 | } | 280 | } |
266 | 281 | ||
267 | static inline int iwl_trans_start_device(struct iwl_trans *trans) | 282 | static inline void iwl_trans_stop_hw(struct iwl_trans *trans) |
268 | { | 283 | { |
269 | return trans->ops->start_device(trans); | 284 | trans->ops->stop_hw(trans); |
270 | } | 285 | } |
271 | 286 | ||
272 | static inline int iwl_trans_prepare_card_hw(struct iwl_trans *trans) | 287 | static inline void iwl_trans_fw_alive(struct iwl_trans *trans) |
273 | { | 288 | { |
274 | return trans->ops->prepare_card_hw(trans); | 289 | trans->ops->fw_alive(trans); |
275 | } | 290 | } |
276 | 291 | ||
277 | static inline void iwl_trans_stop_device(struct iwl_trans *trans) | 292 | static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw) |
278 | { | 293 | { |
279 | trans->ops->stop_device(trans); | 294 | might_sleep(); |
295 | |||
296 | return trans->ops->start_fw(trans, fw); | ||
280 | } | 297 | } |
281 | 298 | ||
282 | static inline void iwl_trans_tx_start(struct iwl_trans *trans) | 299 | static inline void iwl_trans_stop_device(struct iwl_trans *trans) |
283 | { | 300 | { |
284 | trans->ops->tx_start(trans); | 301 | trans->ops->stop_device(trans); |
285 | } | 302 | } |
286 | 303 | ||
287 | static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, | 304 | static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, |
@@ -337,11 +354,6 @@ static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, | |||
337 | trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn); | 354 | trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn); |
338 | } | 355 | } |
339 | 356 | ||
340 | static inline void iwl_trans_kick_nic(struct iwl_trans *trans) | ||
341 | { | ||
342 | trans->ops->kick_nic(trans); | ||
343 | } | ||
344 | |||
345 | static inline void iwl_trans_free(struct iwl_trans *trans) | 357 | static inline void iwl_trans_free(struct iwl_trans *trans) |
346 | { | 358 | { |
347 | trans->ops->free(trans); | 359 | trans->ops->free(trans); |
@@ -380,13 +392,24 @@ static inline int iwl_trans_resume(struct iwl_trans *trans) | |||
380 | } | 392 | } |
381 | #endif | 393 | #endif |
382 | 394 | ||
395 | static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val) | ||
396 | { | ||
397 | trans->ops->write8(trans, ofs, val); | ||
398 | } | ||
399 | |||
400 | static inline void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val) | ||
401 | { | ||
402 | trans->ops->write32(trans, ofs, val); | ||
403 | } | ||
404 | |||
405 | static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs) | ||
406 | { | ||
407 | return trans->ops->read32(trans, ofs); | ||
408 | } | ||
409 | |||
383 | /***************************************************** | 410 | /***************************************************** |
384 | * Transport layers implementations | 411 | * Utils functions |
385 | ******************************************************/ | 412 | ******************************************************/ |
386 | extern const struct iwl_trans_ops trans_ops_pcie; | ||
387 | |||
388 | int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, | ||
389 | const void *data, size_t len); | ||
390 | void iwl_dealloc_ucode(struct iwl_trans *trans); | 413 | void iwl_dealloc_ucode(struct iwl_trans *trans); |
391 | 414 | ||
392 | int iwl_send_calib_results(struct iwl_trans *trans); | 415 | int iwl_send_calib_results(struct iwl_trans *trans); |
@@ -394,4 +417,18 @@ int iwl_calib_set(struct iwl_trans *trans, | |||
394 | const struct iwl_calib_hdr *cmd, int len); | 417 | const struct iwl_calib_hdr *cmd, int len); |
395 | void iwl_calib_free_results(struct iwl_trans *trans); | 418 | void iwl_calib_free_results(struct iwl_trans *trans); |
396 | 419 | ||
420 | /***************************************************** | ||
421 | * Transport layers implementations + their allocation function | ||
422 | ******************************************************/ | ||
423 | struct pci_dev; | ||
424 | struct pci_device_id; | ||
425 | extern const struct iwl_trans_ops trans_ops_pcie; | ||
426 | struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, | ||
427 | struct pci_dev *pdev, | ||
428 | const struct pci_device_id *ent); | ||
429 | |||
430 | extern const struct iwl_trans_ops trans_ops_idi; | ||
431 | struct iwl_trans *iwl_trans_idi_alloc(struct iwl_shared *shrd, | ||
432 | void *pdev_void, | ||
433 | const void *ent_void); | ||
397 | #endif /* __iwl_trans_h__ */ | 434 | #endif /* __iwl_trans_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 2edf0ef65a5b..11b659ab261d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c | |||
@@ -32,7 +32,9 @@ | |||
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
35 | #include <linux/firmware.h> | ||
35 | 36 | ||
37 | #include "iwl-ucode.h" | ||
36 | #include "iwl-wifi.h" | 38 | #include "iwl-wifi.h" |
37 | #include "iwl-dev.h" | 39 | #include "iwl-dev.h" |
38 | #include "iwl-core.h" | 40 | #include "iwl-core.h" |
@@ -80,29 +82,29 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | |||
80 | * | 82 | * |
81 | ******************************************************************************/ | 83 | ******************************************************************************/ |
82 | 84 | ||
83 | static void iwl_free_fw_desc(struct iwl_bus *bus, struct fw_desc *desc) | 85 | static void iwl_free_fw_desc(struct iwl_trans *trans, struct fw_desc *desc) |
84 | { | 86 | { |
85 | if (desc->v_addr) | 87 | if (desc->v_addr) |
86 | dma_free_coherent(bus->dev, desc->len, | 88 | dma_free_coherent(trans->dev, desc->len, |
87 | desc->v_addr, desc->p_addr); | 89 | desc->v_addr, desc->p_addr); |
88 | desc->v_addr = NULL; | 90 | desc->v_addr = NULL; |
89 | desc->len = 0; | 91 | desc->len = 0; |
90 | } | 92 | } |
91 | 93 | ||
92 | static void iwl_free_fw_img(struct iwl_bus *bus, struct fw_img *img) | 94 | static void iwl_free_fw_img(struct iwl_trans *trans, struct fw_img *img) |
93 | { | 95 | { |
94 | iwl_free_fw_desc(bus, &img->code); | 96 | iwl_free_fw_desc(trans, &img->code); |
95 | iwl_free_fw_desc(bus, &img->data); | 97 | iwl_free_fw_desc(trans, &img->data); |
96 | } | 98 | } |
97 | 99 | ||
98 | void iwl_dealloc_ucode(struct iwl_trans *trans) | 100 | void iwl_dealloc_ucode(struct iwl_trans *trans) |
99 | { | 101 | { |
100 | iwl_free_fw_img(bus(trans), &trans->ucode_rt); | 102 | iwl_free_fw_img(trans, &trans->ucode_rt); |
101 | iwl_free_fw_img(bus(trans), &trans->ucode_init); | 103 | iwl_free_fw_img(trans, &trans->ucode_init); |
102 | iwl_free_fw_img(bus(trans), &trans->ucode_wowlan); | 104 | iwl_free_fw_img(trans, &trans->ucode_wowlan); |
103 | } | 105 | } |
104 | 106 | ||
105 | int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, | 107 | static int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc, |
106 | const void *data, size_t len) | 108 | const void *data, size_t len) |
107 | { | 109 | { |
108 | if (!len) { | 110 | if (!len) { |
@@ -110,7 +112,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, | |||
110 | return -EINVAL; | 112 | return -EINVAL; |
111 | } | 113 | } |
112 | 114 | ||
113 | desc->v_addr = dma_alloc_coherent(bus->dev, len, | 115 | desc->v_addr = dma_alloc_coherent(trans->dev, len, |
114 | &desc->p_addr, GFP_KERNEL); | 116 | &desc->p_addr, GFP_KERNEL); |
115 | if (!desc->v_addr) | 117 | if (!desc->v_addr) |
116 | return -ENOMEM; | 118 | return -ENOMEM; |
@@ -120,59 +122,6 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, | |||
120 | return 0; | 122 | return 0; |
121 | } | 123 | } |
122 | 124 | ||
123 | /* | ||
124 | * ucode | ||
125 | */ | ||
126 | static int iwl_load_section(struct iwl_trans *trans, const char *name, | ||
127 | struct fw_desc *image, u32 dst_addr) | ||
128 | { | ||
129 | struct iwl_bus *bus = bus(trans); | ||
130 | dma_addr_t phy_addr = image->p_addr; | ||
131 | u32 byte_cnt = image->len; | ||
132 | int ret; | ||
133 | |||
134 | trans->ucode_write_complete = 0; | ||
135 | |||
136 | iwl_write_direct32(bus, | ||
137 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
138 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
139 | |||
140 | iwl_write_direct32(bus, | ||
141 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | ||
142 | |||
143 | iwl_write_direct32(bus, | ||
144 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | ||
145 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
146 | |||
147 | iwl_write_direct32(bus, | ||
148 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | ||
149 | (iwl_get_dma_hi_addr(phy_addr) | ||
150 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | ||
151 | |||
152 | iwl_write_direct32(bus, | ||
153 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | ||
154 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | ||
155 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | ||
156 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
157 | |||
158 | iwl_write_direct32(bus, | ||
159 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
160 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
161 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | ||
162 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | ||
163 | |||
164 | IWL_DEBUG_FW(bus, "%s uCode section being loaded...\n", name); | ||
165 | ret = wait_event_timeout(trans->shrd->wait_command_queue, | ||
166 | trans->ucode_write_complete, 5 * HZ); | ||
167 | if (!ret) { | ||
168 | IWL_ERR(trans, "Could not load the %s uCode section\n", | ||
169 | name); | ||
170 | return -ETIMEDOUT; | ||
171 | } | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, | 125 | static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, |
177 | enum iwl_ucode_type ucode_type) | 126 | enum iwl_ucode_type ucode_type) |
178 | { | 127 | { |
@@ -189,28 +138,6 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, | |||
189 | return NULL; | 138 | return NULL; |
190 | } | 139 | } |
191 | 140 | ||
192 | static int iwl_load_given_ucode(struct iwl_trans *trans, | ||
193 | enum iwl_ucode_type ucode_type) | ||
194 | { | ||
195 | int ret = 0; | ||
196 | struct fw_img *image = iwl_get_ucode_image(trans, ucode_type); | ||
197 | |||
198 | |||
199 | if (!image) { | ||
200 | IWL_ERR(trans, "Invalid ucode requested (%d)\n", | ||
201 | ucode_type); | ||
202 | return -EINVAL; | ||
203 | } | ||
204 | |||
205 | ret = iwl_load_section(trans, "INST", &image->code, | ||
206 | IWLAGN_RTC_INST_LOWER_BOUND); | ||
207 | if (ret) | ||
208 | return ret; | ||
209 | |||
210 | return iwl_load_section(trans, "DATA", &image->data, | ||
211 | IWLAGN_RTC_DATA_LOWER_BOUND); | ||
212 | } | ||
213 | |||
214 | /* | 141 | /* |
215 | * Calibration | 142 | * Calibration |
216 | */ | 143 | */ |
@@ -447,7 +374,7 @@ static int iwl_alive_notify(struct iwl_trans *trans) | |||
447 | if (!priv->tx_cmd_pool) | 374 | if (!priv->tx_cmd_pool) |
448 | return -ENOMEM; | 375 | return -ENOMEM; |
449 | 376 | ||
450 | iwl_trans_tx_start(trans); | 377 | iwl_trans_fw_alive(trans); |
451 | for_each_context(priv, ctx) | 378 | for_each_context(priv, ctx) |
452 | ctx->last_tx_rejected = false; | 379 | ctx->last_tx_rejected = false; |
453 | 380 | ||
@@ -470,7 +397,7 @@ static int iwl_alive_notify(struct iwl_trans *trans) | |||
470 | * using sample data 100 bytes apart. If these sample points are good, | 397 | * using sample data 100 bytes apart. If these sample points are good, |
471 | * it's a pretty good bet that everything between them is good, too. | 398 | * it's a pretty good bet that everything between them is good, too. |
472 | */ | 399 | */ |
473 | static int iwl_verify_inst_sparse(struct iwl_bus *bus, | 400 | static int iwl_verify_inst_sparse(struct iwl_trans *trans, |
474 | struct fw_desc *fw_desc) | 401 | struct fw_desc *fw_desc) |
475 | { | 402 | { |
476 | __le32 *image = (__le32 *)fw_desc->v_addr; | 403 | __le32 *image = (__le32 *)fw_desc->v_addr; |
@@ -478,15 +405,15 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus, | |||
478 | u32 val; | 405 | u32 val; |
479 | u32 i; | 406 | u32 i; |
480 | 407 | ||
481 | IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len); | 408 | IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len); |
482 | 409 | ||
483 | for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { | 410 | for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { |
484 | /* read data comes through single port, auto-incr addr */ | 411 | /* read data comes through single port, auto-incr addr */ |
485 | /* NOTE: Use the debugless read so we don't flood kernel log | 412 | /* NOTE: Use the debugless read so we don't flood kernel log |
486 | * if IWL_DL_IO is set */ | 413 | * if IWL_DL_IO is set */ |
487 | iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR, | 414 | iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR, |
488 | i + IWLAGN_RTC_INST_LOWER_BOUND); | 415 | i + IWLAGN_RTC_INST_LOWER_BOUND); |
489 | val = iwl_read32(bus, HBUS_TARG_MEM_RDAT); | 416 | val = iwl_read32(trans, HBUS_TARG_MEM_RDAT); |
490 | if (val != le32_to_cpu(*image)) | 417 | if (val != le32_to_cpu(*image)) |
491 | return -EIO; | 418 | return -EIO; |
492 | } | 419 | } |
@@ -494,7 +421,7 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus, | |||
494 | return 0; | 421 | return 0; |
495 | } | 422 | } |
496 | 423 | ||
497 | static void iwl_print_mismatch_inst(struct iwl_bus *bus, | 424 | static void iwl_print_mismatch_inst(struct iwl_trans *trans, |
498 | struct fw_desc *fw_desc) | 425 | struct fw_desc *fw_desc) |
499 | { | 426 | { |
500 | __le32 *image = (__le32 *)fw_desc->v_addr; | 427 | __le32 *image = (__le32 *)fw_desc->v_addr; |
@@ -503,18 +430,18 @@ static void iwl_print_mismatch_inst(struct iwl_bus *bus, | |||
503 | u32 offs; | 430 | u32 offs; |
504 | int errors = 0; | 431 | int errors = 0; |
505 | 432 | ||
506 | IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len); | 433 | IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len); |
507 | 434 | ||
508 | iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR, | 435 | iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR, |
509 | IWLAGN_RTC_INST_LOWER_BOUND); | 436 | IWLAGN_RTC_INST_LOWER_BOUND); |
510 | 437 | ||
511 | for (offs = 0; | 438 | for (offs = 0; |
512 | offs < len && errors < 20; | 439 | offs < len && errors < 20; |
513 | offs += sizeof(u32), image++) { | 440 | offs += sizeof(u32), image++) { |
514 | /* read data comes through single port, auto-incr addr */ | 441 | /* read data comes through single port, auto-incr addr */ |
515 | val = iwl_read32(bus, HBUS_TARG_MEM_RDAT); | 442 | val = iwl_read32(trans, HBUS_TARG_MEM_RDAT); |
516 | if (val != le32_to_cpu(*image)) { | 443 | if (val != le32_to_cpu(*image)) { |
517 | IWL_ERR(bus, "uCode INST section at " | 444 | IWL_ERR(trans, "uCode INST section at " |
518 | "offset 0x%x, is 0x%x, s/b 0x%x\n", | 445 | "offset 0x%x, is 0x%x, s/b 0x%x\n", |
519 | offs, val, le32_to_cpu(*image)); | 446 | offs, val, le32_to_cpu(*image)); |
520 | errors++; | 447 | errors++; |
@@ -536,14 +463,14 @@ static int iwl_verify_ucode(struct iwl_trans *trans, | |||
536 | return -EINVAL; | 463 | return -EINVAL; |
537 | } | 464 | } |
538 | 465 | ||
539 | if (!iwl_verify_inst_sparse(bus(trans), &img->code)) { | 466 | if (!iwl_verify_inst_sparse(trans, &img->code)) { |
540 | IWL_DEBUG_FW(trans, "uCode is good in inst SRAM\n"); | 467 | IWL_DEBUG_FW(trans, "uCode is good in inst SRAM\n"); |
541 | return 0; | 468 | return 0; |
542 | } | 469 | } |
543 | 470 | ||
544 | IWL_ERR(trans, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); | 471 | IWL_ERR(trans, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); |
545 | 472 | ||
546 | iwl_print_mismatch_inst(bus(trans), &img->code); | 473 | iwl_print_mismatch_inst(trans, &img->code); |
547 | return -EIO; | 474 | return -EIO; |
548 | } | 475 | } |
549 | 476 | ||
@@ -647,28 +574,27 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans, | |||
647 | { | 574 | { |
648 | struct iwl_notification_wait alive_wait; | 575 | struct iwl_notification_wait alive_wait; |
649 | struct iwl_alive_data alive_data; | 576 | struct iwl_alive_data alive_data; |
577 | struct fw_img *fw; | ||
650 | int ret; | 578 | int ret; |
651 | enum iwl_ucode_type old_type; | 579 | enum iwl_ucode_type old_type; |
652 | 580 | ||
653 | ret = iwl_trans_start_device(trans); | ||
654 | if (ret) | ||
655 | return ret; | ||
656 | |||
657 | iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE, | 581 | iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE, |
658 | iwl_alive_fn, &alive_data); | 582 | iwl_alive_fn, &alive_data); |
659 | 583 | ||
660 | old_type = trans->shrd->ucode_type; | 584 | old_type = trans->shrd->ucode_type; |
661 | trans->shrd->ucode_type = ucode_type; | 585 | trans->shrd->ucode_type = ucode_type; |
586 | fw = iwl_get_ucode_image(trans, ucode_type); | ||
587 | |||
588 | if (!fw) | ||
589 | return -EINVAL; | ||
662 | 590 | ||
663 | ret = iwl_load_given_ucode(trans, ucode_type); | 591 | ret = iwl_trans_start_fw(trans, fw); |
664 | if (ret) { | 592 | if (ret) { |
665 | trans->shrd->ucode_type = old_type; | 593 | trans->shrd->ucode_type = old_type; |
666 | iwl_remove_notification(trans->shrd, &alive_wait); | 594 | iwl_remove_notification(trans->shrd, &alive_wait); |
667 | return ret; | 595 | return ret; |
668 | } | 596 | } |
669 | 597 | ||
670 | iwl_trans_kick_nic(trans); | ||
671 | |||
672 | /* | 598 | /* |
673 | * Some things may run in the background now, but we | 599 | * Some things may run in the background now, but we |
674 | * just wait for the ALIVE notification here. | 600 | * just wait for the ALIVE notification here. |
@@ -756,3 +682,609 @@ int iwl_run_init_ucode(struct iwl_trans *trans) | |||
756 | iwl_trans_stop_device(trans); | 682 | iwl_trans_stop_device(trans); |
757 | return ret; | 683 | return ret; |
758 | } | 684 | } |
685 | |||
686 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | ||
687 | |||
688 | #define UCODE_EXPERIMENTAL_INDEX 100 | ||
689 | #define UCODE_EXPERIMENTAL_TAG "exp" | ||
690 | |||
691 | int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | ||
692 | { | ||
693 | const char *name_pre = cfg(priv)->fw_name_pre; | ||
694 | char tag[8]; | ||
695 | |||
696 | if (first) { | ||
697 | #ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | ||
698 | priv->fw_index = UCODE_EXPERIMENTAL_INDEX; | ||
699 | strcpy(tag, UCODE_EXPERIMENTAL_TAG); | ||
700 | } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) { | ||
701 | #endif | ||
702 | priv->fw_index = cfg(priv)->ucode_api_max; | ||
703 | sprintf(tag, "%d", priv->fw_index); | ||
704 | } else { | ||
705 | priv->fw_index--; | ||
706 | sprintf(tag, "%d", priv->fw_index); | ||
707 | } | ||
708 | |||
709 | if (priv->fw_index < cfg(priv)->ucode_api_min) { | ||
710 | IWL_ERR(priv, "no suitable firmware found!\n"); | ||
711 | return -ENOENT; | ||
712 | } | ||
713 | |||
714 | sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); | ||
715 | |||
716 | IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n", | ||
717 | (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) | ||
718 | ? "EXPERIMENTAL " : "", | ||
719 | priv->firmware_name); | ||
720 | |||
721 | return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, | ||
722 | trans(priv)->dev, | ||
723 | GFP_KERNEL, priv, iwl_ucode_callback); | ||
724 | } | ||
725 | |||
726 | struct iwlagn_firmware_pieces { | ||
727 | const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data; | ||
728 | size_t inst_size, data_size, init_size, init_data_size, | ||
729 | wowlan_inst_size, wowlan_data_size; | ||
730 | |||
731 | u32 build; | ||
732 | |||
733 | u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; | ||
734 | u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; | ||
735 | }; | ||
736 | |||
737 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, | ||
738 | const struct firmware *ucode_raw, | ||
739 | struct iwlagn_firmware_pieces *pieces) | ||
740 | { | ||
741 | struct iwl_ucode_header *ucode = (void *)ucode_raw->data; | ||
742 | u32 api_ver, hdr_size; | ||
743 | const u8 *src; | ||
744 | |||
745 | priv->ucode_ver = le32_to_cpu(ucode->ver); | ||
746 | api_ver = IWL_UCODE_API(priv->ucode_ver); | ||
747 | |||
748 | switch (api_ver) { | ||
749 | default: | ||
750 | hdr_size = 28; | ||
751 | if (ucode_raw->size < hdr_size) { | ||
752 | IWL_ERR(priv, "File size too small!\n"); | ||
753 | return -EINVAL; | ||
754 | } | ||
755 | pieces->build = le32_to_cpu(ucode->u.v2.build); | ||
756 | pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); | ||
757 | pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); | ||
758 | pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); | ||
759 | pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); | ||
760 | src = ucode->u.v2.data; | ||
761 | break; | ||
762 | case 0: | ||
763 | case 1: | ||
764 | case 2: | ||
765 | hdr_size = 24; | ||
766 | if (ucode_raw->size < hdr_size) { | ||
767 | IWL_ERR(priv, "File size too small!\n"); | ||
768 | return -EINVAL; | ||
769 | } | ||
770 | pieces->build = 0; | ||
771 | pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size); | ||
772 | pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); | ||
773 | pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); | ||
774 | pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); | ||
775 | src = ucode->u.v1.data; | ||
776 | break; | ||
777 | } | ||
778 | |||
779 | /* Verify size of file vs. image size info in file's header */ | ||
780 | if (ucode_raw->size != hdr_size + pieces->inst_size + | ||
781 | pieces->data_size + pieces->init_size + | ||
782 | pieces->init_data_size) { | ||
783 | |||
784 | IWL_ERR(priv, | ||
785 | "uCode file size %d does not match expected size\n", | ||
786 | (int)ucode_raw->size); | ||
787 | return -EINVAL; | ||
788 | } | ||
789 | |||
790 | pieces->inst = src; | ||
791 | src += pieces->inst_size; | ||
792 | pieces->data = src; | ||
793 | src += pieces->data_size; | ||
794 | pieces->init = src; | ||
795 | src += pieces->init_size; | ||
796 | pieces->init_data = src; | ||
797 | src += pieces->init_data_size; | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | static int iwlagn_load_firmware(struct iwl_priv *priv, | ||
803 | const struct firmware *ucode_raw, | ||
804 | struct iwlagn_firmware_pieces *pieces, | ||
805 | struct iwlagn_ucode_capabilities *capa) | ||
806 | { | ||
807 | struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data; | ||
808 | struct iwl_ucode_tlv *tlv; | ||
809 | size_t len = ucode_raw->size; | ||
810 | const u8 *data; | ||
811 | int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; | ||
812 | int tmp; | ||
813 | u64 alternatives; | ||
814 | u32 tlv_len; | ||
815 | enum iwl_ucode_tlv_type tlv_type; | ||
816 | const u8 *tlv_data; | ||
817 | |||
818 | if (len < sizeof(*ucode)) { | ||
819 | IWL_ERR(priv, "uCode has invalid length: %zd\n", len); | ||
820 | return -EINVAL; | ||
821 | } | ||
822 | |||
823 | if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) { | ||
824 | IWL_ERR(priv, "invalid uCode magic: 0X%x\n", | ||
825 | le32_to_cpu(ucode->magic)); | ||
826 | return -EINVAL; | ||
827 | } | ||
828 | |||
829 | /* | ||
830 | * Check which alternatives are present, and "downgrade" | ||
831 | * when the chosen alternative is not present, warning | ||
832 | * the user when that happens. Some files may not have | ||
833 | * any alternatives, so don't warn in that case. | ||
834 | */ | ||
835 | alternatives = le64_to_cpu(ucode->alternatives); | ||
836 | tmp = wanted_alternative; | ||
837 | if (wanted_alternative > 63) | ||
838 | wanted_alternative = 63; | ||
839 | while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) | ||
840 | wanted_alternative--; | ||
841 | if (wanted_alternative && wanted_alternative != tmp) | ||
842 | IWL_WARN(priv, | ||
843 | "uCode alternative %d not available, choosing %d\n", | ||
844 | tmp, wanted_alternative); | ||
845 | |||
846 | priv->ucode_ver = le32_to_cpu(ucode->ver); | ||
847 | pieces->build = le32_to_cpu(ucode->build); | ||
848 | data = ucode->data; | ||
849 | |||
850 | len -= sizeof(*ucode); | ||
851 | |||
852 | while (len >= sizeof(*tlv)) { | ||
853 | u16 tlv_alt; | ||
854 | |||
855 | len -= sizeof(*tlv); | ||
856 | tlv = (void *)data; | ||
857 | |||
858 | tlv_len = le32_to_cpu(tlv->length); | ||
859 | tlv_type = le16_to_cpu(tlv->type); | ||
860 | tlv_alt = le16_to_cpu(tlv->alternative); | ||
861 | tlv_data = tlv->data; | ||
862 | |||
863 | if (len < tlv_len) { | ||
864 | IWL_ERR(priv, "invalid TLV len: %zd/%u\n", | ||
865 | len, tlv_len); | ||
866 | return -EINVAL; | ||
867 | } | ||
868 | len -= ALIGN(tlv_len, 4); | ||
869 | data += sizeof(*tlv) + ALIGN(tlv_len, 4); | ||
870 | |||
871 | /* | ||
872 | * Alternative 0 is always valid. | ||
873 | * | ||
874 | * Skip alternative TLVs that are not selected. | ||
875 | */ | ||
876 | if (tlv_alt != 0 && tlv_alt != wanted_alternative) | ||
877 | continue; | ||
878 | |||
879 | switch (tlv_type) { | ||
880 | case IWL_UCODE_TLV_INST: | ||
881 | pieces->inst = tlv_data; | ||
882 | pieces->inst_size = tlv_len; | ||
883 | break; | ||
884 | case IWL_UCODE_TLV_DATA: | ||
885 | pieces->data = tlv_data; | ||
886 | pieces->data_size = tlv_len; | ||
887 | break; | ||
888 | case IWL_UCODE_TLV_INIT: | ||
889 | pieces->init = tlv_data; | ||
890 | pieces->init_size = tlv_len; | ||
891 | break; | ||
892 | case IWL_UCODE_TLV_INIT_DATA: | ||
893 | pieces->init_data = tlv_data; | ||
894 | pieces->init_data_size = tlv_len; | ||
895 | break; | ||
896 | case IWL_UCODE_TLV_BOOT: | ||
897 | IWL_ERR(priv, "Found unexpected BOOT ucode\n"); | ||
898 | break; | ||
899 | case IWL_UCODE_TLV_PROBE_MAX_LEN: | ||
900 | if (tlv_len != sizeof(u32)) | ||
901 | goto invalid_tlv_len; | ||
902 | capa->max_probe_length = | ||
903 | le32_to_cpup((__le32 *)tlv_data); | ||
904 | break; | ||
905 | case IWL_UCODE_TLV_PAN: | ||
906 | if (tlv_len) | ||
907 | goto invalid_tlv_len; | ||
908 | capa->flags |= IWL_UCODE_TLV_FLAGS_PAN; | ||
909 | break; | ||
910 | case IWL_UCODE_TLV_FLAGS: | ||
911 | /* must be at least one u32 */ | ||
912 | if (tlv_len < sizeof(u32)) | ||
913 | goto invalid_tlv_len; | ||
914 | /* and a proper number of u32s */ | ||
915 | if (tlv_len % sizeof(u32)) | ||
916 | goto invalid_tlv_len; | ||
917 | /* | ||
918 | * This driver only reads the first u32 as | ||
919 | * right now no more features are defined, | ||
920 | * if that changes then either the driver | ||
921 | * will not work with the new firmware, or | ||
922 | * it'll not take advantage of new features. | ||
923 | */ | ||
924 | capa->flags = le32_to_cpup((__le32 *)tlv_data); | ||
925 | break; | ||
926 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: | ||
927 | if (tlv_len != sizeof(u32)) | ||
928 | goto invalid_tlv_len; | ||
929 | pieces->init_evtlog_ptr = | ||
930 | le32_to_cpup((__le32 *)tlv_data); | ||
931 | break; | ||
932 | case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: | ||
933 | if (tlv_len != sizeof(u32)) | ||
934 | goto invalid_tlv_len; | ||
935 | pieces->init_evtlog_size = | ||
936 | le32_to_cpup((__le32 *)tlv_data); | ||
937 | break; | ||
938 | case IWL_UCODE_TLV_INIT_ERRLOG_PTR: | ||
939 | if (tlv_len != sizeof(u32)) | ||
940 | goto invalid_tlv_len; | ||
941 | pieces->init_errlog_ptr = | ||
942 | le32_to_cpup((__le32 *)tlv_data); | ||
943 | break; | ||
944 | case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: | ||
945 | if (tlv_len != sizeof(u32)) | ||
946 | goto invalid_tlv_len; | ||
947 | pieces->inst_evtlog_ptr = | ||
948 | le32_to_cpup((__le32 *)tlv_data); | ||
949 | break; | ||
950 | case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: | ||
951 | if (tlv_len != sizeof(u32)) | ||
952 | goto invalid_tlv_len; | ||
953 | pieces->inst_evtlog_size = | ||
954 | le32_to_cpup((__le32 *)tlv_data); | ||
955 | break; | ||
956 | case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: | ||
957 | if (tlv_len != sizeof(u32)) | ||
958 | goto invalid_tlv_len; | ||
959 | pieces->inst_errlog_ptr = | ||
960 | le32_to_cpup((__le32 *)tlv_data); | ||
961 | break; | ||
962 | case IWL_UCODE_TLV_ENHANCE_SENS_TBL: | ||
963 | if (tlv_len) | ||
964 | goto invalid_tlv_len; | ||
965 | priv->enhance_sensitivity_table = true; | ||
966 | break; | ||
967 | case IWL_UCODE_TLV_WOWLAN_INST: | ||
968 | pieces->wowlan_inst = tlv_data; | ||
969 | pieces->wowlan_inst_size = tlv_len; | ||
970 | break; | ||
971 | case IWL_UCODE_TLV_WOWLAN_DATA: | ||
972 | pieces->wowlan_data = tlv_data; | ||
973 | pieces->wowlan_data_size = tlv_len; | ||
974 | break; | ||
975 | case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: | ||
976 | if (tlv_len != sizeof(u32)) | ||
977 | goto invalid_tlv_len; | ||
978 | capa->standard_phy_calibration_size = | ||
979 | le32_to_cpup((__le32 *)tlv_data); | ||
980 | break; | ||
981 | default: | ||
982 | IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type); | ||
983 | break; | ||
984 | } | ||
985 | } | ||
986 | |||
987 | if (len) { | ||
988 | IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len); | ||
989 | iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len); | ||
990 | return -EINVAL; | ||
991 | } | ||
992 | |||
993 | return 0; | ||
994 | |||
995 | invalid_tlv_len: | ||
996 | IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); | ||
997 | iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len); | ||
998 | |||
999 | return -EINVAL; | ||
1000 | } | ||
1001 | |||
1002 | /** | ||
1003 | * iwl_ucode_callback - callback when firmware was loaded | ||
1004 | * | ||
1005 | * If loaded successfully, copies the firmware into buffers | ||
1006 | * for the card to fetch (via DMA). | ||
1007 | */ | ||
1008 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | ||
1009 | { | ||
1010 | struct iwl_priv *priv = context; | ||
1011 | struct iwl_ucode_header *ucode; | ||
1012 | int err; | ||
1013 | struct iwlagn_firmware_pieces pieces; | ||
1014 | const unsigned int api_max = cfg(priv)->ucode_api_max; | ||
1015 | unsigned int api_ok = cfg(priv)->ucode_api_ok; | ||
1016 | const unsigned int api_min = cfg(priv)->ucode_api_min; | ||
1017 | u32 api_ver; | ||
1018 | char buildstr[25]; | ||
1019 | u32 build; | ||
1020 | struct iwlagn_ucode_capabilities ucode_capa = { | ||
1021 | .max_probe_length = 200, | ||
1022 | .standard_phy_calibration_size = | ||
1023 | IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE, | ||
1024 | }; | ||
1025 | |||
1026 | if (!api_ok) | ||
1027 | api_ok = api_max; | ||
1028 | |||
1029 | memset(&pieces, 0, sizeof(pieces)); | ||
1030 | |||
1031 | if (!ucode_raw) { | ||
1032 | if (priv->fw_index <= api_ok) | ||
1033 | IWL_ERR(priv, | ||
1034 | "request for firmware file '%s' failed.\n", | ||
1035 | priv->firmware_name); | ||
1036 | goto try_again; | ||
1037 | } | ||
1038 | |||
1039 | IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", | ||
1040 | priv->firmware_name, ucode_raw->size); | ||
1041 | |||
1042 | /* Make sure that we got at least the API version number */ | ||
1043 | if (ucode_raw->size < 4) { | ||
1044 | IWL_ERR(priv, "File size way too small!\n"); | ||
1045 | goto try_again; | ||
1046 | } | ||
1047 | |||
1048 | /* Data from ucode file: header followed by uCode images */ | ||
1049 | ucode = (struct iwl_ucode_header *)ucode_raw->data; | ||
1050 | |||
1051 | if (ucode->ver) | ||
1052 | err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces); | ||
1053 | else | ||
1054 | err = iwlagn_load_firmware(priv, ucode_raw, &pieces, | ||
1055 | &ucode_capa); | ||
1056 | |||
1057 | if (err) | ||
1058 | goto try_again; | ||
1059 | |||
1060 | api_ver = IWL_UCODE_API(priv->ucode_ver); | ||
1061 | build = pieces.build; | ||
1062 | |||
1063 | /* | ||
1064 | * api_ver should match the api version forming part of the | ||
1065 | * firmware filename ... but we don't check for that and only rely | ||
1066 | * on the API version read from firmware header from here on forward | ||
1067 | */ | ||
1068 | /* no api version check required for experimental uCode */ | ||
1069 | if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) { | ||
1070 | if (api_ver < api_min || api_ver > api_max) { | ||
1071 | IWL_ERR(priv, | ||
1072 | "Driver unable to support your firmware API. " | ||
1073 | "Driver supports v%u, firmware is v%u.\n", | ||
1074 | api_max, api_ver); | ||
1075 | goto try_again; | ||
1076 | } | ||
1077 | |||
1078 | if (api_ver < api_ok) { | ||
1079 | if (api_ok != api_max) | ||
1080 | IWL_ERR(priv, "Firmware has old API version, " | ||
1081 | "expected v%u through v%u, got v%u.\n", | ||
1082 | api_ok, api_max, api_ver); | ||
1083 | else | ||
1084 | IWL_ERR(priv, "Firmware has old API version, " | ||
1085 | "expected v%u, got v%u.\n", | ||
1086 | api_max, api_ver); | ||
1087 | IWL_ERR(priv, "New firmware can be obtained from " | ||
1088 | "http://www.intellinuxwireless.org/.\n"); | ||
1089 | } | ||
1090 | } | ||
1091 | |||
1092 | if (build) | ||
1093 | sprintf(buildstr, " build %u%s", build, | ||
1094 | (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) | ||
1095 | ? " (EXP)" : ""); | ||
1096 | else | ||
1097 | buildstr[0] = '\0'; | ||
1098 | |||
1099 | IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n", | ||
1100 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
1101 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
1102 | IWL_UCODE_API(priv->ucode_ver), | ||
1103 | IWL_UCODE_SERIAL(priv->ucode_ver), | ||
1104 | buildstr); | ||
1105 | |||
1106 | snprintf(priv->hw->wiphy->fw_version, | ||
1107 | sizeof(priv->hw->wiphy->fw_version), | ||
1108 | "%u.%u.%u.%u%s", | ||
1109 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
1110 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
1111 | IWL_UCODE_API(priv->ucode_ver), | ||
1112 | IWL_UCODE_SERIAL(priv->ucode_ver), | ||
1113 | buildstr); | ||
1114 | |||
1115 | /* | ||
1116 | * For any of the failures below (before allocating pci memory) | ||
1117 | * we will try to load a version with a smaller API -- maybe the | ||
1118 | * user just got a corrupted version of the latest API. | ||
1119 | */ | ||
1120 | |||
1121 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", | ||
1122 | priv->ucode_ver); | ||
1123 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n", | ||
1124 | pieces.inst_size); | ||
1125 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n", | ||
1126 | pieces.data_size); | ||
1127 | IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n", | ||
1128 | pieces.init_size); | ||
1129 | IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", | ||
1130 | pieces.init_data_size); | ||
1131 | |||
1132 | /* Verify that uCode images will fit in card's SRAM */ | ||
1133 | if (pieces.inst_size > hw_params(priv).max_inst_size) { | ||
1134 | IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", | ||
1135 | pieces.inst_size); | ||
1136 | goto try_again; | ||
1137 | } | ||
1138 | |||
1139 | if (pieces.data_size > hw_params(priv).max_data_size) { | ||
1140 | IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", | ||
1141 | pieces.data_size); | ||
1142 | goto try_again; | ||
1143 | } | ||
1144 | |||
1145 | if (pieces.init_size > hw_params(priv).max_inst_size) { | ||
1146 | IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", | ||
1147 | pieces.init_size); | ||
1148 | goto try_again; | ||
1149 | } | ||
1150 | |||
1151 | if (pieces.init_data_size > hw_params(priv).max_data_size) { | ||
1152 | IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", | ||
1153 | pieces.init_data_size); | ||
1154 | goto try_again; | ||
1155 | } | ||
1156 | |||
1157 | /* Allocate ucode buffers for card's bus-master loading ... */ | ||
1158 | |||
1159 | /* Runtime instructions and 2 copies of data: | ||
1160 | * 1) unmodified from disk | ||
1161 | * 2) backup cache for save/restore during power-downs */ | ||
1162 | if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.code, | ||
1163 | pieces.inst, pieces.inst_size)) | ||
1164 | goto err_pci_alloc; | ||
1165 | if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.data, | ||
1166 | pieces.data, pieces.data_size)) | ||
1167 | goto err_pci_alloc; | ||
1168 | |||
1169 | /* Initialization instructions and data */ | ||
1170 | if (pieces.init_size && pieces.init_data_size) { | ||
1171 | if (iwl_alloc_fw_desc(trans(priv), | ||
1172 | &trans(priv)->ucode_init.code, | ||
1173 | pieces.init, pieces.init_size)) | ||
1174 | goto err_pci_alloc; | ||
1175 | if (iwl_alloc_fw_desc(trans(priv), | ||
1176 | &trans(priv)->ucode_init.data, | ||
1177 | pieces.init_data, pieces.init_data_size)) | ||
1178 | goto err_pci_alloc; | ||
1179 | } | ||
1180 | |||
1181 | /* WoWLAN instructions and data */ | ||
1182 | if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { | ||
1183 | if (iwl_alloc_fw_desc(trans(priv), | ||
1184 | &trans(priv)->ucode_wowlan.code, | ||
1185 | pieces.wowlan_inst, | ||
1186 | pieces.wowlan_inst_size)) | ||
1187 | goto err_pci_alloc; | ||
1188 | if (iwl_alloc_fw_desc(trans(priv), | ||
1189 | &trans(priv)->ucode_wowlan.data, | ||
1190 | pieces.wowlan_data, | ||
1191 | pieces.wowlan_data_size)) | ||
1192 | goto err_pci_alloc; | ||
1193 | } | ||
1194 | |||
1195 | /* Now that we can no longer fail, copy information */ | ||
1196 | |||
1197 | /* | ||
1198 | * The (size - 16) / 12 formula is based on the information recorded | ||
1199 | * for each event, which is of mode 1 (including timestamp) for all | ||
1200 | * new microcodes that include this information. | ||
1201 | */ | ||
1202 | priv->init_evtlog_ptr = pieces.init_evtlog_ptr; | ||
1203 | if (pieces.init_evtlog_size) | ||
1204 | priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; | ||
1205 | else | ||
1206 | priv->init_evtlog_size = | ||
1207 | cfg(priv)->base_params->max_event_log_size; | ||
1208 | priv->init_errlog_ptr = pieces.init_errlog_ptr; | ||
1209 | priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr; | ||
1210 | if (pieces.inst_evtlog_size) | ||
1211 | priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; | ||
1212 | else | ||
1213 | priv->inst_evtlog_size = | ||
1214 | cfg(priv)->base_params->max_event_log_size; | ||
1215 | priv->inst_errlog_ptr = pieces.inst_errlog_ptr; | ||
1216 | #ifndef CONFIG_IWLWIFI_P2P | ||
1217 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | ||
1218 | #endif | ||
1219 | |||
1220 | priv->new_scan_threshold_behaviour = | ||
1221 | !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); | ||
1222 | |||
1223 | if (!(cfg(priv)->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) | ||
1224 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; | ||
1225 | |||
1226 | /* | ||
1227 | * if not PAN, then don't support P2P -- might be a uCode | ||
1228 | * packaging bug or due to the eeprom check above | ||
1229 | */ | ||
1230 | if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) | ||
1231 | ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P; | ||
1232 | |||
1233 | if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { | ||
1234 | priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; | ||
1235 | priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; | ||
1236 | } else { | ||
1237 | priv->sta_key_max_num = STA_KEY_MAX_NUM; | ||
1238 | priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; | ||
1239 | } | ||
1240 | /* | ||
1241 | * figure out the offset of chain noise reset and gain commands | ||
1242 | * base on the size of standard phy calibration commands table size | ||
1243 | */ | ||
1244 | if (ucode_capa.standard_phy_calibration_size > | ||
1245 | IWL_MAX_PHY_CALIBRATE_TBL_SIZE) | ||
1246 | ucode_capa.standard_phy_calibration_size = | ||
1247 | IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; | ||
1248 | |||
1249 | priv->phy_calib_chain_noise_reset_cmd = | ||
1250 | ucode_capa.standard_phy_calibration_size; | ||
1251 | priv->phy_calib_chain_noise_gain_cmd = | ||
1252 | ucode_capa.standard_phy_calibration_size + 1; | ||
1253 | |||
1254 | /* initialize all valid contexts */ | ||
1255 | iwl_init_context(priv, ucode_capa.flags); | ||
1256 | |||
1257 | /************************************************** | ||
1258 | * This is still part of probe() in a sense... | ||
1259 | * | ||
1260 | * 9. Setup and register with mac80211 and debugfs | ||
1261 | **************************************************/ | ||
1262 | err = iwlagn_mac_setup_register(priv, &ucode_capa); | ||
1263 | if (err) | ||
1264 | goto out_unbind; | ||
1265 | |||
1266 | err = iwl_dbgfs_register(priv, DRV_NAME); | ||
1267 | if (err) | ||
1268 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | ||
1269 | |||
1270 | /* We have our copies now, allow OS release its copies */ | ||
1271 | release_firmware(ucode_raw); | ||
1272 | complete(&priv->firmware_loading_complete); | ||
1273 | return; | ||
1274 | |||
1275 | try_again: | ||
1276 | /* try next, if any */ | ||
1277 | if (iwl_request_firmware(priv, false)) | ||
1278 | goto out_unbind; | ||
1279 | release_firmware(ucode_raw); | ||
1280 | return; | ||
1281 | |||
1282 | err_pci_alloc: | ||
1283 | IWL_ERR(priv, "failed to allocate pci memory\n"); | ||
1284 | iwl_dealloc_ucode(trans(priv)); | ||
1285 | out_unbind: | ||
1286 | complete(&priv->firmware_loading_complete); | ||
1287 | device_release_driver(trans(priv)->dev); | ||
1288 | release_firmware(ucode_raw); | ||
1289 | } | ||
1290 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.h b/drivers/net/wireless/iwlwifi/iwl-ucode.h new file mode 100644 index 000000000000..eccf92519a84 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.h | |||
@@ -0,0 +1,178 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_ucode_h__ | ||
64 | #define __iwl_ucode_h__ | ||
65 | |||
66 | /* v1/v2 uCode file layout */ | ||
67 | struct iwl_ucode_header { | ||
68 | __le32 ver; /* major/minor/API/serial */ | ||
69 | union { | ||
70 | struct { | ||
71 | __le32 inst_size; /* bytes of runtime code */ | ||
72 | __le32 data_size; /* bytes of runtime data */ | ||
73 | __le32 init_size; /* bytes of init code */ | ||
74 | __le32 init_data_size; /* bytes of init data */ | ||
75 | __le32 boot_size; /* bytes of bootstrap code */ | ||
76 | u8 data[0]; /* in same order as sizes */ | ||
77 | } v1; | ||
78 | struct { | ||
79 | __le32 build; /* build number */ | ||
80 | __le32 inst_size; /* bytes of runtime code */ | ||
81 | __le32 data_size; /* bytes of runtime data */ | ||
82 | __le32 init_size; /* bytes of init code */ | ||
83 | __le32 init_data_size; /* bytes of init data */ | ||
84 | __le32 boot_size; /* bytes of bootstrap code */ | ||
85 | u8 data[0]; /* in same order as sizes */ | ||
86 | } v2; | ||
87 | } u; | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * new TLV uCode file layout | ||
92 | * | ||
93 | * The new TLV file format contains TLVs, that each specify | ||
94 | * some piece of data. To facilitate "groups", for example | ||
95 | * different instruction image with different capabilities, | ||
96 | * bundled with the same init image, an alternative mechanism | ||
97 | * is provided: | ||
98 | * When the alternative field is 0, that means that the item | ||
99 | * is always valid. When it is non-zero, then it is only | ||
100 | * valid in conjunction with items of the same alternative, | ||
101 | * in which case the driver (user) selects one alternative | ||
102 | * to use. | ||
103 | */ | ||
104 | |||
105 | enum iwl_ucode_tlv_type { | ||
106 | IWL_UCODE_TLV_INVALID = 0, /* unused */ | ||
107 | IWL_UCODE_TLV_INST = 1, | ||
108 | IWL_UCODE_TLV_DATA = 2, | ||
109 | IWL_UCODE_TLV_INIT = 3, | ||
110 | IWL_UCODE_TLV_INIT_DATA = 4, | ||
111 | IWL_UCODE_TLV_BOOT = 5, | ||
112 | IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ | ||
113 | IWL_UCODE_TLV_PAN = 7, | ||
114 | IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, | ||
115 | IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, | ||
116 | IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, | ||
117 | IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, | ||
118 | IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, | ||
119 | IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, | ||
120 | IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, | ||
121 | IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, | ||
122 | IWL_UCODE_TLV_WOWLAN_INST = 16, | ||
123 | IWL_UCODE_TLV_WOWLAN_DATA = 17, | ||
124 | IWL_UCODE_TLV_FLAGS = 18, | ||
125 | }; | ||
126 | |||
127 | /** | ||
128 | * enum iwl_ucode_tlv_flag - ucode API flags | ||
129 | * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously | ||
130 | * was a separate TLV but moved here to save space. | ||
131 | * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, | ||
132 | * treats good CRC threshold as a boolean | ||
133 | * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). | ||
134 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. | ||
135 | */ | ||
136 | enum iwl_ucode_tlv_flag { | ||
137 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | ||
138 | IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), | ||
139 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), | ||
140 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | ||
141 | }; | ||
142 | |||
143 | struct iwl_ucode_tlv { | ||
144 | __le16 type; /* see above */ | ||
145 | __le16 alternative; /* see comment */ | ||
146 | __le32 length; /* not including type/length fields */ | ||
147 | u8 data[0]; | ||
148 | }; | ||
149 | |||
150 | #define IWL_TLV_UCODE_MAGIC 0x0a4c5749 | ||
151 | |||
152 | struct iwl_tlv_ucode_header { | ||
153 | /* | ||
154 | * The TLV style ucode header is distinguished from | ||
155 | * the v1/v2 style header by first four bytes being | ||
156 | * zero, as such is an invalid combination of | ||
157 | * major/minor/API/serial versions. | ||
158 | */ | ||
159 | __le32 zero; | ||
160 | __le32 magic; | ||
161 | u8 human_readable[64]; | ||
162 | __le32 ver; /* major/minor/API/serial */ | ||
163 | __le32 build; | ||
164 | __le64 alternatives; /* bitmask of valid alternatives */ | ||
165 | /* | ||
166 | * The data contained herein has a TLV layout, | ||
167 | * see above for the TLV header and types. | ||
168 | * Note that each TLV is padded to a length | ||
169 | * that is a multiple of 4 for alignment. | ||
170 | */ | ||
171 | u8 data[0]; | ||
172 | }; | ||
173 | |||
174 | struct iwl_priv; | ||
175 | |||
176 | int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first); | ||
177 | |||
178 | #endif /* __iwl_ucode_h__ */ | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/trace.h b/drivers/net/wireless/iwmc3200wifi/trace.h index abb4805fa8df..f5f7070b7e22 100644 --- a/drivers/net/wireless/iwmc3200wifi/trace.h +++ b/drivers/net/wireless/iwmc3200wifi/trace.h | |||
@@ -144,7 +144,7 @@ TRACE_EVENT(iwm_tx_packets, | |||
144 | 144 | ||
145 | TP_printk( | 145 | TP_printk( |
146 | IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, " | 146 | IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, " |
147 | "ra_tid 0x%x, credit_group 0x%x, embeded_packets %d, %d bytes", | 147 | "ra_tid 0x%x, credit_group 0x%x, embedded_packets %d, %d bytes", |
148 | IWM_PR_ARG, !__entry->eot ? "concatenated " : "", | 148 | IWM_PR_ARG, !__entry->eot ? "concatenated " : "", |
149 | __entry->eot, __entry->seq, __entry->color, __entry->ra_tid, | 149 | __entry->eot, __entry->seq, __entry->color, __entry->ra_tid, |
150 | __entry->credit_group, __entry->npkt, __entry->bytes | 150 | __entry->credit_group, __entry->npkt, __entry->bytes |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 6fef4925d13a..8d8ee639fe56 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -376,7 +376,12 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, | |||
376 | struct ieee80211_channel *chan, | 376 | struct ieee80211_channel *chan, |
377 | enum nl80211_channel_type channel_type) | 377 | enum nl80211_channel_type channel_type) |
378 | { | 378 | { |
379 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 379 | struct mwifiex_private *priv; |
380 | |||
381 | if (dev) | ||
382 | priv = mwifiex_netdev_get_priv(dev); | ||
383 | else | ||
384 | priv = mwifiex_cfg80211_get_priv(wiphy); | ||
380 | 385 | ||
381 | if (priv->media_connected) { | 386 | if (priv->media_connected) { |
382 | wiphy_err(wiphy, "This setting is valid only when station " | 387 | wiphy_err(wiphy, "This setting is valid only when station " |
@@ -534,6 +539,11 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
534 | ret = -EFAULT; | 539 | ret = -EFAULT; |
535 | } | 540 | } |
536 | 541 | ||
542 | /* Get DTIM period information from firmware */ | ||
543 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | ||
544 | HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, | ||
545 | &priv->dtim_period); | ||
546 | |||
537 | /* | 547 | /* |
538 | * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid | 548 | * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid |
539 | * MCS index values for us are 0 to 7. | 549 | * MCS index values for us are 0 to 7. |
@@ -568,8 +578,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
568 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | 578 | WLAN_CAPABILITY_SHORT_SLOT_TIME) |
569 | sinfo->bss_param.flags |= | 579 | sinfo->bss_param.flags |= |
570 | BSS_PARAM_FLAGS_SHORT_SLOT_TIME; | 580 | BSS_PARAM_FLAGS_SHORT_SLOT_TIME; |
571 | sinfo->bss_param.dtim_period = | 581 | sinfo->bss_param.dtim_period = priv->dtim_period; |
572 | priv->curr_bss_params.bss_descriptor.dtim_period; | ||
573 | sinfo->bss_param.beacon_interval = | 582 | sinfo->bss_param.beacon_interval = |
574 | priv->curr_bss_params.bss_descriptor.beacon_period; | 583 | priv->curr_bss_params.bss_descriptor.beacon_period; |
575 | } | 584 | } |
@@ -858,7 +867,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
858 | ret = mwifiex_set_rf_channel(priv, channel, | 867 | ret = mwifiex_set_rf_channel(priv, channel, |
859 | priv->adapter->channel_type); | 868 | priv->adapter->channel_type); |
860 | 869 | ||
861 | ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ | 870 | /* As this is new association, clear locally stored |
871 | * keys and security related flags */ | ||
872 | priv->sec_info.wpa_enabled = false; | ||
873 | priv->sec_info.wpa2_enabled = false; | ||
874 | priv->wep_key_curr_index = 0; | ||
875 | ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); | ||
862 | 876 | ||
863 | if (mode == NL80211_IFTYPE_ADHOC) { | 877 | if (mode == NL80211_IFTYPE_ADHOC) { |
864 | /* "privacy" is set only for ad-hoc mode */ | 878 | /* "privacy" is set only for ad-hoc mode */ |
@@ -903,6 +917,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
903 | dev_dbg(priv->adapter->dev, | 917 | dev_dbg(priv->adapter->dev, |
904 | "info: setting wep encryption" | 918 | "info: setting wep encryption" |
905 | " with key len %d\n", sme->key_len); | 919 | " with key len %d\n", sme->key_len); |
920 | priv->wep_key_curr_index = sme->key_idx; | ||
906 | ret = mwifiex_set_encode(priv, sme->key, sme->key_len, | 921 | ret = mwifiex_set_encode(priv, sme->key, sme->key_len, |
907 | sme->key_idx, 0); | 922 | sme->key_idx, 0); |
908 | } | 923 | } |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 84fcb741a296..ca59cc0d013e 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -280,6 +280,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
280 | adapter->adhoc_awake_period = 0; | 280 | adapter->adhoc_awake_period = 0; |
281 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); | 281 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); |
282 | adapter->arp_filter_size = 0; | 282 | adapter->arp_filter_size = 0; |
283 | adapter->channel_type = NL80211_CHAN_HT20; | ||
283 | } | 284 | } |
284 | 285 | ||
285 | /* | 286 | /* |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 3dc0f721c1db..52810b1497ea 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -249,7 +249,6 @@ struct mwifiex_bssdescriptor { | |||
249 | u32 channel; | 249 | u32 channel; |
250 | u32 freq; | 250 | u32 freq; |
251 | u16 beacon_period; | 251 | u16 beacon_period; |
252 | u8 dtim_period; | ||
253 | u8 erp_flags; | 252 | u8 erp_flags; |
254 | u32 bss_mode; | 253 | u32 bss_mode; |
255 | u8 supported_rates[MWIFIEX_SUPPORTED_RATES]; | 254 | u8 supported_rates[MWIFIEX_SUPPORTED_RATES]; |
@@ -392,6 +391,7 @@ struct mwifiex_private { | |||
392 | u8 prev_bssid[ETH_ALEN]; | 391 | u8 prev_bssid[ETH_ALEN]; |
393 | struct mwifiex_current_bss_params curr_bss_params; | 392 | struct mwifiex_current_bss_params curr_bss_params; |
394 | u16 beacon_period; | 393 | u16 beacon_period; |
394 | u8 dtim_period; | ||
395 | u16 listen_interval; | 395 | u16 listen_interval; |
396 | u16 atim_window; | 396 | u16 atim_window; |
397 | u8 adhoc_channel; | 397 | u8 adhoc_channel; |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 135208596aff..98f1ca9cd6d8 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1086,7 +1086,6 @@ mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | |||
1086 | struct ieee_types_vendor_specific *vendor_ie; | 1086 | struct ieee_types_vendor_specific *vendor_ie; |
1087 | const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; | 1087 | const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; |
1088 | const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; | 1088 | const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; |
1089 | struct ieee80211_tim_ie *tim_ie; | ||
1090 | 1089 | ||
1091 | found_data_rate_ie = false; | 1090 | found_data_rate_ie = false; |
1092 | rate_size = 0; | 1091 | rate_size = 0; |
@@ -1259,11 +1258,6 @@ mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | |||
1259 | sizeof(struct ieee_types_header) - | 1258 | sizeof(struct ieee_types_header) - |
1260 | bss_entry->beacon_buf); | 1259 | bss_entry->beacon_buf); |
1261 | break; | 1260 | break; |
1262 | case WLAN_EID_TIM: | ||
1263 | tim_ie = (void *) (current_ptr + | ||
1264 | sizeof(struct ieee_types_header)); | ||
1265 | bss_entry->dtim_period = tim_ie->dtim_period; | ||
1266 | break; | ||
1267 | default: | 1261 | default: |
1268 | break; | 1262 | break; |
1269 | } | 1263 | } |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 6e443ffa0465..324c651527cb 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -103,7 +103,7 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv, | |||
103 | static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, | 103 | static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, |
104 | struct host_cmd_ds_command *cmd, | 104 | struct host_cmd_ds_command *cmd, |
105 | u16 cmd_action, u32 cmd_oid, | 105 | u16 cmd_action, u32 cmd_oid, |
106 | u32 *ul_temp) | 106 | u16 *ul_temp) |
107 | { | 107 | { |
108 | struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; | 108 | struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; |
109 | 109 | ||
@@ -112,62 +112,18 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, | |||
112 | cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) | 112 | cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) |
113 | - 1 + S_DS_GEN); | 113 | - 1 + S_DS_GEN); |
114 | 114 | ||
115 | snmp_mib->oid = cpu_to_le16((u16)cmd_oid); | ||
115 | if (cmd_action == HostCmd_ACT_GEN_GET) { | 116 | if (cmd_action == HostCmd_ACT_GEN_GET) { |
116 | snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET); | 117 | snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET); |
117 | snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE); | 118 | snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE); |
118 | cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) | 119 | le16_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE); |
119 | + MAX_SNMP_BUF_SIZE); | 120 | } else if (cmd_action == HostCmd_ACT_GEN_SET) { |
121 | snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); | ||
122 | snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); | ||
123 | *((__le16 *) (snmp_mib->value)) = cpu_to_le16(*ul_temp); | ||
124 | le16_add_cpu(&cmd->size, sizeof(u16)); | ||
120 | } | 125 | } |
121 | 126 | ||
122 | switch (cmd_oid) { | ||
123 | case FRAG_THRESH_I: | ||
124 | snmp_mib->oid = cpu_to_le16((u16) FRAG_THRESH_I); | ||
125 | if (cmd_action == HostCmd_ACT_GEN_SET) { | ||
126 | snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); | ||
127 | snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); | ||
128 | *((__le16 *) (snmp_mib->value)) = | ||
129 | cpu_to_le16((u16) *ul_temp); | ||
130 | cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) | ||
131 | + sizeof(u16)); | ||
132 | } | ||
133 | break; | ||
134 | case RTS_THRESH_I: | ||
135 | snmp_mib->oid = cpu_to_le16((u16) RTS_THRESH_I); | ||
136 | if (cmd_action == HostCmd_ACT_GEN_SET) { | ||
137 | snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); | ||
138 | snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); | ||
139 | *(__le16 *) (snmp_mib->value) = | ||
140 | cpu_to_le16((u16) *ul_temp); | ||
141 | cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) | ||
142 | + sizeof(u16)); | ||
143 | } | ||
144 | break; | ||
145 | |||
146 | case SHORT_RETRY_LIM_I: | ||
147 | snmp_mib->oid = cpu_to_le16((u16) SHORT_RETRY_LIM_I); | ||
148 | if (cmd_action == HostCmd_ACT_GEN_SET) { | ||
149 | snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); | ||
150 | snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); | ||
151 | *((__le16 *) (snmp_mib->value)) = | ||
152 | cpu_to_le16((u16) *ul_temp); | ||
153 | cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) | ||
154 | + sizeof(u16)); | ||
155 | } | ||
156 | break; | ||
157 | case DOT11D_I: | ||
158 | snmp_mib->oid = cpu_to_le16((u16) DOT11D_I); | ||
159 | if (cmd_action == HostCmd_ACT_GEN_SET) { | ||
160 | snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); | ||
161 | snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); | ||
162 | *((__le16 *) (snmp_mib->value)) = | ||
163 | cpu_to_le16((u16) *ul_temp); | ||
164 | cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) | ||
165 | + sizeof(u16)); | ||
166 | } | ||
167 | break; | ||
168 | default: | ||
169 | break; | ||
170 | } | ||
171 | dev_dbg(priv->adapter->dev, | 127 | dev_dbg(priv->adapter->dev, |
172 | "cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x," | 128 | "cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x," |
173 | " Value=0x%x\n", | 129 | " Value=0x%x\n", |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index e812db8b695c..0d8618a8443f 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -210,6 +210,9 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv, | |||
210 | dev_dbg(priv->adapter->dev, | 210 | dev_dbg(priv->adapter->dev, |
211 | "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp); | 211 | "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp); |
212 | break; | 212 | break; |
213 | case DTIM_PERIOD_I: | ||
214 | dev_dbg(priv->adapter->dev, | ||
215 | "info: SNMP_RESP: DTIM period=%u\n", ul_temp); | ||
213 | default: | 216 | default: |
214 | break; | 217 | break; |
215 | } | 218 | } |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 91c5f74350b7..b48674b577e6 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -402,6 +402,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { | |||
402 | #define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ | 402 | #define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ |
403 | #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 | 403 | #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 |
404 | #define MWL8K_CMD_GET_WATCHDOG_BITMAP 0x0205 | 404 | #define MWL8K_CMD_GET_WATCHDOG_BITMAP 0x0205 |
405 | #define MWL8K_CMD_DEL_MAC_ADDR 0x0206 /* per-vif */ | ||
405 | #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ | 406 | #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ |
406 | #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ | 407 | #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ |
407 | #define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ | 408 | #define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ |
@@ -3429,10 +3430,7 @@ static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable) | |||
3429 | return rc; | 3430 | return rc; |
3430 | } | 3431 | } |
3431 | 3432 | ||
3432 | /* | 3433 | struct mwl8k_cmd_update_mac_addr { |
3433 | * CMD_SET_MAC_ADDR. | ||
3434 | */ | ||
3435 | struct mwl8k_cmd_set_mac_addr { | ||
3436 | struct mwl8k_cmd_pkt header; | 3434 | struct mwl8k_cmd_pkt header; |
3437 | union { | 3435 | union { |
3438 | struct { | 3436 | struct { |
@@ -3448,12 +3446,12 @@ struct mwl8k_cmd_set_mac_addr { | |||
3448 | #define MWL8K_MAC_TYPE_PRIMARY_AP 2 | 3446 | #define MWL8K_MAC_TYPE_PRIMARY_AP 2 |
3449 | #define MWL8K_MAC_TYPE_SECONDARY_AP 3 | 3447 | #define MWL8K_MAC_TYPE_SECONDARY_AP 3 |
3450 | 3448 | ||
3451 | static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, | 3449 | static int mwl8k_cmd_update_mac_addr(struct ieee80211_hw *hw, |
3452 | struct ieee80211_vif *vif, u8 *mac) | 3450 | struct ieee80211_vif *vif, u8 *mac, bool set) |
3453 | { | 3451 | { |
3454 | struct mwl8k_priv *priv = hw->priv; | 3452 | struct mwl8k_priv *priv = hw->priv; |
3455 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | 3453 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); |
3456 | struct mwl8k_cmd_set_mac_addr *cmd; | 3454 | struct mwl8k_cmd_update_mac_addr *cmd; |
3457 | int mac_type; | 3455 | int mac_type; |
3458 | int rc; | 3456 | int rc; |
3459 | 3457 | ||
@@ -3474,7 +3472,11 @@ static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, | |||
3474 | if (cmd == NULL) | 3472 | if (cmd == NULL) |
3475 | return -ENOMEM; | 3473 | return -ENOMEM; |
3476 | 3474 | ||
3477 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); | 3475 | if (set) |
3476 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); | ||
3477 | else | ||
3478 | cmd->header.code = cpu_to_le16(MWL8K_CMD_DEL_MAC_ADDR); | ||
3479 | |||
3478 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 3480 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
3479 | if (priv->ap_fw) { | 3481 | if (priv->ap_fw) { |
3480 | cmd->mbss.mac_type = cpu_to_le16(mac_type); | 3482 | cmd->mbss.mac_type = cpu_to_le16(mac_type); |
@@ -3490,6 +3492,24 @@ static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, | |||
3490 | } | 3492 | } |
3491 | 3493 | ||
3492 | /* | 3494 | /* |
3495 | * MWL8K_CMD_SET_MAC_ADDR. | ||
3496 | */ | ||
3497 | static inline int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, | ||
3498 | struct ieee80211_vif *vif, u8 *mac) | ||
3499 | { | ||
3500 | return mwl8k_cmd_update_mac_addr(hw, vif, mac, true); | ||
3501 | } | ||
3502 | |||
3503 | /* | ||
3504 | * MWL8K_CMD_DEL_MAC_ADDR. | ||
3505 | */ | ||
3506 | static inline int mwl8k_cmd_del_mac_addr(struct ieee80211_hw *hw, | ||
3507 | struct ieee80211_vif *vif, u8 *mac) | ||
3508 | { | ||
3509 | return mwl8k_cmd_update_mac_addr(hw, vif, mac, false); | ||
3510 | } | ||
3511 | |||
3512 | /* | ||
3493 | * CMD_SET_RATEADAPT_MODE. | 3513 | * CMD_SET_RATEADAPT_MODE. |
3494 | */ | 3514 | */ |
3495 | struct mwl8k_cmd_set_rate_adapt_mode { | 3515 | struct mwl8k_cmd_set_rate_adapt_mode { |
@@ -4541,7 +4561,7 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, | |||
4541 | if (priv->ap_fw) | 4561 | if (priv->ap_fw) |
4542 | mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr); | 4562 | mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr); |
4543 | 4563 | ||
4544 | mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00"); | 4564 | mwl8k_cmd_del_mac_addr(hw, vif, vif->addr); |
4545 | 4565 | ||
4546 | mwl8k_remove_vif(priv, mwl8k_vif); | 4566 | mwl8k_remove_vif(priv, mwl8k_vif); |
4547 | } | 4567 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 2571a2fa3d09..06acabd02984 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -1796,6 +1796,14 @@ struct mac_iveiv_entry { | |||
1796 | #define RFCSR2_RESCAL_EN FIELD8(0x80) | 1796 | #define RFCSR2_RESCAL_EN FIELD8(0x80) |
1797 | 1797 | ||
1798 | /* | 1798 | /* |
1799 | * RFCSR 3: | ||
1800 | */ | ||
1801 | #define RFCSR3_K FIELD8(0x0f) | ||
1802 | /* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */ | ||
1803 | #define RFCSR3_PA1_BIAS_CCK FIELD8(0x70); | ||
1804 | #define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80); | ||
1805 | |||
1806 | /* | ||
1799 | * FRCSR 5: | 1807 | * FRCSR 5: |
1800 | */ | 1808 | */ |
1801 | #define RFCSR5_R1 FIELD8(0x0c) | 1809 | #define RFCSR5_R1 FIELD8(0x0c) |
@@ -1811,10 +1819,12 @@ struct mac_iveiv_entry { | |||
1811 | * RFCSR 7: | 1819 | * RFCSR 7: |
1812 | */ | 1820 | */ |
1813 | #define RFCSR7_RF_TUNING FIELD8(0x01) | 1821 | #define RFCSR7_RF_TUNING FIELD8(0x01) |
1814 | #define RFCSR7_R02 FIELD8(0x07) | 1822 | #define RFCSR7_BIT1 FIELD8(0x02) |
1815 | #define RFCSR7_R3 FIELD8(0x08) | 1823 | #define RFCSR7_BIT2 FIELD8(0x04) |
1816 | #define RFCSR7_R45 FIELD8(0x30) | 1824 | #define RFCSR7_BIT3 FIELD8(0x08) |
1817 | #define RFCSR7_R67 FIELD8(0xc0) | 1825 | #define RFCSR7_BIT4 FIELD8(0x10) |
1826 | #define RFCSR7_BIT5 FIELD8(0x20) | ||
1827 | #define RFCSR7_BITS67 FIELD8(0xc0) | ||
1818 | 1828 | ||
1819 | /* | 1829 | /* |
1820 | * RFCSR 11: | 1830 | * RFCSR 11: |
@@ -1839,6 +1849,11 @@ struct mac_iveiv_entry { | |||
1839 | #define RFCSR15_TX_LO2_EN FIELD8(0x08) | 1849 | #define RFCSR15_TX_LO2_EN FIELD8(0x08) |
1840 | 1850 | ||
1841 | /* | 1851 | /* |
1852 | * RFCSR 16: | ||
1853 | */ | ||
1854 | #define RFCSR16_TXMIXER_GAIN FIELD8(0x07) | ||
1855 | |||
1856 | /* | ||
1842 | * RFCSR 17: | 1857 | * RFCSR 17: |
1843 | */ | 1858 | */ |
1844 | #define RFCSR17_TXMIXER_GAIN FIELD8(0x07) | 1859 | #define RFCSR17_TXMIXER_GAIN FIELD8(0x07) |
@@ -1867,6 +1882,13 @@ struct mac_iveiv_entry { | |||
1867 | #define RFCSR23_FREQ_OFFSET FIELD8(0x7f) | 1882 | #define RFCSR23_FREQ_OFFSET FIELD8(0x7f) |
1868 | 1883 | ||
1869 | /* | 1884 | /* |
1885 | * RFCSR 24: | ||
1886 | */ | ||
1887 | #define RFCSR24_TX_AGC_FC FIELD8(0x1f) | ||
1888 | #define RFCSR24_TX_H20M FIELD8(0x20) | ||
1889 | #define RFCSR24_TX_CALIB FIELD8(0x7f) | ||
1890 | |||
1891 | /* | ||
1870 | * RFCSR 27: | 1892 | * RFCSR 27: |
1871 | */ | 1893 | */ |
1872 | #define RFCSR27_R1 FIELD8(0x03) | 1894 | #define RFCSR27_R1 FIELD8(0x03) |
@@ -1887,6 +1909,7 @@ struct mac_iveiv_entry { | |||
1887 | */ | 1909 | */ |
1888 | #define RFCSR31_RX_AGC_FC FIELD8(0x1f) | 1910 | #define RFCSR31_RX_AGC_FC FIELD8(0x1f) |
1889 | #define RFCSR31_RX_H20M FIELD8(0x20) | 1911 | #define RFCSR31_RX_H20M FIELD8(0x20) |
1912 | #define RFCSR31_RX_CALIB FIELD8(0x7f) | ||
1890 | 1913 | ||
1891 | /* | 1914 | /* |
1892 | * RFCSR 38: | 1915 | * RFCSR 38: |
@@ -2093,6 +2116,12 @@ struct mac_iveiv_entry { | |||
2093 | #define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) | 2116 | #define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) |
2094 | 2117 | ||
2095 | /* | 2118 | /* |
2119 | * EEPROM TXMIXER GAIN A offset (note overlaps with EEPROM RSSI A2). | ||
2120 | */ | ||
2121 | #define EEPROM_TXMIXER_GAIN_A 0x0026 | ||
2122 | #define EEPROM_TXMIXER_GAIN_A_VAL FIELD16(0x0007) | ||
2123 | |||
2124 | /* | ||
2096 | * EEPROM EIRP Maximum TX power values(unit: dbm) | 2125 | * EEPROM EIRP Maximum TX power values(unit: dbm) |
2097 | */ | 2126 | */ |
2098 | #define EEPROM_EIRP_MAX_TX_POWER 0x0027 | 2127 | #define EEPROM_EIRP_MAX_TX_POWER 0x0027 |
@@ -2422,4 +2451,16 @@ struct mac_iveiv_entry { | |||
2422 | */ | 2451 | */ |
2423 | #define EIRP_MAX_TX_POWER_LIMIT 0x50 | 2452 | #define EIRP_MAX_TX_POWER_LIMIT 0x50 |
2424 | 2453 | ||
2454 | /* | ||
2455 | * RT2800 driver data structure | ||
2456 | */ | ||
2457 | struct rt2800_drv_data { | ||
2458 | u8 calibration_bw20; | ||
2459 | u8 calibration_bw40; | ||
2460 | u8 bbp25; | ||
2461 | u8 bbp26; | ||
2462 | u8 txmixer_gain_24g; | ||
2463 | u8 txmixer_gain_5g; | ||
2464 | }; | ||
2465 | |||
2425 | #endif /* RT2800_H */ | 2466 | #endif /* RT2800_H */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index dbe7ece862f2..772d4aec303a 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1645,10 +1645,14 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, | |||
1645 | struct rf_channel *rf, | 1645 | struct rf_channel *rf, |
1646 | struct channel_info *info) | 1646 | struct channel_info *info) |
1647 | { | 1647 | { |
1648 | u8 rfcsr; | 1648 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; |
1649 | u8 rfcsr, calib_tx, calib_rx; | ||
1649 | 1650 | ||
1650 | rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); | 1651 | rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); |
1651 | rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); | 1652 | |
1653 | rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); | ||
1654 | rt2x00_set_field8(&rfcsr, RFCSR3_K, rf->rf3); | ||
1655 | rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); | ||
1652 | 1656 | ||
1653 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); | 1657 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); |
1654 | rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); | 1658 | rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); |
@@ -1662,16 +1666,82 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, | |||
1662 | rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2); | 1666 | rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2); |
1663 | rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); | 1667 | rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); |
1664 | 1668 | ||
1669 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); | ||
1670 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); | ||
1671 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); | ||
1672 | if (rt2x00_rt(rt2x00dev, RT3390)) { | ||
1673 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, | ||
1674 | rt2x00dev->default_ant.rx_chain_num == 1); | ||
1675 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, | ||
1676 | rt2x00dev->default_ant.tx_chain_num == 1); | ||
1677 | } else { | ||
1678 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); | ||
1679 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); | ||
1680 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); | ||
1681 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); | ||
1682 | |||
1683 | switch (rt2x00dev->default_ant.tx_chain_num) { | ||
1684 | case 1: | ||
1685 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); | ||
1686 | /* fall through */ | ||
1687 | case 2: | ||
1688 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); | ||
1689 | break; | ||
1690 | } | ||
1691 | |||
1692 | switch (rt2x00dev->default_ant.rx_chain_num) { | ||
1693 | case 1: | ||
1694 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); | ||
1695 | /* fall through */ | ||
1696 | case 2: | ||
1697 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); | ||
1698 | break; | ||
1699 | } | ||
1700 | } | ||
1701 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); | ||
1702 | |||
1703 | rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); | ||
1704 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | ||
1705 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
1706 | msleep(1); | ||
1707 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); | ||
1708 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
1709 | |||
1665 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); | 1710 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); |
1666 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); | 1711 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); |
1667 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | 1712 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); |
1668 | 1713 | ||
1669 | rt2800_rfcsr_write(rt2x00dev, 24, | 1714 | if (rt2x00_rt(rt2x00dev, RT3390)) { |
1670 | rt2x00dev->calibration[conf_is_ht40(conf)]); | 1715 | calib_tx = conf_is_ht40(conf) ? 0x68 : 0x4f; |
1716 | calib_rx = conf_is_ht40(conf) ? 0x6f : 0x4f; | ||
1717 | } else { | ||
1718 | if (conf_is_ht40(conf)) { | ||
1719 | calib_tx = drv_data->calibration_bw40; | ||
1720 | calib_rx = drv_data->calibration_bw40; | ||
1721 | } else { | ||
1722 | calib_tx = drv_data->calibration_bw20; | ||
1723 | calib_rx = drv_data->calibration_bw20; | ||
1724 | } | ||
1725 | } | ||
1726 | |||
1727 | rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr); | ||
1728 | rt2x00_set_field8(&rfcsr, RFCSR24_TX_CALIB, calib_tx); | ||
1729 | rt2800_rfcsr_write(rt2x00dev, 24, rfcsr); | ||
1730 | |||
1731 | rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr); | ||
1732 | rt2x00_set_field8(&rfcsr, RFCSR31_RX_CALIB, calib_rx); | ||
1733 | rt2800_rfcsr_write(rt2x00dev, 31, rfcsr); | ||
1671 | 1734 | ||
1672 | rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); | 1735 | rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); |
1673 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); | 1736 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); |
1674 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); | 1737 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); |
1738 | |||
1739 | rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); | ||
1740 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | ||
1741 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
1742 | msleep(1); | ||
1743 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); | ||
1744 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
1675 | } | 1745 | } |
1676 | 1746 | ||
1677 | static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | 1747 | static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, |
@@ -1679,12 +1749,13 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1679 | struct rf_channel *rf, | 1749 | struct rf_channel *rf, |
1680 | struct channel_info *info) | 1750 | struct channel_info *info) |
1681 | { | 1751 | { |
1752 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | ||
1682 | u8 rfcsr; | 1753 | u8 rfcsr; |
1683 | u32 reg; | 1754 | u32 reg; |
1684 | 1755 | ||
1685 | if (rf->channel <= 14) { | 1756 | if (rf->channel <= 14) { |
1686 | rt2800_bbp_write(rt2x00dev, 25, 0x15); | 1757 | rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25); |
1687 | rt2800_bbp_write(rt2x00dev, 26, 0x85); | 1758 | rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26); |
1688 | } else { | 1759 | } else { |
1689 | rt2800_bbp_write(rt2x00dev, 25, 0x09); | 1760 | rt2800_bbp_write(rt2x00dev, 25, 0x09); |
1690 | rt2800_bbp_write(rt2x00dev, 26, 0xff); | 1761 | rt2800_bbp_write(rt2x00dev, 26, 0xff); |
@@ -1712,8 +1783,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1712 | if (rf->channel <= 14) { | 1783 | if (rf->channel <= 14) { |
1713 | rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3); | 1784 | rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3); |
1714 | rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, | 1785 | rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, |
1715 | (info->default_power1 & 0x3) | | 1786 | info->default_power1); |
1716 | ((info->default_power1 & 0xC) << 1)); | ||
1717 | } else { | 1787 | } else { |
1718 | rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7); | 1788 | rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7); |
1719 | rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, | 1789 | rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, |
@@ -1726,8 +1796,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1726 | if (rf->channel <= 14) { | 1796 | if (rf->channel <= 14) { |
1727 | rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3); | 1797 | rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3); |
1728 | rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, | 1798 | rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, |
1729 | (info->default_power2 & 0x3) | | 1799 | info->default_power2); |
1730 | ((info->default_power2 & 0xC) << 1)); | ||
1731 | } else { | 1800 | } else { |
1732 | rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7); | 1801 | rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7); |
1733 | rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, | 1802 | rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, |
@@ -1737,11 +1806,12 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1737 | rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); | 1806 | rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); |
1738 | 1807 | ||
1739 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); | 1808 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); |
1740 | rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); | ||
1741 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); | 1809 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); |
1742 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); | 1810 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); |
1743 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); | 1811 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); |
1744 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); | 1812 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); |
1813 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); | ||
1814 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); | ||
1745 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { | 1815 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { |
1746 | if (rf->channel <= 14) { | 1816 | if (rf->channel <= 14) { |
1747 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); | 1817 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); |
@@ -1772,10 +1842,13 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1772 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); | 1842 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); |
1773 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | 1843 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); |
1774 | 1844 | ||
1775 | rt2800_rfcsr_write(rt2x00dev, 24, | 1845 | if (conf_is_ht40(conf)) { |
1776 | rt2x00dev->calibration[conf_is_ht40(conf)]); | 1846 | rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw40); |
1777 | rt2800_rfcsr_write(rt2x00dev, 31, | 1847 | rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw40); |
1778 | rt2x00dev->calibration[conf_is_ht40(conf)]); | 1848 | } else { |
1849 | rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw20); | ||
1850 | rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw20); | ||
1851 | } | ||
1779 | 1852 | ||
1780 | if (rf->channel <= 14) { | 1853 | if (rf->channel <= 14) { |
1781 | rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); | 1854 | rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); |
@@ -1783,7 +1856,10 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1783 | rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); | 1856 | rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); |
1784 | rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); | 1857 | rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); |
1785 | rt2800_rfcsr_write(rt2x00dev, 15, 0x53); | 1858 | rt2800_rfcsr_write(rt2x00dev, 15, 0x53); |
1786 | rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); | 1859 | rfcsr = 0x4c; |
1860 | rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN, | ||
1861 | drv_data->txmixer_gain_24g); | ||
1862 | rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); | ||
1787 | rt2800_rfcsr_write(rt2x00dev, 17, 0x23); | 1863 | rt2800_rfcsr_write(rt2x00dev, 17, 0x23); |
1788 | rt2800_rfcsr_write(rt2x00dev, 19, 0x93); | 1864 | rt2800_rfcsr_write(rt2x00dev, 19, 0x93); |
1789 | rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); | 1865 | rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); |
@@ -1792,12 +1868,20 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
1792 | rt2800_rfcsr_write(rt2x00dev, 27, 0x00); | 1868 | rt2800_rfcsr_write(rt2x00dev, 27, 0x00); |
1793 | rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); | 1869 | rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); |
1794 | } else { | 1870 | } else { |
1795 | rt2800_rfcsr_write(rt2x00dev, 7, 0x14); | 1871 | rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); |
1872 | rt2x00_set_field8(&rfcsr, RFCSR7_BIT2, 1); | ||
1873 | rt2x00_set_field8(&rfcsr, RFCSR7_BIT3, 0); | ||
1874 | rt2x00_set_field8(&rfcsr, RFCSR7_BIT4, 1); | ||
1875 | rt2x00_set_field8(&rfcsr, RFCSR7_BITS67, 0); | ||
1876 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); | ||
1796 | rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); | 1877 | rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); |
1797 | rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); | 1878 | rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); |
1798 | rt2800_rfcsr_write(rt2x00dev, 11, 0x00); | 1879 | rt2800_rfcsr_write(rt2x00dev, 11, 0x00); |
1799 | rt2800_rfcsr_write(rt2x00dev, 15, 0x43); | 1880 | rt2800_rfcsr_write(rt2x00dev, 15, 0x43); |
1800 | rt2800_rfcsr_write(rt2x00dev, 16, 0x7a); | 1881 | rfcsr = 0x7a; |
1882 | rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN, | ||
1883 | drv_data->txmixer_gain_5g); | ||
1884 | rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); | ||
1801 | rt2800_rfcsr_write(rt2x00dev, 17, 0x23); | 1885 | rt2800_rfcsr_write(rt2x00dev, 17, 0x23); |
1802 | if (rf->channel <= 64) { | 1886 | if (rf->channel <= 64) { |
1803 | rt2800_rfcsr_write(rt2x00dev, 19, 0xb7); | 1887 | rt2800_rfcsr_write(rt2x00dev, 19, 0xb7); |
@@ -3246,6 +3330,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, | |||
3246 | 3330 | ||
3247 | static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | 3331 | static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) |
3248 | { | 3332 | { |
3333 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | ||
3249 | u8 rfcsr; | 3334 | u8 rfcsr; |
3250 | u8 bbp; | 3335 | u8 bbp; |
3251 | u32 reg; | 3336 | u32 reg; |
@@ -3534,20 +3619,26 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
3534 | * Set RX Filter calibration for 20MHz and 40MHz | 3619 | * Set RX Filter calibration for 20MHz and 40MHz |
3535 | */ | 3620 | */ |
3536 | if (rt2x00_rt(rt2x00dev, RT3070)) { | 3621 | if (rt2x00_rt(rt2x00dev, RT3070)) { |
3537 | rt2x00dev->calibration[0] = | 3622 | drv_data->calibration_bw20 = |
3538 | rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); | 3623 | rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); |
3539 | rt2x00dev->calibration[1] = | 3624 | drv_data->calibration_bw40 = |
3540 | rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); | 3625 | rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); |
3541 | } else if (rt2x00_rt(rt2x00dev, RT3071) || | 3626 | } else if (rt2x00_rt(rt2x00dev, RT3071) || |
3542 | rt2x00_rt(rt2x00dev, RT3090) || | 3627 | rt2x00_rt(rt2x00dev, RT3090) || |
3543 | rt2x00_rt(rt2x00dev, RT3390) || | 3628 | rt2x00_rt(rt2x00dev, RT3390) || |
3544 | rt2x00_rt(rt2x00dev, RT3572)) { | 3629 | rt2x00_rt(rt2x00dev, RT3572)) { |
3545 | rt2x00dev->calibration[0] = | 3630 | drv_data->calibration_bw20 = |
3546 | rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13); | 3631 | rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13); |
3547 | rt2x00dev->calibration[1] = | 3632 | drv_data->calibration_bw40 = |
3548 | rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15); | 3633 | rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15); |
3549 | } | 3634 | } |
3550 | 3635 | ||
3636 | /* | ||
3637 | * Save BBP 25 & 26 values for later use in channel switching | ||
3638 | */ | ||
3639 | rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25); | ||
3640 | rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26); | ||
3641 | |||
3551 | if (!rt2x00_rt(rt2x00dev, RT5390)) { | 3642 | if (!rt2x00_rt(rt2x00dev, RT5390)) { |
3552 | /* | 3643 | /* |
3553 | * Set back to initial state | 3644 | * Set back to initial state |
@@ -3587,11 +3678,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
3587 | &rt2x00dev->cap_flags)) | 3678 | &rt2x00dev->cap_flags)) |
3588 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); | 3679 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); |
3589 | } | 3680 | } |
3590 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); | 3681 | rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN, |
3591 | if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1) | 3682 | drv_data->txmixer_gain_24g); |
3592 | rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN, | ||
3593 | rt2x00_get_field16(eeprom, | ||
3594 | EEPROM_TXMIXER_GAIN_BG_VAL)); | ||
3595 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | 3683 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); |
3596 | } | 3684 | } |
3597 | 3685 | ||
@@ -3799,6 +3887,7 @@ EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); | |||
3799 | 3887 | ||
3800 | int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | 3888 | int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) |
3801 | { | 3889 | { |
3890 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | ||
3802 | u16 word; | 3891 | u16 word; |
3803 | u8 *mac; | 3892 | u8 *mac; |
3804 | u8 default_lna_gain; | 3893 | u8 default_lna_gain; |
@@ -3882,6 +3971,14 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
3882 | rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); | 3971 | rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); |
3883 | rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); | 3972 | rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); |
3884 | 3973 | ||
3974 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); | ||
3975 | if ((word & 0x00ff) != 0x00ff) { | ||
3976 | drv_data->txmixer_gain_24g = | ||
3977 | rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); | ||
3978 | } else { | ||
3979 | drv_data->txmixer_gain_24g = 0; | ||
3980 | } | ||
3981 | |||
3885 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); | 3982 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); |
3886 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) | 3983 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) |
3887 | rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); | 3984 | rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); |
@@ -3891,6 +3988,14 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
3891 | default_lna_gain); | 3988 | default_lna_gain); |
3892 | rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); | 3989 | rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); |
3893 | 3990 | ||
3991 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); | ||
3992 | if ((word & 0x00ff) != 0x00ff) { | ||
3993 | drv_data->txmixer_gain_5g = | ||
3994 | rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); | ||
3995 | } else { | ||
3996 | drv_data->txmixer_gain_5g = 0; | ||
3997 | } | ||
3998 | |||
3894 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); | 3999 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); |
3895 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) | 4000 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) |
3896 | rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0); | 4001 | rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0); |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 4e985026985c..6ad692914ee9 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1093,6 +1093,7 @@ static const struct data_queue_desc rt2800pci_queue_bcn = { | |||
1093 | 1093 | ||
1094 | static const struct rt2x00_ops rt2800pci_ops = { | 1094 | static const struct rt2x00_ops rt2800pci_ops = { |
1095 | .name = KBUILD_MODNAME, | 1095 | .name = KBUILD_MODNAME, |
1096 | .drv_data_size = sizeof(struct rt2800_drv_data), | ||
1096 | .max_sta_intf = 1, | 1097 | .max_sta_intf = 1, |
1097 | .max_ap_intf = 8, | 1098 | .max_ap_intf = 8, |
1098 | .eeprom_size = EEPROM_SIZE, | 1099 | .eeprom_size = EEPROM_SIZE, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index f0074bcee7c9..d009b6b794bb 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -827,6 +827,7 @@ static const struct data_queue_desc rt2800usb_queue_bcn = { | |||
827 | 827 | ||
828 | static const struct rt2x00_ops rt2800usb_ops = { | 828 | static const struct rt2x00_ops rt2800usb_ops = { |
829 | .name = KBUILD_MODNAME, | 829 | .name = KBUILD_MODNAME, |
830 | .drv_data_size = sizeof(struct rt2800_drv_data), | ||
830 | .max_sta_intf = 1, | 831 | .max_sta_intf = 1, |
831 | .max_ap_intf = 8, | 832 | .max_ap_intf = 8, |
832 | .eeprom_size = EEPROM_SIZE, | 833 | .eeprom_size = EEPROM_SIZE, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index b03b22c47b18..ed2ae6efcaa3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -647,6 +647,7 @@ struct rt2x00lib_ops { | |||
647 | */ | 647 | */ |
648 | struct rt2x00_ops { | 648 | struct rt2x00_ops { |
649 | const char *name; | 649 | const char *name; |
650 | const unsigned int drv_data_size; | ||
650 | const unsigned int max_sta_intf; | 651 | const unsigned int max_sta_intf; |
651 | const unsigned int max_ap_intf; | 652 | const unsigned int max_ap_intf; |
652 | const unsigned int eeprom_size; | 653 | const unsigned int eeprom_size; |
@@ -742,6 +743,11 @@ struct rt2x00_dev { | |||
742 | const struct rt2x00_ops *ops; | 743 | const struct rt2x00_ops *ops; |
743 | 744 | ||
744 | /* | 745 | /* |
746 | * Driver data. | ||
747 | */ | ||
748 | void *drv_data; | ||
749 | |||
750 | /* | ||
745 | * IEEE80211 control structure. | 751 | * IEEE80211 control structure. |
746 | */ | 752 | */ |
747 | struct ieee80211_hw *hw; | 753 | struct ieee80211_hw *hw; |
@@ -886,18 +892,11 @@ struct rt2x00_dev { | |||
886 | u8 rssi_offset; | 892 | u8 rssi_offset; |
887 | 893 | ||
888 | /* | 894 | /* |
889 | * Frequency offset (for rt61pci & rt73usb). | 895 | * Frequency offset. |
890 | */ | 896 | */ |
891 | u8 freq_offset; | 897 | u8 freq_offset; |
892 | 898 | ||
893 | /* | 899 | /* |
894 | * Calibration information (for rt2800usb & rt2800pci). | ||
895 | * [0] -> BW20 | ||
896 | * [1] -> BW40 | ||
897 | */ | ||
898 | u8 calibration[2]; | ||
899 | |||
900 | /* | ||
901 | * Association id. | 900 | * Association id. |
902 | */ | 901 | */ |
903 | u16 aid; | 902 | u16 aid; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index c3e1aa7c1a80..bae5b01299ea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1121,6 +1121,18 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1121 | { | 1121 | { |
1122 | int retval = -ENOMEM; | 1122 | int retval = -ENOMEM; |
1123 | 1123 | ||
1124 | /* | ||
1125 | * Allocate the driver data memory, if necessary. | ||
1126 | */ | ||
1127 | if (rt2x00dev->ops->drv_data_size > 0) { | ||
1128 | rt2x00dev->drv_data = kzalloc(rt2x00dev->ops->drv_data_size, | ||
1129 | GFP_KERNEL); | ||
1130 | if (!rt2x00dev->drv_data) { | ||
1131 | retval = -ENOMEM; | ||
1132 | goto exit; | ||
1133 | } | ||
1134 | } | ||
1135 | |||
1124 | spin_lock_init(&rt2x00dev->irqmask_lock); | 1136 | spin_lock_init(&rt2x00dev->irqmask_lock); |
1125 | mutex_init(&rt2x00dev->csr_mutex); | 1137 | mutex_init(&rt2x00dev->csr_mutex); |
1126 | 1138 | ||
@@ -1261,6 +1273,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1261 | * Free queue structures. | 1273 | * Free queue structures. |
1262 | */ | 1274 | */ |
1263 | rt2x00queue_free(rt2x00dev); | 1275 | rt2x00queue_free(rt2x00dev); |
1276 | |||
1277 | /* | ||
1278 | * Free the driver data. | ||
1279 | */ | ||
1280 | if (rt2x00dev->drv_data) | ||
1281 | kfree(rt2x00dev->drv_data); | ||
1264 | } | 1282 | } |
1265 | EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); | 1283 | EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); |
1266 | 1284 | ||
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index f231b9180436..278e9f957e0d 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -296,12 +296,10 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
296 | * because that will cause nullfunc send by mac80211 | 296 | * because that will cause nullfunc send by mac80211 |
297 | * fail, and cause pkt loss, we have tested that 5mA | 297 | * fail, and cause pkt loss, we have tested that 5mA |
298 | * is worked very well */ | 298 | * is worked very well */ |
299 | if (!rtlpriv->psc.multi_buffered) { | 299 | if (!rtlpriv->psc.multi_buffered) |
300 | queue_delayed_work(rtlpriv->works.rtl_wq, | 300 | queue_delayed_work(rtlpriv->works.rtl_wq, |
301 | &rtlpriv->works.ps_work, | 301 | &rtlpriv->works.ps_work, |
302 | MSECS(5)); | 302 | MSECS(5)); |
303 | pr_info("In section\n"); | ||
304 | } | ||
305 | } else { | 303 | } else { |
306 | rtl_swlps_rf_awake(hw); | 304 | rtl_swlps_rf_awake(hw); |
307 | rtlpriv->psc.sw_ps_enabled = false; | 305 | rtlpriv->psc.sw_ps_enabled = false; |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 653fe728e4a2..07dd38efe62a 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -198,7 +198,7 @@ static bool _rtl_pci_platform_switch_device_pci_aspm( | |||
198 | } | 198 | } |
199 | 199 | ||
200 | /*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/ | 200 | /*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/ |
201 | static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) | 201 | static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) |
202 | { | 202 | { |
203 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 203 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
204 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 204 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
@@ -207,8 +207,6 @@ static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) | |||
207 | 207 | ||
208 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) | 208 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) |
209 | udelay(100); | 209 | udelay(100); |
210 | |||
211 | return true; | ||
212 | } | 210 | } |
213 | 211 | ||
214 | /*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ | 212 | /*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ |
@@ -1150,10 +1148,12 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, | |||
1150 | ring->idx = (ring->idx + 1) % ring->entries; | 1148 | ring->idx = (ring->idx + 1) % ring->entries; |
1151 | } | 1149 | } |
1152 | 1150 | ||
1153 | pci_free_consistent(rtlpci->pdev, | 1151 | if (ring->desc) { |
1154 | sizeof(*ring->desc) * ring->entries, | 1152 | pci_free_consistent(rtlpci->pdev, |
1155 | ring->desc, ring->dma); | 1153 | sizeof(*ring->desc) * ring->entries, |
1156 | ring->desc = NULL; | 1154 | ring->desc, ring->dma); |
1155 | ring->desc = NULL; | ||
1156 | } | ||
1157 | } | 1157 | } |
1158 | 1158 | ||
1159 | static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci) | 1159 | static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci) |
@@ -1177,12 +1177,14 @@ static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci) | |||
1177 | kfree_skb(skb); | 1177 | kfree_skb(skb); |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | pci_free_consistent(rtlpci->pdev, | 1180 | if (rtlpci->rx_ring[rx_queue_idx].desc) { |
1181 | pci_free_consistent(rtlpci->pdev, | ||
1181 | sizeof(*rtlpci->rx_ring[rx_queue_idx]. | 1182 | sizeof(*rtlpci->rx_ring[rx_queue_idx]. |
1182 | desc) * rtlpci->rxringcount, | 1183 | desc) * rtlpci->rxringcount, |
1183 | rtlpci->rx_ring[rx_queue_idx].desc, | 1184 | rtlpci->rx_ring[rx_queue_idx].desc, |
1184 | rtlpci->rx_ring[rx_queue_idx].dma); | 1185 | rtlpci->rx_ring[rx_queue_idx].dma); |
1185 | rtlpci->rx_ring[rx_queue_idx].desc = NULL; | 1186 | rtlpci->rx_ring[rx_queue_idx].desc = NULL; |
1187 | } | ||
1186 | } | 1188 | } |
1187 | } | 1189 | } |
1188 | 1190 | ||
@@ -1760,8 +1762,8 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1760 | if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { | 1762 | if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { |
1761 | RT_ASSERT(false, | 1763 | RT_ASSERT(false, |
1762 | "Unable to obtain 32bit DMA for consistent allocations\n"); | 1764 | "Unable to obtain 32bit DMA for consistent allocations\n"); |
1763 | pci_disable_device(pdev); | 1765 | err = -ENOMEM; |
1764 | return -ENOMEM; | 1766 | goto fail1; |
1765 | } | 1767 | } |
1766 | } | 1768 | } |
1767 | 1769 | ||
@@ -1803,7 +1805,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1803 | err = pci_request_regions(pdev, KBUILD_MODNAME); | 1805 | err = pci_request_regions(pdev, KBUILD_MODNAME); |
1804 | if (err) { | 1806 | if (err) { |
1805 | RT_ASSERT(false, "Can't obtain PCI resources\n"); | 1807 | RT_ASSERT(false, "Can't obtain PCI resources\n"); |
1806 | goto fail2; | 1808 | goto fail1; |
1807 | } | 1809 | } |
1808 | 1810 | ||
1809 | pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); | 1811 | pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); |
@@ -1816,6 +1818,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1816 | rtlpriv->cfg->bar_id, pmem_len); | 1818 | rtlpriv->cfg->bar_id, pmem_len); |
1817 | if (rtlpriv->io.pci_mem_start == 0) { | 1819 | if (rtlpriv->io.pci_mem_start == 0) { |
1818 | RT_ASSERT(false, "Can't map PCI mem\n"); | 1820 | RT_ASSERT(false, "Can't map PCI mem\n"); |
1821 | err = -ENOMEM; | ||
1819 | goto fail2; | 1822 | goto fail2; |
1820 | } | 1823 | } |
1821 | 1824 | ||
@@ -1832,8 +1835,10 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1832 | pci_write_config_byte(pdev, 0x04, 0x07); | 1835 | pci_write_config_byte(pdev, 0x04, 0x07); |
1833 | 1836 | ||
1834 | /* find adapter */ | 1837 | /* find adapter */ |
1835 | if (!_rtl_pci_find_adapter(pdev, hw)) | 1838 | if (!_rtl_pci_find_adapter(pdev, hw)) { |
1839 | err = -ENODEV; | ||
1836 | goto fail3; | 1840 | goto fail3; |
1841 | } | ||
1837 | 1842 | ||
1838 | /* Init IO handler */ | 1843 | /* Init IO handler */ |
1839 | _rtl_pci_io_handler_init(&pdev->dev, hw); | 1844 | _rtl_pci_io_handler_init(&pdev->dev, hw); |
@@ -1843,6 +1848,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1843 | 1848 | ||
1844 | if (rtlpriv->cfg->ops->init_sw_vars(hw)) { | 1849 | if (rtlpriv->cfg->ops->init_sw_vars(hw)) { |
1845 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n"); | 1850 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n"); |
1851 | err = -ENODEV; | ||
1846 | goto fail3; | 1852 | goto fail3; |
1847 | } | 1853 | } |
1848 | 1854 | ||
@@ -1887,7 +1893,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1887 | return 0; | 1893 | return 0; |
1888 | 1894 | ||
1889 | fail3: | 1895 | fail3: |
1890 | pci_set_drvdata(pdev, NULL); | ||
1891 | rtl_deinit_core(hw); | 1896 | rtl_deinit_core(hw); |
1892 | _rtl_pci_io_handler_release(hw); | 1897 | _rtl_pci_io_handler_release(hw); |
1893 | 1898 | ||
@@ -1899,10 +1904,12 @@ fail2: | |||
1899 | complete(&rtlpriv->firmware_loading_complete); | 1904 | complete(&rtlpriv->firmware_loading_complete); |
1900 | 1905 | ||
1901 | fail1: | 1906 | fail1: |
1902 | 1907 | if (hw) | |
1908 | ieee80211_free_hw(hw); | ||
1909 | pci_set_drvdata(pdev, NULL); | ||
1903 | pci_disable_device(pdev); | 1910 | pci_disable_device(pdev); |
1904 | 1911 | ||
1905 | return -ENODEV; | 1912 | return err; |
1906 | 1913 | ||
1907 | } | 1914 | } |
1908 | EXPORT_SYMBOL(rtl_pci_probe); | 1915 | EXPORT_SYMBOL(rtl_pci_probe); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c index 24b407ff0416..4737018c9daa 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c | |||
@@ -294,7 +294,7 @@ static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw) | |||
294 | de_digtable.min_undecorated_pwdb_for_dm = | 294 | de_digtable.min_undecorated_pwdb_for_dm = |
295 | rtlpriv->dm.UNDEC_SM_PWDB; | 295 | rtlpriv->dm.UNDEC_SM_PWDB; |
296 | RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, | 296 | RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, |
297 | "AP Ext Port or disconnet PWDB = 0x%x\n", | 297 | "AP Ext Port or disconnect PWDB = 0x%x\n", |
298 | de_digtable.min_undecorated_pwdb_for_dm); | 298 | de_digtable.min_undecorated_pwdb_for_dm); |
299 | } | 299 | } |
300 | 300 | ||
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index e5a2e0e9bc19..b58fef780ea0 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c | |||
@@ -13,6 +13,9 @@ | |||
13 | #include <linux/ssb/ssb_driver_chipcommon.h> | 13 | #include <linux/ssb/ssb_driver_chipcommon.h> |
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/export.h> | 15 | #include <linux/export.h> |
16 | #ifdef CONFIG_BCM47XX | ||
17 | #include <asm/mach-bcm47xx/nvram.h> | ||
18 | #endif | ||
16 | 19 | ||
17 | #include "ssb_private.h" | 20 | #include "ssb_private.h" |
18 | 21 | ||
@@ -92,10 +95,6 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, | |||
92 | u32 pmuctl, tmp, pllctl; | 95 | u32 pmuctl, tmp, pllctl; |
93 | unsigned int i; | 96 | unsigned int i; |
94 | 97 | ||
95 | if ((bus->chip_id == 0x5354) && !crystalfreq) { | ||
96 | /* The 5354 crystal freq is 25MHz */ | ||
97 | crystalfreq = 25000; | ||
98 | } | ||
99 | if (crystalfreq) | 98 | if (crystalfreq) |
100 | e = pmu0_plltab_find_entry(crystalfreq); | 99 | e = pmu0_plltab_find_entry(crystalfreq); |
101 | if (!e) | 100 | if (!e) |
@@ -321,7 +320,11 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) | |||
321 | u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ | 320 | u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ |
322 | 321 | ||
323 | if (bus->bustype == SSB_BUSTYPE_SSB) { | 322 | if (bus->bustype == SSB_BUSTYPE_SSB) { |
324 | /* TODO: The user may override the crystal frequency. */ | 323 | #ifdef CONFIG_BCM47XX |
324 | char buf[20]; | ||
325 | if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) | ||
326 | crystalfreq = simple_strtoul(buf, NULL, 0); | ||
327 | #endif | ||
325 | } | 328 | } |
326 | 329 | ||
327 | switch (bus->chip_id) { | 330 | switch (bus->chip_id) { |
@@ -330,7 +333,11 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) | |||
330 | ssb_pmu1_pllinit_r0(cc, crystalfreq); | 333 | ssb_pmu1_pllinit_r0(cc, crystalfreq); |
331 | break; | 334 | break; |
332 | case 0x4328: | 335 | case 0x4328: |
336 | ssb_pmu0_pllinit_r0(cc, crystalfreq); | ||
337 | break; | ||
333 | case 0x5354: | 338 | case 0x5354: |
339 | if (crystalfreq == 0) | ||
340 | crystalfreq = 25000; | ||
334 | ssb_pmu0_pllinit_r0(cc, crystalfreq); | 341 | ssb_pmu0_pllinit_r0(cc, crystalfreq); |
335 | break; | 342 | break; |
336 | case 0x4322: | 343 | case 0x4322: |
@@ -607,3 +614,34 @@ void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on) | |||
607 | 614 | ||
608 | EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); | 615 | EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); |
609 | EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); | 616 | EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); |
617 | |||
618 | u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) | ||
619 | { | ||
620 | struct ssb_bus *bus = cc->dev->bus; | ||
621 | |||
622 | switch (bus->chip_id) { | ||
623 | case 0x5354: | ||
624 | /* 5354 chip uses a non programmable PLL of frequency 240MHz */ | ||
625 | return 240000000; | ||
626 | default: | ||
627 | ssb_printk(KERN_ERR PFX | ||
628 | "ERROR: PMU cpu clock unknown for device %04X\n", | ||
629 | bus->chip_id); | ||
630 | return 0; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) | ||
635 | { | ||
636 | struct ssb_bus *bus = cc->dev->bus; | ||
637 | |||
638 | switch (bus->chip_id) { | ||
639 | case 0x5354: | ||
640 | return 120000000; | ||
641 | default: | ||
642 | ssb_printk(KERN_ERR PFX | ||
643 | "ERROR: PMU controlclock unknown for device %04X\n", | ||
644 | bus->chip_id); | ||
645 | return 0; | ||
646 | } | ||
647 | } | ||
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index ced501568594..7e2ddc042f5b 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -208,6 +208,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *mcore) | |||
208 | struct ssb_bus *bus = mcore->dev->bus; | 208 | struct ssb_bus *bus = mcore->dev->bus; |
209 | u32 pll_type, n, m, rate = 0; | 209 | u32 pll_type, n, m, rate = 0; |
210 | 210 | ||
211 | if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) | ||
212 | return ssb_pmu_get_cpu_clock(&bus->chipco); | ||
213 | |||
211 | if (bus->extif.dev) { | 214 | if (bus->extif.dev) { |
212 | ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); | 215 | ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); |
213 | } else if (bus->chipco.dev) { | 216 | } else if (bus->chipco.dev) { |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index bb6317fb925c..2a0a1b99e0e4 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -1094,6 +1094,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus) | |||
1094 | u32 plltype; | 1094 | u32 plltype; |
1095 | u32 clkctl_n, clkctl_m; | 1095 | u32 clkctl_n, clkctl_m; |
1096 | 1096 | ||
1097 | if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) | ||
1098 | return ssb_pmu_get_controlclock(&bus->chipco); | ||
1099 | |||
1097 | if (ssb_extif_available(&bus->extif)) | 1100 | if (ssb_extif_available(&bus->extif)) |
1098 | ssb_extif_get_clockcontrol(&bus->extif, &plltype, | 1101 | ssb_extif_get_clockcontrol(&bus->extif, &plltype, |
1099 | &clkctl_n, &clkctl_m); | 1102 | &clkctl_n, &clkctl_m); |
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 3e844874631f..266c7c5c86dc 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c | |||
@@ -318,6 +318,9 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
318 | bus->chip_package = 0; | 318 | bus->chip_package = 0; |
319 | } | 319 | } |
320 | } | 320 | } |
321 | ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and " | ||
322 | "package 0x%02X\n", bus->chip_id, bus->chip_rev, | ||
323 | bus->chip_package); | ||
321 | if (!bus->nr_devices) | 324 | if (!bus->nr_devices) |
322 | bus->nr_devices = chipid_to_nrcores(bus->chip_id); | 325 | bus->nr_devices = chipid_to_nrcores(bus->chip_id); |
323 | if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { | 326 | if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 77653014db0b..a305550b4b65 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -207,4 +207,8 @@ static inline void b43_pci_ssb_bridge_exit(void) | |||
207 | } | 207 | } |
208 | #endif /* CONFIG_SSB_B43_PCI_BRIDGE */ | 208 | #endif /* CONFIG_SSB_B43_PCI_BRIDGE */ |
209 | 209 | ||
210 | /* driver_chipcommon_pmu.c */ | ||
211 | extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc); | ||
212 | extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc); | ||
213 | |||
210 | #endif /* LINUX_SSB_PRIVATE_H_ */ | 214 | #endif /* LINUX_SSB_PRIVATE_H_ */ |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 83c209f39493..b9f65fbee42f 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -136,6 +136,7 @@ struct bcma_device { | |||
136 | bool dev_registered; | 136 | bool dev_registered; |
137 | 137 | ||
138 | u8 core_index; | 138 | u8 core_index; |
139 | u8 core_unit; | ||
139 | 140 | ||
140 | u32 addr; | 141 | u32 addr; |
141 | u32 wrap; | 142 | u32 wrap; |
@@ -195,6 +196,7 @@ struct bcma_bus { | |||
195 | struct list_head cores; | 196 | struct list_head cores; |
196 | u8 nr_cores; | 197 | u8 nr_cores; |
197 | u8 init_done:1; | 198 | u8 init_done:1; |
199 | u8 num; | ||
198 | 200 | ||
199 | struct bcma_drv_cc drv_cc; | 201 | struct bcma_drv_cc drv_cc; |
200 | struct bcma_drv_pci drv_pci; | 202 | struct bcma_drv_pci drv_pci; |
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index a33086a7530b..e72938b10714 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -181,6 +181,22 @@ | |||
181 | #define BCMA_CC_FLASH_CFG 0x0128 | 181 | #define BCMA_CC_FLASH_CFG 0x0128 |
182 | #define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ | 182 | #define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ |
183 | #define BCMA_CC_FLASH_WAITCNT 0x012C | 183 | #define BCMA_CC_FLASH_WAITCNT 0x012C |
184 | #define BCMA_CC_SROM_CONTROL 0x0190 | ||
185 | #define BCMA_CC_SROM_CONTROL_START 0x80000000 | ||
186 | #define BCMA_CC_SROM_CONTROL_BUSY 0x80000000 | ||
187 | #define BCMA_CC_SROM_CONTROL_OPCODE 0x60000000 | ||
188 | #define BCMA_CC_SROM_CONTROL_OP_READ 0x00000000 | ||
189 | #define BCMA_CC_SROM_CONTROL_OP_WRITE 0x20000000 | ||
190 | #define BCMA_CC_SROM_CONTROL_OP_WRDIS 0x40000000 | ||
191 | #define BCMA_CC_SROM_CONTROL_OP_WREN 0x60000000 | ||
192 | #define BCMA_CC_SROM_CONTROL_OTPSEL 0x00000010 | ||
193 | #define BCMA_CC_SROM_CONTROL_LOCK 0x00000008 | ||
194 | #define BCMA_CC_SROM_CONTROL_SIZE_MASK 0x00000006 | ||
195 | #define BCMA_CC_SROM_CONTROL_SIZE_1K 0x00000000 | ||
196 | #define BCMA_CC_SROM_CONTROL_SIZE_4K 0x00000002 | ||
197 | #define BCMA_CC_SROM_CONTROL_SIZE_16K 0x00000004 | ||
198 | #define BCMA_CC_SROM_CONTROL_SIZE_SHIFT 1 | ||
199 | #define BCMA_CC_SROM_CONTROL_PRESENT 0x00000001 | ||
184 | /* 0x1E0 is defined as shared BCMA_CLKCTLST */ | 200 | /* 0x1E0 is defined as shared BCMA_CLKCTLST */ |
185 | #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ | 201 | #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ |
186 | #define BCMA_CC_UART0_DATA 0x0300 | 202 | #define BCMA_CC_UART0_DATA 0x0300 |
diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h index 3871b668caf9..46c71e27d31f 100644 --- a/include/linux/bcma/bcma_driver_pci.h +++ b/include/linux/bcma/bcma_driver_pci.h | |||
@@ -53,6 +53,35 @@ struct pci_dev; | |||
53 | #define BCMA_CORE_PCI_SBTOPCI1_MASK 0xFC000000 | 53 | #define BCMA_CORE_PCI_SBTOPCI1_MASK 0xFC000000 |
54 | #define BCMA_CORE_PCI_SBTOPCI2 0x0108 /* Backplane to PCI translation 2 (sbtopci2) */ | 54 | #define BCMA_CORE_PCI_SBTOPCI2 0x0108 /* Backplane to PCI translation 2 (sbtopci2) */ |
55 | #define BCMA_CORE_PCI_SBTOPCI2_MASK 0xC0000000 | 55 | #define BCMA_CORE_PCI_SBTOPCI2_MASK 0xC0000000 |
56 | #define BCMA_CORE_PCI_CONFIG_ADDR 0x0120 /* pcie config space access */ | ||
57 | #define BCMA_CORE_PCI_CONFIG_DATA 0x0124 /* pcie config space access */ | ||
58 | #define BCMA_CORE_PCI_MDIO_CONTROL 0x0128 /* controls the mdio access */ | ||
59 | #define BCMA_CORE_PCI_MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ | ||
60 | #define BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL 0x2 | ||
61 | #define BCMA_CORE_PCI_MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ | ||
62 | #define BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE 0x100 /* Tranaction complete */ | ||
63 | #define BCMA_CORE_PCI_MDIO_DATA 0x012c /* Data to the mdio access */ | ||
64 | #define BCMA_CORE_PCI_MDIODATA_MASK 0x0000ffff /* data 2 bytes */ | ||
65 | #define BCMA_CORE_PCI_MDIODATA_TA 0x00020000 /* Turnaround */ | ||
66 | #define BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift (rev < 10) */ | ||
67 | #define BCMA_CORE_PCI_MDIODATA_REGADDR_MASK_OLD 0x003c0000 /* Regaddr Mask (rev < 10) */ | ||
68 | #define BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift (rev < 10) */ | ||
69 | #define BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 /* Physmedia devaddr Mask (rev < 10) */ | ||
70 | #define BCMA_CORE_PCI_MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ | ||
71 | #define BCMA_CORE_PCI_MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */ | ||
72 | #define BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */ | ||
73 | #define BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK 0x0f800000 /* Physmedia devaddr Mask */ | ||
74 | #define BCMA_CORE_PCI_MDIODATA_WRITE 0x10000000 /* write Transaction */ | ||
75 | #define BCMA_CORE_PCI_MDIODATA_READ 0x20000000 /* Read Transaction */ | ||
76 | #define BCMA_CORE_PCI_MDIODATA_START 0x40000000 /* start of Transaction */ | ||
77 | #define BCMA_CORE_PCI_MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */ | ||
78 | #define BCMA_CORE_PCI_MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */ | ||
79 | #define BCMA_CORE_PCI_MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ | ||
80 | #define BCMA_CORE_PCI_MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ | ||
81 | #define BCMA_CORE_PCI_MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ | ||
82 | #define BCMA_CORE_PCI_PCIEIND_ADDR 0x0130 /* indirect access to the internal register */ | ||
83 | #define BCMA_CORE_PCI_PCIEIND_DATA 0x0134 /* Data to/from the internal regsiter */ | ||
84 | #define BCMA_CORE_PCI_CLKREQENCTRL 0x0138 /* >= rev 6, Clkreq rdma control */ | ||
56 | #define BCMA_CORE_PCI_PCICFG0 0x0400 /* PCI config space 0 (rev >= 8) */ | 85 | #define BCMA_CORE_PCI_PCICFG0 0x0400 /* PCI config space 0 (rev >= 8) */ |
57 | #define BCMA_CORE_PCI_PCICFG1 0x0500 /* PCI config space 1 (rev >= 8) */ | 86 | #define BCMA_CORE_PCI_PCICFG1 0x0500 /* PCI config space 1 (rev >= 8) */ |
58 | #define BCMA_CORE_PCI_PCICFG2 0x0600 /* PCI config space 2 (rev >= 8) */ | 87 | #define BCMA_CORE_PCI_PCICFG2 0x0600 /* PCI config space 2 (rev >= 8) */ |
@@ -72,20 +101,114 @@ struct pci_dev; | |||
72 | #define BCMA_CORE_PCI_SBTOPCI_RC_READL 0x00000010 /* Memory read line */ | 101 | #define BCMA_CORE_PCI_SBTOPCI_RC_READL 0x00000010 /* Memory read line */ |
73 | #define BCMA_CORE_PCI_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */ | 102 | #define BCMA_CORE_PCI_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */ |
74 | 103 | ||
104 | /* PCIE protocol PHY diagnostic registers */ | ||
105 | #define BCMA_CORE_PCI_PLP_MODEREG 0x200 /* Mode */ | ||
106 | #define BCMA_CORE_PCI_PLP_STATUSREG 0x204 /* Status */ | ||
107 | #define BCMA_CORE_PCI_PLP_POLARITYINV_STAT 0x10 /* Status reg PCIE_PLP_STATUSREG */ | ||
108 | #define BCMA_CORE_PCI_PLP_LTSSMCTRLREG 0x208 /* LTSSM control */ | ||
109 | #define BCMA_CORE_PCI_PLP_LTLINKNUMREG 0x20c /* Link Training Link number */ | ||
110 | #define BCMA_CORE_PCI_PLP_LTLANENUMREG 0x210 /* Link Training Lane number */ | ||
111 | #define BCMA_CORE_PCI_PLP_LTNFTSREG 0x214 /* Link Training N_FTS */ | ||
112 | #define BCMA_CORE_PCI_PLP_ATTNREG 0x218 /* Attention */ | ||
113 | #define BCMA_CORE_PCI_PLP_ATTNMASKREG 0x21C /* Attention Mask */ | ||
114 | #define BCMA_CORE_PCI_PLP_RXERRCTR 0x220 /* Rx Error */ | ||
115 | #define BCMA_CORE_PCI_PLP_RXFRMERRCTR 0x224 /* Rx Framing Error */ | ||
116 | #define BCMA_CORE_PCI_PLP_RXERRTHRESHREG 0x228 /* Rx Error threshold */ | ||
117 | #define BCMA_CORE_PCI_PLP_TESTCTRLREG 0x22C /* Test Control reg */ | ||
118 | #define BCMA_CORE_PCI_PLP_SERDESCTRLOVRDREG 0x230 /* SERDES Control Override */ | ||
119 | #define BCMA_CORE_PCI_PLP_TIMINGOVRDREG 0x234 /* Timing param override */ | ||
120 | #define BCMA_CORE_PCI_PLP_RXTXSMDIAGREG 0x238 /* RXTX State Machine Diag */ | ||
121 | #define BCMA_CORE_PCI_PLP_LTSSMDIAGREG 0x23C /* LTSSM State Machine Diag */ | ||
122 | |||
123 | /* PCIE protocol DLLP diagnostic registers */ | ||
124 | #define BCMA_CORE_PCI_DLLP_LCREG 0x100 /* Link Control */ | ||
125 | #define BCMA_CORE_PCI_DLLP_LSREG 0x104 /* Link Status */ | ||
126 | #define BCMA_CORE_PCI_DLLP_LAREG 0x108 /* Link Attention */ | ||
127 | #define BCMA_CORE_PCI_DLLP_LSREG_LINKUP (1 << 16) | ||
128 | #define BCMA_CORE_PCI_DLLP_LAMASKREG 0x10C /* Link Attention Mask */ | ||
129 | #define BCMA_CORE_PCI_DLLP_NEXTTXSEQNUMREG 0x110 /* Next Tx Seq Num */ | ||
130 | #define BCMA_CORE_PCI_DLLP_ACKEDTXSEQNUMREG 0x114 /* Acked Tx Seq Num */ | ||
131 | #define BCMA_CORE_PCI_DLLP_PURGEDTXSEQNUMREG 0x118 /* Purged Tx Seq Num */ | ||
132 | #define BCMA_CORE_PCI_DLLP_RXSEQNUMREG 0x11C /* Rx Sequence Number */ | ||
133 | #define BCMA_CORE_PCI_DLLP_LRREG 0x120 /* Link Replay */ | ||
134 | #define BCMA_CORE_PCI_DLLP_LACKTOREG 0x124 /* Link Ack Timeout */ | ||
135 | #define BCMA_CORE_PCI_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */ | ||
136 | #define BCMA_CORE_PCI_DLLP_RTRYWPREG 0x12C /* Retry buffer write ptr */ | ||
137 | #define BCMA_CORE_PCI_DLLP_RTRYRPREG 0x130 /* Retry buffer Read ptr */ | ||
138 | #define BCMA_CORE_PCI_DLLP_RTRYPPREG 0x134 /* Retry buffer Purged ptr */ | ||
139 | #define BCMA_CORE_PCI_DLLP_RTRRWREG 0x138 /* Retry buffer Read/Write */ | ||
140 | #define BCMA_CORE_PCI_DLLP_ECTHRESHREG 0x13C /* Error Count Threshold */ | ||
141 | #define BCMA_CORE_PCI_DLLP_TLPERRCTRREG 0x140 /* TLP Error Counter */ | ||
142 | #define BCMA_CORE_PCI_DLLP_ERRCTRREG 0x144 /* Error Counter */ | ||
143 | #define BCMA_CORE_PCI_DLLP_NAKRXCTRREG 0x148 /* NAK Received Counter */ | ||
144 | #define BCMA_CORE_PCI_DLLP_TESTREG 0x14C /* Test */ | ||
145 | #define BCMA_CORE_PCI_DLLP_PKTBIST 0x150 /* Packet BIST */ | ||
146 | #define BCMA_CORE_PCI_DLLP_PCIE11 0x154 /* DLLP PCIE 1.1 reg */ | ||
147 | |||
148 | /* SERDES RX registers */ | ||
149 | #define BCMA_CORE_PCI_SERDES_RX_CTRL 1 /* Rx cntrl */ | ||
150 | #define BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */ | ||
151 | #define BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */ | ||
152 | #define BCMA_CORE_PCI_SERDES_RX_TIMER1 2 /* Rx Timer1 */ | ||
153 | #define BCMA_CORE_PCI_SERDES_RX_CDR 6 /* CDR */ | ||
154 | #define BCMA_CORE_PCI_SERDES_RX_CDRBW 7 /* CDR BW */ | ||
155 | |||
156 | /* SERDES PLL registers */ | ||
157 | #define BCMA_CORE_PCI_SERDES_PLL_CTRL 1 /* PLL control reg */ | ||
158 | #define BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */ | ||
159 | |||
75 | /* PCIcore specific boardflags */ | 160 | /* PCIcore specific boardflags */ |
76 | #define BCMA_CORE_PCI_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ | 161 | #define BCMA_CORE_PCI_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ |
77 | 162 | ||
163 | /* PCIE Config space accessing MACROS */ | ||
164 | #define BCMA_CORE_PCI_CFG_BUS_SHIFT 24 /* Bus shift */ | ||
165 | #define BCMA_CORE_PCI_CFG_SLOT_SHIFT 19 /* Slot/Device shift */ | ||
166 | #define BCMA_CORE_PCI_CFG_FUN_SHIFT 16 /* Function shift */ | ||
167 | #define BCMA_CORE_PCI_CFG_OFF_SHIFT 0 /* Register shift */ | ||
168 | |||
169 | #define BCMA_CORE_PCI_CFG_BUS_MASK 0xff /* Bus mask */ | ||
170 | #define BCMA_CORE_PCI_CFG_SLOT_MASK 0x1f /* Slot/Device mask */ | ||
171 | #define BCMA_CORE_PCI_CFG_FUN_MASK 7 /* Function mask */ | ||
172 | #define BCMA_CORE_PCI_CFG_OFF_MASK 0xfff /* Register mask */ | ||
173 | |||
174 | /* PCIE Root Capability Register bits (Host mode only) */ | ||
175 | #define BCMA_CORE_PCI_RC_CRS_VISIBILITY 0x0001 | ||
176 | |||
177 | struct bcma_drv_pci; | ||
178 | |||
179 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | ||
180 | struct bcma_drv_pci_host { | ||
181 | struct bcma_drv_pci *pdev; | ||
182 | |||
183 | u32 host_cfg_addr; | ||
184 | spinlock_t cfgspace_lock; | ||
185 | |||
186 | struct pci_controller pci_controller; | ||
187 | struct pci_ops pci_ops; | ||
188 | struct resource mem_resource; | ||
189 | struct resource io_resource; | ||
190 | }; | ||
191 | #endif | ||
192 | |||
78 | struct bcma_drv_pci { | 193 | struct bcma_drv_pci { |
79 | struct bcma_device *core; | 194 | struct bcma_device *core; |
80 | u8 setup_done:1; | 195 | u8 setup_done:1; |
196 | u8 hostmode:1; | ||
197 | |||
198 | #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE | ||
199 | struct bcma_drv_pci_host *host_controller; | ||
200 | #endif | ||
81 | }; | 201 | }; |
82 | 202 | ||
83 | /* Register access */ | 203 | /* Register access */ |
84 | #define pcicore_read32(pc, offset) bcma_read32((pc)->core, offset) | 204 | #define pcicore_read32(pc, offset) bcma_read32((pc)->core, offset) |
85 | #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) | 205 | #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) |
86 | 206 | ||
87 | extern void bcma_core_pci_init(struct bcma_drv_pci *pc); | 207 | extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc); |
88 | extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, | 208 | extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, |
89 | struct bcma_device *core, bool enable); | 209 | struct bcma_device *core, bool enable); |
90 | 210 | ||
211 | extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev); | ||
212 | extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev); | ||
213 | |||
91 | #endif /* LINUX_BCMA_DRIVER_PCI_H_ */ | 214 | #endif /* LINUX_BCMA_DRIVER_PCI_H_ */ |
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h index 9faae2ae02e8..5a71d5719640 100644 --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h | |||
@@ -56,4 +56,31 @@ | |||
56 | #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ | 56 | #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ |
57 | #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ | 57 | #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ |
58 | 58 | ||
59 | /* SiliconBackplane Address Map. | ||
60 | * All regions may not exist on all chips. | ||
61 | */ | ||
62 | #define BCMA_SOC_SDRAM_BASE 0x00000000U /* Physical SDRAM */ | ||
63 | #define BCMA_SOC_PCI_MEM 0x08000000U /* Host Mode sb2pcitranslation0 (64 MB) */ | ||
64 | #define BCMA_SOC_PCI_MEM_SZ (64 * 1024 * 1024) | ||
65 | #define BCMA_SOC_PCI_CFG 0x0c000000U /* Host Mode sb2pcitranslation1 (64 MB) */ | ||
66 | #define BCMA_SOC_SDRAM_SWAPPED 0x10000000U /* Byteswapped Physical SDRAM */ | ||
67 | #define BCMA_SOC_SDRAM_R2 0x80000000U /* Region 2 for sdram (512 MB) */ | ||
68 | |||
69 | |||
70 | #define BCMA_SOC_PCI_DMA 0x40000000U /* Client Mode sb2pcitranslation2 (1 GB) */ | ||
71 | #define BCMA_SOC_PCI_DMA2 0x80000000U /* Client Mode sb2pcitranslation2 (1 GB) */ | ||
72 | #define BCMA_SOC_PCI_DMA_SZ 0x40000000U /* Client Mode sb2pcitranslation2 size in bytes */ | ||
73 | #define BCMA_SOC_PCIE_DMA_L32 0x00000000U /* PCIE Client Mode sb2pcitranslation2 | ||
74 | * (2 ZettaBytes), low 32 bits | ||
75 | */ | ||
76 | #define BCMA_SOC_PCIE_DMA_H32 0x80000000U /* PCIE Client Mode sb2pcitranslation2 | ||
77 | * (2 ZettaBytes), high 32 bits | ||
78 | */ | ||
79 | |||
80 | #define BCMA_SOC_PCI1_MEM 0x40000000U /* Host Mode sb2pcitranslation0 (64 MB) */ | ||
81 | #define BCMA_SOC_PCI1_CFG 0x44000000U /* Host Mode sb2pcitranslation1 (64 MB) */ | ||
82 | #define BCMA_SOC_PCIE1_DMA_H32 0xc0000000U /* PCIE Client Mode sb2pcitranslation2 | ||
83 | * (2 ZettaBytes), high 32 bits | ||
84 | */ | ||
85 | |||
59 | #endif /* LINUX_BCMA_REGS_H_ */ | 86 | #endif /* LINUX_BCMA_REGS_H_ */ |
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index abaad6ed9b83..4a82ca0bb0b2 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
@@ -256,4 +256,6 @@ void l2cap_exit(void); | |||
256 | int sco_init(void); | 256 | int sco_init(void); |
257 | void sco_exit(void); | 257 | void sco_exit(void); |
258 | 258 | ||
259 | void bt_sock_reclassify_lock(struct sock *sk, int proto); | ||
260 | |||
259 | #endif /* __BLUETOOTH_H */ | 261 | #endif /* __BLUETOOTH_H */ |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ea9231f4935f..453893b3120e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -540,7 +540,7 @@ void hci_conn_put_device(struct hci_conn *conn); | |||
540 | static inline void hci_conn_hold(struct hci_conn *conn) | 540 | static inline void hci_conn_hold(struct hci_conn *conn) |
541 | { | 541 | { |
542 | atomic_inc(&conn->refcnt); | 542 | atomic_inc(&conn->refcnt); |
543 | cancel_delayed_work_sync(&conn->disc_work); | 543 | cancel_delayed_work(&conn->disc_work); |
544 | } | 544 | } |
545 | 545 | ||
546 | static inline void hci_conn_put(struct hci_conn *conn) | 546 | static inline void hci_conn_put(struct hci_conn *conn) |
@@ -559,9 +559,9 @@ static inline void hci_conn_put(struct hci_conn *conn) | |||
559 | } else { | 559 | } else { |
560 | timeo = msecs_to_jiffies(10); | 560 | timeo = msecs_to_jiffies(10); |
561 | } | 561 | } |
562 | cancel_delayed_work_sync(&conn->disc_work); | 562 | cancel_delayed_work(&conn->disc_work); |
563 | queue_delayed_work(conn->hdev->workqueue, | 563 | queue_delayed_work(conn->hdev->workqueue, |
564 | &conn->disc_work, jiffies + timeo); | 564 | &conn->disc_work, timeo); |
565 | } | 565 | } |
566 | } | 566 | } |
567 | 567 | ||
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 68f589150692..b1664ed884e6 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -611,7 +611,7 @@ static inline void l2cap_set_timer(struct l2cap_chan *chan, | |||
611 | { | 611 | { |
612 | BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout); | 612 | BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout); |
613 | 613 | ||
614 | if (!__cancel_delayed_work(work)) | 614 | if (!cancel_delayed_work(work)) |
615 | l2cap_chan_hold(chan); | 615 | l2cap_chan_hold(chan); |
616 | schedule_delayed_work(work, timeout); | 616 | schedule_delayed_work(work, timeout); |
617 | } | 617 | } |
@@ -619,20 +619,20 @@ static inline void l2cap_set_timer(struct l2cap_chan *chan, | |||
619 | static inline void l2cap_clear_timer(struct l2cap_chan *chan, | 619 | static inline void l2cap_clear_timer(struct l2cap_chan *chan, |
620 | struct delayed_work *work) | 620 | struct delayed_work *work) |
621 | { | 621 | { |
622 | if (__cancel_delayed_work(work)) | 622 | if (cancel_delayed_work(work)) |
623 | l2cap_chan_put(chan); | 623 | l2cap_chan_put(chan); |
624 | } | 624 | } |
625 | 625 | ||
626 | #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t)) | 626 | #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t)) |
627 | #define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer) | 627 | #define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer) |
628 | #define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \ | 628 | #define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \ |
629 | L2CAP_DEFAULT_RETRANS_TO); | 629 | msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); |
630 | #define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer) | 630 | #define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer) |
631 | #define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \ | 631 | #define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \ |
632 | L2CAP_DEFAULT_MONITOR_TO); | 632 | msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); |
633 | #define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer) | 633 | #define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer) |
634 | #define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \ | 634 | #define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \ |
635 | L2CAP_DEFAULT_ACK_TO); | 635 | msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); |
636 | #define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer) | 636 | #define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer) |
637 | 637 | ||
638 | static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2) | 638 | static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2) |
@@ -834,7 +834,7 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); | |||
834 | struct l2cap_chan *l2cap_chan_create(struct sock *sk); | 834 | struct l2cap_chan *l2cap_chan_create(struct sock *sk); |
835 | void l2cap_chan_close(struct l2cap_chan *chan, int reason); | 835 | void l2cap_chan_close(struct l2cap_chan *chan, int reason); |
836 | void l2cap_chan_destroy(struct l2cap_chan *chan); | 836 | void l2cap_chan_destroy(struct l2cap_chan *chan); |
837 | inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | 837 | int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, |
838 | bdaddr_t *dst); | 838 | bdaddr_t *dst); |
839 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | 839 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, |
840 | u32 priority); | 840 | u32 priority); |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2964205332f4..e0c9ff3a1977 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1039,10 +1039,6 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); | |||
1039 | * @key_len: length of WEP key for shared key authentication | 1039 | * @key_len: length of WEP key for shared key authentication |
1040 | * @key_idx: index of WEP key for shared key authentication | 1040 | * @key_idx: index of WEP key for shared key authentication |
1041 | * @key: WEP key for shared key authentication | 1041 | * @key: WEP key for shared key authentication |
1042 | * @local_state_change: This is a request for a local state only, i.e., no | ||
1043 | * Authentication frame is to be transmitted and authentication state is | ||
1044 | * to be changed without having to wait for a response from the peer STA | ||
1045 | * (AP). | ||
1046 | */ | 1042 | */ |
1047 | struct cfg80211_auth_request { | 1043 | struct cfg80211_auth_request { |
1048 | struct cfg80211_bss *bss; | 1044 | struct cfg80211_bss *bss; |
@@ -1051,7 +1047,6 @@ struct cfg80211_auth_request { | |||
1051 | enum nl80211_auth_type auth_type; | 1047 | enum nl80211_auth_type auth_type; |
1052 | const u8 *key; | 1048 | const u8 *key; |
1053 | u8 key_len, key_idx; | 1049 | u8 key_len, key_idx; |
1054 | bool local_state_change; | ||
1055 | }; | 1050 | }; |
1056 | 1051 | ||
1057 | /** | 1052 | /** |
@@ -1068,7 +1063,11 @@ enum cfg80211_assoc_req_flags { | |||
1068 | * | 1063 | * |
1069 | * This structure provides information needed to complete IEEE 802.11 | 1064 | * This structure provides information needed to complete IEEE 802.11 |
1070 | * (re)association. | 1065 | * (re)association. |
1071 | * @bss: The BSS to associate with. | 1066 | * @bss: The BSS to associate with. If the call is successful the driver |
1067 | * is given a reference that it must release, normally via a call to | ||
1068 | * cfg80211_send_rx_assoc(), or, if association timed out, with a | ||
1069 | * call to cfg80211_put_bss() (in addition to calling | ||
1070 | * cfg80211_send_assoc_timeout()) | ||
1072 | * @ie: Extra IEs to add to (Re)Association Request frame or %NULL | 1071 | * @ie: Extra IEs to add to (Re)Association Request frame or %NULL |
1073 | * @ie_len: Length of ie buffer in octets | 1072 | * @ie_len: Length of ie buffer in octets |
1074 | * @use_mfp: Use management frame protection (IEEE 802.11w) in this association | 1073 | * @use_mfp: Use management frame protection (IEEE 802.11w) in this association |
@@ -1096,19 +1095,16 @@ struct cfg80211_assoc_request { | |||
1096 | * This structure provides information needed to complete IEEE 802.11 | 1095 | * This structure provides information needed to complete IEEE 802.11 |
1097 | * deauthentication. | 1096 | * deauthentication. |
1098 | * | 1097 | * |
1099 | * @bss: the BSS to deauthenticate from | 1098 | * @bssid: the BSSID of the BSS to deauthenticate from |
1100 | * @ie: Extra IEs to add to Deauthentication frame or %NULL | 1099 | * @ie: Extra IEs to add to Deauthentication frame or %NULL |
1101 | * @ie_len: Length of ie buffer in octets | 1100 | * @ie_len: Length of ie buffer in octets |
1102 | * @reason_code: The reason code for the deauthentication | 1101 | * @reason_code: The reason code for the deauthentication |
1103 | * @local_state_change: This is a request for a local state only, i.e., no | ||
1104 | * Deauthentication frame is to be transmitted. | ||
1105 | */ | 1102 | */ |
1106 | struct cfg80211_deauth_request { | 1103 | struct cfg80211_deauth_request { |
1107 | struct cfg80211_bss *bss; | 1104 | const u8 *bssid; |
1108 | const u8 *ie; | 1105 | const u8 *ie; |
1109 | size_t ie_len; | 1106 | size_t ie_len; |
1110 | u16 reason_code; | 1107 | u16 reason_code; |
1111 | bool local_state_change; | ||
1112 | }; | 1108 | }; |
1113 | 1109 | ||
1114 | /** | 1110 | /** |
@@ -1151,6 +1147,10 @@ struct cfg80211_disassoc_request { | |||
1151 | * @beacon_interval: beacon interval to use | 1147 | * @beacon_interval: beacon interval to use |
1152 | * @privacy: this is a protected network, keys will be configured | 1148 | * @privacy: this is a protected network, keys will be configured |
1153 | * after joining | 1149 | * after joining |
1150 | * @control_port: whether user space controls IEEE 802.1X port, i.e., | ||
1151 | * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is | ||
1152 | * required to assume that the port is unauthorized until authorized by | ||
1153 | * user space. Otherwise, port is marked authorized by default. | ||
1154 | * @basic_rates: bitmap of basic rates to use when creating the IBSS | 1154 | * @basic_rates: bitmap of basic rates to use when creating the IBSS |
1155 | * @mcast_rate: per-band multicast rate index + 1 (0: disabled) | 1155 | * @mcast_rate: per-band multicast rate index + 1 (0: disabled) |
1156 | */ | 1156 | */ |
@@ -1165,6 +1165,7 @@ struct cfg80211_ibss_params { | |||
1165 | u32 basic_rates; | 1165 | u32 basic_rates; |
1166 | bool channel_fixed; | 1166 | bool channel_fixed; |
1167 | bool privacy; | 1167 | bool privacy; |
1168 | bool control_port; | ||
1168 | int mcast_rate[IEEE80211_NUM_BANDS]; | 1169 | int mcast_rate[IEEE80211_NUM_BANDS]; |
1169 | }; | 1170 | }; |
1170 | 1171 | ||
@@ -2206,8 +2207,6 @@ struct cfg80211_conn; | |||
2206 | struct cfg80211_internal_bss; | 2207 | struct cfg80211_internal_bss; |
2207 | struct cfg80211_cached_keys; | 2208 | struct cfg80211_cached_keys; |
2208 | 2209 | ||
2209 | #define MAX_AUTH_BSSES 4 | ||
2210 | |||
2211 | /** | 2210 | /** |
2212 | * struct wireless_dev - wireless per-netdev state | 2211 | * struct wireless_dev - wireless per-netdev state |
2213 | * | 2212 | * |
@@ -2271,8 +2270,6 @@ struct wireless_dev { | |||
2271 | struct list_head event_list; | 2270 | struct list_head event_list; |
2272 | spinlock_t event_lock; | 2271 | spinlock_t event_lock; |
2273 | 2272 | ||
2274 | struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES]; | ||
2275 | struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES]; | ||
2276 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ | 2273 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ |
2277 | struct ieee80211_channel *channel; | 2274 | struct ieee80211_channel *channel; |
2278 | 2275 | ||
@@ -2727,6 +2724,20 @@ struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, | |||
2727 | struct ieee80211_channel *channel, | 2724 | struct ieee80211_channel *channel, |
2728 | const u8 *meshid, size_t meshidlen, | 2725 | const u8 *meshid, size_t meshidlen, |
2729 | const u8 *meshcfg); | 2726 | const u8 *meshcfg); |
2727 | /** | ||
2728 | * cfg80211_ref_bss - reference BSS struct | ||
2729 | * @bss: the BSS struct to reference | ||
2730 | * | ||
2731 | * Increments the refcount of the given BSS struct. | ||
2732 | */ | ||
2733 | void cfg80211_ref_bss(struct cfg80211_bss *bss); | ||
2734 | |||
2735 | /** | ||
2736 | * cfg80211_put_bss - unref BSS struct | ||
2737 | * @bss: the BSS struct | ||
2738 | * | ||
2739 | * Decrements the refcount of the given BSS struct. | ||
2740 | */ | ||
2730 | void cfg80211_put_bss(struct cfg80211_bss *bss); | 2741 | void cfg80211_put_bss(struct cfg80211_bss *bss); |
2731 | 2742 | ||
2732 | /** | 2743 | /** |
@@ -2764,20 +2775,10 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); | |||
2764 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); | 2775 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); |
2765 | 2776 | ||
2766 | /** | 2777 | /** |
2767 | * __cfg80211_auth_canceled - notify cfg80211 that authentication was canceled | ||
2768 | * @dev: network device | ||
2769 | * @addr: The MAC address of the device with which the authentication timed out | ||
2770 | * | ||
2771 | * When a pending authentication had no action yet, the driver may decide | ||
2772 | * to not send a deauth frame, but in that case must calls this function | ||
2773 | * to tell cfg80211 about this decision. It is only valid to call this | ||
2774 | * function within the deauth() callback. | ||
2775 | */ | ||
2776 | void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr); | ||
2777 | |||
2778 | /** | ||
2779 | * cfg80211_send_rx_assoc - notification of processed association | 2778 | * cfg80211_send_rx_assoc - notification of processed association |
2780 | * @dev: network device | 2779 | * @dev: network device |
2780 | * @bss: the BSS struct association was requested for, the struct reference | ||
2781 | * is owned by cfg80211 after this call | ||
2781 | * @buf: (re)association response frame (header + body) | 2782 | * @buf: (re)association response frame (header + body) |
2782 | * @len: length of the frame data | 2783 | * @len: length of the frame data |
2783 | * | 2784 | * |
@@ -2786,7 +2787,8 @@ void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr); | |||
2786 | * function or cfg80211_send_assoc_timeout() to indicate the result of | 2787 | * function or cfg80211_send_assoc_timeout() to indicate the result of |
2787 | * cfg80211_ops::assoc() call. This function may sleep. | 2788 | * cfg80211_ops::assoc() call. This function may sleep. |
2788 | */ | 2789 | */ |
2789 | void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len); | 2790 | void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, |
2791 | const u8 *buf, size_t len); | ||
2790 | 2792 | ||
2791 | /** | 2793 | /** |
2792 | * cfg80211_send_assoc_timeout - notification of timed out association | 2794 | * cfg80211_send_assoc_timeout - notification of timed out association |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 520eb4c5e5a2..cbff4f94a200 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -982,6 +982,25 @@ enum set_key_cmd { | |||
982 | }; | 982 | }; |
983 | 983 | ||
984 | /** | 984 | /** |
985 | * enum ieee80211_sta_state - station state | ||
986 | * | ||
987 | * @IEEE80211_STA_NOTEXIST: station doesn't exist at all, | ||
988 | * this is a special state for add/remove transitions | ||
989 | * @IEEE80211_STA_NONE: station exists without special state | ||
990 | * @IEEE80211_STA_AUTH: station is authenticated | ||
991 | * @IEEE80211_STA_ASSOC: station is associated | ||
992 | * @IEEE80211_STA_AUTHORIZED: station is authorized (802.1X) | ||
993 | */ | ||
994 | enum ieee80211_sta_state { | ||
995 | /* NOTE: These need to be ordered correctly! */ | ||
996 | IEEE80211_STA_NOTEXIST, | ||
997 | IEEE80211_STA_NONE, | ||
998 | IEEE80211_STA_AUTH, | ||
999 | IEEE80211_STA_ASSOC, | ||
1000 | IEEE80211_STA_AUTHORIZED, | ||
1001 | }; | ||
1002 | |||
1003 | /** | ||
985 | * struct ieee80211_sta - station table entry | 1004 | * struct ieee80211_sta - station table entry |
986 | * | 1005 | * |
987 | * A station table entry represents a station we are possibly | 1006 | * A station table entry represents a station we are possibly |
@@ -1145,6 +1164,10 @@ enum sta_notify_cmd { | |||
1145 | * @IEEE80211_HW_TX_AMPDU_SETUP_IN_HW: The device handles TX A-MPDU session | 1164 | * @IEEE80211_HW_TX_AMPDU_SETUP_IN_HW: The device handles TX A-MPDU session |
1146 | * setup strictly in HW. mac80211 should not attempt to do this in | 1165 | * setup strictly in HW. mac80211 should not attempt to do this in |
1147 | * software. | 1166 | * software. |
1167 | * | ||
1168 | * @IEEE80211_HW_SCAN_WHILE_IDLE: The device can do hw scan while | ||
1169 | * being idle (i.e. mac80211 doesn't have to go idle-off during the | ||
1170 | * the scan). | ||
1148 | */ | 1171 | */ |
1149 | enum ieee80211_hw_flags { | 1172 | enum ieee80211_hw_flags { |
1150 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | 1173 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, |
@@ -1171,6 +1194,7 @@ enum ieee80211_hw_flags { | |||
1171 | IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, | 1194 | IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, |
1172 | IEEE80211_HW_AP_LINK_PS = 1<<22, | 1195 | IEEE80211_HW_AP_LINK_PS = 1<<22, |
1173 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, | 1196 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, |
1197 | IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24, | ||
1174 | }; | 1198 | }; |
1175 | 1199 | ||
1176 | /** | 1200 | /** |
@@ -1974,6 +1998,13 @@ enum ieee80211_frame_release_type { | |||
1974 | * in AP mode, this callback will not be called when the flag | 1998 | * in AP mode, this callback will not be called when the flag |
1975 | * %IEEE80211_HW_AP_LINK_PS is set. Must be atomic. | 1999 | * %IEEE80211_HW_AP_LINK_PS is set. Must be atomic. |
1976 | * | 2000 | * |
2001 | * @sta_state: Notifies low level driver about state transition of a | ||
2002 | * station (which can be the AP, a client, IBSS/WDS/mesh peer etc.) | ||
2003 | * This callback is mutually exclusive with @sta_add/@sta_remove. | ||
2004 | * It must not fail for down transitions but may fail for transitions | ||
2005 | * up the list of states. | ||
2006 | * The callback can sleep. | ||
2007 | * | ||
1977 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), | 2008 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), |
1978 | * bursting) for a hardware TX queue. | 2009 | * bursting) for a hardware TX queue. |
1979 | * Returns a negative error code on failure. | 2010 | * Returns a negative error code on failure. |
@@ -2193,6 +2224,10 @@ struct ieee80211_ops { | |||
2193 | struct ieee80211_sta *sta); | 2224 | struct ieee80211_sta *sta); |
2194 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2225 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2195 | enum sta_notify_cmd, struct ieee80211_sta *sta); | 2226 | enum sta_notify_cmd, struct ieee80211_sta *sta); |
2227 | int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
2228 | struct ieee80211_sta *sta, | ||
2229 | enum ieee80211_sta_state old_state, | ||
2230 | enum ieee80211_sta_state new_state); | ||
2196 | int (*conf_tx)(struct ieee80211_hw *hw, | 2231 | int (*conf_tx)(struct ieee80211_hw *hw, |
2197 | struct ieee80211_vif *vif, u16 queue, | 2232 | struct ieee80211_vif *vif, u16 queue, |
2198 | const struct ieee80211_tx_queue_params *params); | 2233 | const struct ieee80211_tx_queue_params *params); |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index ef92864ac625..72eb187a5f60 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -71,19 +71,16 @@ static const char *const bt_slock_key_strings[BT_MAX_PROTO] = { | |||
71 | "slock-AF_BLUETOOTH-BTPROTO_AVDTP", | 71 | "slock-AF_BLUETOOTH-BTPROTO_AVDTP", |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static inline void bt_sock_reclassify_lock(struct socket *sock, int proto) | 74 | void bt_sock_reclassify_lock(struct sock *sk, int proto) |
75 | { | 75 | { |
76 | struct sock *sk = sock->sk; | 76 | BUG_ON(!sk); |
77 | |||
78 | if (!sk) | ||
79 | return; | ||
80 | |||
81 | BUG_ON(sock_owned_by_user(sk)); | 77 | BUG_ON(sock_owned_by_user(sk)); |
82 | 78 | ||
83 | sock_lock_init_class_and_name(sk, | 79 | sock_lock_init_class_and_name(sk, |
84 | bt_slock_key_strings[proto], &bt_slock_key[proto], | 80 | bt_slock_key_strings[proto], &bt_slock_key[proto], |
85 | bt_key_strings[proto], &bt_lock_key[proto]); | 81 | bt_key_strings[proto], &bt_lock_key[proto]); |
86 | } | 82 | } |
83 | EXPORT_SYMBOL(bt_sock_reclassify_lock); | ||
87 | 84 | ||
88 | int bt_sock_register(int proto, const struct net_proto_family *ops) | 85 | int bt_sock_register(int proto, const struct net_proto_family *ops) |
89 | { | 86 | { |
@@ -145,7 +142,8 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto, | |||
145 | 142 | ||
146 | if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { | 143 | if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { |
147 | err = bt_proto[proto]->create(net, sock, proto, kern); | 144 | err = bt_proto[proto]->create(net, sock, proto, kern); |
148 | bt_sock_reclassify_lock(sock, proto); | 145 | if (!err) |
146 | bt_sock_reclassify_lock(sock->sk, proto); | ||
149 | module_put(bt_proto[proto]->owner); | 147 | module_put(bt_proto[proto]->owner); |
150 | } | 148 | } |
151 | 149 | ||
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3db432473ad5..07bc69ed9498 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -635,6 +635,10 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
635 | 635 | ||
636 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { | 636 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { |
637 | struct hci_cp_auth_requested cp; | 637 | struct hci_cp_auth_requested cp; |
638 | |||
639 | /* encrypt must be pending if auth is also pending */ | ||
640 | set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); | ||
641 | |||
638 | cp.handle = cpu_to_le16(conn->handle); | 642 | cp.handle = cpu_to_le16(conn->handle); |
639 | hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, | 643 | hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, |
640 | sizeof(cp), &cp); | 644 | sizeof(cp), &cp); |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9de93714213a..5aeb62491198 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -640,7 +640,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
640 | /* Reset device */ | 640 | /* Reset device */ |
641 | skb_queue_purge(&hdev->cmd_q); | 641 | skb_queue_purge(&hdev->cmd_q); |
642 | atomic_set(&hdev->cmd_cnt, 1); | 642 | atomic_set(&hdev->cmd_cnt, 1); |
643 | if (!test_bit(HCI_RAW, &hdev->flags)) { | 643 | if (!test_bit(HCI_RAW, &hdev->flags) && |
644 | test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) { | ||
644 | set_bit(HCI_INIT, &hdev->flags); | 645 | set_bit(HCI_INIT, &hdev->flags); |
645 | __hci_request(hdev, hci_reset_req, 0, | 646 | __hci_request(hdev, hci_reset_req, 0, |
646 | msecs_to_jiffies(250)); | 647 | msecs_to_jiffies(250)); |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index faf0b11ac1d3..32d338c30e65 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -1018,10 +1018,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
1018 | hci_chan_del(conn->hchan); | 1018 | hci_chan_del(conn->hchan); |
1019 | 1019 | ||
1020 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) | 1020 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) |
1021 | __cancel_delayed_work(&conn->info_timer); | 1021 | cancel_delayed_work_sync(&conn->info_timer); |
1022 | 1022 | ||
1023 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) { | 1023 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) { |
1024 | __cancel_delayed_work(&conn->security_timer); | 1024 | cancel_delayed_work_sync(&conn->security_timer); |
1025 | smp_chan_destroy(conn); | 1025 | smp_chan_destroy(conn); |
1026 | } | 1026 | } |
1027 | 1027 | ||
@@ -1120,7 +1120,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr | |||
1120 | return c1; | 1120 | return c1; |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst) | 1123 | int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst) |
1124 | { | 1124 | { |
1125 | struct sock *sk = chan->sk; | 1125 | struct sock *sk = chan->sk; |
1126 | bdaddr_t *src = &bt_sk(sk)->src; | 1126 | bdaddr_t *src = &bt_sk(sk)->src; |
@@ -2574,7 +2574,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2574 | 2574 | ||
2575 | if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && | 2575 | if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && |
2576 | cmd->ident == conn->info_ident) { | 2576 | cmd->ident == conn->info_ident) { |
2577 | __cancel_delayed_work(&conn->info_timer); | 2577 | cancel_delayed_work(&conn->info_timer); |
2578 | 2578 | ||
2579 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; | 2579 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
2580 | conn->info_ident = 0; | 2580 | conn->info_ident = 0; |
@@ -2970,7 +2970,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2970 | 2970 | ||
2971 | default: | 2971 | default: |
2972 | sk->sk_err = ECONNRESET; | 2972 | sk->sk_err = ECONNRESET; |
2973 | __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); | 2973 | __set_chan_timer(chan, |
2974 | msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT)); | ||
2974 | l2cap_send_disconn_req(conn, chan, ECONNRESET); | 2975 | l2cap_send_disconn_req(conn, chan, ECONNRESET); |
2975 | goto done; | 2976 | goto done; |
2976 | } | 2977 | } |
@@ -3120,7 +3121,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm | |||
3120 | conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) | 3121 | conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) |
3121 | return 0; | 3122 | return 0; |
3122 | 3123 | ||
3123 | __cancel_delayed_work(&conn->info_timer); | 3124 | cancel_delayed_work(&conn->info_timer); |
3124 | 3125 | ||
3125 | if (result != L2CAP_IR_SUCCESS) { | 3126 | if (result != L2CAP_IR_SUCCESS) { |
3126 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; | 3127 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
@@ -4478,7 +4479,8 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) | |||
4478 | if (encrypt == 0x00) { | 4479 | if (encrypt == 0x00) { |
4479 | if (chan->sec_level == BT_SECURITY_MEDIUM) { | 4480 | if (chan->sec_level == BT_SECURITY_MEDIUM) { |
4480 | __clear_chan_timer(chan); | 4481 | __clear_chan_timer(chan); |
4481 | __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); | 4482 | __set_chan_timer(chan, |
4483 | msecs_to_jiffies(L2CAP_ENC_TIMEOUT)); | ||
4482 | } else if (chan->sec_level == BT_SECURITY_HIGH) | 4484 | } else if (chan->sec_level == BT_SECURITY_HIGH) |
4483 | l2cap_chan_close(chan, ECONNREFUSED); | 4485 | l2cap_chan_close(chan, ECONNREFUSED); |
4484 | } else { | 4486 | } else { |
@@ -4499,7 +4501,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4499 | 4501 | ||
4500 | if (hcon->type == LE_LINK) { | 4502 | if (hcon->type == LE_LINK) { |
4501 | smp_distribute_keys(conn, 0); | 4503 | smp_distribute_keys(conn, 0); |
4502 | __cancel_delayed_work(&conn->security_timer); | 4504 | cancel_delayed_work(&conn->security_timer); |
4503 | } | 4505 | } |
4504 | 4506 | ||
4505 | rcu_read_lock(); | 4507 | rcu_read_lock(); |
@@ -4546,7 +4548,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4546 | L2CAP_CONN_REQ, sizeof(req), &req); | 4548 | L2CAP_CONN_REQ, sizeof(req), &req); |
4547 | } else { | 4549 | } else { |
4548 | __clear_chan_timer(chan); | 4550 | __clear_chan_timer(chan); |
4549 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); | 4551 | __set_chan_timer(chan, |
4552 | msecs_to_jiffies(L2CAP_DISC_TIMEOUT)); | ||
4550 | } | 4553 | } |
4551 | } else if (chan->state == BT_CONNECT2) { | 4554 | } else if (chan->state == BT_CONNECT2) { |
4552 | struct l2cap_conn_rsp rsp; | 4555 | struct l2cap_conn_rsp rsp; |
@@ -4566,7 +4569,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
4566 | } | 4569 | } |
4567 | } else { | 4570 | } else { |
4568 | l2cap_state_change(chan, BT_DISCONN); | 4571 | l2cap_state_change(chan, BT_DISCONN); |
4569 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); | 4572 | __set_chan_timer(chan, |
4573 | msecs_to_jiffies(L2CAP_DISC_TIMEOUT)); | ||
4570 | res = L2CAP_CR_SEC_BLOCK; | 4574 | res = L2CAP_CR_SEC_BLOCK; |
4571 | stat = L2CAP_CS_NO_INFO; | 4575 | stat = L2CAP_CS_NO_INFO; |
4572 | } | 4576 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index c61d967012b2..401d9428ae4c 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -849,6 +849,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data) | |||
849 | if (!sk) | 849 | if (!sk) |
850 | return NULL; | 850 | return NULL; |
851 | 851 | ||
852 | bt_sock_reclassify_lock(sk, BTPROTO_L2CAP); | ||
853 | |||
852 | l2cap_sock_init(sk, parent); | 854 | l2cap_sock_init(sk, parent); |
853 | 855 | ||
854 | return l2cap_pi(sk)->chan; | 856 | return l2cap_pi(sk)->chan; |
@@ -1002,7 +1004,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p | |||
1002 | INIT_LIST_HEAD(&bt_sk(sk)->accept_q); | 1004 | INIT_LIST_HEAD(&bt_sk(sk)->accept_q); |
1003 | 1005 | ||
1004 | sk->sk_destruct = l2cap_sock_destruct; | 1006 | sk->sk_destruct = l2cap_sock_destruct; |
1005 | sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT; | 1007 | sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT); |
1006 | 1008 | ||
1007 | sock_reset_flag(sk, SOCK_ZAPPED); | 1009 | sock_reset_flag(sk, SOCK_ZAPPED); |
1008 | 1010 | ||
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 501649bf5596..8a602388f1e7 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -1164,12 +1164,18 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) | |||
1164 | break; | 1164 | break; |
1165 | 1165 | ||
1166 | case BT_DISCONN: | 1166 | case BT_DISCONN: |
1167 | /* When socket is closed and we are not RFCOMM | 1167 | /* rfcomm_session_put is called later so don't do |
1168 | * initiator rfcomm_process_rx already calls | 1168 | * anything here otherwise we will mess up the session |
1169 | * rfcomm_session_put() */ | 1169 | * reference counter: |
1170 | if (s->sock->sk->sk_state != BT_CLOSED) | 1170 | * |
1171 | if (list_empty(&s->dlcs)) | 1171 | * (a) when we are the initiator dlc_unlink will drive |
1172 | rfcomm_session_put(s); | 1172 | * the reference counter to 0 (there is no initial put |
1173 | * after session_add) | ||
1174 | * | ||
1175 | * (b) when we are not the initiator rfcomm_rx_process | ||
1176 | * will explicitly call put to balance the initial hold | ||
1177 | * done after session add. | ||
1178 | */ | ||
1173 | break; | 1179 | break; |
1174 | } | 1180 | } |
1175 | } | 1181 | } |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index f066678faeee..22169c3f1482 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -956,6 +956,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * | |||
956 | if (!sk) | 956 | if (!sk) |
957 | goto done; | 957 | goto done; |
958 | 958 | ||
959 | bt_sock_reclassify_lock(sk, BTPROTO_RFCOMM); | ||
960 | |||
959 | rfcomm_sock_init(sk, parent); | 961 | rfcomm_sock_init(sk, parent); |
960 | bacpy(&bt_sk(sk)->src, &src); | 962 | bacpy(&bt_sk(sk)->src, &src); |
961 | bacpy(&bt_sk(sk)->dst, &dst); | 963 | bacpy(&bt_sk(sk)->dst, &dst); |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index d540c3b160f3..1be7a454aa77 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -9,7 +9,7 @@ mac80211-y := \ | |||
9 | scan.o offchannel.o \ | 9 | scan.o offchannel.o \ |
10 | ht.o agg-tx.o agg-rx.o \ | 10 | ht.o agg-tx.o agg-rx.o \ |
11 | ibss.o \ | 11 | ibss.o \ |
12 | mlme.o work.o \ | 12 | work.o \ |
13 | iface.o \ | 13 | iface.o \ |
14 | rate.o \ | 14 | rate.o \ |
15 | michael.o \ | 15 | michael.o \ |
@@ -25,7 +25,7 @@ mac80211-y := \ | |||
25 | wme.o \ | 25 | wme.o \ |
26 | event.o \ | 26 | event.o \ |
27 | chan.o \ | 27 | chan.o \ |
28 | driver-trace.o | 28 | driver-trace.o mlme.o |
29 | 29 | ||
30 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o | 30 | mac80211-$(CONFIG_MAC80211_LEDS) += led.o |
31 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ | 31 | mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d15ba0d0de94..c3de921c8cfd 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2028,7 +2028,7 @@ ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) | |||
2028 | if (wk->offchan_tx.wait && !wk->offchan_tx.status) | 2028 | if (wk->offchan_tx.wait && !wk->offchan_tx.status) |
2029 | cfg80211_mgmt_tx_status(wk->sdata->dev, | 2029 | cfg80211_mgmt_tx_status(wk->sdata->dev, |
2030 | (unsigned long) wk->offchan_tx.frame, | 2030 | (unsigned long) wk->offchan_tx.frame, |
2031 | wk->ie, wk->ie_len, false, GFP_KERNEL); | 2031 | wk->data, wk->data_len, false, GFP_KERNEL); |
2032 | 2032 | ||
2033 | return WORK_DONE_DESTROY; | 2033 | return WORK_DONE_DESTROY; |
2034 | } | 2034 | } |
@@ -2179,8 +2179,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2179 | wk->done = ieee80211_offchan_tx_done; | 2179 | wk->done = ieee80211_offchan_tx_done; |
2180 | wk->offchan_tx.frame = skb; | 2180 | wk->offchan_tx.frame = skb; |
2181 | wk->offchan_tx.wait = wait; | 2181 | wk->offchan_tx.wait = wait; |
2182 | wk->ie_len = len; | 2182 | wk->data_len = len; |
2183 | memcpy(wk->ie, buf, len); | 2183 | memcpy(wk->data, buf, len); |
2184 | 2184 | ||
2185 | ieee80211_add_work(wk); | 2185 | ieee80211_add_work(wk); |
2186 | return 0; | 2186 | return 0; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index affe64be9092..483e96ed95c1 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -263,6 +263,8 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, | |||
263 | sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); | 263 | sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); |
264 | if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) | 264 | if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) |
265 | sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); | 265 | sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); |
266 | if (local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE) | ||
267 | sf += snprintf(buf + sf, mxln - sf, "SCAN_WHILE_IDLE\n"); | ||
266 | 268 | ||
267 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | 269 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); |
268 | kfree(buf); | 270 | kfree(buf); |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c8383712fdec..6d45804d09bc 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -63,7 +63,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" | 63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" |
64 | 64 | ||
65 | int res = scnprintf(buf, sizeof(buf), | 65 | int res = scnprintf(buf, sizeof(buf), |
66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", | 66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", |
67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), | 67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), |
68 | TEST(PS_DRIVER), TEST(AUTHORIZED), | 68 | TEST(PS_DRIVER), TEST(AUTHORIZED), |
69 | TEST(SHORT_PREAMBLE), | 69 | TEST(SHORT_PREAMBLE), |
@@ -71,7 +71,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), | 71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), |
72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), | 72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), |
73 | TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), | 73 | TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), |
74 | TEST(INSERTED)); | 74 | TEST(INSERTED), TEST(RATE_CONTROL)); |
75 | #undef TEST | 75 | #undef TEST |
76 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 76 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
77 | } | 77 | } |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index e8960ae39861..70dfb6415c20 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -253,6 +253,7 @@ static inline int drv_set_key(struct ieee80211_local *local, | |||
253 | 253 | ||
254 | might_sleep(); | 254 | might_sleep(); |
255 | 255 | ||
256 | sdata = get_bss_sdata(sdata); | ||
256 | check_sdata_in_driver(sdata); | 257 | check_sdata_in_driver(sdata); |
257 | 258 | ||
258 | trace_drv_set_key(local, cmd, sdata, sta, key); | 259 | trace_drv_set_key(local, cmd, sdata, sta, key); |
@@ -272,6 +273,7 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
272 | if (sta) | 273 | if (sta) |
273 | ista = &sta->sta; | 274 | ista = &sta->sta; |
274 | 275 | ||
276 | sdata = get_bss_sdata(sdata); | ||
275 | check_sdata_in_driver(sdata); | 277 | check_sdata_in_driver(sdata); |
276 | 278 | ||
277 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); | 279 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); |
@@ -476,6 +478,37 @@ static inline void drv_sta_remove(struct ieee80211_local *local, | |||
476 | trace_drv_return_void(local); | 478 | trace_drv_return_void(local); |
477 | } | 479 | } |
478 | 480 | ||
481 | static inline __must_check | ||
482 | int drv_sta_state(struct ieee80211_local *local, | ||
483 | struct ieee80211_sub_if_data *sdata, | ||
484 | struct sta_info *sta, | ||
485 | enum ieee80211_sta_state old_state, | ||
486 | enum ieee80211_sta_state new_state) | ||
487 | { | ||
488 | int ret = 0; | ||
489 | |||
490 | might_sleep(); | ||
491 | |||
492 | sdata = get_bss_sdata(sdata); | ||
493 | check_sdata_in_driver(sdata); | ||
494 | |||
495 | trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); | ||
496 | if (local->ops->sta_state) { | ||
497 | ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta, | ||
498 | old_state, new_state); | ||
499 | } else if (old_state == IEEE80211_STA_AUTH && | ||
500 | new_state == IEEE80211_STA_ASSOC) { | ||
501 | ret = drv_sta_add(local, sdata, &sta->sta); | ||
502 | if (ret == 0) | ||
503 | sta->uploaded = true; | ||
504 | } else if (old_state == IEEE80211_STA_ASSOC && | ||
505 | new_state == IEEE80211_STA_AUTH) { | ||
506 | drv_sta_remove(local, sdata, &sta->sta); | ||
507 | } | ||
508 | trace_drv_return_int(local, ret); | ||
509 | return ret; | ||
510 | } | ||
511 | |||
479 | static inline int drv_conf_tx(struct ieee80211_local *local, | 512 | static inline int drv_conf_tx(struct ieee80211_local *local, |
480 | struct ieee80211_sub_if_data *sdata, u16 queue, | 513 | struct ieee80211_sub_if_data *sdata, u16 queue, |
481 | const struct ieee80211_tx_queue_params *params) | 514 | const struct ieee80211_tx_queue_params *params) |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 6e9df8fd8fb8..384e2f08c187 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -635,6 +635,38 @@ TRACE_EVENT(drv_sta_notify, | |||
635 | ) | 635 | ) |
636 | ); | 636 | ); |
637 | 637 | ||
638 | TRACE_EVENT(drv_sta_state, | ||
639 | TP_PROTO(struct ieee80211_local *local, | ||
640 | struct ieee80211_sub_if_data *sdata, | ||
641 | struct ieee80211_sta *sta, | ||
642 | enum ieee80211_sta_state old_state, | ||
643 | enum ieee80211_sta_state new_state), | ||
644 | |||
645 | TP_ARGS(local, sdata, sta, old_state, new_state), | ||
646 | |||
647 | TP_STRUCT__entry( | ||
648 | LOCAL_ENTRY | ||
649 | VIF_ENTRY | ||
650 | STA_ENTRY | ||
651 | __field(u32, old_state) | ||
652 | __field(u32, new_state) | ||
653 | ), | ||
654 | |||
655 | TP_fast_assign( | ||
656 | LOCAL_ASSIGN; | ||
657 | VIF_ASSIGN; | ||
658 | STA_ASSIGN; | ||
659 | __entry->old_state = old_state; | ||
660 | __entry->new_state = new_state; | ||
661 | ), | ||
662 | |||
663 | TP_printk( | ||
664 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " state: %d->%d", | ||
665 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, | ||
666 | __entry->old_state, __entry->new_state | ||
667 | ) | ||
668 | ); | ||
669 | |||
638 | TRACE_EVENT(drv_sta_add, | 670 | TRACE_EVENT(drv_sta_add, |
639 | TP_PROTO(struct ieee80211_local *local, | 671 | TP_PROTO(struct ieee80211_local *local, |
640 | struct ieee80211_sub_if_data *sdata, | 672 | struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 7b3a0b0aa246..8361da4b36ab 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -268,7 +268,10 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, | |||
268 | 268 | ||
269 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 269 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
270 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 270 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
271 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); | 271 | /* authorize the station only if the network is not RSN protected. If |
272 | * not wait for the userspace to authorize it */ | ||
273 | if (!sta->sdata->u.ibss.control_port) | ||
274 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
272 | 275 | ||
273 | rate_control_rate_init(sta); | 276 | rate_control_rate_init(sta); |
274 | 277 | ||
@@ -1075,6 +1078,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1075 | sdata->u.ibss.fixed_bssid = false; | 1078 | sdata->u.ibss.fixed_bssid = false; |
1076 | 1079 | ||
1077 | sdata->u.ibss.privacy = params->privacy; | 1080 | sdata->u.ibss.privacy = params->privacy; |
1081 | sdata->u.ibss.control_port = params->control_port; | ||
1078 | sdata->u.ibss.basic_rates = params->basic_rates; | 1082 | sdata->u.ibss.basic_rates = params->basic_rates; |
1079 | memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, | 1083 | memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, |
1080 | sizeof(params->mcast_rate)); | 1084 | sizeof(params->mcast_rate)); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d47e8c110b16..74594f012cd3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -280,10 +280,6 @@ struct mesh_preq_queue { | |||
280 | 280 | ||
281 | enum ieee80211_work_type { | 281 | enum ieee80211_work_type { |
282 | IEEE80211_WORK_ABORT, | 282 | IEEE80211_WORK_ABORT, |
283 | IEEE80211_WORK_DIRECT_PROBE, | ||
284 | IEEE80211_WORK_AUTH, | ||
285 | IEEE80211_WORK_ASSOC_BEACON_WAIT, | ||
286 | IEEE80211_WORK_ASSOC, | ||
287 | IEEE80211_WORK_REMAIN_ON_CHANNEL, | 283 | IEEE80211_WORK_REMAIN_ON_CHANNEL, |
288 | IEEE80211_WORK_OFFCHANNEL_TX, | 284 | IEEE80211_WORK_OFFCHANNEL_TX, |
289 | }; | 285 | }; |
@@ -316,36 +312,10 @@ struct ieee80211_work { | |||
316 | unsigned long timeout; | 312 | unsigned long timeout; |
317 | enum ieee80211_work_type type; | 313 | enum ieee80211_work_type type; |
318 | 314 | ||
319 | u8 filter_ta[ETH_ALEN]; | ||
320 | |||
321 | bool started; | 315 | bool started; |
322 | 316 | ||
323 | union { | 317 | union { |
324 | struct { | 318 | struct { |
325 | int tries; | ||
326 | u16 algorithm, transaction; | ||
327 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
328 | u8 ssid_len; | ||
329 | u8 key[WLAN_KEY_LEN_WEP104]; | ||
330 | u8 key_len, key_idx; | ||
331 | bool privacy; | ||
332 | bool synced; | ||
333 | } probe_auth; | ||
334 | struct { | ||
335 | struct cfg80211_bss *bss; | ||
336 | const u8 *supp_rates; | ||
337 | const u8 *ht_information_ie; | ||
338 | enum ieee80211_smps_mode smps; | ||
339 | int tries; | ||
340 | u16 capability; | ||
341 | u8 prev_bssid[ETH_ALEN]; | ||
342 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
343 | u8 ssid_len; | ||
344 | u8 supp_rates_len; | ||
345 | bool wmm_used, use_11n, uapsd_used; | ||
346 | bool synced; | ||
347 | } assoc; | ||
348 | struct { | ||
349 | u32 duration; | 319 | u32 duration; |
350 | } remain; | 320 | } remain; |
351 | struct { | 321 | struct { |
@@ -355,9 +325,8 @@ struct ieee80211_work { | |||
355 | } offchan_tx; | 325 | } offchan_tx; |
356 | }; | 326 | }; |
357 | 327 | ||
358 | int ie_len; | 328 | size_t data_len; |
359 | /* must be last */ | 329 | u8 data[]; |
360 | u8 ie[0]; | ||
361 | }; | 330 | }; |
362 | 331 | ||
363 | /* flags used in struct ieee80211_if_managed.flags */ | 332 | /* flags used in struct ieee80211_if_managed.flags */ |
@@ -373,6 +342,43 @@ enum ieee80211_sta_flags { | |||
373 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), | 342 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), |
374 | }; | 343 | }; |
375 | 344 | ||
345 | struct ieee80211_mgd_auth_data { | ||
346 | struct cfg80211_bss *bss; | ||
347 | unsigned long timeout; | ||
348 | int tries; | ||
349 | u16 algorithm, expected_transaction; | ||
350 | |||
351 | u8 key[WLAN_KEY_LEN_WEP104]; | ||
352 | u8 key_len, key_idx; | ||
353 | bool synced; | ||
354 | bool done; | ||
355 | |||
356 | size_t ie_len; | ||
357 | u8 ie[]; | ||
358 | }; | ||
359 | |||
360 | struct ieee80211_mgd_assoc_data { | ||
361 | struct cfg80211_bss *bss; | ||
362 | const u8 *supp_rates; | ||
363 | const u8 *ht_information_ie; | ||
364 | |||
365 | unsigned long timeout; | ||
366 | int tries; | ||
367 | |||
368 | u16 capability; | ||
369 | u8 prev_bssid[ETH_ALEN]; | ||
370 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
371 | u8 ssid_len; | ||
372 | u8 supp_rates_len; | ||
373 | bool wmm_used, uapsd_used; | ||
374 | bool have_beacon; | ||
375 | bool sent_assoc; | ||
376 | bool synced; | ||
377 | |||
378 | size_t ie_len; | ||
379 | u8 ie[]; | ||
380 | }; | ||
381 | |||
376 | struct ieee80211_if_managed { | 382 | struct ieee80211_if_managed { |
377 | struct timer_list timer; | 383 | struct timer_list timer; |
378 | struct timer_list conn_mon_timer; | 384 | struct timer_list conn_mon_timer; |
@@ -389,6 +395,8 @@ struct ieee80211_if_managed { | |||
389 | 395 | ||
390 | struct mutex mtx; | 396 | struct mutex mtx; |
391 | struct cfg80211_bss *associated; | 397 | struct cfg80211_bss *associated; |
398 | struct ieee80211_mgd_auth_data *auth_data; | ||
399 | struct ieee80211_mgd_assoc_data *assoc_data; | ||
392 | 400 | ||
393 | u8 bssid[ETH_ALEN]; | 401 | u8 bssid[ETH_ALEN]; |
394 | 402 | ||
@@ -470,6 +478,8 @@ struct ieee80211_if_ibss { | |||
470 | bool fixed_channel; | 478 | bool fixed_channel; |
471 | bool privacy; | 479 | bool privacy; |
472 | 480 | ||
481 | bool control_port; | ||
482 | |||
473 | u8 bssid[ETH_ALEN]; | 483 | u8 bssid[ETH_ALEN]; |
474 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 484 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
475 | u8 ssid_len, ie_len; | 485 | u8 ssid_len, ie_len; |
@@ -770,7 +780,6 @@ struct ieee80211_local { | |||
770 | struct list_head work_list; | 780 | struct list_head work_list; |
771 | struct timer_list work_timer; | 781 | struct timer_list work_timer; |
772 | struct work_struct work_work; | 782 | struct work_struct work_work; |
773 | struct sk_buff_head work_skb_queue; | ||
774 | 783 | ||
775 | /* | 784 | /* |
776 | * private workqueue to mac80211. mac80211 makes this accessible | 785 | * private workqueue to mac80211. mac80211 makes this accessible |
@@ -1437,8 +1446,6 @@ void ieee80211_work_init(struct ieee80211_local *local); | |||
1437 | void ieee80211_add_work(struct ieee80211_work *wk); | 1446 | void ieee80211_add_work(struct ieee80211_work *wk); |
1438 | void free_work(struct ieee80211_work *wk); | 1447 | void free_work(struct ieee80211_work *wk); |
1439 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); | 1448 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); |
1440 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | ||
1441 | struct sk_buff *skb); | ||
1442 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | 1449 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, |
1443 | struct ieee80211_channel *chan, | 1450 | struct ieee80211_channel *chan, |
1444 | enum nl80211_channel_type channel_type, | 1451 | enum nl80211_channel_type channel_type, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2efd595b2f7a..6b3cd65d1e07 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1310,7 +1310,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1310 | 1310 | ||
1311 | /* do not count disabled managed interfaces */ | 1311 | /* do not count disabled managed interfaces */ |
1312 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1312 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1313 | !sdata->u.mgd.associated) { | 1313 | !sdata->u.mgd.associated && |
1314 | !sdata->u.mgd.auth_data && | ||
1315 | !sdata->u.mgd.assoc_data) { | ||
1314 | sdata->vif.bss_conf.idle = true; | 1316 | sdata->vif.bss_conf.idle = true; |
1315 | continue; | 1317 | continue; |
1316 | } | 1318 | } |
@@ -1330,7 +1332,8 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1330 | wk->sdata->vif.bss_conf.idle = false; | 1332 | wk->sdata->vif.bss_conf.idle = false; |
1331 | } | 1333 | } |
1332 | 1334 | ||
1333 | if (local->scan_sdata) { | 1335 | if (local->scan_sdata && |
1336 | !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { | ||
1334 | scanning = true; | 1337 | scanning = true; |
1335 | local->scan_sdata->vif.bss_conf.idle = false; | 1338 | local->scan_sdata->vif.bss_conf.idle = false; |
1336 | } | 1339 | } |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 87a89741432d..e8616b3ff636 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -54,14 +54,6 @@ static void assert_key_lock(struct ieee80211_local *local) | |||
54 | lockdep_assert_held(&local->key_mtx); | 54 | lockdep_assert_held(&local->key_mtx); |
55 | } | 55 | } |
56 | 56 | ||
57 | static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) | ||
58 | { | ||
59 | if (key->sta) | ||
60 | return &key->sta->sta; | ||
61 | |||
62 | return NULL; | ||
63 | } | ||
64 | |||
65 | static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) | 57 | static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) |
66 | { | 58 | { |
67 | /* | 59 | /* |
@@ -95,7 +87,7 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) | |||
95 | static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | 87 | static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) |
96 | { | 88 | { |
97 | struct ieee80211_sub_if_data *sdata; | 89 | struct ieee80211_sub_if_data *sdata; |
98 | struct ieee80211_sta *sta; | 90 | struct sta_info *sta; |
99 | int ret; | 91 | int ret; |
100 | 92 | ||
101 | might_sleep(); | 93 | might_sleep(); |
@@ -105,7 +97,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
105 | 97 | ||
106 | assert_key_lock(key->local); | 98 | assert_key_lock(key->local); |
107 | 99 | ||
108 | sta = get_sta_for_key(key); | 100 | sta = key->sta; |
109 | 101 | ||
110 | /* | 102 | /* |
111 | * If this is a per-STA GTK, check if it | 103 | * If this is a per-STA GTK, check if it |
@@ -115,6 +107,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
115 | !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)) | 107 | !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)) |
116 | goto out_unsupported; | 108 | goto out_unsupported; |
117 | 109 | ||
110 | if (sta && !sta->uploaded) | ||
111 | goto out_unsupported; | ||
112 | |||
118 | sdata = key->sdata; | 113 | sdata = key->sdata; |
119 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { | 114 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { |
120 | /* | 115 | /* |
@@ -123,12 +118,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
123 | */ | 118 | */ |
124 | if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) | 119 | if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) |
125 | goto out_unsupported; | 120 | goto out_unsupported; |
126 | sdata = container_of(sdata->bss, | ||
127 | struct ieee80211_sub_if_data, | ||
128 | u.ap); | ||
129 | } | 121 | } |
130 | 122 | ||
131 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); | 123 | ret = drv_set_key(key->local, SET_KEY, sdata, |
124 | sta ? &sta->sta : NULL, &key->conf); | ||
132 | 125 | ||
133 | if (!ret) { | 126 | if (!ret) { |
134 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 127 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
@@ -147,7 +140,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
147 | if (ret != -ENOSPC && ret != -EOPNOTSUPP) | 140 | if (ret != -ENOSPC && ret != -EOPNOTSUPP) |
148 | wiphy_err(key->local->hw.wiphy, | 141 | wiphy_err(key->local->hw.wiphy, |
149 | "failed to set key (%d, %pM) to hardware (%d)\n", | 142 | "failed to set key (%d, %pM) to hardware (%d)\n", |
150 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); | 143 | key->conf.keyidx, |
144 | sta ? sta->sta.addr : bcast_addr, ret); | ||
151 | 145 | ||
152 | out_unsupported: | 146 | out_unsupported: |
153 | switch (key->conf.cipher) { | 147 | switch (key->conf.cipher) { |
@@ -166,7 +160,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
166 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | 160 | static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) |
167 | { | 161 | { |
168 | struct ieee80211_sub_if_data *sdata; | 162 | struct ieee80211_sub_if_data *sdata; |
169 | struct ieee80211_sta *sta; | 163 | struct sta_info *sta; |
170 | int ret; | 164 | int ret; |
171 | 165 | ||
172 | might_sleep(); | 166 | might_sleep(); |
@@ -179,7 +173,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
179 | if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 173 | if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
180 | return; | 174 | return; |
181 | 175 | ||
182 | sta = get_sta_for_key(key); | 176 | sta = key->sta; |
183 | sdata = key->sdata; | 177 | sdata = key->sdata; |
184 | 178 | ||
185 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || | 179 | if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || |
@@ -187,18 +181,14 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
187 | (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) | 181 | (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) |
188 | increment_tailroom_need_count(sdata); | 182 | increment_tailroom_need_count(sdata); |
189 | 183 | ||
190 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
191 | sdata = container_of(sdata->bss, | ||
192 | struct ieee80211_sub_if_data, | ||
193 | u.ap); | ||
194 | |||
195 | ret = drv_set_key(key->local, DISABLE_KEY, sdata, | 184 | ret = drv_set_key(key->local, DISABLE_KEY, sdata, |
196 | sta, &key->conf); | 185 | sta ? &sta->sta : NULL, &key->conf); |
197 | 186 | ||
198 | if (ret) | 187 | if (ret) |
199 | wiphy_err(key->local->hw.wiphy, | 188 | wiphy_err(key->local->hw.wiphy, |
200 | "failed to remove key (%d, %pM) from hardware (%d)\n", | 189 | "failed to remove key (%d, %pM) from hardware (%d)\n", |
201 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); | 190 | key->conf.keyidx, |
191 | sta ? sta->sta.addr : bcast_addr, ret); | ||
202 | 192 | ||
203 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 193 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
204 | } | 194 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0ec18618fcfe..2306d7514fff 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -199,15 +199,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
199 | return; | 199 | return; |
200 | 200 | ||
201 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 201 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
202 | /* | 202 | sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; |
203 | * While not associated, claim a BSSID of all-zeroes | ||
204 | * so that drivers don't do any weird things with the | ||
205 | * BSSID at that time. | ||
206 | */ | ||
207 | if (sdata->vif.bss_conf.assoc) | ||
208 | sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; | ||
209 | else | ||
210 | sdata->vif.bss_conf.bssid = zero; | ||
211 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 203 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
212 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; | 204 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; |
213 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | 205 | else if (sdata->vif.type == NL80211_IFTYPE_AP) |
@@ -535,6 +527,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
535 | int priv_size, i; | 527 | int priv_size, i; |
536 | struct wiphy *wiphy; | 528 | struct wiphy *wiphy; |
537 | 529 | ||
530 | if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove))) | ||
531 | return NULL; | ||
532 | |||
538 | /* Ensure 32-byte alignment of our private data and hw private data. | 533 | /* Ensure 32-byte alignment of our private data and hw private data. |
539 | * We use the wiphy priv data for both our ieee80211_local and for | 534 | * We use the wiphy priv data for both our ieee80211_local and for |
540 | * the driver's private data | 535 | * the driver's private data |
@@ -702,6 +697,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
702 | ) | 697 | ) |
703 | return -EINVAL; | 698 | return -EINVAL; |
704 | 699 | ||
700 | if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) | ||
701 | return -EINVAL; | ||
702 | |||
705 | if (hw->max_report_rates == 0) | 703 | if (hw->max_report_rates == 0) |
706 | hw->max_report_rates = hw->max_rates; | 704 | hw->max_report_rates = hw->max_rates; |
707 | 705 | ||
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index edf167e3b8f3..dc51669e67d8 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -336,7 +336,7 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, | |||
336 | } | 336 | } |
337 | 337 | ||
338 | 338 | ||
339 | static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst, | 339 | static struct mesh_path *mpath_lookup(struct mesh_table *tbl, u8 *dst, |
340 | struct ieee80211_sub_if_data *sdata) | 340 | struct ieee80211_sub_if_data *sdata) |
341 | { | 341 | { |
342 | struct mesh_path *mpath; | 342 | struct mesh_path *mpath; |
@@ -371,12 +371,12 @@ static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst, | |||
371 | */ | 371 | */ |
372 | struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | 372 | struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) |
373 | { | 373 | { |
374 | return path_lookup(rcu_dereference(mesh_paths), dst, sdata); | 374 | return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata); |
375 | } | 375 | } |
376 | 376 | ||
377 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | 377 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) |
378 | { | 378 | { |
379 | return path_lookup(rcu_dereference(mpp_paths), dst, sdata); | 379 | return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata); |
380 | } | 380 | } |
381 | 381 | ||
382 | 382 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 49fd1acd5d15..52133dab9297 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -30,6 +30,12 @@ | |||
30 | #include "rate.h" | 30 | #include "rate.h" |
31 | #include "led.h" | 31 | #include "led.h" |
32 | 32 | ||
33 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | ||
34 | #define IEEE80211_AUTH_MAX_TRIES 3 | ||
35 | #define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) | ||
36 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | ||
37 | #define IEEE80211_ASSOC_MAX_TRIES 3 | ||
38 | |||
33 | static int max_nullfunc_tries = 2; | 39 | static int max_nullfunc_tries = 2; |
34 | module_param(max_nullfunc_tries, int, 0644); | 40 | module_param(max_nullfunc_tries, int, 0644); |
35 | MODULE_PARM_DESC(max_nullfunc_tries, | 41 | MODULE_PARM_DESC(max_nullfunc_tries, |
@@ -97,6 +103,15 @@ enum rx_mgmt_action { | |||
97 | 103 | ||
98 | /* caller must call cfg80211_send_disassoc() */ | 104 | /* caller must call cfg80211_send_disassoc() */ |
99 | RX_MGMT_CFG80211_DISASSOC, | 105 | RX_MGMT_CFG80211_DISASSOC, |
106 | |||
107 | /* caller must call cfg80211_send_rx_auth() */ | ||
108 | RX_MGMT_CFG80211_RX_AUTH, | ||
109 | |||
110 | /* caller must call cfg80211_send_rx_assoc() */ | ||
111 | RX_MGMT_CFG80211_RX_ASSOC, | ||
112 | |||
113 | /* caller must call cfg80211_send_assoc_timeout() */ | ||
114 | RX_MGMT_CFG80211_ASSOC_TIMEOUT, | ||
100 | }; | 115 | }; |
101 | 116 | ||
102 | /* utils */ | 117 | /* utils */ |
@@ -115,8 +130,7 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) | |||
115 | * has happened -- the work that runs from this timer will | 130 | * has happened -- the work that runs from this timer will |
116 | * do that. | 131 | * do that. |
117 | */ | 132 | */ |
118 | static void run_again(struct ieee80211_if_managed *ifmgd, | 133 | static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout) |
119 | unsigned long timeout) | ||
120 | { | 134 | { |
121 | ASSERT_MGD_MTX(ifmgd); | 135 | ASSERT_MGD_MTX(ifmgd); |
122 | 136 | ||
@@ -284,6 +298,319 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
284 | 298 | ||
285 | /* frame sending functions */ | 299 | /* frame sending functions */ |
286 | 300 | ||
301 | static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | ||
302 | struct ieee80211_supported_band *sband, | ||
303 | u32 *rates) | ||
304 | { | ||
305 | int i, j, count; | ||
306 | *rates = 0; | ||
307 | count = 0; | ||
308 | for (i = 0; i < supp_rates_len; i++) { | ||
309 | int rate = (supp_rates[i] & 0x7F) * 5; | ||
310 | |||
311 | for (j = 0; j < sband->n_bitrates; j++) | ||
312 | if (sband->bitrates[j].bitrate == rate) { | ||
313 | *rates |= BIT(j); | ||
314 | count++; | ||
315 | break; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | return count; | ||
320 | } | ||
321 | |||
322 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | ||
323 | struct sk_buff *skb, const u8 *ht_info_ie, | ||
324 | struct ieee80211_supported_band *sband, | ||
325 | struct ieee80211_channel *channel, | ||
326 | enum ieee80211_smps_mode smps) | ||
327 | { | ||
328 | struct ieee80211_ht_info *ht_info; | ||
329 | u8 *pos; | ||
330 | u32 flags = channel->flags; | ||
331 | u16 cap; | ||
332 | struct ieee80211_sta_ht_cap ht_cap; | ||
333 | |||
334 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); | ||
335 | |||
336 | if (!sband->ht_cap.ht_supported) | ||
337 | return; | ||
338 | |||
339 | if (!ht_info_ie) | ||
340 | return; | ||
341 | |||
342 | if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) | ||
343 | return; | ||
344 | |||
345 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | ||
346 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | ||
347 | |||
348 | ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); | ||
349 | |||
350 | /* determine capability flags */ | ||
351 | cap = ht_cap.cap; | ||
352 | |||
353 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
354 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
355 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | ||
356 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
357 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
358 | } | ||
359 | break; | ||
360 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
361 | if (flags & IEEE80211_CHAN_NO_HT40MINUS) { | ||
362 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
363 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
364 | } | ||
365 | break; | ||
366 | } | ||
367 | |||
368 | /* set SM PS mode properly */ | ||
369 | cap &= ~IEEE80211_HT_CAP_SM_PS; | ||
370 | switch (smps) { | ||
371 | case IEEE80211_SMPS_AUTOMATIC: | ||
372 | case IEEE80211_SMPS_NUM_MODES: | ||
373 | WARN_ON(1); | ||
374 | case IEEE80211_SMPS_OFF: | ||
375 | cap |= WLAN_HT_CAP_SM_PS_DISABLED << | ||
376 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
377 | break; | ||
378 | case IEEE80211_SMPS_STATIC: | ||
379 | cap |= WLAN_HT_CAP_SM_PS_STATIC << | ||
380 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
381 | break; | ||
382 | case IEEE80211_SMPS_DYNAMIC: | ||
383 | cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
384 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
385 | break; | ||
386 | } | ||
387 | |||
388 | /* reserve and fill IE */ | ||
389 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
390 | ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); | ||
391 | } | ||
392 | |||
393 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | ||
394 | { | ||
395 | struct ieee80211_local *local = sdata->local; | ||
396 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
397 | struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; | ||
398 | struct sk_buff *skb; | ||
399 | struct ieee80211_mgmt *mgmt; | ||
400 | u8 *pos, qos_info; | ||
401 | size_t offset = 0, noffset; | ||
402 | int i, count, rates_len, supp_rates_len; | ||
403 | u16 capab; | ||
404 | struct ieee80211_supported_band *sband; | ||
405 | u32 rates = 0; | ||
406 | struct ieee80211_bss *bss = (void *)assoc_data->bss->priv; | ||
407 | |||
408 | lockdep_assert_held(&ifmgd->mtx); | ||
409 | |||
410 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | ||
411 | |||
412 | if (assoc_data->supp_rates_len) { | ||
413 | /* | ||
414 | * Get all rates supported by the device and the AP as | ||
415 | * some APs don't like getting a superset of their rates | ||
416 | * in the association request (e.g. D-Link DAP 1353 in | ||
417 | * b-only mode)... | ||
418 | */ | ||
419 | rates_len = ieee80211_compatible_rates(assoc_data->supp_rates, | ||
420 | assoc_data->supp_rates_len, | ||
421 | sband, &rates); | ||
422 | } else { | ||
423 | /* | ||
424 | * In case AP not provide any supported rates information | ||
425 | * before association, we send information element(s) with | ||
426 | * all rates that we support. | ||
427 | */ | ||
428 | rates = ~0; | ||
429 | rates_len = sband->n_bitrates; | ||
430 | } | ||
431 | |||
432 | skb = alloc_skb(local->hw.extra_tx_headroom + | ||
433 | sizeof(*mgmt) + /* bit too much but doesn't matter */ | ||
434 | 2 + assoc_data->ssid_len + /* SSID */ | ||
435 | 4 + rates_len + /* (extended) rates */ | ||
436 | 4 + /* power capability */ | ||
437 | 2 + 2 * sband->n_channels + /* supported channels */ | ||
438 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ | ||
439 | assoc_data->ie_len + /* extra IEs */ | ||
440 | 9, /* WMM */ | ||
441 | GFP_KERNEL); | ||
442 | if (!skb) | ||
443 | return; | ||
444 | |||
445 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
446 | |||
447 | capab = WLAN_CAPABILITY_ESS; | ||
448 | |||
449 | if (sband->band == IEEE80211_BAND_2GHZ) { | ||
450 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | ||
451 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; | ||
452 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) | ||
453 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
454 | } | ||
455 | |||
456 | if (assoc_data->capability & WLAN_CAPABILITY_PRIVACY) | ||
457 | capab |= WLAN_CAPABILITY_PRIVACY; | ||
458 | |||
459 | if ((assoc_data->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && | ||
460 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) | ||
461 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; | ||
462 | |||
463 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
464 | memset(mgmt, 0, 24); | ||
465 | memcpy(mgmt->da, assoc_data->bss->bssid, ETH_ALEN); | ||
466 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
467 | memcpy(mgmt->bssid, assoc_data->bss->bssid, ETH_ALEN); | ||
468 | |||
469 | if (!is_zero_ether_addr(assoc_data->prev_bssid)) { | ||
470 | skb_put(skb, 10); | ||
471 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
472 | IEEE80211_STYPE_REASSOC_REQ); | ||
473 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); | ||
474 | mgmt->u.reassoc_req.listen_interval = | ||
475 | cpu_to_le16(local->hw.conf.listen_interval); | ||
476 | memcpy(mgmt->u.reassoc_req.current_ap, assoc_data->prev_bssid, | ||
477 | ETH_ALEN); | ||
478 | } else { | ||
479 | skb_put(skb, 4); | ||
480 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
481 | IEEE80211_STYPE_ASSOC_REQ); | ||
482 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | ||
483 | mgmt->u.assoc_req.listen_interval = | ||
484 | cpu_to_le16(local->hw.conf.listen_interval); | ||
485 | } | ||
486 | |||
487 | /* SSID */ | ||
488 | pos = skb_put(skb, 2 + assoc_data->ssid_len); | ||
489 | *pos++ = WLAN_EID_SSID; | ||
490 | *pos++ = assoc_data->ssid_len; | ||
491 | memcpy(pos, assoc_data->ssid, assoc_data->ssid_len); | ||
492 | |||
493 | /* add all rates which were marked to be used above */ | ||
494 | supp_rates_len = rates_len; | ||
495 | if (supp_rates_len > 8) | ||
496 | supp_rates_len = 8; | ||
497 | |||
498 | pos = skb_put(skb, supp_rates_len + 2); | ||
499 | *pos++ = WLAN_EID_SUPP_RATES; | ||
500 | *pos++ = supp_rates_len; | ||
501 | |||
502 | count = 0; | ||
503 | for (i = 0; i < sband->n_bitrates; i++) { | ||
504 | if (BIT(i) & rates) { | ||
505 | int rate = sband->bitrates[i].bitrate; | ||
506 | *pos++ = (u8) (rate / 5); | ||
507 | if (++count == 8) | ||
508 | break; | ||
509 | } | ||
510 | } | ||
511 | |||
512 | if (rates_len > count) { | ||
513 | pos = skb_put(skb, rates_len - count + 2); | ||
514 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
515 | *pos++ = rates_len - count; | ||
516 | |||
517 | for (i++; i < sband->n_bitrates; i++) { | ||
518 | if (BIT(i) & rates) { | ||
519 | int rate = sband->bitrates[i].bitrate; | ||
520 | *pos++ = (u8) (rate / 5); | ||
521 | } | ||
522 | } | ||
523 | } | ||
524 | |||
525 | if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { | ||
526 | /* 1. power capabilities */ | ||
527 | pos = skb_put(skb, 4); | ||
528 | *pos++ = WLAN_EID_PWR_CAPABILITY; | ||
529 | *pos++ = 2; | ||
530 | *pos++ = 0; /* min tx power */ | ||
531 | *pos++ = local->oper_channel->max_power; /* max tx power */ | ||
532 | |||
533 | /* 2. supported channels */ | ||
534 | /* TODO: get this in reg domain format */ | ||
535 | pos = skb_put(skb, 2 * sband->n_channels + 2); | ||
536 | *pos++ = WLAN_EID_SUPPORTED_CHANNELS; | ||
537 | *pos++ = 2 * sband->n_channels; | ||
538 | for (i = 0; i < sband->n_channels; i++) { | ||
539 | *pos++ = ieee80211_frequency_to_channel( | ||
540 | sband->channels[i].center_freq); | ||
541 | *pos++ = 1; /* one channel in the subband*/ | ||
542 | } | ||
543 | } | ||
544 | |||
545 | /* if present, add any custom IEs that go before HT */ | ||
546 | if (assoc_data->ie_len && assoc_data->ie) { | ||
547 | static const u8 before_ht[] = { | ||
548 | WLAN_EID_SSID, | ||
549 | WLAN_EID_SUPP_RATES, | ||
550 | WLAN_EID_EXT_SUPP_RATES, | ||
551 | WLAN_EID_PWR_CAPABILITY, | ||
552 | WLAN_EID_SUPPORTED_CHANNELS, | ||
553 | WLAN_EID_RSN, | ||
554 | WLAN_EID_QOS_CAPA, | ||
555 | WLAN_EID_RRM_ENABLED_CAPABILITIES, | ||
556 | WLAN_EID_MOBILITY_DOMAIN, | ||
557 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
558 | }; | ||
559 | noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, | ||
560 | before_ht, ARRAY_SIZE(before_ht), | ||
561 | offset); | ||
562 | pos = skb_put(skb, noffset - offset); | ||
563 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | ||
564 | offset = noffset; | ||
565 | } | ||
566 | |||
567 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N) && | ||
568 | bss->wmm_used && local->hw.queues >= 4) | ||
569 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie, | ||
570 | sband, local->oper_channel, ifmgd->ap_smps); | ||
571 | |||
572 | /* if present, add any custom non-vendor IEs that go after HT */ | ||
573 | if (assoc_data->ie_len && assoc_data->ie) { | ||
574 | noffset = ieee80211_ie_split_vendor(assoc_data->ie, | ||
575 | assoc_data->ie_len, | ||
576 | offset); | ||
577 | pos = skb_put(skb, noffset - offset); | ||
578 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | ||
579 | offset = noffset; | ||
580 | } | ||
581 | |||
582 | if (assoc_data->wmm_used && local->hw.queues >= 4) { | ||
583 | if (assoc_data->uapsd_used) { | ||
584 | qos_info = local->uapsd_queues; | ||
585 | qos_info |= (local->uapsd_max_sp_len << | ||
586 | IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT); | ||
587 | } else { | ||
588 | qos_info = 0; | ||
589 | } | ||
590 | |||
591 | pos = skb_put(skb, 9); | ||
592 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
593 | *pos++ = 7; /* len */ | ||
594 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
595 | *pos++ = 0x50; | ||
596 | *pos++ = 0xf2; | ||
597 | *pos++ = 2; /* WME */ | ||
598 | *pos++ = 0; /* WME info */ | ||
599 | *pos++ = 1; /* WME ver */ | ||
600 | *pos++ = qos_info; | ||
601 | } | ||
602 | |||
603 | /* add any remaining custom (i.e. vendor specific here) IEs */ | ||
604 | if (assoc_data->ie_len && assoc_data->ie) { | ||
605 | noffset = assoc_data->ie_len; | ||
606 | pos = skb_put(skb, noffset - offset); | ||
607 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | ||
608 | } | ||
609 | |||
610 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
611 | ieee80211_tx_skb(sdata, skb); | ||
612 | } | ||
613 | |||
287 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | 614 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, |
288 | const u8 *bssid, u16 stype, u16 reason, | 615 | const u8 *bssid, u16 stype, u16 reason, |
289 | void *cookie, bool send_frame) | 616 | void *cookie, bool send_frame) |
@@ -1423,6 +1750,135 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif) | |||
1423 | EXPORT_SYMBOL(ieee80211_connection_loss); | 1750 | EXPORT_SYMBOL(ieee80211_connection_loss); |
1424 | 1751 | ||
1425 | 1752 | ||
1753 | static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, | ||
1754 | bool assoc) | ||
1755 | { | ||
1756 | struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; | ||
1757 | |||
1758 | lockdep_assert_held(&sdata->u.mgd.mtx); | ||
1759 | |||
1760 | if (auth_data->synced) | ||
1761 | drv_finish_tx_sync(sdata->local, sdata, | ||
1762 | auth_data->bss->bssid, | ||
1763 | IEEE80211_TX_SYNC_AUTH); | ||
1764 | |||
1765 | if (!assoc) { | ||
1766 | sta_info_destroy_addr(sdata, auth_data->bss->bssid); | ||
1767 | |||
1768 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | ||
1769 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | ||
1770 | } | ||
1771 | |||
1772 | cfg80211_put_bss(auth_data->bss); | ||
1773 | kfree(auth_data); | ||
1774 | sdata->u.mgd.auth_data = NULL; | ||
1775 | } | ||
1776 | |||
1777 | static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | ||
1778 | struct ieee80211_mgmt *mgmt, size_t len) | ||
1779 | { | ||
1780 | struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; | ||
1781 | u8 *pos; | ||
1782 | struct ieee802_11_elems elems; | ||
1783 | |||
1784 | pos = mgmt->u.auth.variable; | ||
1785 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1786 | if (!elems.challenge) | ||
1787 | return; | ||
1788 | auth_data->expected_transaction = 4; | ||
1789 | ieee80211_send_auth(sdata, 3, auth_data->algorithm, | ||
1790 | elems.challenge - 2, elems.challenge_len + 2, | ||
1791 | auth_data->bss->bssid, auth_data->bss->bssid, | ||
1792 | auth_data->key, auth_data->key_len, | ||
1793 | auth_data->key_idx); | ||
1794 | } | ||
1795 | |||
1796 | static enum rx_mgmt_action __must_check | ||
1797 | ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | ||
1798 | struct ieee80211_mgmt *mgmt, size_t len) | ||
1799 | { | ||
1800 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1801 | u8 bssid[ETH_ALEN]; | ||
1802 | u16 auth_alg, auth_transaction, status_code; | ||
1803 | struct sta_info *sta; | ||
1804 | |||
1805 | lockdep_assert_held(&ifmgd->mtx); | ||
1806 | |||
1807 | if (len < 24 + 6) | ||
1808 | return RX_MGMT_NONE; | ||
1809 | |||
1810 | if (!ifmgd->auth_data || ifmgd->auth_data->done) | ||
1811 | return RX_MGMT_NONE; | ||
1812 | |||
1813 | memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN); | ||
1814 | |||
1815 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN)) | ||
1816 | return RX_MGMT_NONE; | ||
1817 | |||
1818 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | ||
1819 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | ||
1820 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | ||
1821 | |||
1822 | if (auth_alg != ifmgd->auth_data->algorithm || | ||
1823 | auth_transaction != ifmgd->auth_data->expected_transaction) | ||
1824 | return RX_MGMT_NONE; | ||
1825 | |||
1826 | if (status_code != WLAN_STATUS_SUCCESS) { | ||
1827 | printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", | ||
1828 | sdata->name, mgmt->sa, status_code); | ||
1829 | goto out; | ||
1830 | } | ||
1831 | |||
1832 | switch (ifmgd->auth_data->algorithm) { | ||
1833 | case WLAN_AUTH_OPEN: | ||
1834 | case WLAN_AUTH_LEAP: | ||
1835 | case WLAN_AUTH_FT: | ||
1836 | break; | ||
1837 | case WLAN_AUTH_SHARED_KEY: | ||
1838 | if (ifmgd->auth_data->expected_transaction != 4) { | ||
1839 | ieee80211_auth_challenge(sdata, mgmt, len); | ||
1840 | /* need another frame */ | ||
1841 | return RX_MGMT_NONE; | ||
1842 | } | ||
1843 | break; | ||
1844 | default: | ||
1845 | WARN_ONCE(1, "invalid auth alg %d", | ||
1846 | ifmgd->auth_data->algorithm); | ||
1847 | return RX_MGMT_NONE; | ||
1848 | } | ||
1849 | |||
1850 | printk(KERN_DEBUG "%s: authenticated\n", sdata->name); | ||
1851 | out: | ||
1852 | if (ifmgd->auth_data->synced) | ||
1853 | drv_finish_tx_sync(sdata->local, sdata, bssid, | ||
1854 | IEEE80211_TX_SYNC_AUTH); | ||
1855 | ifmgd->auth_data->synced = false; | ||
1856 | ifmgd->auth_data->done = true; | ||
1857 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; | ||
1858 | run_again(ifmgd, ifmgd->auth_data->timeout); | ||
1859 | |||
1860 | /* move station state to auth */ | ||
1861 | mutex_lock(&sdata->local->sta_mtx); | ||
1862 | sta = sta_info_get(sdata, bssid); | ||
1863 | if (!sta) { | ||
1864 | WARN_ONCE(1, "%s: STA %pM not found", sdata->name, bssid); | ||
1865 | goto out_err; | ||
1866 | } | ||
1867 | if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) { | ||
1868 | printk(KERN_DEBUG "%s: failed moving %pM to auth\n", | ||
1869 | sdata->name, bssid); | ||
1870 | goto out_err; | ||
1871 | } | ||
1872 | mutex_unlock(&sdata->local->sta_mtx); | ||
1873 | |||
1874 | return RX_MGMT_CFG80211_RX_AUTH; | ||
1875 | out_err: | ||
1876 | mutex_unlock(&sdata->local->sta_mtx); | ||
1877 | /* ignore frame -- wait for timeout */ | ||
1878 | return RX_MGMT_NONE; | ||
1879 | } | ||
1880 | |||
1881 | |||
1426 | static enum rx_mgmt_action __must_check | 1882 | static enum rx_mgmt_action __must_check |
1427 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | 1883 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
1428 | struct ieee80211_mgmt *mgmt, size_t len) | 1884 | struct ieee80211_mgmt *mgmt, size_t len) |
@@ -1431,10 +1887,14 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1431 | const u8 *bssid = NULL; | 1887 | const u8 *bssid = NULL; |
1432 | u16 reason_code; | 1888 | u16 reason_code; |
1433 | 1889 | ||
1890 | lockdep_assert_held(&ifmgd->mtx); | ||
1891 | |||
1434 | if (len < 24 + 2) | 1892 | if (len < 24 + 2) |
1435 | return RX_MGMT_NONE; | 1893 | return RX_MGMT_NONE; |
1436 | 1894 | ||
1437 | ASSERT_MGD_MTX(ifmgd); | 1895 | if (!ifmgd->associated || |
1896 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN)) | ||
1897 | return RX_MGMT_NONE; | ||
1438 | 1898 | ||
1439 | bssid = ifmgd->associated->bssid; | 1899 | bssid = ifmgd->associated->bssid; |
1440 | 1900 | ||
@@ -1459,15 +1919,13 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1459 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1919 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1460 | u16 reason_code; | 1920 | u16 reason_code; |
1461 | 1921 | ||
1462 | if (len < 24 + 2) | 1922 | lockdep_assert_held(&ifmgd->mtx); |
1463 | return RX_MGMT_NONE; | ||
1464 | |||
1465 | ASSERT_MGD_MTX(ifmgd); | ||
1466 | 1923 | ||
1467 | if (WARN_ON(!ifmgd->associated)) | 1924 | if (len < 24 + 2) |
1468 | return RX_MGMT_NONE; | 1925 | return RX_MGMT_NONE; |
1469 | 1926 | ||
1470 | if (WARN_ON(memcmp(ifmgd->associated->bssid, mgmt->sa, ETH_ALEN))) | 1927 | if (!ifmgd->associated || |
1928 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN)) | ||
1471 | return RX_MGMT_NONE; | 1929 | return RX_MGMT_NONE; |
1472 | 1930 | ||
1473 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1931 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
@@ -1524,15 +1982,37 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, | |||
1524 | } | 1982 | } |
1525 | } | 1983 | } |
1526 | 1984 | ||
1527 | static bool ieee80211_assoc_success(struct ieee80211_work *wk, | 1985 | static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, |
1986 | bool assoc) | ||
1987 | { | ||
1988 | struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; | ||
1989 | |||
1990 | lockdep_assert_held(&sdata->u.mgd.mtx); | ||
1991 | |||
1992 | if (assoc_data->synced) | ||
1993 | drv_finish_tx_sync(sdata->local, sdata, | ||
1994 | assoc_data->bss->bssid, | ||
1995 | IEEE80211_TX_SYNC_ASSOC); | ||
1996 | |||
1997 | if (!assoc) { | ||
1998 | sta_info_destroy_addr(sdata, assoc_data->bss->bssid); | ||
1999 | |||
2000 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | ||
2001 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | ||
2002 | } | ||
2003 | |||
2004 | kfree(assoc_data); | ||
2005 | sdata->u.mgd.assoc_data = NULL; | ||
2006 | } | ||
2007 | |||
2008 | static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | ||
2009 | struct cfg80211_bss *cbss, | ||
1528 | struct ieee80211_mgmt *mgmt, size_t len) | 2010 | struct ieee80211_mgmt *mgmt, size_t len) |
1529 | { | 2011 | { |
1530 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
1531 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2012 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1532 | struct ieee80211_local *local = sdata->local; | 2013 | struct ieee80211_local *local = sdata->local; |
1533 | struct ieee80211_supported_band *sband; | 2014 | struct ieee80211_supported_band *sband; |
1534 | struct sta_info *sta; | 2015 | struct sta_info *sta; |
1535 | struct cfg80211_bss *cbss = wk->assoc.bss; | ||
1536 | u8 *pos; | 2016 | u8 *pos; |
1537 | u32 rates, basic_rates; | 2017 | u32 rates, basic_rates; |
1538 | u16 capab_info, aid; | 2018 | u16 capab_info, aid; |
@@ -1581,29 +2061,15 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1581 | * station info was already allocated and inserted before | 2061 | * station info was already allocated and inserted before |
1582 | * the association and should be available to us | 2062 | * the association and should be available to us |
1583 | */ | 2063 | */ |
1584 | sta = sta_info_get_rx(sdata, cbss->bssid); | 2064 | sta = sta_info_get(sdata, cbss->bssid); |
1585 | if (WARN_ON(!sta)) { | 2065 | if (WARN_ON(!sta)) { |
1586 | mutex_unlock(&sdata->local->sta_mtx); | 2066 | mutex_unlock(&sdata->local->sta_mtx); |
1587 | return false; | 2067 | return false; |
1588 | } | 2068 | } |
1589 | 2069 | ||
1590 | err = sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
1591 | if (!err) | ||
1592 | err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
1593 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | ||
1594 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
1595 | if (err) { | ||
1596 | printk(KERN_DEBUG | ||
1597 | "%s: failed to move station %pM to desired state\n", | ||
1598 | sdata->name, sta->sta.addr); | ||
1599 | WARN_ON(__sta_info_destroy(sta)); | ||
1600 | mutex_unlock(&sdata->local->sta_mtx); | ||
1601 | return false; | ||
1602 | } | ||
1603 | |||
1604 | rates = 0; | 2070 | rates = 0; |
1605 | basic_rates = 0; | 2071 | basic_rates = 0; |
1606 | sband = local->hw.wiphy->bands[wk->chan->band]; | 2072 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
1607 | 2073 | ||
1608 | ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len, | 2074 | ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len, |
1609 | &rates, &basic_rates, &have_higher_than_11mbit, | 2075 | &rates, &basic_rates, &have_higher_than_11mbit, |
@@ -1624,11 +2090,11 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1624 | basic_rates = BIT(min_rate_index); | 2090 | basic_rates = BIT(min_rate_index); |
1625 | } | 2091 | } |
1626 | 2092 | ||
1627 | sta->sta.supp_rates[wk->chan->band] = rates; | 2093 | sta->sta.supp_rates[local->oper_channel->band] = rates; |
1628 | sdata->vif.bss_conf.basic_rates = basic_rates; | 2094 | sdata->vif.bss_conf.basic_rates = basic_rates; |
1629 | 2095 | ||
1630 | /* cf. IEEE 802.11 9.2.12 */ | 2096 | /* cf. IEEE 802.11 9.2.12 */ |
1631 | if (wk->chan->band == IEEE80211_BAND_2GHZ && | 2097 | if (local->oper_channel->band == IEEE80211_BAND_2GHZ && |
1632 | have_higher_than_11mbit) | 2098 | have_higher_than_11mbit) |
1633 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 2099 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
1634 | else | 2100 | else |
@@ -1648,15 +2114,22 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1648 | if (elems.wmm_param) | 2114 | if (elems.wmm_param) |
1649 | set_sta_flag(sta, WLAN_STA_WME); | 2115 | set_sta_flag(sta, WLAN_STA_WME); |
1650 | 2116 | ||
1651 | /* sta_info_reinsert will also unlock the mutex lock */ | 2117 | err = sta_info_move_state(sta, IEEE80211_STA_AUTH); |
1652 | err = sta_info_reinsert(sta); | 2118 | if (!err) |
1653 | sta = NULL; | 2119 | err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
2120 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | ||
2121 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
1654 | if (err) { | 2122 | if (err) { |
1655 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | 2123 | printk(KERN_DEBUG |
1656 | " the AP (error %d)\n", sdata->name, err); | 2124 | "%s: failed to move station %pM to desired state\n", |
2125 | sdata->name, sta->sta.addr); | ||
2126 | WARN_ON(__sta_info_destroy(sta)); | ||
2127 | mutex_unlock(&sdata->local->sta_mtx); | ||
1657 | return false; | 2128 | return false; |
1658 | } | 2129 | } |
1659 | 2130 | ||
2131 | mutex_unlock(&sdata->local->sta_mtx); | ||
2132 | |||
1660 | /* | 2133 | /* |
1661 | * Always handle WMM once after association regardless | 2134 | * Always handle WMM once after association regardless |
1662 | * of the first value the AP uses. Setting -1 here has | 2135 | * of the first value the AP uses. Setting -1 here has |
@@ -1671,8 +2144,6 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1671 | else | 2144 | else |
1672 | ieee80211_set_wmm_default(sdata); | 2145 | ieee80211_set_wmm_default(sdata); |
1673 | 2146 | ||
1674 | local->oper_channel = wk->chan; | ||
1675 | |||
1676 | if (elems.ht_info_elem && elems.wmm_param && | 2147 | if (elems.ht_info_elem && elems.wmm_param && |
1677 | (sdata->local->hw.queues >= 4) && | 2148 | (sdata->local->hw.queues >= 4) && |
1678 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2149 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
@@ -1703,7 +2174,82 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1703 | return true; | 2174 | return true; |
1704 | } | 2175 | } |
1705 | 2176 | ||
2177 | static enum rx_mgmt_action __must_check | ||
2178 | ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | ||
2179 | struct ieee80211_mgmt *mgmt, size_t len, | ||
2180 | struct cfg80211_bss **bss) | ||
2181 | { | ||
2182 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2183 | struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; | ||
2184 | u16 capab_info, status_code, aid; | ||
2185 | struct ieee802_11_elems elems; | ||
2186 | u8 *pos; | ||
2187 | bool reassoc; | ||
2188 | |||
2189 | lockdep_assert_held(&ifmgd->mtx); | ||
2190 | |||
2191 | if (!assoc_data) | ||
2192 | return RX_MGMT_NONE; | ||
2193 | if (memcmp(assoc_data->bss->bssid, mgmt->bssid, ETH_ALEN)) | ||
2194 | return RX_MGMT_NONE; | ||
1706 | 2195 | ||
2196 | /* | ||
2197 | * AssocResp and ReassocResp have identical structure, so process both | ||
2198 | * of them in this function. | ||
2199 | */ | ||
2200 | |||
2201 | if (len < 24 + 6) | ||
2202 | return RX_MGMT_NONE; | ||
2203 | |||
2204 | reassoc = ieee80211_is_reassoc_req(mgmt->frame_control); | ||
2205 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | ||
2206 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | ||
2207 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | ||
2208 | |||
2209 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | ||
2210 | "status=%d aid=%d)\n", | ||
2211 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, | ||
2212 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | ||
2213 | |||
2214 | pos = mgmt->u.assoc_resp.variable; | ||
2215 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
2216 | |||
2217 | if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && | ||
2218 | elems.timeout_int && elems.timeout_int_len == 5 && | ||
2219 | elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { | ||
2220 | u32 tu, ms; | ||
2221 | tu = get_unaligned_le32(elems.timeout_int + 1); | ||
2222 | ms = tu * 1024 / 1000; | ||
2223 | printk(KERN_DEBUG "%s: %pM rejected association temporarily; " | ||
2224 | "comeback duration %u TU (%u ms)\n", | ||
2225 | sdata->name, mgmt->sa, tu, ms); | ||
2226 | assoc_data->timeout = jiffies + msecs_to_jiffies(ms); | ||
2227 | if (ms > IEEE80211_ASSOC_TIMEOUT) | ||
2228 | run_again(ifmgd, assoc_data->timeout); | ||
2229 | return RX_MGMT_NONE; | ||
2230 | } | ||
2231 | |||
2232 | *bss = assoc_data->bss; | ||
2233 | |||
2234 | if (status_code != WLAN_STATUS_SUCCESS) { | ||
2235 | printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", | ||
2236 | sdata->name, mgmt->sa, status_code); | ||
2237 | ieee80211_destroy_assoc_data(sdata, false); | ||
2238 | } else { | ||
2239 | printk(KERN_DEBUG "%s: associated\n", sdata->name); | ||
2240 | |||
2241 | ieee80211_destroy_assoc_data(sdata, true); | ||
2242 | |||
2243 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { | ||
2244 | /* oops -- internal error -- send timeout for now */ | ||
2245 | sta_info_destroy_addr(sdata, mgmt->bssid); | ||
2246 | cfg80211_put_bss(*bss); | ||
2247 | return RX_MGMT_CFG80211_ASSOC_TIMEOUT; | ||
2248 | } | ||
2249 | } | ||
2250 | |||
2251 | return RX_MGMT_CFG80211_RX_ASSOC; | ||
2252 | } | ||
1707 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 2253 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
1708 | struct ieee80211_mgmt *mgmt, | 2254 | struct ieee80211_mgmt *mgmt, |
1709 | size_t len, | 2255 | size_t len, |
@@ -1717,7 +2263,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1717 | struct ieee80211_channel *channel; | 2263 | struct ieee80211_channel *channel; |
1718 | bool need_ps = false; | 2264 | bool need_ps = false; |
1719 | 2265 | ||
1720 | if (sdata->u.mgd.associated) { | 2266 | if (sdata->u.mgd.associated && |
2267 | memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, | ||
2268 | ETH_ALEN) == 0) { | ||
1721 | bss = (void *)sdata->u.mgd.associated->priv; | 2269 | bss = (void *)sdata->u.mgd.associated->priv; |
1722 | /* not previously set so we may need to recalc */ | 2270 | /* not previously set so we may need to recalc */ |
1723 | need_ps = !bss->dtim_period; | 2271 | need_ps = !bss->dtim_period; |
@@ -1787,6 +2335,15 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1787 | if (ifmgd->associated && | 2335 | if (ifmgd->associated && |
1788 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0) | 2336 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0) |
1789 | ieee80211_reset_ap_probe(sdata); | 2337 | ieee80211_reset_ap_probe(sdata); |
2338 | |||
2339 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && | ||
2340 | memcmp(mgmt->bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN) == 0) { | ||
2341 | /* got probe response, continue with auth */ | ||
2342 | printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); | ||
2343 | ifmgd->auth_data->tries = 0; | ||
2344 | ifmgd->auth_data->timeout = jiffies; | ||
2345 | run_again(ifmgd, ifmgd->auth_data->timeout); | ||
2346 | } | ||
1790 | } | 2347 | } |
1791 | 2348 | ||
1792 | /* | 2349 | /* |
@@ -1826,7 +2383,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1826 | u32 ncrc; | 2383 | u32 ncrc; |
1827 | u8 *bssid; | 2384 | u8 *bssid; |
1828 | 2385 | ||
1829 | ASSERT_MGD_MTX(ifmgd); | 2386 | lockdep_assert_held(&ifmgd->mtx); |
1830 | 2387 | ||
1831 | /* Process beacon from the current BSS */ | 2388 | /* Process beacon from the current BSS */ |
1832 | baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; | 2389 | baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; |
@@ -1836,21 +2393,25 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1836 | if (rx_status->freq != local->hw.conf.channel->center_freq) | 2393 | if (rx_status->freq != local->hw.conf.channel->center_freq) |
1837 | return; | 2394 | return; |
1838 | 2395 | ||
1839 | /* | 2396 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && |
1840 | * We might have received a number of frames, among them a | 2397 | memcmp(mgmt->bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN) == 0) { |
1841 | * disassoc frame and a beacon... | 2398 | ieee802_11_parse_elems(mgmt->u.beacon.variable, |
1842 | */ | 2399 | len - baselen, &elems); |
1843 | if (!ifmgd->associated) | ||
1844 | return; | ||
1845 | 2400 | ||
1846 | bssid = ifmgd->associated->bssid; | 2401 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, |
2402 | false); | ||
2403 | ifmgd->assoc_data->have_beacon = true; | ||
2404 | ifmgd->assoc_data->sent_assoc = false; | ||
2405 | /* continue assoc process */ | ||
2406 | ifmgd->assoc_data->timeout = jiffies; | ||
2407 | run_again(ifmgd, ifmgd->assoc_data->timeout); | ||
2408 | return; | ||
2409 | } | ||
1847 | 2410 | ||
1848 | /* | 2411 | if (!ifmgd->associated || |
1849 | * And in theory even frames from a different AP we were just | 2412 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN)) |
1850 | * associated to a split-second ago! | ||
1851 | */ | ||
1852 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) | ||
1853 | return; | 2413 | return; |
2414 | bssid = ifmgd->associated->bssid; | ||
1854 | 2415 | ||
1855 | /* Track average RSSI from the Beacon frames of the current AP */ | 2416 | /* Track average RSSI from the Beacon frames of the current AP */ |
1856 | ifmgd->last_beacon_signal = rx_status->signal; | 2417 | ifmgd->last_beacon_signal = rx_status->signal; |
@@ -2034,6 +2595,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
2034 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2595 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2035 | struct ieee80211_rx_status *rx_status; | 2596 | struct ieee80211_rx_status *rx_status; |
2036 | struct ieee80211_mgmt *mgmt; | 2597 | struct ieee80211_mgmt *mgmt; |
2598 | struct cfg80211_bss *bss = NULL; | ||
2037 | enum rx_mgmt_action rma = RX_MGMT_NONE; | 2599 | enum rx_mgmt_action rma = RX_MGMT_NONE; |
2038 | u16 fc; | 2600 | u16 fc; |
2039 | 2601 | ||
@@ -2043,92 +2605,59 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
2043 | 2605 | ||
2044 | mutex_lock(&ifmgd->mtx); | 2606 | mutex_lock(&ifmgd->mtx); |
2045 | 2607 | ||
2046 | if (ifmgd->associated && | 2608 | switch (fc & IEEE80211_FCTL_STYPE) { |
2047 | memcmp(ifmgd->associated->bssid, mgmt->bssid, ETH_ALEN) == 0) { | 2609 | case IEEE80211_STYPE_BEACON: |
2048 | switch (fc & IEEE80211_FCTL_STYPE) { | 2610 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); |
2049 | case IEEE80211_STYPE_BEACON: | 2611 | break; |
2050 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, | 2612 | case IEEE80211_STYPE_PROBE_RESP: |
2051 | rx_status); | 2613 | ieee80211_rx_mgmt_probe_resp(sdata, skb); |
2052 | break; | 2614 | break; |
2053 | case IEEE80211_STYPE_PROBE_RESP: | 2615 | case IEEE80211_STYPE_AUTH: |
2054 | ieee80211_rx_mgmt_probe_resp(sdata, skb); | 2616 | rma = ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len); |
2055 | break; | 2617 | break; |
2056 | case IEEE80211_STYPE_DEAUTH: | 2618 | case IEEE80211_STYPE_DEAUTH: |
2057 | rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); | 2619 | rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); |
2058 | break; | 2620 | break; |
2059 | case IEEE80211_STYPE_DISASSOC: | 2621 | case IEEE80211_STYPE_DISASSOC: |
2060 | rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); | 2622 | rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); |
2061 | break; | 2623 | break; |
2062 | case IEEE80211_STYPE_ACTION: | 2624 | case IEEE80211_STYPE_ASSOC_RESP: |
2063 | switch (mgmt->u.action.category) { | 2625 | case IEEE80211_STYPE_REASSOC_RESP: |
2064 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 2626 | rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss); |
2065 | ieee80211_sta_process_chanswitch(sdata, | 2627 | break; |
2066 | &mgmt->u.action.u.chan_switch.sw_elem, | 2628 | case IEEE80211_STYPE_ACTION: |
2067 | (void *)ifmgd->associated->priv, | 2629 | switch (mgmt->u.action.category) { |
2068 | rx_status->mactime); | 2630 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
2069 | break; | 2631 | ieee80211_sta_process_chanswitch(sdata, |
2070 | } | 2632 | &mgmt->u.action.u.chan_switch.sw_elem, |
2071 | } | 2633 | (void *)ifmgd->associated->priv, |
2072 | mutex_unlock(&ifmgd->mtx); | 2634 | rx_status->mactime); |
2073 | |||
2074 | switch (rma) { | ||
2075 | case RX_MGMT_NONE: | ||
2076 | /* no action */ | ||
2077 | break; | ||
2078 | case RX_MGMT_CFG80211_DEAUTH: | ||
2079 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | ||
2080 | break; | ||
2081 | case RX_MGMT_CFG80211_DISASSOC: | ||
2082 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); | ||
2083 | break; | 2635 | break; |
2084 | default: | ||
2085 | WARN(1, "unexpected: %d", rma); | ||
2086 | } | 2636 | } |
2087 | return; | ||
2088 | } | 2637 | } |
2089 | |||
2090 | mutex_unlock(&ifmgd->mtx); | 2638 | mutex_unlock(&ifmgd->mtx); |
2091 | 2639 | ||
2092 | if (skb->len >= 24 + 2 /* mgmt + deauth reason */ && | 2640 | switch (rma) { |
2093 | (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) { | 2641 | case RX_MGMT_NONE: |
2094 | struct ieee80211_local *local = sdata->local; | 2642 | /* no action */ |
2095 | struct ieee80211_work *wk; | 2643 | break; |
2096 | 2644 | case RX_MGMT_CFG80211_DEAUTH: | |
2097 | mutex_lock(&local->mtx); | ||
2098 | list_for_each_entry(wk, &local->work_list, list) { | ||
2099 | if (wk->sdata != sdata) | ||
2100 | continue; | ||
2101 | |||
2102 | if (wk->type != IEEE80211_WORK_ASSOC && | ||
2103 | wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) | ||
2104 | continue; | ||
2105 | |||
2106 | if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN)) | ||
2107 | continue; | ||
2108 | if (memcmp(mgmt->sa, wk->filter_ta, ETH_ALEN)) | ||
2109 | continue; | ||
2110 | |||
2111 | /* | ||
2112 | * Printing the message only here means we can't | ||
2113 | * spuriously print it, but it also means that it | ||
2114 | * won't be printed when the frame comes in before | ||
2115 | * we even tried to associate or in similar cases. | ||
2116 | * | ||
2117 | * Ultimately, I suspect cfg80211 should print the | ||
2118 | * messages instead. | ||
2119 | */ | ||
2120 | printk(KERN_DEBUG | ||
2121 | "%s: deauthenticated from %pM (Reason: %u)\n", | ||
2122 | sdata->name, mgmt->bssid, | ||
2123 | le16_to_cpu(mgmt->u.deauth.reason_code)); | ||
2124 | |||
2125 | list_del_rcu(&wk->list); | ||
2126 | free_work(wk); | ||
2127 | break; | ||
2128 | } | ||
2129 | mutex_unlock(&local->mtx); | ||
2130 | |||
2131 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | 2645 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); |
2646 | break; | ||
2647 | case RX_MGMT_CFG80211_DISASSOC: | ||
2648 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); | ||
2649 | break; | ||
2650 | case RX_MGMT_CFG80211_RX_AUTH: | ||
2651 | cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, skb->len); | ||
2652 | break; | ||
2653 | case RX_MGMT_CFG80211_RX_ASSOC: | ||
2654 | cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len); | ||
2655 | break; | ||
2656 | case RX_MGMT_CFG80211_ASSOC_TIMEOUT: | ||
2657 | cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); | ||
2658 | break; | ||
2659 | default: | ||
2660 | WARN(1, "unexpected: %d", rma); | ||
2132 | } | 2661 | } |
2133 | } | 2662 | } |
2134 | 2663 | ||
@@ -2173,14 +2702,160 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2173 | mutex_lock(&ifmgd->mtx); | 2702 | mutex_lock(&ifmgd->mtx); |
2174 | } | 2703 | } |
2175 | 2704 | ||
2705 | static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | ||
2706 | { | ||
2707 | struct ieee80211_local *local = sdata->local; | ||
2708 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2709 | struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data; | ||
2710 | |||
2711 | lockdep_assert_held(&ifmgd->mtx); | ||
2712 | |||
2713 | if (WARN_ON_ONCE(!auth_data)) | ||
2714 | return -EINVAL; | ||
2715 | |||
2716 | if (!auth_data->synced) { | ||
2717 | int ret = drv_tx_sync(local, sdata, auth_data->bss->bssid, | ||
2718 | IEEE80211_TX_SYNC_AUTH); | ||
2719 | if (ret) | ||
2720 | return ret; | ||
2721 | } | ||
2722 | auth_data->synced = true; | ||
2723 | |||
2724 | auth_data->tries++; | ||
2725 | |||
2726 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { | ||
2727 | printk(KERN_DEBUG "%s: authentication with %pM timed out\n", | ||
2728 | sdata->name, auth_data->bss->bssid); | ||
2729 | |||
2730 | /* | ||
2731 | * Most likely AP is not in the range so remove the | ||
2732 | * bss struct for that AP. | ||
2733 | */ | ||
2734 | cfg80211_unlink_bss(local->hw.wiphy, auth_data->bss); | ||
2735 | |||
2736 | return -ETIMEDOUT; | ||
2737 | } | ||
2738 | |||
2739 | if (auth_data->bss->proberesp_ies) { | ||
2740 | printk(KERN_DEBUG "%s: send auth to %pM (try %d/%d)\n", | ||
2741 | sdata->name, auth_data->bss->bssid, auth_data->tries, | ||
2742 | IEEE80211_AUTH_MAX_TRIES); | ||
2743 | |||
2744 | auth_data->expected_transaction = 2; | ||
2745 | ieee80211_send_auth(sdata, 1, auth_data->algorithm, | ||
2746 | auth_data->ie, auth_data->ie_len, | ||
2747 | auth_data->bss->bssid, | ||
2748 | auth_data->bss->bssid, NULL, 0, 0); | ||
2749 | } else { | ||
2750 | const u8 *ssidie; | ||
2751 | |||
2752 | printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n", | ||
2753 | sdata->name, auth_data->bss->bssid, auth_data->tries, | ||
2754 | IEEE80211_AUTH_MAX_TRIES); | ||
2755 | |||
2756 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); | ||
2757 | if (!ssidie) | ||
2758 | return -EINVAL; | ||
2759 | /* | ||
2760 | * Direct probe is sent to broadcast address as some APs | ||
2761 | * will not answer to direct packet in unassociated state. | ||
2762 | */ | ||
2763 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], | ||
2764 | NULL, 0, (u32) -1, true, false); | ||
2765 | } | ||
2766 | |||
2767 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
2768 | run_again(ifmgd, auth_data->timeout); | ||
2769 | |||
2770 | return 0; | ||
2771 | } | ||
2772 | |||
2773 | static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | ||
2774 | { | ||
2775 | struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; | ||
2776 | struct ieee80211_local *local = sdata->local; | ||
2777 | |||
2778 | lockdep_assert_held(&sdata->u.mgd.mtx); | ||
2779 | |||
2780 | if (!assoc_data->synced) { | ||
2781 | int ret = drv_tx_sync(local, sdata, assoc_data->bss->bssid, | ||
2782 | IEEE80211_TX_SYNC_ASSOC); | ||
2783 | if (ret) | ||
2784 | return ret; | ||
2785 | } | ||
2786 | assoc_data->synced = true; | ||
2787 | |||
2788 | assoc_data->tries++; | ||
2789 | if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { | ||
2790 | printk(KERN_DEBUG "%s: association with %pM timed out\n", | ||
2791 | sdata->name, assoc_data->bss->bssid); | ||
2792 | |||
2793 | /* | ||
2794 | * Most likely AP is not in the range so remove the | ||
2795 | * bss struct for that AP. | ||
2796 | */ | ||
2797 | cfg80211_unlink_bss(local->hw.wiphy, assoc_data->bss); | ||
2798 | |||
2799 | return -ETIMEDOUT; | ||
2800 | } | ||
2801 | |||
2802 | printk(KERN_DEBUG "%s: associate with %pM (try %d/%d)\n", | ||
2803 | sdata->name, assoc_data->bss->bssid, assoc_data->tries, | ||
2804 | IEEE80211_ASSOC_MAX_TRIES); | ||
2805 | ieee80211_send_assoc(sdata); | ||
2806 | |||
2807 | assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | ||
2808 | run_again(&sdata->u.mgd, assoc_data->timeout); | ||
2809 | |||
2810 | return 0; | ||
2811 | } | ||
2812 | |||
2176 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | 2813 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) |
2177 | { | 2814 | { |
2178 | struct ieee80211_local *local = sdata->local; | 2815 | struct ieee80211_local *local = sdata->local; |
2179 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2816 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2180 | 2817 | ||
2181 | /* then process the rest of the work */ | ||
2182 | mutex_lock(&ifmgd->mtx); | 2818 | mutex_lock(&ifmgd->mtx); |
2183 | 2819 | ||
2820 | if (ifmgd->auth_data && | ||
2821 | time_after(jiffies, ifmgd->auth_data->timeout)) { | ||
2822 | if (ifmgd->auth_data->done) { | ||
2823 | /* | ||
2824 | * ok ... we waited for assoc but userspace didn't, | ||
2825 | * so let's just kill the auth data | ||
2826 | */ | ||
2827 | ieee80211_destroy_auth_data(sdata, false); | ||
2828 | } else if (ieee80211_probe_auth(sdata)) { | ||
2829 | u8 bssid[ETH_ALEN]; | ||
2830 | |||
2831 | memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN); | ||
2832 | |||
2833 | ieee80211_destroy_auth_data(sdata, false); | ||
2834 | |||
2835 | mutex_unlock(&ifmgd->mtx); | ||
2836 | cfg80211_send_auth_timeout(sdata->dev, bssid); | ||
2837 | mutex_lock(&ifmgd->mtx); | ||
2838 | } | ||
2839 | } else if (ifmgd->auth_data) | ||
2840 | run_again(ifmgd, ifmgd->auth_data->timeout); | ||
2841 | |||
2842 | if (ifmgd->assoc_data && | ||
2843 | time_after(jiffies, ifmgd->assoc_data->timeout)) { | ||
2844 | if (!ifmgd->assoc_data->have_beacon || | ||
2845 | ieee80211_do_assoc(sdata)) { | ||
2846 | u8 bssid[ETH_ALEN]; | ||
2847 | |||
2848 | memcpy(bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN); | ||
2849 | |||
2850 | ieee80211_destroy_assoc_data(sdata, false); | ||
2851 | |||
2852 | mutex_unlock(&ifmgd->mtx); | ||
2853 | cfg80211_send_assoc_timeout(sdata->dev, bssid); | ||
2854 | mutex_lock(&ifmgd->mtx); | ||
2855 | } | ||
2856 | } else if (ifmgd->assoc_data) | ||
2857 | run_again(ifmgd, ifmgd->assoc_data->timeout); | ||
2858 | |||
2184 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 2859 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
2185 | IEEE80211_STA_CONNECTION_POLL) && | 2860 | IEEE80211_STA_CONNECTION_POLL) && |
2186 | ifmgd->associated) { | 2861 | ifmgd->associated) { |
@@ -2256,6 +2931,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2256 | } | 2931 | } |
2257 | 2932 | ||
2258 | mutex_unlock(&ifmgd->mtx); | 2933 | mutex_unlock(&ifmgd->mtx); |
2934 | |||
2935 | mutex_lock(&local->mtx); | ||
2936 | ieee80211_recalc_idle(local); | ||
2937 | mutex_unlock(&local->mtx); | ||
2259 | } | 2938 | } |
2260 | 2939 | ||
2261 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) | 2940 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) |
@@ -2428,53 +3107,24 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
2428 | } | 3107 | } |
2429 | 3108 | ||
2430 | /* config hooks */ | 3109 | /* config hooks */ |
2431 | static enum work_done_result | ||
2432 | ieee80211_probe_auth_done(struct ieee80211_work *wk, | ||
2433 | struct sk_buff *skb) | ||
2434 | { | ||
2435 | struct ieee80211_local *local = wk->sdata->local; | ||
2436 | |||
2437 | if (!skb) { | ||
2438 | cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); | ||
2439 | goto destroy; | ||
2440 | } | ||
2441 | |||
2442 | if (wk->type == IEEE80211_WORK_AUTH) { | ||
2443 | cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); | ||
2444 | goto destroy; | ||
2445 | } | ||
2446 | |||
2447 | mutex_lock(&wk->sdata->u.mgd.mtx); | ||
2448 | ieee80211_rx_mgmt_probe_resp(wk->sdata, skb); | ||
2449 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
2450 | |||
2451 | wk->type = IEEE80211_WORK_AUTH; | ||
2452 | wk->probe_auth.tries = 0; | ||
2453 | return WORK_DONE_REQUEUE; | ||
2454 | destroy: | ||
2455 | if (wk->probe_auth.synced) | ||
2456 | drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, | ||
2457 | IEEE80211_TX_SYNC_AUTH); | ||
2458 | |||
2459 | return WORK_DONE_DESTROY; | ||
2460 | } | ||
2461 | |||
2462 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 3110 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
2463 | struct cfg80211_auth_request *req) | 3111 | struct cfg80211_auth_request *req) |
2464 | { | 3112 | { |
2465 | const u8 *ssid; | 3113 | struct ieee80211_local *local = sdata->local; |
2466 | struct ieee80211_work *wk; | 3114 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3115 | struct ieee80211_mgd_auth_data *auth_data; | ||
3116 | struct sta_info *sta; | ||
2467 | u16 auth_alg; | 3117 | u16 auth_alg; |
3118 | int err; | ||
2468 | 3119 | ||
2469 | if (req->local_state_change) | 3120 | /* prepare auth data structure */ |
2470 | return 0; /* no need to update mac80211 state */ | ||
2471 | 3121 | ||
2472 | switch (req->auth_type) { | 3122 | switch (req->auth_type) { |
2473 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | 3123 | case NL80211_AUTHTYPE_OPEN_SYSTEM: |
2474 | auth_alg = WLAN_AUTH_OPEN; | 3124 | auth_alg = WLAN_AUTH_OPEN; |
2475 | break; | 3125 | break; |
2476 | case NL80211_AUTHTYPE_SHARED_KEY: | 3126 | case NL80211_AUTHTYPE_SHARED_KEY: |
2477 | if (IS_ERR(sdata->local->wep_tx_tfm)) | 3127 | if (IS_ERR(local->wep_tx_tfm)) |
2478 | return -EOPNOTSUPP; | 3128 | return -EOPNOTSUPP; |
2479 | auth_alg = WLAN_AUTH_SHARED_KEY; | 3129 | auth_alg = WLAN_AUTH_SHARED_KEY; |
2480 | break; | 3130 | break; |
@@ -2488,171 +3138,142 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2488 | return -EOPNOTSUPP; | 3138 | return -EOPNOTSUPP; |
2489 | } | 3139 | } |
2490 | 3140 | ||
2491 | wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); | 3141 | auth_data = kzalloc(sizeof(*auth_data) + req->ie_len, GFP_KERNEL); |
2492 | if (!wk) | 3142 | if (!auth_data) |
2493 | return -ENOMEM; | 3143 | return -ENOMEM; |
2494 | 3144 | ||
2495 | memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); | 3145 | auth_data->bss = req->bss; |
2496 | 3146 | ||
2497 | if (req->ie && req->ie_len) { | 3147 | if (req->ie && req->ie_len) { |
2498 | memcpy(wk->ie, req->ie, req->ie_len); | 3148 | memcpy(auth_data->ie, req->ie, req->ie_len); |
2499 | wk->ie_len = req->ie_len; | 3149 | auth_data->ie_len = req->ie_len; |
2500 | } | 3150 | } |
2501 | 3151 | ||
2502 | if (req->key && req->key_len) { | 3152 | if (req->key && req->key_len) { |
2503 | wk->probe_auth.key_len = req->key_len; | 3153 | auth_data->key_len = req->key_len; |
2504 | wk->probe_auth.key_idx = req->key_idx; | 3154 | auth_data->key_idx = req->key_idx; |
2505 | memcpy(wk->probe_auth.key, req->key, req->key_len); | 3155 | memcpy(auth_data->key, req->key, req->key_len); |
2506 | } | 3156 | } |
2507 | 3157 | ||
2508 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | 3158 | auth_data->algorithm = auth_alg; |
2509 | memcpy(wk->probe_auth.ssid, ssid + 2, ssid[1]); | ||
2510 | wk->probe_auth.ssid_len = ssid[1]; | ||
2511 | |||
2512 | wk->probe_auth.algorithm = auth_alg; | ||
2513 | wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; | ||
2514 | |||
2515 | /* if we already have a probe, don't probe again */ | ||
2516 | if (req->bss->proberesp_ies) | ||
2517 | wk->type = IEEE80211_WORK_AUTH; | ||
2518 | else | ||
2519 | wk->type = IEEE80211_WORK_DIRECT_PROBE; | ||
2520 | wk->chan = req->bss->channel; | ||
2521 | wk->chan_type = NL80211_CHAN_NO_HT; | ||
2522 | wk->sdata = sdata; | ||
2523 | wk->done = ieee80211_probe_auth_done; | ||
2524 | |||
2525 | ieee80211_add_work(wk); | ||
2526 | return 0; | ||
2527 | } | ||
2528 | |||
2529 | /* create and insert a dummy station entry */ | ||
2530 | static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata, | ||
2531 | u8 *bssid) { | ||
2532 | struct sta_info *sta; | ||
2533 | int err; | ||
2534 | 3159 | ||
2535 | sta = sta_info_alloc(sdata, bssid, GFP_KERNEL); | 3160 | /* try to authenticate/probe */ |
2536 | if (!sta) | ||
2537 | return -ENOMEM; | ||
2538 | 3161 | ||
2539 | sta->dummy = true; | 3162 | mutex_lock(&ifmgd->mtx); |
2540 | 3163 | ||
2541 | err = sta_info_insert(sta); | 3164 | if ((ifmgd->auth_data && !ifmgd->auth_data->done) || |
2542 | sta = NULL; | 3165 | ifmgd->assoc_data) { |
2543 | if (err) { | 3166 | err = -EBUSY; |
2544 | printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for" | 3167 | goto err_free; |
2545 | " the AP (error %d)\n", sdata->name, err); | ||
2546 | return err; | ||
2547 | } | 3168 | } |
2548 | 3169 | ||
2549 | return 0; | 3170 | if (ifmgd->auth_data) |
2550 | } | 3171 | ieee80211_destroy_auth_data(sdata, false); |
2551 | 3172 | ||
2552 | static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, | 3173 | /* prep auth_data so we don't go into idle on disassoc */ |
2553 | struct sk_buff *skb) | 3174 | ifmgd->auth_data = auth_data; |
2554 | { | ||
2555 | struct ieee80211_local *local = wk->sdata->local; | ||
2556 | struct ieee80211_mgmt *mgmt; | ||
2557 | struct ieee80211_rx_status *rx_status; | ||
2558 | struct ieee802_11_elems elems; | ||
2559 | struct cfg80211_bss *cbss = wk->assoc.bss; | ||
2560 | u16 status; | ||
2561 | 3175 | ||
2562 | if (!skb) { | 3176 | if (ifmgd->associated) |
2563 | sta_info_destroy_addr(wk->sdata, cbss->bssid); | 3177 | ieee80211_set_disassoc(sdata, true, false); |
2564 | cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); | ||
2565 | goto destroy; | ||
2566 | } | ||
2567 | 3178 | ||
2568 | if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) { | 3179 | printk(KERN_DEBUG "%s: authenticate with %pM\n", |
2569 | mutex_lock(&wk->sdata->u.mgd.mtx); | 3180 | sdata->name, req->bss->bssid); |
2570 | rx_status = (void *) skb->cb; | ||
2571 | ieee802_11_parse_elems(skb->data + 24 + 12, skb->len - 24 - 12, &elems); | ||
2572 | ieee80211_rx_bss_info(wk->sdata, (void *)skb->data, skb->len, rx_status, | ||
2573 | &elems, true); | ||
2574 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
2575 | 3181 | ||
2576 | wk->type = IEEE80211_WORK_ASSOC; | 3182 | mutex_lock(&local->mtx); |
2577 | /* not really done yet */ | 3183 | ieee80211_recalc_idle(sdata->local); |
2578 | return WORK_DONE_REQUEUE; | 3184 | mutex_unlock(&local->mtx); |
2579 | } | ||
2580 | 3185 | ||
2581 | mgmt = (void *)skb->data; | 3186 | /* switch to the right channel */ |
2582 | status = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 3187 | local->oper_channel = req->bss->channel; |
3188 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
2583 | 3189 | ||
2584 | if (status == WLAN_STATUS_SUCCESS) { | 3190 | /* set BSSID */ |
2585 | if (wk->assoc.synced) | 3191 | memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN); |
2586 | drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, | 3192 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
2587 | IEEE80211_TX_SYNC_ASSOC); | ||
2588 | 3193 | ||
2589 | mutex_lock(&wk->sdata->u.mgd.mtx); | 3194 | /* add station entry */ |
2590 | if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { | 3195 | sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL); |
2591 | mutex_unlock(&wk->sdata->u.mgd.mtx); | 3196 | if (!sta) { |
2592 | /* oops -- internal error -- send timeout for now */ | 3197 | err = -ENOMEM; |
2593 | sta_info_destroy_addr(wk->sdata, cbss->bssid); | 3198 | goto err_clear; |
2594 | cfg80211_send_assoc_timeout(wk->sdata->dev, | 3199 | } |
2595 | wk->filter_ta); | ||
2596 | return WORK_DONE_DESTROY; | ||
2597 | } | ||
2598 | 3200 | ||
2599 | mutex_unlock(&wk->sdata->u.mgd.mtx); | 3201 | err = sta_info_insert(sta); |
2600 | } else { | 3202 | if (err) { |
2601 | /* assoc failed - destroy the dummy station entry */ | 3203 | printk(KERN_DEBUG |
2602 | sta_info_destroy_addr(wk->sdata, cbss->bssid); | 3204 | "%s: failed to insert STA entry for the AP %pM (error %d)\n", |
3205 | sdata->name, req->bss->bssid, err); | ||
3206 | goto err_clear; | ||
2603 | } | 3207 | } |
2604 | 3208 | ||
2605 | cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); | 3209 | err = ieee80211_probe_auth(sdata); |
2606 | destroy: | 3210 | if (err) { |
2607 | if (wk->assoc.synced) | 3211 | if (auth_data->synced) |
2608 | drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, | 3212 | drv_finish_tx_sync(local, sdata, req->bss->bssid, |
2609 | IEEE80211_TX_SYNC_ASSOC); | 3213 | IEEE80211_TX_SYNC_AUTH); |
3214 | sta_info_destroy_addr(sdata, req->bss->bssid); | ||
3215 | goto err_clear; | ||
3216 | } | ||
3217 | |||
3218 | /* hold our own reference */ | ||
3219 | cfg80211_ref_bss(auth_data->bss); | ||
3220 | err = 0; | ||
3221 | goto out_unlock; | ||
3222 | |||
3223 | err_clear: | ||
3224 | ifmgd->auth_data = NULL; | ||
3225 | err_free: | ||
3226 | kfree(auth_data); | ||
3227 | out_unlock: | ||
3228 | mutex_unlock(&ifmgd->mtx); | ||
2610 | 3229 | ||
2611 | return WORK_DONE_DESTROY; | 3230 | return err; |
2612 | } | 3231 | } |
2613 | 3232 | ||
2614 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | 3233 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, |
2615 | struct cfg80211_assoc_request *req) | 3234 | struct cfg80211_assoc_request *req) |
2616 | { | 3235 | { |
3236 | struct ieee80211_local *local = sdata->local; | ||
2617 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3237 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2618 | struct ieee80211_bss *bss = (void *)req->bss->priv; | 3238 | struct ieee80211_bss *bss = (void *)req->bss->priv; |
2619 | struct ieee80211_work *wk; | 3239 | struct ieee80211_mgd_assoc_data *assoc_data; |
2620 | const u8 *ssid; | 3240 | struct sta_info *sta; |
3241 | const u8 *ssidie; | ||
2621 | int i, err; | 3242 | int i, err; |
2622 | 3243 | ||
3244 | ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | ||
3245 | if (!ssidie) | ||
3246 | return -EINVAL; | ||
3247 | |||
3248 | assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); | ||
3249 | if (!assoc_data) | ||
3250 | return -ENOMEM; | ||
3251 | |||
2623 | mutex_lock(&ifmgd->mtx); | 3252 | mutex_lock(&ifmgd->mtx); |
2624 | if (ifmgd->associated) { | ||
2625 | if (!req->prev_bssid || | ||
2626 | memcmp(req->prev_bssid, ifmgd->associated->bssid, | ||
2627 | ETH_ALEN)) { | ||
2628 | /* | ||
2629 | * We are already associated and the request was not a | ||
2630 | * reassociation request from the current BSS, so | ||
2631 | * reject it. | ||
2632 | */ | ||
2633 | mutex_unlock(&ifmgd->mtx); | ||
2634 | return -EALREADY; | ||
2635 | } | ||
2636 | 3253 | ||
2637 | /* Trying to reassociate - clear previous association state */ | 3254 | if (ifmgd->associated) |
2638 | ieee80211_set_disassoc(sdata, true, false); | 3255 | ieee80211_set_disassoc(sdata, true, false); |
3256 | |||
3257 | if (ifmgd->auth_data && !ifmgd->auth_data->done) { | ||
3258 | err = -EBUSY; | ||
3259 | goto err_free; | ||
2639 | } | 3260 | } |
2640 | mutex_unlock(&ifmgd->mtx); | ||
2641 | 3261 | ||
2642 | wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); | 3262 | if (ifmgd->assoc_data) { |
2643 | if (!wk) | 3263 | err = -EBUSY; |
2644 | return -ENOMEM; | 3264 | goto err_free; |
3265 | } | ||
2645 | 3266 | ||
2646 | /* | 3267 | if (ifmgd->auth_data) { |
2647 | * create a dummy station info entry in order | 3268 | bool match; |
2648 | * to start accepting incoming EAPOL packets from the station | 3269 | |
2649 | */ | 3270 | /* keep sta info, bssid if matching */ |
2650 | err = ieee80211_pre_assoc(sdata, req->bss->bssid); | 3271 | match = memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN) == 0; |
2651 | if (err) { | 3272 | ieee80211_destroy_auth_data(sdata, match); |
2652 | kfree(wk); | ||
2653 | return err; | ||
2654 | } | 3273 | } |
2655 | 3274 | ||
3275 | /* prepare assoc data */ | ||
3276 | |||
2656 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; | 3277 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; |
2657 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 3278 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; |
2658 | 3279 | ||
@@ -2664,7 +3285,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2664 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) | 3285 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) |
2665 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3286 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
2666 | 3287 | ||
2667 | |||
2668 | if (req->flags & ASSOC_REQ_DISABLE_HT) | 3288 | if (req->flags & ASSOC_REQ_DISABLE_HT) |
2669 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3289 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
2670 | 3290 | ||
@@ -2673,16 +3293,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2673 | sizeof(ifmgd->ht_capa_mask)); | 3293 | sizeof(ifmgd->ht_capa_mask)); |
2674 | 3294 | ||
2675 | if (req->ie && req->ie_len) { | 3295 | if (req->ie && req->ie_len) { |
2676 | memcpy(wk->ie, req->ie, req->ie_len); | 3296 | memcpy(assoc_data->ie, req->ie, req->ie_len); |
2677 | wk->ie_len = req->ie_len; | 3297 | assoc_data->ie_len = req->ie_len; |
2678 | } else | 3298 | } |
2679 | wk->ie_len = 0; | ||
2680 | |||
2681 | wk->assoc.bss = req->bss; | ||
2682 | 3299 | ||
2683 | memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); | 3300 | assoc_data->bss = req->bss; |
2684 | 3301 | ||
2685 | /* new association always uses requested smps mode */ | ||
2686 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { | 3302 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { |
2687 | if (ifmgd->powersave) | 3303 | if (ifmgd->powersave) |
2688 | ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; | 3304 | ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; |
@@ -2691,7 +3307,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2691 | } else | 3307 | } else |
2692 | ifmgd->ap_smps = ifmgd->req_smps; | 3308 | ifmgd->ap_smps = ifmgd->req_smps; |
2693 | 3309 | ||
2694 | wk->assoc.smps = ifmgd->ap_smps; | ||
2695 | /* | 3310 | /* |
2696 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. | 3311 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. |
2697 | * We still associate in non-HT mode (11a/b/g) if any one of these | 3312 | * We still associate in non-HT mode (11a/b/g) if any one of these |
@@ -2699,39 +3314,27 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2699 | * We can set this to true for non-11n hardware, that'll be checked | 3314 | * We can set this to true for non-11n hardware, that'll be checked |
2700 | * separately along with the peer capabilities. | 3315 | * separately along with the peer capabilities. |
2701 | */ | 3316 | */ |
2702 | wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N); | 3317 | assoc_data->capability = req->bss->capability; |
2703 | wk->assoc.capability = req->bss->capability; | 3318 | assoc_data->wmm_used = bss->wmm_used; |
2704 | wk->assoc.wmm_used = bss->wmm_used; | 3319 | assoc_data->supp_rates = bss->supp_rates; |
2705 | wk->assoc.supp_rates = bss->supp_rates; | 3320 | assoc_data->supp_rates_len = bss->supp_rates_len; |
2706 | wk->assoc.supp_rates_len = bss->supp_rates_len; | 3321 | assoc_data->ht_information_ie = |
2707 | wk->assoc.ht_information_ie = | ||
2708 | ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); | 3322 | ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); |
2709 | 3323 | ||
2710 | if (bss->wmm_used && bss->uapsd_supported && | 3324 | if (bss->wmm_used && bss->uapsd_supported && |
2711 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 3325 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
2712 | wk->assoc.uapsd_used = true; | 3326 | assoc_data->uapsd_used = true; |
2713 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; | 3327 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; |
2714 | } else { | 3328 | } else { |
2715 | wk->assoc.uapsd_used = false; | 3329 | assoc_data->uapsd_used = false; |
2716 | ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; | 3330 | ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; |
2717 | } | 3331 | } |
2718 | 3332 | ||
2719 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | 3333 | memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]); |
2720 | memcpy(wk->assoc.ssid, ssid + 2, ssid[1]); | 3334 | assoc_data->ssid_len = ssidie[1]; |
2721 | wk->assoc.ssid_len = ssid[1]; | ||
2722 | 3335 | ||
2723 | if (req->prev_bssid) | 3336 | if (req->prev_bssid) |
2724 | memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); | 3337 | memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN); |
2725 | |||
2726 | wk->chan = req->bss->channel; | ||
2727 | wk->chan_type = NL80211_CHAN_NO_HT; | ||
2728 | wk->sdata = sdata; | ||
2729 | wk->done = ieee80211_assoc_done; | ||
2730 | if (!bss->dtim_period && | ||
2731 | sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) | ||
2732 | wk->type = IEEE80211_WORK_ASSOC_BEACON_WAIT; | ||
2733 | else | ||
2734 | wk->type = IEEE80211_WORK_ASSOC; | ||
2735 | 3338 | ||
2736 | if (req->use_mfp) { | 3339 | if (req->use_mfp) { |
2737 | ifmgd->mfp = IEEE80211_MFP_REQUIRED; | 3340 | ifmgd->mfp = IEEE80211_MFP_REQUIRED; |
@@ -2749,89 +3352,100 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2749 | sdata->control_port_protocol = req->crypto.control_port_ethertype; | 3352 | sdata->control_port_protocol = req->crypto.control_port_ethertype; |
2750 | sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; | 3353 | sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; |
2751 | 3354 | ||
2752 | ieee80211_add_work(wk); | 3355 | /* kick off associate process */ |
2753 | return 0; | 3356 | |
3357 | ifmgd->assoc_data = assoc_data; | ||
3358 | |||
3359 | mutex_lock(&local->mtx); | ||
3360 | ieee80211_recalc_idle(sdata->local); | ||
3361 | mutex_unlock(&local->mtx); | ||
3362 | |||
3363 | /* switch to the right channel */ | ||
3364 | local->oper_channel = req->bss->channel; | ||
3365 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
3366 | |||
3367 | rcu_read_lock(); | ||
3368 | sta = sta_info_get(sdata, req->bss->bssid); | ||
3369 | rcu_read_unlock(); | ||
3370 | |||
3371 | if (!sta) { | ||
3372 | /* set BSSID */ | ||
3373 | memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN); | ||
3374 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | ||
3375 | |||
3376 | sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL); | ||
3377 | if (!sta) { | ||
3378 | err = -ENOMEM; | ||
3379 | goto err_clear; | ||
3380 | } | ||
3381 | |||
3382 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | ||
3383 | |||
3384 | err = sta_info_insert(sta); | ||
3385 | sta = NULL; | ||
3386 | if (err) { | ||
3387 | printk(KERN_DEBUG | ||
3388 | "%s: failed to insert STA entry for the AP (error %d)\n", | ||
3389 | sdata->name, err); | ||
3390 | goto err_clear; | ||
3391 | } | ||
3392 | } else | ||
3393 | WARN_ON_ONCE(memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN)); | ||
3394 | |||
3395 | if (!bss->dtim_period && | ||
3396 | sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { | ||
3397 | /* | ||
3398 | * Wait up to one beacon interval ... | ||
3399 | * should this be more if we miss one? | ||
3400 | */ | ||
3401 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", | ||
3402 | sdata->name, ifmgd->bssid); | ||
3403 | assoc_data->timeout = jiffies + | ||
3404 | TU_TO_EXP_TIME(req->bss->beacon_interval); | ||
3405 | } else { | ||
3406 | assoc_data->have_beacon = true; | ||
3407 | assoc_data->sent_assoc = false; | ||
3408 | assoc_data->timeout = jiffies; | ||
3409 | } | ||
3410 | run_again(ifmgd, assoc_data->timeout); | ||
3411 | |||
3412 | err = 0; | ||
3413 | goto out; | ||
3414 | err_clear: | ||
3415 | ifmgd->assoc_data = NULL; | ||
3416 | err_free: | ||
3417 | kfree(assoc_data); | ||
3418 | out: | ||
3419 | mutex_unlock(&ifmgd->mtx); | ||
3420 | |||
3421 | return err; | ||
2754 | } | 3422 | } |
2755 | 3423 | ||
2756 | int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | 3424 | int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, |
2757 | struct cfg80211_deauth_request *req, | 3425 | struct cfg80211_deauth_request *req, |
2758 | void *cookie) | 3426 | void *cookie) |
2759 | { | 3427 | { |
2760 | struct ieee80211_local *local = sdata->local; | ||
2761 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3428 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2762 | u8 bssid[ETH_ALEN]; | ||
2763 | bool assoc_bss = false; | 3429 | bool assoc_bss = false; |
2764 | 3430 | ||
2765 | mutex_lock(&ifmgd->mtx); | 3431 | mutex_lock(&ifmgd->mtx); |
2766 | 3432 | ||
2767 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | 3433 | if (ifmgd->associated && |
2768 | if (ifmgd->associated == req->bss) { | 3434 | memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0) { |
2769 | ieee80211_set_disassoc(sdata, false, true); | 3435 | ieee80211_set_disassoc(sdata, false, true); |
2770 | mutex_unlock(&ifmgd->mtx); | ||
2771 | assoc_bss = true; | 3436 | assoc_bss = true; |
2772 | } else { | 3437 | } else if (ifmgd->auth_data) { |
2773 | bool not_auth_yet = false; | 3438 | ieee80211_destroy_auth_data(sdata, false); |
2774 | struct ieee80211_work *tmp, *wk = NULL; | ||
2775 | |||
2776 | mutex_unlock(&ifmgd->mtx); | 3439 | mutex_unlock(&ifmgd->mtx); |
2777 | 3440 | return 0; | |
2778 | mutex_lock(&local->mtx); | ||
2779 | list_for_each_entry(tmp, &local->work_list, list) { | ||
2780 | if (tmp->sdata != sdata) | ||
2781 | continue; | ||
2782 | |||
2783 | if (tmp->type != IEEE80211_WORK_DIRECT_PROBE && | ||
2784 | tmp->type != IEEE80211_WORK_AUTH && | ||
2785 | tmp->type != IEEE80211_WORK_ASSOC && | ||
2786 | tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) | ||
2787 | continue; | ||
2788 | |||
2789 | if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN)) | ||
2790 | continue; | ||
2791 | |||
2792 | not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE; | ||
2793 | list_del_rcu(&tmp->list); | ||
2794 | synchronize_rcu(); | ||
2795 | wk = tmp; | ||
2796 | break; | ||
2797 | } | ||
2798 | mutex_unlock(&local->mtx); | ||
2799 | |||
2800 | if (wk && wk->type == IEEE80211_WORK_ASSOC) { | ||
2801 | /* clean up dummy sta & TX sync */ | ||
2802 | sta_info_destroy_addr(wk->sdata, wk->filter_ta); | ||
2803 | if (wk->assoc.synced) | ||
2804 | drv_finish_tx_sync(local, wk->sdata, | ||
2805 | wk->filter_ta, | ||
2806 | IEEE80211_TX_SYNC_ASSOC); | ||
2807 | } else if (wk && wk->type == IEEE80211_WORK_AUTH) { | ||
2808 | if (wk->probe_auth.synced) | ||
2809 | drv_finish_tx_sync(local, wk->sdata, | ||
2810 | wk->filter_ta, | ||
2811 | IEEE80211_TX_SYNC_AUTH); | ||
2812 | } | ||
2813 | kfree(wk); | ||
2814 | |||
2815 | /* | ||
2816 | * If somebody requests authentication and we haven't | ||
2817 | * sent out an auth frame yet there's no need to send | ||
2818 | * out a deauth frame either. If the state was PROBE, | ||
2819 | * then this is the case. If it's AUTH we have sent a | ||
2820 | * frame, and if it's IDLE we have completed the auth | ||
2821 | * process already. | ||
2822 | */ | ||
2823 | if (not_auth_yet) { | ||
2824 | __cfg80211_auth_canceled(sdata->dev, bssid); | ||
2825 | return 0; | ||
2826 | } | ||
2827 | } | 3441 | } |
3442 | mutex_unlock(&ifmgd->mtx); | ||
2828 | 3443 | ||
2829 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 3444 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", |
2830 | sdata->name, bssid, req->reason_code); | 3445 | sdata->name, req->bssid, req->reason_code); |
2831 | 3446 | ||
2832 | ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH, | 3447 | ieee80211_send_deauth_disassoc(sdata, req->bssid, IEEE80211_STYPE_DEAUTH, |
2833 | req->reason_code, cookie, | 3448 | req->reason_code, cookie, true); |
2834 | !req->local_state_change); | ||
2835 | if (assoc_bss) | 3449 | if (assoc_bss) |
2836 | sta_info_flush(sdata->local, sdata); | 3450 | sta_info_flush(sdata->local, sdata); |
2837 | 3451 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 596efaf50e09..2b53a5348ace 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -98,13 +98,12 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
98 | mutex_lock(&local->sta_mtx); | 98 | mutex_lock(&local->sta_mtx); |
99 | list_for_each_entry(sta, &local->sta_list, list) { | 99 | list_for_each_entry(sta, &local->sta_list, list) { |
100 | if (sta->uploaded) { | 100 | if (sta->uploaded) { |
101 | sdata = sta->sdata; | 101 | enum ieee80211_sta_state state; |
102 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
103 | sdata = container_of(sdata->bss, | ||
104 | struct ieee80211_sub_if_data, | ||
105 | u.ap); | ||
106 | 102 | ||
107 | drv_sta_remove(local, sdata, &sta->sta); | 103 | state = sta->sta_state; |
104 | for (; state > IEEE80211_STA_NOTEXIST; state--) | ||
105 | WARN_ON(drv_sta_state(local, sdata, sta, | ||
106 | state, state - 1)); | ||
108 | } | 107 | } |
109 | 108 | ||
110 | mesh_plink_quiesce(sta); | 109 | mesh_plink_quiesce(sta); |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 3fef26d8898a..111fba38be82 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -324,7 +324,7 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate, | |||
324 | rbit = rate->idx % 8; | 324 | rbit = rate->idx % 8; |
325 | 325 | ||
326 | /* sanity check */ | 326 | /* sanity check */ |
327 | if (ridx < 0 || ridx > IEEE80211_HT_MCS_MASK_LEN) | 327 | if (ridx < 0 || ridx >= IEEE80211_HT_MCS_MASK_LEN) |
328 | return false; | 328 | return false; |
329 | 329 | ||
330 | /* See whether the selected rate or anything below it is allowed. */ | 330 | /* See whether the selected rate or anything below it is allowed. */ |
@@ -439,7 +439,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
439 | u32 mask; | 439 | u32 mask; |
440 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; | 440 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; |
441 | 441 | ||
442 | if (sta) { | 442 | if (sta && test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) { |
443 | ista = &sta->sta; | 443 | ista = &sta->sta; |
444 | priv_sta = sta->rate_ctrl_priv; | 444 | priv_sta = sta->rate_ctrl_priv; |
445 | } | 445 | } |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 8268457bd143..fbb1efdc4d04 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -37,7 +37,7 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, | |||
37 | struct ieee80211_sta *ista = &sta->sta; | 37 | struct ieee80211_sta *ista = &sta->sta; |
38 | void *priv_sta = sta->rate_ctrl_priv; | 38 | void *priv_sta = sta->rate_ctrl_priv; |
39 | 39 | ||
40 | if (!ref) | 40 | if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) |
41 | return; | 41 | return; |
42 | 42 | ||
43 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); | 43 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); |
@@ -58,6 +58,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
58 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 58 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
59 | 59 | ||
60 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | 60 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); |
61 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); | ||
61 | } | 62 | } |
62 | 63 | ||
63 | static inline void rate_control_rate_update(struct ieee80211_local *local, | 64 | static inline void rate_control_rate_update(struct ieee80211_local *local, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b5ee0847a7e1..3ab85c02ef04 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -859,7 +859,12 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
859 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | 859 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
860 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && | 860 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && |
861 | (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) { | 861 | (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) { |
862 | if (rx->sta && rx->sta->dummy && | 862 | /* |
863 | * accept port control frames from the AP even when it's not | ||
864 | * yet marked ASSOC to prevent a race where we don't set the | ||
865 | * assoc bit quickly enough before it sends the first frame | ||
866 | */ | ||
867 | if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && | ||
863 | ieee80211_is_data_present(hdr->frame_control)) { | 868 | ieee80211_is_data_present(hdr->frame_control)) { |
864 | u16 ethertype; | 869 | u16 ethertype; |
865 | u8 *payload; | 870 | u8 *payload; |
@@ -2479,14 +2484,9 @@ static ieee80211_rx_result debug_noinline | |||
2479 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 2484 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
2480 | { | 2485 | { |
2481 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 2486 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
2482 | ieee80211_rx_result rxs; | ||
2483 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; | 2487 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; |
2484 | __le16 stype; | 2488 | __le16 stype; |
2485 | 2489 | ||
2486 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); | ||
2487 | if (rxs != RX_CONTINUE) | ||
2488 | return rxs; | ||
2489 | |||
2490 | stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); | 2490 | stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); |
2491 | 2491 | ||
2492 | if (!ieee80211_vif_is_mesh(&sdata->vif) && | 2492 | if (!ieee80211_vif_is_mesh(&sdata->vif) && |
@@ -2495,10 +2495,13 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2495 | return RX_DROP_MONITOR; | 2495 | return RX_DROP_MONITOR; |
2496 | 2496 | ||
2497 | switch (stype) { | 2497 | switch (stype) { |
2498 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
2498 | case cpu_to_le16(IEEE80211_STYPE_BEACON): | 2499 | case cpu_to_le16(IEEE80211_STYPE_BEACON): |
2499 | case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): | 2500 | case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): |
2500 | /* process for all: mesh, mlme, ibss */ | 2501 | /* process for all: mesh, mlme, ibss */ |
2501 | break; | 2502 | break; |
2503 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): | ||
2504 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): | ||
2502 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | 2505 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): |
2503 | case cpu_to_le16(IEEE80211_STYPE_DISASSOC): | 2506 | case cpu_to_le16(IEEE80211_STYPE_DISASSOC): |
2504 | if (is_multicast_ether_addr(mgmt->da) && | 2507 | if (is_multicast_ether_addr(mgmt->da) && |
@@ -2510,7 +2513,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2510 | return RX_DROP_MONITOR; | 2513 | return RX_DROP_MONITOR; |
2511 | break; | 2514 | break; |
2512 | case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): | 2515 | case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): |
2513 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
2514 | /* process only for ibss */ | 2516 | /* process only for ibss */ |
2515 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 2517 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
2516 | return RX_DROP_MONITOR; | 2518 | return RX_DROP_MONITOR; |
@@ -2949,7 +2951,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2949 | if (ieee80211_is_data(fc)) { | 2951 | if (ieee80211_is_data(fc)) { |
2950 | prev_sta = NULL; | 2952 | prev_sta = NULL; |
2951 | 2953 | ||
2952 | for_each_sta_info_rx(local, hdr->addr2, sta, tmp) { | 2954 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2953 | if (!prev_sta) { | 2955 | if (!prev_sta) { |
2954 | prev_sta = sta; | 2956 | prev_sta = sta; |
2955 | continue; | 2957 | continue; |
@@ -2993,7 +2995,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2993 | continue; | 2995 | continue; |
2994 | } | 2996 | } |
2995 | 2997 | ||
2996 | rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); | 2998 | rx.sta = sta_info_get_bss(prev, hdr->addr2); |
2997 | rx.sdata = prev; | 2999 | rx.sdata = prev; |
2998 | ieee80211_prepare_and_rx_handle(&rx, skb, false); | 3000 | ieee80211_prepare_and_rx_handle(&rx, skb, false); |
2999 | 3001 | ||
@@ -3001,7 +3003,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
3001 | } | 3003 | } |
3002 | 3004 | ||
3003 | if (prev) { | 3005 | if (prev) { |
3004 | rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); | 3006 | rx.sta = sta_info_get_bss(prev, hdr->addr2); |
3005 | rx.sdata = prev; | 3007 | rx.sdata = prev; |
3006 | 3008 | ||
3007 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) | 3009 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index fa0823892b2d..4034ee616022 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -100,25 +100,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | 100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
101 | lockdep_is_held(&local->sta_mtx)); | 101 | lockdep_is_held(&local->sta_mtx)); |
102 | while (sta) { | 102 | while (sta) { |
103 | if (sta->sdata == sdata && !sta->dummy && | ||
104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
105 | break; | ||
106 | sta = rcu_dereference_check(sta->hnext, | ||
107 | lockdep_is_held(&local->sta_mtx)); | ||
108 | } | ||
109 | return sta; | ||
110 | } | ||
111 | |||
112 | /* get a station info entry even if it is a dummy station*/ | ||
113 | struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | ||
114 | const u8 *addr) | ||
115 | { | ||
116 | struct ieee80211_local *local = sdata->local; | ||
117 | struct sta_info *sta; | ||
118 | |||
119 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | ||
120 | lockdep_is_held(&local->sta_mtx)); | ||
121 | while (sta) { | ||
122 | if (sta->sdata == sdata && | 103 | if (sta->sdata == sdata && |
123 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
124 | break; | 105 | break; |
@@ -143,30 +124,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
143 | while (sta) { | 124 | while (sta) { |
144 | if ((sta->sdata == sdata || | 125 | if ((sta->sdata == sdata || |
145 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && | 126 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && |
146 | !sta->dummy && | ||
147 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
148 | break; | ||
149 | sta = rcu_dereference_check(sta->hnext, | ||
150 | lockdep_is_held(&local->sta_mtx)); | ||
151 | } | ||
152 | return sta; | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Get sta info either from the specified interface | ||
157 | * or from one of its vlans (including dummy stations) | ||
158 | */ | ||
159 | struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | ||
160 | const u8 *addr) | ||
161 | { | ||
162 | struct ieee80211_local *local = sdata->local; | ||
163 | struct sta_info *sta; | ||
164 | |||
165 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], | ||
166 | lockdep_is_held(&local->sta_mtx)); | ||
167 | while (sta) { | ||
168 | if ((sta->sdata == sdata || | ||
169 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && | ||
170 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 127 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
171 | break; | 128 | break; |
172 | sta = rcu_dereference_check(sta->hnext, | 129 | sta = rcu_dereference_check(sta->hnext, |
@@ -293,6 +250,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
293 | sta->sdata = sdata; | 250 | sta->sdata = sdata; |
294 | sta->last_rx = jiffies; | 251 | sta->last_rx = jiffies; |
295 | 252 | ||
253 | sta->sta_state = IEEE80211_STA_NONE; | ||
254 | |||
296 | do_posix_clock_monotonic_gettime(&uptime); | 255 | do_posix_clock_monotonic_gettime(&uptime); |
297 | sta->last_connected = uptime.tv_sec; | 256 | sta->last_connected = uptime.tv_sec; |
298 | ewma_init(&sta->avg_signal, 1024, 8); | 257 | ewma_init(&sta->avg_signal, 1024, 8); |
@@ -349,6 +308,43 @@ static int sta_info_insert_check(struct sta_info *sta) | |||
349 | return 0; | 308 | return 0; |
350 | } | 309 | } |
351 | 310 | ||
311 | static int sta_info_insert_drv_state(struct ieee80211_local *local, | ||
312 | struct ieee80211_sub_if_data *sdata, | ||
313 | struct sta_info *sta) | ||
314 | { | ||
315 | enum ieee80211_sta_state state; | ||
316 | int err = 0; | ||
317 | |||
318 | for (state = IEEE80211_STA_NOTEXIST; state < sta->sta_state; state++) { | ||
319 | err = drv_sta_state(local, sdata, sta, state, state + 1); | ||
320 | if (err) | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | if (!err) { | ||
325 | /* | ||
326 | * Drivers using legacy sta_add/sta_remove callbacks only | ||
327 | * get uploaded set to true after sta_add is called. | ||
328 | */ | ||
329 | if (!local->ops->sta_add) | ||
330 | sta->uploaded = true; | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
335 | printk(KERN_DEBUG | ||
336 | "%s: failed to move IBSS STA %pM to state %d (%d) - keeping it anyway.\n", | ||
337 | sdata->name, sta->sta.addr, state + 1, err); | ||
338 | err = 0; | ||
339 | } | ||
340 | |||
341 | /* unwind on error */ | ||
342 | for (; state > IEEE80211_STA_NOTEXIST; state--) | ||
343 | WARN_ON(drv_sta_state(local, sdata, sta, state, state - 1)); | ||
344 | |||
345 | return err; | ||
346 | } | ||
347 | |||
352 | /* | 348 | /* |
353 | * should be called with sta_mtx locked | 349 | * should be called with sta_mtx locked |
354 | * this function replaces the mutex lock | 350 | * this function replaces the mutex lock |
@@ -358,72 +354,43 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) | |||
358 | { | 354 | { |
359 | struct ieee80211_local *local = sta->local; | 355 | struct ieee80211_local *local = sta->local; |
360 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 356 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
361 | struct sta_info *exist_sta; | 357 | struct station_info sinfo; |
362 | bool dummy_reinsert = false; | ||
363 | int err = 0; | 358 | int err = 0; |
364 | 359 | ||
365 | lockdep_assert_held(&local->sta_mtx); | 360 | lockdep_assert_held(&local->sta_mtx); |
366 | 361 | ||
367 | /* | 362 | /* check if STA exists already */ |
368 | * check if STA exists already. | 363 | if (sta_info_get_bss(sdata, sta->sta.addr)) { |
369 | * only accept a scenario of a second call to sta_info_insert_finish | 364 | err = -EEXIST; |
370 | * with a dummy station entry that was inserted earlier | 365 | goto out_err; |
371 | * in that case - assume that the dummy station flag should | ||
372 | * be removed. | ||
373 | */ | ||
374 | exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr); | ||
375 | if (exist_sta) { | ||
376 | if (exist_sta == sta && sta->dummy) { | ||
377 | dummy_reinsert = true; | ||
378 | } else { | ||
379 | err = -EEXIST; | ||
380 | goto out_err; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | if (!sta->dummy || dummy_reinsert) { | ||
385 | /* notify driver */ | ||
386 | err = drv_sta_add(local, sdata, &sta->sta); | ||
387 | if (err) { | ||
388 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
389 | goto out_err; | ||
390 | printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " | ||
391 | "driver (%d) - keeping it anyway.\n", | ||
392 | sdata->name, sta->sta.addr, err); | ||
393 | } else | ||
394 | sta->uploaded = true; | ||
395 | } | 366 | } |
396 | 367 | ||
397 | if (!dummy_reinsert) { | 368 | /* notify driver */ |
398 | local->num_sta++; | 369 | err = sta_info_insert_drv_state(local, sdata, sta); |
399 | local->sta_generation++; | 370 | if (err) |
400 | smp_mb(); | 371 | goto out_err; |
401 | 372 | ||
402 | /* make the station visible */ | 373 | local->num_sta++; |
403 | sta_info_hash_add(local, sta); | 374 | local->sta_generation++; |
375 | smp_mb(); | ||
404 | 376 | ||
405 | list_add(&sta->list, &local->sta_list); | 377 | /* make the station visible */ |
378 | sta_info_hash_add(local, sta); | ||
406 | 379 | ||
407 | set_sta_flag(sta, WLAN_STA_INSERTED); | 380 | list_add(&sta->list, &local->sta_list); |
408 | } else { | ||
409 | sta->dummy = false; | ||
410 | } | ||
411 | 381 | ||
412 | if (!sta->dummy) { | 382 | set_sta_flag(sta, WLAN_STA_INSERTED); |
413 | struct station_info sinfo; | ||
414 | 383 | ||
415 | ieee80211_sta_debugfs_add(sta); | 384 | ieee80211_sta_debugfs_add(sta); |
416 | rate_control_add_sta_debugfs(sta); | 385 | rate_control_add_sta_debugfs(sta); |
417 | 386 | ||
418 | memset(&sinfo, 0, sizeof(sinfo)); | 387 | memset(&sinfo, 0, sizeof(sinfo)); |
419 | sinfo.filled = 0; | 388 | sinfo.filled = 0; |
420 | sinfo.generation = local->sta_generation; | 389 | sinfo.generation = local->sta_generation; |
421 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | 390 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); |
422 | } | ||
423 | 391 | ||
424 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 392 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
425 | wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", | 393 | wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); |
426 | sta->dummy ? "dummy " : "", sta->sta.addr); | ||
427 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 394 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
428 | 395 | ||
429 | /* move reference to rcu-protected */ | 396 | /* move reference to rcu-protected */ |
@@ -475,25 +442,6 @@ int sta_info_insert(struct sta_info *sta) | |||
475 | return err; | 442 | return err; |
476 | } | 443 | } |
477 | 444 | ||
478 | /* Caller must hold sta->local->sta_mtx */ | ||
479 | int sta_info_reinsert(struct sta_info *sta) | ||
480 | { | ||
481 | struct ieee80211_local *local = sta->local; | ||
482 | int err = 0; | ||
483 | |||
484 | err = sta_info_insert_check(sta); | ||
485 | if (err) { | ||
486 | mutex_unlock(&local->sta_mtx); | ||
487 | return err; | ||
488 | } | ||
489 | |||
490 | might_sleep(); | ||
491 | |||
492 | err = sta_info_insert_finish(sta); | ||
493 | rcu_read_unlock(); | ||
494 | return err; | ||
495 | } | ||
496 | |||
497 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) | 445 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) |
498 | { | 446 | { |
499 | /* | 447 | /* |
@@ -757,20 +705,17 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
757 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); | 705 | RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); |
758 | 706 | ||
759 | while (sta->sta_state > IEEE80211_STA_NONE) { | 707 | while (sta->sta_state > IEEE80211_STA_NONE) { |
760 | int err = sta_info_move_state(sta, sta->sta_state - 1); | 708 | ret = sta_info_move_state(sta, sta->sta_state - 1); |
761 | if (err) { | 709 | if (ret) { |
762 | WARN_ON_ONCE(1); | 710 | WARN_ON_ONCE(1); |
763 | break; | 711 | break; |
764 | } | 712 | } |
765 | } | 713 | } |
766 | 714 | ||
767 | if (sta->uploaded) { | 715 | if (sta->uploaded) { |
768 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 716 | ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE, |
769 | sdata = container_of(sdata->bss, | 717 | IEEE80211_STA_NOTEXIST); |
770 | struct ieee80211_sub_if_data, | 718 | WARN_ON_ONCE(ret != 0); |
771 | u.ap); | ||
772 | drv_sta_remove(local, sdata, &sta->sta); | ||
773 | sdata = sta->sdata; | ||
774 | } | 719 | } |
775 | 720 | ||
776 | /* | 721 | /* |
@@ -843,7 +788,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) | |||
843 | int ret; | 788 | int ret; |
844 | 789 | ||
845 | mutex_lock(&sdata->local->sta_mtx); | 790 | mutex_lock(&sdata->local->sta_mtx); |
846 | sta = sta_info_get_rx(sdata, addr); | 791 | sta = sta_info_get(sdata, addr); |
847 | ret = __sta_info_destroy(sta); | 792 | ret = __sta_info_destroy(sta); |
848 | mutex_unlock(&sdata->local->sta_mtx); | 793 | mutex_unlock(&sdata->local->sta_mtx); |
849 | 794 | ||
@@ -857,7 +802,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, | |||
857 | int ret; | 802 | int ret; |
858 | 803 | ||
859 | mutex_lock(&sdata->local->sta_mtx); | 804 | mutex_lock(&sdata->local->sta_mtx); |
860 | sta = sta_info_get_bss_rx(sdata, addr); | 805 | sta = sta_info_get_bss(sdata, addr); |
861 | ret = __sta_info_destroy(sta); | 806 | ret = __sta_info_destroy(sta); |
862 | mutex_unlock(&sdata->local->sta_mtx); | 807 | mutex_unlock(&sdata->local->sta_mtx); |
863 | 808 | ||
@@ -1408,20 +1353,60 @@ int sta_info_move_state(struct sta_info *sta, | |||
1408 | if (sta->sta_state == new_state) | 1353 | if (sta->sta_state == new_state) |
1409 | return 0; | 1354 | return 0; |
1410 | 1355 | ||
1356 | /* check allowed transitions first */ | ||
1357 | |||
1358 | switch (new_state) { | ||
1359 | case IEEE80211_STA_NONE: | ||
1360 | if (sta->sta_state != IEEE80211_STA_AUTH) | ||
1361 | return -EINVAL; | ||
1362 | break; | ||
1363 | case IEEE80211_STA_AUTH: | ||
1364 | if (sta->sta_state != IEEE80211_STA_NONE && | ||
1365 | sta->sta_state != IEEE80211_STA_ASSOC) | ||
1366 | return -EINVAL; | ||
1367 | break; | ||
1368 | case IEEE80211_STA_ASSOC: | ||
1369 | if (sta->sta_state != IEEE80211_STA_AUTH && | ||
1370 | sta->sta_state != IEEE80211_STA_AUTHORIZED) | ||
1371 | return -EINVAL; | ||
1372 | break; | ||
1373 | case IEEE80211_STA_AUTHORIZED: | ||
1374 | if (sta->sta_state != IEEE80211_STA_ASSOC) | ||
1375 | return -EINVAL; | ||
1376 | break; | ||
1377 | default: | ||
1378 | WARN(1, "invalid state %d", new_state); | ||
1379 | return -EINVAL; | ||
1380 | } | ||
1381 | |||
1382 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1383 | printk(KERN_DEBUG "%s: moving STA %pM to state %d\n", | ||
1384 | sta->sdata->name, sta->sta.addr, new_state); | ||
1385 | #endif | ||
1386 | |||
1387 | /* | ||
1388 | * notify the driver before the actual changes so it can | ||
1389 | * fail the transition | ||
1390 | */ | ||
1391 | if (test_sta_flag(sta, WLAN_STA_INSERTED)) { | ||
1392 | int err = drv_sta_state(sta->local, sta->sdata, sta, | ||
1393 | sta->sta_state, new_state); | ||
1394 | if (err) | ||
1395 | return err; | ||
1396 | } | ||
1397 | |||
1398 | /* reflect the change in all state variables */ | ||
1399 | |||
1411 | switch (new_state) { | 1400 | switch (new_state) { |
1412 | case IEEE80211_STA_NONE: | 1401 | case IEEE80211_STA_NONE: |
1413 | if (sta->sta_state == IEEE80211_STA_AUTH) | 1402 | if (sta->sta_state == IEEE80211_STA_AUTH) |
1414 | clear_bit(WLAN_STA_AUTH, &sta->_flags); | 1403 | clear_bit(WLAN_STA_AUTH, &sta->_flags); |
1415 | else | ||
1416 | return -EINVAL; | ||
1417 | break; | 1404 | break; |
1418 | case IEEE80211_STA_AUTH: | 1405 | case IEEE80211_STA_AUTH: |
1419 | if (sta->sta_state == IEEE80211_STA_NONE) | 1406 | if (sta->sta_state == IEEE80211_STA_NONE) |
1420 | set_bit(WLAN_STA_AUTH, &sta->_flags); | 1407 | set_bit(WLAN_STA_AUTH, &sta->_flags); |
1421 | else if (sta->sta_state == IEEE80211_STA_ASSOC) | 1408 | else if (sta->sta_state == IEEE80211_STA_ASSOC) |
1422 | clear_bit(WLAN_STA_ASSOC, &sta->_flags); | 1409 | clear_bit(WLAN_STA_ASSOC, &sta->_flags); |
1423 | else | ||
1424 | return -EINVAL; | ||
1425 | break; | 1410 | break; |
1426 | case IEEE80211_STA_ASSOC: | 1411 | case IEEE80211_STA_ASSOC: |
1427 | if (sta->sta_state == IEEE80211_STA_AUTH) { | 1412 | if (sta->sta_state == IEEE80211_STA_AUTH) { |
@@ -1430,24 +1415,19 @@ int sta_info_move_state(struct sta_info *sta, | |||
1430 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | 1415 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) |
1431 | atomic_dec(&sta->sdata->u.ap.num_sta_authorized); | 1416 | atomic_dec(&sta->sdata->u.ap.num_sta_authorized); |
1432 | clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | 1417 | clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); |
1433 | } else | 1418 | } |
1434 | return -EINVAL; | ||
1435 | break; | 1419 | break; |
1436 | case IEEE80211_STA_AUTHORIZED: | 1420 | case IEEE80211_STA_AUTHORIZED: |
1437 | if (sta->sta_state == IEEE80211_STA_ASSOC) { | 1421 | if (sta->sta_state == IEEE80211_STA_ASSOC) { |
1438 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) | 1422 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP) |
1439 | atomic_inc(&sta->sdata->u.ap.num_sta_authorized); | 1423 | atomic_inc(&sta->sdata->u.ap.num_sta_authorized); |
1440 | set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); | 1424 | set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); |
1441 | } else | 1425 | } |
1442 | return -EINVAL; | ||
1443 | break; | 1426 | break; |
1444 | default: | 1427 | default: |
1445 | WARN(1, "invalid state %d", new_state); | 1428 | break; |
1446 | return -EINVAL; | ||
1447 | } | 1429 | } |
1448 | 1430 | ||
1449 | printk(KERN_DEBUG "%s: moving STA %pM to state %d\n", | ||
1450 | sta->sdata->name, sta->sta.addr, new_state); | ||
1451 | sta->sta_state = new_state; | 1431 | sta->sta_state = new_state; |
1452 | 1432 | ||
1453 | return 0; | 1433 | return 0; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 381de37d2478..23a97c9dc042 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -53,6 +53,7 @@ | |||
53 | * reply to other uAPSD trigger frames or PS-Poll. | 53 | * reply to other uAPSD trigger frames or PS-Poll. |
54 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. | 54 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. |
55 | * @WLAN_STA_INSERTED: This station is inserted into the hash table. | 55 | * @WLAN_STA_INSERTED: This station is inserted into the hash table. |
56 | * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. | ||
56 | */ | 57 | */ |
57 | enum ieee80211_sta_info_flags { | 58 | enum ieee80211_sta_info_flags { |
58 | WLAN_STA_AUTH, | 59 | WLAN_STA_AUTH, |
@@ -73,14 +74,7 @@ enum ieee80211_sta_info_flags { | |||
73 | WLAN_STA_SP, | 74 | WLAN_STA_SP, |
74 | WLAN_STA_4ADDR_EVENT, | 75 | WLAN_STA_4ADDR_EVENT, |
75 | WLAN_STA_INSERTED, | 76 | WLAN_STA_INSERTED, |
76 | }; | 77 | WLAN_STA_RATE_CONTROL, |
77 | |||
78 | enum ieee80211_sta_state { | ||
79 | /* NOTE: These need to be ordered correctly! */ | ||
80 | IEEE80211_STA_NONE, | ||
81 | IEEE80211_STA_AUTH, | ||
82 | IEEE80211_STA_ASSOC, | ||
83 | IEEE80211_STA_AUTHORIZED, | ||
84 | }; | 78 | }; |
85 | 79 | ||
86 | #define STA_TID_NUM 16 | 80 | #define STA_TID_NUM 16 |
@@ -273,8 +267,6 @@ struct sta_ampdu_mlme { | |||
273 | * @dead: set to true when sta is unlinked | 267 | * @dead: set to true when sta is unlinked |
274 | * @uploaded: set to true when sta is uploaded to the driver | 268 | * @uploaded: set to true when sta is uploaded to the driver |
275 | * @lost_packets: number of consecutive lost packets | 269 | * @lost_packets: number of consecutive lost packets |
276 | * @dummy: indicate a dummy station created for receiving | ||
277 | * EAP frames before association | ||
278 | * @sta: station information we share with the driver | 270 | * @sta: station information we share with the driver |
279 | * @sta_state: duplicates information about station state (for debug) | 271 | * @sta_state: duplicates information about station state (for debug) |
280 | * @beacon_loss_count: number of times beacon loss has triggered | 272 | * @beacon_loss_count: number of times beacon loss has triggered |
@@ -372,9 +364,6 @@ struct sta_info { | |||
372 | unsigned int lost_packets; | 364 | unsigned int lost_packets; |
373 | unsigned int beacon_loss_count; | 365 | unsigned int beacon_loss_count; |
374 | 366 | ||
375 | /* should be right in front of sta to be in the same cache line */ | ||
376 | bool dummy; | ||
377 | |||
378 | /* keep last! */ | 367 | /* keep last! */ |
379 | struct ieee80211_sta sta; | 368 | struct ieee80211_sta sta; |
380 | }; | 369 | }; |
@@ -476,15 +465,9 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) | |||
476 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | 465 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
477 | const u8 *addr); | 466 | const u8 *addr); |
478 | 467 | ||
479 | struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | ||
480 | const u8 *addr); | ||
481 | |||
482 | struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | 468 | struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, |
483 | const u8 *addr); | 469 | const u8 *addr); |
484 | 470 | ||
485 | struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | ||
486 | const u8 *addr); | ||
487 | |||
488 | static inline | 471 | static inline |
489 | void for_each_sta_info_type_check(struct ieee80211_local *local, | 472 | void for_each_sta_info_type_check(struct ieee80211_local *local, |
490 | const u8 *addr, | 473 | const u8 *addr, |
@@ -493,23 +476,7 @@ void for_each_sta_info_type_check(struct ieee80211_local *local, | |||
493 | { | 476 | { |
494 | } | 477 | } |
495 | 478 | ||
496 | #define for_each_sta_info(local, _addr, _sta, nxt) \ | 479 | #define for_each_sta_info(local, _addr, _sta, nxt) \ |
497 | for ( /* initialise loop */ \ | ||
498 | _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ | ||
499 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ | ||
500 | /* typecheck */ \ | ||
501 | for_each_sta_info_type_check(local, (_addr), _sta, nxt),\ | ||
502 | /* continue condition */ \ | ||
503 | _sta; \ | ||
504 | /* advance loop */ \ | ||
505 | _sta = nxt, \ | ||
506 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ | ||
507 | ) \ | ||
508 | /* run code only if address matches and it's not a dummy sta */ \ | ||
509 | if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \ | ||
510 | !_sta->dummy) | ||
511 | |||
512 | #define for_each_sta_info_rx(local, _addr, _sta, nxt) \ | ||
513 | for ( /* initialise loop */ \ | 480 | for ( /* initialise loop */ \ |
514 | _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ | 481 | _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ |
515 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ | 482 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ |
@@ -548,7 +515,6 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta); | |||
548 | */ | 515 | */ |
549 | int sta_info_insert(struct sta_info *sta); | 516 | int sta_info_insert(struct sta_info *sta); |
550 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); | 517 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
551 | int sta_info_reinsert(struct sta_info *sta); | ||
552 | 518 | ||
553 | int __must_check __sta_info_destroy(struct sta_info *sta); | 519 | int __must_check __sta_info_destroy(struct sta_info *sta); |
554 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, | 520 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d82d886d0867..264397aee811 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1185,13 +1185,12 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1185 | mutex_lock(&local->sta_mtx); | 1185 | mutex_lock(&local->sta_mtx); |
1186 | list_for_each_entry(sta, &local->sta_list, list) { | 1186 | list_for_each_entry(sta, &local->sta_list, list) { |
1187 | if (sta->uploaded) { | 1187 | if (sta->uploaded) { |
1188 | sdata = sta->sdata; | 1188 | enum ieee80211_sta_state state; |
1189 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1190 | sdata = container_of(sdata->bss, | ||
1191 | struct ieee80211_sub_if_data, | ||
1192 | u.ap); | ||
1193 | 1189 | ||
1194 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); | 1190 | for (state = IEEE80211_STA_NOTEXIST; |
1191 | state < sta->sta_state - 1; state++) | ||
1192 | WARN_ON(drv_sta_state(local, sta->sdata, sta, | ||
1193 | state, state + 1)); | ||
1195 | } | 1194 | } |
1196 | } | 1195 | } |
1197 | mutex_unlock(&local->sta_mtx); | 1196 | mutex_unlock(&local->sta_mtx); |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 0a1a176fbe91..c6e230efa049 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -27,16 +27,9 @@ | |||
27 | #include "rate.h" | 27 | #include "rate.h" |
28 | #include "driver-ops.h" | 28 | #include "driver-ops.h" |
29 | 29 | ||
30 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | ||
31 | #define IEEE80211_AUTH_MAX_TRIES 3 | ||
32 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | ||
33 | #define IEEE80211_ASSOC_MAX_TRIES 3 | ||
34 | |||
35 | enum work_action { | 30 | enum work_action { |
36 | WORK_ACT_MISMATCH, | ||
37 | WORK_ACT_NONE, | 31 | WORK_ACT_NONE, |
38 | WORK_ACT_TIMEOUT, | 32 | WORK_ACT_TIMEOUT, |
39 | WORK_ACT_DONE, | ||
40 | }; | 33 | }; |
41 | 34 | ||
42 | 35 | ||
@@ -71,465 +64,6 @@ void free_work(struct ieee80211_work *wk) | |||
71 | kfree_rcu(wk, rcu_head); | 64 | kfree_rcu(wk, rcu_head); |
72 | } | 65 | } |
73 | 66 | ||
74 | static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | ||
75 | struct ieee80211_supported_band *sband, | ||
76 | u32 *rates) | ||
77 | { | ||
78 | int i, j, count; | ||
79 | *rates = 0; | ||
80 | count = 0; | ||
81 | for (i = 0; i < supp_rates_len; i++) { | ||
82 | int rate = (supp_rates[i] & 0x7F) * 5; | ||
83 | |||
84 | for (j = 0; j < sband->n_bitrates; j++) | ||
85 | if (sband->bitrates[j].bitrate == rate) { | ||
86 | *rates |= BIT(j); | ||
87 | count++; | ||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | return count; | ||
93 | } | ||
94 | |||
95 | /* frame sending functions */ | ||
96 | |||
97 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | ||
98 | struct sk_buff *skb, const u8 *ht_info_ie, | ||
99 | struct ieee80211_supported_band *sband, | ||
100 | struct ieee80211_channel *channel, | ||
101 | enum ieee80211_smps_mode smps) | ||
102 | { | ||
103 | struct ieee80211_ht_info *ht_info; | ||
104 | u8 *pos; | ||
105 | u32 flags = channel->flags; | ||
106 | u16 cap; | ||
107 | struct ieee80211_sta_ht_cap ht_cap; | ||
108 | |||
109 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); | ||
110 | |||
111 | if (!sband->ht_cap.ht_supported) | ||
112 | return; | ||
113 | |||
114 | if (!ht_info_ie) | ||
115 | return; | ||
116 | |||
117 | if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) | ||
118 | return; | ||
119 | |||
120 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | ||
121 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | ||
122 | |||
123 | ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); | ||
124 | |||
125 | /* determine capability flags */ | ||
126 | cap = ht_cap.cap; | ||
127 | |||
128 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
129 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
130 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | ||
131 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
132 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
133 | } | ||
134 | break; | ||
135 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
136 | if (flags & IEEE80211_CHAN_NO_HT40MINUS) { | ||
137 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
138 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
139 | } | ||
140 | break; | ||
141 | } | ||
142 | |||
143 | /* set SM PS mode properly */ | ||
144 | cap &= ~IEEE80211_HT_CAP_SM_PS; | ||
145 | switch (smps) { | ||
146 | case IEEE80211_SMPS_AUTOMATIC: | ||
147 | case IEEE80211_SMPS_NUM_MODES: | ||
148 | WARN_ON(1); | ||
149 | case IEEE80211_SMPS_OFF: | ||
150 | cap |= WLAN_HT_CAP_SM_PS_DISABLED << | ||
151 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
152 | break; | ||
153 | case IEEE80211_SMPS_STATIC: | ||
154 | cap |= WLAN_HT_CAP_SM_PS_STATIC << | ||
155 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
156 | break; | ||
157 | case IEEE80211_SMPS_DYNAMIC: | ||
158 | cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
159 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
160 | break; | ||
161 | } | ||
162 | |||
163 | /* reserve and fill IE */ | ||
164 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
165 | ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); | ||
166 | } | ||
167 | |||
168 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | ||
169 | struct ieee80211_work *wk) | ||
170 | { | ||
171 | struct ieee80211_local *local = sdata->local; | ||
172 | struct sk_buff *skb; | ||
173 | struct ieee80211_mgmt *mgmt; | ||
174 | u8 *pos, qos_info; | ||
175 | size_t offset = 0, noffset; | ||
176 | int i, count, rates_len, supp_rates_len; | ||
177 | u16 capab; | ||
178 | struct ieee80211_supported_band *sband; | ||
179 | u32 rates = 0; | ||
180 | |||
181 | sband = local->hw.wiphy->bands[wk->chan->band]; | ||
182 | |||
183 | if (wk->assoc.supp_rates_len) { | ||
184 | /* | ||
185 | * Get all rates supported by the device and the AP as | ||
186 | * some APs don't like getting a superset of their rates | ||
187 | * in the association request (e.g. D-Link DAP 1353 in | ||
188 | * b-only mode)... | ||
189 | */ | ||
190 | rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, | ||
191 | wk->assoc.supp_rates_len, | ||
192 | sband, &rates); | ||
193 | } else { | ||
194 | /* | ||
195 | * In case AP not provide any supported rates information | ||
196 | * before association, we send information element(s) with | ||
197 | * all rates that we support. | ||
198 | */ | ||
199 | rates = ~0; | ||
200 | rates_len = sband->n_bitrates; | ||
201 | } | ||
202 | |||
203 | skb = alloc_skb(local->hw.extra_tx_headroom + | ||
204 | sizeof(*mgmt) + /* bit too much but doesn't matter */ | ||
205 | 2 + wk->assoc.ssid_len + /* SSID */ | ||
206 | 4 + rates_len + /* (extended) rates */ | ||
207 | 4 + /* power capability */ | ||
208 | 2 + 2 * sband->n_channels + /* supported channels */ | ||
209 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ | ||
210 | wk->ie_len + /* extra IEs */ | ||
211 | 9, /* WMM */ | ||
212 | GFP_KERNEL); | ||
213 | if (!skb) | ||
214 | return; | ||
215 | |||
216 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
217 | |||
218 | capab = WLAN_CAPABILITY_ESS; | ||
219 | |||
220 | if (sband->band == IEEE80211_BAND_2GHZ) { | ||
221 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | ||
222 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; | ||
223 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) | ||
224 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
225 | } | ||
226 | |||
227 | if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY) | ||
228 | capab |= WLAN_CAPABILITY_PRIVACY; | ||
229 | |||
230 | if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && | ||
231 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) | ||
232 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; | ||
233 | |||
234 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
235 | memset(mgmt, 0, 24); | ||
236 | memcpy(mgmt->da, wk->filter_ta, ETH_ALEN); | ||
237 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
238 | memcpy(mgmt->bssid, wk->filter_ta, ETH_ALEN); | ||
239 | |||
240 | if (!is_zero_ether_addr(wk->assoc.prev_bssid)) { | ||
241 | skb_put(skb, 10); | ||
242 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
243 | IEEE80211_STYPE_REASSOC_REQ); | ||
244 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); | ||
245 | mgmt->u.reassoc_req.listen_interval = | ||
246 | cpu_to_le16(local->hw.conf.listen_interval); | ||
247 | memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid, | ||
248 | ETH_ALEN); | ||
249 | } else { | ||
250 | skb_put(skb, 4); | ||
251 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
252 | IEEE80211_STYPE_ASSOC_REQ); | ||
253 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | ||
254 | mgmt->u.assoc_req.listen_interval = | ||
255 | cpu_to_le16(local->hw.conf.listen_interval); | ||
256 | } | ||
257 | |||
258 | /* SSID */ | ||
259 | pos = skb_put(skb, 2 + wk->assoc.ssid_len); | ||
260 | *pos++ = WLAN_EID_SSID; | ||
261 | *pos++ = wk->assoc.ssid_len; | ||
262 | memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); | ||
263 | |||
264 | /* add all rates which were marked to be used above */ | ||
265 | supp_rates_len = rates_len; | ||
266 | if (supp_rates_len > 8) | ||
267 | supp_rates_len = 8; | ||
268 | |||
269 | pos = skb_put(skb, supp_rates_len + 2); | ||
270 | *pos++ = WLAN_EID_SUPP_RATES; | ||
271 | *pos++ = supp_rates_len; | ||
272 | |||
273 | count = 0; | ||
274 | for (i = 0; i < sband->n_bitrates; i++) { | ||
275 | if (BIT(i) & rates) { | ||
276 | int rate = sband->bitrates[i].bitrate; | ||
277 | *pos++ = (u8) (rate / 5); | ||
278 | if (++count == 8) | ||
279 | break; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | if (rates_len > count) { | ||
284 | pos = skb_put(skb, rates_len - count + 2); | ||
285 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
286 | *pos++ = rates_len - count; | ||
287 | |||
288 | for (i++; i < sband->n_bitrates; i++) { | ||
289 | if (BIT(i) & rates) { | ||
290 | int rate = sband->bitrates[i].bitrate; | ||
291 | *pos++ = (u8) (rate / 5); | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { | ||
297 | /* 1. power capabilities */ | ||
298 | pos = skb_put(skb, 4); | ||
299 | *pos++ = WLAN_EID_PWR_CAPABILITY; | ||
300 | *pos++ = 2; | ||
301 | *pos++ = 0; /* min tx power */ | ||
302 | *pos++ = wk->chan->max_power; /* max tx power */ | ||
303 | |||
304 | /* 2. supported channels */ | ||
305 | /* TODO: get this in reg domain format */ | ||
306 | pos = skb_put(skb, 2 * sband->n_channels + 2); | ||
307 | *pos++ = WLAN_EID_SUPPORTED_CHANNELS; | ||
308 | *pos++ = 2 * sband->n_channels; | ||
309 | for (i = 0; i < sband->n_channels; i++) { | ||
310 | *pos++ = ieee80211_frequency_to_channel( | ||
311 | sband->channels[i].center_freq); | ||
312 | *pos++ = 1; /* one channel in the subband*/ | ||
313 | } | ||
314 | } | ||
315 | |||
316 | /* if present, add any custom IEs that go before HT */ | ||
317 | if (wk->ie_len && wk->ie) { | ||
318 | static const u8 before_ht[] = { | ||
319 | WLAN_EID_SSID, | ||
320 | WLAN_EID_SUPP_RATES, | ||
321 | WLAN_EID_EXT_SUPP_RATES, | ||
322 | WLAN_EID_PWR_CAPABILITY, | ||
323 | WLAN_EID_SUPPORTED_CHANNELS, | ||
324 | WLAN_EID_RSN, | ||
325 | WLAN_EID_QOS_CAPA, | ||
326 | WLAN_EID_RRM_ENABLED_CAPABILITIES, | ||
327 | WLAN_EID_MOBILITY_DOMAIN, | ||
328 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
329 | }; | ||
330 | noffset = ieee80211_ie_split(wk->ie, wk->ie_len, | ||
331 | before_ht, ARRAY_SIZE(before_ht), | ||
332 | offset); | ||
333 | pos = skb_put(skb, noffset - offset); | ||
334 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
335 | offset = noffset; | ||
336 | } | ||
337 | |||
338 | if (wk->assoc.use_11n && wk->assoc.wmm_used && | ||
339 | local->hw.queues >= 4) | ||
340 | ieee80211_add_ht_ie(sdata, skb, wk->assoc.ht_information_ie, | ||
341 | sband, wk->chan, wk->assoc.smps); | ||
342 | |||
343 | /* if present, add any custom non-vendor IEs that go after HT */ | ||
344 | if (wk->ie_len && wk->ie) { | ||
345 | noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len, | ||
346 | offset); | ||
347 | pos = skb_put(skb, noffset - offset); | ||
348 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
349 | offset = noffset; | ||
350 | } | ||
351 | |||
352 | if (wk->assoc.wmm_used && local->hw.queues >= 4) { | ||
353 | if (wk->assoc.uapsd_used) { | ||
354 | qos_info = local->uapsd_queues; | ||
355 | qos_info |= (local->uapsd_max_sp_len << | ||
356 | IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT); | ||
357 | } else { | ||
358 | qos_info = 0; | ||
359 | } | ||
360 | |||
361 | pos = skb_put(skb, 9); | ||
362 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
363 | *pos++ = 7; /* len */ | ||
364 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
365 | *pos++ = 0x50; | ||
366 | *pos++ = 0xf2; | ||
367 | *pos++ = 2; /* WME */ | ||
368 | *pos++ = 0; /* WME info */ | ||
369 | *pos++ = 1; /* WME ver */ | ||
370 | *pos++ = qos_info; | ||
371 | } | ||
372 | |||
373 | /* add any remaining custom (i.e. vendor specific here) IEs */ | ||
374 | if (wk->ie_len && wk->ie) { | ||
375 | noffset = wk->ie_len; | ||
376 | pos = skb_put(skb, noffset - offset); | ||
377 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
378 | } | ||
379 | |||
380 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
381 | ieee80211_tx_skb(sdata, skb); | ||
382 | } | ||
383 | |||
384 | static void ieee80211_remove_auth_bss(struct ieee80211_local *local, | ||
385 | struct ieee80211_work *wk) | ||
386 | { | ||
387 | struct cfg80211_bss *cbss; | ||
388 | u16 capa_val = WLAN_CAPABILITY_ESS; | ||
389 | |||
390 | if (wk->probe_auth.privacy) | ||
391 | capa_val |= WLAN_CAPABILITY_PRIVACY; | ||
392 | |||
393 | cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->filter_ta, | ||
394 | wk->probe_auth.ssid, wk->probe_auth.ssid_len, | ||
395 | WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, | ||
396 | capa_val); | ||
397 | if (!cbss) | ||
398 | return; | ||
399 | |||
400 | cfg80211_unlink_bss(local->hw.wiphy, cbss); | ||
401 | cfg80211_put_bss(cbss); | ||
402 | } | ||
403 | |||
404 | static enum work_action __must_check | ||
405 | ieee80211_direct_probe(struct ieee80211_work *wk) | ||
406 | { | ||
407 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
408 | struct ieee80211_local *local = sdata->local; | ||
409 | |||
410 | if (!wk->probe_auth.synced) { | ||
411 | int ret = drv_tx_sync(local, sdata, wk->filter_ta, | ||
412 | IEEE80211_TX_SYNC_AUTH); | ||
413 | if (ret) | ||
414 | return WORK_ACT_TIMEOUT; | ||
415 | } | ||
416 | wk->probe_auth.synced = true; | ||
417 | |||
418 | wk->probe_auth.tries++; | ||
419 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { | ||
420 | printk(KERN_DEBUG "%s: direct probe to %pM timed out\n", | ||
421 | sdata->name, wk->filter_ta); | ||
422 | |||
423 | /* | ||
424 | * Most likely AP is not in the range so remove the | ||
425 | * bss struct for that AP. | ||
426 | */ | ||
427 | ieee80211_remove_auth_bss(local, wk); | ||
428 | |||
429 | return WORK_ACT_TIMEOUT; | ||
430 | } | ||
431 | |||
432 | printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n", | ||
433 | sdata->name, wk->filter_ta, wk->probe_auth.tries, | ||
434 | IEEE80211_AUTH_MAX_TRIES); | ||
435 | |||
436 | /* | ||
437 | * Direct probe is sent to broadcast address as some APs | ||
438 | * will not answer to direct packet in unassociated state. | ||
439 | */ | ||
440 | ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, | ||
441 | wk->probe_auth.ssid_len, NULL, 0, | ||
442 | (u32) -1, true, false); | ||
443 | |||
444 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
445 | run_again(local, wk->timeout); | ||
446 | |||
447 | return WORK_ACT_NONE; | ||
448 | } | ||
449 | |||
450 | |||
451 | static enum work_action __must_check | ||
452 | ieee80211_authenticate(struct ieee80211_work *wk) | ||
453 | { | ||
454 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
455 | struct ieee80211_local *local = sdata->local; | ||
456 | |||
457 | if (!wk->probe_auth.synced) { | ||
458 | int ret = drv_tx_sync(local, sdata, wk->filter_ta, | ||
459 | IEEE80211_TX_SYNC_AUTH); | ||
460 | if (ret) | ||
461 | return WORK_ACT_TIMEOUT; | ||
462 | } | ||
463 | wk->probe_auth.synced = true; | ||
464 | |||
465 | wk->probe_auth.tries++; | ||
466 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { | ||
467 | printk(KERN_DEBUG "%s: authentication with %pM" | ||
468 | " timed out\n", sdata->name, wk->filter_ta); | ||
469 | |||
470 | /* | ||
471 | * Most likely AP is not in the range so remove the | ||
472 | * bss struct for that AP. | ||
473 | */ | ||
474 | ieee80211_remove_auth_bss(local, wk); | ||
475 | |||
476 | return WORK_ACT_TIMEOUT; | ||
477 | } | ||
478 | |||
479 | printk(KERN_DEBUG "%s: authenticate with %pM (try %d)\n", | ||
480 | sdata->name, wk->filter_ta, wk->probe_auth.tries); | ||
481 | |||
482 | ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie, | ||
483 | wk->ie_len, wk->filter_ta, wk->filter_ta, NULL, 0, | ||
484 | 0); | ||
485 | wk->probe_auth.transaction = 2; | ||
486 | |||
487 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
488 | run_again(local, wk->timeout); | ||
489 | |||
490 | return WORK_ACT_NONE; | ||
491 | } | ||
492 | |||
493 | static enum work_action __must_check | ||
494 | ieee80211_associate(struct ieee80211_work *wk) | ||
495 | { | ||
496 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
497 | struct ieee80211_local *local = sdata->local; | ||
498 | |||
499 | if (!wk->assoc.synced) { | ||
500 | int ret = drv_tx_sync(local, sdata, wk->filter_ta, | ||
501 | IEEE80211_TX_SYNC_ASSOC); | ||
502 | if (ret) | ||
503 | return WORK_ACT_TIMEOUT; | ||
504 | } | ||
505 | wk->assoc.synced = true; | ||
506 | |||
507 | wk->assoc.tries++; | ||
508 | if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { | ||
509 | printk(KERN_DEBUG "%s: association with %pM" | ||
510 | " timed out\n", | ||
511 | sdata->name, wk->filter_ta); | ||
512 | |||
513 | /* | ||
514 | * Most likely AP is not in the range so remove the | ||
515 | * bss struct for that AP. | ||
516 | */ | ||
517 | if (wk->assoc.bss) | ||
518 | cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss); | ||
519 | |||
520 | return WORK_ACT_TIMEOUT; | ||
521 | } | ||
522 | |||
523 | printk(KERN_DEBUG "%s: associate with %pM (try %d)\n", | ||
524 | sdata->name, wk->filter_ta, wk->assoc.tries); | ||
525 | ieee80211_send_assoc(sdata, wk); | ||
526 | |||
527 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | ||
528 | run_again(local, wk->timeout); | ||
529 | |||
530 | return WORK_ACT_NONE; | ||
531 | } | ||
532 | |||
533 | static enum work_action __must_check | 67 | static enum work_action __must_check |
534 | ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) | 68 | ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) |
535 | { | 69 | { |
@@ -569,300 +103,6 @@ ieee80211_offchannel_tx(struct ieee80211_work *wk) | |||
569 | return WORK_ACT_TIMEOUT; | 103 | return WORK_ACT_TIMEOUT; |
570 | } | 104 | } |
571 | 105 | ||
572 | static enum work_action __must_check | ||
573 | ieee80211_assoc_beacon_wait(struct ieee80211_work *wk) | ||
574 | { | ||
575 | if (wk->started) | ||
576 | return WORK_ACT_TIMEOUT; | ||
577 | |||
578 | /* | ||
579 | * Wait up to one beacon interval ... | ||
580 | * should this be more if we miss one? | ||
581 | */ | ||
582 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", | ||
583 | wk->sdata->name, wk->filter_ta); | ||
584 | wk->timeout = TU_TO_EXP_TIME(wk->assoc.bss->beacon_interval); | ||
585 | return WORK_ACT_NONE; | ||
586 | } | ||
587 | |||
588 | static void ieee80211_auth_challenge(struct ieee80211_work *wk, | ||
589 | struct ieee80211_mgmt *mgmt, | ||
590 | size_t len) | ||
591 | { | ||
592 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
593 | u8 *pos; | ||
594 | struct ieee802_11_elems elems; | ||
595 | |||
596 | pos = mgmt->u.auth.variable; | ||
597 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
598 | if (!elems.challenge) | ||
599 | return; | ||
600 | ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm, | ||
601 | elems.challenge - 2, elems.challenge_len + 2, | ||
602 | wk->filter_ta, wk->filter_ta, wk->probe_auth.key, | ||
603 | wk->probe_auth.key_len, wk->probe_auth.key_idx); | ||
604 | wk->probe_auth.transaction = 4; | ||
605 | } | ||
606 | |||
607 | static enum work_action __must_check | ||
608 | ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, | ||
609 | struct ieee80211_mgmt *mgmt, size_t len) | ||
610 | { | ||
611 | u16 auth_alg, auth_transaction, status_code; | ||
612 | |||
613 | if (wk->type != IEEE80211_WORK_AUTH) | ||
614 | return WORK_ACT_MISMATCH; | ||
615 | |||
616 | if (len < 24 + 6) | ||
617 | return WORK_ACT_NONE; | ||
618 | |||
619 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | ||
620 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | ||
621 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | ||
622 | |||
623 | if (auth_alg != wk->probe_auth.algorithm || | ||
624 | auth_transaction != wk->probe_auth.transaction) | ||
625 | return WORK_ACT_NONE; | ||
626 | |||
627 | if (status_code != WLAN_STATUS_SUCCESS) { | ||
628 | printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", | ||
629 | wk->sdata->name, mgmt->sa, status_code); | ||
630 | return WORK_ACT_DONE; | ||
631 | } | ||
632 | |||
633 | switch (wk->probe_auth.algorithm) { | ||
634 | case WLAN_AUTH_OPEN: | ||
635 | case WLAN_AUTH_LEAP: | ||
636 | case WLAN_AUTH_FT: | ||
637 | break; | ||
638 | case WLAN_AUTH_SHARED_KEY: | ||
639 | if (wk->probe_auth.transaction != 4) { | ||
640 | ieee80211_auth_challenge(wk, mgmt, len); | ||
641 | /* need another frame */ | ||
642 | return WORK_ACT_NONE; | ||
643 | } | ||
644 | break; | ||
645 | default: | ||
646 | WARN_ON(1); | ||
647 | return WORK_ACT_NONE; | ||
648 | } | ||
649 | |||
650 | printk(KERN_DEBUG "%s: authenticated\n", wk->sdata->name); | ||
651 | return WORK_ACT_DONE; | ||
652 | } | ||
653 | |||
654 | static enum work_action __must_check | ||
655 | ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, | ||
656 | struct ieee80211_mgmt *mgmt, size_t len, | ||
657 | bool reassoc) | ||
658 | { | ||
659 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
660 | struct ieee80211_local *local = sdata->local; | ||
661 | u16 capab_info, status_code, aid; | ||
662 | struct ieee802_11_elems elems; | ||
663 | u8 *pos; | ||
664 | |||
665 | if (wk->type != IEEE80211_WORK_ASSOC) | ||
666 | return WORK_ACT_MISMATCH; | ||
667 | |||
668 | /* | ||
669 | * AssocResp and ReassocResp have identical structure, so process both | ||
670 | * of them in this function. | ||
671 | */ | ||
672 | |||
673 | if (len < 24 + 6) | ||
674 | return WORK_ACT_NONE; | ||
675 | |||
676 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | ||
677 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | ||
678 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | ||
679 | |||
680 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | ||
681 | "status=%d aid=%d)\n", | ||
682 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, | ||
683 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | ||
684 | |||
685 | pos = mgmt->u.assoc_resp.variable; | ||
686 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
687 | |||
688 | if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && | ||
689 | elems.timeout_int && elems.timeout_int_len == 5 && | ||
690 | elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { | ||
691 | u32 tu, ms; | ||
692 | tu = get_unaligned_le32(elems.timeout_int + 1); | ||
693 | ms = tu * 1024 / 1000; | ||
694 | printk(KERN_DEBUG "%s: %pM rejected association temporarily; " | ||
695 | "comeback duration %u TU (%u ms)\n", | ||
696 | sdata->name, mgmt->sa, tu, ms); | ||
697 | wk->timeout = jiffies + msecs_to_jiffies(ms); | ||
698 | if (ms > IEEE80211_ASSOC_TIMEOUT) | ||
699 | run_again(local, wk->timeout); | ||
700 | return WORK_ACT_NONE; | ||
701 | } | ||
702 | |||
703 | if (status_code != WLAN_STATUS_SUCCESS) | ||
704 | printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", | ||
705 | sdata->name, mgmt->sa, status_code); | ||
706 | else | ||
707 | printk(KERN_DEBUG "%s: associated\n", sdata->name); | ||
708 | |||
709 | return WORK_ACT_DONE; | ||
710 | } | ||
711 | |||
712 | static enum work_action __must_check | ||
713 | ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, | ||
714 | struct ieee80211_mgmt *mgmt, size_t len, | ||
715 | struct ieee80211_rx_status *rx_status) | ||
716 | { | ||
717 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
718 | struct ieee80211_local *local = sdata->local; | ||
719 | size_t baselen; | ||
720 | |||
721 | ASSERT_WORK_MTX(local); | ||
722 | |||
723 | if (wk->type != IEEE80211_WORK_DIRECT_PROBE) | ||
724 | return WORK_ACT_MISMATCH; | ||
725 | |||
726 | if (len < 24 + 12) | ||
727 | return WORK_ACT_NONE; | ||
728 | |||
729 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | ||
730 | if (baselen > len) | ||
731 | return WORK_ACT_NONE; | ||
732 | |||
733 | printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); | ||
734 | return WORK_ACT_DONE; | ||
735 | } | ||
736 | |||
737 | static enum work_action __must_check | ||
738 | ieee80211_rx_mgmt_beacon(struct ieee80211_work *wk, | ||
739 | struct ieee80211_mgmt *mgmt, size_t len) | ||
740 | { | ||
741 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
742 | struct ieee80211_local *local = sdata->local; | ||
743 | |||
744 | ASSERT_WORK_MTX(local); | ||
745 | |||
746 | if (wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) | ||
747 | return WORK_ACT_MISMATCH; | ||
748 | |||
749 | if (len < 24 + 12) | ||
750 | return WORK_ACT_NONE; | ||
751 | |||
752 | printk(KERN_DEBUG "%s: beacon received\n", sdata->name); | ||
753 | return WORK_ACT_DONE; | ||
754 | } | ||
755 | |||
756 | static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | ||
757 | struct sk_buff *skb) | ||
758 | { | ||
759 | struct ieee80211_rx_status *rx_status; | ||
760 | struct ieee80211_mgmt *mgmt; | ||
761 | struct ieee80211_work *wk; | ||
762 | enum work_action rma = WORK_ACT_NONE; | ||
763 | u16 fc; | ||
764 | |||
765 | rx_status = (struct ieee80211_rx_status *) skb->cb; | ||
766 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
767 | fc = le16_to_cpu(mgmt->frame_control); | ||
768 | |||
769 | mutex_lock(&local->mtx); | ||
770 | |||
771 | list_for_each_entry(wk, &local->work_list, list) { | ||
772 | const u8 *bssid = NULL; | ||
773 | |||
774 | switch (wk->type) { | ||
775 | case IEEE80211_WORK_DIRECT_PROBE: | ||
776 | case IEEE80211_WORK_AUTH: | ||
777 | case IEEE80211_WORK_ASSOC: | ||
778 | case IEEE80211_WORK_ASSOC_BEACON_WAIT: | ||
779 | bssid = wk->filter_ta; | ||
780 | break; | ||
781 | default: | ||
782 | continue; | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * Before queuing, we already verified mgmt->sa, | ||
787 | * so this is needed just for matching. | ||
788 | */ | ||
789 | if (compare_ether_addr(bssid, mgmt->bssid)) | ||
790 | continue; | ||
791 | |||
792 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
793 | case IEEE80211_STYPE_BEACON: | ||
794 | rma = ieee80211_rx_mgmt_beacon(wk, mgmt, skb->len); | ||
795 | break; | ||
796 | case IEEE80211_STYPE_PROBE_RESP: | ||
797 | rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len, | ||
798 | rx_status); | ||
799 | break; | ||
800 | case IEEE80211_STYPE_AUTH: | ||
801 | rma = ieee80211_rx_mgmt_auth(wk, mgmt, skb->len); | ||
802 | break; | ||
803 | case IEEE80211_STYPE_ASSOC_RESP: | ||
804 | rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, | ||
805 | skb->len, false); | ||
806 | break; | ||
807 | case IEEE80211_STYPE_REASSOC_RESP: | ||
808 | rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, | ||
809 | skb->len, true); | ||
810 | break; | ||
811 | default: | ||
812 | WARN_ON(1); | ||
813 | rma = WORK_ACT_NONE; | ||
814 | } | ||
815 | |||
816 | /* | ||
817 | * We've either received an unexpected frame, or we have | ||
818 | * multiple work items and need to match the frame to the | ||
819 | * right one. | ||
820 | */ | ||
821 | if (rma == WORK_ACT_MISMATCH) | ||
822 | continue; | ||
823 | |||
824 | /* | ||
825 | * We've processed this frame for that work, so it can't | ||
826 | * belong to another work struct. | ||
827 | * NB: this is also required for correctness for 'rma'! | ||
828 | */ | ||
829 | break; | ||
830 | } | ||
831 | |||
832 | switch (rma) { | ||
833 | case WORK_ACT_MISMATCH: | ||
834 | /* ignore this unmatched frame */ | ||
835 | break; | ||
836 | case WORK_ACT_NONE: | ||
837 | break; | ||
838 | case WORK_ACT_DONE: | ||
839 | list_del_rcu(&wk->list); | ||
840 | break; | ||
841 | default: | ||
842 | WARN(1, "unexpected: %d", rma); | ||
843 | } | ||
844 | |||
845 | mutex_unlock(&local->mtx); | ||
846 | |||
847 | if (rma != WORK_ACT_DONE) | ||
848 | goto out; | ||
849 | |||
850 | switch (wk->done(wk, skb)) { | ||
851 | case WORK_DONE_DESTROY: | ||
852 | free_work(wk); | ||
853 | break; | ||
854 | case WORK_DONE_REQUEUE: | ||
855 | synchronize_rcu(); | ||
856 | wk->started = false; /* restart */ | ||
857 | mutex_lock(&local->mtx); | ||
858 | list_add_tail(&wk->list, &local->work_list); | ||
859 | mutex_unlock(&local->mtx); | ||
860 | } | ||
861 | |||
862 | out: | ||
863 | kfree_skb(skb); | ||
864 | } | ||
865 | |||
866 | static void ieee80211_work_timer(unsigned long data) | 106 | static void ieee80211_work_timer(unsigned long data) |
867 | { | 107 | { |
868 | struct ieee80211_local *local = (void *) data; | 108 | struct ieee80211_local *local = (void *) data; |
@@ -877,7 +117,6 @@ static void ieee80211_work_work(struct work_struct *work) | |||
877 | { | 117 | { |
878 | struct ieee80211_local *local = | 118 | struct ieee80211_local *local = |
879 | container_of(work, struct ieee80211_local, work_work); | 119 | container_of(work, struct ieee80211_local, work_work); |
880 | struct sk_buff *skb; | ||
881 | struct ieee80211_work *wk, *tmp; | 120 | struct ieee80211_work *wk, *tmp; |
882 | LIST_HEAD(free_work); | 121 | LIST_HEAD(free_work); |
883 | enum work_action rma; | 122 | enum work_action rma; |
@@ -893,10 +132,6 @@ static void ieee80211_work_work(struct work_struct *work) | |||
893 | if (WARN(local->suspended, "work scheduled while going to suspend\n")) | 132 | if (WARN(local->suspended, "work scheduled while going to suspend\n")) |
894 | return; | 133 | return; |
895 | 134 | ||
896 | /* first process frames to avoid timing out while a frame is pending */ | ||
897 | while ((skb = skb_dequeue(&local->work_skb_queue))) | ||
898 | ieee80211_work_rx_queued_mgmt(local, skb); | ||
899 | |||
900 | mutex_lock(&local->mtx); | 135 | mutex_lock(&local->mtx); |
901 | 136 | ||
902 | ieee80211_recalc_idle(local); | 137 | ieee80211_recalc_idle(local); |
@@ -947,24 +182,12 @@ static void ieee80211_work_work(struct work_struct *work) | |||
947 | case IEEE80211_WORK_ABORT: | 182 | case IEEE80211_WORK_ABORT: |
948 | rma = WORK_ACT_TIMEOUT; | 183 | rma = WORK_ACT_TIMEOUT; |
949 | break; | 184 | break; |
950 | case IEEE80211_WORK_DIRECT_PROBE: | ||
951 | rma = ieee80211_direct_probe(wk); | ||
952 | break; | ||
953 | case IEEE80211_WORK_AUTH: | ||
954 | rma = ieee80211_authenticate(wk); | ||
955 | break; | ||
956 | case IEEE80211_WORK_ASSOC: | ||
957 | rma = ieee80211_associate(wk); | ||
958 | break; | ||
959 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: | 185 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: |
960 | rma = ieee80211_remain_on_channel_timeout(wk); | 186 | rma = ieee80211_remain_on_channel_timeout(wk); |
961 | break; | 187 | break; |
962 | case IEEE80211_WORK_OFFCHANNEL_TX: | 188 | case IEEE80211_WORK_OFFCHANNEL_TX: |
963 | rma = ieee80211_offchannel_tx(wk); | 189 | rma = ieee80211_offchannel_tx(wk); |
964 | break; | 190 | break; |
965 | case IEEE80211_WORK_ASSOC_BEACON_WAIT: | ||
966 | rma = ieee80211_assoc_beacon_wait(wk); | ||
967 | break; | ||
968 | } | 191 | } |
969 | 192 | ||
970 | wk->started = started; | 193 | wk->started = started; |
@@ -1052,7 +275,6 @@ void ieee80211_work_init(struct ieee80211_local *local) | |||
1052 | setup_timer(&local->work_timer, ieee80211_work_timer, | 275 | setup_timer(&local->work_timer, ieee80211_work_timer, |
1053 | (unsigned long)local); | 276 | (unsigned long)local); |
1054 | INIT_WORK(&local->work_work, ieee80211_work_work); | 277 | INIT_WORK(&local->work_work, ieee80211_work_work); |
1055 | skb_queue_head_init(&local->work_skb_queue); | ||
1056 | } | 278 | } |
1057 | 279 | ||
1058 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | 280 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) |
@@ -1086,43 +308,6 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | |||
1086 | mutex_unlock(&local->mtx); | 308 | mutex_unlock(&local->mtx); |
1087 | } | 309 | } |
1088 | 310 | ||
1089 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | ||
1090 | struct sk_buff *skb) | ||
1091 | { | ||
1092 | struct ieee80211_local *local = sdata->local; | ||
1093 | struct ieee80211_mgmt *mgmt; | ||
1094 | struct ieee80211_work *wk; | ||
1095 | u16 fc; | ||
1096 | |||
1097 | if (skb->len < 24) | ||
1098 | return RX_DROP_MONITOR; | ||
1099 | |||
1100 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
1101 | fc = le16_to_cpu(mgmt->frame_control); | ||
1102 | |||
1103 | list_for_each_entry_rcu(wk, &local->work_list, list) { | ||
1104 | if (sdata != wk->sdata) | ||
1105 | continue; | ||
1106 | if (compare_ether_addr(wk->filter_ta, mgmt->sa)) | ||
1107 | continue; | ||
1108 | if (compare_ether_addr(wk->filter_ta, mgmt->bssid)) | ||
1109 | continue; | ||
1110 | |||
1111 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
1112 | case IEEE80211_STYPE_AUTH: | ||
1113 | case IEEE80211_STYPE_PROBE_RESP: | ||
1114 | case IEEE80211_STYPE_ASSOC_RESP: | ||
1115 | case IEEE80211_STYPE_REASSOC_RESP: | ||
1116 | case IEEE80211_STYPE_BEACON: | ||
1117 | skb_queue_tail(&local->work_skb_queue, skb); | ||
1118 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
1119 | return RX_QUEUED; | ||
1120 | } | ||
1121 | } | ||
1122 | |||
1123 | return RX_CONTINUE; | ||
1124 | } | ||
1125 | |||
1126 | static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, | 311 | static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, |
1127 | struct sk_buff *skb) | 312 | struct sk_buff *skb) |
1128 | { | 313 | { |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 43ad9c81efcf..3ac2dd00d714 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -144,11 +144,6 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu | |||
144 | return container_of(pub, struct cfg80211_internal_bss, pub); | 144 | return container_of(pub, struct cfg80211_internal_bss, pub); |
145 | } | 145 | } |
146 | 146 | ||
147 | static inline void cfg80211_ref_bss(struct cfg80211_internal_bss *bss) | ||
148 | { | ||
149 | kref_get(&bss->ref); | ||
150 | } | ||
151 | |||
152 | static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss) | 147 | static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss) |
153 | { | 148 | { |
154 | atomic_inc(&bss->hold); | 149 | atomic_inc(&bss->hold); |
@@ -325,15 +320,13 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
325 | const u8 *bssid, | 320 | const u8 *bssid, |
326 | const u8 *ssid, int ssid_len, | 321 | const u8 *ssid, int ssid_len, |
327 | const u8 *ie, int ie_len, | 322 | const u8 *ie, int ie_len, |
328 | const u8 *key, int key_len, int key_idx, | 323 | const u8 *key, int key_len, int key_idx); |
329 | bool local_state_change); | ||
330 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 324 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
331 | struct net_device *dev, struct ieee80211_channel *chan, | 325 | struct net_device *dev, struct ieee80211_channel *chan, |
332 | enum nl80211_auth_type auth_type, const u8 *bssid, | 326 | enum nl80211_auth_type auth_type, const u8 *bssid, |
333 | const u8 *ssid, int ssid_len, | 327 | const u8 *ssid, int ssid_len, |
334 | const u8 *ie, int ie_len, | 328 | const u8 *ie, int ie_len, |
335 | const u8 *key, int key_len, int key_idx, | 329 | const u8 *key, int key_len, int key_idx); |
336 | bool local_state_change); | ||
337 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 330 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
338 | struct net_device *dev, | 331 | struct net_device *dev, |
339 | struct ieee80211_channel *chan, | 332 | struct ieee80211_channel *chan, |
@@ -421,7 +414,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
421 | size_t ie_len, u16 reason, bool from_ap); | 414 | size_t ie_len, u16 reason, bool from_ap); |
422 | void cfg80211_sme_scan_done(struct net_device *dev); | 415 | void cfg80211_sme_scan_done(struct net_device *dev); |
423 | void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); | 416 | void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); |
424 | void cfg80211_sme_disassoc(struct net_device *dev, int idx); | 417 | void cfg80211_sme_disassoc(struct net_device *dev, |
418 | struct cfg80211_internal_bss *bss); | ||
425 | void __cfg80211_scan_done(struct work_struct *wk); | 419 | void __cfg80211_scan_done(struct work_struct *wk); |
426 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); | 420 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); |
427 | void __cfg80211_sched_scan_results(struct work_struct *wk); | 421 | void __cfg80211_sched_scan_results(struct work_struct *wk); |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 438dfc105b4a..d553d365e751 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -20,40 +20,18 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) | |||
20 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 20 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
21 | struct wiphy *wiphy = wdev->wiphy; | 21 | struct wiphy *wiphy = wdev->wiphy; |
22 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 22 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
23 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | ||
24 | u8 *bssid = mgmt->bssid; | ||
25 | int i; | ||
26 | u16 status = le16_to_cpu(mgmt->u.auth.status_code); | ||
27 | bool done = false; | ||
28 | 23 | ||
29 | wdev_lock(wdev); | 24 | wdev_lock(wdev); |
30 | 25 | ||
31 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | 26 | nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); |
32 | if (wdev->authtry_bsses[i] && | 27 | cfg80211_sme_rx_auth(dev, buf, len); |
33 | memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, | ||
34 | ETH_ALEN) == 0) { | ||
35 | if (status == WLAN_STATUS_SUCCESS) { | ||
36 | wdev->auth_bsses[i] = wdev->authtry_bsses[i]; | ||
37 | } else { | ||
38 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | ||
39 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | ||
40 | } | ||
41 | wdev->authtry_bsses[i] = NULL; | ||
42 | done = true; | ||
43 | break; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | if (done) { | ||
48 | nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); | ||
49 | cfg80211_sme_rx_auth(dev, buf, len); | ||
50 | } | ||
51 | 28 | ||
52 | wdev_unlock(wdev); | 29 | wdev_unlock(wdev); |
53 | } | 30 | } |
54 | EXPORT_SYMBOL(cfg80211_send_rx_auth); | 31 | EXPORT_SYMBOL(cfg80211_send_rx_auth); |
55 | 32 | ||
56 | void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | 33 | void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, |
34 | const u8 *buf, size_t len) | ||
57 | { | 35 | { |
58 | u16 status_code; | 36 | u16 status_code; |
59 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 37 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -61,8 +39,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
61 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 39 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
62 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 40 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
63 | u8 *ie = mgmt->u.assoc_resp.variable; | 41 | u8 *ie = mgmt->u.assoc_resp.variable; |
64 | int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); | 42 | int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); |
65 | struct cfg80211_internal_bss *bss = NULL; | ||
66 | 43 | ||
67 | wdev_lock(wdev); | 44 | wdev_lock(wdev); |
68 | 45 | ||
@@ -75,43 +52,20 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
75 | * frame instead of reassoc. | 52 | * frame instead of reassoc. |
76 | */ | 53 | */ |
77 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && | 54 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && |
78 | cfg80211_sme_failed_reassoc(wdev)) | 55 | cfg80211_sme_failed_reassoc(wdev)) { |
56 | cfg80211_put_bss(bss); | ||
79 | goto out; | 57 | goto out; |
58 | } | ||
80 | 59 | ||
81 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); | 60 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); |
82 | 61 | ||
83 | if (status_code == WLAN_STATUS_SUCCESS) { | 62 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn) { |
84 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
85 | if (!wdev->auth_bsses[i]) | ||
86 | continue; | ||
87 | if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid, | ||
88 | ETH_ALEN) == 0) { | ||
89 | bss = wdev->auth_bsses[i]; | ||
90 | wdev->auth_bsses[i] = NULL; | ||
91 | /* additional reference to drop hold */ | ||
92 | cfg80211_ref_bss(bss); | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * We might be coming here because the driver reported | ||
99 | * a successful association at the same time as the | ||
100 | * user requested a deauth. In that case, we will have | ||
101 | * removed the BSS from the auth_bsses list due to the | ||
102 | * deauth request when the assoc response makes it. If | ||
103 | * the two code paths acquire the lock the other way | ||
104 | * around, that's just the standard situation of a | ||
105 | * deauth being requested while connected. | ||
106 | */ | ||
107 | if (!bss) | ||
108 | goto out; | ||
109 | } else if (wdev->conn) { | ||
110 | cfg80211_sme_failed_assoc(wdev); | 63 | cfg80211_sme_failed_assoc(wdev); |
111 | /* | 64 | /* |
112 | * do not call connect_result() now because the | 65 | * do not call connect_result() now because the |
113 | * sme will schedule work that does it later. | 66 | * sme will schedule work that does it later. |
114 | */ | 67 | */ |
68 | cfg80211_put_bss(bss); | ||
115 | goto out; | 69 | goto out; |
116 | } | 70 | } |
117 | 71 | ||
@@ -124,17 +78,10 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
124 | wdev->sme_state = CFG80211_SME_CONNECTING; | 78 | wdev->sme_state = CFG80211_SME_CONNECTING; |
125 | } | 79 | } |
126 | 80 | ||
127 | /* this consumes one bss reference (unless bss is NULL) */ | 81 | /* this consumes the bss reference */ |
128 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | 82 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, |
129 | status_code, | 83 | status_code, |
130 | status_code == WLAN_STATUS_SUCCESS, | 84 | status_code == WLAN_STATUS_SUCCESS, bss); |
131 | bss ? &bss->pub : NULL); | ||
132 | /* drop hold now, and also reference acquired above */ | ||
133 | if (bss) { | ||
134 | cfg80211_unhold_bss(bss); | ||
135 | cfg80211_put_bss(&bss->pub); | ||
136 | } | ||
137 | |||
138 | out: | 85 | out: |
139 | wdev_unlock(wdev); | 86 | wdev_unlock(wdev); |
140 | } | 87 | } |
@@ -148,8 +95,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
148 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 95 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
149 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 96 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
150 | const u8 *bssid = mgmt->bssid; | 97 | const u8 *bssid = mgmt->bssid; |
151 | int i; | 98 | bool was_current = false; |
152 | bool found = false, was_current = false; | ||
153 | 99 | ||
154 | ASSERT_WDEV_LOCK(wdev); | 100 | ASSERT_WDEV_LOCK(wdev); |
155 | 101 | ||
@@ -158,32 +104,9 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
158 | cfg80211_unhold_bss(wdev->current_bss); | 104 | cfg80211_unhold_bss(wdev->current_bss); |
159 | cfg80211_put_bss(&wdev->current_bss->pub); | 105 | cfg80211_put_bss(&wdev->current_bss->pub); |
160 | wdev->current_bss = NULL; | 106 | wdev->current_bss = NULL; |
161 | found = true; | ||
162 | was_current = true; | 107 | was_current = true; |
163 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
164 | if (wdev->auth_bsses[i] && | ||
165 | memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { | ||
166 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | ||
167 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | ||
168 | wdev->auth_bsses[i] = NULL; | ||
169 | found = true; | ||
170 | break; | ||
171 | } | ||
172 | if (wdev->authtry_bsses[i] && | ||
173 | memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, | ||
174 | ETH_ALEN) == 0 && | ||
175 | memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) == 0) { | ||
176 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | ||
177 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | ||
178 | wdev->authtry_bsses[i] = NULL; | ||
179 | found = true; | ||
180 | break; | ||
181 | } | ||
182 | } | 108 | } |
183 | 109 | ||
184 | if (!found) | ||
185 | return; | ||
186 | |||
187 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); | 110 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); |
188 | 111 | ||
189 | if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { | 112 | if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { |
@@ -220,10 +143,8 @@ void __cfg80211_send_disassoc(struct net_device *dev, | |||
220 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 143 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
221 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 144 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
222 | const u8 *bssid = mgmt->bssid; | 145 | const u8 *bssid = mgmt->bssid; |
223 | int i; | ||
224 | u16 reason_code; | 146 | u16 reason_code; |
225 | bool from_ap; | 147 | bool from_ap; |
226 | bool done = false; | ||
227 | 148 | ||
228 | ASSERT_WDEV_LOCK(wdev); | 149 | ASSERT_WDEV_LOCK(wdev); |
229 | 150 | ||
@@ -234,16 +155,10 @@ void __cfg80211_send_disassoc(struct net_device *dev, | |||
234 | 155 | ||
235 | if (wdev->current_bss && | 156 | if (wdev->current_bss && |
236 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { | 157 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { |
237 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | 158 | cfg80211_sme_disassoc(dev, wdev->current_bss); |
238 | if (wdev->authtry_bsses[i] || wdev->auth_bsses[i]) | 159 | cfg80211_unhold_bss(wdev->current_bss); |
239 | continue; | 160 | cfg80211_put_bss(&wdev->current_bss->pub); |
240 | wdev->auth_bsses[i] = wdev->current_bss; | 161 | wdev->current_bss = NULL; |
241 | wdev->current_bss = NULL; | ||
242 | done = true; | ||
243 | cfg80211_sme_disassoc(dev, i); | ||
244 | break; | ||
245 | } | ||
246 | WARN_ON(!done); | ||
247 | } else | 162 | } else |
248 | WARN_ON(1); | 163 | WARN_ON(1); |
249 | 164 | ||
@@ -287,34 +202,6 @@ void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, | |||
287 | } | 202 | } |
288 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); | 203 | EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); |
289 | 204 | ||
290 | static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) | ||
291 | { | ||
292 | int i; | ||
293 | bool done = false; | ||
294 | |||
295 | ASSERT_WDEV_LOCK(wdev); | ||
296 | |||
297 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | ||
298 | if (wdev->authtry_bsses[i] && | ||
299 | memcmp(wdev->authtry_bsses[i]->pub.bssid, | ||
300 | addr, ETH_ALEN) == 0) { | ||
301 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | ||
302 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | ||
303 | wdev->authtry_bsses[i] = NULL; | ||
304 | done = true; | ||
305 | break; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | WARN_ON(!done); | ||
310 | } | ||
311 | |||
312 | void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr) | ||
313 | { | ||
314 | __cfg80211_auth_remove(dev->ieee80211_ptr, addr); | ||
315 | } | ||
316 | EXPORT_SYMBOL(__cfg80211_auth_canceled); | ||
317 | |||
318 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | 205 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) |
319 | { | 206 | { |
320 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 207 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -329,8 +216,6 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | |||
329 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 216 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
330 | false, NULL); | 217 | false, NULL); |
331 | 218 | ||
332 | __cfg80211_auth_remove(wdev, addr); | ||
333 | |||
334 | wdev_unlock(wdev); | 219 | wdev_unlock(wdev); |
335 | } | 220 | } |
336 | EXPORT_SYMBOL(cfg80211_send_auth_timeout); | 221 | EXPORT_SYMBOL(cfg80211_send_auth_timeout); |
@@ -340,8 +225,6 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) | |||
340 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 225 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
341 | struct wiphy *wiphy = wdev->wiphy; | 226 | struct wiphy *wiphy = wdev->wiphy; |
342 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 227 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
343 | int i; | ||
344 | bool done = false; | ||
345 | 228 | ||
346 | wdev_lock(wdev); | 229 | wdev_lock(wdev); |
347 | 230 | ||
@@ -351,20 +234,6 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) | |||
351 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 234 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
352 | false, NULL); | 235 | false, NULL); |
353 | 236 | ||
354 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | ||
355 | if (wdev->auth_bsses[i] && | ||
356 | memcmp(wdev->auth_bsses[i]->pub.bssid, | ||
357 | addr, ETH_ALEN) == 0) { | ||
358 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | ||
359 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | ||
360 | wdev->auth_bsses[i] = NULL; | ||
361 | done = true; | ||
362 | break; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | WARN_ON(!done); | ||
367 | |||
368 | wdev_unlock(wdev); | 237 | wdev_unlock(wdev); |
369 | } | 238 | } |
370 | EXPORT_SYMBOL(cfg80211_send_assoc_timeout); | 239 | EXPORT_SYMBOL(cfg80211_send_assoc_timeout); |
@@ -403,13 +272,11 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
403 | const u8 *bssid, | 272 | const u8 *bssid, |
404 | const u8 *ssid, int ssid_len, | 273 | const u8 *ssid, int ssid_len, |
405 | const u8 *ie, int ie_len, | 274 | const u8 *ie, int ie_len, |
406 | const u8 *key, int key_len, int key_idx, | 275 | const u8 *key, int key_len, int key_idx) |
407 | bool local_state_change) | ||
408 | { | 276 | { |
409 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 277 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
410 | struct cfg80211_auth_request req; | 278 | struct cfg80211_auth_request req; |
411 | struct cfg80211_internal_bss *bss; | 279 | int err; |
412 | int i, err, slot = -1, nfree = 0; | ||
413 | 280 | ||
414 | ASSERT_WDEV_LOCK(wdev); | 281 | ASSERT_WDEV_LOCK(wdev); |
415 | 282 | ||
@@ -421,20 +288,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
421 | memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) | 288 | memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) |
422 | return -EALREADY; | 289 | return -EALREADY; |
423 | 290 | ||
424 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
425 | if (wdev->authtry_bsses[i] && | ||
426 | memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, | ||
427 | ETH_ALEN) == 0) | ||
428 | return -EALREADY; | ||
429 | if (wdev->auth_bsses[i] && | ||
430 | memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, | ||
431 | ETH_ALEN) == 0) | ||
432 | return -EALREADY; | ||
433 | } | ||
434 | |||
435 | memset(&req, 0, sizeof(req)); | 291 | memset(&req, 0, sizeof(req)); |
436 | 292 | ||
437 | req.local_state_change = local_state_change; | ||
438 | req.ie = ie; | 293 | req.ie = ie; |
439 | req.ie_len = ie_len; | 294 | req.ie_len = ie_len; |
440 | req.auth_type = auth_type; | 295 | req.auth_type = auth_type; |
@@ -446,39 +301,9 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
446 | if (!req.bss) | 301 | if (!req.bss) |
447 | return -ENOENT; | 302 | return -ENOENT; |
448 | 303 | ||
449 | bss = bss_from_pub(req.bss); | ||
450 | |||
451 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
452 | if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) { | ||
453 | slot = i; | ||
454 | nfree++; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | /* we need one free slot for disassoc and one for this auth */ | ||
459 | if (nfree < 2) { | ||
460 | err = -ENOSPC; | ||
461 | goto out; | ||
462 | } | ||
463 | |||
464 | if (local_state_change) | ||
465 | wdev->auth_bsses[slot] = bss; | ||
466 | else | ||
467 | wdev->authtry_bsses[slot] = bss; | ||
468 | cfg80211_hold_bss(bss); | ||
469 | |||
470 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); | 304 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); |
471 | if (err) { | ||
472 | if (local_state_change) | ||
473 | wdev->auth_bsses[slot] = NULL; | ||
474 | else | ||
475 | wdev->authtry_bsses[slot] = NULL; | ||
476 | cfg80211_unhold_bss(bss); | ||
477 | } | ||
478 | 305 | ||
479 | out: | 306 | cfg80211_put_bss(req.bss); |
480 | if (err) | ||
481 | cfg80211_put_bss(req.bss); | ||
482 | return err; | 307 | return err; |
483 | } | 308 | } |
484 | 309 | ||
@@ -487,15 +312,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
487 | enum nl80211_auth_type auth_type, const u8 *bssid, | 312 | enum nl80211_auth_type auth_type, const u8 *bssid, |
488 | const u8 *ssid, int ssid_len, | 313 | const u8 *ssid, int ssid_len, |
489 | const u8 *ie, int ie_len, | 314 | const u8 *ie, int ie_len, |
490 | const u8 *key, int key_len, int key_idx, | 315 | const u8 *key, int key_len, int key_idx) |
491 | bool local_state_change) | ||
492 | { | 316 | { |
493 | int err; | 317 | int err; |
494 | 318 | ||
495 | wdev_lock(dev->ieee80211_ptr); | 319 | wdev_lock(dev->ieee80211_ptr); |
496 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 320 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
497 | ssid, ssid_len, ie, ie_len, | 321 | ssid, ssid_len, ie, ie_len, |
498 | key, key_len, key_idx, local_state_change); | 322 | key, key_len, key_idx); |
499 | wdev_unlock(dev->ieee80211_ptr); | 323 | wdev_unlock(dev->ieee80211_ptr); |
500 | 324 | ||
501 | return err; | 325 | return err; |
@@ -530,8 +354,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
530 | { | 354 | { |
531 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 355 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
532 | struct cfg80211_assoc_request req; | 356 | struct cfg80211_assoc_request req; |
533 | struct cfg80211_internal_bss *bss; | 357 | int err; |
534 | int i, err, slot = -1; | ||
535 | bool was_connected = false; | 358 | bool was_connected = false; |
536 | 359 | ||
537 | ASSERT_WDEV_LOCK(wdev); | 360 | ASSERT_WDEV_LOCK(wdev); |
@@ -573,26 +396,14 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
573 | return -ENOENT; | 396 | return -ENOENT; |
574 | } | 397 | } |
575 | 398 | ||
576 | bss = bss_from_pub(req.bss); | 399 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); |
577 | |||
578 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
579 | if (bss == wdev->auth_bsses[i]) { | ||
580 | slot = i; | ||
581 | break; | ||
582 | } | ||
583 | } | ||
584 | 400 | ||
585 | if (slot < 0) { | 401 | if (err) { |
586 | err = -ENOTCONN; | 402 | if (was_connected) |
587 | goto out; | 403 | wdev->sme_state = CFG80211_SME_CONNECTED; |
404 | cfg80211_put_bss(req.bss); | ||
588 | } | 405 | } |
589 | 406 | ||
590 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); | ||
591 | out: | ||
592 | if (err && was_connected) | ||
593 | wdev->sme_state = CFG80211_SME_CONNECTED; | ||
594 | /* still a reference in wdev->auth_bsses[slot] */ | ||
595 | cfg80211_put_bss(req.bss); | ||
596 | return err; | 407 | return err; |
597 | } | 408 | } |
598 | 409 | ||
@@ -624,34 +435,25 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
624 | bool local_state_change) | 435 | bool local_state_change) |
625 | { | 436 | { |
626 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 437 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
627 | struct cfg80211_deauth_request req; | 438 | struct cfg80211_deauth_request req = { |
628 | int i; | 439 | .bssid = bssid, |
440 | .reason_code = reason, | ||
441 | .ie = ie, | ||
442 | .ie_len = ie_len, | ||
443 | }; | ||
629 | 444 | ||
630 | ASSERT_WDEV_LOCK(wdev); | 445 | ASSERT_WDEV_LOCK(wdev); |
631 | 446 | ||
632 | memset(&req, 0, sizeof(req)); | 447 | if (local_state_change) { |
633 | req.reason_code = reason; | 448 | if (wdev->current_bss && |
634 | req.local_state_change = local_state_change; | 449 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { |
635 | req.ie = ie; | 450 | cfg80211_unhold_bss(wdev->current_bss); |
636 | req.ie_len = ie_len; | 451 | cfg80211_put_bss(&wdev->current_bss->pub); |
637 | if (wdev->current_bss && | 452 | wdev->current_bss = NULL; |
638 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { | ||
639 | req.bss = &wdev->current_bss->pub; | ||
640 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
641 | if (wdev->auth_bsses[i] && | ||
642 | memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) { | ||
643 | req.bss = &wdev->auth_bsses[i]->pub; | ||
644 | break; | ||
645 | } | ||
646 | if (wdev->authtry_bsses[i] && | ||
647 | memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) { | ||
648 | req.bss = &wdev->authtry_bsses[i]->pub; | ||
649 | break; | ||
650 | } | 453 | } |
651 | } | ||
652 | 454 | ||
653 | if (!req.bss) | 455 | return 0; |
654 | return -ENOTCONN; | 456 | } |
655 | 457 | ||
656 | return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); | 458 | return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); |
657 | } | 459 | } |
@@ -722,7 +524,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
722 | { | 524 | { |
723 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 525 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
724 | struct cfg80211_deauth_request req; | 526 | struct cfg80211_deauth_request req; |
725 | int i; | 527 | u8 bssid[ETH_ALEN]; |
726 | 528 | ||
727 | ASSERT_WDEV_LOCK(wdev); | 529 | ASSERT_WDEV_LOCK(wdev); |
728 | 530 | ||
@@ -734,35 +536,17 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
734 | req.ie = NULL; | 536 | req.ie = NULL; |
735 | req.ie_len = 0; | 537 | req.ie_len = 0; |
736 | 538 | ||
737 | if (wdev->current_bss) { | 539 | if (!wdev->current_bss) |
738 | req.bss = &wdev->current_bss->pub; | 540 | return; |
739 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); | ||
740 | if (wdev->current_bss) { | ||
741 | cfg80211_unhold_bss(wdev->current_bss); | ||
742 | cfg80211_put_bss(&wdev->current_bss->pub); | ||
743 | wdev->current_bss = NULL; | ||
744 | } | ||
745 | } | ||
746 | 541 | ||
747 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | 542 | memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); |
748 | if (wdev->auth_bsses[i]) { | 543 | req.bssid = bssid; |
749 | req.bss = &wdev->auth_bsses[i]->pub; | 544 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); |
750 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); | 545 | |
751 | if (wdev->auth_bsses[i]) { | 546 | if (wdev->current_bss) { |
752 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | 547 | cfg80211_unhold_bss(wdev->current_bss); |
753 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | 548 | cfg80211_put_bss(&wdev->current_bss->pub); |
754 | wdev->auth_bsses[i] = NULL; | 549 | wdev->current_bss = NULL; |
755 | } | ||
756 | } | ||
757 | if (wdev->authtry_bsses[i]) { | ||
758 | req.bss = &wdev->authtry_bsses[i]->pub; | ||
759 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); | ||
760 | if (wdev->authtry_bsses[i]) { | ||
761 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | ||
762 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | ||
763 | wdev->authtry_bsses[i] = NULL; | ||
764 | } | ||
765 | } | ||
766 | } | 550 | } |
767 | } | 551 | } |
768 | 552 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c910b0750dc2..fe2747653564 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2654,13 +2654,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2654 | break; | 2654 | break; |
2655 | case NL80211_IFTYPE_P2P_CLIENT: | 2655 | case NL80211_IFTYPE_P2P_CLIENT: |
2656 | case NL80211_IFTYPE_STATION: | 2656 | case NL80211_IFTYPE_STATION: |
2657 | /* disallow things sta doesn't support */ | ||
2658 | if (params.plink_action) | ||
2659 | return -EINVAL; | ||
2660 | if (params.ht_capa) | ||
2661 | return -EINVAL; | ||
2662 | if (params.listen_interval >= 0) | ||
2663 | return -EINVAL; | ||
2664 | /* | 2657 | /* |
2665 | * Don't allow userspace to change the TDLS_PEER flag, | 2658 | * Don't allow userspace to change the TDLS_PEER flag, |
2666 | * but silently ignore attempts to change it since we | 2659 | * but silently ignore attempts to change it since we |
@@ -2668,7 +2661,15 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2668 | * to change the flag. | 2661 | * to change the flag. |
2669 | */ | 2662 | */ |
2670 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); | 2663 | params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); |
2671 | 2664 | /* fall through */ | |
2665 | case NL80211_IFTYPE_ADHOC: | ||
2666 | /* disallow things sta doesn't support */ | ||
2667 | if (params.plink_action) | ||
2668 | return -EINVAL; | ||
2669 | if (params.ht_capa) | ||
2670 | return -EINVAL; | ||
2671 | if (params.listen_interval >= 0) | ||
2672 | return -EINVAL; | ||
2672 | /* reject any changes other than AUTHORIZED */ | 2673 | /* reject any changes other than AUTHORIZED */ |
2673 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | 2674 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) |
2674 | return -EINVAL; | 2675 | return -EINVAL; |
@@ -4083,7 +4084,6 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
4083 | struct cfg80211_bss *res = &intbss->pub; | 4084 | struct cfg80211_bss *res = &intbss->pub; |
4084 | void *hdr; | 4085 | void *hdr; |
4085 | struct nlattr *bss; | 4086 | struct nlattr *bss; |
4086 | int i; | ||
4087 | 4087 | ||
4088 | ASSERT_WDEV_LOCK(wdev); | 4088 | ASSERT_WDEV_LOCK(wdev); |
4089 | 4089 | ||
@@ -4136,13 +4136,6 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
4136 | if (intbss == wdev->current_bss) | 4136 | if (intbss == wdev->current_bss) |
4137 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | 4137 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, |
4138 | NL80211_BSS_STATUS_ASSOCIATED); | 4138 | NL80211_BSS_STATUS_ASSOCIATED); |
4139 | else for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
4140 | if (intbss != wdev->auth_bsses[i]) | ||
4141 | continue; | ||
4142 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | ||
4143 | NL80211_BSS_STATUS_AUTHENTICATED); | ||
4144 | break; | ||
4145 | } | ||
4146 | break; | 4139 | break; |
4147 | case NL80211_IFTYPE_ADHOC: | 4140 | case NL80211_IFTYPE_ADHOC: |
4148 | if (intbss == wdev->current_bss) | 4141 | if (intbss == wdev->current_bss) |
@@ -4410,10 +4403,16 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
4410 | 4403 | ||
4411 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 4404 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
4412 | 4405 | ||
4406 | /* | ||
4407 | * Since we no longer track auth state, ignore | ||
4408 | * requests to only change local state. | ||
4409 | */ | ||
4410 | if (local_state_change) | ||
4411 | return 0; | ||
4412 | |||
4413 | return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 4413 | return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
4414 | ssid, ssid_len, ie, ie_len, | 4414 | ssid, ssid_len, ie, ie_len, |
4415 | key.p.key, key.p.key_len, key.idx, | 4415 | key.p.key, key.p.key_len, key.idx); |
4416 | local_state_change); | ||
4417 | } | 4416 | } |
4418 | 4417 | ||
4419 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | 4418 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, |
@@ -4804,6 +4803,9 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
4804 | return PTR_ERR(connkeys); | 4803 | return PTR_ERR(connkeys); |
4805 | } | 4804 | } |
4806 | 4805 | ||
4806 | ibss.control_port = | ||
4807 | nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]); | ||
4808 | |||
4807 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); | 4809 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); |
4808 | if (err) | 4810 | if (err) |
4809 | kfree(connkeys); | 4811 | kfree(connkeys); |
@@ -5408,7 +5410,7 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband, | |||
5408 | rbit = BIT(rates[i] % 8); | 5410 | rbit = BIT(rates[i] % 8); |
5409 | 5411 | ||
5410 | /* check validity */ | 5412 | /* check validity */ |
5411 | if ((ridx < 0) || (ridx > IEEE80211_HT_MCS_MASK_LEN)) | 5413 | if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN)) |
5412 | return false; | 5414 | return false; |
5413 | 5415 | ||
5414 | /* check availability */ | 5416 | /* check availability */ |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 31119e32e092..afde7e5f0010 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -861,6 +861,18 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
861 | } | 861 | } |
862 | EXPORT_SYMBOL(cfg80211_inform_bss_frame); | 862 | EXPORT_SYMBOL(cfg80211_inform_bss_frame); |
863 | 863 | ||
864 | void cfg80211_ref_bss(struct cfg80211_bss *pub) | ||
865 | { | ||
866 | struct cfg80211_internal_bss *bss; | ||
867 | |||
868 | if (!pub) | ||
869 | return; | ||
870 | |||
871 | bss = container_of(pub, struct cfg80211_internal_bss, pub); | ||
872 | kref_get(&bss->ref); | ||
873 | } | ||
874 | EXPORT_SYMBOL(cfg80211_ref_bss); | ||
875 | |||
864 | void cfg80211_put_bss(struct cfg80211_bss *pub) | 876 | void cfg80211_put_bss(struct cfg80211_bss *pub) |
865 | { | 877 | { |
866 | struct cfg80211_internal_bss *bss; | 878 | struct cfg80211_internal_bss *bss; |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 7b9ecaed96be..f7e937ff8978 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -179,7 +179,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
179 | params->ssid, params->ssid_len, | 179 | params->ssid, params->ssid_len, |
180 | NULL, 0, | 180 | NULL, 0, |
181 | params->key, params->key_len, | 181 | params->key, params->key_len, |
182 | params->key_idx, false); | 182 | params->key_idx); |
183 | case CFG80211_CONN_ASSOCIATE_NEXT: | 183 | case CFG80211_CONN_ASSOCIATE_NEXT: |
184 | BUG_ON(!rdev->ops->assoc); | 184 | BUG_ON(!rdev->ops->assoc); |
185 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 185 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |
@@ -477,6 +477,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
477 | kfree(wdev->connect_keys); | 477 | kfree(wdev->connect_keys); |
478 | wdev->connect_keys = NULL; | 478 | wdev->connect_keys = NULL; |
479 | wdev->ssid_len = 0; | 479 | wdev->ssid_len = 0; |
480 | cfg80211_put_bss(bss); | ||
480 | return; | 481 | return; |
481 | } | 482 | } |
482 | 483 | ||
@@ -701,31 +702,10 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
701 | wdev->ssid_len = 0; | 702 | wdev->ssid_len = 0; |
702 | 703 | ||
703 | if (wdev->conn) { | 704 | if (wdev->conn) { |
704 | const u8 *bssid; | ||
705 | int ret; | ||
706 | |||
707 | kfree(wdev->conn->ie); | 705 | kfree(wdev->conn->ie); |
708 | wdev->conn->ie = NULL; | 706 | wdev->conn->ie = NULL; |
709 | kfree(wdev->conn); | 707 | kfree(wdev->conn); |
710 | wdev->conn = NULL; | 708 | wdev->conn = NULL; |
711 | |||
712 | /* | ||
713 | * If this disconnect was due to a disassoc, we | ||
714 | * we might still have an auth BSS around. For | ||
715 | * the userspace SME that's currently expected, | ||
716 | * but for the kernel SME (nl80211 CONNECT or | ||
717 | * wireless extensions) we want to clear up all | ||
718 | * state. | ||
719 | */ | ||
720 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
721 | if (!wdev->auth_bsses[i]) | ||
722 | continue; | ||
723 | bssid = wdev->auth_bsses[i]->pub.bssid; | ||
724 | ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, | ||
725 | WLAN_REASON_DEAUTH_LEAVING, | ||
726 | false); | ||
727 | WARN(ret, "deauth failed: %d\n", ret); | ||
728 | } | ||
729 | } | 709 | } |
730 | 710 | ||
731 | nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); | 711 | nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); |
@@ -1012,7 +992,8 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
1012 | return err; | 992 | return err; |
1013 | } | 993 | } |
1014 | 994 | ||
1015 | void cfg80211_sme_disassoc(struct net_device *dev, int idx) | 995 | void cfg80211_sme_disassoc(struct net_device *dev, |
996 | struct cfg80211_internal_bss *bss) | ||
1016 | { | 997 | { |
1017 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 998 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
1018 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 999 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
@@ -1031,16 +1012,8 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx) | |||
1031 | * want it any more so deauthenticate too. | 1012 | * want it any more so deauthenticate too. |
1032 | */ | 1013 | */ |
1033 | 1014 | ||
1034 | if (!wdev->auth_bsses[idx]) | 1015 | memcpy(bssid, bss->pub.bssid, ETH_ALEN); |
1035 | return; | ||
1036 | 1016 | ||
1037 | memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); | 1017 | __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, |
1038 | if (__cfg80211_mlme_deauth(rdev, dev, bssid, | 1018 | WLAN_REASON_DEAUTH_LEAVING, false); |
1039 | NULL, 0, WLAN_REASON_DEAUTH_LEAVING, | ||
1040 | false)) { | ||
1041 | /* whatever -- assume gone anyway */ | ||
1042 | cfg80211_unhold_bss(wdev->auth_bsses[idx]); | ||
1043 | cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); | ||
1044 | wdev->auth_bsses[idx] = NULL; | ||
1045 | } | ||
1046 | } | 1019 | } |