Commit d1423c7ab847e72a63e0e3512a1a7f3bce55ae01
Committed by
David S. Miller
1 parent
f5d640371d
Exists in
master
and in
7 other branches
net: ps3_gelic: convert to hw_features
Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 3 changed files with 5 additions and 28 deletions Inline Diff
drivers/net/ps3_gelic_net.c
1 | /* | 1 | /* |
2 | * PS3 gelic network driver. | 2 | * PS3 gelic network driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
5 | * Copyright 2006, 2007 Sony Corporation | 5 | * Copyright 2006, 2007 Sony Corporation |
6 | * | 6 | * |
7 | * This file is based on: spider_net.c | 7 | * This file is based on: spider_net.c |
8 | * | 8 | * |
9 | * (C) Copyright IBM Corp. 2005 | 9 | * (C) Copyright IBM Corp. 2005 |
10 | * | 10 | * |
11 | * Authors : Utz Bacher <utz.bacher@de.ibm.com> | 11 | * Authors : Utz Bacher <utz.bacher@de.ibm.com> |
12 | * Jens Osterkamp <Jens.Osterkamp@de.ibm.com> | 12 | * Jens Osterkamp <Jens.Osterkamp@de.ibm.com> |
13 | * | 13 | * |
14 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by |
16 | * the Free Software Foundation; either version 2, or (at your option) | 16 | * the Free Software Foundation; either version 2, or (at your option) |
17 | * any later version. | 17 | * any later version. |
18 | * | 18 | * |
19 | * This program is distributed in the hope that it will be useful, | 19 | * This program is distributed in the hope that it will be useful, |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | * GNU General Public License for more details. | 22 | * GNU General Public License for more details. |
23 | * | 23 | * |
24 | * You should have received a copy of the GNU General Public License | 24 | * You should have received a copy of the GNU General Public License |
25 | * along with this program; if not, write to the Free Software | 25 | * along with this program; if not, write to the Free Software |
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #undef DEBUG | 29 | #undef DEBUG |
30 | 30 | ||
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | 34 | ||
35 | #include <linux/etherdevice.h> | 35 | #include <linux/etherdevice.h> |
36 | #include <linux/ethtool.h> | 36 | #include <linux/ethtool.h> |
37 | #include <linux/if_vlan.h> | 37 | #include <linux/if_vlan.h> |
38 | 38 | ||
39 | #include <linux/in.h> | 39 | #include <linux/in.h> |
40 | #include <linux/ip.h> | 40 | #include <linux/ip.h> |
41 | #include <linux/tcp.h> | 41 | #include <linux/tcp.h> |
42 | 42 | ||
43 | #include <linux/dma-mapping.h> | 43 | #include <linux/dma-mapping.h> |
44 | #include <net/checksum.h> | 44 | #include <net/checksum.h> |
45 | #include <asm/firmware.h> | 45 | #include <asm/firmware.h> |
46 | #include <asm/ps3.h> | 46 | #include <asm/ps3.h> |
47 | #include <asm/lv1call.h> | 47 | #include <asm/lv1call.h> |
48 | 48 | ||
49 | #include "ps3_gelic_net.h" | 49 | #include "ps3_gelic_net.h" |
50 | #include "ps3_gelic_wireless.h" | 50 | #include "ps3_gelic_wireless.h" |
51 | 51 | ||
52 | #define DRV_NAME "Gelic Network Driver" | 52 | #define DRV_NAME "Gelic Network Driver" |
53 | #define DRV_VERSION "2.0" | 53 | #define DRV_VERSION "2.0" |
54 | 54 | ||
55 | MODULE_AUTHOR("SCE Inc."); | 55 | MODULE_AUTHOR("SCE Inc."); |
56 | MODULE_DESCRIPTION("Gelic Network driver"); | 56 | MODULE_DESCRIPTION("Gelic Network driver"); |
57 | MODULE_LICENSE("GPL"); | 57 | MODULE_LICENSE("GPL"); |
58 | 58 | ||
59 | 59 | ||
60 | static inline void gelic_card_enable_rxdmac(struct gelic_card *card); | 60 | static inline void gelic_card_enable_rxdmac(struct gelic_card *card); |
61 | static inline void gelic_card_disable_rxdmac(struct gelic_card *card); | 61 | static inline void gelic_card_disable_rxdmac(struct gelic_card *card); |
62 | static inline void gelic_card_disable_txdmac(struct gelic_card *card); | 62 | static inline void gelic_card_disable_txdmac(struct gelic_card *card); |
63 | static inline void gelic_card_reset_chain(struct gelic_card *card, | 63 | static inline void gelic_card_reset_chain(struct gelic_card *card, |
64 | struct gelic_descr_chain *chain, | 64 | struct gelic_descr_chain *chain, |
65 | struct gelic_descr *start_descr); | 65 | struct gelic_descr *start_descr); |
66 | 66 | ||
67 | /* set irq_mask */ | 67 | /* set irq_mask */ |
68 | int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask) | 68 | int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask) |
69 | { | 69 | { |
70 | int status; | 70 | int status; |
71 | 71 | ||
72 | status = lv1_net_set_interrupt_mask(bus_id(card), dev_id(card), | 72 | status = lv1_net_set_interrupt_mask(bus_id(card), dev_id(card), |
73 | mask, 0); | 73 | mask, 0); |
74 | if (status) | 74 | if (status) |
75 | dev_info(ctodev(card), | 75 | dev_info(ctodev(card), |
76 | "%s failed %d\n", __func__, status); | 76 | "%s failed %d\n", __func__, status); |
77 | return status; | 77 | return status; |
78 | } | 78 | } |
79 | 79 | ||
80 | static inline void gelic_card_rx_irq_on(struct gelic_card *card) | 80 | static inline void gelic_card_rx_irq_on(struct gelic_card *card) |
81 | { | 81 | { |
82 | card->irq_mask |= GELIC_CARD_RXINT; | 82 | card->irq_mask |= GELIC_CARD_RXINT; |
83 | gelic_card_set_irq_mask(card, card->irq_mask); | 83 | gelic_card_set_irq_mask(card, card->irq_mask); |
84 | } | 84 | } |
85 | static inline void gelic_card_rx_irq_off(struct gelic_card *card) | 85 | static inline void gelic_card_rx_irq_off(struct gelic_card *card) |
86 | { | 86 | { |
87 | card->irq_mask &= ~GELIC_CARD_RXINT; | 87 | card->irq_mask &= ~GELIC_CARD_RXINT; |
88 | gelic_card_set_irq_mask(card, card->irq_mask); | 88 | gelic_card_set_irq_mask(card, card->irq_mask); |
89 | } | 89 | } |
90 | 90 | ||
91 | static void gelic_card_get_ether_port_status(struct gelic_card *card, | 91 | static void gelic_card_get_ether_port_status(struct gelic_card *card, |
92 | int inform) | 92 | int inform) |
93 | { | 93 | { |
94 | u64 v2; | 94 | u64 v2; |
95 | struct net_device *ether_netdev; | 95 | struct net_device *ether_netdev; |
96 | 96 | ||
97 | lv1_net_control(bus_id(card), dev_id(card), | 97 | lv1_net_control(bus_id(card), dev_id(card), |
98 | GELIC_LV1_GET_ETH_PORT_STATUS, | 98 | GELIC_LV1_GET_ETH_PORT_STATUS, |
99 | GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0, | 99 | GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0, |
100 | &card->ether_port_status, &v2); | 100 | &card->ether_port_status, &v2); |
101 | 101 | ||
102 | if (inform) { | 102 | if (inform) { |
103 | ether_netdev = card->netdev[GELIC_PORT_ETHERNET_0]; | 103 | ether_netdev = card->netdev[GELIC_PORT_ETHERNET_0]; |
104 | if (card->ether_port_status & GELIC_LV1_ETHER_LINK_UP) | 104 | if (card->ether_port_status & GELIC_LV1_ETHER_LINK_UP) |
105 | netif_carrier_on(ether_netdev); | 105 | netif_carrier_on(ether_netdev); |
106 | else | 106 | else |
107 | netif_carrier_off(ether_netdev); | 107 | netif_carrier_off(ether_netdev); |
108 | } | 108 | } |
109 | } | 109 | } |
110 | 110 | ||
111 | static int gelic_card_set_link_mode(struct gelic_card *card, int mode) | 111 | static int gelic_card_set_link_mode(struct gelic_card *card, int mode) |
112 | { | 112 | { |
113 | int status; | 113 | int status; |
114 | u64 v1, v2; | 114 | u64 v1, v2; |
115 | 115 | ||
116 | status = lv1_net_control(bus_id(card), dev_id(card), | 116 | status = lv1_net_control(bus_id(card), dev_id(card), |
117 | GELIC_LV1_SET_NEGOTIATION_MODE, | 117 | GELIC_LV1_SET_NEGOTIATION_MODE, |
118 | GELIC_LV1_PHY_ETHERNET_0, mode, 0, &v1, &v2); | 118 | GELIC_LV1_PHY_ETHERNET_0, mode, 0, &v1, &v2); |
119 | if (status) { | 119 | if (status) { |
120 | pr_info("%s: failed setting negotiation mode %d\n", __func__, | 120 | pr_info("%s: failed setting negotiation mode %d\n", __func__, |
121 | status); | 121 | status); |
122 | return -EBUSY; | 122 | return -EBUSY; |
123 | } | 123 | } |
124 | 124 | ||
125 | card->link_mode = mode; | 125 | card->link_mode = mode; |
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
129 | void gelic_card_up(struct gelic_card *card) | 129 | void gelic_card_up(struct gelic_card *card) |
130 | { | 130 | { |
131 | pr_debug("%s: called\n", __func__); | 131 | pr_debug("%s: called\n", __func__); |
132 | mutex_lock(&card->updown_lock); | 132 | mutex_lock(&card->updown_lock); |
133 | if (atomic_inc_return(&card->users) == 1) { | 133 | if (atomic_inc_return(&card->users) == 1) { |
134 | pr_debug("%s: real do\n", __func__); | 134 | pr_debug("%s: real do\n", __func__); |
135 | /* enable irq */ | 135 | /* enable irq */ |
136 | gelic_card_set_irq_mask(card, card->irq_mask); | 136 | gelic_card_set_irq_mask(card, card->irq_mask); |
137 | /* start rx */ | 137 | /* start rx */ |
138 | gelic_card_enable_rxdmac(card); | 138 | gelic_card_enable_rxdmac(card); |
139 | 139 | ||
140 | napi_enable(&card->napi); | 140 | napi_enable(&card->napi); |
141 | } | 141 | } |
142 | mutex_unlock(&card->updown_lock); | 142 | mutex_unlock(&card->updown_lock); |
143 | pr_debug("%s: done\n", __func__); | 143 | pr_debug("%s: done\n", __func__); |
144 | } | 144 | } |
145 | 145 | ||
146 | void gelic_card_down(struct gelic_card *card) | 146 | void gelic_card_down(struct gelic_card *card) |
147 | { | 147 | { |
148 | u64 mask; | 148 | u64 mask; |
149 | pr_debug("%s: called\n", __func__); | 149 | pr_debug("%s: called\n", __func__); |
150 | mutex_lock(&card->updown_lock); | 150 | mutex_lock(&card->updown_lock); |
151 | if (atomic_dec_if_positive(&card->users) == 0) { | 151 | if (atomic_dec_if_positive(&card->users) == 0) { |
152 | pr_debug("%s: real do\n", __func__); | 152 | pr_debug("%s: real do\n", __func__); |
153 | napi_disable(&card->napi); | 153 | napi_disable(&card->napi); |
154 | /* | 154 | /* |
155 | * Disable irq. Wireless interrupts will | 155 | * Disable irq. Wireless interrupts will |
156 | * be disabled later if any | 156 | * be disabled later if any |
157 | */ | 157 | */ |
158 | mask = card->irq_mask & (GELIC_CARD_WLAN_EVENT_RECEIVED | | 158 | mask = card->irq_mask & (GELIC_CARD_WLAN_EVENT_RECEIVED | |
159 | GELIC_CARD_WLAN_COMMAND_COMPLETED); | 159 | GELIC_CARD_WLAN_COMMAND_COMPLETED); |
160 | gelic_card_set_irq_mask(card, mask); | 160 | gelic_card_set_irq_mask(card, mask); |
161 | /* stop rx */ | 161 | /* stop rx */ |
162 | gelic_card_disable_rxdmac(card); | 162 | gelic_card_disable_rxdmac(card); |
163 | gelic_card_reset_chain(card, &card->rx_chain, | 163 | gelic_card_reset_chain(card, &card->rx_chain, |
164 | card->descr + GELIC_NET_TX_DESCRIPTORS); | 164 | card->descr + GELIC_NET_TX_DESCRIPTORS); |
165 | /* stop tx */ | 165 | /* stop tx */ |
166 | gelic_card_disable_txdmac(card); | 166 | gelic_card_disable_txdmac(card); |
167 | } | 167 | } |
168 | mutex_unlock(&card->updown_lock); | 168 | mutex_unlock(&card->updown_lock); |
169 | pr_debug("%s: done\n", __func__); | 169 | pr_debug("%s: done\n", __func__); |
170 | } | 170 | } |
171 | 171 | ||
172 | /** | 172 | /** |
173 | * gelic_descr_get_status -- returns the status of a descriptor | 173 | * gelic_descr_get_status -- returns the status of a descriptor |
174 | * @descr: descriptor to look at | 174 | * @descr: descriptor to look at |
175 | * | 175 | * |
176 | * returns the status as in the dmac_cmd_status field of the descriptor | 176 | * returns the status as in the dmac_cmd_status field of the descriptor |
177 | */ | 177 | */ |
178 | static enum gelic_descr_dma_status | 178 | static enum gelic_descr_dma_status |
179 | gelic_descr_get_status(struct gelic_descr *descr) | 179 | gelic_descr_get_status(struct gelic_descr *descr) |
180 | { | 180 | { |
181 | return be32_to_cpu(descr->dmac_cmd_status) & GELIC_DESCR_DMA_STAT_MASK; | 181 | return be32_to_cpu(descr->dmac_cmd_status) & GELIC_DESCR_DMA_STAT_MASK; |
182 | } | 182 | } |
183 | 183 | ||
184 | /** | 184 | /** |
185 | * gelic_descr_set_status -- sets the status of a descriptor | 185 | * gelic_descr_set_status -- sets the status of a descriptor |
186 | * @descr: descriptor to change | 186 | * @descr: descriptor to change |
187 | * @status: status to set in the descriptor | 187 | * @status: status to set in the descriptor |
188 | * | 188 | * |
189 | * changes the status to the specified value. Doesn't change other bits | 189 | * changes the status to the specified value. Doesn't change other bits |
190 | * in the status | 190 | * in the status |
191 | */ | 191 | */ |
192 | static void gelic_descr_set_status(struct gelic_descr *descr, | 192 | static void gelic_descr_set_status(struct gelic_descr *descr, |
193 | enum gelic_descr_dma_status status) | 193 | enum gelic_descr_dma_status status) |
194 | { | 194 | { |
195 | descr->dmac_cmd_status = cpu_to_be32(status | | 195 | descr->dmac_cmd_status = cpu_to_be32(status | |
196 | (be32_to_cpu(descr->dmac_cmd_status) & | 196 | (be32_to_cpu(descr->dmac_cmd_status) & |
197 | ~GELIC_DESCR_DMA_STAT_MASK)); | 197 | ~GELIC_DESCR_DMA_STAT_MASK)); |
198 | /* | 198 | /* |
199 | * dma_cmd_status field is used to indicate whether the descriptor | 199 | * dma_cmd_status field is used to indicate whether the descriptor |
200 | * is valid or not. | 200 | * is valid or not. |
201 | * Usually caller of this function wants to inform that to the | 201 | * Usually caller of this function wants to inform that to the |
202 | * hardware, so we assure here the hardware sees the change. | 202 | * hardware, so we assure here the hardware sees the change. |
203 | */ | 203 | */ |
204 | wmb(); | 204 | wmb(); |
205 | } | 205 | } |
206 | 206 | ||
207 | /** | 207 | /** |
208 | * gelic_card_free_chain - free descriptor chain | 208 | * gelic_card_free_chain - free descriptor chain |
209 | * @card: card structure | 209 | * @card: card structure |
210 | * @descr_in: address of desc | 210 | * @descr_in: address of desc |
211 | */ | 211 | */ |
212 | static void gelic_card_free_chain(struct gelic_card *card, | 212 | static void gelic_card_free_chain(struct gelic_card *card, |
213 | struct gelic_descr *descr_in) | 213 | struct gelic_descr *descr_in) |
214 | { | 214 | { |
215 | struct gelic_descr *descr; | 215 | struct gelic_descr *descr; |
216 | 216 | ||
217 | for (descr = descr_in; descr && descr->bus_addr; descr = descr->next) { | 217 | for (descr = descr_in; descr && descr->bus_addr; descr = descr->next) { |
218 | dma_unmap_single(ctodev(card), descr->bus_addr, | 218 | dma_unmap_single(ctodev(card), descr->bus_addr, |
219 | GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL); | 219 | GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL); |
220 | descr->bus_addr = 0; | 220 | descr->bus_addr = 0; |
221 | } | 221 | } |
222 | } | 222 | } |
223 | 223 | ||
224 | /** | 224 | /** |
225 | * gelic_card_init_chain - links descriptor chain | 225 | * gelic_card_init_chain - links descriptor chain |
226 | * @card: card structure | 226 | * @card: card structure |
227 | * @chain: address of chain | 227 | * @chain: address of chain |
228 | * @start_descr: address of descriptor array | 228 | * @start_descr: address of descriptor array |
229 | * @no: number of descriptors | 229 | * @no: number of descriptors |
230 | * | 230 | * |
231 | * we manage a circular list that mirrors the hardware structure, | 231 | * we manage a circular list that mirrors the hardware structure, |
232 | * except that the hardware uses bus addresses. | 232 | * except that the hardware uses bus addresses. |
233 | * | 233 | * |
234 | * returns 0 on success, <0 on failure | 234 | * returns 0 on success, <0 on failure |
235 | */ | 235 | */ |
236 | static int __devinit gelic_card_init_chain(struct gelic_card *card, | 236 | static int __devinit gelic_card_init_chain(struct gelic_card *card, |
237 | struct gelic_descr_chain *chain, | 237 | struct gelic_descr_chain *chain, |
238 | struct gelic_descr *start_descr, | 238 | struct gelic_descr *start_descr, |
239 | int no) | 239 | int no) |
240 | { | 240 | { |
241 | int i; | 241 | int i; |
242 | struct gelic_descr *descr; | 242 | struct gelic_descr *descr; |
243 | 243 | ||
244 | descr = start_descr; | 244 | descr = start_descr; |
245 | memset(descr, 0, sizeof(*descr) * no); | 245 | memset(descr, 0, sizeof(*descr) * no); |
246 | 246 | ||
247 | /* set up the hardware pointers in each descriptor */ | 247 | /* set up the hardware pointers in each descriptor */ |
248 | for (i = 0; i < no; i++, descr++) { | 248 | for (i = 0; i < no; i++, descr++) { |
249 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); | 249 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); |
250 | descr->bus_addr = | 250 | descr->bus_addr = |
251 | dma_map_single(ctodev(card), descr, | 251 | dma_map_single(ctodev(card), descr, |
252 | GELIC_DESCR_SIZE, | 252 | GELIC_DESCR_SIZE, |
253 | DMA_BIDIRECTIONAL); | 253 | DMA_BIDIRECTIONAL); |
254 | 254 | ||
255 | if (!descr->bus_addr) | 255 | if (!descr->bus_addr) |
256 | goto iommu_error; | 256 | goto iommu_error; |
257 | 257 | ||
258 | descr->next = descr + 1; | 258 | descr->next = descr + 1; |
259 | descr->prev = descr - 1; | 259 | descr->prev = descr - 1; |
260 | } | 260 | } |
261 | /* make them as ring */ | 261 | /* make them as ring */ |
262 | (descr - 1)->next = start_descr; | 262 | (descr - 1)->next = start_descr; |
263 | start_descr->prev = (descr - 1); | 263 | start_descr->prev = (descr - 1); |
264 | 264 | ||
265 | /* chain bus addr of hw descriptor */ | 265 | /* chain bus addr of hw descriptor */ |
266 | descr = start_descr; | 266 | descr = start_descr; |
267 | for (i = 0; i < no; i++, descr++) { | 267 | for (i = 0; i < no; i++, descr++) { |
268 | descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr); | 268 | descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr); |
269 | } | 269 | } |
270 | 270 | ||
271 | chain->head = start_descr; | 271 | chain->head = start_descr; |
272 | chain->tail = start_descr; | 272 | chain->tail = start_descr; |
273 | 273 | ||
274 | /* do not chain last hw descriptor */ | 274 | /* do not chain last hw descriptor */ |
275 | (descr - 1)->next_descr_addr = 0; | 275 | (descr - 1)->next_descr_addr = 0; |
276 | 276 | ||
277 | return 0; | 277 | return 0; |
278 | 278 | ||
279 | iommu_error: | 279 | iommu_error: |
280 | for (i--, descr--; 0 <= i; i--, descr--) | 280 | for (i--, descr--; 0 <= i; i--, descr--) |
281 | if (descr->bus_addr) | 281 | if (descr->bus_addr) |
282 | dma_unmap_single(ctodev(card), descr->bus_addr, | 282 | dma_unmap_single(ctodev(card), descr->bus_addr, |
283 | GELIC_DESCR_SIZE, | 283 | GELIC_DESCR_SIZE, |
284 | DMA_BIDIRECTIONAL); | 284 | DMA_BIDIRECTIONAL); |
285 | return -ENOMEM; | 285 | return -ENOMEM; |
286 | } | 286 | } |
287 | 287 | ||
288 | /** | 288 | /** |
289 | * gelic_card_reset_chain - reset status of a descriptor chain | 289 | * gelic_card_reset_chain - reset status of a descriptor chain |
290 | * @card: card structure | 290 | * @card: card structure |
291 | * @chain: address of chain | 291 | * @chain: address of chain |
292 | * @start_descr: address of descriptor array | 292 | * @start_descr: address of descriptor array |
293 | * | 293 | * |
294 | * Reset the status of dma descriptors to ready state | 294 | * Reset the status of dma descriptors to ready state |
295 | * and re-initialize the hardware chain for later use | 295 | * and re-initialize the hardware chain for later use |
296 | */ | 296 | */ |
297 | static void gelic_card_reset_chain(struct gelic_card *card, | 297 | static void gelic_card_reset_chain(struct gelic_card *card, |
298 | struct gelic_descr_chain *chain, | 298 | struct gelic_descr_chain *chain, |
299 | struct gelic_descr *start_descr) | 299 | struct gelic_descr *start_descr) |
300 | { | 300 | { |
301 | struct gelic_descr *descr; | 301 | struct gelic_descr *descr; |
302 | 302 | ||
303 | for (descr = start_descr; start_descr != descr->next; descr++) { | 303 | for (descr = start_descr; start_descr != descr->next; descr++) { |
304 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED); | 304 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED); |
305 | descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr); | 305 | descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr); |
306 | } | 306 | } |
307 | 307 | ||
308 | chain->head = start_descr; | 308 | chain->head = start_descr; |
309 | chain->tail = (descr - 1); | 309 | chain->tail = (descr - 1); |
310 | 310 | ||
311 | (descr - 1)->next_descr_addr = 0; | 311 | (descr - 1)->next_descr_addr = 0; |
312 | } | 312 | } |
313 | /** | 313 | /** |
314 | * gelic_descr_prepare_rx - reinitializes a rx descriptor | 314 | * gelic_descr_prepare_rx - reinitializes a rx descriptor |
315 | * @card: card structure | 315 | * @card: card structure |
316 | * @descr: descriptor to re-init | 316 | * @descr: descriptor to re-init |
317 | * | 317 | * |
318 | * return 0 on success, <0 on failure | 318 | * return 0 on success, <0 on failure |
319 | * | 319 | * |
320 | * allocates a new rx skb, iommu-maps it and attaches it to the descriptor. | 320 | * allocates a new rx skb, iommu-maps it and attaches it to the descriptor. |
321 | * Activate the descriptor state-wise | 321 | * Activate the descriptor state-wise |
322 | */ | 322 | */ |
323 | static int gelic_descr_prepare_rx(struct gelic_card *card, | 323 | static int gelic_descr_prepare_rx(struct gelic_card *card, |
324 | struct gelic_descr *descr) | 324 | struct gelic_descr *descr) |
325 | { | 325 | { |
326 | int offset; | 326 | int offset; |
327 | unsigned int bufsize; | 327 | unsigned int bufsize; |
328 | 328 | ||
329 | if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE) | 329 | if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE) |
330 | dev_info(ctodev(card), "%s: ERROR status\n", __func__); | 330 | dev_info(ctodev(card), "%s: ERROR status\n", __func__); |
331 | /* we need to round up the buffer size to a multiple of 128 */ | 331 | /* we need to round up the buffer size to a multiple of 128 */ |
332 | bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN); | 332 | bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN); |
333 | 333 | ||
334 | /* and we need to have it 128 byte aligned, therefore we allocate a | 334 | /* and we need to have it 128 byte aligned, therefore we allocate a |
335 | * bit more */ | 335 | * bit more */ |
336 | descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1); | 336 | descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1); |
337 | if (!descr->skb) { | 337 | if (!descr->skb) { |
338 | descr->buf_addr = 0; /* tell DMAC don't touch memory */ | 338 | descr->buf_addr = 0; /* tell DMAC don't touch memory */ |
339 | dev_info(ctodev(card), | 339 | dev_info(ctodev(card), |
340 | "%s:allocate skb failed !!\n", __func__); | 340 | "%s:allocate skb failed !!\n", __func__); |
341 | return -ENOMEM; | 341 | return -ENOMEM; |
342 | } | 342 | } |
343 | descr->buf_size = cpu_to_be32(bufsize); | 343 | descr->buf_size = cpu_to_be32(bufsize); |
344 | descr->dmac_cmd_status = 0; | 344 | descr->dmac_cmd_status = 0; |
345 | descr->result_size = 0; | 345 | descr->result_size = 0; |
346 | descr->valid_size = 0; | 346 | descr->valid_size = 0; |
347 | descr->data_error = 0; | 347 | descr->data_error = 0; |
348 | 348 | ||
349 | offset = ((unsigned long)descr->skb->data) & | 349 | offset = ((unsigned long)descr->skb->data) & |
350 | (GELIC_NET_RXBUF_ALIGN - 1); | 350 | (GELIC_NET_RXBUF_ALIGN - 1); |
351 | if (offset) | 351 | if (offset) |
352 | skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset); | 352 | skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset); |
353 | /* io-mmu-map the skb */ | 353 | /* io-mmu-map the skb */ |
354 | descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card), | 354 | descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card), |
355 | descr->skb->data, | 355 | descr->skb->data, |
356 | GELIC_NET_MAX_MTU, | 356 | GELIC_NET_MAX_MTU, |
357 | DMA_FROM_DEVICE)); | 357 | DMA_FROM_DEVICE)); |
358 | if (!descr->buf_addr) { | 358 | if (!descr->buf_addr) { |
359 | dev_kfree_skb_any(descr->skb); | 359 | dev_kfree_skb_any(descr->skb); |
360 | descr->skb = NULL; | 360 | descr->skb = NULL; |
361 | dev_info(ctodev(card), | 361 | dev_info(ctodev(card), |
362 | "%s:Could not iommu-map rx buffer\n", __func__); | 362 | "%s:Could not iommu-map rx buffer\n", __func__); |
363 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); | 363 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); |
364 | return -ENOMEM; | 364 | return -ENOMEM; |
365 | } else { | 365 | } else { |
366 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED); | 366 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED); |
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | } | 369 | } |
370 | 370 | ||
371 | /** | 371 | /** |
372 | * gelic_card_release_rx_chain - free all skb of rx descr | 372 | * gelic_card_release_rx_chain - free all skb of rx descr |
373 | * @card: card structure | 373 | * @card: card structure |
374 | * | 374 | * |
375 | */ | 375 | */ |
376 | static void gelic_card_release_rx_chain(struct gelic_card *card) | 376 | static void gelic_card_release_rx_chain(struct gelic_card *card) |
377 | { | 377 | { |
378 | struct gelic_descr *descr = card->rx_chain.head; | 378 | struct gelic_descr *descr = card->rx_chain.head; |
379 | 379 | ||
380 | do { | 380 | do { |
381 | if (descr->skb) { | 381 | if (descr->skb) { |
382 | dma_unmap_single(ctodev(card), | 382 | dma_unmap_single(ctodev(card), |
383 | be32_to_cpu(descr->buf_addr), | 383 | be32_to_cpu(descr->buf_addr), |
384 | descr->skb->len, | 384 | descr->skb->len, |
385 | DMA_FROM_DEVICE); | 385 | DMA_FROM_DEVICE); |
386 | descr->buf_addr = 0; | 386 | descr->buf_addr = 0; |
387 | dev_kfree_skb_any(descr->skb); | 387 | dev_kfree_skb_any(descr->skb); |
388 | descr->skb = NULL; | 388 | descr->skb = NULL; |
389 | gelic_descr_set_status(descr, | 389 | gelic_descr_set_status(descr, |
390 | GELIC_DESCR_DMA_NOT_IN_USE); | 390 | GELIC_DESCR_DMA_NOT_IN_USE); |
391 | } | 391 | } |
392 | descr = descr->next; | 392 | descr = descr->next; |
393 | } while (descr != card->rx_chain.head); | 393 | } while (descr != card->rx_chain.head); |
394 | } | 394 | } |
395 | 395 | ||
396 | /** | 396 | /** |
397 | * gelic_card_fill_rx_chain - fills descriptors/skbs in the rx chains | 397 | * gelic_card_fill_rx_chain - fills descriptors/skbs in the rx chains |
398 | * @card: card structure | 398 | * @card: card structure |
399 | * | 399 | * |
400 | * fills all descriptors in the rx chain: allocates skbs | 400 | * fills all descriptors in the rx chain: allocates skbs |
401 | * and iommu-maps them. | 401 | * and iommu-maps them. |
402 | * returns 0 on success, < 0 on failure | 402 | * returns 0 on success, < 0 on failure |
403 | */ | 403 | */ |
404 | static int gelic_card_fill_rx_chain(struct gelic_card *card) | 404 | static int gelic_card_fill_rx_chain(struct gelic_card *card) |
405 | { | 405 | { |
406 | struct gelic_descr *descr = card->rx_chain.head; | 406 | struct gelic_descr *descr = card->rx_chain.head; |
407 | int ret; | 407 | int ret; |
408 | 408 | ||
409 | do { | 409 | do { |
410 | if (!descr->skb) { | 410 | if (!descr->skb) { |
411 | ret = gelic_descr_prepare_rx(card, descr); | 411 | ret = gelic_descr_prepare_rx(card, descr); |
412 | if (ret) | 412 | if (ret) |
413 | goto rewind; | 413 | goto rewind; |
414 | } | 414 | } |
415 | descr = descr->next; | 415 | descr = descr->next; |
416 | } while (descr != card->rx_chain.head); | 416 | } while (descr != card->rx_chain.head); |
417 | 417 | ||
418 | return 0; | 418 | return 0; |
419 | rewind: | 419 | rewind: |
420 | gelic_card_release_rx_chain(card); | 420 | gelic_card_release_rx_chain(card); |
421 | return ret; | 421 | return ret; |
422 | } | 422 | } |
423 | 423 | ||
424 | /** | 424 | /** |
425 | * gelic_card_alloc_rx_skbs - allocates rx skbs in rx descriptor chains | 425 | * gelic_card_alloc_rx_skbs - allocates rx skbs in rx descriptor chains |
426 | * @card: card structure | 426 | * @card: card structure |
427 | * | 427 | * |
428 | * returns 0 on success, < 0 on failure | 428 | * returns 0 on success, < 0 on failure |
429 | */ | 429 | */ |
430 | static int __devinit gelic_card_alloc_rx_skbs(struct gelic_card *card) | 430 | static int __devinit gelic_card_alloc_rx_skbs(struct gelic_card *card) |
431 | { | 431 | { |
432 | struct gelic_descr_chain *chain; | 432 | struct gelic_descr_chain *chain; |
433 | int ret; | 433 | int ret; |
434 | chain = &card->rx_chain; | 434 | chain = &card->rx_chain; |
435 | ret = gelic_card_fill_rx_chain(card); | 435 | ret = gelic_card_fill_rx_chain(card); |
436 | chain->tail = card->rx_top->prev; /* point to the last */ | 436 | chain->tail = card->rx_top->prev; /* point to the last */ |
437 | return ret; | 437 | return ret; |
438 | } | 438 | } |
439 | 439 | ||
440 | /** | 440 | /** |
441 | * gelic_descr_release_tx - processes a used tx descriptor | 441 | * gelic_descr_release_tx - processes a used tx descriptor |
442 | * @card: card structure | 442 | * @card: card structure |
443 | * @descr: descriptor to release | 443 | * @descr: descriptor to release |
444 | * | 444 | * |
445 | * releases a used tx descriptor (unmapping, freeing of skb) | 445 | * releases a used tx descriptor (unmapping, freeing of skb) |
446 | */ | 446 | */ |
447 | static void gelic_descr_release_tx(struct gelic_card *card, | 447 | static void gelic_descr_release_tx(struct gelic_card *card, |
448 | struct gelic_descr *descr) | 448 | struct gelic_descr *descr) |
449 | { | 449 | { |
450 | struct sk_buff *skb = descr->skb; | 450 | struct sk_buff *skb = descr->skb; |
451 | 451 | ||
452 | BUG_ON(!(be32_to_cpu(descr->data_status) & GELIC_DESCR_TX_TAIL)); | 452 | BUG_ON(!(be32_to_cpu(descr->data_status) & GELIC_DESCR_TX_TAIL)); |
453 | 453 | ||
454 | dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), skb->len, | 454 | dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), skb->len, |
455 | DMA_TO_DEVICE); | 455 | DMA_TO_DEVICE); |
456 | dev_kfree_skb_any(skb); | 456 | dev_kfree_skb_any(skb); |
457 | 457 | ||
458 | descr->buf_addr = 0; | 458 | descr->buf_addr = 0; |
459 | descr->buf_size = 0; | 459 | descr->buf_size = 0; |
460 | descr->next_descr_addr = 0; | 460 | descr->next_descr_addr = 0; |
461 | descr->result_size = 0; | 461 | descr->result_size = 0; |
462 | descr->valid_size = 0; | 462 | descr->valid_size = 0; |
463 | descr->data_status = 0; | 463 | descr->data_status = 0; |
464 | descr->data_error = 0; | 464 | descr->data_error = 0; |
465 | descr->skb = NULL; | 465 | descr->skb = NULL; |
466 | 466 | ||
467 | /* set descr status */ | 467 | /* set descr status */ |
468 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); | 468 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); |
469 | } | 469 | } |
470 | 470 | ||
471 | static void gelic_card_stop_queues(struct gelic_card *card) | 471 | static void gelic_card_stop_queues(struct gelic_card *card) |
472 | { | 472 | { |
473 | netif_stop_queue(card->netdev[GELIC_PORT_ETHERNET_0]); | 473 | netif_stop_queue(card->netdev[GELIC_PORT_ETHERNET_0]); |
474 | 474 | ||
475 | if (card->netdev[GELIC_PORT_WIRELESS]) | 475 | if (card->netdev[GELIC_PORT_WIRELESS]) |
476 | netif_stop_queue(card->netdev[GELIC_PORT_WIRELESS]); | 476 | netif_stop_queue(card->netdev[GELIC_PORT_WIRELESS]); |
477 | } | 477 | } |
478 | static void gelic_card_wake_queues(struct gelic_card *card) | 478 | static void gelic_card_wake_queues(struct gelic_card *card) |
479 | { | 479 | { |
480 | netif_wake_queue(card->netdev[GELIC_PORT_ETHERNET_0]); | 480 | netif_wake_queue(card->netdev[GELIC_PORT_ETHERNET_0]); |
481 | 481 | ||
482 | if (card->netdev[GELIC_PORT_WIRELESS]) | 482 | if (card->netdev[GELIC_PORT_WIRELESS]) |
483 | netif_wake_queue(card->netdev[GELIC_PORT_WIRELESS]); | 483 | netif_wake_queue(card->netdev[GELIC_PORT_WIRELESS]); |
484 | } | 484 | } |
485 | /** | 485 | /** |
486 | * gelic_card_release_tx_chain - processes sent tx descriptors | 486 | * gelic_card_release_tx_chain - processes sent tx descriptors |
487 | * @card: adapter structure | 487 | * @card: adapter structure |
488 | * @stop: net_stop sequence | 488 | * @stop: net_stop sequence |
489 | * | 489 | * |
490 | * releases the tx descriptors that gelic has finished with | 490 | * releases the tx descriptors that gelic has finished with |
491 | */ | 491 | */ |
492 | static void gelic_card_release_tx_chain(struct gelic_card *card, int stop) | 492 | static void gelic_card_release_tx_chain(struct gelic_card *card, int stop) |
493 | { | 493 | { |
494 | struct gelic_descr_chain *tx_chain; | 494 | struct gelic_descr_chain *tx_chain; |
495 | enum gelic_descr_dma_status status; | 495 | enum gelic_descr_dma_status status; |
496 | struct net_device *netdev; | 496 | struct net_device *netdev; |
497 | int release = 0; | 497 | int release = 0; |
498 | 498 | ||
499 | for (tx_chain = &card->tx_chain; | 499 | for (tx_chain = &card->tx_chain; |
500 | tx_chain->head != tx_chain->tail && tx_chain->tail; | 500 | tx_chain->head != tx_chain->tail && tx_chain->tail; |
501 | tx_chain->tail = tx_chain->tail->next) { | 501 | tx_chain->tail = tx_chain->tail->next) { |
502 | status = gelic_descr_get_status(tx_chain->tail); | 502 | status = gelic_descr_get_status(tx_chain->tail); |
503 | netdev = tx_chain->tail->skb->dev; | 503 | netdev = tx_chain->tail->skb->dev; |
504 | switch (status) { | 504 | switch (status) { |
505 | case GELIC_DESCR_DMA_RESPONSE_ERROR: | 505 | case GELIC_DESCR_DMA_RESPONSE_ERROR: |
506 | case GELIC_DESCR_DMA_PROTECTION_ERROR: | 506 | case GELIC_DESCR_DMA_PROTECTION_ERROR: |
507 | case GELIC_DESCR_DMA_FORCE_END: | 507 | case GELIC_DESCR_DMA_FORCE_END: |
508 | if (printk_ratelimit()) | 508 | if (printk_ratelimit()) |
509 | dev_info(ctodev(card), | 509 | dev_info(ctodev(card), |
510 | "%s: forcing end of tx descriptor " \ | 510 | "%s: forcing end of tx descriptor " \ |
511 | "with status %x\n", | 511 | "with status %x\n", |
512 | __func__, status); | 512 | __func__, status); |
513 | netdev->stats.tx_dropped++; | 513 | netdev->stats.tx_dropped++; |
514 | break; | 514 | break; |
515 | 515 | ||
516 | case GELIC_DESCR_DMA_COMPLETE: | 516 | case GELIC_DESCR_DMA_COMPLETE: |
517 | if (tx_chain->tail->skb) { | 517 | if (tx_chain->tail->skb) { |
518 | netdev->stats.tx_packets++; | 518 | netdev->stats.tx_packets++; |
519 | netdev->stats.tx_bytes += | 519 | netdev->stats.tx_bytes += |
520 | tx_chain->tail->skb->len; | 520 | tx_chain->tail->skb->len; |
521 | } | 521 | } |
522 | break; | 522 | break; |
523 | 523 | ||
524 | case GELIC_DESCR_DMA_CARDOWNED: | 524 | case GELIC_DESCR_DMA_CARDOWNED: |
525 | /* pending tx request */ | 525 | /* pending tx request */ |
526 | default: | 526 | default: |
527 | /* any other value (== GELIC_DESCR_DMA_NOT_IN_USE) */ | 527 | /* any other value (== GELIC_DESCR_DMA_NOT_IN_USE) */ |
528 | if (!stop) | 528 | if (!stop) |
529 | goto out; | 529 | goto out; |
530 | } | 530 | } |
531 | gelic_descr_release_tx(card, tx_chain->tail); | 531 | gelic_descr_release_tx(card, tx_chain->tail); |
532 | release ++; | 532 | release ++; |
533 | } | 533 | } |
534 | out: | 534 | out: |
535 | if (!stop && release) | 535 | if (!stop && release) |
536 | gelic_card_wake_queues(card); | 536 | gelic_card_wake_queues(card); |
537 | } | 537 | } |
538 | 538 | ||
539 | /** | 539 | /** |
540 | * gelic_net_set_multi - sets multicast addresses and promisc flags | 540 | * gelic_net_set_multi - sets multicast addresses and promisc flags |
541 | * @netdev: interface device structure | 541 | * @netdev: interface device structure |
542 | * | 542 | * |
543 | * gelic_net_set_multi configures multicast addresses as needed for the | 543 | * gelic_net_set_multi configures multicast addresses as needed for the |
544 | * netdev interface. It also sets up multicast, allmulti and promisc | 544 | * netdev interface. It also sets up multicast, allmulti and promisc |
545 | * flags appropriately | 545 | * flags appropriately |
546 | */ | 546 | */ |
547 | void gelic_net_set_multi(struct net_device *netdev) | 547 | void gelic_net_set_multi(struct net_device *netdev) |
548 | { | 548 | { |
549 | struct gelic_card *card = netdev_card(netdev); | 549 | struct gelic_card *card = netdev_card(netdev); |
550 | struct netdev_hw_addr *ha; | 550 | struct netdev_hw_addr *ha; |
551 | unsigned int i; | 551 | unsigned int i; |
552 | uint8_t *p; | 552 | uint8_t *p; |
553 | u64 addr; | 553 | u64 addr; |
554 | int status; | 554 | int status; |
555 | 555 | ||
556 | /* clear all multicast address */ | 556 | /* clear all multicast address */ |
557 | status = lv1_net_remove_multicast_address(bus_id(card), dev_id(card), | 557 | status = lv1_net_remove_multicast_address(bus_id(card), dev_id(card), |
558 | 0, 1); | 558 | 0, 1); |
559 | if (status) | 559 | if (status) |
560 | dev_err(ctodev(card), | 560 | dev_err(ctodev(card), |
561 | "lv1_net_remove_multicast_address failed %d\n", | 561 | "lv1_net_remove_multicast_address failed %d\n", |
562 | status); | 562 | status); |
563 | /* set broadcast address */ | 563 | /* set broadcast address */ |
564 | status = lv1_net_add_multicast_address(bus_id(card), dev_id(card), | 564 | status = lv1_net_add_multicast_address(bus_id(card), dev_id(card), |
565 | GELIC_NET_BROADCAST_ADDR, 0); | 565 | GELIC_NET_BROADCAST_ADDR, 0); |
566 | if (status) | 566 | if (status) |
567 | dev_err(ctodev(card), | 567 | dev_err(ctodev(card), |
568 | "lv1_net_add_multicast_address failed, %d\n", | 568 | "lv1_net_add_multicast_address failed, %d\n", |
569 | status); | 569 | status); |
570 | 570 | ||
571 | if ((netdev->flags & IFF_ALLMULTI) || | 571 | if ((netdev->flags & IFF_ALLMULTI) || |
572 | (netdev_mc_count(netdev) > GELIC_NET_MC_COUNT_MAX)) { | 572 | (netdev_mc_count(netdev) > GELIC_NET_MC_COUNT_MAX)) { |
573 | status = lv1_net_add_multicast_address(bus_id(card), | 573 | status = lv1_net_add_multicast_address(bus_id(card), |
574 | dev_id(card), | 574 | dev_id(card), |
575 | 0, 1); | 575 | 0, 1); |
576 | if (status) | 576 | if (status) |
577 | dev_err(ctodev(card), | 577 | dev_err(ctodev(card), |
578 | "lv1_net_add_multicast_address failed, %d\n", | 578 | "lv1_net_add_multicast_address failed, %d\n", |
579 | status); | 579 | status); |
580 | return; | 580 | return; |
581 | } | 581 | } |
582 | 582 | ||
583 | /* set multicast addresses */ | 583 | /* set multicast addresses */ |
584 | netdev_for_each_mc_addr(ha, netdev) { | 584 | netdev_for_each_mc_addr(ha, netdev) { |
585 | addr = 0; | 585 | addr = 0; |
586 | p = ha->addr; | 586 | p = ha->addr; |
587 | for (i = 0; i < ETH_ALEN; i++) { | 587 | for (i = 0; i < ETH_ALEN; i++) { |
588 | addr <<= 8; | 588 | addr <<= 8; |
589 | addr |= *p++; | 589 | addr |= *p++; |
590 | } | 590 | } |
591 | status = lv1_net_add_multicast_address(bus_id(card), | 591 | status = lv1_net_add_multicast_address(bus_id(card), |
592 | dev_id(card), | 592 | dev_id(card), |
593 | addr, 0); | 593 | addr, 0); |
594 | if (status) | 594 | if (status) |
595 | dev_err(ctodev(card), | 595 | dev_err(ctodev(card), |
596 | "lv1_net_add_multicast_address failed, %d\n", | 596 | "lv1_net_add_multicast_address failed, %d\n", |
597 | status); | 597 | status); |
598 | } | 598 | } |
599 | } | 599 | } |
600 | 600 | ||
601 | /** | 601 | /** |
602 | * gelic_card_enable_rxdmac - enables the receive DMA controller | 602 | * gelic_card_enable_rxdmac - enables the receive DMA controller |
603 | * @card: card structure | 603 | * @card: card structure |
604 | * | 604 | * |
605 | * gelic_card_enable_rxdmac enables the DMA controller by setting RX_DMA_EN | 605 | * gelic_card_enable_rxdmac enables the DMA controller by setting RX_DMA_EN |
606 | * in the GDADMACCNTR register | 606 | * in the GDADMACCNTR register |
607 | */ | 607 | */ |
608 | static inline void gelic_card_enable_rxdmac(struct gelic_card *card) | 608 | static inline void gelic_card_enable_rxdmac(struct gelic_card *card) |
609 | { | 609 | { |
610 | int status; | 610 | int status; |
611 | 611 | ||
612 | #ifdef DEBUG | 612 | #ifdef DEBUG |
613 | if (gelic_descr_get_status(card->rx_chain.head) != | 613 | if (gelic_descr_get_status(card->rx_chain.head) != |
614 | GELIC_DESCR_DMA_CARDOWNED) { | 614 | GELIC_DESCR_DMA_CARDOWNED) { |
615 | printk(KERN_ERR "%s: status=%x\n", __func__, | 615 | printk(KERN_ERR "%s: status=%x\n", __func__, |
616 | be32_to_cpu(card->rx_chain.head->dmac_cmd_status)); | 616 | be32_to_cpu(card->rx_chain.head->dmac_cmd_status)); |
617 | printk(KERN_ERR "%s: nextphy=%x\n", __func__, | 617 | printk(KERN_ERR "%s: nextphy=%x\n", __func__, |
618 | be32_to_cpu(card->rx_chain.head->next_descr_addr)); | 618 | be32_to_cpu(card->rx_chain.head->next_descr_addr)); |
619 | printk(KERN_ERR "%s: head=%p\n", __func__, | 619 | printk(KERN_ERR "%s: head=%p\n", __func__, |
620 | card->rx_chain.head); | 620 | card->rx_chain.head); |
621 | } | 621 | } |
622 | #endif | 622 | #endif |
623 | status = lv1_net_start_rx_dma(bus_id(card), dev_id(card), | 623 | status = lv1_net_start_rx_dma(bus_id(card), dev_id(card), |
624 | card->rx_chain.head->bus_addr, 0); | 624 | card->rx_chain.head->bus_addr, 0); |
625 | if (status) | 625 | if (status) |
626 | dev_info(ctodev(card), | 626 | dev_info(ctodev(card), |
627 | "lv1_net_start_rx_dma failed, status=%d\n", status); | 627 | "lv1_net_start_rx_dma failed, status=%d\n", status); |
628 | } | 628 | } |
629 | 629 | ||
630 | /** | 630 | /** |
631 | * gelic_card_disable_rxdmac - disables the receive DMA controller | 631 | * gelic_card_disable_rxdmac - disables the receive DMA controller |
632 | * @card: card structure | 632 | * @card: card structure |
633 | * | 633 | * |
634 | * gelic_card_disable_rxdmac terminates processing on the DMA controller by | 634 | * gelic_card_disable_rxdmac terminates processing on the DMA controller by |
635 | * turing off DMA and issuing a force end | 635 | * turing off DMA and issuing a force end |
636 | */ | 636 | */ |
637 | static inline void gelic_card_disable_rxdmac(struct gelic_card *card) | 637 | static inline void gelic_card_disable_rxdmac(struct gelic_card *card) |
638 | { | 638 | { |
639 | int status; | 639 | int status; |
640 | 640 | ||
641 | /* this hvc blocks until the DMA in progress really stopped */ | 641 | /* this hvc blocks until the DMA in progress really stopped */ |
642 | status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card), 0); | 642 | status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card), 0); |
643 | if (status) | 643 | if (status) |
644 | dev_err(ctodev(card), | 644 | dev_err(ctodev(card), |
645 | "lv1_net_stop_rx_dma failed, %d\n", status); | 645 | "lv1_net_stop_rx_dma failed, %d\n", status); |
646 | } | 646 | } |
647 | 647 | ||
648 | /** | 648 | /** |
649 | * gelic_card_disable_txdmac - disables the transmit DMA controller | 649 | * gelic_card_disable_txdmac - disables the transmit DMA controller |
650 | * @card: card structure | 650 | * @card: card structure |
651 | * | 651 | * |
652 | * gelic_card_disable_txdmac terminates processing on the DMA controller by | 652 | * gelic_card_disable_txdmac terminates processing on the DMA controller by |
653 | * turing off DMA and issuing a force end | 653 | * turing off DMA and issuing a force end |
654 | */ | 654 | */ |
655 | static inline void gelic_card_disable_txdmac(struct gelic_card *card) | 655 | static inline void gelic_card_disable_txdmac(struct gelic_card *card) |
656 | { | 656 | { |
657 | int status; | 657 | int status; |
658 | 658 | ||
659 | /* this hvc blocks until the DMA in progress really stopped */ | 659 | /* this hvc blocks until the DMA in progress really stopped */ |
660 | status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0); | 660 | status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0); |
661 | if (status) | 661 | if (status) |
662 | dev_err(ctodev(card), | 662 | dev_err(ctodev(card), |
663 | "lv1_net_stop_tx_dma failed, status=%d\n", status); | 663 | "lv1_net_stop_tx_dma failed, status=%d\n", status); |
664 | } | 664 | } |
665 | 665 | ||
666 | /** | 666 | /** |
667 | * gelic_net_stop - called upon ifconfig down | 667 | * gelic_net_stop - called upon ifconfig down |
668 | * @netdev: interface device structure | 668 | * @netdev: interface device structure |
669 | * | 669 | * |
670 | * always returns 0 | 670 | * always returns 0 |
671 | */ | 671 | */ |
672 | int gelic_net_stop(struct net_device *netdev) | 672 | int gelic_net_stop(struct net_device *netdev) |
673 | { | 673 | { |
674 | struct gelic_card *card; | 674 | struct gelic_card *card; |
675 | 675 | ||
676 | pr_debug("%s: start\n", __func__); | 676 | pr_debug("%s: start\n", __func__); |
677 | 677 | ||
678 | netif_stop_queue(netdev); | 678 | netif_stop_queue(netdev); |
679 | netif_carrier_off(netdev); | 679 | netif_carrier_off(netdev); |
680 | 680 | ||
681 | card = netdev_card(netdev); | 681 | card = netdev_card(netdev); |
682 | gelic_card_down(card); | 682 | gelic_card_down(card); |
683 | 683 | ||
684 | pr_debug("%s: done\n", __func__); | 684 | pr_debug("%s: done\n", __func__); |
685 | return 0; | 685 | return 0; |
686 | } | 686 | } |
687 | 687 | ||
688 | /** | 688 | /** |
689 | * gelic_card_get_next_tx_descr - returns the next available tx descriptor | 689 | * gelic_card_get_next_tx_descr - returns the next available tx descriptor |
690 | * @card: device structure to get descriptor from | 690 | * @card: device structure to get descriptor from |
691 | * | 691 | * |
692 | * returns the address of the next descriptor, or NULL if not available. | 692 | * returns the address of the next descriptor, or NULL if not available. |
693 | */ | 693 | */ |
694 | static struct gelic_descr * | 694 | static struct gelic_descr * |
695 | gelic_card_get_next_tx_descr(struct gelic_card *card) | 695 | gelic_card_get_next_tx_descr(struct gelic_card *card) |
696 | { | 696 | { |
697 | if (!card->tx_chain.head) | 697 | if (!card->tx_chain.head) |
698 | return NULL; | 698 | return NULL; |
699 | /* see if the next descriptor is free */ | 699 | /* see if the next descriptor is free */ |
700 | if (card->tx_chain.tail != card->tx_chain.head->next && | 700 | if (card->tx_chain.tail != card->tx_chain.head->next && |
701 | gelic_descr_get_status(card->tx_chain.head) == | 701 | gelic_descr_get_status(card->tx_chain.head) == |
702 | GELIC_DESCR_DMA_NOT_IN_USE) | 702 | GELIC_DESCR_DMA_NOT_IN_USE) |
703 | return card->tx_chain.head; | 703 | return card->tx_chain.head; |
704 | else | 704 | else |
705 | return NULL; | 705 | return NULL; |
706 | 706 | ||
707 | } | 707 | } |
708 | 708 | ||
709 | /** | 709 | /** |
710 | * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field | 710 | * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field |
711 | * @descr: descriptor structure to fill out | 711 | * @descr: descriptor structure to fill out |
712 | * @skb: packet to consider | 712 | * @skb: packet to consider |
713 | * | 713 | * |
714 | * fills out the command and status field of the descriptor structure, | 714 | * fills out the command and status field of the descriptor structure, |
715 | * depending on hardware checksum settings. This function assumes a wmb() | 715 | * depending on hardware checksum settings. This function assumes a wmb() |
716 | * has executed before. | 716 | * has executed before. |
717 | */ | 717 | */ |
718 | static void gelic_descr_set_tx_cmdstat(struct gelic_descr *descr, | 718 | static void gelic_descr_set_tx_cmdstat(struct gelic_descr *descr, |
719 | struct sk_buff *skb) | 719 | struct sk_buff *skb) |
720 | { | 720 | { |
721 | if (skb->ip_summed != CHECKSUM_PARTIAL) | 721 | if (skb->ip_summed != CHECKSUM_PARTIAL) |
722 | descr->dmac_cmd_status = | 722 | descr->dmac_cmd_status = |
723 | cpu_to_be32(GELIC_DESCR_DMA_CMD_NO_CHKSUM | | 723 | cpu_to_be32(GELIC_DESCR_DMA_CMD_NO_CHKSUM | |
724 | GELIC_DESCR_TX_DMA_FRAME_TAIL); | 724 | GELIC_DESCR_TX_DMA_FRAME_TAIL); |
725 | else { | 725 | else { |
726 | /* is packet ip? | 726 | /* is packet ip? |
727 | * if yes: tcp? udp? */ | 727 | * if yes: tcp? udp? */ |
728 | if (skb->protocol == htons(ETH_P_IP)) { | 728 | if (skb->protocol == htons(ETH_P_IP)) { |
729 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) | 729 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) |
730 | descr->dmac_cmd_status = | 730 | descr->dmac_cmd_status = |
731 | cpu_to_be32(GELIC_DESCR_DMA_CMD_TCP_CHKSUM | | 731 | cpu_to_be32(GELIC_DESCR_DMA_CMD_TCP_CHKSUM | |
732 | GELIC_DESCR_TX_DMA_FRAME_TAIL); | 732 | GELIC_DESCR_TX_DMA_FRAME_TAIL); |
733 | 733 | ||
734 | else if (ip_hdr(skb)->protocol == IPPROTO_UDP) | 734 | else if (ip_hdr(skb)->protocol == IPPROTO_UDP) |
735 | descr->dmac_cmd_status = | 735 | descr->dmac_cmd_status = |
736 | cpu_to_be32(GELIC_DESCR_DMA_CMD_UDP_CHKSUM | | 736 | cpu_to_be32(GELIC_DESCR_DMA_CMD_UDP_CHKSUM | |
737 | GELIC_DESCR_TX_DMA_FRAME_TAIL); | 737 | GELIC_DESCR_TX_DMA_FRAME_TAIL); |
738 | else /* | 738 | else /* |
739 | * the stack should checksum non-tcp and non-udp | 739 | * the stack should checksum non-tcp and non-udp |
740 | * packets on his own: NETIF_F_IP_CSUM | 740 | * packets on his own: NETIF_F_IP_CSUM |
741 | */ | 741 | */ |
742 | descr->dmac_cmd_status = | 742 | descr->dmac_cmd_status = |
743 | cpu_to_be32(GELIC_DESCR_DMA_CMD_NO_CHKSUM | | 743 | cpu_to_be32(GELIC_DESCR_DMA_CMD_NO_CHKSUM | |
744 | GELIC_DESCR_TX_DMA_FRAME_TAIL); | 744 | GELIC_DESCR_TX_DMA_FRAME_TAIL); |
745 | } | 745 | } |
746 | } | 746 | } |
747 | } | 747 | } |
748 | 748 | ||
749 | static inline struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb, | 749 | static inline struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb, |
750 | unsigned short tag) | 750 | unsigned short tag) |
751 | { | 751 | { |
752 | struct vlan_ethhdr *veth; | 752 | struct vlan_ethhdr *veth; |
753 | static unsigned int c; | 753 | static unsigned int c; |
754 | 754 | ||
755 | if (skb_headroom(skb) < VLAN_HLEN) { | 755 | if (skb_headroom(skb) < VLAN_HLEN) { |
756 | struct sk_buff *sk_tmp = skb; | 756 | struct sk_buff *sk_tmp = skb; |
757 | pr_debug("%s: hd=%d c=%ud\n", __func__, skb_headroom(skb), c); | 757 | pr_debug("%s: hd=%d c=%ud\n", __func__, skb_headroom(skb), c); |
758 | skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN); | 758 | skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN); |
759 | if (!skb) | 759 | if (!skb) |
760 | return NULL; | 760 | return NULL; |
761 | dev_kfree_skb_any(sk_tmp); | 761 | dev_kfree_skb_any(sk_tmp); |
762 | } | 762 | } |
763 | veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); | 763 | veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); |
764 | 764 | ||
765 | /* Move the mac addresses to the top of buffer */ | 765 | /* Move the mac addresses to the top of buffer */ |
766 | memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); | 766 | memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); |
767 | 767 | ||
768 | veth->h_vlan_proto = cpu_to_be16(ETH_P_8021Q); | 768 | veth->h_vlan_proto = cpu_to_be16(ETH_P_8021Q); |
769 | veth->h_vlan_TCI = htons(tag); | 769 | veth->h_vlan_TCI = htons(tag); |
770 | 770 | ||
771 | return skb; | 771 | return skb; |
772 | } | 772 | } |
773 | 773 | ||
774 | /** | 774 | /** |
775 | * gelic_descr_prepare_tx - setup a descriptor for sending packets | 775 | * gelic_descr_prepare_tx - setup a descriptor for sending packets |
776 | * @card: card structure | 776 | * @card: card structure |
777 | * @descr: descriptor structure | 777 | * @descr: descriptor structure |
778 | * @skb: packet to use | 778 | * @skb: packet to use |
779 | * | 779 | * |
780 | * returns 0 on success, <0 on failure. | 780 | * returns 0 on success, <0 on failure. |
781 | * | 781 | * |
782 | */ | 782 | */ |
783 | static int gelic_descr_prepare_tx(struct gelic_card *card, | 783 | static int gelic_descr_prepare_tx(struct gelic_card *card, |
784 | struct gelic_descr *descr, | 784 | struct gelic_descr *descr, |
785 | struct sk_buff *skb) | 785 | struct sk_buff *skb) |
786 | { | 786 | { |
787 | dma_addr_t buf; | 787 | dma_addr_t buf; |
788 | 788 | ||
789 | if (card->vlan_required) { | 789 | if (card->vlan_required) { |
790 | struct sk_buff *skb_tmp; | 790 | struct sk_buff *skb_tmp; |
791 | enum gelic_port_type type; | 791 | enum gelic_port_type type; |
792 | 792 | ||
793 | type = netdev_port(skb->dev)->type; | 793 | type = netdev_port(skb->dev)->type; |
794 | skb_tmp = gelic_put_vlan_tag(skb, | 794 | skb_tmp = gelic_put_vlan_tag(skb, |
795 | card->vlan[type].tx); | 795 | card->vlan[type].tx); |
796 | if (!skb_tmp) | 796 | if (!skb_tmp) |
797 | return -ENOMEM; | 797 | return -ENOMEM; |
798 | skb = skb_tmp; | 798 | skb = skb_tmp; |
799 | } | 799 | } |
800 | 800 | ||
801 | buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE); | 801 | buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE); |
802 | 802 | ||
803 | if (!buf) { | 803 | if (!buf) { |
804 | dev_err(ctodev(card), | 804 | dev_err(ctodev(card), |
805 | "dma map 2 failed (%p, %i). Dropping packet\n", | 805 | "dma map 2 failed (%p, %i). Dropping packet\n", |
806 | skb->data, skb->len); | 806 | skb->data, skb->len); |
807 | return -ENOMEM; | 807 | return -ENOMEM; |
808 | } | 808 | } |
809 | 809 | ||
810 | descr->buf_addr = cpu_to_be32(buf); | 810 | descr->buf_addr = cpu_to_be32(buf); |
811 | descr->buf_size = cpu_to_be32(skb->len); | 811 | descr->buf_size = cpu_to_be32(skb->len); |
812 | descr->skb = skb; | 812 | descr->skb = skb; |
813 | descr->data_status = 0; | 813 | descr->data_status = 0; |
814 | descr->next_descr_addr = 0; /* terminate hw descr */ | 814 | descr->next_descr_addr = 0; /* terminate hw descr */ |
815 | gelic_descr_set_tx_cmdstat(descr, skb); | 815 | gelic_descr_set_tx_cmdstat(descr, skb); |
816 | 816 | ||
817 | /* bump free descriptor pointer */ | 817 | /* bump free descriptor pointer */ |
818 | card->tx_chain.head = descr->next; | 818 | card->tx_chain.head = descr->next; |
819 | return 0; | 819 | return 0; |
820 | } | 820 | } |
821 | 821 | ||
822 | /** | 822 | /** |
823 | * gelic_card_kick_txdma - enables TX DMA processing | 823 | * gelic_card_kick_txdma - enables TX DMA processing |
824 | * @card: card structure | 824 | * @card: card structure |
825 | * @descr: descriptor address to enable TX processing at | 825 | * @descr: descriptor address to enable TX processing at |
826 | * | 826 | * |
827 | */ | 827 | */ |
828 | static int gelic_card_kick_txdma(struct gelic_card *card, | 828 | static int gelic_card_kick_txdma(struct gelic_card *card, |
829 | struct gelic_descr *descr) | 829 | struct gelic_descr *descr) |
830 | { | 830 | { |
831 | int status = 0; | 831 | int status = 0; |
832 | 832 | ||
833 | if (card->tx_dma_progress) | 833 | if (card->tx_dma_progress) |
834 | return 0; | 834 | return 0; |
835 | 835 | ||
836 | if (gelic_descr_get_status(descr) == GELIC_DESCR_DMA_CARDOWNED) { | 836 | if (gelic_descr_get_status(descr) == GELIC_DESCR_DMA_CARDOWNED) { |
837 | card->tx_dma_progress = 1; | 837 | card->tx_dma_progress = 1; |
838 | status = lv1_net_start_tx_dma(bus_id(card), dev_id(card), | 838 | status = lv1_net_start_tx_dma(bus_id(card), dev_id(card), |
839 | descr->bus_addr, 0); | 839 | descr->bus_addr, 0); |
840 | if (status) | 840 | if (status) |
841 | dev_info(ctodev(card), "lv1_net_start_txdma failed," \ | 841 | dev_info(ctodev(card), "lv1_net_start_txdma failed," \ |
842 | "status=%d\n", status); | 842 | "status=%d\n", status); |
843 | } | 843 | } |
844 | return status; | 844 | return status; |
845 | } | 845 | } |
846 | 846 | ||
847 | /** | 847 | /** |
848 | * gelic_net_xmit - transmits a frame over the device | 848 | * gelic_net_xmit - transmits a frame over the device |
849 | * @skb: packet to send out | 849 | * @skb: packet to send out |
850 | * @netdev: interface device structure | 850 | * @netdev: interface device structure |
851 | * | 851 | * |
852 | * returns 0 on success, <0 on failure | 852 | * returns 0 on success, <0 on failure |
853 | */ | 853 | */ |
854 | int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) | 854 | int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) |
855 | { | 855 | { |
856 | struct gelic_card *card = netdev_card(netdev); | 856 | struct gelic_card *card = netdev_card(netdev); |
857 | struct gelic_descr *descr; | 857 | struct gelic_descr *descr; |
858 | int result; | 858 | int result; |
859 | unsigned long flags; | 859 | unsigned long flags; |
860 | 860 | ||
861 | spin_lock_irqsave(&card->tx_lock, flags); | 861 | spin_lock_irqsave(&card->tx_lock, flags); |
862 | 862 | ||
863 | gelic_card_release_tx_chain(card, 0); | 863 | gelic_card_release_tx_chain(card, 0); |
864 | 864 | ||
865 | descr = gelic_card_get_next_tx_descr(card); | 865 | descr = gelic_card_get_next_tx_descr(card); |
866 | if (!descr) { | 866 | if (!descr) { |
867 | /* | 867 | /* |
868 | * no more descriptors free | 868 | * no more descriptors free |
869 | */ | 869 | */ |
870 | gelic_card_stop_queues(card); | 870 | gelic_card_stop_queues(card); |
871 | spin_unlock_irqrestore(&card->tx_lock, flags); | 871 | spin_unlock_irqrestore(&card->tx_lock, flags); |
872 | return NETDEV_TX_BUSY; | 872 | return NETDEV_TX_BUSY; |
873 | } | 873 | } |
874 | 874 | ||
875 | result = gelic_descr_prepare_tx(card, descr, skb); | 875 | result = gelic_descr_prepare_tx(card, descr, skb); |
876 | if (result) { | 876 | if (result) { |
877 | /* | 877 | /* |
878 | * DMA map failed. As chanses are that failure | 878 | * DMA map failed. As chanses are that failure |
879 | * would continue, just release skb and return | 879 | * would continue, just release skb and return |
880 | */ | 880 | */ |
881 | netdev->stats.tx_dropped++; | 881 | netdev->stats.tx_dropped++; |
882 | dev_kfree_skb_any(skb); | 882 | dev_kfree_skb_any(skb); |
883 | spin_unlock_irqrestore(&card->tx_lock, flags); | 883 | spin_unlock_irqrestore(&card->tx_lock, flags); |
884 | return NETDEV_TX_OK; | 884 | return NETDEV_TX_OK; |
885 | } | 885 | } |
886 | /* | 886 | /* |
887 | * link this prepared descriptor to previous one | 887 | * link this prepared descriptor to previous one |
888 | * to achieve high performance | 888 | * to achieve high performance |
889 | */ | 889 | */ |
890 | descr->prev->next_descr_addr = cpu_to_be32(descr->bus_addr); | 890 | descr->prev->next_descr_addr = cpu_to_be32(descr->bus_addr); |
891 | /* | 891 | /* |
892 | * as hardware descriptor is modified in the above lines, | 892 | * as hardware descriptor is modified in the above lines, |
893 | * ensure that the hardware sees it | 893 | * ensure that the hardware sees it |
894 | */ | 894 | */ |
895 | wmb(); | 895 | wmb(); |
896 | if (gelic_card_kick_txdma(card, descr)) { | 896 | if (gelic_card_kick_txdma(card, descr)) { |
897 | /* | 897 | /* |
898 | * kick failed. | 898 | * kick failed. |
899 | * release descriptors which were just prepared | 899 | * release descriptors which were just prepared |
900 | */ | 900 | */ |
901 | netdev->stats.tx_dropped++; | 901 | netdev->stats.tx_dropped++; |
902 | gelic_descr_release_tx(card, descr); | 902 | gelic_descr_release_tx(card, descr); |
903 | gelic_descr_release_tx(card, descr->next); | 903 | gelic_descr_release_tx(card, descr->next); |
904 | card->tx_chain.tail = descr->next->next; | 904 | card->tx_chain.tail = descr->next->next; |
905 | dev_info(ctodev(card), "%s: kick failure\n", __func__); | 905 | dev_info(ctodev(card), "%s: kick failure\n", __func__); |
906 | } | 906 | } |
907 | 907 | ||
908 | spin_unlock_irqrestore(&card->tx_lock, flags); | 908 | spin_unlock_irqrestore(&card->tx_lock, flags); |
909 | return NETDEV_TX_OK; | 909 | return NETDEV_TX_OK; |
910 | } | 910 | } |
911 | 911 | ||
912 | /** | 912 | /** |
913 | * gelic_net_pass_skb_up - takes an skb from a descriptor and passes it on | 913 | * gelic_net_pass_skb_up - takes an skb from a descriptor and passes it on |
914 | * @descr: descriptor to process | 914 | * @descr: descriptor to process |
915 | * @card: card structure | 915 | * @card: card structure |
916 | * @netdev: net_device structure to be passed packet | 916 | * @netdev: net_device structure to be passed packet |
917 | * | 917 | * |
918 | * iommu-unmaps the skb, fills out skb structure and passes the data to the | 918 | * iommu-unmaps the skb, fills out skb structure and passes the data to the |
919 | * stack. The descriptor state is not changed. | 919 | * stack. The descriptor state is not changed. |
920 | */ | 920 | */ |
921 | static void gelic_net_pass_skb_up(struct gelic_descr *descr, | 921 | static void gelic_net_pass_skb_up(struct gelic_descr *descr, |
922 | struct gelic_card *card, | 922 | struct gelic_card *card, |
923 | struct net_device *netdev) | 923 | struct net_device *netdev) |
924 | 924 | ||
925 | { | 925 | { |
926 | struct sk_buff *skb = descr->skb; | 926 | struct sk_buff *skb = descr->skb; |
927 | u32 data_status, data_error; | 927 | u32 data_status, data_error; |
928 | 928 | ||
929 | data_status = be32_to_cpu(descr->data_status); | 929 | data_status = be32_to_cpu(descr->data_status); |
930 | data_error = be32_to_cpu(descr->data_error); | 930 | data_error = be32_to_cpu(descr->data_error); |
931 | /* unmap skb buffer */ | 931 | /* unmap skb buffer */ |
932 | dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), | 932 | dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), |
933 | GELIC_NET_MAX_MTU, | 933 | GELIC_NET_MAX_MTU, |
934 | DMA_FROM_DEVICE); | 934 | DMA_FROM_DEVICE); |
935 | 935 | ||
936 | skb_put(skb, be32_to_cpu(descr->valid_size)? | 936 | skb_put(skb, be32_to_cpu(descr->valid_size)? |
937 | be32_to_cpu(descr->valid_size) : | 937 | be32_to_cpu(descr->valid_size) : |
938 | be32_to_cpu(descr->result_size)); | 938 | be32_to_cpu(descr->result_size)); |
939 | if (!descr->valid_size) | 939 | if (!descr->valid_size) |
940 | dev_info(ctodev(card), "buffer full %x %x %x\n", | 940 | dev_info(ctodev(card), "buffer full %x %x %x\n", |
941 | be32_to_cpu(descr->result_size), | 941 | be32_to_cpu(descr->result_size), |
942 | be32_to_cpu(descr->buf_size), | 942 | be32_to_cpu(descr->buf_size), |
943 | be32_to_cpu(descr->dmac_cmd_status)); | 943 | be32_to_cpu(descr->dmac_cmd_status)); |
944 | 944 | ||
945 | descr->skb = NULL; | 945 | descr->skb = NULL; |
946 | /* | 946 | /* |
947 | * the card put 2 bytes vlan tag in front | 947 | * the card put 2 bytes vlan tag in front |
948 | * of the ethernet frame | 948 | * of the ethernet frame |
949 | */ | 949 | */ |
950 | skb_pull(skb, 2); | 950 | skb_pull(skb, 2); |
951 | skb->protocol = eth_type_trans(skb, netdev); | 951 | skb->protocol = eth_type_trans(skb, netdev); |
952 | 952 | ||
953 | /* checksum offload */ | 953 | /* checksum offload */ |
954 | if (card->rx_csum) { | 954 | if (netdev->features & NETIF_F_RXCSUM) { |
955 | if ((data_status & GELIC_DESCR_DATA_STATUS_CHK_MASK) && | 955 | if ((data_status & GELIC_DESCR_DATA_STATUS_CHK_MASK) && |
956 | (!(data_error & GELIC_DESCR_DATA_ERROR_CHK_MASK))) | 956 | (!(data_error & GELIC_DESCR_DATA_ERROR_CHK_MASK))) |
957 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 957 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
958 | else | 958 | else |
959 | skb_checksum_none_assert(skb); | 959 | skb_checksum_none_assert(skb); |
960 | } else | 960 | } else |
961 | skb_checksum_none_assert(skb); | 961 | skb_checksum_none_assert(skb); |
962 | 962 | ||
963 | /* update netdevice statistics */ | 963 | /* update netdevice statistics */ |
964 | netdev->stats.rx_packets++; | 964 | netdev->stats.rx_packets++; |
965 | netdev->stats.rx_bytes += skb->len; | 965 | netdev->stats.rx_bytes += skb->len; |
966 | 966 | ||
967 | /* pass skb up to stack */ | 967 | /* pass skb up to stack */ |
968 | netif_receive_skb(skb); | 968 | netif_receive_skb(skb); |
969 | } | 969 | } |
970 | 970 | ||
971 | /** | 971 | /** |
972 | * gelic_card_decode_one_descr - processes an rx descriptor | 972 | * gelic_card_decode_one_descr - processes an rx descriptor |
973 | * @card: card structure | 973 | * @card: card structure |
974 | * | 974 | * |
975 | * returns 1 if a packet has been sent to the stack, otherwise 0 | 975 | * returns 1 if a packet has been sent to the stack, otherwise 0 |
976 | * | 976 | * |
977 | * processes an rx descriptor by iommu-unmapping the data buffer and passing | 977 | * processes an rx descriptor by iommu-unmapping the data buffer and passing |
978 | * the packet up to the stack | 978 | * the packet up to the stack |
979 | */ | 979 | */ |
980 | static int gelic_card_decode_one_descr(struct gelic_card *card) | 980 | static int gelic_card_decode_one_descr(struct gelic_card *card) |
981 | { | 981 | { |
982 | enum gelic_descr_dma_status status; | 982 | enum gelic_descr_dma_status status; |
983 | struct gelic_descr_chain *chain = &card->rx_chain; | 983 | struct gelic_descr_chain *chain = &card->rx_chain; |
984 | struct gelic_descr *descr = chain->head; | 984 | struct gelic_descr *descr = chain->head; |
985 | struct net_device *netdev = NULL; | 985 | struct net_device *netdev = NULL; |
986 | int dmac_chain_ended; | 986 | int dmac_chain_ended; |
987 | 987 | ||
988 | status = gelic_descr_get_status(descr); | 988 | status = gelic_descr_get_status(descr); |
989 | /* is this descriptor terminated with next_descr == NULL? */ | 989 | /* is this descriptor terminated with next_descr == NULL? */ |
990 | dmac_chain_ended = | 990 | dmac_chain_ended = |
991 | be32_to_cpu(descr->dmac_cmd_status) & | 991 | be32_to_cpu(descr->dmac_cmd_status) & |
992 | GELIC_DESCR_RX_DMA_CHAIN_END; | 992 | GELIC_DESCR_RX_DMA_CHAIN_END; |
993 | 993 | ||
994 | if (status == GELIC_DESCR_DMA_CARDOWNED) | 994 | if (status == GELIC_DESCR_DMA_CARDOWNED) |
995 | return 0; | 995 | return 0; |
996 | 996 | ||
997 | if (status == GELIC_DESCR_DMA_NOT_IN_USE) { | 997 | if (status == GELIC_DESCR_DMA_NOT_IN_USE) { |
998 | dev_dbg(ctodev(card), "dormant descr? %p\n", descr); | 998 | dev_dbg(ctodev(card), "dormant descr? %p\n", descr); |
999 | return 0; | 999 | return 0; |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | /* netdevice select */ | 1002 | /* netdevice select */ |
1003 | if (card->vlan_required) { | 1003 | if (card->vlan_required) { |
1004 | unsigned int i; | 1004 | unsigned int i; |
1005 | u16 vid; | 1005 | u16 vid; |
1006 | vid = *(u16 *)(descr->skb->data) & VLAN_VID_MASK; | 1006 | vid = *(u16 *)(descr->skb->data) & VLAN_VID_MASK; |
1007 | for (i = 0; i < GELIC_PORT_MAX; i++) { | 1007 | for (i = 0; i < GELIC_PORT_MAX; i++) { |
1008 | if (card->vlan[i].rx == vid) { | 1008 | if (card->vlan[i].rx == vid) { |
1009 | netdev = card->netdev[i]; | 1009 | netdev = card->netdev[i]; |
1010 | break; | 1010 | break; |
1011 | } | 1011 | } |
1012 | }; | 1012 | }; |
1013 | if (GELIC_PORT_MAX <= i) { | 1013 | if (GELIC_PORT_MAX <= i) { |
1014 | pr_info("%s: unknown packet vid=%x\n", __func__, vid); | 1014 | pr_info("%s: unknown packet vid=%x\n", __func__, vid); |
1015 | goto refill; | 1015 | goto refill; |
1016 | } | 1016 | } |
1017 | } else | 1017 | } else |
1018 | netdev = card->netdev[GELIC_PORT_ETHERNET_0]; | 1018 | netdev = card->netdev[GELIC_PORT_ETHERNET_0]; |
1019 | 1019 | ||
1020 | if ((status == GELIC_DESCR_DMA_RESPONSE_ERROR) || | 1020 | if ((status == GELIC_DESCR_DMA_RESPONSE_ERROR) || |
1021 | (status == GELIC_DESCR_DMA_PROTECTION_ERROR) || | 1021 | (status == GELIC_DESCR_DMA_PROTECTION_ERROR) || |
1022 | (status == GELIC_DESCR_DMA_FORCE_END)) { | 1022 | (status == GELIC_DESCR_DMA_FORCE_END)) { |
1023 | dev_info(ctodev(card), "dropping RX descriptor with state %x\n", | 1023 | dev_info(ctodev(card), "dropping RX descriptor with state %x\n", |
1024 | status); | 1024 | status); |
1025 | netdev->stats.rx_dropped++; | 1025 | netdev->stats.rx_dropped++; |
1026 | goto refill; | 1026 | goto refill; |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | if (status == GELIC_DESCR_DMA_BUFFER_FULL) { | 1029 | if (status == GELIC_DESCR_DMA_BUFFER_FULL) { |
1030 | /* | 1030 | /* |
1031 | * Buffer full would occur if and only if | 1031 | * Buffer full would occur if and only if |
1032 | * the frame length was longer than the size of this | 1032 | * the frame length was longer than the size of this |
1033 | * descriptor's buffer. If the frame length was equal | 1033 | * descriptor's buffer. If the frame length was equal |
1034 | * to or shorter than buffer'size, FRAME_END condition | 1034 | * to or shorter than buffer'size, FRAME_END condition |
1035 | * would occur. | 1035 | * would occur. |
1036 | * Anyway this frame was longer than the MTU, | 1036 | * Anyway this frame was longer than the MTU, |
1037 | * just drop it. | 1037 | * just drop it. |
1038 | */ | 1038 | */ |
1039 | dev_info(ctodev(card), "overlength frame\n"); | 1039 | dev_info(ctodev(card), "overlength frame\n"); |
1040 | goto refill; | 1040 | goto refill; |
1041 | } | 1041 | } |
1042 | /* | 1042 | /* |
1043 | * descriptoers any other than FRAME_END here should | 1043 | * descriptoers any other than FRAME_END here should |
1044 | * be treated as error. | 1044 | * be treated as error. |
1045 | */ | 1045 | */ |
1046 | if (status != GELIC_DESCR_DMA_FRAME_END) { | 1046 | if (status != GELIC_DESCR_DMA_FRAME_END) { |
1047 | dev_dbg(ctodev(card), "RX descriptor with state %x\n", | 1047 | dev_dbg(ctodev(card), "RX descriptor with state %x\n", |
1048 | status); | 1048 | status); |
1049 | goto refill; | 1049 | goto refill; |
1050 | } | 1050 | } |
1051 | 1051 | ||
1052 | /* ok, we've got a packet in descr */ | 1052 | /* ok, we've got a packet in descr */ |
1053 | gelic_net_pass_skb_up(descr, card, netdev); | 1053 | gelic_net_pass_skb_up(descr, card, netdev); |
1054 | refill: | 1054 | refill: |
1055 | /* | 1055 | /* |
1056 | * So that always DMAC can see the end | 1056 | * So that always DMAC can see the end |
1057 | * of the descriptor chain to avoid | 1057 | * of the descriptor chain to avoid |
1058 | * from unwanted DMAC overrun. | 1058 | * from unwanted DMAC overrun. |
1059 | */ | 1059 | */ |
1060 | descr->next_descr_addr = 0; | 1060 | descr->next_descr_addr = 0; |
1061 | 1061 | ||
1062 | /* change the descriptor state: */ | 1062 | /* change the descriptor state: */ |
1063 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); | 1063 | gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); |
1064 | 1064 | ||
1065 | /* | 1065 | /* |
1066 | * this call can fail, but for now, just leave this | 1066 | * this call can fail, but for now, just leave this |
1067 | * decriptor without skb | 1067 | * decriptor without skb |
1068 | */ | 1068 | */ |
1069 | gelic_descr_prepare_rx(card, descr); | 1069 | gelic_descr_prepare_rx(card, descr); |
1070 | 1070 | ||
1071 | chain->tail = descr; | 1071 | chain->tail = descr; |
1072 | chain->head = descr->next; | 1072 | chain->head = descr->next; |
1073 | 1073 | ||
1074 | /* | 1074 | /* |
1075 | * Set this descriptor the end of the chain. | 1075 | * Set this descriptor the end of the chain. |
1076 | */ | 1076 | */ |
1077 | descr->prev->next_descr_addr = cpu_to_be32(descr->bus_addr); | 1077 | descr->prev->next_descr_addr = cpu_to_be32(descr->bus_addr); |
1078 | 1078 | ||
1079 | /* | 1079 | /* |
1080 | * If dmac chain was met, DMAC stopped. | 1080 | * If dmac chain was met, DMAC stopped. |
1081 | * thus re-enable it | 1081 | * thus re-enable it |
1082 | */ | 1082 | */ |
1083 | if (dmac_chain_ended) { | 1083 | if (dmac_chain_ended) { |
1084 | card->rx_dma_restart_required = 1; | 1084 | card->rx_dma_restart_required = 1; |
1085 | dev_dbg(ctodev(card), "reenable rx dma scheduled\n"); | 1085 | dev_dbg(ctodev(card), "reenable rx dma scheduled\n"); |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | return 1; | 1088 | return 1; |
1089 | } | 1089 | } |
1090 | 1090 | ||
1091 | /** | 1091 | /** |
1092 | * gelic_net_poll - NAPI poll function called by the stack to return packets | 1092 | * gelic_net_poll - NAPI poll function called by the stack to return packets |
1093 | * @napi: napi structure | 1093 | * @napi: napi structure |
1094 | * @budget: number of packets we can pass to the stack at most | 1094 | * @budget: number of packets we can pass to the stack at most |
1095 | * | 1095 | * |
1096 | * returns the number of the processed packets | 1096 | * returns the number of the processed packets |
1097 | * | 1097 | * |
1098 | */ | 1098 | */ |
1099 | static int gelic_net_poll(struct napi_struct *napi, int budget) | 1099 | static int gelic_net_poll(struct napi_struct *napi, int budget) |
1100 | { | 1100 | { |
1101 | struct gelic_card *card = container_of(napi, struct gelic_card, napi); | 1101 | struct gelic_card *card = container_of(napi, struct gelic_card, napi); |
1102 | int packets_done = 0; | 1102 | int packets_done = 0; |
1103 | 1103 | ||
1104 | while (packets_done < budget) { | 1104 | while (packets_done < budget) { |
1105 | if (!gelic_card_decode_one_descr(card)) | 1105 | if (!gelic_card_decode_one_descr(card)) |
1106 | break; | 1106 | break; |
1107 | 1107 | ||
1108 | packets_done++; | 1108 | packets_done++; |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | if (packets_done < budget) { | 1111 | if (packets_done < budget) { |
1112 | napi_complete(napi); | 1112 | napi_complete(napi); |
1113 | gelic_card_rx_irq_on(card); | 1113 | gelic_card_rx_irq_on(card); |
1114 | } | 1114 | } |
1115 | return packets_done; | 1115 | return packets_done; |
1116 | } | 1116 | } |
1117 | /** | 1117 | /** |
1118 | * gelic_net_change_mtu - changes the MTU of an interface | 1118 | * gelic_net_change_mtu - changes the MTU of an interface |
1119 | * @netdev: interface device structure | 1119 | * @netdev: interface device structure |
1120 | * @new_mtu: new MTU value | 1120 | * @new_mtu: new MTU value |
1121 | * | 1121 | * |
1122 | * returns 0 on success, <0 on failure | 1122 | * returns 0 on success, <0 on failure |
1123 | */ | 1123 | */ |
1124 | int gelic_net_change_mtu(struct net_device *netdev, int new_mtu) | 1124 | int gelic_net_change_mtu(struct net_device *netdev, int new_mtu) |
1125 | { | 1125 | { |
1126 | /* no need to re-alloc skbs or so -- the max mtu is about 2.3k | 1126 | /* no need to re-alloc skbs or so -- the max mtu is about 2.3k |
1127 | * and mtu is outbound only anyway */ | 1127 | * and mtu is outbound only anyway */ |
1128 | if ((new_mtu < GELIC_NET_MIN_MTU) || | 1128 | if ((new_mtu < GELIC_NET_MIN_MTU) || |
1129 | (new_mtu > GELIC_NET_MAX_MTU)) { | 1129 | (new_mtu > GELIC_NET_MAX_MTU)) { |
1130 | return -EINVAL; | 1130 | return -EINVAL; |
1131 | } | 1131 | } |
1132 | netdev->mtu = new_mtu; | 1132 | netdev->mtu = new_mtu; |
1133 | return 0; | 1133 | return 0; |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | /** | 1136 | /** |
1137 | * gelic_card_interrupt - event handler for gelic_net | 1137 | * gelic_card_interrupt - event handler for gelic_net |
1138 | */ | 1138 | */ |
1139 | static irqreturn_t gelic_card_interrupt(int irq, void *ptr) | 1139 | static irqreturn_t gelic_card_interrupt(int irq, void *ptr) |
1140 | { | 1140 | { |
1141 | unsigned long flags; | 1141 | unsigned long flags; |
1142 | struct gelic_card *card = ptr; | 1142 | struct gelic_card *card = ptr; |
1143 | u64 status; | 1143 | u64 status; |
1144 | 1144 | ||
1145 | status = card->irq_status; | 1145 | status = card->irq_status; |
1146 | 1146 | ||
1147 | if (!status) | 1147 | if (!status) |
1148 | return IRQ_NONE; | 1148 | return IRQ_NONE; |
1149 | 1149 | ||
1150 | status &= card->irq_mask; | 1150 | status &= card->irq_mask; |
1151 | 1151 | ||
1152 | if (card->rx_dma_restart_required) { | 1152 | if (card->rx_dma_restart_required) { |
1153 | card->rx_dma_restart_required = 0; | 1153 | card->rx_dma_restart_required = 0; |
1154 | gelic_card_enable_rxdmac(card); | 1154 | gelic_card_enable_rxdmac(card); |
1155 | } | 1155 | } |
1156 | 1156 | ||
1157 | if (status & GELIC_CARD_RXINT) { | 1157 | if (status & GELIC_CARD_RXINT) { |
1158 | gelic_card_rx_irq_off(card); | 1158 | gelic_card_rx_irq_off(card); |
1159 | napi_schedule(&card->napi); | 1159 | napi_schedule(&card->napi); |
1160 | } | 1160 | } |
1161 | 1161 | ||
1162 | if (status & GELIC_CARD_TXINT) { | 1162 | if (status & GELIC_CARD_TXINT) { |
1163 | spin_lock_irqsave(&card->tx_lock, flags); | 1163 | spin_lock_irqsave(&card->tx_lock, flags); |
1164 | card->tx_dma_progress = 0; | 1164 | card->tx_dma_progress = 0; |
1165 | gelic_card_release_tx_chain(card, 0); | 1165 | gelic_card_release_tx_chain(card, 0); |
1166 | /* kick outstanding tx descriptor if any */ | 1166 | /* kick outstanding tx descriptor if any */ |
1167 | gelic_card_kick_txdma(card, card->tx_chain.tail); | 1167 | gelic_card_kick_txdma(card, card->tx_chain.tail); |
1168 | spin_unlock_irqrestore(&card->tx_lock, flags); | 1168 | spin_unlock_irqrestore(&card->tx_lock, flags); |
1169 | } | 1169 | } |
1170 | 1170 | ||
1171 | /* ether port status changed */ | 1171 | /* ether port status changed */ |
1172 | if (status & GELIC_CARD_PORT_STATUS_CHANGED) | 1172 | if (status & GELIC_CARD_PORT_STATUS_CHANGED) |
1173 | gelic_card_get_ether_port_status(card, 1); | 1173 | gelic_card_get_ether_port_status(card, 1); |
1174 | 1174 | ||
1175 | #ifdef CONFIG_GELIC_WIRELESS | 1175 | #ifdef CONFIG_GELIC_WIRELESS |
1176 | if (status & (GELIC_CARD_WLAN_EVENT_RECEIVED | | 1176 | if (status & (GELIC_CARD_WLAN_EVENT_RECEIVED | |
1177 | GELIC_CARD_WLAN_COMMAND_COMPLETED)) | 1177 | GELIC_CARD_WLAN_COMMAND_COMPLETED)) |
1178 | gelic_wl_interrupt(card->netdev[GELIC_PORT_WIRELESS], status); | 1178 | gelic_wl_interrupt(card->netdev[GELIC_PORT_WIRELESS], status); |
1179 | #endif | 1179 | #endif |
1180 | 1180 | ||
1181 | return IRQ_HANDLED; | 1181 | return IRQ_HANDLED; |
1182 | } | 1182 | } |
1183 | 1183 | ||
1184 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1184 | #ifdef CONFIG_NET_POLL_CONTROLLER |
1185 | /** | 1185 | /** |
1186 | * gelic_net_poll_controller - artificial interrupt for netconsole etc. | 1186 | * gelic_net_poll_controller - artificial interrupt for netconsole etc. |
1187 | * @netdev: interface device structure | 1187 | * @netdev: interface device structure |
1188 | * | 1188 | * |
1189 | * see Documentation/networking/netconsole.txt | 1189 | * see Documentation/networking/netconsole.txt |
1190 | */ | 1190 | */ |
1191 | void gelic_net_poll_controller(struct net_device *netdev) | 1191 | void gelic_net_poll_controller(struct net_device *netdev) |
1192 | { | 1192 | { |
1193 | struct gelic_card *card = netdev_card(netdev); | 1193 | struct gelic_card *card = netdev_card(netdev); |
1194 | 1194 | ||
1195 | gelic_card_set_irq_mask(card, 0); | 1195 | gelic_card_set_irq_mask(card, 0); |
1196 | gelic_card_interrupt(netdev->irq, netdev); | 1196 | gelic_card_interrupt(netdev->irq, netdev); |
1197 | gelic_card_set_irq_mask(card, card->irq_mask); | 1197 | gelic_card_set_irq_mask(card, card->irq_mask); |
1198 | } | 1198 | } |
1199 | #endif /* CONFIG_NET_POLL_CONTROLLER */ | 1199 | #endif /* CONFIG_NET_POLL_CONTROLLER */ |
1200 | 1200 | ||
1201 | /** | 1201 | /** |
1202 | * gelic_net_open - called upon ifonfig up | 1202 | * gelic_net_open - called upon ifonfig up |
1203 | * @netdev: interface device structure | 1203 | * @netdev: interface device structure |
1204 | * | 1204 | * |
1205 | * returns 0 on success, <0 on failure | 1205 | * returns 0 on success, <0 on failure |
1206 | * | 1206 | * |
1207 | * gelic_net_open allocates all the descriptors and memory needed for | 1207 | * gelic_net_open allocates all the descriptors and memory needed for |
1208 | * operation, sets up multicast list and enables interrupts | 1208 | * operation, sets up multicast list and enables interrupts |
1209 | */ | 1209 | */ |
1210 | int gelic_net_open(struct net_device *netdev) | 1210 | int gelic_net_open(struct net_device *netdev) |
1211 | { | 1211 | { |
1212 | struct gelic_card *card = netdev_card(netdev); | 1212 | struct gelic_card *card = netdev_card(netdev); |
1213 | 1213 | ||
1214 | dev_dbg(ctodev(card), " -> %s %p\n", __func__, netdev); | 1214 | dev_dbg(ctodev(card), " -> %s %p\n", __func__, netdev); |
1215 | 1215 | ||
1216 | gelic_card_up(card); | 1216 | gelic_card_up(card); |
1217 | 1217 | ||
1218 | netif_start_queue(netdev); | 1218 | netif_start_queue(netdev); |
1219 | gelic_card_get_ether_port_status(card, 1); | 1219 | gelic_card_get_ether_port_status(card, 1); |
1220 | 1220 | ||
1221 | dev_dbg(ctodev(card), " <- %s\n", __func__); | 1221 | dev_dbg(ctodev(card), " <- %s\n", __func__); |
1222 | return 0; | 1222 | return 0; |
1223 | } | 1223 | } |
1224 | 1224 | ||
1225 | void gelic_net_get_drvinfo(struct net_device *netdev, | 1225 | void gelic_net_get_drvinfo(struct net_device *netdev, |
1226 | struct ethtool_drvinfo *info) | 1226 | struct ethtool_drvinfo *info) |
1227 | { | 1227 | { |
1228 | strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1); | 1228 | strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1); |
1229 | strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1); | 1229 | strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1); |
1230 | } | 1230 | } |
1231 | 1231 | ||
1232 | static int gelic_ether_get_settings(struct net_device *netdev, | 1232 | static int gelic_ether_get_settings(struct net_device *netdev, |
1233 | struct ethtool_cmd *cmd) | 1233 | struct ethtool_cmd *cmd) |
1234 | { | 1234 | { |
1235 | struct gelic_card *card = netdev_card(netdev); | 1235 | struct gelic_card *card = netdev_card(netdev); |
1236 | 1236 | ||
1237 | gelic_card_get_ether_port_status(card, 0); | 1237 | gelic_card_get_ether_port_status(card, 0); |
1238 | 1238 | ||
1239 | if (card->ether_port_status & GELIC_LV1_ETHER_FULL_DUPLEX) | 1239 | if (card->ether_port_status & GELIC_LV1_ETHER_FULL_DUPLEX) |
1240 | cmd->duplex = DUPLEX_FULL; | 1240 | cmd->duplex = DUPLEX_FULL; |
1241 | else | 1241 | else |
1242 | cmd->duplex = DUPLEX_HALF; | 1242 | cmd->duplex = DUPLEX_HALF; |
1243 | 1243 | ||
1244 | switch (card->ether_port_status & GELIC_LV1_ETHER_SPEED_MASK) { | 1244 | switch (card->ether_port_status & GELIC_LV1_ETHER_SPEED_MASK) { |
1245 | case GELIC_LV1_ETHER_SPEED_10: | 1245 | case GELIC_LV1_ETHER_SPEED_10: |
1246 | cmd->speed = SPEED_10; | 1246 | cmd->speed = SPEED_10; |
1247 | break; | 1247 | break; |
1248 | case GELIC_LV1_ETHER_SPEED_100: | 1248 | case GELIC_LV1_ETHER_SPEED_100: |
1249 | cmd->speed = SPEED_100; | 1249 | cmd->speed = SPEED_100; |
1250 | break; | 1250 | break; |
1251 | case GELIC_LV1_ETHER_SPEED_1000: | 1251 | case GELIC_LV1_ETHER_SPEED_1000: |
1252 | cmd->speed = SPEED_1000; | 1252 | cmd->speed = SPEED_1000; |
1253 | break; | 1253 | break; |
1254 | default: | 1254 | default: |
1255 | pr_info("%s: speed unknown\n", __func__); | 1255 | pr_info("%s: speed unknown\n", __func__); |
1256 | cmd->speed = SPEED_10; | 1256 | cmd->speed = SPEED_10; |
1257 | break; | 1257 | break; |
1258 | } | 1258 | } |
1259 | 1259 | ||
1260 | cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | | 1260 | cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | |
1261 | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | | 1261 | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | |
1262 | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | | 1262 | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | |
1263 | SUPPORTED_1000baseT_Full; | 1263 | SUPPORTED_1000baseT_Full; |
1264 | cmd->advertising = cmd->supported; | 1264 | cmd->advertising = cmd->supported; |
1265 | if (card->link_mode & GELIC_LV1_ETHER_AUTO_NEG) { | 1265 | if (card->link_mode & GELIC_LV1_ETHER_AUTO_NEG) { |
1266 | cmd->autoneg = AUTONEG_ENABLE; | 1266 | cmd->autoneg = AUTONEG_ENABLE; |
1267 | } else { | 1267 | } else { |
1268 | cmd->autoneg = AUTONEG_DISABLE; | 1268 | cmd->autoneg = AUTONEG_DISABLE; |
1269 | cmd->advertising &= ~ADVERTISED_Autoneg; | 1269 | cmd->advertising &= ~ADVERTISED_Autoneg; |
1270 | } | 1270 | } |
1271 | cmd->port = PORT_TP; | 1271 | cmd->port = PORT_TP; |
1272 | 1272 | ||
1273 | return 0; | 1273 | return 0; |
1274 | } | 1274 | } |
1275 | 1275 | ||
1276 | static int gelic_ether_set_settings(struct net_device *netdev, | 1276 | static int gelic_ether_set_settings(struct net_device *netdev, |
1277 | struct ethtool_cmd *cmd) | 1277 | struct ethtool_cmd *cmd) |
1278 | { | 1278 | { |
1279 | struct gelic_card *card = netdev_card(netdev); | 1279 | struct gelic_card *card = netdev_card(netdev); |
1280 | u64 mode; | 1280 | u64 mode; |
1281 | int ret; | 1281 | int ret; |
1282 | 1282 | ||
1283 | if (cmd->autoneg == AUTONEG_ENABLE) { | 1283 | if (cmd->autoneg == AUTONEG_ENABLE) { |
1284 | mode = GELIC_LV1_ETHER_AUTO_NEG; | 1284 | mode = GELIC_LV1_ETHER_AUTO_NEG; |
1285 | } else { | 1285 | } else { |
1286 | switch (cmd->speed) { | 1286 | switch (cmd->speed) { |
1287 | case SPEED_10: | 1287 | case SPEED_10: |
1288 | mode = GELIC_LV1_ETHER_SPEED_10; | 1288 | mode = GELIC_LV1_ETHER_SPEED_10; |
1289 | break; | 1289 | break; |
1290 | case SPEED_100: | 1290 | case SPEED_100: |
1291 | mode = GELIC_LV1_ETHER_SPEED_100; | 1291 | mode = GELIC_LV1_ETHER_SPEED_100; |
1292 | break; | 1292 | break; |
1293 | case SPEED_1000: | 1293 | case SPEED_1000: |
1294 | mode = GELIC_LV1_ETHER_SPEED_1000; | 1294 | mode = GELIC_LV1_ETHER_SPEED_1000; |
1295 | break; | 1295 | break; |
1296 | default: | 1296 | default: |
1297 | return -EINVAL; | 1297 | return -EINVAL; |
1298 | } | 1298 | } |
1299 | if (cmd->duplex == DUPLEX_FULL) | 1299 | if (cmd->duplex == DUPLEX_FULL) |
1300 | mode |= GELIC_LV1_ETHER_FULL_DUPLEX; | 1300 | mode |= GELIC_LV1_ETHER_FULL_DUPLEX; |
1301 | else if (cmd->speed == SPEED_1000) { | 1301 | else if (cmd->speed == SPEED_1000) { |
1302 | pr_info("1000 half duplex is not supported.\n"); | 1302 | pr_info("1000 half duplex is not supported.\n"); |
1303 | return -EINVAL; | 1303 | return -EINVAL; |
1304 | } | 1304 | } |
1305 | } | 1305 | } |
1306 | 1306 | ||
1307 | ret = gelic_card_set_link_mode(card, mode); | 1307 | ret = gelic_card_set_link_mode(card, mode); |
1308 | 1308 | ||
1309 | if (ret) | 1309 | if (ret) |
1310 | return ret; | 1310 | return ret; |
1311 | 1311 | ||
1312 | return 0; | 1312 | return 0; |
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | u32 gelic_net_get_rx_csum(struct net_device *netdev) | ||
1316 | { | ||
1317 | struct gelic_card *card = netdev_card(netdev); | ||
1318 | |||
1319 | return card->rx_csum; | ||
1320 | } | ||
1321 | |||
1322 | int gelic_net_set_rx_csum(struct net_device *netdev, u32 data) | ||
1323 | { | ||
1324 | struct gelic_card *card = netdev_card(netdev); | ||
1325 | |||
1326 | card->rx_csum = data; | ||
1327 | return 0; | ||
1328 | } | ||
1329 | |||
1330 | static void gelic_net_get_wol(struct net_device *netdev, | 1315 | static void gelic_net_get_wol(struct net_device *netdev, |
1331 | struct ethtool_wolinfo *wol) | 1316 | struct ethtool_wolinfo *wol) |
1332 | { | 1317 | { |
1333 | if (0 <= ps3_compare_firmware_version(2, 2, 0)) | 1318 | if (0 <= ps3_compare_firmware_version(2, 2, 0)) |
1334 | wol->supported = WAKE_MAGIC; | 1319 | wol->supported = WAKE_MAGIC; |
1335 | else | 1320 | else |
1336 | wol->supported = 0; | 1321 | wol->supported = 0; |
1337 | 1322 | ||
1338 | wol->wolopts = ps3_sys_manager_get_wol() ? wol->supported : 0; | 1323 | wol->wolopts = ps3_sys_manager_get_wol() ? wol->supported : 0; |
1339 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | 1324 | memset(&wol->sopass, 0, sizeof(wol->sopass)); |
1340 | } | 1325 | } |
1341 | static int gelic_net_set_wol(struct net_device *netdev, | 1326 | static int gelic_net_set_wol(struct net_device *netdev, |
1342 | struct ethtool_wolinfo *wol) | 1327 | struct ethtool_wolinfo *wol) |
1343 | { | 1328 | { |
1344 | int status; | 1329 | int status; |
1345 | struct gelic_card *card; | 1330 | struct gelic_card *card; |
1346 | u64 v1, v2; | 1331 | u64 v1, v2; |
1347 | 1332 | ||
1348 | if (ps3_compare_firmware_version(2, 2, 0) < 0 || | 1333 | if (ps3_compare_firmware_version(2, 2, 0) < 0 || |
1349 | !capable(CAP_NET_ADMIN)) | 1334 | !capable(CAP_NET_ADMIN)) |
1350 | return -EPERM; | 1335 | return -EPERM; |
1351 | 1336 | ||
1352 | if (wol->wolopts & ~WAKE_MAGIC) | 1337 | if (wol->wolopts & ~WAKE_MAGIC) |
1353 | return -EINVAL; | 1338 | return -EINVAL; |
1354 | 1339 | ||
1355 | card = netdev_card(netdev); | 1340 | card = netdev_card(netdev); |
1356 | if (wol->wolopts & WAKE_MAGIC) { | 1341 | if (wol->wolopts & WAKE_MAGIC) { |
1357 | status = lv1_net_control(bus_id(card), dev_id(card), | 1342 | status = lv1_net_control(bus_id(card), dev_id(card), |
1358 | GELIC_LV1_SET_WOL, | 1343 | GELIC_LV1_SET_WOL, |
1359 | GELIC_LV1_WOL_MAGIC_PACKET, | 1344 | GELIC_LV1_WOL_MAGIC_PACKET, |
1360 | 0, GELIC_LV1_WOL_MP_ENABLE, | 1345 | 0, GELIC_LV1_WOL_MP_ENABLE, |
1361 | &v1, &v2); | 1346 | &v1, &v2); |
1362 | if (status) { | 1347 | if (status) { |
1363 | pr_info("%s: enabling WOL failed %d\n", __func__, | 1348 | pr_info("%s: enabling WOL failed %d\n", __func__, |
1364 | status); | 1349 | status); |
1365 | status = -EIO; | 1350 | status = -EIO; |
1366 | goto done; | 1351 | goto done; |
1367 | } | 1352 | } |
1368 | status = lv1_net_control(bus_id(card), dev_id(card), | 1353 | status = lv1_net_control(bus_id(card), dev_id(card), |
1369 | GELIC_LV1_SET_WOL, | 1354 | GELIC_LV1_SET_WOL, |
1370 | GELIC_LV1_WOL_ADD_MATCH_ADDR, | 1355 | GELIC_LV1_WOL_ADD_MATCH_ADDR, |
1371 | 0, GELIC_LV1_WOL_MATCH_ALL, | 1356 | 0, GELIC_LV1_WOL_MATCH_ALL, |
1372 | &v1, &v2); | 1357 | &v1, &v2); |
1373 | if (!status) | 1358 | if (!status) |
1374 | ps3_sys_manager_set_wol(1); | 1359 | ps3_sys_manager_set_wol(1); |
1375 | else { | 1360 | else { |
1376 | pr_info("%s: enabling WOL filter failed %d\n", | 1361 | pr_info("%s: enabling WOL filter failed %d\n", |
1377 | __func__, status); | 1362 | __func__, status); |
1378 | status = -EIO; | 1363 | status = -EIO; |
1379 | } | 1364 | } |
1380 | } else { | 1365 | } else { |
1381 | status = lv1_net_control(bus_id(card), dev_id(card), | 1366 | status = lv1_net_control(bus_id(card), dev_id(card), |
1382 | GELIC_LV1_SET_WOL, | 1367 | GELIC_LV1_SET_WOL, |
1383 | GELIC_LV1_WOL_MAGIC_PACKET, | 1368 | GELIC_LV1_WOL_MAGIC_PACKET, |
1384 | 0, GELIC_LV1_WOL_MP_DISABLE, | 1369 | 0, GELIC_LV1_WOL_MP_DISABLE, |
1385 | &v1, &v2); | 1370 | &v1, &v2); |
1386 | if (status) { | 1371 | if (status) { |
1387 | pr_info("%s: disabling WOL failed %d\n", __func__, | 1372 | pr_info("%s: disabling WOL failed %d\n", __func__, |
1388 | status); | 1373 | status); |
1389 | status = -EIO; | 1374 | status = -EIO; |
1390 | goto done; | 1375 | goto done; |
1391 | } | 1376 | } |
1392 | status = lv1_net_control(bus_id(card), dev_id(card), | 1377 | status = lv1_net_control(bus_id(card), dev_id(card), |
1393 | GELIC_LV1_SET_WOL, | 1378 | GELIC_LV1_SET_WOL, |
1394 | GELIC_LV1_WOL_DELETE_MATCH_ADDR, | 1379 | GELIC_LV1_WOL_DELETE_MATCH_ADDR, |
1395 | 0, GELIC_LV1_WOL_MATCH_ALL, | 1380 | 0, GELIC_LV1_WOL_MATCH_ALL, |
1396 | &v1, &v2); | 1381 | &v1, &v2); |
1397 | if (!status) | 1382 | if (!status) |
1398 | ps3_sys_manager_set_wol(0); | 1383 | ps3_sys_manager_set_wol(0); |
1399 | else { | 1384 | else { |
1400 | pr_info("%s: removing WOL filter failed %d\n", | 1385 | pr_info("%s: removing WOL filter failed %d\n", |
1401 | __func__, status); | 1386 | __func__, status); |
1402 | status = -EIO; | 1387 | status = -EIO; |
1403 | } | 1388 | } |
1404 | } | 1389 | } |
1405 | done: | 1390 | done: |
1406 | return status; | 1391 | return status; |
1407 | } | 1392 | } |
1408 | 1393 | ||
1409 | static const struct ethtool_ops gelic_ether_ethtool_ops = { | 1394 | static const struct ethtool_ops gelic_ether_ethtool_ops = { |
1410 | .get_drvinfo = gelic_net_get_drvinfo, | 1395 | .get_drvinfo = gelic_net_get_drvinfo, |
1411 | .get_settings = gelic_ether_get_settings, | 1396 | .get_settings = gelic_ether_get_settings, |
1412 | .set_settings = gelic_ether_set_settings, | 1397 | .set_settings = gelic_ether_set_settings, |
1413 | .get_link = ethtool_op_get_link, | 1398 | .get_link = ethtool_op_get_link, |
1414 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
1415 | .set_tx_csum = ethtool_op_set_tx_csum, | ||
1416 | .get_rx_csum = gelic_net_get_rx_csum, | ||
1417 | .set_rx_csum = gelic_net_set_rx_csum, | ||
1418 | .get_wol = gelic_net_get_wol, | 1399 | .get_wol = gelic_net_get_wol, |
1419 | .set_wol = gelic_net_set_wol, | 1400 | .set_wol = gelic_net_set_wol, |
1420 | }; | 1401 | }; |
1421 | 1402 | ||
1422 | /** | 1403 | /** |
1423 | * gelic_net_tx_timeout_task - task scheduled by the watchdog timeout | 1404 | * gelic_net_tx_timeout_task - task scheduled by the watchdog timeout |
1424 | * function (to be called not under interrupt status) | 1405 | * function (to be called not under interrupt status) |
1425 | * @work: work is context of tx timout task | 1406 | * @work: work is context of tx timout task |
1426 | * | 1407 | * |
1427 | * called as task when tx hangs, resets interface (if interface is up) | 1408 | * called as task when tx hangs, resets interface (if interface is up) |
1428 | */ | 1409 | */ |
1429 | static void gelic_net_tx_timeout_task(struct work_struct *work) | 1410 | static void gelic_net_tx_timeout_task(struct work_struct *work) |
1430 | { | 1411 | { |
1431 | struct gelic_card *card = | 1412 | struct gelic_card *card = |
1432 | container_of(work, struct gelic_card, tx_timeout_task); | 1413 | container_of(work, struct gelic_card, tx_timeout_task); |
1433 | struct net_device *netdev = card->netdev[GELIC_PORT_ETHERNET_0]; | 1414 | struct net_device *netdev = card->netdev[GELIC_PORT_ETHERNET_0]; |
1434 | 1415 | ||
1435 | dev_info(ctodev(card), "%s:Timed out. Restarting...\n", __func__); | 1416 | dev_info(ctodev(card), "%s:Timed out. Restarting...\n", __func__); |
1436 | 1417 | ||
1437 | if (!(netdev->flags & IFF_UP)) | 1418 | if (!(netdev->flags & IFF_UP)) |
1438 | goto out; | 1419 | goto out; |
1439 | 1420 | ||
1440 | netif_device_detach(netdev); | 1421 | netif_device_detach(netdev); |
1441 | gelic_net_stop(netdev); | 1422 | gelic_net_stop(netdev); |
1442 | 1423 | ||
1443 | gelic_net_open(netdev); | 1424 | gelic_net_open(netdev); |
1444 | netif_device_attach(netdev); | 1425 | netif_device_attach(netdev); |
1445 | 1426 | ||
1446 | out: | 1427 | out: |
1447 | atomic_dec(&card->tx_timeout_task_counter); | 1428 | atomic_dec(&card->tx_timeout_task_counter); |
1448 | } | 1429 | } |
1449 | 1430 | ||
1450 | /** | 1431 | /** |
1451 | * gelic_net_tx_timeout - called when the tx timeout watchdog kicks in. | 1432 | * gelic_net_tx_timeout - called when the tx timeout watchdog kicks in. |
1452 | * @netdev: interface device structure | 1433 | * @netdev: interface device structure |
1453 | * | 1434 | * |
1454 | * called, if tx hangs. Schedules a task that resets the interface | 1435 | * called, if tx hangs. Schedules a task that resets the interface |
1455 | */ | 1436 | */ |
1456 | void gelic_net_tx_timeout(struct net_device *netdev) | 1437 | void gelic_net_tx_timeout(struct net_device *netdev) |
1457 | { | 1438 | { |
1458 | struct gelic_card *card; | 1439 | struct gelic_card *card; |
1459 | 1440 | ||
1460 | card = netdev_card(netdev); | 1441 | card = netdev_card(netdev); |
1461 | atomic_inc(&card->tx_timeout_task_counter); | 1442 | atomic_inc(&card->tx_timeout_task_counter); |
1462 | if (netdev->flags & IFF_UP) | 1443 | if (netdev->flags & IFF_UP) |
1463 | schedule_work(&card->tx_timeout_task); | 1444 | schedule_work(&card->tx_timeout_task); |
1464 | else | 1445 | else |
1465 | atomic_dec(&card->tx_timeout_task_counter); | 1446 | atomic_dec(&card->tx_timeout_task_counter); |
1466 | } | 1447 | } |
1467 | 1448 | ||
1468 | static const struct net_device_ops gelic_netdevice_ops = { | 1449 | static const struct net_device_ops gelic_netdevice_ops = { |
1469 | .ndo_open = gelic_net_open, | 1450 | .ndo_open = gelic_net_open, |
1470 | .ndo_stop = gelic_net_stop, | 1451 | .ndo_stop = gelic_net_stop, |
1471 | .ndo_start_xmit = gelic_net_xmit, | 1452 | .ndo_start_xmit = gelic_net_xmit, |
1472 | .ndo_set_multicast_list = gelic_net_set_multi, | 1453 | .ndo_set_multicast_list = gelic_net_set_multi, |
1473 | .ndo_change_mtu = gelic_net_change_mtu, | 1454 | .ndo_change_mtu = gelic_net_change_mtu, |
1474 | .ndo_tx_timeout = gelic_net_tx_timeout, | 1455 | .ndo_tx_timeout = gelic_net_tx_timeout, |
1475 | .ndo_set_mac_address = eth_mac_addr, | 1456 | .ndo_set_mac_address = eth_mac_addr, |
1476 | .ndo_validate_addr = eth_validate_addr, | 1457 | .ndo_validate_addr = eth_validate_addr, |
1477 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1458 | #ifdef CONFIG_NET_POLL_CONTROLLER |
1478 | .ndo_poll_controller = gelic_net_poll_controller, | 1459 | .ndo_poll_controller = gelic_net_poll_controller, |
1479 | #endif | 1460 | #endif |
1480 | }; | 1461 | }; |
1481 | 1462 | ||
1482 | /** | 1463 | /** |
1483 | * gelic_ether_setup_netdev_ops - initialization of net_device operations | 1464 | * gelic_ether_setup_netdev_ops - initialization of net_device operations |
1484 | * @netdev: net_device structure | 1465 | * @netdev: net_device structure |
1485 | * | 1466 | * |
1486 | * fills out function pointers in the net_device structure | 1467 | * fills out function pointers in the net_device structure |
1487 | */ | 1468 | */ |
1488 | static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev, | 1469 | static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev, |
1489 | struct napi_struct *napi) | 1470 | struct napi_struct *napi) |
1490 | { | 1471 | { |
1491 | netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; | 1472 | netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; |
1492 | /* NAPI */ | 1473 | /* NAPI */ |
1493 | netif_napi_add(netdev, napi, | 1474 | netif_napi_add(netdev, napi, |
1494 | gelic_net_poll, GELIC_NET_NAPI_WEIGHT); | 1475 | gelic_net_poll, GELIC_NET_NAPI_WEIGHT); |
1495 | netdev->ethtool_ops = &gelic_ether_ethtool_ops; | 1476 | netdev->ethtool_ops = &gelic_ether_ethtool_ops; |
1496 | netdev->netdev_ops = &gelic_netdevice_ops; | 1477 | netdev->netdev_ops = &gelic_netdevice_ops; |
1497 | } | 1478 | } |
1498 | 1479 | ||
1499 | /** | 1480 | /** |
1500 | * gelic_ether_setup_netdev - initialization of net_device | 1481 | * gelic_ether_setup_netdev - initialization of net_device |
1501 | * @netdev: net_device structure | 1482 | * @netdev: net_device structure |
1502 | * @card: card structure | 1483 | * @card: card structure |
1503 | * | 1484 | * |
1504 | * Returns 0 on success or <0 on failure | 1485 | * Returns 0 on success or <0 on failure |
1505 | * | 1486 | * |
1506 | * gelic_ether_setup_netdev initializes the net_device structure | 1487 | * gelic_ether_setup_netdev initializes the net_device structure |
1507 | * and register it. | 1488 | * and register it. |
1508 | **/ | 1489 | **/ |
1509 | int __devinit gelic_net_setup_netdev(struct net_device *netdev, | 1490 | int __devinit gelic_net_setup_netdev(struct net_device *netdev, |
1510 | struct gelic_card *card) | 1491 | struct gelic_card *card) |
1511 | { | 1492 | { |
1512 | int status; | 1493 | int status; |
1513 | u64 v1, v2; | 1494 | u64 v1, v2; |
1514 | 1495 | ||
1496 | netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM; | ||
1497 | |||
1515 | netdev->features = NETIF_F_IP_CSUM; | 1498 | netdev->features = NETIF_F_IP_CSUM; |
1499 | if (GELIC_CARD_RX_CSUM_DEFAULT) | ||
1500 | netdev->features |= NETIF_F_RXCSUM; | ||
1516 | 1501 | ||
1517 | status = lv1_net_control(bus_id(card), dev_id(card), | 1502 | status = lv1_net_control(bus_id(card), dev_id(card), |
1518 | GELIC_LV1_GET_MAC_ADDRESS, | 1503 | GELIC_LV1_GET_MAC_ADDRESS, |
1519 | 0, 0, 0, &v1, &v2); | 1504 | 0, 0, 0, &v1, &v2); |
1520 | v1 <<= 16; | 1505 | v1 <<= 16; |
1521 | if (status || !is_valid_ether_addr((u8 *)&v1)) { | 1506 | if (status || !is_valid_ether_addr((u8 *)&v1)) { |
1522 | dev_info(ctodev(card), | 1507 | dev_info(ctodev(card), |
1523 | "%s:lv1_net_control GET_MAC_ADDR failed %d\n", | 1508 | "%s:lv1_net_control GET_MAC_ADDR failed %d\n", |
1524 | __func__, status); | 1509 | __func__, status); |
1525 | return -EINVAL; | 1510 | return -EINVAL; |
1526 | } | 1511 | } |
1527 | memcpy(netdev->dev_addr, &v1, ETH_ALEN); | 1512 | memcpy(netdev->dev_addr, &v1, ETH_ALEN); |
1528 | 1513 | ||
1529 | if (card->vlan_required) { | 1514 | if (card->vlan_required) { |
1530 | netdev->hard_header_len += VLAN_HLEN; | 1515 | netdev->hard_header_len += VLAN_HLEN; |
1531 | /* | 1516 | /* |
1532 | * As vlan is internally used, | 1517 | * As vlan is internally used, |
1533 | * we can not receive vlan packets | 1518 | * we can not receive vlan packets |
1534 | */ | 1519 | */ |
1535 | netdev->features |= NETIF_F_VLAN_CHALLENGED; | 1520 | netdev->features |= NETIF_F_VLAN_CHALLENGED; |
1536 | } | 1521 | } |
1537 | 1522 | ||
1538 | status = register_netdev(netdev); | 1523 | status = register_netdev(netdev); |
1539 | if (status) { | 1524 | if (status) { |
1540 | dev_err(ctodev(card), "%s:Couldn't register %s %d\n", | 1525 | dev_err(ctodev(card), "%s:Couldn't register %s %d\n", |
1541 | __func__, netdev->name, status); | 1526 | __func__, netdev->name, status); |
1542 | return status; | 1527 | return status; |
1543 | } | 1528 | } |
1544 | dev_info(ctodev(card), "%s: MAC addr %pM\n", | 1529 | dev_info(ctodev(card), "%s: MAC addr %pM\n", |
1545 | netdev->name, netdev->dev_addr); | 1530 | netdev->name, netdev->dev_addr); |
1546 | 1531 | ||
1547 | return 0; | 1532 | return 0; |
1548 | } | 1533 | } |
1549 | 1534 | ||
1550 | /** | 1535 | /** |
1551 | * gelic_alloc_card_net - allocates net_device and card structure | 1536 | * gelic_alloc_card_net - allocates net_device and card structure |
1552 | * | 1537 | * |
1553 | * returns the card structure or NULL in case of errors | 1538 | * returns the card structure or NULL in case of errors |
1554 | * | 1539 | * |
1555 | * the card and net_device structures are linked to each other | 1540 | * the card and net_device structures are linked to each other |
1556 | */ | 1541 | */ |
1557 | #define GELIC_ALIGN (32) | 1542 | #define GELIC_ALIGN (32) |
1558 | static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **netdev) | 1543 | static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **netdev) |
1559 | { | 1544 | { |
1560 | struct gelic_card *card; | 1545 | struct gelic_card *card; |
1561 | struct gelic_port *port; | 1546 | struct gelic_port *port; |
1562 | void *p; | 1547 | void *p; |
1563 | size_t alloc_size; | 1548 | size_t alloc_size; |
1564 | /* | 1549 | /* |
1565 | * gelic requires dma descriptor is 32 bytes aligned and | 1550 | * gelic requires dma descriptor is 32 bytes aligned and |
1566 | * the hypervisor requires irq_status is 8 bytes aligned. | 1551 | * the hypervisor requires irq_status is 8 bytes aligned. |
1567 | */ | 1552 | */ |
1568 | BUILD_BUG_ON(offsetof(struct gelic_card, irq_status) % 8); | 1553 | BUILD_BUG_ON(offsetof(struct gelic_card, irq_status) % 8); |
1569 | BUILD_BUG_ON(offsetof(struct gelic_card, descr) % 32); | 1554 | BUILD_BUG_ON(offsetof(struct gelic_card, descr) % 32); |
1570 | alloc_size = | 1555 | alloc_size = |
1571 | sizeof(struct gelic_card) + | 1556 | sizeof(struct gelic_card) + |
1572 | sizeof(struct gelic_descr) * GELIC_NET_RX_DESCRIPTORS + | 1557 | sizeof(struct gelic_descr) * GELIC_NET_RX_DESCRIPTORS + |
1573 | sizeof(struct gelic_descr) * GELIC_NET_TX_DESCRIPTORS + | 1558 | sizeof(struct gelic_descr) * GELIC_NET_TX_DESCRIPTORS + |
1574 | GELIC_ALIGN - 1; | 1559 | GELIC_ALIGN - 1; |
1575 | 1560 | ||
1576 | p = kzalloc(alloc_size, GFP_KERNEL); | 1561 | p = kzalloc(alloc_size, GFP_KERNEL); |
1577 | if (!p) | 1562 | if (!p) |
1578 | return NULL; | 1563 | return NULL; |
1579 | card = PTR_ALIGN(p, GELIC_ALIGN); | 1564 | card = PTR_ALIGN(p, GELIC_ALIGN); |
1580 | card->unalign = p; | 1565 | card->unalign = p; |
1581 | 1566 | ||
1582 | /* | 1567 | /* |
1583 | * alloc netdev | 1568 | * alloc netdev |
1584 | */ | 1569 | */ |
1585 | *netdev = alloc_etherdev(sizeof(struct gelic_port)); | 1570 | *netdev = alloc_etherdev(sizeof(struct gelic_port)); |
1586 | if (!netdev) { | 1571 | if (!netdev) { |
1587 | kfree(card->unalign); | 1572 | kfree(card->unalign); |
1588 | return NULL; | 1573 | return NULL; |
1589 | } | 1574 | } |
1590 | port = netdev_priv(*netdev); | 1575 | port = netdev_priv(*netdev); |
1591 | 1576 | ||
1592 | /* gelic_port */ | 1577 | /* gelic_port */ |
1593 | port->netdev = *netdev; | 1578 | port->netdev = *netdev; |
1594 | port->card = card; | 1579 | port->card = card; |
1595 | port->type = GELIC_PORT_ETHERNET_0; | 1580 | port->type = GELIC_PORT_ETHERNET_0; |
1596 | 1581 | ||
1597 | /* gelic_card */ | 1582 | /* gelic_card */ |
1598 | card->netdev[GELIC_PORT_ETHERNET_0] = *netdev; | 1583 | card->netdev[GELIC_PORT_ETHERNET_0] = *netdev; |
1599 | 1584 | ||
1600 | INIT_WORK(&card->tx_timeout_task, gelic_net_tx_timeout_task); | 1585 | INIT_WORK(&card->tx_timeout_task, gelic_net_tx_timeout_task); |
1601 | init_waitqueue_head(&card->waitq); | 1586 | init_waitqueue_head(&card->waitq); |
1602 | atomic_set(&card->tx_timeout_task_counter, 0); | 1587 | atomic_set(&card->tx_timeout_task_counter, 0); |
1603 | mutex_init(&card->updown_lock); | 1588 | mutex_init(&card->updown_lock); |
1604 | atomic_set(&card->users, 0); | 1589 | atomic_set(&card->users, 0); |
1605 | 1590 | ||
1606 | return card; | 1591 | return card; |
1607 | } | 1592 | } |
1608 | 1593 | ||
1609 | static void __devinit gelic_card_get_vlan_info(struct gelic_card *card) | 1594 | static void __devinit gelic_card_get_vlan_info(struct gelic_card *card) |
1610 | { | 1595 | { |
1611 | u64 v1, v2; | 1596 | u64 v1, v2; |
1612 | int status; | 1597 | int status; |
1613 | unsigned int i; | 1598 | unsigned int i; |
1614 | struct { | 1599 | struct { |
1615 | int tx; | 1600 | int tx; |
1616 | int rx; | 1601 | int rx; |
1617 | } vlan_id_ix[2] = { | 1602 | } vlan_id_ix[2] = { |
1618 | [GELIC_PORT_ETHERNET_0] = { | 1603 | [GELIC_PORT_ETHERNET_0] = { |
1619 | .tx = GELIC_LV1_VLAN_TX_ETHERNET_0, | 1604 | .tx = GELIC_LV1_VLAN_TX_ETHERNET_0, |
1620 | .rx = GELIC_LV1_VLAN_RX_ETHERNET_0 | 1605 | .rx = GELIC_LV1_VLAN_RX_ETHERNET_0 |
1621 | }, | 1606 | }, |
1622 | [GELIC_PORT_WIRELESS] = { | 1607 | [GELIC_PORT_WIRELESS] = { |
1623 | .tx = GELIC_LV1_VLAN_TX_WIRELESS, | 1608 | .tx = GELIC_LV1_VLAN_TX_WIRELESS, |
1624 | .rx = GELIC_LV1_VLAN_RX_WIRELESS | 1609 | .rx = GELIC_LV1_VLAN_RX_WIRELESS |
1625 | } | 1610 | } |
1626 | }; | 1611 | }; |
1627 | 1612 | ||
1628 | for (i = 0; i < ARRAY_SIZE(vlan_id_ix); i++) { | 1613 | for (i = 0; i < ARRAY_SIZE(vlan_id_ix); i++) { |
1629 | /* tx tag */ | 1614 | /* tx tag */ |
1630 | status = lv1_net_control(bus_id(card), dev_id(card), | 1615 | status = lv1_net_control(bus_id(card), dev_id(card), |
1631 | GELIC_LV1_GET_VLAN_ID, | 1616 | GELIC_LV1_GET_VLAN_ID, |
1632 | vlan_id_ix[i].tx, | 1617 | vlan_id_ix[i].tx, |
1633 | 0, 0, &v1, &v2); | 1618 | 0, 0, &v1, &v2); |
1634 | if (status || !v1) { | 1619 | if (status || !v1) { |
1635 | if (status != LV1_NO_ENTRY) | 1620 | if (status != LV1_NO_ENTRY) |
1636 | dev_dbg(ctodev(card), | 1621 | dev_dbg(ctodev(card), |
1637 | "get vlan id for tx(%d) failed(%d)\n", | 1622 | "get vlan id for tx(%d) failed(%d)\n", |
1638 | vlan_id_ix[i].tx, status); | 1623 | vlan_id_ix[i].tx, status); |
1639 | card->vlan[i].tx = 0; | 1624 | card->vlan[i].tx = 0; |
1640 | card->vlan[i].rx = 0; | 1625 | card->vlan[i].rx = 0; |
1641 | continue; | 1626 | continue; |
1642 | } | 1627 | } |
1643 | card->vlan[i].tx = (u16)v1; | 1628 | card->vlan[i].tx = (u16)v1; |
1644 | 1629 | ||
1645 | /* rx tag */ | 1630 | /* rx tag */ |
1646 | status = lv1_net_control(bus_id(card), dev_id(card), | 1631 | status = lv1_net_control(bus_id(card), dev_id(card), |
1647 | GELIC_LV1_GET_VLAN_ID, | 1632 | GELIC_LV1_GET_VLAN_ID, |
1648 | vlan_id_ix[i].rx, | 1633 | vlan_id_ix[i].rx, |
1649 | 0, 0, &v1, &v2); | 1634 | 0, 0, &v1, &v2); |
1650 | if (status || !v1) { | 1635 | if (status || !v1) { |
1651 | if (status != LV1_NO_ENTRY) | 1636 | if (status != LV1_NO_ENTRY) |
1652 | dev_info(ctodev(card), | 1637 | dev_info(ctodev(card), |
1653 | "get vlan id for rx(%d) failed(%d)\n", | 1638 | "get vlan id for rx(%d) failed(%d)\n", |
1654 | vlan_id_ix[i].rx, status); | 1639 | vlan_id_ix[i].rx, status); |
1655 | card->vlan[i].tx = 0; | 1640 | card->vlan[i].tx = 0; |
1656 | card->vlan[i].rx = 0; | 1641 | card->vlan[i].rx = 0; |
1657 | continue; | 1642 | continue; |
1658 | } | 1643 | } |
1659 | card->vlan[i].rx = (u16)v1; | 1644 | card->vlan[i].rx = (u16)v1; |
1660 | 1645 | ||
1661 | dev_dbg(ctodev(card), "vlan_id[%d] tx=%02x rx=%02x\n", | 1646 | dev_dbg(ctodev(card), "vlan_id[%d] tx=%02x rx=%02x\n", |
1662 | i, card->vlan[i].tx, card->vlan[i].rx); | 1647 | i, card->vlan[i].tx, card->vlan[i].rx); |
1663 | } | 1648 | } |
1664 | 1649 | ||
1665 | if (card->vlan[GELIC_PORT_ETHERNET_0].tx) { | 1650 | if (card->vlan[GELIC_PORT_ETHERNET_0].tx) { |
1666 | BUG_ON(!card->vlan[GELIC_PORT_WIRELESS].tx); | 1651 | BUG_ON(!card->vlan[GELIC_PORT_WIRELESS].tx); |
1667 | card->vlan_required = 1; | 1652 | card->vlan_required = 1; |
1668 | } else | 1653 | } else |
1669 | card->vlan_required = 0; | 1654 | card->vlan_required = 0; |
1670 | 1655 | ||
1671 | /* check wirelss capable firmware */ | 1656 | /* check wirelss capable firmware */ |
1672 | if (ps3_compare_firmware_version(1, 6, 0) < 0) { | 1657 | if (ps3_compare_firmware_version(1, 6, 0) < 0) { |
1673 | card->vlan[GELIC_PORT_WIRELESS].tx = 0; | 1658 | card->vlan[GELIC_PORT_WIRELESS].tx = 0; |
1674 | card->vlan[GELIC_PORT_WIRELESS].rx = 0; | 1659 | card->vlan[GELIC_PORT_WIRELESS].rx = 0; |
1675 | } | 1660 | } |
1676 | 1661 | ||
1677 | dev_info(ctodev(card), "internal vlan %s\n", | 1662 | dev_info(ctodev(card), "internal vlan %s\n", |
1678 | card->vlan_required? "enabled" : "disabled"); | 1663 | card->vlan_required? "enabled" : "disabled"); |
1679 | } | 1664 | } |
1680 | /** | 1665 | /** |
1681 | * ps3_gelic_driver_probe - add a device to the control of this driver | 1666 | * ps3_gelic_driver_probe - add a device to the control of this driver |
1682 | */ | 1667 | */ |
1683 | static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) | 1668 | static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) |
1684 | { | 1669 | { |
1685 | struct gelic_card *card; | 1670 | struct gelic_card *card; |
1686 | struct net_device *netdev; | 1671 | struct net_device *netdev; |
1687 | int result; | 1672 | int result; |
1688 | 1673 | ||
1689 | pr_debug("%s: called\n", __func__); | 1674 | pr_debug("%s: called\n", __func__); |
1690 | result = ps3_open_hv_device(dev); | 1675 | result = ps3_open_hv_device(dev); |
1691 | 1676 | ||
1692 | if (result) { | 1677 | if (result) { |
1693 | dev_dbg(&dev->core, "%s:ps3_open_hv_device failed\n", | 1678 | dev_dbg(&dev->core, "%s:ps3_open_hv_device failed\n", |
1694 | __func__); | 1679 | __func__); |
1695 | goto fail_open; | 1680 | goto fail_open; |
1696 | } | 1681 | } |
1697 | 1682 | ||
1698 | result = ps3_dma_region_create(dev->d_region); | 1683 | result = ps3_dma_region_create(dev->d_region); |
1699 | 1684 | ||
1700 | if (result) { | 1685 | if (result) { |
1701 | dev_dbg(&dev->core, "%s:ps3_dma_region_create failed(%d)\n", | 1686 | dev_dbg(&dev->core, "%s:ps3_dma_region_create failed(%d)\n", |
1702 | __func__, result); | 1687 | __func__, result); |
1703 | BUG_ON("check region type"); | 1688 | BUG_ON("check region type"); |
1704 | goto fail_dma_region; | 1689 | goto fail_dma_region; |
1705 | } | 1690 | } |
1706 | 1691 | ||
1707 | /* alloc card/netdevice */ | 1692 | /* alloc card/netdevice */ |
1708 | card = gelic_alloc_card_net(&netdev); | 1693 | card = gelic_alloc_card_net(&netdev); |
1709 | if (!card) { | 1694 | if (!card) { |
1710 | dev_info(&dev->core, "%s:gelic_net_alloc_card failed\n", | 1695 | dev_info(&dev->core, "%s:gelic_net_alloc_card failed\n", |
1711 | __func__); | 1696 | __func__); |
1712 | result = -ENOMEM; | 1697 | result = -ENOMEM; |
1713 | goto fail_alloc_card; | 1698 | goto fail_alloc_card; |
1714 | } | 1699 | } |
1715 | ps3_system_bus_set_drvdata(dev, card); | 1700 | ps3_system_bus_set_drvdata(dev, card); |
1716 | card->dev = dev; | 1701 | card->dev = dev; |
1717 | 1702 | ||
1718 | /* get internal vlan info */ | 1703 | /* get internal vlan info */ |
1719 | gelic_card_get_vlan_info(card); | 1704 | gelic_card_get_vlan_info(card); |
1720 | 1705 | ||
1721 | card->link_mode = GELIC_LV1_ETHER_AUTO_NEG; | 1706 | card->link_mode = GELIC_LV1_ETHER_AUTO_NEG; |
1722 | 1707 | ||
1723 | /* setup interrupt */ | 1708 | /* setup interrupt */ |
1724 | result = lv1_net_set_interrupt_status_indicator(bus_id(card), | 1709 | result = lv1_net_set_interrupt_status_indicator(bus_id(card), |
1725 | dev_id(card), | 1710 | dev_id(card), |
1726 | ps3_mm_phys_to_lpar(__pa(&card->irq_status)), | 1711 | ps3_mm_phys_to_lpar(__pa(&card->irq_status)), |
1727 | 0); | 1712 | 0); |
1728 | 1713 | ||
1729 | if (result) { | 1714 | if (result) { |
1730 | dev_dbg(&dev->core, | 1715 | dev_dbg(&dev->core, |
1731 | "%s:set_interrupt_status_indicator failed: %s\n", | 1716 | "%s:set_interrupt_status_indicator failed: %s\n", |
1732 | __func__, ps3_result(result)); | 1717 | __func__, ps3_result(result)); |
1733 | result = -EIO; | 1718 | result = -EIO; |
1734 | goto fail_status_indicator; | 1719 | goto fail_status_indicator; |
1735 | } | 1720 | } |
1736 | 1721 | ||
1737 | result = ps3_sb_event_receive_port_setup(dev, PS3_BINDING_CPU_ANY, | 1722 | result = ps3_sb_event_receive_port_setup(dev, PS3_BINDING_CPU_ANY, |
1738 | &card->irq); | 1723 | &card->irq); |
1739 | 1724 | ||
1740 | if (result) { | 1725 | if (result) { |
1741 | dev_info(ctodev(card), | 1726 | dev_info(ctodev(card), |
1742 | "%s:gelic_net_open_device failed (%d)\n", | 1727 | "%s:gelic_net_open_device failed (%d)\n", |
1743 | __func__, result); | 1728 | __func__, result); |
1744 | result = -EPERM; | 1729 | result = -EPERM; |
1745 | goto fail_alloc_irq; | 1730 | goto fail_alloc_irq; |
1746 | } | 1731 | } |
1747 | result = request_irq(card->irq, gelic_card_interrupt, | 1732 | result = request_irq(card->irq, gelic_card_interrupt, |
1748 | IRQF_DISABLED, netdev->name, card); | 1733 | IRQF_DISABLED, netdev->name, card); |
1749 | 1734 | ||
1750 | if (result) { | 1735 | if (result) { |
1751 | dev_info(ctodev(card), "%s:request_irq failed (%d)\n", | 1736 | dev_info(ctodev(card), "%s:request_irq failed (%d)\n", |
1752 | __func__, result); | 1737 | __func__, result); |
1753 | goto fail_request_irq; | 1738 | goto fail_request_irq; |
1754 | } | 1739 | } |
1755 | 1740 | ||
1756 | /* setup card structure */ | 1741 | /* setup card structure */ |
1757 | card->irq_mask = GELIC_CARD_RXINT | GELIC_CARD_TXINT | | 1742 | card->irq_mask = GELIC_CARD_RXINT | GELIC_CARD_TXINT | |
1758 | GELIC_CARD_PORT_STATUS_CHANGED; | 1743 | GELIC_CARD_PORT_STATUS_CHANGED; |
1759 | card->rx_csum = GELIC_CARD_RX_CSUM_DEFAULT; | ||
1760 | 1744 | ||
1761 | 1745 | ||
1762 | if (gelic_card_init_chain(card, &card->tx_chain, | 1746 | if (gelic_card_init_chain(card, &card->tx_chain, |
1763 | card->descr, GELIC_NET_TX_DESCRIPTORS)) | 1747 | card->descr, GELIC_NET_TX_DESCRIPTORS)) |
1764 | goto fail_alloc_tx; | 1748 | goto fail_alloc_tx; |
1765 | if (gelic_card_init_chain(card, &card->rx_chain, | 1749 | if (gelic_card_init_chain(card, &card->rx_chain, |
1766 | card->descr + GELIC_NET_TX_DESCRIPTORS, | 1750 | card->descr + GELIC_NET_TX_DESCRIPTORS, |
1767 | GELIC_NET_RX_DESCRIPTORS)) | 1751 | GELIC_NET_RX_DESCRIPTORS)) |
1768 | goto fail_alloc_rx; | 1752 | goto fail_alloc_rx; |
1769 | 1753 | ||
1770 | /* head of chain */ | 1754 | /* head of chain */ |
1771 | card->tx_top = card->tx_chain.head; | 1755 | card->tx_top = card->tx_chain.head; |
1772 | card->rx_top = card->rx_chain.head; | 1756 | card->rx_top = card->rx_chain.head; |
1773 | dev_dbg(ctodev(card), "descr rx %p, tx %p, size %#lx, num %#x\n", | 1757 | dev_dbg(ctodev(card), "descr rx %p, tx %p, size %#lx, num %#x\n", |
1774 | card->rx_top, card->tx_top, sizeof(struct gelic_descr), | 1758 | card->rx_top, card->tx_top, sizeof(struct gelic_descr), |
1775 | GELIC_NET_RX_DESCRIPTORS); | 1759 | GELIC_NET_RX_DESCRIPTORS); |
1776 | /* allocate rx skbs */ | 1760 | /* allocate rx skbs */ |
1777 | if (gelic_card_alloc_rx_skbs(card)) | 1761 | if (gelic_card_alloc_rx_skbs(card)) |
1778 | goto fail_alloc_skbs; | 1762 | goto fail_alloc_skbs; |
1779 | 1763 | ||
1780 | spin_lock_init(&card->tx_lock); | 1764 | spin_lock_init(&card->tx_lock); |
1781 | card->tx_dma_progress = 0; | 1765 | card->tx_dma_progress = 0; |
1782 | 1766 | ||
1783 | /* setup net_device structure */ | 1767 | /* setup net_device structure */ |
1784 | netdev->irq = card->irq; | 1768 | netdev->irq = card->irq; |
1785 | SET_NETDEV_DEV(netdev, &card->dev->core); | 1769 | SET_NETDEV_DEV(netdev, &card->dev->core); |
1786 | gelic_ether_setup_netdev_ops(netdev, &card->napi); | 1770 | gelic_ether_setup_netdev_ops(netdev, &card->napi); |
1787 | result = gelic_net_setup_netdev(netdev, card); | 1771 | result = gelic_net_setup_netdev(netdev, card); |
1788 | if (result) { | 1772 | if (result) { |
1789 | dev_dbg(&dev->core, "%s: setup_netdev failed %d", | 1773 | dev_dbg(&dev->core, "%s: setup_netdev failed %d", |
1790 | __func__, result); | 1774 | __func__, result); |
1791 | goto fail_setup_netdev; | 1775 | goto fail_setup_netdev; |
1792 | } | 1776 | } |
1793 | 1777 | ||
1794 | #ifdef CONFIG_GELIC_WIRELESS | 1778 | #ifdef CONFIG_GELIC_WIRELESS |
1795 | if (gelic_wl_driver_probe(card)) { | 1779 | if (gelic_wl_driver_probe(card)) { |
1796 | dev_dbg(&dev->core, "%s: WL init failed\n", __func__); | 1780 | dev_dbg(&dev->core, "%s: WL init failed\n", __func__); |
1797 | goto fail_setup_netdev; | 1781 | goto fail_setup_netdev; |
1798 | } | 1782 | } |
1799 | #endif | 1783 | #endif |
1800 | pr_debug("%s: done\n", __func__); | 1784 | pr_debug("%s: done\n", __func__); |
1801 | return 0; | 1785 | return 0; |
1802 | 1786 | ||
1803 | fail_setup_netdev: | 1787 | fail_setup_netdev: |
1804 | fail_alloc_skbs: | 1788 | fail_alloc_skbs: |
1805 | gelic_card_free_chain(card, card->rx_chain.head); | 1789 | gelic_card_free_chain(card, card->rx_chain.head); |
1806 | fail_alloc_rx: | 1790 | fail_alloc_rx: |
1807 | gelic_card_free_chain(card, card->tx_chain.head); | 1791 | gelic_card_free_chain(card, card->tx_chain.head); |
1808 | fail_alloc_tx: | 1792 | fail_alloc_tx: |
1809 | free_irq(card->irq, card); | 1793 | free_irq(card->irq, card); |
1810 | netdev->irq = NO_IRQ; | 1794 | netdev->irq = NO_IRQ; |
1811 | fail_request_irq: | 1795 | fail_request_irq: |
1812 | ps3_sb_event_receive_port_destroy(dev, card->irq); | 1796 | ps3_sb_event_receive_port_destroy(dev, card->irq); |
1813 | fail_alloc_irq: | 1797 | fail_alloc_irq: |
1814 | lv1_net_set_interrupt_status_indicator(bus_id(card), | 1798 | lv1_net_set_interrupt_status_indicator(bus_id(card), |
1815 | bus_id(card), | 1799 | bus_id(card), |
1816 | 0, 0); | 1800 | 0, 0); |
1817 | fail_status_indicator: | 1801 | fail_status_indicator: |
1818 | ps3_system_bus_set_drvdata(dev, NULL); | 1802 | ps3_system_bus_set_drvdata(dev, NULL); |
1819 | kfree(netdev_card(netdev)->unalign); | 1803 | kfree(netdev_card(netdev)->unalign); |
1820 | free_netdev(netdev); | 1804 | free_netdev(netdev); |
1821 | fail_alloc_card: | 1805 | fail_alloc_card: |
1822 | ps3_dma_region_free(dev->d_region); | 1806 | ps3_dma_region_free(dev->d_region); |
1823 | fail_dma_region: | 1807 | fail_dma_region: |
1824 | ps3_close_hv_device(dev); | 1808 | ps3_close_hv_device(dev); |
1825 | fail_open: | 1809 | fail_open: |
1826 | return result; | 1810 | return result; |
1827 | } | 1811 | } |
1828 | 1812 | ||
1829 | /** | 1813 | /** |
1830 | * ps3_gelic_driver_remove - remove a device from the control of this driver | 1814 | * ps3_gelic_driver_remove - remove a device from the control of this driver |
1831 | */ | 1815 | */ |
1832 | 1816 | ||
1833 | static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev) | 1817 | static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev) |
1834 | { | 1818 | { |
1835 | struct gelic_card *card = ps3_system_bus_get_drvdata(dev); | 1819 | struct gelic_card *card = ps3_system_bus_get_drvdata(dev); |
1836 | struct net_device *netdev0; | 1820 | struct net_device *netdev0; |
1837 | pr_debug("%s: called\n", __func__); | 1821 | pr_debug("%s: called\n", __func__); |
1838 | 1822 | ||
1839 | /* set auto-negotiation */ | 1823 | /* set auto-negotiation */ |
1840 | gelic_card_set_link_mode(card, GELIC_LV1_ETHER_AUTO_NEG); | 1824 | gelic_card_set_link_mode(card, GELIC_LV1_ETHER_AUTO_NEG); |
1841 | 1825 | ||
1842 | #ifdef CONFIG_GELIC_WIRELESS | 1826 | #ifdef CONFIG_GELIC_WIRELESS |
1843 | gelic_wl_driver_remove(card); | 1827 | gelic_wl_driver_remove(card); |
1844 | #endif | 1828 | #endif |
1845 | /* stop interrupt */ | 1829 | /* stop interrupt */ |
1846 | gelic_card_set_irq_mask(card, 0); | 1830 | gelic_card_set_irq_mask(card, 0); |
1847 | 1831 | ||
1848 | /* turn off DMA, force end */ | 1832 | /* turn off DMA, force end */ |
1849 | gelic_card_disable_rxdmac(card); | 1833 | gelic_card_disable_rxdmac(card); |
1850 | gelic_card_disable_txdmac(card); | 1834 | gelic_card_disable_txdmac(card); |
1851 | 1835 | ||
1852 | /* release chains */ | 1836 | /* release chains */ |
1853 | gelic_card_release_tx_chain(card, 1); | 1837 | gelic_card_release_tx_chain(card, 1); |
1854 | gelic_card_release_rx_chain(card); | 1838 | gelic_card_release_rx_chain(card); |
1855 | 1839 | ||
1856 | gelic_card_free_chain(card, card->tx_top); | 1840 | gelic_card_free_chain(card, card->tx_top); |
1857 | gelic_card_free_chain(card, card->rx_top); | 1841 | gelic_card_free_chain(card, card->rx_top); |
1858 | 1842 | ||
1859 | netdev0 = card->netdev[GELIC_PORT_ETHERNET_0]; | 1843 | netdev0 = card->netdev[GELIC_PORT_ETHERNET_0]; |
1860 | /* disconnect event port */ | 1844 | /* disconnect event port */ |
1861 | free_irq(card->irq, card); | 1845 | free_irq(card->irq, card); |
1862 | netdev0->irq = NO_IRQ; | 1846 | netdev0->irq = NO_IRQ; |
1863 | ps3_sb_event_receive_port_destroy(card->dev, card->irq); | 1847 | ps3_sb_event_receive_port_destroy(card->dev, card->irq); |
1864 | 1848 | ||
1865 | wait_event(card->waitq, | 1849 | wait_event(card->waitq, |
1866 | atomic_read(&card->tx_timeout_task_counter) == 0); | 1850 | atomic_read(&card->tx_timeout_task_counter) == 0); |
1867 | 1851 | ||
1868 | lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card), | 1852 | lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card), |
1869 | 0 , 0); | 1853 | 0 , 0); |
1870 | 1854 | ||
1871 | unregister_netdev(netdev0); | 1855 | unregister_netdev(netdev0); |
1872 | kfree(netdev_card(netdev0)->unalign); | 1856 | kfree(netdev_card(netdev0)->unalign); |
1873 | free_netdev(netdev0); | 1857 | free_netdev(netdev0); |
1874 | 1858 | ||
1875 | ps3_system_bus_set_drvdata(dev, NULL); | 1859 | ps3_system_bus_set_drvdata(dev, NULL); |
1876 | 1860 | ||
1877 | ps3_dma_region_free(dev->d_region); | 1861 | ps3_dma_region_free(dev->d_region); |
1878 | 1862 | ||
1879 | ps3_close_hv_device(dev); | 1863 | ps3_close_hv_device(dev); |
1880 | 1864 | ||
1881 | pr_debug("%s: done\n", __func__); | 1865 | pr_debug("%s: done\n", __func__); |
1882 | return 0; | 1866 | return 0; |
1883 | } | 1867 | } |
1884 | 1868 | ||
1885 | static struct ps3_system_bus_driver ps3_gelic_driver = { | 1869 | static struct ps3_system_bus_driver ps3_gelic_driver = { |
1886 | .match_id = PS3_MATCH_ID_GELIC, | 1870 | .match_id = PS3_MATCH_ID_GELIC, |
1887 | .probe = ps3_gelic_driver_probe, | 1871 | .probe = ps3_gelic_driver_probe, |
1888 | .remove = ps3_gelic_driver_remove, | 1872 | .remove = ps3_gelic_driver_remove, |
1889 | .shutdown = ps3_gelic_driver_remove, | 1873 | .shutdown = ps3_gelic_driver_remove, |
1890 | .core.name = "ps3_gelic_driver", | 1874 | .core.name = "ps3_gelic_driver", |
1891 | .core.owner = THIS_MODULE, | 1875 | .core.owner = THIS_MODULE, |
1892 | }; | 1876 | }; |
1893 | 1877 | ||
1894 | static int __init ps3_gelic_driver_init (void) | 1878 | static int __init ps3_gelic_driver_init (void) |
1895 | { | 1879 | { |
1896 | return firmware_has_feature(FW_FEATURE_PS3_LV1) | 1880 | return firmware_has_feature(FW_FEATURE_PS3_LV1) |
1897 | ? ps3_system_bus_driver_register(&ps3_gelic_driver) | 1881 | ? ps3_system_bus_driver_register(&ps3_gelic_driver) |
1898 | : -ENODEV; | 1882 | : -ENODEV; |
1899 | } | 1883 | } |
1900 | 1884 | ||
1901 | static void __exit ps3_gelic_driver_exit (void) | 1885 | static void __exit ps3_gelic_driver_exit (void) |
1902 | { | 1886 | { |
1903 | ps3_system_bus_driver_unregister(&ps3_gelic_driver); | 1887 | ps3_system_bus_driver_unregister(&ps3_gelic_driver); |
1904 | } | 1888 | } |
1905 | 1889 | ||
1906 | module_init(ps3_gelic_driver_init); | 1890 | module_init(ps3_gelic_driver_init); |
1907 | module_exit(ps3_gelic_driver_exit); | 1891 | module_exit(ps3_gelic_driver_exit); |
drivers/net/ps3_gelic_net.h
1 | /* | 1 | /* |
2 | * PS3 Platfom gelic network driver. | 2 | * PS3 Platfom gelic network driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
5 | * Copyright 2006, 2007 Sony Corporation. | 5 | * Copyright 2006, 2007 Sony Corporation. |
6 | * | 6 | * |
7 | * This file is based on: spider_net.h | 7 | * This file is based on: spider_net.h |
8 | * | 8 | * |
9 | * (C) Copyright IBM Corp. 2005 | 9 | * (C) Copyright IBM Corp. 2005 |
10 | * | 10 | * |
11 | * Authors : Utz Bacher <utz.bacher@de.ibm.com> | 11 | * Authors : Utz Bacher <utz.bacher@de.ibm.com> |
12 | * Jens Osterkamp <Jens.Osterkamp@de.ibm.com> | 12 | * Jens Osterkamp <Jens.Osterkamp@de.ibm.com> |
13 | * | 13 | * |
14 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by |
16 | * the Free Software Foundation; either version 2, or (at your option) | 16 | * the Free Software Foundation; either version 2, or (at your option) |
17 | * any later version. | 17 | * any later version. |
18 | * | 18 | * |
19 | * This program is distributed in the hope that it will be useful, | 19 | * This program is distributed in the hope that it will be useful, |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | * GNU General Public License for more details. | 22 | * GNU General Public License for more details. |
23 | * | 23 | * |
24 | * You should have received a copy of the GNU General Public License | 24 | * You should have received a copy of the GNU General Public License |
25 | * along with this program; if not, write to the Free Software | 25 | * along with this program; if not, write to the Free Software |
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
27 | */ | 27 | */ |
28 | #ifndef _GELIC_NET_H | 28 | #ifndef _GELIC_NET_H |
29 | #define _GELIC_NET_H | 29 | #define _GELIC_NET_H |
30 | 30 | ||
31 | /* descriptors */ | 31 | /* descriptors */ |
32 | #define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */ | 32 | #define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */ |
33 | #define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */ | 33 | #define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */ |
34 | 34 | ||
35 | #define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN | 35 | #define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN |
36 | #define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN | 36 | #define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN |
37 | #define GELIC_NET_RXBUF_ALIGN 128 | 37 | #define GELIC_NET_RXBUF_ALIGN 128 |
38 | #define GELIC_CARD_RX_CSUM_DEFAULT 1 /* hw chksum */ | 38 | #define GELIC_CARD_RX_CSUM_DEFAULT 1 /* hw chksum */ |
39 | #define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ | 39 | #define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ |
40 | #define GELIC_NET_NAPI_WEIGHT (GELIC_NET_RX_DESCRIPTORS) | 40 | #define GELIC_NET_NAPI_WEIGHT (GELIC_NET_RX_DESCRIPTORS) |
41 | #define GELIC_NET_BROADCAST_ADDR 0xffffffffffffL | 41 | #define GELIC_NET_BROADCAST_ADDR 0xffffffffffffL |
42 | 42 | ||
43 | #define GELIC_NET_MC_COUNT_MAX 32 /* multicast address list */ | 43 | #define GELIC_NET_MC_COUNT_MAX 32 /* multicast address list */ |
44 | 44 | ||
45 | /* virtual interrupt status register bits */ | 45 | /* virtual interrupt status register bits */ |
46 | /* INT1 */ | 46 | /* INT1 */ |
47 | #define GELIC_CARD_TX_RAM_FULL_ERR 0x0000000000000001L | 47 | #define GELIC_CARD_TX_RAM_FULL_ERR 0x0000000000000001L |
48 | #define GELIC_CARD_RX_RAM_FULL_ERR 0x0000000000000002L | 48 | #define GELIC_CARD_RX_RAM_FULL_ERR 0x0000000000000002L |
49 | #define GELIC_CARD_TX_SHORT_FRAME_ERR 0x0000000000000004L | 49 | #define GELIC_CARD_TX_SHORT_FRAME_ERR 0x0000000000000004L |
50 | #define GELIC_CARD_TX_INVALID_DESCR_ERR 0x0000000000000008L | 50 | #define GELIC_CARD_TX_INVALID_DESCR_ERR 0x0000000000000008L |
51 | #define GELIC_CARD_RX_FIFO_FULL_ERR 0x0000000000002000L | 51 | #define GELIC_CARD_RX_FIFO_FULL_ERR 0x0000000000002000L |
52 | #define GELIC_CARD_RX_DESCR_CHAIN_END 0x0000000000004000L | 52 | #define GELIC_CARD_RX_DESCR_CHAIN_END 0x0000000000004000L |
53 | #define GELIC_CARD_RX_INVALID_DESCR_ERR 0x0000000000008000L | 53 | #define GELIC_CARD_RX_INVALID_DESCR_ERR 0x0000000000008000L |
54 | #define GELIC_CARD_TX_RESPONCE_ERR 0x0000000000010000L | 54 | #define GELIC_CARD_TX_RESPONCE_ERR 0x0000000000010000L |
55 | #define GELIC_CARD_RX_RESPONCE_ERR 0x0000000000100000L | 55 | #define GELIC_CARD_RX_RESPONCE_ERR 0x0000000000100000L |
56 | #define GELIC_CARD_TX_PROTECTION_ERR 0x0000000000400000L | 56 | #define GELIC_CARD_TX_PROTECTION_ERR 0x0000000000400000L |
57 | #define GELIC_CARD_RX_PROTECTION_ERR 0x0000000004000000L | 57 | #define GELIC_CARD_RX_PROTECTION_ERR 0x0000000004000000L |
58 | #define GELIC_CARD_TX_TCP_UDP_CHECKSUM_ERR 0x0000000008000000L | 58 | #define GELIC_CARD_TX_TCP_UDP_CHECKSUM_ERR 0x0000000008000000L |
59 | #define GELIC_CARD_PORT_STATUS_CHANGED 0x0000000020000000L | 59 | #define GELIC_CARD_PORT_STATUS_CHANGED 0x0000000020000000L |
60 | #define GELIC_CARD_WLAN_EVENT_RECEIVED 0x0000000040000000L | 60 | #define GELIC_CARD_WLAN_EVENT_RECEIVED 0x0000000040000000L |
61 | #define GELIC_CARD_WLAN_COMMAND_COMPLETED 0x0000000080000000L | 61 | #define GELIC_CARD_WLAN_COMMAND_COMPLETED 0x0000000080000000L |
62 | /* INT 0 */ | 62 | /* INT 0 */ |
63 | #define GELIC_CARD_TX_FLAGGED_DESCR 0x0004000000000000L | 63 | #define GELIC_CARD_TX_FLAGGED_DESCR 0x0004000000000000L |
64 | #define GELIC_CARD_RX_FLAGGED_DESCR 0x0040000000000000L | 64 | #define GELIC_CARD_RX_FLAGGED_DESCR 0x0040000000000000L |
65 | #define GELIC_CARD_TX_TRANSFER_END 0x0080000000000000L | 65 | #define GELIC_CARD_TX_TRANSFER_END 0x0080000000000000L |
66 | #define GELIC_CARD_TX_DESCR_CHAIN_END 0x0100000000000000L | 66 | #define GELIC_CARD_TX_DESCR_CHAIN_END 0x0100000000000000L |
67 | #define GELIC_CARD_NUMBER_OF_RX_FRAME 0x1000000000000000L | 67 | #define GELIC_CARD_NUMBER_OF_RX_FRAME 0x1000000000000000L |
68 | #define GELIC_CARD_ONE_TIME_COUNT_TIMER 0x4000000000000000L | 68 | #define GELIC_CARD_ONE_TIME_COUNT_TIMER 0x4000000000000000L |
69 | #define GELIC_CARD_FREE_RUN_COUNT_TIMER 0x8000000000000000L | 69 | #define GELIC_CARD_FREE_RUN_COUNT_TIMER 0x8000000000000000L |
70 | 70 | ||
71 | /* initial interrupt mask */ | 71 | /* initial interrupt mask */ |
72 | #define GELIC_CARD_TXINT GELIC_CARD_TX_DESCR_CHAIN_END | 72 | #define GELIC_CARD_TXINT GELIC_CARD_TX_DESCR_CHAIN_END |
73 | 73 | ||
74 | #define GELIC_CARD_RXINT (GELIC_CARD_RX_DESCR_CHAIN_END | \ | 74 | #define GELIC_CARD_RXINT (GELIC_CARD_RX_DESCR_CHAIN_END | \ |
75 | GELIC_CARD_NUMBER_OF_RX_FRAME) | 75 | GELIC_CARD_NUMBER_OF_RX_FRAME) |
76 | 76 | ||
77 | /* RX descriptor data_status bits */ | 77 | /* RX descriptor data_status bits */ |
78 | enum gelic_descr_rx_status { | 78 | enum gelic_descr_rx_status { |
79 | GELIC_DESCR_RXDMADU = 0x80000000, /* destination MAC addr unknown */ | 79 | GELIC_DESCR_RXDMADU = 0x80000000, /* destination MAC addr unknown */ |
80 | GELIC_DESCR_RXLSTFBF = 0x40000000, /* last frame buffer */ | 80 | GELIC_DESCR_RXLSTFBF = 0x40000000, /* last frame buffer */ |
81 | GELIC_DESCR_RXIPCHK = 0x20000000, /* IP checksum performed */ | 81 | GELIC_DESCR_RXIPCHK = 0x20000000, /* IP checksum performed */ |
82 | GELIC_DESCR_RXTCPCHK = 0x10000000, /* TCP/UDP checksup performed */ | 82 | GELIC_DESCR_RXTCPCHK = 0x10000000, /* TCP/UDP checksup performed */ |
83 | GELIC_DESCR_RXWTPKT = 0x00C00000, /* | 83 | GELIC_DESCR_RXWTPKT = 0x00C00000, /* |
84 | * wakeup trigger packet | 84 | * wakeup trigger packet |
85 | * 01: Magic Packet (TM) | 85 | * 01: Magic Packet (TM) |
86 | * 10: ARP packet | 86 | * 10: ARP packet |
87 | * 11: Multicast MAC addr | 87 | * 11: Multicast MAC addr |
88 | */ | 88 | */ |
89 | GELIC_DESCR_RXVLNPKT = 0x00200000, /* VLAN packet */ | 89 | GELIC_DESCR_RXVLNPKT = 0x00200000, /* VLAN packet */ |
90 | /* bit 20..16 reserved */ | 90 | /* bit 20..16 reserved */ |
91 | GELIC_DESCR_RXRRECNUM = 0x0000ff00, /* reception receipt number */ | 91 | GELIC_DESCR_RXRRECNUM = 0x0000ff00, /* reception receipt number */ |
92 | /* bit 7..0 reserved */ | 92 | /* bit 7..0 reserved */ |
93 | }; | 93 | }; |
94 | 94 | ||
95 | #define GELIC_DESCR_DATA_STATUS_CHK_MASK \ | 95 | #define GELIC_DESCR_DATA_STATUS_CHK_MASK \ |
96 | (GELIC_DESCR_RXIPCHK | GELIC_DESCR_RXTCPCHK) | 96 | (GELIC_DESCR_RXIPCHK | GELIC_DESCR_RXTCPCHK) |
97 | 97 | ||
98 | /* TX descriptor data_status bits */ | 98 | /* TX descriptor data_status bits */ |
99 | enum gelic_descr_tx_status { | 99 | enum gelic_descr_tx_status { |
100 | GELIC_DESCR_TX_TAIL = 0x00000001, /* gelic treated this | 100 | GELIC_DESCR_TX_TAIL = 0x00000001, /* gelic treated this |
101 | * descriptor was end of | 101 | * descriptor was end of |
102 | * a tx frame | 102 | * a tx frame |
103 | */ | 103 | */ |
104 | }; | 104 | }; |
105 | 105 | ||
106 | /* RX descriptor data error bits */ | 106 | /* RX descriptor data error bits */ |
107 | enum gelic_descr_rx_error { | 107 | enum gelic_descr_rx_error { |
108 | /* bit 31 reserved */ | 108 | /* bit 31 reserved */ |
109 | GELIC_DESCR_RXALNERR = 0x40000000, /* alignement error 10/100M */ | 109 | GELIC_DESCR_RXALNERR = 0x40000000, /* alignement error 10/100M */ |
110 | GELIC_DESCR_RXOVERERR = 0x20000000, /* oversize error */ | 110 | GELIC_DESCR_RXOVERERR = 0x20000000, /* oversize error */ |
111 | GELIC_DESCR_RXRNTERR = 0x10000000, /* Runt error */ | 111 | GELIC_DESCR_RXRNTERR = 0x10000000, /* Runt error */ |
112 | GELIC_DESCR_RXIPCHKERR = 0x08000000, /* IP checksum error */ | 112 | GELIC_DESCR_RXIPCHKERR = 0x08000000, /* IP checksum error */ |
113 | GELIC_DESCR_RXTCPCHKERR = 0x04000000, /* TCP/UDP checksum error */ | 113 | GELIC_DESCR_RXTCPCHKERR = 0x04000000, /* TCP/UDP checksum error */ |
114 | GELIC_DESCR_RXDRPPKT = 0x00100000, /* drop packet */ | 114 | GELIC_DESCR_RXDRPPKT = 0x00100000, /* drop packet */ |
115 | GELIC_DESCR_RXIPFMTERR = 0x00080000, /* IP packet format error */ | 115 | GELIC_DESCR_RXIPFMTERR = 0x00080000, /* IP packet format error */ |
116 | /* bit 18 reserved */ | 116 | /* bit 18 reserved */ |
117 | GELIC_DESCR_RXDATAERR = 0x00020000, /* IP packet format error */ | 117 | GELIC_DESCR_RXDATAERR = 0x00020000, /* IP packet format error */ |
118 | GELIC_DESCR_RXCALERR = 0x00010000, /* cariier extension length | 118 | GELIC_DESCR_RXCALERR = 0x00010000, /* cariier extension length |
119 | * error */ | 119 | * error */ |
120 | GELIC_DESCR_RXCREXERR = 0x00008000, /* carrier extension error */ | 120 | GELIC_DESCR_RXCREXERR = 0x00008000, /* carrier extension error */ |
121 | GELIC_DESCR_RXMLTCST = 0x00004000, /* multicast address frame */ | 121 | GELIC_DESCR_RXMLTCST = 0x00004000, /* multicast address frame */ |
122 | /* bit 13..0 reserved */ | 122 | /* bit 13..0 reserved */ |
123 | }; | 123 | }; |
124 | #define GELIC_DESCR_DATA_ERROR_CHK_MASK \ | 124 | #define GELIC_DESCR_DATA_ERROR_CHK_MASK \ |
125 | (GELIC_DESCR_RXIPCHKERR | GELIC_DESCR_RXTCPCHKERR) | 125 | (GELIC_DESCR_RXIPCHKERR | GELIC_DESCR_RXTCPCHKERR) |
126 | 126 | ||
127 | /* DMA command and status (RX and TX)*/ | 127 | /* DMA command and status (RX and TX)*/ |
128 | enum gelic_descr_dma_status { | 128 | enum gelic_descr_dma_status { |
129 | GELIC_DESCR_DMA_COMPLETE = 0x00000000, /* used in tx */ | 129 | GELIC_DESCR_DMA_COMPLETE = 0x00000000, /* used in tx */ |
130 | GELIC_DESCR_DMA_BUFFER_FULL = 0x00000000, /* used in rx */ | 130 | GELIC_DESCR_DMA_BUFFER_FULL = 0x00000000, /* used in rx */ |
131 | GELIC_DESCR_DMA_RESPONSE_ERROR = 0x10000000, /* used in rx, tx */ | 131 | GELIC_DESCR_DMA_RESPONSE_ERROR = 0x10000000, /* used in rx, tx */ |
132 | GELIC_DESCR_DMA_PROTECTION_ERROR = 0x20000000, /* used in rx, tx */ | 132 | GELIC_DESCR_DMA_PROTECTION_ERROR = 0x20000000, /* used in rx, tx */ |
133 | GELIC_DESCR_DMA_FRAME_END = 0x40000000, /* used in rx */ | 133 | GELIC_DESCR_DMA_FRAME_END = 0x40000000, /* used in rx */ |
134 | GELIC_DESCR_DMA_FORCE_END = 0x50000000, /* used in rx, tx */ | 134 | GELIC_DESCR_DMA_FORCE_END = 0x50000000, /* used in rx, tx */ |
135 | GELIC_DESCR_DMA_CARDOWNED = 0xa0000000, /* used in rx, tx */ | 135 | GELIC_DESCR_DMA_CARDOWNED = 0xa0000000, /* used in rx, tx */ |
136 | GELIC_DESCR_DMA_NOT_IN_USE = 0xb0000000, /* any other value */ | 136 | GELIC_DESCR_DMA_NOT_IN_USE = 0xb0000000, /* any other value */ |
137 | }; | 137 | }; |
138 | 138 | ||
139 | #define GELIC_DESCR_DMA_STAT_MASK (0xf0000000) | 139 | #define GELIC_DESCR_DMA_STAT_MASK (0xf0000000) |
140 | 140 | ||
141 | /* tx descriptor command and status */ | 141 | /* tx descriptor command and status */ |
142 | enum gelic_descr_tx_dma_status { | 142 | enum gelic_descr_tx_dma_status { |
143 | /* [19] */ | 143 | /* [19] */ |
144 | GELIC_DESCR_TX_DMA_IKE = 0x00080000, /* IPSEC off */ | 144 | GELIC_DESCR_TX_DMA_IKE = 0x00080000, /* IPSEC off */ |
145 | /* [18] */ | 145 | /* [18] */ |
146 | GELIC_DESCR_TX_DMA_FRAME_TAIL = 0x00040000, /* last descriptor of | 146 | GELIC_DESCR_TX_DMA_FRAME_TAIL = 0x00040000, /* last descriptor of |
147 | * the packet | 147 | * the packet |
148 | */ | 148 | */ |
149 | /* [17..16] */ | 149 | /* [17..16] */ |
150 | GELIC_DESCR_TX_DMA_TCP_CHKSUM = 0x00020000, /* TCP packet */ | 150 | GELIC_DESCR_TX_DMA_TCP_CHKSUM = 0x00020000, /* TCP packet */ |
151 | GELIC_DESCR_TX_DMA_UDP_CHKSUM = 0x00030000, /* UDP packet */ | 151 | GELIC_DESCR_TX_DMA_UDP_CHKSUM = 0x00030000, /* UDP packet */ |
152 | GELIC_DESCR_TX_DMA_NO_CHKSUM = 0x00000000, /* no checksum */ | 152 | GELIC_DESCR_TX_DMA_NO_CHKSUM = 0x00000000, /* no checksum */ |
153 | 153 | ||
154 | /* [1] */ | 154 | /* [1] */ |
155 | GELIC_DESCR_TX_DMA_CHAIN_END = 0x00000002, /* DMA terminated | 155 | GELIC_DESCR_TX_DMA_CHAIN_END = 0x00000002, /* DMA terminated |
156 | * due to chain end | 156 | * due to chain end |
157 | */ | 157 | */ |
158 | }; | 158 | }; |
159 | 159 | ||
160 | #define GELIC_DESCR_DMA_CMD_NO_CHKSUM \ | 160 | #define GELIC_DESCR_DMA_CMD_NO_CHKSUM \ |
161 | (GELIC_DESCR_DMA_CARDOWNED | GELIC_DESCR_TX_DMA_IKE | \ | 161 | (GELIC_DESCR_DMA_CARDOWNED | GELIC_DESCR_TX_DMA_IKE | \ |
162 | GELIC_DESCR_TX_DMA_NO_CHKSUM) | 162 | GELIC_DESCR_TX_DMA_NO_CHKSUM) |
163 | 163 | ||
164 | #define GELIC_DESCR_DMA_CMD_TCP_CHKSUM \ | 164 | #define GELIC_DESCR_DMA_CMD_TCP_CHKSUM \ |
165 | (GELIC_DESCR_DMA_CARDOWNED | GELIC_DESCR_TX_DMA_IKE | \ | 165 | (GELIC_DESCR_DMA_CARDOWNED | GELIC_DESCR_TX_DMA_IKE | \ |
166 | GELIC_DESCR_TX_DMA_TCP_CHKSUM) | 166 | GELIC_DESCR_TX_DMA_TCP_CHKSUM) |
167 | 167 | ||
168 | #define GELIC_DESCR_DMA_CMD_UDP_CHKSUM \ | 168 | #define GELIC_DESCR_DMA_CMD_UDP_CHKSUM \ |
169 | (GELIC_DESCR_DMA_CARDOWNED | GELIC_DESCR_TX_DMA_IKE | \ | 169 | (GELIC_DESCR_DMA_CARDOWNED | GELIC_DESCR_TX_DMA_IKE | \ |
170 | GELIC_DESCR_TX_DMA_UDP_CHKSUM) | 170 | GELIC_DESCR_TX_DMA_UDP_CHKSUM) |
171 | 171 | ||
172 | enum gelic_descr_rx_dma_status { | 172 | enum gelic_descr_rx_dma_status { |
173 | /* [ 1 ] */ | 173 | /* [ 1 ] */ |
174 | GELIC_DESCR_RX_DMA_CHAIN_END = 0x00000002, /* DMA terminated | 174 | GELIC_DESCR_RX_DMA_CHAIN_END = 0x00000002, /* DMA terminated |
175 | * due to chain end | 175 | * due to chain end |
176 | */ | 176 | */ |
177 | }; | 177 | }; |
178 | 178 | ||
179 | /* for lv1_net_control */ | 179 | /* for lv1_net_control */ |
180 | enum gelic_lv1_net_control_code { | 180 | enum gelic_lv1_net_control_code { |
181 | GELIC_LV1_GET_MAC_ADDRESS = 1, | 181 | GELIC_LV1_GET_MAC_ADDRESS = 1, |
182 | GELIC_LV1_GET_ETH_PORT_STATUS = 2, | 182 | GELIC_LV1_GET_ETH_PORT_STATUS = 2, |
183 | GELIC_LV1_SET_NEGOTIATION_MODE = 3, | 183 | GELIC_LV1_SET_NEGOTIATION_MODE = 3, |
184 | GELIC_LV1_GET_VLAN_ID = 4, | 184 | GELIC_LV1_GET_VLAN_ID = 4, |
185 | GELIC_LV1_SET_WOL = 5, | 185 | GELIC_LV1_SET_WOL = 5, |
186 | GELIC_LV1_GET_CHANNEL = 6, | 186 | GELIC_LV1_GET_CHANNEL = 6, |
187 | GELIC_LV1_POST_WLAN_CMD = 9, | 187 | GELIC_LV1_POST_WLAN_CMD = 9, |
188 | GELIC_LV1_GET_WLAN_CMD_RESULT = 10, | 188 | GELIC_LV1_GET_WLAN_CMD_RESULT = 10, |
189 | GELIC_LV1_GET_WLAN_EVENT = 11, | 189 | GELIC_LV1_GET_WLAN_EVENT = 11, |
190 | }; | 190 | }; |
191 | 191 | ||
192 | /* for GELIC_LV1_SET_WOL */ | 192 | /* for GELIC_LV1_SET_WOL */ |
193 | enum gelic_lv1_wol_command { | 193 | enum gelic_lv1_wol_command { |
194 | GELIC_LV1_WOL_MAGIC_PACKET = 1, | 194 | GELIC_LV1_WOL_MAGIC_PACKET = 1, |
195 | GELIC_LV1_WOL_ADD_MATCH_ADDR = 6, | 195 | GELIC_LV1_WOL_ADD_MATCH_ADDR = 6, |
196 | GELIC_LV1_WOL_DELETE_MATCH_ADDR = 7, | 196 | GELIC_LV1_WOL_DELETE_MATCH_ADDR = 7, |
197 | }; | 197 | }; |
198 | 198 | ||
199 | /* for GELIC_LV1_WOL_MAGIC_PACKET */ | 199 | /* for GELIC_LV1_WOL_MAGIC_PACKET */ |
200 | enum gelic_lv1_wol_mp_arg { | 200 | enum gelic_lv1_wol_mp_arg { |
201 | GELIC_LV1_WOL_MP_DISABLE = 0, | 201 | GELIC_LV1_WOL_MP_DISABLE = 0, |
202 | GELIC_LV1_WOL_MP_ENABLE = 1, | 202 | GELIC_LV1_WOL_MP_ENABLE = 1, |
203 | }; | 203 | }; |
204 | 204 | ||
205 | /* for GELIC_LV1_WOL_{ADD,DELETE}_MATCH_ADDR */ | 205 | /* for GELIC_LV1_WOL_{ADD,DELETE}_MATCH_ADDR */ |
206 | enum gelic_lv1_wol_match_arg { | 206 | enum gelic_lv1_wol_match_arg { |
207 | GELIC_LV1_WOL_MATCH_INDIVIDUAL = 0, | 207 | GELIC_LV1_WOL_MATCH_INDIVIDUAL = 0, |
208 | GELIC_LV1_WOL_MATCH_ALL = 1, | 208 | GELIC_LV1_WOL_MATCH_ALL = 1, |
209 | }; | 209 | }; |
210 | 210 | ||
211 | /* status returened from GET_ETH_PORT_STATUS */ | 211 | /* status returened from GET_ETH_PORT_STATUS */ |
212 | enum gelic_lv1_ether_port_status { | 212 | enum gelic_lv1_ether_port_status { |
213 | GELIC_LV1_ETHER_LINK_UP = 0x0000000000000001L, | 213 | GELIC_LV1_ETHER_LINK_UP = 0x0000000000000001L, |
214 | GELIC_LV1_ETHER_FULL_DUPLEX = 0x0000000000000002L, | 214 | GELIC_LV1_ETHER_FULL_DUPLEX = 0x0000000000000002L, |
215 | GELIC_LV1_ETHER_AUTO_NEG = 0x0000000000000004L, | 215 | GELIC_LV1_ETHER_AUTO_NEG = 0x0000000000000004L, |
216 | 216 | ||
217 | GELIC_LV1_ETHER_SPEED_10 = 0x0000000000000010L, | 217 | GELIC_LV1_ETHER_SPEED_10 = 0x0000000000000010L, |
218 | GELIC_LV1_ETHER_SPEED_100 = 0x0000000000000020L, | 218 | GELIC_LV1_ETHER_SPEED_100 = 0x0000000000000020L, |
219 | GELIC_LV1_ETHER_SPEED_1000 = 0x0000000000000040L, | 219 | GELIC_LV1_ETHER_SPEED_1000 = 0x0000000000000040L, |
220 | GELIC_LV1_ETHER_SPEED_MASK = 0x0000000000000070L, | 220 | GELIC_LV1_ETHER_SPEED_MASK = 0x0000000000000070L, |
221 | }; | 221 | }; |
222 | 222 | ||
223 | enum gelic_lv1_vlan_index { | 223 | enum gelic_lv1_vlan_index { |
224 | /* for outgoing packets */ | 224 | /* for outgoing packets */ |
225 | GELIC_LV1_VLAN_TX_ETHERNET_0 = 0x0000000000000002L, | 225 | GELIC_LV1_VLAN_TX_ETHERNET_0 = 0x0000000000000002L, |
226 | GELIC_LV1_VLAN_TX_WIRELESS = 0x0000000000000003L, | 226 | GELIC_LV1_VLAN_TX_WIRELESS = 0x0000000000000003L, |
227 | 227 | ||
228 | /* for incoming packets */ | 228 | /* for incoming packets */ |
229 | GELIC_LV1_VLAN_RX_ETHERNET_0 = 0x0000000000000012L, | 229 | GELIC_LV1_VLAN_RX_ETHERNET_0 = 0x0000000000000012L, |
230 | GELIC_LV1_VLAN_RX_WIRELESS = 0x0000000000000013L, | 230 | GELIC_LV1_VLAN_RX_WIRELESS = 0x0000000000000013L, |
231 | }; | 231 | }; |
232 | 232 | ||
233 | enum gelic_lv1_phy { | 233 | enum gelic_lv1_phy { |
234 | GELIC_LV1_PHY_ETHERNET_0 = 0x0000000000000002L, | 234 | GELIC_LV1_PHY_ETHERNET_0 = 0x0000000000000002L, |
235 | }; | 235 | }; |
236 | 236 | ||
237 | /* size of hardware part of gelic descriptor */ | 237 | /* size of hardware part of gelic descriptor */ |
238 | #define GELIC_DESCR_SIZE (32) | 238 | #define GELIC_DESCR_SIZE (32) |
239 | 239 | ||
240 | enum gelic_port_type { | 240 | enum gelic_port_type { |
241 | GELIC_PORT_ETHERNET_0 = 0, | 241 | GELIC_PORT_ETHERNET_0 = 0, |
242 | GELIC_PORT_WIRELESS = 1, | 242 | GELIC_PORT_WIRELESS = 1, |
243 | GELIC_PORT_MAX | 243 | GELIC_PORT_MAX |
244 | }; | 244 | }; |
245 | 245 | ||
246 | struct gelic_descr { | 246 | struct gelic_descr { |
247 | /* as defined by the hardware */ | 247 | /* as defined by the hardware */ |
248 | __be32 buf_addr; | 248 | __be32 buf_addr; |
249 | __be32 buf_size; | 249 | __be32 buf_size; |
250 | __be32 next_descr_addr; | 250 | __be32 next_descr_addr; |
251 | __be32 dmac_cmd_status; | 251 | __be32 dmac_cmd_status; |
252 | __be32 result_size; | 252 | __be32 result_size; |
253 | __be32 valid_size; /* all zeroes for tx */ | 253 | __be32 valid_size; /* all zeroes for tx */ |
254 | __be32 data_status; | 254 | __be32 data_status; |
255 | __be32 data_error; /* all zeroes for tx */ | 255 | __be32 data_error; /* all zeroes for tx */ |
256 | 256 | ||
257 | /* used in the driver */ | 257 | /* used in the driver */ |
258 | struct sk_buff *skb; | 258 | struct sk_buff *skb; |
259 | dma_addr_t bus_addr; | 259 | dma_addr_t bus_addr; |
260 | struct gelic_descr *next; | 260 | struct gelic_descr *next; |
261 | struct gelic_descr *prev; | 261 | struct gelic_descr *prev; |
262 | } __attribute__((aligned(32))); | 262 | } __attribute__((aligned(32))); |
263 | 263 | ||
264 | struct gelic_descr_chain { | 264 | struct gelic_descr_chain { |
265 | /* we walk from tail to head */ | 265 | /* we walk from tail to head */ |
266 | struct gelic_descr *head; | 266 | struct gelic_descr *head; |
267 | struct gelic_descr *tail; | 267 | struct gelic_descr *tail; |
268 | }; | 268 | }; |
269 | 269 | ||
270 | struct gelic_vlan_id { | 270 | struct gelic_vlan_id { |
271 | u16 tx; | 271 | u16 tx; |
272 | u16 rx; | 272 | u16 rx; |
273 | }; | 273 | }; |
274 | 274 | ||
275 | struct gelic_card { | 275 | struct gelic_card { |
276 | struct napi_struct napi; | 276 | struct napi_struct napi; |
277 | struct net_device *netdev[GELIC_PORT_MAX]; | 277 | struct net_device *netdev[GELIC_PORT_MAX]; |
278 | /* | 278 | /* |
279 | * hypervisor requires irq_status should be | 279 | * hypervisor requires irq_status should be |
280 | * 8 bytes aligned, but u64 member is | 280 | * 8 bytes aligned, but u64 member is |
281 | * always disposed in that manner | 281 | * always disposed in that manner |
282 | */ | 282 | */ |
283 | u64 irq_status; | 283 | u64 irq_status; |
284 | u64 irq_mask; | 284 | u64 irq_mask; |
285 | 285 | ||
286 | struct ps3_system_bus_device *dev; | 286 | struct ps3_system_bus_device *dev; |
287 | struct gelic_vlan_id vlan[GELIC_PORT_MAX]; | 287 | struct gelic_vlan_id vlan[GELIC_PORT_MAX]; |
288 | int vlan_required; | 288 | int vlan_required; |
289 | 289 | ||
290 | struct gelic_descr_chain tx_chain; | 290 | struct gelic_descr_chain tx_chain; |
291 | struct gelic_descr_chain rx_chain; | 291 | struct gelic_descr_chain rx_chain; |
292 | int rx_dma_restart_required; | 292 | int rx_dma_restart_required; |
293 | int rx_csum; | ||
294 | /* | 293 | /* |
295 | * tx_lock guards tx descriptor list and | 294 | * tx_lock guards tx descriptor list and |
296 | * tx_dma_progress. | 295 | * tx_dma_progress. |
297 | */ | 296 | */ |
298 | spinlock_t tx_lock; | 297 | spinlock_t tx_lock; |
299 | int tx_dma_progress; | 298 | int tx_dma_progress; |
300 | 299 | ||
301 | struct work_struct tx_timeout_task; | 300 | struct work_struct tx_timeout_task; |
302 | atomic_t tx_timeout_task_counter; | 301 | atomic_t tx_timeout_task_counter; |
303 | wait_queue_head_t waitq; | 302 | wait_queue_head_t waitq; |
304 | 303 | ||
305 | /* only first user should up the card */ | 304 | /* only first user should up the card */ |
306 | struct mutex updown_lock; | 305 | struct mutex updown_lock; |
307 | atomic_t users; | 306 | atomic_t users; |
308 | 307 | ||
309 | u64 ether_port_status; | 308 | u64 ether_port_status; |
310 | int link_mode; | 309 | int link_mode; |
311 | 310 | ||
312 | /* original address returned by kzalloc */ | 311 | /* original address returned by kzalloc */ |
313 | void *unalign; | 312 | void *unalign; |
314 | 313 | ||
315 | /* | 314 | /* |
316 | * each netdevice has copy of irq | 315 | * each netdevice has copy of irq |
317 | */ | 316 | */ |
318 | unsigned int irq; | 317 | unsigned int irq; |
319 | struct gelic_descr *tx_top, *rx_top; | 318 | struct gelic_descr *tx_top, *rx_top; |
320 | struct gelic_descr descr[0]; /* must be the last */ | 319 | struct gelic_descr descr[0]; /* must be the last */ |
321 | }; | 320 | }; |
322 | 321 | ||
323 | struct gelic_port { | 322 | struct gelic_port { |
324 | struct gelic_card *card; | 323 | struct gelic_card *card; |
325 | struct net_device *netdev; | 324 | struct net_device *netdev; |
326 | enum gelic_port_type type; | 325 | enum gelic_port_type type; |
327 | long priv[0]; /* long for alignment */ | 326 | long priv[0]; /* long for alignment */ |
328 | }; | 327 | }; |
329 | 328 | ||
330 | static inline struct gelic_card *port_to_card(struct gelic_port *p) | 329 | static inline struct gelic_card *port_to_card(struct gelic_port *p) |
331 | { | 330 | { |
332 | return p->card; | 331 | return p->card; |
333 | } | 332 | } |
334 | static inline struct net_device *port_to_netdev(struct gelic_port *p) | 333 | static inline struct net_device *port_to_netdev(struct gelic_port *p) |
335 | { | 334 | { |
336 | return p->netdev; | 335 | return p->netdev; |
337 | } | 336 | } |
338 | static inline struct gelic_card *netdev_card(struct net_device *d) | 337 | static inline struct gelic_card *netdev_card(struct net_device *d) |
339 | { | 338 | { |
340 | return ((struct gelic_port *)netdev_priv(d))->card; | 339 | return ((struct gelic_port *)netdev_priv(d))->card; |
341 | } | 340 | } |
342 | static inline struct gelic_port *netdev_port(struct net_device *d) | 341 | static inline struct gelic_port *netdev_port(struct net_device *d) |
343 | { | 342 | { |
344 | return (struct gelic_port *)netdev_priv(d); | 343 | return (struct gelic_port *)netdev_priv(d); |
345 | } | 344 | } |
346 | static inline struct device *ctodev(struct gelic_card *card) | 345 | static inline struct device *ctodev(struct gelic_card *card) |
347 | { | 346 | { |
348 | return &card->dev->core; | 347 | return &card->dev->core; |
349 | } | 348 | } |
350 | static inline u64 bus_id(struct gelic_card *card) | 349 | static inline u64 bus_id(struct gelic_card *card) |
351 | { | 350 | { |
352 | return card->dev->bus_id; | 351 | return card->dev->bus_id; |
353 | } | 352 | } |
354 | static inline u64 dev_id(struct gelic_card *card) | 353 | static inline u64 dev_id(struct gelic_card *card) |
355 | { | 354 | { |
356 | return card->dev->dev_id; | 355 | return card->dev->dev_id; |
357 | } | 356 | } |
358 | 357 | ||
359 | static inline void *port_priv(struct gelic_port *port) | 358 | static inline void *port_priv(struct gelic_port *port) |
360 | { | 359 | { |
361 | return port->priv; | 360 | return port->priv; |
362 | } | 361 | } |
363 | 362 | ||
364 | extern int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask); | 363 | extern int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask); |
365 | /* shared netdev ops */ | 364 | /* shared netdev ops */ |
366 | extern void gelic_card_up(struct gelic_card *card); | 365 | extern void gelic_card_up(struct gelic_card *card); |
367 | extern void gelic_card_down(struct gelic_card *card); | 366 | extern void gelic_card_down(struct gelic_card *card); |
368 | extern int gelic_net_open(struct net_device *netdev); | 367 | extern int gelic_net_open(struct net_device *netdev); |
369 | extern int gelic_net_stop(struct net_device *netdev); | 368 | extern int gelic_net_stop(struct net_device *netdev); |
370 | extern int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev); | 369 | extern int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev); |
371 | extern void gelic_net_set_multi(struct net_device *netdev); | 370 | extern void gelic_net_set_multi(struct net_device *netdev); |
372 | extern void gelic_net_tx_timeout(struct net_device *netdev); | 371 | extern void gelic_net_tx_timeout(struct net_device *netdev); |
373 | extern int gelic_net_change_mtu(struct net_device *netdev, int new_mtu); | 372 | extern int gelic_net_change_mtu(struct net_device *netdev, int new_mtu); |
374 | extern int gelic_net_setup_netdev(struct net_device *netdev, | 373 | extern int gelic_net_setup_netdev(struct net_device *netdev, |
375 | struct gelic_card *card); | 374 | struct gelic_card *card); |
376 | 375 | ||
377 | /* shared ethtool ops */ | 376 | /* shared ethtool ops */ |
378 | extern void gelic_net_get_drvinfo(struct net_device *netdev, | 377 | extern void gelic_net_get_drvinfo(struct net_device *netdev, |
379 | struct ethtool_drvinfo *info); | 378 | struct ethtool_drvinfo *info); |
380 | extern u32 gelic_net_get_rx_csum(struct net_device *netdev); | ||
381 | extern int gelic_net_set_rx_csum(struct net_device *netdev, u32 data); | ||
382 | extern void gelic_net_poll_controller(struct net_device *netdev); | 379 | extern void gelic_net_poll_controller(struct net_device *netdev); |
383 | 380 | ||
384 | #endif /* _GELIC_NET_H */ | 381 | #endif /* _GELIC_NET_H */ |
385 | 382 |
drivers/net/ps3_gelic_wireless.c
1 | /* | 1 | /* |
2 | * PS3 gelic network driver. | 2 | * PS3 gelic network driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
5 | * Copyright 2007 Sony Corporation | 5 | * Copyright 2007 Sony Corporation |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 | 8 | * it under the terms of the GNU General Public License version 2 |
9 | * as published by the Free Software Foundation. | 9 | * as published by the Free Software Foundation. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | */ | 19 | */ |
20 | #undef DEBUG | 20 | #undef DEBUG |
21 | 21 | ||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | 25 | ||
26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
27 | #include <linux/ethtool.h> | 27 | #include <linux/ethtool.h> |
28 | #include <linux/if_vlan.h> | 28 | #include <linux/if_vlan.h> |
29 | 29 | ||
30 | #include <linux/in.h> | 30 | #include <linux/in.h> |
31 | #include <linux/ip.h> | 31 | #include <linux/ip.h> |
32 | #include <linux/tcp.h> | 32 | #include <linux/tcp.h> |
33 | #include <linux/wireless.h> | 33 | #include <linux/wireless.h> |
34 | #include <linux/ieee80211.h> | 34 | #include <linux/ieee80211.h> |
35 | #include <linux/if_arp.h> | 35 | #include <linux/if_arp.h> |
36 | #include <linux/ctype.h> | 36 | #include <linux/ctype.h> |
37 | #include <linux/string.h> | 37 | #include <linux/string.h> |
38 | #include <net/iw_handler.h> | 38 | #include <net/iw_handler.h> |
39 | 39 | ||
40 | #include <linux/dma-mapping.h> | 40 | #include <linux/dma-mapping.h> |
41 | #include <net/checksum.h> | 41 | #include <net/checksum.h> |
42 | #include <asm/firmware.h> | 42 | #include <asm/firmware.h> |
43 | #include <asm/ps3.h> | 43 | #include <asm/ps3.h> |
44 | #include <asm/lv1call.h> | 44 | #include <asm/lv1call.h> |
45 | 45 | ||
46 | #include "ps3_gelic_net.h" | 46 | #include "ps3_gelic_net.h" |
47 | #include "ps3_gelic_wireless.h" | 47 | #include "ps3_gelic_wireless.h" |
48 | 48 | ||
49 | 49 | ||
50 | static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, | 50 | static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, |
51 | u8 *essid, size_t essid_len); | 51 | u8 *essid, size_t essid_len); |
52 | static int gelic_wl_try_associate(struct net_device *netdev); | 52 | static int gelic_wl_try_associate(struct net_device *netdev); |
53 | 53 | ||
54 | /* | 54 | /* |
55 | * tables | 55 | * tables |
56 | */ | 56 | */ |
57 | 57 | ||
58 | /* 802.11b/g channel to freq in MHz */ | 58 | /* 802.11b/g channel to freq in MHz */ |
59 | static const int channel_freq[] = { | 59 | static const int channel_freq[] = { |
60 | 2412, 2417, 2422, 2427, 2432, | 60 | 2412, 2417, 2422, 2427, 2432, |
61 | 2437, 2442, 2447, 2452, 2457, | 61 | 2437, 2442, 2447, 2452, 2457, |
62 | 2462, 2467, 2472, 2484 | 62 | 2462, 2467, 2472, 2484 |
63 | }; | 63 | }; |
64 | #define NUM_CHANNELS ARRAY_SIZE(channel_freq) | 64 | #define NUM_CHANNELS ARRAY_SIZE(channel_freq) |
65 | 65 | ||
66 | /* in bps */ | 66 | /* in bps */ |
67 | static const int bitrate_list[] = { | 67 | static const int bitrate_list[] = { |
68 | 1000000, | 68 | 1000000, |
69 | 2000000, | 69 | 2000000, |
70 | 5500000, | 70 | 5500000, |
71 | 11000000, | 71 | 11000000, |
72 | 6000000, | 72 | 6000000, |
73 | 9000000, | 73 | 9000000, |
74 | 12000000, | 74 | 12000000, |
75 | 18000000, | 75 | 18000000, |
76 | 24000000, | 76 | 24000000, |
77 | 36000000, | 77 | 36000000, |
78 | 48000000, | 78 | 48000000, |
79 | 54000000 | 79 | 54000000 |
80 | }; | 80 | }; |
81 | #define NUM_BITRATES ARRAY_SIZE(bitrate_list) | 81 | #define NUM_BITRATES ARRAY_SIZE(bitrate_list) |
82 | 82 | ||
83 | /* | 83 | /* |
84 | * wpa2 support requires the hypervisor version 2.0 or later | 84 | * wpa2 support requires the hypervisor version 2.0 or later |
85 | */ | 85 | */ |
86 | static inline int wpa2_capable(void) | 86 | static inline int wpa2_capable(void) |
87 | { | 87 | { |
88 | return 0 <= ps3_compare_firmware_version(2, 0, 0); | 88 | return 0 <= ps3_compare_firmware_version(2, 0, 0); |
89 | } | 89 | } |
90 | 90 | ||
91 | static inline int precise_ie(void) | 91 | static inline int precise_ie(void) |
92 | { | 92 | { |
93 | return 0 <= ps3_compare_firmware_version(2, 2, 0); | 93 | return 0 <= ps3_compare_firmware_version(2, 2, 0); |
94 | } | 94 | } |
95 | /* | 95 | /* |
96 | * post_eurus_cmd helpers | 96 | * post_eurus_cmd helpers |
97 | */ | 97 | */ |
98 | struct eurus_cmd_arg_info { | 98 | struct eurus_cmd_arg_info { |
99 | int pre_arg; /* command requires arg1, arg2 at POST COMMAND */ | 99 | int pre_arg; /* command requires arg1, arg2 at POST COMMAND */ |
100 | int post_arg; /* command requires arg1, arg2 at GET_RESULT */ | 100 | int post_arg; /* command requires arg1, arg2 at GET_RESULT */ |
101 | }; | 101 | }; |
102 | 102 | ||
103 | static const struct eurus_cmd_arg_info cmd_info[GELIC_EURUS_CMD_MAX_INDEX] = { | 103 | static const struct eurus_cmd_arg_info cmd_info[GELIC_EURUS_CMD_MAX_INDEX] = { |
104 | [GELIC_EURUS_CMD_SET_COMMON_CFG] = { .pre_arg = 1}, | 104 | [GELIC_EURUS_CMD_SET_COMMON_CFG] = { .pre_arg = 1}, |
105 | [GELIC_EURUS_CMD_SET_WEP_CFG] = { .pre_arg = 1}, | 105 | [GELIC_EURUS_CMD_SET_WEP_CFG] = { .pre_arg = 1}, |
106 | [GELIC_EURUS_CMD_SET_WPA_CFG] = { .pre_arg = 1}, | 106 | [GELIC_EURUS_CMD_SET_WPA_CFG] = { .pre_arg = 1}, |
107 | [GELIC_EURUS_CMD_GET_COMMON_CFG] = { .post_arg = 1}, | 107 | [GELIC_EURUS_CMD_GET_COMMON_CFG] = { .post_arg = 1}, |
108 | [GELIC_EURUS_CMD_GET_WEP_CFG] = { .post_arg = 1}, | 108 | [GELIC_EURUS_CMD_GET_WEP_CFG] = { .post_arg = 1}, |
109 | [GELIC_EURUS_CMD_GET_WPA_CFG] = { .post_arg = 1}, | 109 | [GELIC_EURUS_CMD_GET_WPA_CFG] = { .post_arg = 1}, |
110 | [GELIC_EURUS_CMD_GET_RSSI_CFG] = { .post_arg = 1}, | 110 | [GELIC_EURUS_CMD_GET_RSSI_CFG] = { .post_arg = 1}, |
111 | [GELIC_EURUS_CMD_START_SCAN] = { .pre_arg = 1}, | 111 | [GELIC_EURUS_CMD_START_SCAN] = { .pre_arg = 1}, |
112 | [GELIC_EURUS_CMD_GET_SCAN] = { .post_arg = 1}, | 112 | [GELIC_EURUS_CMD_GET_SCAN] = { .post_arg = 1}, |
113 | }; | 113 | }; |
114 | 114 | ||
115 | #ifdef DEBUG | 115 | #ifdef DEBUG |
116 | static const char *cmdstr(enum gelic_eurus_command ix) | 116 | static const char *cmdstr(enum gelic_eurus_command ix) |
117 | { | 117 | { |
118 | switch (ix) { | 118 | switch (ix) { |
119 | case GELIC_EURUS_CMD_ASSOC: | 119 | case GELIC_EURUS_CMD_ASSOC: |
120 | return "ASSOC"; | 120 | return "ASSOC"; |
121 | case GELIC_EURUS_CMD_DISASSOC: | 121 | case GELIC_EURUS_CMD_DISASSOC: |
122 | return "DISASSOC"; | 122 | return "DISASSOC"; |
123 | case GELIC_EURUS_CMD_START_SCAN: | 123 | case GELIC_EURUS_CMD_START_SCAN: |
124 | return "SCAN"; | 124 | return "SCAN"; |
125 | case GELIC_EURUS_CMD_GET_SCAN: | 125 | case GELIC_EURUS_CMD_GET_SCAN: |
126 | return "GET SCAN"; | 126 | return "GET SCAN"; |
127 | case GELIC_EURUS_CMD_SET_COMMON_CFG: | 127 | case GELIC_EURUS_CMD_SET_COMMON_CFG: |
128 | return "SET_COMMON_CFG"; | 128 | return "SET_COMMON_CFG"; |
129 | case GELIC_EURUS_CMD_GET_COMMON_CFG: | 129 | case GELIC_EURUS_CMD_GET_COMMON_CFG: |
130 | return "GET_COMMON_CFG"; | 130 | return "GET_COMMON_CFG"; |
131 | case GELIC_EURUS_CMD_SET_WEP_CFG: | 131 | case GELIC_EURUS_CMD_SET_WEP_CFG: |
132 | return "SET_WEP_CFG"; | 132 | return "SET_WEP_CFG"; |
133 | case GELIC_EURUS_CMD_GET_WEP_CFG: | 133 | case GELIC_EURUS_CMD_GET_WEP_CFG: |
134 | return "GET_WEP_CFG"; | 134 | return "GET_WEP_CFG"; |
135 | case GELIC_EURUS_CMD_SET_WPA_CFG: | 135 | case GELIC_EURUS_CMD_SET_WPA_CFG: |
136 | return "SET_WPA_CFG"; | 136 | return "SET_WPA_CFG"; |
137 | case GELIC_EURUS_CMD_GET_WPA_CFG: | 137 | case GELIC_EURUS_CMD_GET_WPA_CFG: |
138 | return "GET_WPA_CFG"; | 138 | return "GET_WPA_CFG"; |
139 | case GELIC_EURUS_CMD_GET_RSSI_CFG: | 139 | case GELIC_EURUS_CMD_GET_RSSI_CFG: |
140 | return "GET_RSSI"; | 140 | return "GET_RSSI"; |
141 | default: | 141 | default: |
142 | break; | 142 | break; |
143 | } | 143 | } |
144 | return ""; | 144 | return ""; |
145 | }; | 145 | }; |
146 | #else | 146 | #else |
147 | static inline const char *cmdstr(enum gelic_eurus_command ix) | 147 | static inline const char *cmdstr(enum gelic_eurus_command ix) |
148 | { | 148 | { |
149 | return ""; | 149 | return ""; |
150 | } | 150 | } |
151 | #endif | 151 | #endif |
152 | 152 | ||
153 | /* synchronously do eurus commands */ | 153 | /* synchronously do eurus commands */ |
154 | static void gelic_eurus_sync_cmd_worker(struct work_struct *work) | 154 | static void gelic_eurus_sync_cmd_worker(struct work_struct *work) |
155 | { | 155 | { |
156 | struct gelic_eurus_cmd *cmd; | 156 | struct gelic_eurus_cmd *cmd; |
157 | struct gelic_card *card; | 157 | struct gelic_card *card; |
158 | struct gelic_wl_info *wl; | 158 | struct gelic_wl_info *wl; |
159 | 159 | ||
160 | u64 arg1, arg2; | 160 | u64 arg1, arg2; |
161 | 161 | ||
162 | pr_debug("%s: <-\n", __func__); | 162 | pr_debug("%s: <-\n", __func__); |
163 | cmd = container_of(work, struct gelic_eurus_cmd, work); | 163 | cmd = container_of(work, struct gelic_eurus_cmd, work); |
164 | BUG_ON(cmd_info[cmd->cmd].pre_arg && | 164 | BUG_ON(cmd_info[cmd->cmd].pre_arg && |
165 | cmd_info[cmd->cmd].post_arg); | 165 | cmd_info[cmd->cmd].post_arg); |
166 | wl = cmd->wl; | 166 | wl = cmd->wl; |
167 | card = port_to_card(wl_port(wl)); | 167 | card = port_to_card(wl_port(wl)); |
168 | 168 | ||
169 | if (cmd_info[cmd->cmd].pre_arg) { | 169 | if (cmd_info[cmd->cmd].pre_arg) { |
170 | arg1 = (cmd->buffer) ? | 170 | arg1 = (cmd->buffer) ? |
171 | ps3_mm_phys_to_lpar(__pa(cmd->buffer)) : | 171 | ps3_mm_phys_to_lpar(__pa(cmd->buffer)) : |
172 | 0; | 172 | 0; |
173 | arg2 = cmd->buf_size; | 173 | arg2 = cmd->buf_size; |
174 | } else { | 174 | } else { |
175 | arg1 = 0; | 175 | arg1 = 0; |
176 | arg2 = 0; | 176 | arg2 = 0; |
177 | } | 177 | } |
178 | init_completion(&wl->cmd_done_intr); | 178 | init_completion(&wl->cmd_done_intr); |
179 | pr_debug("%s: cmd='%s' start\n", __func__, cmdstr(cmd->cmd)); | 179 | pr_debug("%s: cmd='%s' start\n", __func__, cmdstr(cmd->cmd)); |
180 | cmd->status = lv1_net_control(bus_id(card), dev_id(card), | 180 | cmd->status = lv1_net_control(bus_id(card), dev_id(card), |
181 | GELIC_LV1_POST_WLAN_CMD, | 181 | GELIC_LV1_POST_WLAN_CMD, |
182 | cmd->cmd, arg1, arg2, | 182 | cmd->cmd, arg1, arg2, |
183 | &cmd->tag, &cmd->size); | 183 | &cmd->tag, &cmd->size); |
184 | if (cmd->status) { | 184 | if (cmd->status) { |
185 | complete(&cmd->done); | 185 | complete(&cmd->done); |
186 | pr_info("%s: cmd issue failed\n", __func__); | 186 | pr_info("%s: cmd issue failed\n", __func__); |
187 | return; | 187 | return; |
188 | } | 188 | } |
189 | 189 | ||
190 | wait_for_completion(&wl->cmd_done_intr); | 190 | wait_for_completion(&wl->cmd_done_intr); |
191 | 191 | ||
192 | if (cmd_info[cmd->cmd].post_arg) { | 192 | if (cmd_info[cmd->cmd].post_arg) { |
193 | arg1 = ps3_mm_phys_to_lpar(__pa(cmd->buffer)); | 193 | arg1 = ps3_mm_phys_to_lpar(__pa(cmd->buffer)); |
194 | arg2 = cmd->buf_size; | 194 | arg2 = cmd->buf_size; |
195 | } else { | 195 | } else { |
196 | arg1 = 0; | 196 | arg1 = 0; |
197 | arg2 = 0; | 197 | arg2 = 0; |
198 | } | 198 | } |
199 | 199 | ||
200 | cmd->status = lv1_net_control(bus_id(card), dev_id(card), | 200 | cmd->status = lv1_net_control(bus_id(card), dev_id(card), |
201 | GELIC_LV1_GET_WLAN_CMD_RESULT, | 201 | GELIC_LV1_GET_WLAN_CMD_RESULT, |
202 | cmd->tag, arg1, arg2, | 202 | cmd->tag, arg1, arg2, |
203 | &cmd->cmd_status, &cmd->size); | 203 | &cmd->cmd_status, &cmd->size); |
204 | #ifdef DEBUG | 204 | #ifdef DEBUG |
205 | if (cmd->status || cmd->cmd_status) { | 205 | if (cmd->status || cmd->cmd_status) { |
206 | pr_debug("%s: cmd done tag=%#lx arg1=%#lx, arg2=%#lx\n", __func__, | 206 | pr_debug("%s: cmd done tag=%#lx arg1=%#lx, arg2=%#lx\n", __func__, |
207 | cmd->tag, arg1, arg2); | 207 | cmd->tag, arg1, arg2); |
208 | pr_debug("%s: cmd done status=%#x cmd_status=%#lx size=%#lx\n", | 208 | pr_debug("%s: cmd done status=%#x cmd_status=%#lx size=%#lx\n", |
209 | __func__, cmd->status, cmd->cmd_status, cmd->size); | 209 | __func__, cmd->status, cmd->cmd_status, cmd->size); |
210 | } | 210 | } |
211 | #endif | 211 | #endif |
212 | complete(&cmd->done); | 212 | complete(&cmd->done); |
213 | pr_debug("%s: cmd='%s' done\n", __func__, cmdstr(cmd->cmd)); | 213 | pr_debug("%s: cmd='%s' done\n", __func__, cmdstr(cmd->cmd)); |
214 | } | 214 | } |
215 | 215 | ||
216 | static struct gelic_eurus_cmd *gelic_eurus_sync_cmd(struct gelic_wl_info *wl, | 216 | static struct gelic_eurus_cmd *gelic_eurus_sync_cmd(struct gelic_wl_info *wl, |
217 | unsigned int eurus_cmd, | 217 | unsigned int eurus_cmd, |
218 | void *buffer, | 218 | void *buffer, |
219 | unsigned int buf_size) | 219 | unsigned int buf_size) |
220 | { | 220 | { |
221 | struct gelic_eurus_cmd *cmd; | 221 | struct gelic_eurus_cmd *cmd; |
222 | 222 | ||
223 | /* allocate cmd */ | 223 | /* allocate cmd */ |
224 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 224 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
225 | if (!cmd) | 225 | if (!cmd) |
226 | return NULL; | 226 | return NULL; |
227 | 227 | ||
228 | /* initialize members */ | 228 | /* initialize members */ |
229 | cmd->cmd = eurus_cmd; | 229 | cmd->cmd = eurus_cmd; |
230 | cmd->buffer = buffer; | 230 | cmd->buffer = buffer; |
231 | cmd->buf_size = buf_size; | 231 | cmd->buf_size = buf_size; |
232 | cmd->wl = wl; | 232 | cmd->wl = wl; |
233 | INIT_WORK(&cmd->work, gelic_eurus_sync_cmd_worker); | 233 | INIT_WORK(&cmd->work, gelic_eurus_sync_cmd_worker); |
234 | init_completion(&cmd->done); | 234 | init_completion(&cmd->done); |
235 | queue_work(wl->eurus_cmd_queue, &cmd->work); | 235 | queue_work(wl->eurus_cmd_queue, &cmd->work); |
236 | 236 | ||
237 | /* wait for command completion */ | 237 | /* wait for command completion */ |
238 | wait_for_completion(&cmd->done); | 238 | wait_for_completion(&cmd->done); |
239 | 239 | ||
240 | return cmd; | 240 | return cmd; |
241 | } | 241 | } |
242 | 242 | ||
243 | static u32 gelic_wl_get_link(struct net_device *netdev) | 243 | static u32 gelic_wl_get_link(struct net_device *netdev) |
244 | { | 244 | { |
245 | struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); | 245 | struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); |
246 | u32 ret; | 246 | u32 ret; |
247 | 247 | ||
248 | pr_debug("%s: <-\n", __func__); | 248 | pr_debug("%s: <-\n", __func__); |
249 | mutex_lock(&wl->assoc_stat_lock); | 249 | mutex_lock(&wl->assoc_stat_lock); |
250 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) | 250 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) |
251 | ret = 1; | 251 | ret = 1; |
252 | else | 252 | else |
253 | ret = 0; | 253 | ret = 0; |
254 | mutex_unlock(&wl->assoc_stat_lock); | 254 | mutex_unlock(&wl->assoc_stat_lock); |
255 | pr_debug("%s: ->\n", __func__); | 255 | pr_debug("%s: ->\n", __func__); |
256 | return ret; | 256 | return ret; |
257 | } | 257 | } |
258 | 258 | ||
259 | static void gelic_wl_send_iwap_event(struct gelic_wl_info *wl, u8 *bssid) | 259 | static void gelic_wl_send_iwap_event(struct gelic_wl_info *wl, u8 *bssid) |
260 | { | 260 | { |
261 | union iwreq_data data; | 261 | union iwreq_data data; |
262 | 262 | ||
263 | memset(&data, 0, sizeof(data)); | 263 | memset(&data, 0, sizeof(data)); |
264 | if (bssid) | 264 | if (bssid) |
265 | memcpy(data.ap_addr.sa_data, bssid, ETH_ALEN); | 265 | memcpy(data.ap_addr.sa_data, bssid, ETH_ALEN); |
266 | data.ap_addr.sa_family = ARPHRD_ETHER; | 266 | data.ap_addr.sa_family = ARPHRD_ETHER; |
267 | wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWAP, | 267 | wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWAP, |
268 | &data, NULL); | 268 | &data, NULL); |
269 | } | 269 | } |
270 | 270 | ||
271 | /* | 271 | /* |
272 | * wireless extension handlers and helpers | 272 | * wireless extension handlers and helpers |
273 | */ | 273 | */ |
274 | 274 | ||
275 | /* SIOGIWNAME */ | 275 | /* SIOGIWNAME */ |
276 | static int gelic_wl_get_name(struct net_device *dev, | 276 | static int gelic_wl_get_name(struct net_device *dev, |
277 | struct iw_request_info *info, | 277 | struct iw_request_info *info, |
278 | union iwreq_data *iwreq, char *extra) | 278 | union iwreq_data *iwreq, char *extra) |
279 | { | 279 | { |
280 | strcpy(iwreq->name, "IEEE 802.11bg"); | 280 | strcpy(iwreq->name, "IEEE 802.11bg"); |
281 | return 0; | 281 | return 0; |
282 | } | 282 | } |
283 | 283 | ||
284 | static void gelic_wl_get_ch_info(struct gelic_wl_info *wl) | 284 | static void gelic_wl_get_ch_info(struct gelic_wl_info *wl) |
285 | { | 285 | { |
286 | struct gelic_card *card = port_to_card(wl_port(wl)); | 286 | struct gelic_card *card = port_to_card(wl_port(wl)); |
287 | u64 ch_info_raw, tmp; | 287 | u64 ch_info_raw, tmp; |
288 | int status; | 288 | int status; |
289 | 289 | ||
290 | if (!test_and_set_bit(GELIC_WL_STAT_CH_INFO, &wl->stat)) { | 290 | if (!test_and_set_bit(GELIC_WL_STAT_CH_INFO, &wl->stat)) { |
291 | status = lv1_net_control(bus_id(card), dev_id(card), | 291 | status = lv1_net_control(bus_id(card), dev_id(card), |
292 | GELIC_LV1_GET_CHANNEL, 0, 0, 0, | 292 | GELIC_LV1_GET_CHANNEL, 0, 0, 0, |
293 | &ch_info_raw, | 293 | &ch_info_raw, |
294 | &tmp); | 294 | &tmp); |
295 | /* some fw versions may return error */ | 295 | /* some fw versions may return error */ |
296 | if (status) { | 296 | if (status) { |
297 | if (status != LV1_NO_ENTRY) | 297 | if (status != LV1_NO_ENTRY) |
298 | pr_info("%s: available ch unknown\n", __func__); | 298 | pr_info("%s: available ch unknown\n", __func__); |
299 | wl->ch_info = 0x07ff;/* 11 ch */ | 299 | wl->ch_info = 0x07ff;/* 11 ch */ |
300 | } else | 300 | } else |
301 | /* 16 bits of MSB has available channels */ | 301 | /* 16 bits of MSB has available channels */ |
302 | wl->ch_info = ch_info_raw >> 48; | 302 | wl->ch_info = ch_info_raw >> 48; |
303 | } | 303 | } |
304 | } | 304 | } |
305 | 305 | ||
306 | /* SIOGIWRANGE */ | 306 | /* SIOGIWRANGE */ |
307 | static int gelic_wl_get_range(struct net_device *netdev, | 307 | static int gelic_wl_get_range(struct net_device *netdev, |
308 | struct iw_request_info *info, | 308 | struct iw_request_info *info, |
309 | union iwreq_data *iwreq, char *extra) | 309 | union iwreq_data *iwreq, char *extra) |
310 | { | 310 | { |
311 | struct iw_point *point = &iwreq->data; | 311 | struct iw_point *point = &iwreq->data; |
312 | struct iw_range *range = (struct iw_range *)extra; | 312 | struct iw_range *range = (struct iw_range *)extra; |
313 | struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); | 313 | struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); |
314 | unsigned int i, chs; | 314 | unsigned int i, chs; |
315 | 315 | ||
316 | pr_debug("%s: <-\n", __func__); | 316 | pr_debug("%s: <-\n", __func__); |
317 | point->length = sizeof(struct iw_range); | 317 | point->length = sizeof(struct iw_range); |
318 | memset(range, 0, sizeof(struct iw_range)); | 318 | memset(range, 0, sizeof(struct iw_range)); |
319 | 319 | ||
320 | range->we_version_compiled = WIRELESS_EXT; | 320 | range->we_version_compiled = WIRELESS_EXT; |
321 | range->we_version_source = 22; | 321 | range->we_version_source = 22; |
322 | 322 | ||
323 | /* available channels and frequencies */ | 323 | /* available channels and frequencies */ |
324 | gelic_wl_get_ch_info(wl); | 324 | gelic_wl_get_ch_info(wl); |
325 | 325 | ||
326 | for (i = 0, chs = 0; | 326 | for (i = 0, chs = 0; |
327 | i < NUM_CHANNELS && chs < IW_MAX_FREQUENCIES; i++) | 327 | i < NUM_CHANNELS && chs < IW_MAX_FREQUENCIES; i++) |
328 | if (wl->ch_info & (1 << i)) { | 328 | if (wl->ch_info & (1 << i)) { |
329 | range->freq[chs].i = i + 1; | 329 | range->freq[chs].i = i + 1; |
330 | range->freq[chs].m = channel_freq[i]; | 330 | range->freq[chs].m = channel_freq[i]; |
331 | range->freq[chs].e = 6; | 331 | range->freq[chs].e = 6; |
332 | chs++; | 332 | chs++; |
333 | } | 333 | } |
334 | range->num_frequency = chs; | 334 | range->num_frequency = chs; |
335 | range->old_num_frequency = chs; | 335 | range->old_num_frequency = chs; |
336 | range->num_channels = chs; | 336 | range->num_channels = chs; |
337 | range->old_num_channels = chs; | 337 | range->old_num_channels = chs; |
338 | 338 | ||
339 | /* bitrates */ | 339 | /* bitrates */ |
340 | for (i = 0; i < NUM_BITRATES; i++) | 340 | for (i = 0; i < NUM_BITRATES; i++) |
341 | range->bitrate[i] = bitrate_list[i]; | 341 | range->bitrate[i] = bitrate_list[i]; |
342 | range->num_bitrates = i; | 342 | range->num_bitrates = i; |
343 | 343 | ||
344 | /* signal levels */ | 344 | /* signal levels */ |
345 | range->max_qual.qual = 100; /* relative value */ | 345 | range->max_qual.qual = 100; /* relative value */ |
346 | range->max_qual.level = 100; | 346 | range->max_qual.level = 100; |
347 | range->avg_qual.qual = 50; | 347 | range->avg_qual.qual = 50; |
348 | range->avg_qual.level = 50; | 348 | range->avg_qual.level = 50; |
349 | range->sensitivity = 0; | 349 | range->sensitivity = 0; |
350 | 350 | ||
351 | /* Event capability */ | 351 | /* Event capability */ |
352 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); | 352 | IW_EVENT_CAPA_SET_KERNEL(range->event_capa); |
353 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); | 353 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); |
354 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); | 354 | IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); |
355 | 355 | ||
356 | /* encryption capability */ | 356 | /* encryption capability */ |
357 | range->enc_capa = IW_ENC_CAPA_WPA | | 357 | range->enc_capa = IW_ENC_CAPA_WPA | |
358 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP | | 358 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP | |
359 | IW_ENC_CAPA_4WAY_HANDSHAKE; | 359 | IW_ENC_CAPA_4WAY_HANDSHAKE; |
360 | if (wpa2_capable()) | 360 | if (wpa2_capable()) |
361 | range->enc_capa |= IW_ENC_CAPA_WPA2; | 361 | range->enc_capa |= IW_ENC_CAPA_WPA2; |
362 | range->encoding_size[0] = 5; /* 40bit WEP */ | 362 | range->encoding_size[0] = 5; /* 40bit WEP */ |
363 | range->encoding_size[1] = 13; /* 104bit WEP */ | 363 | range->encoding_size[1] = 13; /* 104bit WEP */ |
364 | range->encoding_size[2] = 32; /* WPA-PSK */ | 364 | range->encoding_size[2] = 32; /* WPA-PSK */ |
365 | range->num_encoding_sizes = 3; | 365 | range->num_encoding_sizes = 3; |
366 | range->max_encoding_tokens = GELIC_WEP_KEYS; | 366 | range->max_encoding_tokens = GELIC_WEP_KEYS; |
367 | 367 | ||
368 | /* scan capability */ | 368 | /* scan capability */ |
369 | range->scan_capa = IW_SCAN_CAPA_ESSID; | 369 | range->scan_capa = IW_SCAN_CAPA_ESSID; |
370 | 370 | ||
371 | pr_debug("%s: ->\n", __func__); | 371 | pr_debug("%s: ->\n", __func__); |
372 | return 0; | 372 | return 0; |
373 | 373 | ||
374 | } | 374 | } |
375 | 375 | ||
376 | /* SIOC{G,S}IWSCAN */ | 376 | /* SIOC{G,S}IWSCAN */ |
377 | static int gelic_wl_set_scan(struct net_device *netdev, | 377 | static int gelic_wl_set_scan(struct net_device *netdev, |
378 | struct iw_request_info *info, | 378 | struct iw_request_info *info, |
379 | union iwreq_data *wrqu, char *extra) | 379 | union iwreq_data *wrqu, char *extra) |
380 | { | 380 | { |
381 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 381 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
382 | struct iw_scan_req *req; | 382 | struct iw_scan_req *req; |
383 | u8 *essid = NULL; | 383 | u8 *essid = NULL; |
384 | size_t essid_len = 0; | 384 | size_t essid_len = 0; |
385 | 385 | ||
386 | if (wrqu->data.length == sizeof(struct iw_scan_req) && | 386 | if (wrqu->data.length == sizeof(struct iw_scan_req) && |
387 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { | 387 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
388 | req = (struct iw_scan_req*)extra; | 388 | req = (struct iw_scan_req*)extra; |
389 | essid = req->essid; | 389 | essid = req->essid; |
390 | essid_len = req->essid_len; | 390 | essid_len = req->essid_len; |
391 | pr_debug("%s: ESSID scan =%s\n", __func__, essid); | 391 | pr_debug("%s: ESSID scan =%s\n", __func__, essid); |
392 | } | 392 | } |
393 | return gelic_wl_start_scan(wl, 1, essid, essid_len); | 393 | return gelic_wl_start_scan(wl, 1, essid, essid_len); |
394 | } | 394 | } |
395 | 395 | ||
396 | #define OUI_LEN 3 | 396 | #define OUI_LEN 3 |
397 | static const u8 rsn_oui[OUI_LEN] = { 0x00, 0x0f, 0xac }; | 397 | static const u8 rsn_oui[OUI_LEN] = { 0x00, 0x0f, 0xac }; |
398 | static const u8 wpa_oui[OUI_LEN] = { 0x00, 0x50, 0xf2 }; | 398 | static const u8 wpa_oui[OUI_LEN] = { 0x00, 0x50, 0xf2 }; |
399 | 399 | ||
400 | /* | 400 | /* |
401 | * synthesize WPA/RSN IE data | 401 | * synthesize WPA/RSN IE data |
402 | * See WiFi WPA specification and IEEE 802.11-2007 7.3.2.25 | 402 | * See WiFi WPA specification and IEEE 802.11-2007 7.3.2.25 |
403 | * for the format | 403 | * for the format |
404 | */ | 404 | */ |
405 | static size_t gelic_wl_synthesize_ie(u8 *buf, | 405 | static size_t gelic_wl_synthesize_ie(u8 *buf, |
406 | struct gelic_eurus_scan_info *scan) | 406 | struct gelic_eurus_scan_info *scan) |
407 | { | 407 | { |
408 | 408 | ||
409 | const u8 *oui_header; | 409 | const u8 *oui_header; |
410 | u8 *start = buf; | 410 | u8 *start = buf; |
411 | int rsn; | 411 | int rsn; |
412 | int ccmp; | 412 | int ccmp; |
413 | 413 | ||
414 | pr_debug("%s: <- sec=%16x\n", __func__, scan->security); | 414 | pr_debug("%s: <- sec=%16x\n", __func__, scan->security); |
415 | switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_MASK) { | 415 | switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_MASK) { |
416 | case GELIC_EURUS_SCAN_SEC_WPA: | 416 | case GELIC_EURUS_SCAN_SEC_WPA: |
417 | rsn = 0; | 417 | rsn = 0; |
418 | break; | 418 | break; |
419 | case GELIC_EURUS_SCAN_SEC_WPA2: | 419 | case GELIC_EURUS_SCAN_SEC_WPA2: |
420 | rsn = 1; | 420 | rsn = 1; |
421 | break; | 421 | break; |
422 | default: | 422 | default: |
423 | /* WEP or none. No IE returned */ | 423 | /* WEP or none. No IE returned */ |
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | 426 | ||
427 | switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_WPA_MASK) { | 427 | switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_WPA_MASK) { |
428 | case GELIC_EURUS_SCAN_SEC_WPA_TKIP: | 428 | case GELIC_EURUS_SCAN_SEC_WPA_TKIP: |
429 | ccmp = 0; | 429 | ccmp = 0; |
430 | break; | 430 | break; |
431 | case GELIC_EURUS_SCAN_SEC_WPA_AES: | 431 | case GELIC_EURUS_SCAN_SEC_WPA_AES: |
432 | ccmp = 1; | 432 | ccmp = 1; |
433 | break; | 433 | break; |
434 | default: | 434 | default: |
435 | if (rsn) { | 435 | if (rsn) { |
436 | ccmp = 1; | 436 | ccmp = 1; |
437 | pr_info("%s: no cipher info. defaulted to CCMP\n", | 437 | pr_info("%s: no cipher info. defaulted to CCMP\n", |
438 | __func__); | 438 | __func__); |
439 | } else { | 439 | } else { |
440 | ccmp = 0; | 440 | ccmp = 0; |
441 | pr_info("%s: no cipher info. defaulted to TKIP\n", | 441 | pr_info("%s: no cipher info. defaulted to TKIP\n", |
442 | __func__); | 442 | __func__); |
443 | } | 443 | } |
444 | } | 444 | } |
445 | 445 | ||
446 | if (rsn) | 446 | if (rsn) |
447 | oui_header = rsn_oui; | 447 | oui_header = rsn_oui; |
448 | else | 448 | else |
449 | oui_header = wpa_oui; | 449 | oui_header = wpa_oui; |
450 | 450 | ||
451 | /* element id */ | 451 | /* element id */ |
452 | if (rsn) | 452 | if (rsn) |
453 | *buf++ = WLAN_EID_RSN; | 453 | *buf++ = WLAN_EID_RSN; |
454 | else | 454 | else |
455 | *buf++ = WLAN_EID_GENERIC; | 455 | *buf++ = WLAN_EID_GENERIC; |
456 | 456 | ||
457 | /* length filed; set later */ | 457 | /* length filed; set later */ |
458 | buf++; | 458 | buf++; |
459 | 459 | ||
460 | /* wpa special header */ | 460 | /* wpa special header */ |
461 | if (!rsn) { | 461 | if (!rsn) { |
462 | memcpy(buf, wpa_oui, OUI_LEN); | 462 | memcpy(buf, wpa_oui, OUI_LEN); |
463 | buf += OUI_LEN; | 463 | buf += OUI_LEN; |
464 | *buf++ = 0x01; | 464 | *buf++ = 0x01; |
465 | } | 465 | } |
466 | 466 | ||
467 | /* version */ | 467 | /* version */ |
468 | *buf++ = 0x01; /* version 1.0 */ | 468 | *buf++ = 0x01; /* version 1.0 */ |
469 | *buf++ = 0x00; | 469 | *buf++ = 0x00; |
470 | 470 | ||
471 | /* group cipher */ | 471 | /* group cipher */ |
472 | memcpy(buf, oui_header, OUI_LEN); | 472 | memcpy(buf, oui_header, OUI_LEN); |
473 | buf += OUI_LEN; | 473 | buf += OUI_LEN; |
474 | 474 | ||
475 | if (ccmp) | 475 | if (ccmp) |
476 | *buf++ = 0x04; /* CCMP */ | 476 | *buf++ = 0x04; /* CCMP */ |
477 | else | 477 | else |
478 | *buf++ = 0x02; /* TKIP */ | 478 | *buf++ = 0x02; /* TKIP */ |
479 | 479 | ||
480 | /* pairwise key count always 1 */ | 480 | /* pairwise key count always 1 */ |
481 | *buf++ = 0x01; | 481 | *buf++ = 0x01; |
482 | *buf++ = 0x00; | 482 | *buf++ = 0x00; |
483 | 483 | ||
484 | /* pairwise key suit */ | 484 | /* pairwise key suit */ |
485 | memcpy(buf, oui_header, OUI_LEN); | 485 | memcpy(buf, oui_header, OUI_LEN); |
486 | buf += OUI_LEN; | 486 | buf += OUI_LEN; |
487 | if (ccmp) | 487 | if (ccmp) |
488 | *buf++ = 0x04; /* CCMP */ | 488 | *buf++ = 0x04; /* CCMP */ |
489 | else | 489 | else |
490 | *buf++ = 0x02; /* TKIP */ | 490 | *buf++ = 0x02; /* TKIP */ |
491 | 491 | ||
492 | /* AKM count is 1 */ | 492 | /* AKM count is 1 */ |
493 | *buf++ = 0x01; | 493 | *buf++ = 0x01; |
494 | *buf++ = 0x00; | 494 | *buf++ = 0x00; |
495 | 495 | ||
496 | /* AKM suite is assumed as PSK*/ | 496 | /* AKM suite is assumed as PSK*/ |
497 | memcpy(buf, oui_header, OUI_LEN); | 497 | memcpy(buf, oui_header, OUI_LEN); |
498 | buf += OUI_LEN; | 498 | buf += OUI_LEN; |
499 | *buf++ = 0x02; /* PSK */ | 499 | *buf++ = 0x02; /* PSK */ |
500 | 500 | ||
501 | /* RSN capabilities is 0 */ | 501 | /* RSN capabilities is 0 */ |
502 | *buf++ = 0x00; | 502 | *buf++ = 0x00; |
503 | *buf++ = 0x00; | 503 | *buf++ = 0x00; |
504 | 504 | ||
505 | /* set length field */ | 505 | /* set length field */ |
506 | start[1] = (buf - start - 2); | 506 | start[1] = (buf - start - 2); |
507 | 507 | ||
508 | pr_debug("%s: ->\n", __func__); | 508 | pr_debug("%s: ->\n", __func__); |
509 | return buf - start; | 509 | return buf - start; |
510 | } | 510 | } |
511 | 511 | ||
512 | struct ie_item { | 512 | struct ie_item { |
513 | u8 *data; | 513 | u8 *data; |
514 | u8 len; | 514 | u8 len; |
515 | }; | 515 | }; |
516 | 516 | ||
517 | struct ie_info { | 517 | struct ie_info { |
518 | struct ie_item wpa; | 518 | struct ie_item wpa; |
519 | struct ie_item rsn; | 519 | struct ie_item rsn; |
520 | }; | 520 | }; |
521 | 521 | ||
522 | static void gelic_wl_parse_ie(u8 *data, size_t len, | 522 | static void gelic_wl_parse_ie(u8 *data, size_t len, |
523 | struct ie_info *ie_info) | 523 | struct ie_info *ie_info) |
524 | { | 524 | { |
525 | size_t data_left = len; | 525 | size_t data_left = len; |
526 | u8 *pos = data; | 526 | u8 *pos = data; |
527 | u8 item_len; | 527 | u8 item_len; |
528 | u8 item_id; | 528 | u8 item_id; |
529 | 529 | ||
530 | pr_debug("%s: data=%p len=%ld\n", __func__, | 530 | pr_debug("%s: data=%p len=%ld\n", __func__, |
531 | data, len); | 531 | data, len); |
532 | memset(ie_info, 0, sizeof(struct ie_info)); | 532 | memset(ie_info, 0, sizeof(struct ie_info)); |
533 | 533 | ||
534 | while (2 <= data_left) { | 534 | while (2 <= data_left) { |
535 | item_id = *pos++; | 535 | item_id = *pos++; |
536 | item_len = *pos++; | 536 | item_len = *pos++; |
537 | data_left -= 2; | 537 | data_left -= 2; |
538 | 538 | ||
539 | if (data_left < item_len) | 539 | if (data_left < item_len) |
540 | break; | 540 | break; |
541 | 541 | ||
542 | switch (item_id) { | 542 | switch (item_id) { |
543 | case WLAN_EID_GENERIC: | 543 | case WLAN_EID_GENERIC: |
544 | if ((OUI_LEN + 1 <= item_len) && | 544 | if ((OUI_LEN + 1 <= item_len) && |
545 | !memcmp(pos, wpa_oui, OUI_LEN) && | 545 | !memcmp(pos, wpa_oui, OUI_LEN) && |
546 | pos[OUI_LEN] == 0x01) { | 546 | pos[OUI_LEN] == 0x01) { |
547 | ie_info->wpa.data = pos - 2; | 547 | ie_info->wpa.data = pos - 2; |
548 | ie_info->wpa.len = item_len + 2; | 548 | ie_info->wpa.len = item_len + 2; |
549 | } | 549 | } |
550 | break; | 550 | break; |
551 | case WLAN_EID_RSN: | 551 | case WLAN_EID_RSN: |
552 | ie_info->rsn.data = pos - 2; | 552 | ie_info->rsn.data = pos - 2; |
553 | /* length includes the header */ | 553 | /* length includes the header */ |
554 | ie_info->rsn.len = item_len + 2; | 554 | ie_info->rsn.len = item_len + 2; |
555 | break; | 555 | break; |
556 | default: | 556 | default: |
557 | pr_debug("%s: ignore %#x,%d\n", __func__, | 557 | pr_debug("%s: ignore %#x,%d\n", __func__, |
558 | item_id, item_len); | 558 | item_id, item_len); |
559 | break; | 559 | break; |
560 | } | 560 | } |
561 | pos += item_len; | 561 | pos += item_len; |
562 | data_left -= item_len; | 562 | data_left -= item_len; |
563 | } | 563 | } |
564 | pr_debug("%s: wpa=%p,%d wpa2=%p,%d\n", __func__, | 564 | pr_debug("%s: wpa=%p,%d wpa2=%p,%d\n", __func__, |
565 | ie_info->wpa.data, ie_info->wpa.len, | 565 | ie_info->wpa.data, ie_info->wpa.len, |
566 | ie_info->rsn.data, ie_info->rsn.len); | 566 | ie_info->rsn.data, ie_info->rsn.len); |
567 | } | 567 | } |
568 | 568 | ||
569 | 569 | ||
570 | /* | 570 | /* |
571 | * translate the scan informations from hypervisor to a | 571 | * translate the scan informations from hypervisor to a |
572 | * independent format | 572 | * independent format |
573 | */ | 573 | */ |
574 | static char *gelic_wl_translate_scan(struct net_device *netdev, | 574 | static char *gelic_wl_translate_scan(struct net_device *netdev, |
575 | struct iw_request_info *info, | 575 | struct iw_request_info *info, |
576 | char *ev, | 576 | char *ev, |
577 | char *stop, | 577 | char *stop, |
578 | struct gelic_wl_scan_info *network) | 578 | struct gelic_wl_scan_info *network) |
579 | { | 579 | { |
580 | struct iw_event iwe; | 580 | struct iw_event iwe; |
581 | struct gelic_eurus_scan_info *scan = network->hwinfo; | 581 | struct gelic_eurus_scan_info *scan = network->hwinfo; |
582 | char *tmp; | 582 | char *tmp; |
583 | u8 rate; | 583 | u8 rate; |
584 | unsigned int i, j, len; | 584 | unsigned int i, j, len; |
585 | u8 buf[64]; /* arbitrary size large enough */ | 585 | u8 buf[64]; /* arbitrary size large enough */ |
586 | 586 | ||
587 | pr_debug("%s: <-\n", __func__); | 587 | pr_debug("%s: <-\n", __func__); |
588 | 588 | ||
589 | /* first entry should be AP's mac address */ | 589 | /* first entry should be AP's mac address */ |
590 | iwe.cmd = SIOCGIWAP; | 590 | iwe.cmd = SIOCGIWAP; |
591 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 591 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
592 | memcpy(iwe.u.ap_addr.sa_data, &scan->bssid[2], ETH_ALEN); | 592 | memcpy(iwe.u.ap_addr.sa_data, &scan->bssid[2], ETH_ALEN); |
593 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_ADDR_LEN); | 593 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_ADDR_LEN); |
594 | 594 | ||
595 | /* ESSID */ | 595 | /* ESSID */ |
596 | iwe.cmd = SIOCGIWESSID; | 596 | iwe.cmd = SIOCGIWESSID; |
597 | iwe.u.data.flags = 1; | 597 | iwe.u.data.flags = 1; |
598 | iwe.u.data.length = strnlen(scan->essid, 32); | 598 | iwe.u.data.length = strnlen(scan->essid, 32); |
599 | ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); | 599 | ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); |
600 | 600 | ||
601 | /* FREQUENCY */ | 601 | /* FREQUENCY */ |
602 | iwe.cmd = SIOCGIWFREQ; | 602 | iwe.cmd = SIOCGIWFREQ; |
603 | iwe.u.freq.m = be16_to_cpu(scan->channel); | 603 | iwe.u.freq.m = be16_to_cpu(scan->channel); |
604 | iwe.u.freq.e = 0; /* table value in MHz */ | 604 | iwe.u.freq.e = 0; /* table value in MHz */ |
605 | iwe.u.freq.i = 0; | 605 | iwe.u.freq.i = 0; |
606 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_FREQ_LEN); | 606 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_FREQ_LEN); |
607 | 607 | ||
608 | /* RATES */ | 608 | /* RATES */ |
609 | iwe.cmd = SIOCGIWRATE; | 609 | iwe.cmd = SIOCGIWRATE; |
610 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | 610 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; |
611 | /* to stuff multiple values in one event */ | 611 | /* to stuff multiple values in one event */ |
612 | tmp = ev + iwe_stream_lcp_len(info); | 612 | tmp = ev + iwe_stream_lcp_len(info); |
613 | /* put them in ascendant order (older is first) */ | 613 | /* put them in ascendant order (older is first) */ |
614 | i = 0; | 614 | i = 0; |
615 | j = 0; | 615 | j = 0; |
616 | pr_debug("%s: rates=%d rate=%d\n", __func__, | 616 | pr_debug("%s: rates=%d rate=%d\n", __func__, |
617 | network->rate_len, network->rate_ext_len); | 617 | network->rate_len, network->rate_ext_len); |
618 | while (i < network->rate_len) { | 618 | while (i < network->rate_len) { |
619 | if (j < network->rate_ext_len && | 619 | if (j < network->rate_ext_len && |
620 | ((scan->ext_rate[j] & 0x7f) < (scan->rate[i] & 0x7f))) | 620 | ((scan->ext_rate[j] & 0x7f) < (scan->rate[i] & 0x7f))) |
621 | rate = scan->ext_rate[j++] & 0x7f; | 621 | rate = scan->ext_rate[j++] & 0x7f; |
622 | else | 622 | else |
623 | rate = scan->rate[i++] & 0x7f; | 623 | rate = scan->rate[i++] & 0x7f; |
624 | iwe.u.bitrate.value = rate * 500000; /* 500kbps unit */ | 624 | iwe.u.bitrate.value = rate * 500000; /* 500kbps unit */ |
625 | tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, | 625 | tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, |
626 | IW_EV_PARAM_LEN); | 626 | IW_EV_PARAM_LEN); |
627 | } | 627 | } |
628 | while (j < network->rate_ext_len) { | 628 | while (j < network->rate_ext_len) { |
629 | iwe.u.bitrate.value = (scan->ext_rate[j++] & 0x7f) * 500000; | 629 | iwe.u.bitrate.value = (scan->ext_rate[j++] & 0x7f) * 500000; |
630 | tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, | 630 | tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, |
631 | IW_EV_PARAM_LEN); | 631 | IW_EV_PARAM_LEN); |
632 | } | 632 | } |
633 | /* Check if we added any rate */ | 633 | /* Check if we added any rate */ |
634 | if (iwe_stream_lcp_len(info) < (tmp - ev)) | 634 | if (iwe_stream_lcp_len(info) < (tmp - ev)) |
635 | ev = tmp; | 635 | ev = tmp; |
636 | 636 | ||
637 | /* ENCODE */ | 637 | /* ENCODE */ |
638 | iwe.cmd = SIOCGIWENCODE; | 638 | iwe.cmd = SIOCGIWENCODE; |
639 | if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_PRIVACY) | 639 | if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_PRIVACY) |
640 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | 640 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; |
641 | else | 641 | else |
642 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 642 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
643 | iwe.u.data.length = 0; | 643 | iwe.u.data.length = 0; |
644 | ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); | 644 | ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); |
645 | 645 | ||
646 | /* MODE */ | 646 | /* MODE */ |
647 | iwe.cmd = SIOCGIWMODE; | 647 | iwe.cmd = SIOCGIWMODE; |
648 | if (be16_to_cpu(scan->capability) & | 648 | if (be16_to_cpu(scan->capability) & |
649 | (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { | 649 | (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { |
650 | if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_ESS) | 650 | if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_ESS) |
651 | iwe.u.mode = IW_MODE_MASTER; | 651 | iwe.u.mode = IW_MODE_MASTER; |
652 | else | 652 | else |
653 | iwe.u.mode = IW_MODE_ADHOC; | 653 | iwe.u.mode = IW_MODE_ADHOC; |
654 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_UINT_LEN); | 654 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_UINT_LEN); |
655 | } | 655 | } |
656 | 656 | ||
657 | /* QUAL */ | 657 | /* QUAL */ |
658 | iwe.cmd = IWEVQUAL; | 658 | iwe.cmd = IWEVQUAL; |
659 | iwe.u.qual.updated = IW_QUAL_ALL_UPDATED | | 659 | iwe.u.qual.updated = IW_QUAL_ALL_UPDATED | |
660 | IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID; | 660 | IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID; |
661 | iwe.u.qual.level = be16_to_cpu(scan->rssi); | 661 | iwe.u.qual.level = be16_to_cpu(scan->rssi); |
662 | iwe.u.qual.qual = be16_to_cpu(scan->rssi); | 662 | iwe.u.qual.qual = be16_to_cpu(scan->rssi); |
663 | iwe.u.qual.noise = 0; | 663 | iwe.u.qual.noise = 0; |
664 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_QUAL_LEN); | 664 | ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_QUAL_LEN); |
665 | 665 | ||
666 | /* RSN */ | 666 | /* RSN */ |
667 | memset(&iwe, 0, sizeof(iwe)); | 667 | memset(&iwe, 0, sizeof(iwe)); |
668 | if (be16_to_cpu(scan->size) <= sizeof(*scan)) { | 668 | if (be16_to_cpu(scan->size) <= sizeof(*scan)) { |
669 | /* If wpa[2] capable station, synthesize IE and put it */ | 669 | /* If wpa[2] capable station, synthesize IE and put it */ |
670 | len = gelic_wl_synthesize_ie(buf, scan); | 670 | len = gelic_wl_synthesize_ie(buf, scan); |
671 | if (len) { | 671 | if (len) { |
672 | iwe.cmd = IWEVGENIE; | 672 | iwe.cmd = IWEVGENIE; |
673 | iwe.u.data.length = len; | 673 | iwe.u.data.length = len; |
674 | ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); | 674 | ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); |
675 | } | 675 | } |
676 | } else { | 676 | } else { |
677 | /* this scan info has IE data */ | 677 | /* this scan info has IE data */ |
678 | struct ie_info ie_info; | 678 | struct ie_info ie_info; |
679 | size_t data_len; | 679 | size_t data_len; |
680 | 680 | ||
681 | data_len = be16_to_cpu(scan->size) - sizeof(*scan); | 681 | data_len = be16_to_cpu(scan->size) - sizeof(*scan); |
682 | 682 | ||
683 | gelic_wl_parse_ie(scan->elements, data_len, &ie_info); | 683 | gelic_wl_parse_ie(scan->elements, data_len, &ie_info); |
684 | 684 | ||
685 | if (ie_info.wpa.len && (ie_info.wpa.len <= sizeof(buf))) { | 685 | if (ie_info.wpa.len && (ie_info.wpa.len <= sizeof(buf))) { |
686 | memcpy(buf, ie_info.wpa.data, ie_info.wpa.len); | 686 | memcpy(buf, ie_info.wpa.data, ie_info.wpa.len); |
687 | iwe.cmd = IWEVGENIE; | 687 | iwe.cmd = IWEVGENIE; |
688 | iwe.u.data.length = ie_info.wpa.len; | 688 | iwe.u.data.length = ie_info.wpa.len; |
689 | ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); | 689 | ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); |
690 | } | 690 | } |
691 | 691 | ||
692 | if (ie_info.rsn.len && (ie_info.rsn.len <= sizeof(buf))) { | 692 | if (ie_info.rsn.len && (ie_info.rsn.len <= sizeof(buf))) { |
693 | memset(&iwe, 0, sizeof(iwe)); | 693 | memset(&iwe, 0, sizeof(iwe)); |
694 | memcpy(buf, ie_info.rsn.data, ie_info.rsn.len); | 694 | memcpy(buf, ie_info.rsn.data, ie_info.rsn.len); |
695 | iwe.cmd = IWEVGENIE; | 695 | iwe.cmd = IWEVGENIE; |
696 | iwe.u.data.length = ie_info.rsn.len; | 696 | iwe.u.data.length = ie_info.rsn.len; |
697 | ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); | 697 | ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); |
698 | } | 698 | } |
699 | } | 699 | } |
700 | 700 | ||
701 | pr_debug("%s: ->\n", __func__); | 701 | pr_debug("%s: ->\n", __func__); |
702 | return ev; | 702 | return ev; |
703 | } | 703 | } |
704 | 704 | ||
705 | 705 | ||
706 | static int gelic_wl_get_scan(struct net_device *netdev, | 706 | static int gelic_wl_get_scan(struct net_device *netdev, |
707 | struct iw_request_info *info, | 707 | struct iw_request_info *info, |
708 | union iwreq_data *wrqu, char *extra) | 708 | union iwreq_data *wrqu, char *extra) |
709 | { | 709 | { |
710 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 710 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
711 | struct gelic_wl_scan_info *scan_info; | 711 | struct gelic_wl_scan_info *scan_info; |
712 | char *ev = extra; | 712 | char *ev = extra; |
713 | char *stop = ev + wrqu->data.length; | 713 | char *stop = ev + wrqu->data.length; |
714 | int ret = 0; | 714 | int ret = 0; |
715 | unsigned long this_time = jiffies; | 715 | unsigned long this_time = jiffies; |
716 | 716 | ||
717 | pr_debug("%s: <-\n", __func__); | 717 | pr_debug("%s: <-\n", __func__); |
718 | if (mutex_lock_interruptible(&wl->scan_lock)) | 718 | if (mutex_lock_interruptible(&wl->scan_lock)) |
719 | return -EAGAIN; | 719 | return -EAGAIN; |
720 | 720 | ||
721 | switch (wl->scan_stat) { | 721 | switch (wl->scan_stat) { |
722 | case GELIC_WL_SCAN_STAT_SCANNING: | 722 | case GELIC_WL_SCAN_STAT_SCANNING: |
723 | /* If a scan in progress, caller should call me again */ | 723 | /* If a scan in progress, caller should call me again */ |
724 | ret = -EAGAIN; | 724 | ret = -EAGAIN; |
725 | goto out; | 725 | goto out; |
726 | break; | 726 | break; |
727 | 727 | ||
728 | case GELIC_WL_SCAN_STAT_INIT: | 728 | case GELIC_WL_SCAN_STAT_INIT: |
729 | /* last scan request failed or never issued */ | 729 | /* last scan request failed or never issued */ |
730 | ret = -ENODEV; | 730 | ret = -ENODEV; |
731 | goto out; | 731 | goto out; |
732 | break; | 732 | break; |
733 | case GELIC_WL_SCAN_STAT_GOT_LIST: | 733 | case GELIC_WL_SCAN_STAT_GOT_LIST: |
734 | /* ok, use current list */ | 734 | /* ok, use current list */ |
735 | break; | 735 | break; |
736 | } | 736 | } |
737 | 737 | ||
738 | list_for_each_entry(scan_info, &wl->network_list, list) { | 738 | list_for_each_entry(scan_info, &wl->network_list, list) { |
739 | if (wl->scan_age == 0 || | 739 | if (wl->scan_age == 0 || |
740 | time_after(scan_info->last_scanned + wl->scan_age, | 740 | time_after(scan_info->last_scanned + wl->scan_age, |
741 | this_time)) | 741 | this_time)) |
742 | ev = gelic_wl_translate_scan(netdev, info, | 742 | ev = gelic_wl_translate_scan(netdev, info, |
743 | ev, stop, | 743 | ev, stop, |
744 | scan_info); | 744 | scan_info); |
745 | else | 745 | else |
746 | pr_debug("%s:entry too old\n", __func__); | 746 | pr_debug("%s:entry too old\n", __func__); |
747 | 747 | ||
748 | if (stop - ev <= IW_EV_ADDR_LEN) { | 748 | if (stop - ev <= IW_EV_ADDR_LEN) { |
749 | ret = -E2BIG; | 749 | ret = -E2BIG; |
750 | goto out; | 750 | goto out; |
751 | } | 751 | } |
752 | } | 752 | } |
753 | 753 | ||
754 | wrqu->data.length = ev - extra; | 754 | wrqu->data.length = ev - extra; |
755 | wrqu->data.flags = 0; | 755 | wrqu->data.flags = 0; |
756 | out: | 756 | out: |
757 | mutex_unlock(&wl->scan_lock); | 757 | mutex_unlock(&wl->scan_lock); |
758 | pr_debug("%s: -> %d %d\n", __func__, ret, wrqu->data.length); | 758 | pr_debug("%s: -> %d %d\n", __func__, ret, wrqu->data.length); |
759 | return ret; | 759 | return ret; |
760 | } | 760 | } |
761 | 761 | ||
762 | #ifdef DEBUG | 762 | #ifdef DEBUG |
763 | static void scan_list_dump(struct gelic_wl_info *wl) | 763 | static void scan_list_dump(struct gelic_wl_info *wl) |
764 | { | 764 | { |
765 | struct gelic_wl_scan_info *scan_info; | 765 | struct gelic_wl_scan_info *scan_info; |
766 | int i; | 766 | int i; |
767 | 767 | ||
768 | i = 0; | 768 | i = 0; |
769 | list_for_each_entry(scan_info, &wl->network_list, list) { | 769 | list_for_each_entry(scan_info, &wl->network_list, list) { |
770 | pr_debug("%s: item %d\n", __func__, i++); | 770 | pr_debug("%s: item %d\n", __func__, i++); |
771 | pr_debug("valid=%d eurusindex=%d last=%lx\n", | 771 | pr_debug("valid=%d eurusindex=%d last=%lx\n", |
772 | scan_info->valid, scan_info->eurus_index, | 772 | scan_info->valid, scan_info->eurus_index, |
773 | scan_info->last_scanned); | 773 | scan_info->last_scanned); |
774 | pr_debug("r_len=%d r_ext_len=%d essid_len=%d\n", | 774 | pr_debug("r_len=%d r_ext_len=%d essid_len=%d\n", |
775 | scan_info->rate_len, scan_info->rate_ext_len, | 775 | scan_info->rate_len, scan_info->rate_ext_len, |
776 | scan_info->essid_len); | 776 | scan_info->essid_len); |
777 | /* -- */ | 777 | /* -- */ |
778 | pr_debug("bssid=%pM\n", &scan_info->hwinfo->bssid[2]); | 778 | pr_debug("bssid=%pM\n", &scan_info->hwinfo->bssid[2]); |
779 | pr_debug("essid=%s\n", scan_info->hwinfo->essid); | 779 | pr_debug("essid=%s\n", scan_info->hwinfo->essid); |
780 | } | 780 | } |
781 | } | 781 | } |
782 | #endif | 782 | #endif |
783 | 783 | ||
784 | static int gelic_wl_set_auth(struct net_device *netdev, | 784 | static int gelic_wl_set_auth(struct net_device *netdev, |
785 | struct iw_request_info *info, | 785 | struct iw_request_info *info, |
786 | union iwreq_data *data, char *extra) | 786 | union iwreq_data *data, char *extra) |
787 | { | 787 | { |
788 | struct iw_param *param = &data->param; | 788 | struct iw_param *param = &data->param; |
789 | struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); | 789 | struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); |
790 | unsigned long irqflag; | 790 | unsigned long irqflag; |
791 | int ret = 0; | 791 | int ret = 0; |
792 | 792 | ||
793 | pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX); | 793 | pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX); |
794 | spin_lock_irqsave(&wl->lock, irqflag); | 794 | spin_lock_irqsave(&wl->lock, irqflag); |
795 | switch (param->flags & IW_AUTH_INDEX) { | 795 | switch (param->flags & IW_AUTH_INDEX) { |
796 | case IW_AUTH_WPA_VERSION: | 796 | case IW_AUTH_WPA_VERSION: |
797 | if (param->value & IW_AUTH_WPA_VERSION_DISABLED) { | 797 | if (param->value & IW_AUTH_WPA_VERSION_DISABLED) { |
798 | pr_debug("%s: NO WPA selected\n", __func__); | 798 | pr_debug("%s: NO WPA selected\n", __func__); |
799 | wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; | 799 | wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; |
800 | wl->group_cipher_method = GELIC_WL_CIPHER_WEP; | 800 | wl->group_cipher_method = GELIC_WL_CIPHER_WEP; |
801 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; | 801 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; |
802 | } | 802 | } |
803 | if (param->value & IW_AUTH_WPA_VERSION_WPA) { | 803 | if (param->value & IW_AUTH_WPA_VERSION_WPA) { |
804 | pr_debug("%s: WPA version 1 selected\n", __func__); | 804 | pr_debug("%s: WPA version 1 selected\n", __func__); |
805 | wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA; | 805 | wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA; |
806 | wl->group_cipher_method = GELIC_WL_CIPHER_TKIP; | 806 | wl->group_cipher_method = GELIC_WL_CIPHER_TKIP; |
807 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP; | 807 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP; |
808 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; | 808 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; |
809 | } | 809 | } |
810 | if (param->value & IW_AUTH_WPA_VERSION_WPA2) { | 810 | if (param->value & IW_AUTH_WPA_VERSION_WPA2) { |
811 | /* | 811 | /* |
812 | * As the hypervisor may not tell the cipher | 812 | * As the hypervisor may not tell the cipher |
813 | * information of the AP if it is WPA2, | 813 | * information of the AP if it is WPA2, |
814 | * you will not decide suitable cipher from | 814 | * you will not decide suitable cipher from |
815 | * its beacon. | 815 | * its beacon. |
816 | * You should have knowledge about the AP's | 816 | * You should have knowledge about the AP's |
817 | * cipher information in other method prior to | 817 | * cipher information in other method prior to |
818 | * the association. | 818 | * the association. |
819 | */ | 819 | */ |
820 | if (!precise_ie()) | 820 | if (!precise_ie()) |
821 | pr_info("%s: WPA2 may not work\n", __func__); | 821 | pr_info("%s: WPA2 may not work\n", __func__); |
822 | if (wpa2_capable()) { | 822 | if (wpa2_capable()) { |
823 | wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA2; | 823 | wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA2; |
824 | wl->group_cipher_method = GELIC_WL_CIPHER_AES; | 824 | wl->group_cipher_method = GELIC_WL_CIPHER_AES; |
825 | wl->pairwise_cipher_method = | 825 | wl->pairwise_cipher_method = |
826 | GELIC_WL_CIPHER_AES; | 826 | GELIC_WL_CIPHER_AES; |
827 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; | 827 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; |
828 | } else | 828 | } else |
829 | ret = -EINVAL; | 829 | ret = -EINVAL; |
830 | } | 830 | } |
831 | break; | 831 | break; |
832 | 832 | ||
833 | case IW_AUTH_CIPHER_PAIRWISE: | 833 | case IW_AUTH_CIPHER_PAIRWISE: |
834 | if (param->value & | 834 | if (param->value & |
835 | (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { | 835 | (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { |
836 | pr_debug("%s: WEP selected\n", __func__); | 836 | pr_debug("%s: WEP selected\n", __func__); |
837 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; | 837 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; |
838 | } | 838 | } |
839 | if (param->value & IW_AUTH_CIPHER_TKIP) { | 839 | if (param->value & IW_AUTH_CIPHER_TKIP) { |
840 | pr_debug("%s: TKIP selected\n", __func__); | 840 | pr_debug("%s: TKIP selected\n", __func__); |
841 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP; | 841 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP; |
842 | } | 842 | } |
843 | if (param->value & IW_AUTH_CIPHER_CCMP) { | 843 | if (param->value & IW_AUTH_CIPHER_CCMP) { |
844 | pr_debug("%s: CCMP selected\n", __func__); | 844 | pr_debug("%s: CCMP selected\n", __func__); |
845 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_AES; | 845 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_AES; |
846 | } | 846 | } |
847 | if (param->value & IW_AUTH_CIPHER_NONE) { | 847 | if (param->value & IW_AUTH_CIPHER_NONE) { |
848 | pr_debug("%s: no auth selected\n", __func__); | 848 | pr_debug("%s: no auth selected\n", __func__); |
849 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; | 849 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; |
850 | } | 850 | } |
851 | break; | 851 | break; |
852 | case IW_AUTH_CIPHER_GROUP: | 852 | case IW_AUTH_CIPHER_GROUP: |
853 | if (param->value & | 853 | if (param->value & |
854 | (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { | 854 | (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { |
855 | pr_debug("%s: WEP selected\n", __func__); | 855 | pr_debug("%s: WEP selected\n", __func__); |
856 | wl->group_cipher_method = GELIC_WL_CIPHER_WEP; | 856 | wl->group_cipher_method = GELIC_WL_CIPHER_WEP; |
857 | } | 857 | } |
858 | if (param->value & IW_AUTH_CIPHER_TKIP) { | 858 | if (param->value & IW_AUTH_CIPHER_TKIP) { |
859 | pr_debug("%s: TKIP selected\n", __func__); | 859 | pr_debug("%s: TKIP selected\n", __func__); |
860 | wl->group_cipher_method = GELIC_WL_CIPHER_TKIP; | 860 | wl->group_cipher_method = GELIC_WL_CIPHER_TKIP; |
861 | } | 861 | } |
862 | if (param->value & IW_AUTH_CIPHER_CCMP) { | 862 | if (param->value & IW_AUTH_CIPHER_CCMP) { |
863 | pr_debug("%s: CCMP selected\n", __func__); | 863 | pr_debug("%s: CCMP selected\n", __func__); |
864 | wl->group_cipher_method = GELIC_WL_CIPHER_AES; | 864 | wl->group_cipher_method = GELIC_WL_CIPHER_AES; |
865 | } | 865 | } |
866 | if (param->value & IW_AUTH_CIPHER_NONE) { | 866 | if (param->value & IW_AUTH_CIPHER_NONE) { |
867 | pr_debug("%s: no auth selected\n", __func__); | 867 | pr_debug("%s: no auth selected\n", __func__); |
868 | wl->group_cipher_method = GELIC_WL_CIPHER_NONE; | 868 | wl->group_cipher_method = GELIC_WL_CIPHER_NONE; |
869 | } | 869 | } |
870 | break; | 870 | break; |
871 | case IW_AUTH_80211_AUTH_ALG: | 871 | case IW_AUTH_80211_AUTH_ALG: |
872 | if (param->value & IW_AUTH_ALG_SHARED_KEY) { | 872 | if (param->value & IW_AUTH_ALG_SHARED_KEY) { |
873 | pr_debug("%s: shared key specified\n", __func__); | 873 | pr_debug("%s: shared key specified\n", __func__); |
874 | wl->auth_method = GELIC_EURUS_AUTH_SHARED; | 874 | wl->auth_method = GELIC_EURUS_AUTH_SHARED; |
875 | } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { | 875 | } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { |
876 | pr_debug("%s: open system specified\n", __func__); | 876 | pr_debug("%s: open system specified\n", __func__); |
877 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; | 877 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; |
878 | } else | 878 | } else |
879 | ret = -EINVAL; | 879 | ret = -EINVAL; |
880 | break; | 880 | break; |
881 | 881 | ||
882 | case IW_AUTH_WPA_ENABLED: | 882 | case IW_AUTH_WPA_ENABLED: |
883 | if (param->value) { | 883 | if (param->value) { |
884 | pr_debug("%s: WPA enabled\n", __func__); | 884 | pr_debug("%s: WPA enabled\n", __func__); |
885 | wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA; | 885 | wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA; |
886 | } else { | 886 | } else { |
887 | pr_debug("%s: WPA disabled\n", __func__); | 887 | pr_debug("%s: WPA disabled\n", __func__); |
888 | wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; | 888 | wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; |
889 | } | 889 | } |
890 | break; | 890 | break; |
891 | 891 | ||
892 | case IW_AUTH_KEY_MGMT: | 892 | case IW_AUTH_KEY_MGMT: |
893 | if (param->value & IW_AUTH_KEY_MGMT_PSK) | 893 | if (param->value & IW_AUTH_KEY_MGMT_PSK) |
894 | break; | 894 | break; |
895 | /* intentionally fall through */ | 895 | /* intentionally fall through */ |
896 | default: | 896 | default: |
897 | ret = -EOPNOTSUPP; | 897 | ret = -EOPNOTSUPP; |
898 | break; | 898 | break; |
899 | } | 899 | } |
900 | 900 | ||
901 | if (!ret) | 901 | if (!ret) |
902 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); | 902 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); |
903 | 903 | ||
904 | spin_unlock_irqrestore(&wl->lock, irqflag); | 904 | spin_unlock_irqrestore(&wl->lock, irqflag); |
905 | pr_debug("%s: -> %d\n", __func__, ret); | 905 | pr_debug("%s: -> %d\n", __func__, ret); |
906 | return ret; | 906 | return ret; |
907 | } | 907 | } |
908 | 908 | ||
909 | static int gelic_wl_get_auth(struct net_device *netdev, | 909 | static int gelic_wl_get_auth(struct net_device *netdev, |
910 | struct iw_request_info *info, | 910 | struct iw_request_info *info, |
911 | union iwreq_data *iwreq, char *extra) | 911 | union iwreq_data *iwreq, char *extra) |
912 | { | 912 | { |
913 | struct iw_param *param = &iwreq->param; | 913 | struct iw_param *param = &iwreq->param; |
914 | struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); | 914 | struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); |
915 | unsigned long irqflag; | 915 | unsigned long irqflag; |
916 | int ret = 0; | 916 | int ret = 0; |
917 | 917 | ||
918 | pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX); | 918 | pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX); |
919 | spin_lock_irqsave(&wl->lock, irqflag); | 919 | spin_lock_irqsave(&wl->lock, irqflag); |
920 | switch (param->flags & IW_AUTH_INDEX) { | 920 | switch (param->flags & IW_AUTH_INDEX) { |
921 | case IW_AUTH_WPA_VERSION: | 921 | case IW_AUTH_WPA_VERSION: |
922 | switch (wl->wpa_level) { | 922 | switch (wl->wpa_level) { |
923 | case GELIC_WL_WPA_LEVEL_WPA: | 923 | case GELIC_WL_WPA_LEVEL_WPA: |
924 | param->value |= IW_AUTH_WPA_VERSION_WPA; | 924 | param->value |= IW_AUTH_WPA_VERSION_WPA; |
925 | break; | 925 | break; |
926 | case GELIC_WL_WPA_LEVEL_WPA2: | 926 | case GELIC_WL_WPA_LEVEL_WPA2: |
927 | param->value |= IW_AUTH_WPA_VERSION_WPA2; | 927 | param->value |= IW_AUTH_WPA_VERSION_WPA2; |
928 | break; | 928 | break; |
929 | default: | 929 | default: |
930 | param->value |= IW_AUTH_WPA_VERSION_DISABLED; | 930 | param->value |= IW_AUTH_WPA_VERSION_DISABLED; |
931 | } | 931 | } |
932 | break; | 932 | break; |
933 | 933 | ||
934 | case IW_AUTH_80211_AUTH_ALG: | 934 | case IW_AUTH_80211_AUTH_ALG: |
935 | if (wl->auth_method == GELIC_EURUS_AUTH_SHARED) | 935 | if (wl->auth_method == GELIC_EURUS_AUTH_SHARED) |
936 | param->value = IW_AUTH_ALG_SHARED_KEY; | 936 | param->value = IW_AUTH_ALG_SHARED_KEY; |
937 | else if (wl->auth_method == GELIC_EURUS_AUTH_OPEN) | 937 | else if (wl->auth_method == GELIC_EURUS_AUTH_OPEN) |
938 | param->value = IW_AUTH_ALG_OPEN_SYSTEM; | 938 | param->value = IW_AUTH_ALG_OPEN_SYSTEM; |
939 | break; | 939 | break; |
940 | 940 | ||
941 | case IW_AUTH_WPA_ENABLED: | 941 | case IW_AUTH_WPA_ENABLED: |
942 | switch (wl->wpa_level) { | 942 | switch (wl->wpa_level) { |
943 | case GELIC_WL_WPA_LEVEL_WPA: | 943 | case GELIC_WL_WPA_LEVEL_WPA: |
944 | case GELIC_WL_WPA_LEVEL_WPA2: | 944 | case GELIC_WL_WPA_LEVEL_WPA2: |
945 | param->value = 1; | 945 | param->value = 1; |
946 | break; | 946 | break; |
947 | default: | 947 | default: |
948 | param->value = 0; | 948 | param->value = 0; |
949 | break; | 949 | break; |
950 | } | 950 | } |
951 | break; | 951 | break; |
952 | default: | 952 | default: |
953 | ret = -EOPNOTSUPP; | 953 | ret = -EOPNOTSUPP; |
954 | } | 954 | } |
955 | 955 | ||
956 | spin_unlock_irqrestore(&wl->lock, irqflag); | 956 | spin_unlock_irqrestore(&wl->lock, irqflag); |
957 | pr_debug("%s: -> %d\n", __func__, ret); | 957 | pr_debug("%s: -> %d\n", __func__, ret); |
958 | return ret; | 958 | return ret; |
959 | } | 959 | } |
960 | 960 | ||
961 | /* SIOC{S,G}IWESSID */ | 961 | /* SIOC{S,G}IWESSID */ |
962 | static int gelic_wl_set_essid(struct net_device *netdev, | 962 | static int gelic_wl_set_essid(struct net_device *netdev, |
963 | struct iw_request_info *info, | 963 | struct iw_request_info *info, |
964 | union iwreq_data *data, char *extra) | 964 | union iwreq_data *data, char *extra) |
965 | { | 965 | { |
966 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 966 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
967 | unsigned long irqflag; | 967 | unsigned long irqflag; |
968 | 968 | ||
969 | pr_debug("%s: <- l=%d f=%d\n", __func__, | 969 | pr_debug("%s: <- l=%d f=%d\n", __func__, |
970 | data->essid.length, data->essid.flags); | 970 | data->essid.length, data->essid.flags); |
971 | if (IW_ESSID_MAX_SIZE < data->essid.length) | 971 | if (IW_ESSID_MAX_SIZE < data->essid.length) |
972 | return -EINVAL; | 972 | return -EINVAL; |
973 | 973 | ||
974 | spin_lock_irqsave(&wl->lock, irqflag); | 974 | spin_lock_irqsave(&wl->lock, irqflag); |
975 | if (data->essid.flags) { | 975 | if (data->essid.flags) { |
976 | wl->essid_len = data->essid.length; | 976 | wl->essid_len = data->essid.length; |
977 | memcpy(wl->essid, extra, wl->essid_len); | 977 | memcpy(wl->essid, extra, wl->essid_len); |
978 | pr_debug("%s: essid = '%s'\n", __func__, extra); | 978 | pr_debug("%s: essid = '%s'\n", __func__, extra); |
979 | set_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat); | 979 | set_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat); |
980 | } else { | 980 | } else { |
981 | pr_debug("%s: ESSID any\n", __func__); | 981 | pr_debug("%s: ESSID any\n", __func__); |
982 | clear_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat); | 982 | clear_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat); |
983 | } | 983 | } |
984 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); | 984 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); |
985 | spin_unlock_irqrestore(&wl->lock, irqflag); | 985 | spin_unlock_irqrestore(&wl->lock, irqflag); |
986 | 986 | ||
987 | 987 | ||
988 | gelic_wl_try_associate(netdev); /* FIXME */ | 988 | gelic_wl_try_associate(netdev); /* FIXME */ |
989 | pr_debug("%s: ->\n", __func__); | 989 | pr_debug("%s: ->\n", __func__); |
990 | return 0; | 990 | return 0; |
991 | } | 991 | } |
992 | 992 | ||
993 | static int gelic_wl_get_essid(struct net_device *netdev, | 993 | static int gelic_wl_get_essid(struct net_device *netdev, |
994 | struct iw_request_info *info, | 994 | struct iw_request_info *info, |
995 | union iwreq_data *data, char *extra) | 995 | union iwreq_data *data, char *extra) |
996 | { | 996 | { |
997 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 997 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
998 | unsigned long irqflag; | 998 | unsigned long irqflag; |
999 | 999 | ||
1000 | pr_debug("%s: <-\n", __func__); | 1000 | pr_debug("%s: <-\n", __func__); |
1001 | mutex_lock(&wl->assoc_stat_lock); | 1001 | mutex_lock(&wl->assoc_stat_lock); |
1002 | spin_lock_irqsave(&wl->lock, irqflag); | 1002 | spin_lock_irqsave(&wl->lock, irqflag); |
1003 | if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat) || | 1003 | if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat) || |
1004 | wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) { | 1004 | wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) { |
1005 | memcpy(extra, wl->essid, wl->essid_len); | 1005 | memcpy(extra, wl->essid, wl->essid_len); |
1006 | data->essid.length = wl->essid_len; | 1006 | data->essid.length = wl->essid_len; |
1007 | data->essid.flags = 1; | 1007 | data->essid.flags = 1; |
1008 | } else | 1008 | } else |
1009 | data->essid.flags = 0; | 1009 | data->essid.flags = 0; |
1010 | 1010 | ||
1011 | mutex_unlock(&wl->assoc_stat_lock); | 1011 | mutex_unlock(&wl->assoc_stat_lock); |
1012 | spin_unlock_irqrestore(&wl->lock, irqflag); | 1012 | spin_unlock_irqrestore(&wl->lock, irqflag); |
1013 | pr_debug("%s: -> len=%d\n", __func__, data->essid.length); | 1013 | pr_debug("%s: -> len=%d\n", __func__, data->essid.length); |
1014 | 1014 | ||
1015 | return 0; | 1015 | return 0; |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | /* SIO{S,G}IWENCODE */ | 1018 | /* SIO{S,G}IWENCODE */ |
1019 | static int gelic_wl_set_encode(struct net_device *netdev, | 1019 | static int gelic_wl_set_encode(struct net_device *netdev, |
1020 | struct iw_request_info *info, | 1020 | struct iw_request_info *info, |
1021 | union iwreq_data *data, char *extra) | 1021 | union iwreq_data *data, char *extra) |
1022 | { | 1022 | { |
1023 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 1023 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
1024 | struct iw_point *enc = &data->encoding; | 1024 | struct iw_point *enc = &data->encoding; |
1025 | __u16 flags; | 1025 | __u16 flags; |
1026 | unsigned long irqflag; | 1026 | unsigned long irqflag; |
1027 | int key_index, index_specified; | 1027 | int key_index, index_specified; |
1028 | int ret = 0; | 1028 | int ret = 0; |
1029 | 1029 | ||
1030 | pr_debug("%s: <-\n", __func__); | 1030 | pr_debug("%s: <-\n", __func__); |
1031 | flags = enc->flags & IW_ENCODE_FLAGS; | 1031 | flags = enc->flags & IW_ENCODE_FLAGS; |
1032 | key_index = enc->flags & IW_ENCODE_INDEX; | 1032 | key_index = enc->flags & IW_ENCODE_INDEX; |
1033 | 1033 | ||
1034 | pr_debug("%s: key_index = %d\n", __func__, key_index); | 1034 | pr_debug("%s: key_index = %d\n", __func__, key_index); |
1035 | pr_debug("%s: key_len = %d\n", __func__, enc->length); | 1035 | pr_debug("%s: key_len = %d\n", __func__, enc->length); |
1036 | pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); | 1036 | pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); |
1037 | 1037 | ||
1038 | if (GELIC_WEP_KEYS < key_index) | 1038 | if (GELIC_WEP_KEYS < key_index) |
1039 | return -EINVAL; | 1039 | return -EINVAL; |
1040 | 1040 | ||
1041 | spin_lock_irqsave(&wl->lock, irqflag); | 1041 | spin_lock_irqsave(&wl->lock, irqflag); |
1042 | if (key_index) { | 1042 | if (key_index) { |
1043 | index_specified = 1; | 1043 | index_specified = 1; |
1044 | key_index--; | 1044 | key_index--; |
1045 | } else { | 1045 | } else { |
1046 | index_specified = 0; | 1046 | index_specified = 0; |
1047 | key_index = wl->current_key; | 1047 | key_index = wl->current_key; |
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | if (flags & IW_ENCODE_NOKEY) { | 1050 | if (flags & IW_ENCODE_NOKEY) { |
1051 | /* if just IW_ENCODE_NOKEY, change current key index */ | 1051 | /* if just IW_ENCODE_NOKEY, change current key index */ |
1052 | if (!flags && index_specified) { | 1052 | if (!flags && index_specified) { |
1053 | wl->current_key = key_index; | 1053 | wl->current_key = key_index; |
1054 | goto done; | 1054 | goto done; |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | if (flags & IW_ENCODE_DISABLED) { | 1057 | if (flags & IW_ENCODE_DISABLED) { |
1058 | if (!index_specified) { | 1058 | if (!index_specified) { |
1059 | /* disable encryption */ | 1059 | /* disable encryption */ |
1060 | wl->group_cipher_method = GELIC_WL_CIPHER_NONE; | 1060 | wl->group_cipher_method = GELIC_WL_CIPHER_NONE; |
1061 | wl->pairwise_cipher_method = | 1061 | wl->pairwise_cipher_method = |
1062 | GELIC_WL_CIPHER_NONE; | 1062 | GELIC_WL_CIPHER_NONE; |
1063 | /* invalidate all key */ | 1063 | /* invalidate all key */ |
1064 | wl->key_enabled = 0; | 1064 | wl->key_enabled = 0; |
1065 | } else | 1065 | } else |
1066 | clear_bit(key_index, &wl->key_enabled); | 1066 | clear_bit(key_index, &wl->key_enabled); |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | if (flags & IW_ENCODE_OPEN) | 1069 | if (flags & IW_ENCODE_OPEN) |
1070 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; | 1070 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; |
1071 | if (flags & IW_ENCODE_RESTRICTED) { | 1071 | if (flags & IW_ENCODE_RESTRICTED) { |
1072 | pr_info("%s: shared key mode enabled\n", __func__); | 1072 | pr_info("%s: shared key mode enabled\n", __func__); |
1073 | wl->auth_method = GELIC_EURUS_AUTH_SHARED; | 1073 | wl->auth_method = GELIC_EURUS_AUTH_SHARED; |
1074 | } | 1074 | } |
1075 | } else { | 1075 | } else { |
1076 | if (IW_ENCODING_TOKEN_MAX < enc->length) { | 1076 | if (IW_ENCODING_TOKEN_MAX < enc->length) { |
1077 | ret = -EINVAL; | 1077 | ret = -EINVAL; |
1078 | goto done; | 1078 | goto done; |
1079 | } | 1079 | } |
1080 | wl->key_len[key_index] = enc->length; | 1080 | wl->key_len[key_index] = enc->length; |
1081 | memcpy(wl->key[key_index], extra, enc->length); | 1081 | memcpy(wl->key[key_index], extra, enc->length); |
1082 | set_bit(key_index, &wl->key_enabled); | 1082 | set_bit(key_index, &wl->key_enabled); |
1083 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; | 1083 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; |
1084 | wl->group_cipher_method = GELIC_WL_CIPHER_WEP; | 1084 | wl->group_cipher_method = GELIC_WL_CIPHER_WEP; |
1085 | } | 1085 | } |
1086 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); | 1086 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); |
1087 | done: | 1087 | done: |
1088 | spin_unlock_irqrestore(&wl->lock, irqflag); | 1088 | spin_unlock_irqrestore(&wl->lock, irqflag); |
1089 | pr_debug("%s: ->\n", __func__); | 1089 | pr_debug("%s: ->\n", __func__); |
1090 | return ret; | 1090 | return ret; |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | static int gelic_wl_get_encode(struct net_device *netdev, | 1093 | static int gelic_wl_get_encode(struct net_device *netdev, |
1094 | struct iw_request_info *info, | 1094 | struct iw_request_info *info, |
1095 | union iwreq_data *data, char *extra) | 1095 | union iwreq_data *data, char *extra) |
1096 | { | 1096 | { |
1097 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 1097 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
1098 | struct iw_point *enc = &data->encoding; | 1098 | struct iw_point *enc = &data->encoding; |
1099 | unsigned long irqflag; | 1099 | unsigned long irqflag; |
1100 | unsigned int key_index, index_specified; | 1100 | unsigned int key_index, index_specified; |
1101 | int ret = 0; | 1101 | int ret = 0; |
1102 | 1102 | ||
1103 | pr_debug("%s: <-\n", __func__); | 1103 | pr_debug("%s: <-\n", __func__); |
1104 | key_index = enc->flags & IW_ENCODE_INDEX; | 1104 | key_index = enc->flags & IW_ENCODE_INDEX; |
1105 | pr_debug("%s: flag=%#x point=%p len=%d extra=%p\n", __func__, | 1105 | pr_debug("%s: flag=%#x point=%p len=%d extra=%p\n", __func__, |
1106 | enc->flags, enc->pointer, enc->length, extra); | 1106 | enc->flags, enc->pointer, enc->length, extra); |
1107 | if (GELIC_WEP_KEYS < key_index) | 1107 | if (GELIC_WEP_KEYS < key_index) |
1108 | return -EINVAL; | 1108 | return -EINVAL; |
1109 | 1109 | ||
1110 | spin_lock_irqsave(&wl->lock, irqflag); | 1110 | spin_lock_irqsave(&wl->lock, irqflag); |
1111 | if (key_index) { | 1111 | if (key_index) { |
1112 | index_specified = 1; | 1112 | index_specified = 1; |
1113 | key_index--; | 1113 | key_index--; |
1114 | } else { | 1114 | } else { |
1115 | index_specified = 0; | 1115 | index_specified = 0; |
1116 | key_index = wl->current_key; | 1116 | key_index = wl->current_key; |
1117 | } | 1117 | } |
1118 | 1118 | ||
1119 | if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { | 1119 | if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { |
1120 | switch (wl->auth_method) { | 1120 | switch (wl->auth_method) { |
1121 | case GELIC_EURUS_AUTH_OPEN: | 1121 | case GELIC_EURUS_AUTH_OPEN: |
1122 | enc->flags = IW_ENCODE_OPEN; | 1122 | enc->flags = IW_ENCODE_OPEN; |
1123 | break; | 1123 | break; |
1124 | case GELIC_EURUS_AUTH_SHARED: | 1124 | case GELIC_EURUS_AUTH_SHARED: |
1125 | enc->flags = IW_ENCODE_RESTRICTED; | 1125 | enc->flags = IW_ENCODE_RESTRICTED; |
1126 | break; | 1126 | break; |
1127 | } | 1127 | } |
1128 | } else | 1128 | } else |
1129 | enc->flags = IW_ENCODE_DISABLED; | 1129 | enc->flags = IW_ENCODE_DISABLED; |
1130 | 1130 | ||
1131 | if (test_bit(key_index, &wl->key_enabled)) { | 1131 | if (test_bit(key_index, &wl->key_enabled)) { |
1132 | if (enc->length < wl->key_len[key_index]) { | 1132 | if (enc->length < wl->key_len[key_index]) { |
1133 | ret = -EINVAL; | 1133 | ret = -EINVAL; |
1134 | goto done; | 1134 | goto done; |
1135 | } | 1135 | } |
1136 | enc->length = wl->key_len[key_index]; | 1136 | enc->length = wl->key_len[key_index]; |
1137 | memcpy(extra, wl->key[key_index], wl->key_len[key_index]); | 1137 | memcpy(extra, wl->key[key_index], wl->key_len[key_index]); |
1138 | } else { | 1138 | } else { |
1139 | enc->length = 0; | 1139 | enc->length = 0; |
1140 | enc->flags |= IW_ENCODE_NOKEY; | 1140 | enc->flags |= IW_ENCODE_NOKEY; |
1141 | } | 1141 | } |
1142 | enc->flags |= key_index + 1; | 1142 | enc->flags |= key_index + 1; |
1143 | pr_debug("%s: -> flag=%x len=%d\n", __func__, | 1143 | pr_debug("%s: -> flag=%x len=%d\n", __func__, |
1144 | enc->flags, enc->length); | 1144 | enc->flags, enc->length); |
1145 | 1145 | ||
1146 | done: | 1146 | done: |
1147 | spin_unlock_irqrestore(&wl->lock, irqflag); | 1147 | spin_unlock_irqrestore(&wl->lock, irqflag); |
1148 | return ret; | 1148 | return ret; |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | /* SIOC{S,G}IWAP */ | 1151 | /* SIOC{S,G}IWAP */ |
1152 | static int gelic_wl_set_ap(struct net_device *netdev, | 1152 | static int gelic_wl_set_ap(struct net_device *netdev, |
1153 | struct iw_request_info *info, | 1153 | struct iw_request_info *info, |
1154 | union iwreq_data *data, char *extra) | 1154 | union iwreq_data *data, char *extra) |
1155 | { | 1155 | { |
1156 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 1156 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
1157 | unsigned long irqflag; | 1157 | unsigned long irqflag; |
1158 | 1158 | ||
1159 | pr_debug("%s: <-\n", __func__); | 1159 | pr_debug("%s: <-\n", __func__); |
1160 | if (data->ap_addr.sa_family != ARPHRD_ETHER) | 1160 | if (data->ap_addr.sa_family != ARPHRD_ETHER) |
1161 | return -EINVAL; | 1161 | return -EINVAL; |
1162 | 1162 | ||
1163 | spin_lock_irqsave(&wl->lock, irqflag); | 1163 | spin_lock_irqsave(&wl->lock, irqflag); |
1164 | if (is_valid_ether_addr(data->ap_addr.sa_data)) { | 1164 | if (is_valid_ether_addr(data->ap_addr.sa_data)) { |
1165 | memcpy(wl->bssid, data->ap_addr.sa_data, | 1165 | memcpy(wl->bssid, data->ap_addr.sa_data, |
1166 | ETH_ALEN); | 1166 | ETH_ALEN); |
1167 | set_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat); | 1167 | set_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat); |
1168 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); | 1168 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); |
1169 | pr_debug("%s: bss=%pM\n", __func__, wl->bssid); | 1169 | pr_debug("%s: bss=%pM\n", __func__, wl->bssid); |
1170 | } else { | 1170 | } else { |
1171 | pr_debug("%s: clear bssid\n", __func__); | 1171 | pr_debug("%s: clear bssid\n", __func__); |
1172 | clear_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat); | 1172 | clear_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat); |
1173 | memset(wl->bssid, 0, ETH_ALEN); | 1173 | memset(wl->bssid, 0, ETH_ALEN); |
1174 | } | 1174 | } |
1175 | spin_unlock_irqrestore(&wl->lock, irqflag); | 1175 | spin_unlock_irqrestore(&wl->lock, irqflag); |
1176 | pr_debug("%s: ->\n", __func__); | 1176 | pr_debug("%s: ->\n", __func__); |
1177 | return 0; | 1177 | return 0; |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | static int gelic_wl_get_ap(struct net_device *netdev, | 1180 | static int gelic_wl_get_ap(struct net_device *netdev, |
1181 | struct iw_request_info *info, | 1181 | struct iw_request_info *info, |
1182 | union iwreq_data *data, char *extra) | 1182 | union iwreq_data *data, char *extra) |
1183 | { | 1183 | { |
1184 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 1184 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
1185 | unsigned long irqflag; | 1185 | unsigned long irqflag; |
1186 | 1186 | ||
1187 | pr_debug("%s: <-\n", __func__); | 1187 | pr_debug("%s: <-\n", __func__); |
1188 | mutex_lock(&wl->assoc_stat_lock); | 1188 | mutex_lock(&wl->assoc_stat_lock); |
1189 | spin_lock_irqsave(&wl->lock, irqflag); | 1189 | spin_lock_irqsave(&wl->lock, irqflag); |
1190 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) { | 1190 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) { |
1191 | data->ap_addr.sa_family = ARPHRD_ETHER; | 1191 | data->ap_addr.sa_family = ARPHRD_ETHER; |
1192 | memcpy(data->ap_addr.sa_data, wl->active_bssid, | 1192 | memcpy(data->ap_addr.sa_data, wl->active_bssid, |
1193 | ETH_ALEN); | 1193 | ETH_ALEN); |
1194 | } else | 1194 | } else |
1195 | memset(data->ap_addr.sa_data, 0, ETH_ALEN); | 1195 | memset(data->ap_addr.sa_data, 0, ETH_ALEN); |
1196 | 1196 | ||
1197 | spin_unlock_irqrestore(&wl->lock, irqflag); | 1197 | spin_unlock_irqrestore(&wl->lock, irqflag); |
1198 | mutex_unlock(&wl->assoc_stat_lock); | 1198 | mutex_unlock(&wl->assoc_stat_lock); |
1199 | pr_debug("%s: ->\n", __func__); | 1199 | pr_debug("%s: ->\n", __func__); |
1200 | return 0; | 1200 | return 0; |
1201 | } | 1201 | } |
1202 | 1202 | ||
1203 | /* SIOC{S,G}IWENCODEEXT */ | 1203 | /* SIOC{S,G}IWENCODEEXT */ |
1204 | static int gelic_wl_set_encodeext(struct net_device *netdev, | 1204 | static int gelic_wl_set_encodeext(struct net_device *netdev, |
1205 | struct iw_request_info *info, | 1205 | struct iw_request_info *info, |
1206 | union iwreq_data *data, char *extra) | 1206 | union iwreq_data *data, char *extra) |
1207 | { | 1207 | { |
1208 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 1208 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
1209 | struct iw_point *enc = &data->encoding; | 1209 | struct iw_point *enc = &data->encoding; |
1210 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 1210 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
1211 | __u16 alg; | 1211 | __u16 alg; |
1212 | __u16 flags; | 1212 | __u16 flags; |
1213 | unsigned long irqflag; | 1213 | unsigned long irqflag; |
1214 | int key_index; | 1214 | int key_index; |
1215 | int ret = 0; | 1215 | int ret = 0; |
1216 | 1216 | ||
1217 | pr_debug("%s: <-\n", __func__); | 1217 | pr_debug("%s: <-\n", __func__); |
1218 | flags = enc->flags & IW_ENCODE_FLAGS; | 1218 | flags = enc->flags & IW_ENCODE_FLAGS; |
1219 | alg = ext->alg; | 1219 | alg = ext->alg; |
1220 | key_index = enc->flags & IW_ENCODE_INDEX; | 1220 | key_index = enc->flags & IW_ENCODE_INDEX; |
1221 | 1221 | ||
1222 | pr_debug("%s: key_index = %d\n", __func__, key_index); | 1222 | pr_debug("%s: key_index = %d\n", __func__, key_index); |
1223 | pr_debug("%s: key_len = %d\n", __func__, enc->length); | 1223 | pr_debug("%s: key_len = %d\n", __func__, enc->length); |
1224 | pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); | 1224 | pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); |
1225 | pr_debug("%s: ext_flag=%x\n", __func__, ext->ext_flags); | 1225 | pr_debug("%s: ext_flag=%x\n", __func__, ext->ext_flags); |
1226 | pr_debug("%s: ext_key_len=%x\n", __func__, ext->key_len); | 1226 | pr_debug("%s: ext_key_len=%x\n", __func__, ext->key_len); |
1227 | 1227 | ||
1228 | if (GELIC_WEP_KEYS < key_index) | 1228 | if (GELIC_WEP_KEYS < key_index) |
1229 | return -EINVAL; | 1229 | return -EINVAL; |
1230 | 1230 | ||
1231 | spin_lock_irqsave(&wl->lock, irqflag); | 1231 | spin_lock_irqsave(&wl->lock, irqflag); |
1232 | if (key_index) | 1232 | if (key_index) |
1233 | key_index--; | 1233 | key_index--; |
1234 | else | 1234 | else |
1235 | key_index = wl->current_key; | 1235 | key_index = wl->current_key; |
1236 | 1236 | ||
1237 | if (!enc->length && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { | 1237 | if (!enc->length && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { |
1238 | /* reques to change default key index */ | 1238 | /* reques to change default key index */ |
1239 | pr_debug("%s: request to change default key to %d\n", | 1239 | pr_debug("%s: request to change default key to %d\n", |
1240 | __func__, key_index); | 1240 | __func__, key_index); |
1241 | wl->current_key = key_index; | 1241 | wl->current_key = key_index; |
1242 | goto done; | 1242 | goto done; |
1243 | } | 1243 | } |
1244 | 1244 | ||
1245 | if (alg == IW_ENCODE_ALG_NONE || (flags & IW_ENCODE_DISABLED)) { | 1245 | if (alg == IW_ENCODE_ALG_NONE || (flags & IW_ENCODE_DISABLED)) { |
1246 | pr_debug("%s: alg disabled\n", __func__); | 1246 | pr_debug("%s: alg disabled\n", __func__); |
1247 | wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; | 1247 | wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; |
1248 | wl->group_cipher_method = GELIC_WL_CIPHER_NONE; | 1248 | wl->group_cipher_method = GELIC_WL_CIPHER_NONE; |
1249 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; | 1249 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; |
1250 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; /* should be open */ | 1250 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; /* should be open */ |
1251 | } else if (alg == IW_ENCODE_ALG_WEP) { | 1251 | } else if (alg == IW_ENCODE_ALG_WEP) { |
1252 | pr_debug("%s: WEP requested\n", __func__); | 1252 | pr_debug("%s: WEP requested\n", __func__); |
1253 | if (flags & IW_ENCODE_OPEN) { | 1253 | if (flags & IW_ENCODE_OPEN) { |
1254 | pr_debug("%s: open key mode\n", __func__); | 1254 | pr_debug("%s: open key mode\n", __func__); |
1255 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; | 1255 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; |
1256 | } | 1256 | } |
1257 | if (flags & IW_ENCODE_RESTRICTED) { | 1257 | if (flags & IW_ENCODE_RESTRICTED) { |
1258 | pr_debug("%s: shared key mode\n", __func__); | 1258 | pr_debug("%s: shared key mode\n", __func__); |
1259 | wl->auth_method = GELIC_EURUS_AUTH_SHARED; | 1259 | wl->auth_method = GELIC_EURUS_AUTH_SHARED; |
1260 | } | 1260 | } |
1261 | if (IW_ENCODING_TOKEN_MAX < ext->key_len) { | 1261 | if (IW_ENCODING_TOKEN_MAX < ext->key_len) { |
1262 | pr_info("%s: key is too long %d\n", __func__, | 1262 | pr_info("%s: key is too long %d\n", __func__, |
1263 | ext->key_len); | 1263 | ext->key_len); |
1264 | ret = -EINVAL; | 1264 | ret = -EINVAL; |
1265 | goto done; | 1265 | goto done; |
1266 | } | 1266 | } |
1267 | /* OK, update the key */ | 1267 | /* OK, update the key */ |
1268 | wl->key_len[key_index] = ext->key_len; | 1268 | wl->key_len[key_index] = ext->key_len; |
1269 | memset(wl->key[key_index], 0, IW_ENCODING_TOKEN_MAX); | 1269 | memset(wl->key[key_index], 0, IW_ENCODING_TOKEN_MAX); |
1270 | memcpy(wl->key[key_index], ext->key, ext->key_len); | 1270 | memcpy(wl->key[key_index], ext->key, ext->key_len); |
1271 | set_bit(key_index, &wl->key_enabled); | 1271 | set_bit(key_index, &wl->key_enabled); |
1272 | /* remember wep info changed */ | 1272 | /* remember wep info changed */ |
1273 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); | 1273 | set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); |
1274 | } else if (alg == IW_ENCODE_ALG_PMK) { | 1274 | } else if (alg == IW_ENCODE_ALG_PMK) { |
1275 | if (ext->key_len != WPA_PSK_LEN) { | 1275 | if (ext->key_len != WPA_PSK_LEN) { |
1276 | pr_err("%s: PSK length wrong %d\n", __func__, | 1276 | pr_err("%s: PSK length wrong %d\n", __func__, |
1277 | ext->key_len); | 1277 | ext->key_len); |
1278 | ret = -EINVAL; | 1278 | ret = -EINVAL; |
1279 | goto done; | 1279 | goto done; |
1280 | } | 1280 | } |
1281 | memset(wl->psk, 0, sizeof(wl->psk)); | 1281 | memset(wl->psk, 0, sizeof(wl->psk)); |
1282 | memcpy(wl->psk, ext->key, ext->key_len); | 1282 | memcpy(wl->psk, ext->key, ext->key_len); |
1283 | wl->psk_len = ext->key_len; | 1283 | wl->psk_len = ext->key_len; |
1284 | wl->psk_type = GELIC_EURUS_WPA_PSK_BIN; | 1284 | wl->psk_type = GELIC_EURUS_WPA_PSK_BIN; |
1285 | /* remember PSK configured */ | 1285 | /* remember PSK configured */ |
1286 | set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat); | 1286 | set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat); |
1287 | } | 1287 | } |
1288 | done: | 1288 | done: |
1289 | spin_unlock_irqrestore(&wl->lock, irqflag); | 1289 | spin_unlock_irqrestore(&wl->lock, irqflag); |
1290 | pr_debug("%s: ->\n", __func__); | 1290 | pr_debug("%s: ->\n", __func__); |
1291 | return ret; | 1291 | return ret; |
1292 | } | 1292 | } |
1293 | 1293 | ||
1294 | static int gelic_wl_get_encodeext(struct net_device *netdev, | 1294 | static int gelic_wl_get_encodeext(struct net_device *netdev, |
1295 | struct iw_request_info *info, | 1295 | struct iw_request_info *info, |
1296 | union iwreq_data *data, char *extra) | 1296 | union iwreq_data *data, char *extra) |
1297 | { | 1297 | { |
1298 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 1298 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
1299 | struct iw_point *enc = &data->encoding; | 1299 | struct iw_point *enc = &data->encoding; |
1300 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 1300 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
1301 | unsigned long irqflag; | 1301 | unsigned long irqflag; |
1302 | int key_index; | 1302 | int key_index; |
1303 | int ret = 0; | 1303 | int ret = 0; |
1304 | int max_key_len; | 1304 | int max_key_len; |
1305 | 1305 | ||
1306 | pr_debug("%s: <-\n", __func__); | 1306 | pr_debug("%s: <-\n", __func__); |
1307 | 1307 | ||
1308 | max_key_len = enc->length - sizeof(struct iw_encode_ext); | 1308 | max_key_len = enc->length - sizeof(struct iw_encode_ext); |
1309 | if (max_key_len < 0) | 1309 | if (max_key_len < 0) |
1310 | return -EINVAL; | 1310 | return -EINVAL; |
1311 | key_index = enc->flags & IW_ENCODE_INDEX; | 1311 | key_index = enc->flags & IW_ENCODE_INDEX; |
1312 | 1312 | ||
1313 | pr_debug("%s: key_index = %d\n", __func__, key_index); | 1313 | pr_debug("%s: key_index = %d\n", __func__, key_index); |
1314 | pr_debug("%s: key_len = %d\n", __func__, enc->length); | 1314 | pr_debug("%s: key_len = %d\n", __func__, enc->length); |
1315 | pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); | 1315 | pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); |
1316 | 1316 | ||
1317 | if (GELIC_WEP_KEYS < key_index) | 1317 | if (GELIC_WEP_KEYS < key_index) |
1318 | return -EINVAL; | 1318 | return -EINVAL; |
1319 | 1319 | ||
1320 | spin_lock_irqsave(&wl->lock, irqflag); | 1320 | spin_lock_irqsave(&wl->lock, irqflag); |
1321 | if (key_index) | 1321 | if (key_index) |
1322 | key_index--; | 1322 | key_index--; |
1323 | else | 1323 | else |
1324 | key_index = wl->current_key; | 1324 | key_index = wl->current_key; |
1325 | 1325 | ||
1326 | memset(ext, 0, sizeof(struct iw_encode_ext)); | 1326 | memset(ext, 0, sizeof(struct iw_encode_ext)); |
1327 | switch (wl->group_cipher_method) { | 1327 | switch (wl->group_cipher_method) { |
1328 | case GELIC_WL_CIPHER_WEP: | 1328 | case GELIC_WL_CIPHER_WEP: |
1329 | ext->alg = IW_ENCODE_ALG_WEP; | 1329 | ext->alg = IW_ENCODE_ALG_WEP; |
1330 | enc->flags |= IW_ENCODE_ENABLED; | 1330 | enc->flags |= IW_ENCODE_ENABLED; |
1331 | break; | 1331 | break; |
1332 | case GELIC_WL_CIPHER_TKIP: | 1332 | case GELIC_WL_CIPHER_TKIP: |
1333 | ext->alg = IW_ENCODE_ALG_TKIP; | 1333 | ext->alg = IW_ENCODE_ALG_TKIP; |
1334 | enc->flags |= IW_ENCODE_ENABLED; | 1334 | enc->flags |= IW_ENCODE_ENABLED; |
1335 | break; | 1335 | break; |
1336 | case GELIC_WL_CIPHER_AES: | 1336 | case GELIC_WL_CIPHER_AES: |
1337 | ext->alg = IW_ENCODE_ALG_CCMP; | 1337 | ext->alg = IW_ENCODE_ALG_CCMP; |
1338 | enc->flags |= IW_ENCODE_ENABLED; | 1338 | enc->flags |= IW_ENCODE_ENABLED; |
1339 | break; | 1339 | break; |
1340 | case GELIC_WL_CIPHER_NONE: | 1340 | case GELIC_WL_CIPHER_NONE: |
1341 | default: | 1341 | default: |
1342 | ext->alg = IW_ENCODE_ALG_NONE; | 1342 | ext->alg = IW_ENCODE_ALG_NONE; |
1343 | enc->flags |= IW_ENCODE_NOKEY; | 1343 | enc->flags |= IW_ENCODE_NOKEY; |
1344 | break; | 1344 | break; |
1345 | } | 1345 | } |
1346 | 1346 | ||
1347 | if (!(enc->flags & IW_ENCODE_NOKEY)) { | 1347 | if (!(enc->flags & IW_ENCODE_NOKEY)) { |
1348 | if (max_key_len < wl->key_len[key_index]) { | 1348 | if (max_key_len < wl->key_len[key_index]) { |
1349 | ret = -E2BIG; | 1349 | ret = -E2BIG; |
1350 | goto out; | 1350 | goto out; |
1351 | } | 1351 | } |
1352 | if (test_bit(key_index, &wl->key_enabled)) | 1352 | if (test_bit(key_index, &wl->key_enabled)) |
1353 | memcpy(ext->key, wl->key[key_index], | 1353 | memcpy(ext->key, wl->key[key_index], |
1354 | wl->key_len[key_index]); | 1354 | wl->key_len[key_index]); |
1355 | else | 1355 | else |
1356 | pr_debug("%s: disabled key requested ix=%d\n", | 1356 | pr_debug("%s: disabled key requested ix=%d\n", |
1357 | __func__, key_index); | 1357 | __func__, key_index); |
1358 | } | 1358 | } |
1359 | out: | 1359 | out: |
1360 | spin_unlock_irqrestore(&wl->lock, irqflag); | 1360 | spin_unlock_irqrestore(&wl->lock, irqflag); |
1361 | pr_debug("%s: ->\n", __func__); | 1361 | pr_debug("%s: ->\n", __func__); |
1362 | return ret; | 1362 | return ret; |
1363 | } | 1363 | } |
1364 | /* SIOC{S,G}IWMODE */ | 1364 | /* SIOC{S,G}IWMODE */ |
1365 | static int gelic_wl_set_mode(struct net_device *netdev, | 1365 | static int gelic_wl_set_mode(struct net_device *netdev, |
1366 | struct iw_request_info *info, | 1366 | struct iw_request_info *info, |
1367 | union iwreq_data *data, char *extra) | 1367 | union iwreq_data *data, char *extra) |
1368 | { | 1368 | { |
1369 | __u32 mode = data->mode; | 1369 | __u32 mode = data->mode; |
1370 | int ret; | 1370 | int ret; |
1371 | 1371 | ||
1372 | pr_debug("%s: <-\n", __func__); | 1372 | pr_debug("%s: <-\n", __func__); |
1373 | if (mode == IW_MODE_INFRA) | 1373 | if (mode == IW_MODE_INFRA) |
1374 | ret = 0; | 1374 | ret = 0; |
1375 | else | 1375 | else |
1376 | ret = -EOPNOTSUPP; | 1376 | ret = -EOPNOTSUPP; |
1377 | pr_debug("%s: -> %d\n", __func__, ret); | 1377 | pr_debug("%s: -> %d\n", __func__, ret); |
1378 | return ret; | 1378 | return ret; |
1379 | } | 1379 | } |
1380 | 1380 | ||
1381 | static int gelic_wl_get_mode(struct net_device *netdev, | 1381 | static int gelic_wl_get_mode(struct net_device *netdev, |
1382 | struct iw_request_info *info, | 1382 | struct iw_request_info *info, |
1383 | union iwreq_data *data, char *extra) | 1383 | union iwreq_data *data, char *extra) |
1384 | { | 1384 | { |
1385 | __u32 *mode = &data->mode; | 1385 | __u32 *mode = &data->mode; |
1386 | pr_debug("%s: <-\n", __func__); | 1386 | pr_debug("%s: <-\n", __func__); |
1387 | *mode = IW_MODE_INFRA; | 1387 | *mode = IW_MODE_INFRA; |
1388 | pr_debug("%s: ->\n", __func__); | 1388 | pr_debug("%s: ->\n", __func__); |
1389 | return 0; | 1389 | return 0; |
1390 | } | 1390 | } |
1391 | 1391 | ||
1392 | /* SIOCGIWNICKN */ | 1392 | /* SIOCGIWNICKN */ |
1393 | static int gelic_wl_get_nick(struct net_device *net_dev, | 1393 | static int gelic_wl_get_nick(struct net_device *net_dev, |
1394 | struct iw_request_info *info, | 1394 | struct iw_request_info *info, |
1395 | union iwreq_data *data, char *extra) | 1395 | union iwreq_data *data, char *extra) |
1396 | { | 1396 | { |
1397 | strcpy(extra, "gelic_wl"); | 1397 | strcpy(extra, "gelic_wl"); |
1398 | data->data.length = strlen(extra); | 1398 | data->data.length = strlen(extra); |
1399 | data->data.flags = 1; | 1399 | data->data.flags = 1; |
1400 | return 0; | 1400 | return 0; |
1401 | } | 1401 | } |
1402 | 1402 | ||
1403 | 1403 | ||
1404 | /* --- */ | 1404 | /* --- */ |
1405 | 1405 | ||
1406 | static struct iw_statistics *gelic_wl_get_wireless_stats( | 1406 | static struct iw_statistics *gelic_wl_get_wireless_stats( |
1407 | struct net_device *netdev) | 1407 | struct net_device *netdev) |
1408 | { | 1408 | { |
1409 | 1409 | ||
1410 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 1410 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
1411 | struct gelic_eurus_cmd *cmd; | 1411 | struct gelic_eurus_cmd *cmd; |
1412 | struct iw_statistics *is; | 1412 | struct iw_statistics *is; |
1413 | struct gelic_eurus_rssi_info *rssi; | 1413 | struct gelic_eurus_rssi_info *rssi; |
1414 | void *buf; | 1414 | void *buf; |
1415 | 1415 | ||
1416 | pr_debug("%s: <-\n", __func__); | 1416 | pr_debug("%s: <-\n", __func__); |
1417 | 1417 | ||
1418 | buf = (void *)__get_free_page(GFP_KERNEL); | 1418 | buf = (void *)__get_free_page(GFP_KERNEL); |
1419 | if (!buf) | 1419 | if (!buf) |
1420 | return NULL; | 1420 | return NULL; |
1421 | 1421 | ||
1422 | is = &wl->iwstat; | 1422 | is = &wl->iwstat; |
1423 | memset(is, 0, sizeof(*is)); | 1423 | memset(is, 0, sizeof(*is)); |
1424 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_RSSI_CFG, | 1424 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_RSSI_CFG, |
1425 | buf, sizeof(*rssi)); | 1425 | buf, sizeof(*rssi)); |
1426 | if (cmd && !cmd->status && !cmd->cmd_status) { | 1426 | if (cmd && !cmd->status && !cmd->cmd_status) { |
1427 | rssi = buf; | 1427 | rssi = buf; |
1428 | is->qual.level = be16_to_cpu(rssi->rssi); | 1428 | is->qual.level = be16_to_cpu(rssi->rssi); |
1429 | is->qual.updated = IW_QUAL_LEVEL_UPDATED | | 1429 | is->qual.updated = IW_QUAL_LEVEL_UPDATED | |
1430 | IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID; | 1430 | IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID; |
1431 | } else | 1431 | } else |
1432 | /* not associated */ | 1432 | /* not associated */ |
1433 | is->qual.updated = IW_QUAL_ALL_INVALID; | 1433 | is->qual.updated = IW_QUAL_ALL_INVALID; |
1434 | 1434 | ||
1435 | kfree(cmd); | 1435 | kfree(cmd); |
1436 | free_page((unsigned long)buf); | 1436 | free_page((unsigned long)buf); |
1437 | pr_debug("%s: ->\n", __func__); | 1437 | pr_debug("%s: ->\n", __func__); |
1438 | return is; | 1438 | return is; |
1439 | } | 1439 | } |
1440 | 1440 | ||
1441 | /* | 1441 | /* |
1442 | * scanning helpers | 1442 | * scanning helpers |
1443 | */ | 1443 | */ |
1444 | static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, | 1444 | static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, |
1445 | u8 *essid, size_t essid_len) | 1445 | u8 *essid, size_t essid_len) |
1446 | { | 1446 | { |
1447 | struct gelic_eurus_cmd *cmd; | 1447 | struct gelic_eurus_cmd *cmd; |
1448 | int ret = 0; | 1448 | int ret = 0; |
1449 | void *buf = NULL; | 1449 | void *buf = NULL; |
1450 | size_t len; | 1450 | size_t len; |
1451 | 1451 | ||
1452 | pr_debug("%s: <- always=%d\n", __func__, always_scan); | 1452 | pr_debug("%s: <- always=%d\n", __func__, always_scan); |
1453 | if (mutex_lock_interruptible(&wl->scan_lock)) | 1453 | if (mutex_lock_interruptible(&wl->scan_lock)) |
1454 | return -ERESTARTSYS; | 1454 | return -ERESTARTSYS; |
1455 | 1455 | ||
1456 | /* | 1456 | /* |
1457 | * If already a scan in progress, do not trigger more | 1457 | * If already a scan in progress, do not trigger more |
1458 | */ | 1458 | */ |
1459 | if (wl->scan_stat == GELIC_WL_SCAN_STAT_SCANNING) { | 1459 | if (wl->scan_stat == GELIC_WL_SCAN_STAT_SCANNING) { |
1460 | pr_debug("%s: scanning now\n", __func__); | 1460 | pr_debug("%s: scanning now\n", __func__); |
1461 | goto out; | 1461 | goto out; |
1462 | } | 1462 | } |
1463 | 1463 | ||
1464 | init_completion(&wl->scan_done); | 1464 | init_completion(&wl->scan_done); |
1465 | /* | 1465 | /* |
1466 | * If we have already a bss list, don't try to get new | 1466 | * If we have already a bss list, don't try to get new |
1467 | * unless we are doing an ESSID scan | 1467 | * unless we are doing an ESSID scan |
1468 | */ | 1468 | */ |
1469 | if ((!essid_len && !always_scan) | 1469 | if ((!essid_len && !always_scan) |
1470 | && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) { | 1470 | && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) { |
1471 | pr_debug("%s: already has the list\n", __func__); | 1471 | pr_debug("%s: already has the list\n", __func__); |
1472 | complete(&wl->scan_done); | 1472 | complete(&wl->scan_done); |
1473 | goto out; | 1473 | goto out; |
1474 | } | 1474 | } |
1475 | 1475 | ||
1476 | /* ESSID scan ? */ | 1476 | /* ESSID scan ? */ |
1477 | if (essid_len && essid) { | 1477 | if (essid_len && essid) { |
1478 | buf = (void *)__get_free_page(GFP_KERNEL); | 1478 | buf = (void *)__get_free_page(GFP_KERNEL); |
1479 | if (!buf) { | 1479 | if (!buf) { |
1480 | ret = -ENOMEM; | 1480 | ret = -ENOMEM; |
1481 | goto out; | 1481 | goto out; |
1482 | } | 1482 | } |
1483 | len = IW_ESSID_MAX_SIZE; /* hypervisor always requires 32 */ | 1483 | len = IW_ESSID_MAX_SIZE; /* hypervisor always requires 32 */ |
1484 | memset(buf, 0, len); | 1484 | memset(buf, 0, len); |
1485 | memcpy(buf, essid, essid_len); | 1485 | memcpy(buf, essid, essid_len); |
1486 | pr_debug("%s: essid scan='%s'\n", __func__, (char *)buf); | 1486 | pr_debug("%s: essid scan='%s'\n", __func__, (char *)buf); |
1487 | } else | 1487 | } else |
1488 | len = 0; | 1488 | len = 0; |
1489 | 1489 | ||
1490 | /* | 1490 | /* |
1491 | * issue start scan request | 1491 | * issue start scan request |
1492 | */ | 1492 | */ |
1493 | wl->scan_stat = GELIC_WL_SCAN_STAT_SCANNING; | 1493 | wl->scan_stat = GELIC_WL_SCAN_STAT_SCANNING; |
1494 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_START_SCAN, | 1494 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_START_SCAN, |
1495 | buf, len); | 1495 | buf, len); |
1496 | if (!cmd || cmd->status || cmd->cmd_status) { | 1496 | if (!cmd || cmd->status || cmd->cmd_status) { |
1497 | wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; | 1497 | wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; |
1498 | complete(&wl->scan_done); | 1498 | complete(&wl->scan_done); |
1499 | ret = -ENOMEM; | 1499 | ret = -ENOMEM; |
1500 | goto out; | 1500 | goto out; |
1501 | } | 1501 | } |
1502 | kfree(cmd); | 1502 | kfree(cmd); |
1503 | out: | 1503 | out: |
1504 | free_page((unsigned long)buf); | 1504 | free_page((unsigned long)buf); |
1505 | mutex_unlock(&wl->scan_lock); | 1505 | mutex_unlock(&wl->scan_lock); |
1506 | pr_debug("%s: ->\n", __func__); | 1506 | pr_debug("%s: ->\n", __func__); |
1507 | return ret; | 1507 | return ret; |
1508 | } | 1508 | } |
1509 | 1509 | ||
1510 | /* | 1510 | /* |
1511 | * retrieve scan result from the chip (hypervisor) | 1511 | * retrieve scan result from the chip (hypervisor) |
1512 | * this function is invoked by schedule work. | 1512 | * this function is invoked by schedule work. |
1513 | */ | 1513 | */ |
1514 | static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl) | 1514 | static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl) |
1515 | { | 1515 | { |
1516 | struct gelic_eurus_cmd *cmd = NULL; | 1516 | struct gelic_eurus_cmd *cmd = NULL; |
1517 | struct gelic_wl_scan_info *target, *tmp; | 1517 | struct gelic_wl_scan_info *target, *tmp; |
1518 | struct gelic_wl_scan_info *oldest = NULL; | 1518 | struct gelic_wl_scan_info *oldest = NULL; |
1519 | struct gelic_eurus_scan_info *scan_info; | 1519 | struct gelic_eurus_scan_info *scan_info; |
1520 | unsigned int scan_info_size; | 1520 | unsigned int scan_info_size; |
1521 | union iwreq_data data; | 1521 | union iwreq_data data; |
1522 | unsigned long this_time = jiffies; | 1522 | unsigned long this_time = jiffies; |
1523 | unsigned int data_len, i, found, r; | 1523 | unsigned int data_len, i, found, r; |
1524 | void *buf; | 1524 | void *buf; |
1525 | 1525 | ||
1526 | pr_debug("%s:start\n", __func__); | 1526 | pr_debug("%s:start\n", __func__); |
1527 | mutex_lock(&wl->scan_lock); | 1527 | mutex_lock(&wl->scan_lock); |
1528 | 1528 | ||
1529 | buf = (void *)__get_free_page(GFP_KERNEL); | 1529 | buf = (void *)__get_free_page(GFP_KERNEL); |
1530 | if (!buf) { | 1530 | if (!buf) { |
1531 | pr_info("%s: scan buffer alloc failed\n", __func__); | 1531 | pr_info("%s: scan buffer alloc failed\n", __func__); |
1532 | goto out; | 1532 | goto out; |
1533 | } | 1533 | } |
1534 | 1534 | ||
1535 | if (wl->scan_stat != GELIC_WL_SCAN_STAT_SCANNING) { | 1535 | if (wl->scan_stat != GELIC_WL_SCAN_STAT_SCANNING) { |
1536 | /* | 1536 | /* |
1537 | * stop() may be called while scanning, ignore result | 1537 | * stop() may be called while scanning, ignore result |
1538 | */ | 1538 | */ |
1539 | pr_debug("%s: scan complete when stat != scanning(%d)\n", | 1539 | pr_debug("%s: scan complete when stat != scanning(%d)\n", |
1540 | __func__, wl->scan_stat); | 1540 | __func__, wl->scan_stat); |
1541 | goto out; | 1541 | goto out; |
1542 | } | 1542 | } |
1543 | 1543 | ||
1544 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_SCAN, | 1544 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_SCAN, |
1545 | buf, PAGE_SIZE); | 1545 | buf, PAGE_SIZE); |
1546 | if (!cmd || cmd->status || cmd->cmd_status) { | 1546 | if (!cmd || cmd->status || cmd->cmd_status) { |
1547 | wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; | 1547 | wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; |
1548 | pr_info("%s:cmd failed\n", __func__); | 1548 | pr_info("%s:cmd failed\n", __func__); |
1549 | kfree(cmd); | 1549 | kfree(cmd); |
1550 | goto out; | 1550 | goto out; |
1551 | } | 1551 | } |
1552 | data_len = cmd->size; | 1552 | data_len = cmd->size; |
1553 | pr_debug("%s: data_len = %d\n", __func__, data_len); | 1553 | pr_debug("%s: data_len = %d\n", __func__, data_len); |
1554 | kfree(cmd); | 1554 | kfree(cmd); |
1555 | 1555 | ||
1556 | /* OK, bss list retrieved */ | 1556 | /* OK, bss list retrieved */ |
1557 | wl->scan_stat = GELIC_WL_SCAN_STAT_GOT_LIST; | 1557 | wl->scan_stat = GELIC_WL_SCAN_STAT_GOT_LIST; |
1558 | 1558 | ||
1559 | /* mark all entries are old */ | 1559 | /* mark all entries are old */ |
1560 | list_for_each_entry_safe(target, tmp, &wl->network_list, list) { | 1560 | list_for_each_entry_safe(target, tmp, &wl->network_list, list) { |
1561 | target->valid = 0; | 1561 | target->valid = 0; |
1562 | /* expire too old entries */ | 1562 | /* expire too old entries */ |
1563 | if (time_before(target->last_scanned + wl->scan_age, | 1563 | if (time_before(target->last_scanned + wl->scan_age, |
1564 | this_time)) { | 1564 | this_time)) { |
1565 | kfree(target->hwinfo); | 1565 | kfree(target->hwinfo); |
1566 | target->hwinfo = NULL; | 1566 | target->hwinfo = NULL; |
1567 | list_move_tail(&target->list, &wl->network_free_list); | 1567 | list_move_tail(&target->list, &wl->network_free_list); |
1568 | } | 1568 | } |
1569 | } | 1569 | } |
1570 | 1570 | ||
1571 | /* put them in the network_list */ | 1571 | /* put them in the network_list */ |
1572 | for (i = 0, scan_info_size = 0, scan_info = buf; | 1572 | for (i = 0, scan_info_size = 0, scan_info = buf; |
1573 | scan_info_size < data_len; | 1573 | scan_info_size < data_len; |
1574 | i++, scan_info_size += be16_to_cpu(scan_info->size), | 1574 | i++, scan_info_size += be16_to_cpu(scan_info->size), |
1575 | scan_info = (void *)scan_info + be16_to_cpu(scan_info->size)) { | 1575 | scan_info = (void *)scan_info + be16_to_cpu(scan_info->size)) { |
1576 | pr_debug("%s:size=%d bssid=%pM scan_info=%p\n", __func__, | 1576 | pr_debug("%s:size=%d bssid=%pM scan_info=%p\n", __func__, |
1577 | be16_to_cpu(scan_info->size), | 1577 | be16_to_cpu(scan_info->size), |
1578 | &scan_info->bssid[2], scan_info); | 1578 | &scan_info->bssid[2], scan_info); |
1579 | 1579 | ||
1580 | /* | 1580 | /* |
1581 | * The wireless firmware may return invalid channel 0 and/or | 1581 | * The wireless firmware may return invalid channel 0 and/or |
1582 | * invalid rate if the AP emits zero length SSID ie. As this | 1582 | * invalid rate if the AP emits zero length SSID ie. As this |
1583 | * scan information is useless, ignore it | 1583 | * scan information is useless, ignore it |
1584 | */ | 1584 | */ |
1585 | if (!be16_to_cpu(scan_info->channel) || !scan_info->rate[0]) { | 1585 | if (!be16_to_cpu(scan_info->channel) || !scan_info->rate[0]) { |
1586 | pr_debug("%s: invalid scan info\n", __func__); | 1586 | pr_debug("%s: invalid scan info\n", __func__); |
1587 | continue; | 1587 | continue; |
1588 | } | 1588 | } |
1589 | 1589 | ||
1590 | found = 0; | 1590 | found = 0; |
1591 | oldest = NULL; | 1591 | oldest = NULL; |
1592 | list_for_each_entry(target, &wl->network_list, list) { | 1592 | list_for_each_entry(target, &wl->network_list, list) { |
1593 | if (!compare_ether_addr(&target->hwinfo->bssid[2], | 1593 | if (!compare_ether_addr(&target->hwinfo->bssid[2], |
1594 | &scan_info->bssid[2])) { | 1594 | &scan_info->bssid[2])) { |
1595 | found = 1; | 1595 | found = 1; |
1596 | pr_debug("%s: same BBS found scanned list\n", | 1596 | pr_debug("%s: same BBS found scanned list\n", |
1597 | __func__); | 1597 | __func__); |
1598 | break; | 1598 | break; |
1599 | } | 1599 | } |
1600 | if (!oldest || | 1600 | if (!oldest || |
1601 | (target->last_scanned < oldest->last_scanned)) | 1601 | (target->last_scanned < oldest->last_scanned)) |
1602 | oldest = target; | 1602 | oldest = target; |
1603 | } | 1603 | } |
1604 | 1604 | ||
1605 | if (!found) { | 1605 | if (!found) { |
1606 | /* not found in the list */ | 1606 | /* not found in the list */ |
1607 | if (list_empty(&wl->network_free_list)) { | 1607 | if (list_empty(&wl->network_free_list)) { |
1608 | /* expire oldest */ | 1608 | /* expire oldest */ |
1609 | target = oldest; | 1609 | target = oldest; |
1610 | } else { | 1610 | } else { |
1611 | target = list_entry(wl->network_free_list.next, | 1611 | target = list_entry(wl->network_free_list.next, |
1612 | struct gelic_wl_scan_info, | 1612 | struct gelic_wl_scan_info, |
1613 | list); | 1613 | list); |
1614 | } | 1614 | } |
1615 | } | 1615 | } |
1616 | 1616 | ||
1617 | /* update the item */ | 1617 | /* update the item */ |
1618 | target->last_scanned = this_time; | 1618 | target->last_scanned = this_time; |
1619 | target->valid = 1; | 1619 | target->valid = 1; |
1620 | target->eurus_index = i; | 1620 | target->eurus_index = i; |
1621 | kfree(target->hwinfo); | 1621 | kfree(target->hwinfo); |
1622 | target->hwinfo = kzalloc(be16_to_cpu(scan_info->size), | 1622 | target->hwinfo = kzalloc(be16_to_cpu(scan_info->size), |
1623 | GFP_KERNEL); | 1623 | GFP_KERNEL); |
1624 | if (!target->hwinfo) { | 1624 | if (!target->hwinfo) { |
1625 | pr_info("%s: kzalloc failed\n", __func__); | 1625 | pr_info("%s: kzalloc failed\n", __func__); |
1626 | continue; | 1626 | continue; |
1627 | } | 1627 | } |
1628 | /* copy hw scan info */ | 1628 | /* copy hw scan info */ |
1629 | memcpy(target->hwinfo, scan_info, scan_info->size); | 1629 | memcpy(target->hwinfo, scan_info, scan_info->size); |
1630 | target->essid_len = strnlen(scan_info->essid, | 1630 | target->essid_len = strnlen(scan_info->essid, |
1631 | sizeof(scan_info->essid)); | 1631 | sizeof(scan_info->essid)); |
1632 | target->rate_len = 0; | 1632 | target->rate_len = 0; |
1633 | for (r = 0; r < 12; r++) | 1633 | for (r = 0; r < 12; r++) |
1634 | if (scan_info->rate[r]) | 1634 | if (scan_info->rate[r]) |
1635 | target->rate_len++; | 1635 | target->rate_len++; |
1636 | if (8 < target->rate_len) | 1636 | if (8 < target->rate_len) |
1637 | pr_info("%s: AP returns %d rates\n", __func__, | 1637 | pr_info("%s: AP returns %d rates\n", __func__, |
1638 | target->rate_len); | 1638 | target->rate_len); |
1639 | target->rate_ext_len = 0; | 1639 | target->rate_ext_len = 0; |
1640 | for (r = 0; r < 16; r++) | 1640 | for (r = 0; r < 16; r++) |
1641 | if (scan_info->ext_rate[r]) | 1641 | if (scan_info->ext_rate[r]) |
1642 | target->rate_ext_len++; | 1642 | target->rate_ext_len++; |
1643 | list_move_tail(&target->list, &wl->network_list); | 1643 | list_move_tail(&target->list, &wl->network_list); |
1644 | } | 1644 | } |
1645 | memset(&data, 0, sizeof(data)); | 1645 | memset(&data, 0, sizeof(data)); |
1646 | wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWSCAN, &data, | 1646 | wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWSCAN, &data, |
1647 | NULL); | 1647 | NULL); |
1648 | out: | 1648 | out: |
1649 | free_page((unsigned long)buf); | 1649 | free_page((unsigned long)buf); |
1650 | complete(&wl->scan_done); | 1650 | complete(&wl->scan_done); |
1651 | mutex_unlock(&wl->scan_lock); | 1651 | mutex_unlock(&wl->scan_lock); |
1652 | pr_debug("%s:end\n", __func__); | 1652 | pr_debug("%s:end\n", __func__); |
1653 | } | 1653 | } |
1654 | 1654 | ||
1655 | /* | 1655 | /* |
1656 | * Select an appropriate bss from current scan list regarding | 1656 | * Select an appropriate bss from current scan list regarding |
1657 | * current settings from userspace. | 1657 | * current settings from userspace. |
1658 | * The caller must hold wl->scan_lock, | 1658 | * The caller must hold wl->scan_lock, |
1659 | * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST | 1659 | * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST |
1660 | */ | 1660 | */ |
1661 | static void update_best(struct gelic_wl_scan_info **best, | 1661 | static void update_best(struct gelic_wl_scan_info **best, |
1662 | struct gelic_wl_scan_info *candid, | 1662 | struct gelic_wl_scan_info *candid, |
1663 | int *best_weight, | 1663 | int *best_weight, |
1664 | int *weight) | 1664 | int *weight) |
1665 | { | 1665 | { |
1666 | if (*best_weight < ++(*weight)) { | 1666 | if (*best_weight < ++(*weight)) { |
1667 | *best_weight = *weight; | 1667 | *best_weight = *weight; |
1668 | *best = candid; | 1668 | *best = candid; |
1669 | } | 1669 | } |
1670 | } | 1670 | } |
1671 | 1671 | ||
1672 | static | 1672 | static |
1673 | struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl) | 1673 | struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl) |
1674 | { | 1674 | { |
1675 | struct gelic_wl_scan_info *scan_info; | 1675 | struct gelic_wl_scan_info *scan_info; |
1676 | struct gelic_wl_scan_info *best_bss; | 1676 | struct gelic_wl_scan_info *best_bss; |
1677 | int weight, best_weight; | 1677 | int weight, best_weight; |
1678 | u16 security; | 1678 | u16 security; |
1679 | 1679 | ||
1680 | pr_debug("%s: <-\n", __func__); | 1680 | pr_debug("%s: <-\n", __func__); |
1681 | 1681 | ||
1682 | best_bss = NULL; | 1682 | best_bss = NULL; |
1683 | best_weight = 0; | 1683 | best_weight = 0; |
1684 | 1684 | ||
1685 | list_for_each_entry(scan_info, &wl->network_list, list) { | 1685 | list_for_each_entry(scan_info, &wl->network_list, list) { |
1686 | pr_debug("%s: station %p\n", __func__, scan_info); | 1686 | pr_debug("%s: station %p\n", __func__, scan_info); |
1687 | 1687 | ||
1688 | if (!scan_info->valid) { | 1688 | if (!scan_info->valid) { |
1689 | pr_debug("%s: station invalid\n", __func__); | 1689 | pr_debug("%s: station invalid\n", __func__); |
1690 | continue; | 1690 | continue; |
1691 | } | 1691 | } |
1692 | 1692 | ||
1693 | /* If bss specified, check it only */ | 1693 | /* If bss specified, check it only */ |
1694 | if (test_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat)) { | 1694 | if (test_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat)) { |
1695 | if (!compare_ether_addr(&scan_info->hwinfo->bssid[2], | 1695 | if (!compare_ether_addr(&scan_info->hwinfo->bssid[2], |
1696 | wl->bssid)) { | 1696 | wl->bssid)) { |
1697 | best_bss = scan_info; | 1697 | best_bss = scan_info; |
1698 | pr_debug("%s: bssid matched\n", __func__); | 1698 | pr_debug("%s: bssid matched\n", __func__); |
1699 | break; | 1699 | break; |
1700 | } else { | 1700 | } else { |
1701 | pr_debug("%s: bssid unmached\n", __func__); | 1701 | pr_debug("%s: bssid unmached\n", __func__); |
1702 | continue; | 1702 | continue; |
1703 | } | 1703 | } |
1704 | } | 1704 | } |
1705 | 1705 | ||
1706 | weight = 0; | 1706 | weight = 0; |
1707 | 1707 | ||
1708 | /* security */ | 1708 | /* security */ |
1709 | security = be16_to_cpu(scan_info->hwinfo->security) & | 1709 | security = be16_to_cpu(scan_info->hwinfo->security) & |
1710 | GELIC_EURUS_SCAN_SEC_MASK; | 1710 | GELIC_EURUS_SCAN_SEC_MASK; |
1711 | if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) { | 1711 | if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) { |
1712 | if (security == GELIC_EURUS_SCAN_SEC_WPA2) | 1712 | if (security == GELIC_EURUS_SCAN_SEC_WPA2) |
1713 | update_best(&best_bss, scan_info, | 1713 | update_best(&best_bss, scan_info, |
1714 | &best_weight, &weight); | 1714 | &best_weight, &weight); |
1715 | else | 1715 | else |
1716 | continue; | 1716 | continue; |
1717 | } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA) { | 1717 | } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA) { |
1718 | if (security == GELIC_EURUS_SCAN_SEC_WPA) | 1718 | if (security == GELIC_EURUS_SCAN_SEC_WPA) |
1719 | update_best(&best_bss, scan_info, | 1719 | update_best(&best_bss, scan_info, |
1720 | &best_weight, &weight); | 1720 | &best_weight, &weight); |
1721 | else | 1721 | else |
1722 | continue; | 1722 | continue; |
1723 | } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_NONE && | 1723 | } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_NONE && |
1724 | wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { | 1724 | wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { |
1725 | if (security == GELIC_EURUS_SCAN_SEC_WEP) | 1725 | if (security == GELIC_EURUS_SCAN_SEC_WEP) |
1726 | update_best(&best_bss, scan_info, | 1726 | update_best(&best_bss, scan_info, |
1727 | &best_weight, &weight); | 1727 | &best_weight, &weight); |
1728 | else | 1728 | else |
1729 | continue; | 1729 | continue; |
1730 | } | 1730 | } |
1731 | 1731 | ||
1732 | /* If ESSID is set, check it */ | 1732 | /* If ESSID is set, check it */ |
1733 | if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) { | 1733 | if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) { |
1734 | if ((scan_info->essid_len == wl->essid_len) && | 1734 | if ((scan_info->essid_len == wl->essid_len) && |
1735 | !strncmp(wl->essid, | 1735 | !strncmp(wl->essid, |
1736 | scan_info->hwinfo->essid, | 1736 | scan_info->hwinfo->essid, |
1737 | scan_info->essid_len)) | 1737 | scan_info->essid_len)) |
1738 | update_best(&best_bss, scan_info, | 1738 | update_best(&best_bss, scan_info, |
1739 | &best_weight, &weight); | 1739 | &best_weight, &weight); |
1740 | else | 1740 | else |
1741 | continue; | 1741 | continue; |
1742 | } | 1742 | } |
1743 | } | 1743 | } |
1744 | 1744 | ||
1745 | #ifdef DEBUG | 1745 | #ifdef DEBUG |
1746 | pr_debug("%s: -> bss=%p\n", __func__, best_bss); | 1746 | pr_debug("%s: -> bss=%p\n", __func__, best_bss); |
1747 | if (best_bss) { | 1747 | if (best_bss) { |
1748 | pr_debug("%s:addr=%pM\n", __func__, | 1748 | pr_debug("%s:addr=%pM\n", __func__, |
1749 | &best_bss->hwinfo->bssid[2]); | 1749 | &best_bss->hwinfo->bssid[2]); |
1750 | } | 1750 | } |
1751 | #endif | 1751 | #endif |
1752 | return best_bss; | 1752 | return best_bss; |
1753 | } | 1753 | } |
1754 | 1754 | ||
1755 | /* | 1755 | /* |
1756 | * Setup WEP configuration to the chip | 1756 | * Setup WEP configuration to the chip |
1757 | * The caller must hold wl->scan_lock, | 1757 | * The caller must hold wl->scan_lock, |
1758 | * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST | 1758 | * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST |
1759 | */ | 1759 | */ |
1760 | static int gelic_wl_do_wep_setup(struct gelic_wl_info *wl) | 1760 | static int gelic_wl_do_wep_setup(struct gelic_wl_info *wl) |
1761 | { | 1761 | { |
1762 | unsigned int i; | 1762 | unsigned int i; |
1763 | struct gelic_eurus_wep_cfg *wep; | 1763 | struct gelic_eurus_wep_cfg *wep; |
1764 | struct gelic_eurus_cmd *cmd; | 1764 | struct gelic_eurus_cmd *cmd; |
1765 | int wep104 = 0; | 1765 | int wep104 = 0; |
1766 | int have_key = 0; | 1766 | int have_key = 0; |
1767 | int ret = 0; | 1767 | int ret = 0; |
1768 | 1768 | ||
1769 | pr_debug("%s: <-\n", __func__); | 1769 | pr_debug("%s: <-\n", __func__); |
1770 | /* we can assume no one should uses the buffer */ | 1770 | /* we can assume no one should uses the buffer */ |
1771 | wep = (struct gelic_eurus_wep_cfg *)__get_free_page(GFP_KERNEL); | 1771 | wep = (struct gelic_eurus_wep_cfg *)__get_free_page(GFP_KERNEL); |
1772 | if (!wep) | 1772 | if (!wep) |
1773 | return -ENOMEM; | 1773 | return -ENOMEM; |
1774 | 1774 | ||
1775 | memset(wep, 0, sizeof(*wep)); | 1775 | memset(wep, 0, sizeof(*wep)); |
1776 | 1776 | ||
1777 | if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { | 1777 | if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { |
1778 | pr_debug("%s: WEP mode\n", __func__); | 1778 | pr_debug("%s: WEP mode\n", __func__); |
1779 | for (i = 0; i < GELIC_WEP_KEYS; i++) { | 1779 | for (i = 0; i < GELIC_WEP_KEYS; i++) { |
1780 | if (!test_bit(i, &wl->key_enabled)) | 1780 | if (!test_bit(i, &wl->key_enabled)) |
1781 | continue; | 1781 | continue; |
1782 | 1782 | ||
1783 | pr_debug("%s: key#%d enabled\n", __func__, i); | 1783 | pr_debug("%s: key#%d enabled\n", __func__, i); |
1784 | have_key = 1; | 1784 | have_key = 1; |
1785 | if (wl->key_len[i] == 13) | 1785 | if (wl->key_len[i] == 13) |
1786 | wep104 = 1; | 1786 | wep104 = 1; |
1787 | else if (wl->key_len[i] != 5) { | 1787 | else if (wl->key_len[i] != 5) { |
1788 | pr_info("%s: wrong wep key[%d]=%d\n", | 1788 | pr_info("%s: wrong wep key[%d]=%d\n", |
1789 | __func__, i, wl->key_len[i]); | 1789 | __func__, i, wl->key_len[i]); |
1790 | ret = -EINVAL; | 1790 | ret = -EINVAL; |
1791 | goto out; | 1791 | goto out; |
1792 | } | 1792 | } |
1793 | memcpy(wep->key[i], wl->key[i], wl->key_len[i]); | 1793 | memcpy(wep->key[i], wl->key[i], wl->key_len[i]); |
1794 | } | 1794 | } |
1795 | 1795 | ||
1796 | if (!have_key) { | 1796 | if (!have_key) { |
1797 | pr_info("%s: all wep key disabled\n", __func__); | 1797 | pr_info("%s: all wep key disabled\n", __func__); |
1798 | ret = -EINVAL; | 1798 | ret = -EINVAL; |
1799 | goto out; | 1799 | goto out; |
1800 | } | 1800 | } |
1801 | 1801 | ||
1802 | if (wep104) { | 1802 | if (wep104) { |
1803 | pr_debug("%s: 104bit key\n", __func__); | 1803 | pr_debug("%s: 104bit key\n", __func__); |
1804 | wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_104BIT); | 1804 | wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_104BIT); |
1805 | } else { | 1805 | } else { |
1806 | pr_debug("%s: 40bit key\n", __func__); | 1806 | pr_debug("%s: 40bit key\n", __func__); |
1807 | wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_40BIT); | 1807 | wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_40BIT); |
1808 | } | 1808 | } |
1809 | } else { | 1809 | } else { |
1810 | pr_debug("%s: NO encryption\n", __func__); | 1810 | pr_debug("%s: NO encryption\n", __func__); |
1811 | wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_NONE); | 1811 | wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_NONE); |
1812 | } | 1812 | } |
1813 | 1813 | ||
1814 | /* issue wep setup */ | 1814 | /* issue wep setup */ |
1815 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WEP_CFG, | 1815 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WEP_CFG, |
1816 | wep, sizeof(*wep)); | 1816 | wep, sizeof(*wep)); |
1817 | if (!cmd) | 1817 | if (!cmd) |
1818 | ret = -ENOMEM; | 1818 | ret = -ENOMEM; |
1819 | else if (cmd->status || cmd->cmd_status) | 1819 | else if (cmd->status || cmd->cmd_status) |
1820 | ret = -ENXIO; | 1820 | ret = -ENXIO; |
1821 | 1821 | ||
1822 | kfree(cmd); | 1822 | kfree(cmd); |
1823 | out: | 1823 | out: |
1824 | free_page((unsigned long)wep); | 1824 | free_page((unsigned long)wep); |
1825 | pr_debug("%s: ->\n", __func__); | 1825 | pr_debug("%s: ->\n", __func__); |
1826 | return ret; | 1826 | return ret; |
1827 | } | 1827 | } |
1828 | 1828 | ||
1829 | #ifdef DEBUG | 1829 | #ifdef DEBUG |
1830 | static const char *wpasecstr(enum gelic_eurus_wpa_security sec) | 1830 | static const char *wpasecstr(enum gelic_eurus_wpa_security sec) |
1831 | { | 1831 | { |
1832 | switch (sec) { | 1832 | switch (sec) { |
1833 | case GELIC_EURUS_WPA_SEC_NONE: | 1833 | case GELIC_EURUS_WPA_SEC_NONE: |
1834 | return "NONE"; | 1834 | return "NONE"; |
1835 | break; | 1835 | break; |
1836 | case GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP: | 1836 | case GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP: |
1837 | return "WPA_TKIP_TKIP"; | 1837 | return "WPA_TKIP_TKIP"; |
1838 | break; | 1838 | break; |
1839 | case GELIC_EURUS_WPA_SEC_WPA_TKIP_AES: | 1839 | case GELIC_EURUS_WPA_SEC_WPA_TKIP_AES: |
1840 | return "WPA_TKIP_AES"; | 1840 | return "WPA_TKIP_AES"; |
1841 | break; | 1841 | break; |
1842 | case GELIC_EURUS_WPA_SEC_WPA_AES_AES: | 1842 | case GELIC_EURUS_WPA_SEC_WPA_AES_AES: |
1843 | return "WPA_AES_AES"; | 1843 | return "WPA_AES_AES"; |
1844 | break; | 1844 | break; |
1845 | case GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP: | 1845 | case GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP: |
1846 | return "WPA2_TKIP_TKIP"; | 1846 | return "WPA2_TKIP_TKIP"; |
1847 | break; | 1847 | break; |
1848 | case GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES: | 1848 | case GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES: |
1849 | return "WPA2_TKIP_AES"; | 1849 | return "WPA2_TKIP_AES"; |
1850 | break; | 1850 | break; |
1851 | case GELIC_EURUS_WPA_SEC_WPA2_AES_AES: | 1851 | case GELIC_EURUS_WPA_SEC_WPA2_AES_AES: |
1852 | return "WPA2_AES_AES"; | 1852 | return "WPA2_AES_AES"; |
1853 | break; | 1853 | break; |
1854 | } | 1854 | } |
1855 | return ""; | 1855 | return ""; |
1856 | }; | 1856 | }; |
1857 | #endif | 1857 | #endif |
1858 | 1858 | ||
1859 | static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl) | 1859 | static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl) |
1860 | { | 1860 | { |
1861 | struct gelic_eurus_wpa_cfg *wpa; | 1861 | struct gelic_eurus_wpa_cfg *wpa; |
1862 | struct gelic_eurus_cmd *cmd; | 1862 | struct gelic_eurus_cmd *cmd; |
1863 | u16 security; | 1863 | u16 security; |
1864 | int ret = 0; | 1864 | int ret = 0; |
1865 | 1865 | ||
1866 | pr_debug("%s: <-\n", __func__); | 1866 | pr_debug("%s: <-\n", __func__); |
1867 | /* we can assume no one should uses the buffer */ | 1867 | /* we can assume no one should uses the buffer */ |
1868 | wpa = (struct gelic_eurus_wpa_cfg *)__get_free_page(GFP_KERNEL); | 1868 | wpa = (struct gelic_eurus_wpa_cfg *)__get_free_page(GFP_KERNEL); |
1869 | if (!wpa) | 1869 | if (!wpa) |
1870 | return -ENOMEM; | 1870 | return -ENOMEM; |
1871 | 1871 | ||
1872 | memset(wpa, 0, sizeof(*wpa)); | 1872 | memset(wpa, 0, sizeof(*wpa)); |
1873 | 1873 | ||
1874 | if (!test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat)) | 1874 | if (!test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat)) |
1875 | pr_info("%s: PSK not configured yet\n", __func__); | 1875 | pr_info("%s: PSK not configured yet\n", __func__); |
1876 | 1876 | ||
1877 | /* copy key */ | 1877 | /* copy key */ |
1878 | memcpy(wpa->psk, wl->psk, wl->psk_len); | 1878 | memcpy(wpa->psk, wl->psk, wl->psk_len); |
1879 | 1879 | ||
1880 | /* set security level */ | 1880 | /* set security level */ |
1881 | if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) { | 1881 | if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) { |
1882 | if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) { | 1882 | if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) { |
1883 | security = GELIC_EURUS_WPA_SEC_WPA2_AES_AES; | 1883 | security = GELIC_EURUS_WPA_SEC_WPA2_AES_AES; |
1884 | } else { | 1884 | } else { |
1885 | if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES && | 1885 | if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES && |
1886 | precise_ie()) | 1886 | precise_ie()) |
1887 | security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES; | 1887 | security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES; |
1888 | else | 1888 | else |
1889 | security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP; | 1889 | security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP; |
1890 | } | 1890 | } |
1891 | } else { | 1891 | } else { |
1892 | if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) { | 1892 | if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) { |
1893 | security = GELIC_EURUS_WPA_SEC_WPA_AES_AES; | 1893 | security = GELIC_EURUS_WPA_SEC_WPA_AES_AES; |
1894 | } else { | 1894 | } else { |
1895 | if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES && | 1895 | if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES && |
1896 | precise_ie()) | 1896 | precise_ie()) |
1897 | security = GELIC_EURUS_WPA_SEC_WPA_TKIP_AES; | 1897 | security = GELIC_EURUS_WPA_SEC_WPA_TKIP_AES; |
1898 | else | 1898 | else |
1899 | security = GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP; | 1899 | security = GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP; |
1900 | } | 1900 | } |
1901 | } | 1901 | } |
1902 | wpa->security = cpu_to_be16(security); | 1902 | wpa->security = cpu_to_be16(security); |
1903 | 1903 | ||
1904 | /* PSK type */ | 1904 | /* PSK type */ |
1905 | wpa->psk_type = cpu_to_be16(wl->psk_type); | 1905 | wpa->psk_type = cpu_to_be16(wl->psk_type); |
1906 | #ifdef DEBUG | 1906 | #ifdef DEBUG |
1907 | pr_debug("%s: sec=%s psktype=%s\n", __func__, | 1907 | pr_debug("%s: sec=%s psktype=%s\n", __func__, |
1908 | wpasecstr(wpa->security), | 1908 | wpasecstr(wpa->security), |
1909 | (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? | 1909 | (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? |
1910 | "BIN" : "passphrase"); | 1910 | "BIN" : "passphrase"); |
1911 | #if 0 | 1911 | #if 0 |
1912 | /* | 1912 | /* |
1913 | * don't enable here if you plan to submit | 1913 | * don't enable here if you plan to submit |
1914 | * the debug log because this dumps your precious | 1914 | * the debug log because this dumps your precious |
1915 | * passphrase/key. | 1915 | * passphrase/key. |
1916 | */ | 1916 | */ |
1917 | pr_debug("%s: psk=%s\n", __func__, | 1917 | pr_debug("%s: psk=%s\n", __func__, |
1918 | (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? | 1918 | (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? |
1919 | "N/A" : wpa->psk); | 1919 | "N/A" : wpa->psk); |
1920 | #endif | 1920 | #endif |
1921 | #endif | 1921 | #endif |
1922 | /* issue wpa setup */ | 1922 | /* issue wpa setup */ |
1923 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WPA_CFG, | 1923 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WPA_CFG, |
1924 | wpa, sizeof(*wpa)); | 1924 | wpa, sizeof(*wpa)); |
1925 | if (!cmd) | 1925 | if (!cmd) |
1926 | ret = -ENOMEM; | 1926 | ret = -ENOMEM; |
1927 | else if (cmd->status || cmd->cmd_status) | 1927 | else if (cmd->status || cmd->cmd_status) |
1928 | ret = -ENXIO; | 1928 | ret = -ENXIO; |
1929 | kfree(cmd); | 1929 | kfree(cmd); |
1930 | free_page((unsigned long)wpa); | 1930 | free_page((unsigned long)wpa); |
1931 | pr_debug("%s: --> %d\n", __func__, ret); | 1931 | pr_debug("%s: --> %d\n", __func__, ret); |
1932 | return ret; | 1932 | return ret; |
1933 | } | 1933 | } |
1934 | 1934 | ||
1935 | /* | 1935 | /* |
1936 | * Start association. caller must hold assoc_stat_lock | 1936 | * Start association. caller must hold assoc_stat_lock |
1937 | */ | 1937 | */ |
1938 | static int gelic_wl_associate_bss(struct gelic_wl_info *wl, | 1938 | static int gelic_wl_associate_bss(struct gelic_wl_info *wl, |
1939 | struct gelic_wl_scan_info *bss) | 1939 | struct gelic_wl_scan_info *bss) |
1940 | { | 1940 | { |
1941 | struct gelic_eurus_cmd *cmd; | 1941 | struct gelic_eurus_cmd *cmd; |
1942 | struct gelic_eurus_common_cfg *common; | 1942 | struct gelic_eurus_common_cfg *common; |
1943 | int ret = 0; | 1943 | int ret = 0; |
1944 | unsigned long rc; | 1944 | unsigned long rc; |
1945 | 1945 | ||
1946 | pr_debug("%s: <-\n", __func__); | 1946 | pr_debug("%s: <-\n", __func__); |
1947 | 1947 | ||
1948 | /* do common config */ | 1948 | /* do common config */ |
1949 | common = (struct gelic_eurus_common_cfg *)__get_free_page(GFP_KERNEL); | 1949 | common = (struct gelic_eurus_common_cfg *)__get_free_page(GFP_KERNEL); |
1950 | if (!common) | 1950 | if (!common) |
1951 | return -ENOMEM; | 1951 | return -ENOMEM; |
1952 | 1952 | ||
1953 | memset(common, 0, sizeof(*common)); | 1953 | memset(common, 0, sizeof(*common)); |
1954 | common->bss_type = cpu_to_be16(GELIC_EURUS_BSS_INFRA); | 1954 | common->bss_type = cpu_to_be16(GELIC_EURUS_BSS_INFRA); |
1955 | common->op_mode = cpu_to_be16(GELIC_EURUS_OPMODE_11BG); | 1955 | common->op_mode = cpu_to_be16(GELIC_EURUS_OPMODE_11BG); |
1956 | 1956 | ||
1957 | common->scan_index = cpu_to_be16(bss->eurus_index); | 1957 | common->scan_index = cpu_to_be16(bss->eurus_index); |
1958 | switch (wl->auth_method) { | 1958 | switch (wl->auth_method) { |
1959 | case GELIC_EURUS_AUTH_OPEN: | 1959 | case GELIC_EURUS_AUTH_OPEN: |
1960 | common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_OPEN); | 1960 | common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_OPEN); |
1961 | break; | 1961 | break; |
1962 | case GELIC_EURUS_AUTH_SHARED: | 1962 | case GELIC_EURUS_AUTH_SHARED: |
1963 | common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_SHARED); | 1963 | common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_SHARED); |
1964 | break; | 1964 | break; |
1965 | } | 1965 | } |
1966 | 1966 | ||
1967 | #ifdef DEBUG | 1967 | #ifdef DEBUG |
1968 | scan_list_dump(wl); | 1968 | scan_list_dump(wl); |
1969 | #endif | 1969 | #endif |
1970 | pr_debug("%s: common cfg index=%d bsstype=%d auth=%d\n", __func__, | 1970 | pr_debug("%s: common cfg index=%d bsstype=%d auth=%d\n", __func__, |
1971 | be16_to_cpu(common->scan_index), | 1971 | be16_to_cpu(common->scan_index), |
1972 | be16_to_cpu(common->bss_type), | 1972 | be16_to_cpu(common->bss_type), |
1973 | be16_to_cpu(common->auth_method)); | 1973 | be16_to_cpu(common->auth_method)); |
1974 | 1974 | ||
1975 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_COMMON_CFG, | 1975 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_COMMON_CFG, |
1976 | common, sizeof(*common)); | 1976 | common, sizeof(*common)); |
1977 | if (!cmd || cmd->status || cmd->cmd_status) { | 1977 | if (!cmd || cmd->status || cmd->cmd_status) { |
1978 | ret = -ENOMEM; | 1978 | ret = -ENOMEM; |
1979 | kfree(cmd); | 1979 | kfree(cmd); |
1980 | goto out; | 1980 | goto out; |
1981 | } | 1981 | } |
1982 | kfree(cmd); | 1982 | kfree(cmd); |
1983 | 1983 | ||
1984 | /* WEP/WPA */ | 1984 | /* WEP/WPA */ |
1985 | switch (wl->wpa_level) { | 1985 | switch (wl->wpa_level) { |
1986 | case GELIC_WL_WPA_LEVEL_NONE: | 1986 | case GELIC_WL_WPA_LEVEL_NONE: |
1987 | /* If WEP or no security, setup WEP config */ | 1987 | /* If WEP or no security, setup WEP config */ |
1988 | ret = gelic_wl_do_wep_setup(wl); | 1988 | ret = gelic_wl_do_wep_setup(wl); |
1989 | break; | 1989 | break; |
1990 | case GELIC_WL_WPA_LEVEL_WPA: | 1990 | case GELIC_WL_WPA_LEVEL_WPA: |
1991 | case GELIC_WL_WPA_LEVEL_WPA2: | 1991 | case GELIC_WL_WPA_LEVEL_WPA2: |
1992 | ret = gelic_wl_do_wpa_setup(wl); | 1992 | ret = gelic_wl_do_wpa_setup(wl); |
1993 | break; | 1993 | break; |
1994 | } | 1994 | } |
1995 | 1995 | ||
1996 | if (ret) { | 1996 | if (ret) { |
1997 | pr_debug("%s: WEP/WPA setup failed %d\n", __func__, | 1997 | pr_debug("%s: WEP/WPA setup failed %d\n", __func__, |
1998 | ret); | 1998 | ret); |
1999 | ret = -EPERM; | 1999 | ret = -EPERM; |
2000 | gelic_wl_send_iwap_event(wl, NULL); | 2000 | gelic_wl_send_iwap_event(wl, NULL); |
2001 | goto out; | 2001 | goto out; |
2002 | } | 2002 | } |
2003 | 2003 | ||
2004 | /* start association */ | 2004 | /* start association */ |
2005 | init_completion(&wl->assoc_done); | 2005 | init_completion(&wl->assoc_done); |
2006 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATING; | 2006 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATING; |
2007 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_ASSOC, | 2007 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_ASSOC, |
2008 | NULL, 0); | 2008 | NULL, 0); |
2009 | if (!cmd || cmd->status || cmd->cmd_status) { | 2009 | if (!cmd || cmd->status || cmd->cmd_status) { |
2010 | pr_debug("%s: assoc request failed\n", __func__); | 2010 | pr_debug("%s: assoc request failed\n", __func__); |
2011 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; | 2011 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; |
2012 | kfree(cmd); | 2012 | kfree(cmd); |
2013 | ret = -ENOMEM; | 2013 | ret = -ENOMEM; |
2014 | gelic_wl_send_iwap_event(wl, NULL); | 2014 | gelic_wl_send_iwap_event(wl, NULL); |
2015 | goto out; | 2015 | goto out; |
2016 | } | 2016 | } |
2017 | kfree(cmd); | 2017 | kfree(cmd); |
2018 | 2018 | ||
2019 | /* wait for connected event */ | 2019 | /* wait for connected event */ |
2020 | rc = wait_for_completion_timeout(&wl->assoc_done, HZ * 4);/*FIXME*/ | 2020 | rc = wait_for_completion_timeout(&wl->assoc_done, HZ * 4);/*FIXME*/ |
2021 | 2021 | ||
2022 | if (!rc) { | 2022 | if (!rc) { |
2023 | /* timeouted. Maybe key or cyrpt mode is wrong */ | 2023 | /* timeouted. Maybe key or cyrpt mode is wrong */ |
2024 | pr_info("%s: connect timeout\n", __func__); | 2024 | pr_info("%s: connect timeout\n", __func__); |
2025 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, | 2025 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, |
2026 | NULL, 0); | 2026 | NULL, 0); |
2027 | kfree(cmd); | 2027 | kfree(cmd); |
2028 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; | 2028 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; |
2029 | gelic_wl_send_iwap_event(wl, NULL); | 2029 | gelic_wl_send_iwap_event(wl, NULL); |
2030 | ret = -ENXIO; | 2030 | ret = -ENXIO; |
2031 | } else { | 2031 | } else { |
2032 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATED; | 2032 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATED; |
2033 | /* copy bssid */ | 2033 | /* copy bssid */ |
2034 | memcpy(wl->active_bssid, &bss->hwinfo->bssid[2], ETH_ALEN); | 2034 | memcpy(wl->active_bssid, &bss->hwinfo->bssid[2], ETH_ALEN); |
2035 | 2035 | ||
2036 | /* send connect event */ | 2036 | /* send connect event */ |
2037 | gelic_wl_send_iwap_event(wl, wl->active_bssid); | 2037 | gelic_wl_send_iwap_event(wl, wl->active_bssid); |
2038 | pr_info("%s: connected\n", __func__); | 2038 | pr_info("%s: connected\n", __func__); |
2039 | } | 2039 | } |
2040 | out: | 2040 | out: |
2041 | free_page((unsigned long)common); | 2041 | free_page((unsigned long)common); |
2042 | pr_debug("%s: ->\n", __func__); | 2042 | pr_debug("%s: ->\n", __func__); |
2043 | return ret; | 2043 | return ret; |
2044 | } | 2044 | } |
2045 | 2045 | ||
2046 | /* | 2046 | /* |
2047 | * connected event | 2047 | * connected event |
2048 | */ | 2048 | */ |
2049 | static void gelic_wl_connected_event(struct gelic_wl_info *wl, | 2049 | static void gelic_wl_connected_event(struct gelic_wl_info *wl, |
2050 | u64 event) | 2050 | u64 event) |
2051 | { | 2051 | { |
2052 | u64 desired_event = 0; | 2052 | u64 desired_event = 0; |
2053 | 2053 | ||
2054 | switch (wl->wpa_level) { | 2054 | switch (wl->wpa_level) { |
2055 | case GELIC_WL_WPA_LEVEL_NONE: | 2055 | case GELIC_WL_WPA_LEVEL_NONE: |
2056 | desired_event = GELIC_LV1_WL_EVENT_CONNECTED; | 2056 | desired_event = GELIC_LV1_WL_EVENT_CONNECTED; |
2057 | break; | 2057 | break; |
2058 | case GELIC_WL_WPA_LEVEL_WPA: | 2058 | case GELIC_WL_WPA_LEVEL_WPA: |
2059 | case GELIC_WL_WPA_LEVEL_WPA2: | 2059 | case GELIC_WL_WPA_LEVEL_WPA2: |
2060 | desired_event = GELIC_LV1_WL_EVENT_WPA_CONNECTED; | 2060 | desired_event = GELIC_LV1_WL_EVENT_WPA_CONNECTED; |
2061 | break; | 2061 | break; |
2062 | } | 2062 | } |
2063 | 2063 | ||
2064 | if (desired_event == event) { | 2064 | if (desired_event == event) { |
2065 | pr_debug("%s: completed\n", __func__); | 2065 | pr_debug("%s: completed\n", __func__); |
2066 | complete(&wl->assoc_done); | 2066 | complete(&wl->assoc_done); |
2067 | netif_carrier_on(port_to_netdev(wl_port(wl))); | 2067 | netif_carrier_on(port_to_netdev(wl_port(wl))); |
2068 | } else | 2068 | } else |
2069 | pr_debug("%s: event %#llx under wpa\n", | 2069 | pr_debug("%s: event %#llx under wpa\n", |
2070 | __func__, event); | 2070 | __func__, event); |
2071 | } | 2071 | } |
2072 | 2072 | ||
2073 | /* | 2073 | /* |
2074 | * disconnect event | 2074 | * disconnect event |
2075 | */ | 2075 | */ |
2076 | static void gelic_wl_disconnect_event(struct gelic_wl_info *wl, | 2076 | static void gelic_wl_disconnect_event(struct gelic_wl_info *wl, |
2077 | u64 event) | 2077 | u64 event) |
2078 | { | 2078 | { |
2079 | struct gelic_eurus_cmd *cmd; | 2079 | struct gelic_eurus_cmd *cmd; |
2080 | int lock; | 2080 | int lock; |
2081 | 2081 | ||
2082 | /* | 2082 | /* |
2083 | * If we fall here in the middle of association, | 2083 | * If we fall here in the middle of association, |
2084 | * associate_bss() should be waiting for complation of | 2084 | * associate_bss() should be waiting for complation of |
2085 | * wl->assoc_done. | 2085 | * wl->assoc_done. |
2086 | * As it waits with timeout, just leave assoc_done | 2086 | * As it waits with timeout, just leave assoc_done |
2087 | * uncompleted, then it terminates with timeout | 2087 | * uncompleted, then it terminates with timeout |
2088 | */ | 2088 | */ |
2089 | if (!mutex_trylock(&wl->assoc_stat_lock)) { | 2089 | if (!mutex_trylock(&wl->assoc_stat_lock)) { |
2090 | pr_debug("%s: already locked\n", __func__); | 2090 | pr_debug("%s: already locked\n", __func__); |
2091 | lock = 0; | 2091 | lock = 0; |
2092 | } else { | 2092 | } else { |
2093 | pr_debug("%s: obtain lock\n", __func__); | 2093 | pr_debug("%s: obtain lock\n", __func__); |
2094 | lock = 1; | 2094 | lock = 1; |
2095 | } | 2095 | } |
2096 | 2096 | ||
2097 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, NULL, 0); | 2097 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, NULL, 0); |
2098 | kfree(cmd); | 2098 | kfree(cmd); |
2099 | 2099 | ||
2100 | /* send disconnected event to the supplicant */ | 2100 | /* send disconnected event to the supplicant */ |
2101 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) | 2101 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) |
2102 | gelic_wl_send_iwap_event(wl, NULL); | 2102 | gelic_wl_send_iwap_event(wl, NULL); |
2103 | 2103 | ||
2104 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; | 2104 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; |
2105 | netif_carrier_off(port_to_netdev(wl_port(wl))); | 2105 | netif_carrier_off(port_to_netdev(wl_port(wl))); |
2106 | 2106 | ||
2107 | if (lock) | 2107 | if (lock) |
2108 | mutex_unlock(&wl->assoc_stat_lock); | 2108 | mutex_unlock(&wl->assoc_stat_lock); |
2109 | } | 2109 | } |
2110 | /* | 2110 | /* |
2111 | * event worker | 2111 | * event worker |
2112 | */ | 2112 | */ |
2113 | #ifdef DEBUG | 2113 | #ifdef DEBUG |
2114 | static const char *eventstr(enum gelic_lv1_wl_event event) | 2114 | static const char *eventstr(enum gelic_lv1_wl_event event) |
2115 | { | 2115 | { |
2116 | static char buf[32]; | 2116 | static char buf[32]; |
2117 | char *ret; | 2117 | char *ret; |
2118 | if (event & GELIC_LV1_WL_EVENT_DEVICE_READY) | 2118 | if (event & GELIC_LV1_WL_EVENT_DEVICE_READY) |
2119 | ret = "EURUS_READY"; | 2119 | ret = "EURUS_READY"; |
2120 | else if (event & GELIC_LV1_WL_EVENT_SCAN_COMPLETED) | 2120 | else if (event & GELIC_LV1_WL_EVENT_SCAN_COMPLETED) |
2121 | ret = "SCAN_COMPLETED"; | 2121 | ret = "SCAN_COMPLETED"; |
2122 | else if (event & GELIC_LV1_WL_EVENT_DEAUTH) | 2122 | else if (event & GELIC_LV1_WL_EVENT_DEAUTH) |
2123 | ret = "DEAUTH"; | 2123 | ret = "DEAUTH"; |
2124 | else if (event & GELIC_LV1_WL_EVENT_BEACON_LOST) | 2124 | else if (event & GELIC_LV1_WL_EVENT_BEACON_LOST) |
2125 | ret = "BEACON_LOST"; | 2125 | ret = "BEACON_LOST"; |
2126 | else if (event & GELIC_LV1_WL_EVENT_CONNECTED) | 2126 | else if (event & GELIC_LV1_WL_EVENT_CONNECTED) |
2127 | ret = "CONNECTED"; | 2127 | ret = "CONNECTED"; |
2128 | else if (event & GELIC_LV1_WL_EVENT_WPA_CONNECTED) | 2128 | else if (event & GELIC_LV1_WL_EVENT_WPA_CONNECTED) |
2129 | ret = "WPA_CONNECTED"; | 2129 | ret = "WPA_CONNECTED"; |
2130 | else if (event & GELIC_LV1_WL_EVENT_WPA_ERROR) | 2130 | else if (event & GELIC_LV1_WL_EVENT_WPA_ERROR) |
2131 | ret = "WPA_ERROR"; | 2131 | ret = "WPA_ERROR"; |
2132 | else { | 2132 | else { |
2133 | sprintf(buf, "Unknown(%#x)", event); | 2133 | sprintf(buf, "Unknown(%#x)", event); |
2134 | ret = buf; | 2134 | ret = buf; |
2135 | } | 2135 | } |
2136 | return ret; | 2136 | return ret; |
2137 | } | 2137 | } |
2138 | #else | 2138 | #else |
2139 | static const char *eventstr(enum gelic_lv1_wl_event event) | 2139 | static const char *eventstr(enum gelic_lv1_wl_event event) |
2140 | { | 2140 | { |
2141 | return NULL; | 2141 | return NULL; |
2142 | } | 2142 | } |
2143 | #endif | 2143 | #endif |
2144 | static void gelic_wl_event_worker(struct work_struct *work) | 2144 | static void gelic_wl_event_worker(struct work_struct *work) |
2145 | { | 2145 | { |
2146 | struct gelic_wl_info *wl; | 2146 | struct gelic_wl_info *wl; |
2147 | struct gelic_port *port; | 2147 | struct gelic_port *port; |
2148 | u64 event, tmp; | 2148 | u64 event, tmp; |
2149 | int status; | 2149 | int status; |
2150 | 2150 | ||
2151 | pr_debug("%s:start\n", __func__); | 2151 | pr_debug("%s:start\n", __func__); |
2152 | wl = container_of(work, struct gelic_wl_info, event_work.work); | 2152 | wl = container_of(work, struct gelic_wl_info, event_work.work); |
2153 | port = wl_port(wl); | 2153 | port = wl_port(wl); |
2154 | while (1) { | 2154 | while (1) { |
2155 | status = lv1_net_control(bus_id(port->card), dev_id(port->card), | 2155 | status = lv1_net_control(bus_id(port->card), dev_id(port->card), |
2156 | GELIC_LV1_GET_WLAN_EVENT, 0, 0, 0, | 2156 | GELIC_LV1_GET_WLAN_EVENT, 0, 0, 0, |
2157 | &event, &tmp); | 2157 | &event, &tmp); |
2158 | if (status) { | 2158 | if (status) { |
2159 | if (status != LV1_NO_ENTRY) | 2159 | if (status != LV1_NO_ENTRY) |
2160 | pr_debug("%s:wlan event failed %d\n", | 2160 | pr_debug("%s:wlan event failed %d\n", |
2161 | __func__, status); | 2161 | __func__, status); |
2162 | /* got all events */ | 2162 | /* got all events */ |
2163 | pr_debug("%s:end\n", __func__); | 2163 | pr_debug("%s:end\n", __func__); |
2164 | return; | 2164 | return; |
2165 | } | 2165 | } |
2166 | pr_debug("%s: event=%s\n", __func__, eventstr(event)); | 2166 | pr_debug("%s: event=%s\n", __func__, eventstr(event)); |
2167 | switch (event) { | 2167 | switch (event) { |
2168 | case GELIC_LV1_WL_EVENT_SCAN_COMPLETED: | 2168 | case GELIC_LV1_WL_EVENT_SCAN_COMPLETED: |
2169 | gelic_wl_scan_complete_event(wl); | 2169 | gelic_wl_scan_complete_event(wl); |
2170 | break; | 2170 | break; |
2171 | case GELIC_LV1_WL_EVENT_BEACON_LOST: | 2171 | case GELIC_LV1_WL_EVENT_BEACON_LOST: |
2172 | case GELIC_LV1_WL_EVENT_DEAUTH: | 2172 | case GELIC_LV1_WL_EVENT_DEAUTH: |
2173 | gelic_wl_disconnect_event(wl, event); | 2173 | gelic_wl_disconnect_event(wl, event); |
2174 | break; | 2174 | break; |
2175 | case GELIC_LV1_WL_EVENT_CONNECTED: | 2175 | case GELIC_LV1_WL_EVENT_CONNECTED: |
2176 | case GELIC_LV1_WL_EVENT_WPA_CONNECTED: | 2176 | case GELIC_LV1_WL_EVENT_WPA_CONNECTED: |
2177 | gelic_wl_connected_event(wl, event); | 2177 | gelic_wl_connected_event(wl, event); |
2178 | break; | 2178 | break; |
2179 | default: | 2179 | default: |
2180 | break; | 2180 | break; |
2181 | } | 2181 | } |
2182 | } /* while */ | 2182 | } /* while */ |
2183 | } | 2183 | } |
2184 | /* | 2184 | /* |
2185 | * association worker | 2185 | * association worker |
2186 | */ | 2186 | */ |
2187 | static void gelic_wl_assoc_worker(struct work_struct *work) | 2187 | static void gelic_wl_assoc_worker(struct work_struct *work) |
2188 | { | 2188 | { |
2189 | struct gelic_wl_info *wl; | 2189 | struct gelic_wl_info *wl; |
2190 | 2190 | ||
2191 | struct gelic_wl_scan_info *best_bss; | 2191 | struct gelic_wl_scan_info *best_bss; |
2192 | int ret; | 2192 | int ret; |
2193 | unsigned long irqflag; | 2193 | unsigned long irqflag; |
2194 | u8 *essid; | 2194 | u8 *essid; |
2195 | size_t essid_len; | 2195 | size_t essid_len; |
2196 | 2196 | ||
2197 | wl = container_of(work, struct gelic_wl_info, assoc_work.work); | 2197 | wl = container_of(work, struct gelic_wl_info, assoc_work.work); |
2198 | 2198 | ||
2199 | mutex_lock(&wl->assoc_stat_lock); | 2199 | mutex_lock(&wl->assoc_stat_lock); |
2200 | 2200 | ||
2201 | if (wl->assoc_stat != GELIC_WL_ASSOC_STAT_DISCONN) | 2201 | if (wl->assoc_stat != GELIC_WL_ASSOC_STAT_DISCONN) |
2202 | goto out; | 2202 | goto out; |
2203 | 2203 | ||
2204 | spin_lock_irqsave(&wl->lock, irqflag); | 2204 | spin_lock_irqsave(&wl->lock, irqflag); |
2205 | if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) { | 2205 | if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) { |
2206 | pr_debug("%s: assoc ESSID configured %s\n", __func__, | 2206 | pr_debug("%s: assoc ESSID configured %s\n", __func__, |
2207 | wl->essid); | 2207 | wl->essid); |
2208 | essid = wl->essid; | 2208 | essid = wl->essid; |
2209 | essid_len = wl->essid_len; | 2209 | essid_len = wl->essid_len; |
2210 | } else { | 2210 | } else { |
2211 | essid = NULL; | 2211 | essid = NULL; |
2212 | essid_len = 0; | 2212 | essid_len = 0; |
2213 | } | 2213 | } |
2214 | spin_unlock_irqrestore(&wl->lock, irqflag); | 2214 | spin_unlock_irqrestore(&wl->lock, irqflag); |
2215 | 2215 | ||
2216 | ret = gelic_wl_start_scan(wl, 0, essid, essid_len); | 2216 | ret = gelic_wl_start_scan(wl, 0, essid, essid_len); |
2217 | if (ret == -ERESTARTSYS) { | 2217 | if (ret == -ERESTARTSYS) { |
2218 | pr_debug("%s: scan start failed association\n", __func__); | 2218 | pr_debug("%s: scan start failed association\n", __func__); |
2219 | schedule_delayed_work(&wl->assoc_work, HZ/10); /*FIXME*/ | 2219 | schedule_delayed_work(&wl->assoc_work, HZ/10); /*FIXME*/ |
2220 | goto out; | 2220 | goto out; |
2221 | } else if (ret) { | 2221 | } else if (ret) { |
2222 | pr_info("%s: scan prerequisite failed\n", __func__); | 2222 | pr_info("%s: scan prerequisite failed\n", __func__); |
2223 | goto out; | 2223 | goto out; |
2224 | } | 2224 | } |
2225 | 2225 | ||
2226 | /* | 2226 | /* |
2227 | * Wait for bss scan completion | 2227 | * Wait for bss scan completion |
2228 | * If we have scan list already, gelic_wl_start_scan() | 2228 | * If we have scan list already, gelic_wl_start_scan() |
2229 | * returns OK and raises the complete. Thus, | 2229 | * returns OK and raises the complete. Thus, |
2230 | * it's ok to wait unconditionally here | 2230 | * it's ok to wait unconditionally here |
2231 | */ | 2231 | */ |
2232 | wait_for_completion(&wl->scan_done); | 2232 | wait_for_completion(&wl->scan_done); |
2233 | 2233 | ||
2234 | pr_debug("%s: scan done\n", __func__); | 2234 | pr_debug("%s: scan done\n", __func__); |
2235 | mutex_lock(&wl->scan_lock); | 2235 | mutex_lock(&wl->scan_lock); |
2236 | if (wl->scan_stat != GELIC_WL_SCAN_STAT_GOT_LIST) { | 2236 | if (wl->scan_stat != GELIC_WL_SCAN_STAT_GOT_LIST) { |
2237 | gelic_wl_send_iwap_event(wl, NULL); | 2237 | gelic_wl_send_iwap_event(wl, NULL); |
2238 | pr_info("%s: no scan list. association failed\n", __func__); | 2238 | pr_info("%s: no scan list. association failed\n", __func__); |
2239 | goto scan_lock_out; | 2239 | goto scan_lock_out; |
2240 | } | 2240 | } |
2241 | 2241 | ||
2242 | /* find best matching bss */ | 2242 | /* find best matching bss */ |
2243 | best_bss = gelic_wl_find_best_bss(wl); | 2243 | best_bss = gelic_wl_find_best_bss(wl); |
2244 | if (!best_bss) { | 2244 | if (!best_bss) { |
2245 | gelic_wl_send_iwap_event(wl, NULL); | 2245 | gelic_wl_send_iwap_event(wl, NULL); |
2246 | pr_info("%s: no bss matched. association failed\n", __func__); | 2246 | pr_info("%s: no bss matched. association failed\n", __func__); |
2247 | goto scan_lock_out; | 2247 | goto scan_lock_out; |
2248 | } | 2248 | } |
2249 | 2249 | ||
2250 | /* ok, do association */ | 2250 | /* ok, do association */ |
2251 | ret = gelic_wl_associate_bss(wl, best_bss); | 2251 | ret = gelic_wl_associate_bss(wl, best_bss); |
2252 | if (ret) | 2252 | if (ret) |
2253 | pr_info("%s: association failed %d\n", __func__, ret); | 2253 | pr_info("%s: association failed %d\n", __func__, ret); |
2254 | scan_lock_out: | 2254 | scan_lock_out: |
2255 | mutex_unlock(&wl->scan_lock); | 2255 | mutex_unlock(&wl->scan_lock); |
2256 | out: | 2256 | out: |
2257 | mutex_unlock(&wl->assoc_stat_lock); | 2257 | mutex_unlock(&wl->assoc_stat_lock); |
2258 | } | 2258 | } |
2259 | /* | 2259 | /* |
2260 | * Interrupt handler | 2260 | * Interrupt handler |
2261 | * Called from the ethernet interrupt handler | 2261 | * Called from the ethernet interrupt handler |
2262 | * Processes wireless specific virtual interrupts only | 2262 | * Processes wireless specific virtual interrupts only |
2263 | */ | 2263 | */ |
2264 | void gelic_wl_interrupt(struct net_device *netdev, u64 status) | 2264 | void gelic_wl_interrupt(struct net_device *netdev, u64 status) |
2265 | { | 2265 | { |
2266 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 2266 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
2267 | 2267 | ||
2268 | if (status & GELIC_CARD_WLAN_COMMAND_COMPLETED) { | 2268 | if (status & GELIC_CARD_WLAN_COMMAND_COMPLETED) { |
2269 | pr_debug("%s:cmd complete\n", __func__); | 2269 | pr_debug("%s:cmd complete\n", __func__); |
2270 | complete(&wl->cmd_done_intr); | 2270 | complete(&wl->cmd_done_intr); |
2271 | } | 2271 | } |
2272 | 2272 | ||
2273 | if (status & GELIC_CARD_WLAN_EVENT_RECEIVED) { | 2273 | if (status & GELIC_CARD_WLAN_EVENT_RECEIVED) { |
2274 | pr_debug("%s:event received\n", __func__); | 2274 | pr_debug("%s:event received\n", __func__); |
2275 | queue_delayed_work(wl->event_queue, &wl->event_work, 0); | 2275 | queue_delayed_work(wl->event_queue, &wl->event_work, 0); |
2276 | } | 2276 | } |
2277 | } | 2277 | } |
2278 | 2278 | ||
2279 | /* | 2279 | /* |
2280 | * driver helpers | 2280 | * driver helpers |
2281 | */ | 2281 | */ |
2282 | static const iw_handler gelic_wl_wext_handler[] = | 2282 | static const iw_handler gelic_wl_wext_handler[] = |
2283 | { | 2283 | { |
2284 | IW_HANDLER(SIOCGIWNAME, gelic_wl_get_name), | 2284 | IW_HANDLER(SIOCGIWNAME, gelic_wl_get_name), |
2285 | IW_HANDLER(SIOCGIWRANGE, gelic_wl_get_range), | 2285 | IW_HANDLER(SIOCGIWRANGE, gelic_wl_get_range), |
2286 | IW_HANDLER(SIOCSIWSCAN, gelic_wl_set_scan), | 2286 | IW_HANDLER(SIOCSIWSCAN, gelic_wl_set_scan), |
2287 | IW_HANDLER(SIOCGIWSCAN, gelic_wl_get_scan), | 2287 | IW_HANDLER(SIOCGIWSCAN, gelic_wl_get_scan), |
2288 | IW_HANDLER(SIOCSIWAUTH, gelic_wl_set_auth), | 2288 | IW_HANDLER(SIOCSIWAUTH, gelic_wl_set_auth), |
2289 | IW_HANDLER(SIOCGIWAUTH, gelic_wl_get_auth), | 2289 | IW_HANDLER(SIOCGIWAUTH, gelic_wl_get_auth), |
2290 | IW_HANDLER(SIOCSIWESSID, gelic_wl_set_essid), | 2290 | IW_HANDLER(SIOCSIWESSID, gelic_wl_set_essid), |
2291 | IW_HANDLER(SIOCGIWESSID, gelic_wl_get_essid), | 2291 | IW_HANDLER(SIOCGIWESSID, gelic_wl_get_essid), |
2292 | IW_HANDLER(SIOCSIWENCODE, gelic_wl_set_encode), | 2292 | IW_HANDLER(SIOCSIWENCODE, gelic_wl_set_encode), |
2293 | IW_HANDLER(SIOCGIWENCODE, gelic_wl_get_encode), | 2293 | IW_HANDLER(SIOCGIWENCODE, gelic_wl_get_encode), |
2294 | IW_HANDLER(SIOCSIWAP, gelic_wl_set_ap), | 2294 | IW_HANDLER(SIOCSIWAP, gelic_wl_set_ap), |
2295 | IW_HANDLER(SIOCGIWAP, gelic_wl_get_ap), | 2295 | IW_HANDLER(SIOCGIWAP, gelic_wl_get_ap), |
2296 | IW_HANDLER(SIOCSIWENCODEEXT, gelic_wl_set_encodeext), | 2296 | IW_HANDLER(SIOCSIWENCODEEXT, gelic_wl_set_encodeext), |
2297 | IW_HANDLER(SIOCGIWENCODEEXT, gelic_wl_get_encodeext), | 2297 | IW_HANDLER(SIOCGIWENCODEEXT, gelic_wl_get_encodeext), |
2298 | IW_HANDLER(SIOCSIWMODE, gelic_wl_set_mode), | 2298 | IW_HANDLER(SIOCSIWMODE, gelic_wl_set_mode), |
2299 | IW_HANDLER(SIOCGIWMODE, gelic_wl_get_mode), | 2299 | IW_HANDLER(SIOCGIWMODE, gelic_wl_get_mode), |
2300 | IW_HANDLER(SIOCGIWNICKN, gelic_wl_get_nick), | 2300 | IW_HANDLER(SIOCGIWNICKN, gelic_wl_get_nick), |
2301 | }; | 2301 | }; |
2302 | 2302 | ||
2303 | static const struct iw_handler_def gelic_wl_wext_handler_def = { | 2303 | static const struct iw_handler_def gelic_wl_wext_handler_def = { |
2304 | .num_standard = ARRAY_SIZE(gelic_wl_wext_handler), | 2304 | .num_standard = ARRAY_SIZE(gelic_wl_wext_handler), |
2305 | .standard = gelic_wl_wext_handler, | 2305 | .standard = gelic_wl_wext_handler, |
2306 | .get_wireless_stats = gelic_wl_get_wireless_stats, | 2306 | .get_wireless_stats = gelic_wl_get_wireless_stats, |
2307 | }; | 2307 | }; |
2308 | 2308 | ||
2309 | static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card) | 2309 | static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card) |
2310 | { | 2310 | { |
2311 | struct net_device *netdev; | 2311 | struct net_device *netdev; |
2312 | struct gelic_port *port; | 2312 | struct gelic_port *port; |
2313 | struct gelic_wl_info *wl; | 2313 | struct gelic_wl_info *wl; |
2314 | unsigned int i; | 2314 | unsigned int i; |
2315 | 2315 | ||
2316 | pr_debug("%s:start\n", __func__); | 2316 | pr_debug("%s:start\n", __func__); |
2317 | netdev = alloc_etherdev(sizeof(struct gelic_port) + | 2317 | netdev = alloc_etherdev(sizeof(struct gelic_port) + |
2318 | sizeof(struct gelic_wl_info)); | 2318 | sizeof(struct gelic_wl_info)); |
2319 | pr_debug("%s: netdev =%p card=%p\n", __func__, netdev, card); | 2319 | pr_debug("%s: netdev =%p card=%p\n", __func__, netdev, card); |
2320 | if (!netdev) | 2320 | if (!netdev) |
2321 | return NULL; | 2321 | return NULL; |
2322 | 2322 | ||
2323 | strcpy(netdev->name, "wlan%d"); | 2323 | strcpy(netdev->name, "wlan%d"); |
2324 | 2324 | ||
2325 | port = netdev_priv(netdev); | 2325 | port = netdev_priv(netdev); |
2326 | port->netdev = netdev; | 2326 | port->netdev = netdev; |
2327 | port->card = card; | 2327 | port->card = card; |
2328 | port->type = GELIC_PORT_WIRELESS; | 2328 | port->type = GELIC_PORT_WIRELESS; |
2329 | 2329 | ||
2330 | wl = port_wl(port); | 2330 | wl = port_wl(port); |
2331 | pr_debug("%s: wl=%p port=%p\n", __func__, wl, port); | 2331 | pr_debug("%s: wl=%p port=%p\n", __func__, wl, port); |
2332 | 2332 | ||
2333 | /* allocate scan list */ | 2333 | /* allocate scan list */ |
2334 | wl->networks = kzalloc(sizeof(struct gelic_wl_scan_info) * | 2334 | wl->networks = kzalloc(sizeof(struct gelic_wl_scan_info) * |
2335 | GELIC_WL_BSS_MAX_ENT, GFP_KERNEL); | 2335 | GELIC_WL_BSS_MAX_ENT, GFP_KERNEL); |
2336 | 2336 | ||
2337 | if (!wl->networks) | 2337 | if (!wl->networks) |
2338 | goto fail_bss; | 2338 | goto fail_bss; |
2339 | 2339 | ||
2340 | wl->eurus_cmd_queue = create_singlethread_workqueue("gelic_cmd"); | 2340 | wl->eurus_cmd_queue = create_singlethread_workqueue("gelic_cmd"); |
2341 | if (!wl->eurus_cmd_queue) | 2341 | if (!wl->eurus_cmd_queue) |
2342 | goto fail_cmd_workqueue; | 2342 | goto fail_cmd_workqueue; |
2343 | 2343 | ||
2344 | wl->event_queue = create_singlethread_workqueue("gelic_event"); | 2344 | wl->event_queue = create_singlethread_workqueue("gelic_event"); |
2345 | if (!wl->event_queue) | 2345 | if (!wl->event_queue) |
2346 | goto fail_event_workqueue; | 2346 | goto fail_event_workqueue; |
2347 | 2347 | ||
2348 | INIT_LIST_HEAD(&wl->network_free_list); | 2348 | INIT_LIST_HEAD(&wl->network_free_list); |
2349 | INIT_LIST_HEAD(&wl->network_list); | 2349 | INIT_LIST_HEAD(&wl->network_list); |
2350 | for (i = 0; i < GELIC_WL_BSS_MAX_ENT; i++) | 2350 | for (i = 0; i < GELIC_WL_BSS_MAX_ENT; i++) |
2351 | list_add_tail(&wl->networks[i].list, | 2351 | list_add_tail(&wl->networks[i].list, |
2352 | &wl->network_free_list); | 2352 | &wl->network_free_list); |
2353 | init_completion(&wl->cmd_done_intr); | 2353 | init_completion(&wl->cmd_done_intr); |
2354 | 2354 | ||
2355 | INIT_DELAYED_WORK(&wl->event_work, gelic_wl_event_worker); | 2355 | INIT_DELAYED_WORK(&wl->event_work, gelic_wl_event_worker); |
2356 | INIT_DELAYED_WORK(&wl->assoc_work, gelic_wl_assoc_worker); | 2356 | INIT_DELAYED_WORK(&wl->assoc_work, gelic_wl_assoc_worker); |
2357 | mutex_init(&wl->scan_lock); | 2357 | mutex_init(&wl->scan_lock); |
2358 | mutex_init(&wl->assoc_stat_lock); | 2358 | mutex_init(&wl->assoc_stat_lock); |
2359 | 2359 | ||
2360 | init_completion(&wl->scan_done); | 2360 | init_completion(&wl->scan_done); |
2361 | /* for the case that no scan request is issued and stop() is called */ | 2361 | /* for the case that no scan request is issued and stop() is called */ |
2362 | complete(&wl->scan_done); | 2362 | complete(&wl->scan_done); |
2363 | 2363 | ||
2364 | spin_lock_init(&wl->lock); | 2364 | spin_lock_init(&wl->lock); |
2365 | 2365 | ||
2366 | wl->scan_age = 5*HZ; /* FIXME */ | 2366 | wl->scan_age = 5*HZ; /* FIXME */ |
2367 | 2367 | ||
2368 | /* buffer for receiving scanned list etc */ | 2368 | /* buffer for receiving scanned list etc */ |
2369 | BUILD_BUG_ON(PAGE_SIZE < | 2369 | BUILD_BUG_ON(PAGE_SIZE < |
2370 | sizeof(struct gelic_eurus_scan_info) * | 2370 | sizeof(struct gelic_eurus_scan_info) * |
2371 | GELIC_EURUS_MAX_SCAN); | 2371 | GELIC_EURUS_MAX_SCAN); |
2372 | pr_debug("%s:end\n", __func__); | 2372 | pr_debug("%s:end\n", __func__); |
2373 | return netdev; | 2373 | return netdev; |
2374 | 2374 | ||
2375 | fail_event_workqueue: | 2375 | fail_event_workqueue: |
2376 | destroy_workqueue(wl->eurus_cmd_queue); | 2376 | destroy_workqueue(wl->eurus_cmd_queue); |
2377 | fail_cmd_workqueue: | 2377 | fail_cmd_workqueue: |
2378 | kfree(wl->networks); | 2378 | kfree(wl->networks); |
2379 | fail_bss: | 2379 | fail_bss: |
2380 | free_netdev(netdev); | 2380 | free_netdev(netdev); |
2381 | pr_debug("%s:end error\n", __func__); | 2381 | pr_debug("%s:end error\n", __func__); |
2382 | return NULL; | 2382 | return NULL; |
2383 | 2383 | ||
2384 | } | 2384 | } |
2385 | 2385 | ||
2386 | static void gelic_wl_free(struct gelic_wl_info *wl) | 2386 | static void gelic_wl_free(struct gelic_wl_info *wl) |
2387 | { | 2387 | { |
2388 | struct gelic_wl_scan_info *scan_info; | 2388 | struct gelic_wl_scan_info *scan_info; |
2389 | unsigned int i; | 2389 | unsigned int i; |
2390 | 2390 | ||
2391 | pr_debug("%s: <-\n", __func__); | 2391 | pr_debug("%s: <-\n", __func__); |
2392 | 2392 | ||
2393 | pr_debug("%s: destroy queues\n", __func__); | 2393 | pr_debug("%s: destroy queues\n", __func__); |
2394 | destroy_workqueue(wl->eurus_cmd_queue); | 2394 | destroy_workqueue(wl->eurus_cmd_queue); |
2395 | destroy_workqueue(wl->event_queue); | 2395 | destroy_workqueue(wl->event_queue); |
2396 | 2396 | ||
2397 | scan_info = wl->networks; | 2397 | scan_info = wl->networks; |
2398 | for (i = 0; i < GELIC_WL_BSS_MAX_ENT; i++, scan_info++) | 2398 | for (i = 0; i < GELIC_WL_BSS_MAX_ENT; i++, scan_info++) |
2399 | kfree(scan_info->hwinfo); | 2399 | kfree(scan_info->hwinfo); |
2400 | kfree(wl->networks); | 2400 | kfree(wl->networks); |
2401 | 2401 | ||
2402 | free_netdev(port_to_netdev(wl_port(wl))); | 2402 | free_netdev(port_to_netdev(wl_port(wl))); |
2403 | 2403 | ||
2404 | pr_debug("%s: ->\n", __func__); | 2404 | pr_debug("%s: ->\n", __func__); |
2405 | } | 2405 | } |
2406 | 2406 | ||
2407 | static int gelic_wl_try_associate(struct net_device *netdev) | 2407 | static int gelic_wl_try_associate(struct net_device *netdev) |
2408 | { | 2408 | { |
2409 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 2409 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
2410 | int ret = -1; | 2410 | int ret = -1; |
2411 | unsigned int i; | 2411 | unsigned int i; |
2412 | 2412 | ||
2413 | pr_debug("%s: <-\n", __func__); | 2413 | pr_debug("%s: <-\n", __func__); |
2414 | 2414 | ||
2415 | /* check constraits for start association */ | 2415 | /* check constraits for start association */ |
2416 | /* for no access restriction AP */ | 2416 | /* for no access restriction AP */ |
2417 | if (wl->group_cipher_method == GELIC_WL_CIPHER_NONE) { | 2417 | if (wl->group_cipher_method == GELIC_WL_CIPHER_NONE) { |
2418 | if (test_bit(GELIC_WL_STAT_CONFIGURED, | 2418 | if (test_bit(GELIC_WL_STAT_CONFIGURED, |
2419 | &wl->stat)) | 2419 | &wl->stat)) |
2420 | goto do_associate; | 2420 | goto do_associate; |
2421 | else { | 2421 | else { |
2422 | pr_debug("%s: no wep, not configured\n", __func__); | 2422 | pr_debug("%s: no wep, not configured\n", __func__); |
2423 | return ret; | 2423 | return ret; |
2424 | } | 2424 | } |
2425 | } | 2425 | } |
2426 | 2426 | ||
2427 | /* for WEP, one of four keys should be set */ | 2427 | /* for WEP, one of four keys should be set */ |
2428 | if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { | 2428 | if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { |
2429 | /* one of keys set */ | 2429 | /* one of keys set */ |
2430 | for (i = 0; i < GELIC_WEP_KEYS; i++) { | 2430 | for (i = 0; i < GELIC_WEP_KEYS; i++) { |
2431 | if (test_bit(i, &wl->key_enabled)) | 2431 | if (test_bit(i, &wl->key_enabled)) |
2432 | goto do_associate; | 2432 | goto do_associate; |
2433 | } | 2433 | } |
2434 | pr_debug("%s: WEP, but no key specified\n", __func__); | 2434 | pr_debug("%s: WEP, but no key specified\n", __func__); |
2435 | return ret; | 2435 | return ret; |
2436 | } | 2436 | } |
2437 | 2437 | ||
2438 | /* for WPA[2], psk should be set */ | 2438 | /* for WPA[2], psk should be set */ |
2439 | if ((wl->group_cipher_method == GELIC_WL_CIPHER_TKIP) || | 2439 | if ((wl->group_cipher_method == GELIC_WL_CIPHER_TKIP) || |
2440 | (wl->group_cipher_method == GELIC_WL_CIPHER_AES)) { | 2440 | (wl->group_cipher_method == GELIC_WL_CIPHER_AES)) { |
2441 | if (test_bit(GELIC_WL_STAT_WPA_PSK_SET, | 2441 | if (test_bit(GELIC_WL_STAT_WPA_PSK_SET, |
2442 | &wl->stat)) | 2442 | &wl->stat)) |
2443 | goto do_associate; | 2443 | goto do_associate; |
2444 | else { | 2444 | else { |
2445 | pr_debug("%s: AES/TKIP, but PSK not configured\n", | 2445 | pr_debug("%s: AES/TKIP, but PSK not configured\n", |
2446 | __func__); | 2446 | __func__); |
2447 | return ret; | 2447 | return ret; |
2448 | } | 2448 | } |
2449 | } | 2449 | } |
2450 | 2450 | ||
2451 | do_associate: | 2451 | do_associate: |
2452 | ret = schedule_delayed_work(&wl->assoc_work, 0); | 2452 | ret = schedule_delayed_work(&wl->assoc_work, 0); |
2453 | pr_debug("%s: start association work %d\n", __func__, ret); | 2453 | pr_debug("%s: start association work %d\n", __func__, ret); |
2454 | return ret; | 2454 | return ret; |
2455 | } | 2455 | } |
2456 | 2456 | ||
2457 | /* | 2457 | /* |
2458 | * netdev handlers | 2458 | * netdev handlers |
2459 | */ | 2459 | */ |
2460 | static int gelic_wl_open(struct net_device *netdev) | 2460 | static int gelic_wl_open(struct net_device *netdev) |
2461 | { | 2461 | { |
2462 | struct gelic_card *card = netdev_card(netdev); | 2462 | struct gelic_card *card = netdev_card(netdev); |
2463 | 2463 | ||
2464 | pr_debug("%s:->%p\n", __func__, netdev); | 2464 | pr_debug("%s:->%p\n", __func__, netdev); |
2465 | 2465 | ||
2466 | gelic_card_up(card); | 2466 | gelic_card_up(card); |
2467 | 2467 | ||
2468 | /* try to associate */ | 2468 | /* try to associate */ |
2469 | gelic_wl_try_associate(netdev); | 2469 | gelic_wl_try_associate(netdev); |
2470 | 2470 | ||
2471 | netif_start_queue(netdev); | 2471 | netif_start_queue(netdev); |
2472 | 2472 | ||
2473 | pr_debug("%s:<-\n", __func__); | 2473 | pr_debug("%s:<-\n", __func__); |
2474 | return 0; | 2474 | return 0; |
2475 | } | 2475 | } |
2476 | 2476 | ||
2477 | /* | 2477 | /* |
2478 | * reset state machine | 2478 | * reset state machine |
2479 | */ | 2479 | */ |
2480 | static int gelic_wl_reset_state(struct gelic_wl_info *wl) | 2480 | static int gelic_wl_reset_state(struct gelic_wl_info *wl) |
2481 | { | 2481 | { |
2482 | struct gelic_wl_scan_info *target; | 2482 | struct gelic_wl_scan_info *target; |
2483 | struct gelic_wl_scan_info *tmp; | 2483 | struct gelic_wl_scan_info *tmp; |
2484 | 2484 | ||
2485 | /* empty scan list */ | 2485 | /* empty scan list */ |
2486 | list_for_each_entry_safe(target, tmp, &wl->network_list, list) { | 2486 | list_for_each_entry_safe(target, tmp, &wl->network_list, list) { |
2487 | list_move_tail(&target->list, &wl->network_free_list); | 2487 | list_move_tail(&target->list, &wl->network_free_list); |
2488 | } | 2488 | } |
2489 | wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; | 2489 | wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; |
2490 | 2490 | ||
2491 | /* clear configuration */ | 2491 | /* clear configuration */ |
2492 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; | 2492 | wl->auth_method = GELIC_EURUS_AUTH_OPEN; |
2493 | wl->group_cipher_method = GELIC_WL_CIPHER_NONE; | 2493 | wl->group_cipher_method = GELIC_WL_CIPHER_NONE; |
2494 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; | 2494 | wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; |
2495 | wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; | 2495 | wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; |
2496 | 2496 | ||
2497 | wl->key_enabled = 0; | 2497 | wl->key_enabled = 0; |
2498 | wl->current_key = 0; | 2498 | wl->current_key = 0; |
2499 | 2499 | ||
2500 | wl->psk_type = GELIC_EURUS_WPA_PSK_PASSPHRASE; | 2500 | wl->psk_type = GELIC_EURUS_WPA_PSK_PASSPHRASE; |
2501 | wl->psk_len = 0; | 2501 | wl->psk_len = 0; |
2502 | 2502 | ||
2503 | wl->essid_len = 0; | 2503 | wl->essid_len = 0; |
2504 | memset(wl->essid, 0, sizeof(wl->essid)); | 2504 | memset(wl->essid, 0, sizeof(wl->essid)); |
2505 | memset(wl->bssid, 0, sizeof(wl->bssid)); | 2505 | memset(wl->bssid, 0, sizeof(wl->bssid)); |
2506 | memset(wl->active_bssid, 0, sizeof(wl->active_bssid)); | 2506 | memset(wl->active_bssid, 0, sizeof(wl->active_bssid)); |
2507 | 2507 | ||
2508 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; | 2508 | wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; |
2509 | 2509 | ||
2510 | memset(&wl->iwstat, 0, sizeof(wl->iwstat)); | 2510 | memset(&wl->iwstat, 0, sizeof(wl->iwstat)); |
2511 | /* all status bit clear */ | 2511 | /* all status bit clear */ |
2512 | wl->stat = 0; | 2512 | wl->stat = 0; |
2513 | return 0; | 2513 | return 0; |
2514 | } | 2514 | } |
2515 | 2515 | ||
2516 | /* | 2516 | /* |
2517 | * Tell eurus to terminate association | 2517 | * Tell eurus to terminate association |
2518 | */ | 2518 | */ |
2519 | static void gelic_wl_disconnect(struct net_device *netdev) | 2519 | static void gelic_wl_disconnect(struct net_device *netdev) |
2520 | { | 2520 | { |
2521 | struct gelic_port *port = netdev_priv(netdev); | 2521 | struct gelic_port *port = netdev_priv(netdev); |
2522 | struct gelic_wl_info *wl = port_wl(port); | 2522 | struct gelic_wl_info *wl = port_wl(port); |
2523 | struct gelic_eurus_cmd *cmd; | 2523 | struct gelic_eurus_cmd *cmd; |
2524 | 2524 | ||
2525 | /* | 2525 | /* |
2526 | * If scann process is running on chip, | 2526 | * If scann process is running on chip, |
2527 | * further requests will be rejected | 2527 | * further requests will be rejected |
2528 | */ | 2528 | */ |
2529 | if (wl->scan_stat == GELIC_WL_SCAN_STAT_SCANNING) | 2529 | if (wl->scan_stat == GELIC_WL_SCAN_STAT_SCANNING) |
2530 | wait_for_completion_timeout(&wl->scan_done, HZ); | 2530 | wait_for_completion_timeout(&wl->scan_done, HZ); |
2531 | 2531 | ||
2532 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, NULL, 0); | 2532 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, NULL, 0); |
2533 | kfree(cmd); | 2533 | kfree(cmd); |
2534 | gelic_wl_send_iwap_event(wl, NULL); | 2534 | gelic_wl_send_iwap_event(wl, NULL); |
2535 | }; | 2535 | }; |
2536 | 2536 | ||
2537 | static int gelic_wl_stop(struct net_device *netdev) | 2537 | static int gelic_wl_stop(struct net_device *netdev) |
2538 | { | 2538 | { |
2539 | struct gelic_port *port = netdev_priv(netdev); | 2539 | struct gelic_port *port = netdev_priv(netdev); |
2540 | struct gelic_wl_info *wl = port_wl(port); | 2540 | struct gelic_wl_info *wl = port_wl(port); |
2541 | struct gelic_card *card = netdev_card(netdev); | 2541 | struct gelic_card *card = netdev_card(netdev); |
2542 | 2542 | ||
2543 | pr_debug("%s:<-\n", __func__); | 2543 | pr_debug("%s:<-\n", __func__); |
2544 | 2544 | ||
2545 | /* | 2545 | /* |
2546 | * Cancel pending association work. | 2546 | * Cancel pending association work. |
2547 | * event work can run after netdev down | 2547 | * event work can run after netdev down |
2548 | */ | 2548 | */ |
2549 | cancel_delayed_work(&wl->assoc_work); | 2549 | cancel_delayed_work(&wl->assoc_work); |
2550 | 2550 | ||
2551 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) | 2551 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) |
2552 | gelic_wl_disconnect(netdev); | 2552 | gelic_wl_disconnect(netdev); |
2553 | 2553 | ||
2554 | /* reset our state machine */ | 2554 | /* reset our state machine */ |
2555 | gelic_wl_reset_state(wl); | 2555 | gelic_wl_reset_state(wl); |
2556 | 2556 | ||
2557 | netif_stop_queue(netdev); | 2557 | netif_stop_queue(netdev); |
2558 | 2558 | ||
2559 | gelic_card_down(card); | 2559 | gelic_card_down(card); |
2560 | 2560 | ||
2561 | pr_debug("%s:->\n", __func__); | 2561 | pr_debug("%s:->\n", __func__); |
2562 | return 0; | 2562 | return 0; |
2563 | } | 2563 | } |
2564 | 2564 | ||
2565 | /* -- */ | 2565 | /* -- */ |
2566 | 2566 | ||
2567 | static const struct net_device_ops gelic_wl_netdevice_ops = { | 2567 | static const struct net_device_ops gelic_wl_netdevice_ops = { |
2568 | .ndo_open = gelic_wl_open, | 2568 | .ndo_open = gelic_wl_open, |
2569 | .ndo_stop = gelic_wl_stop, | 2569 | .ndo_stop = gelic_wl_stop, |
2570 | .ndo_start_xmit = gelic_net_xmit, | 2570 | .ndo_start_xmit = gelic_net_xmit, |
2571 | .ndo_set_multicast_list = gelic_net_set_multi, | 2571 | .ndo_set_multicast_list = gelic_net_set_multi, |
2572 | .ndo_change_mtu = gelic_net_change_mtu, | 2572 | .ndo_change_mtu = gelic_net_change_mtu, |
2573 | .ndo_tx_timeout = gelic_net_tx_timeout, | 2573 | .ndo_tx_timeout = gelic_net_tx_timeout, |
2574 | .ndo_set_mac_address = eth_mac_addr, | 2574 | .ndo_set_mac_address = eth_mac_addr, |
2575 | .ndo_validate_addr = eth_validate_addr, | 2575 | .ndo_validate_addr = eth_validate_addr, |
2576 | #ifdef CONFIG_NET_POLL_CONTROLLER | 2576 | #ifdef CONFIG_NET_POLL_CONTROLLER |
2577 | .ndo_poll_controller = gelic_net_poll_controller, | 2577 | .ndo_poll_controller = gelic_net_poll_controller, |
2578 | #endif | 2578 | #endif |
2579 | }; | 2579 | }; |
2580 | 2580 | ||
2581 | static const struct ethtool_ops gelic_wl_ethtool_ops = { | 2581 | static const struct ethtool_ops gelic_wl_ethtool_ops = { |
2582 | .get_drvinfo = gelic_net_get_drvinfo, | 2582 | .get_drvinfo = gelic_net_get_drvinfo, |
2583 | .get_link = gelic_wl_get_link, | 2583 | .get_link = gelic_wl_get_link, |
2584 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
2585 | .set_tx_csum = ethtool_op_set_tx_csum, | ||
2586 | .get_rx_csum = gelic_net_get_rx_csum, | ||
2587 | .set_rx_csum = gelic_net_set_rx_csum, | ||
2588 | }; | 2584 | }; |
2589 | 2585 | ||
2590 | static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev) | 2586 | static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev) |
2591 | { | 2587 | { |
2592 | struct gelic_wl_info *wl; | 2588 | struct gelic_wl_info *wl; |
2593 | wl = port_wl(netdev_priv(netdev)); | 2589 | wl = port_wl(netdev_priv(netdev)); |
2594 | BUG_ON(!wl); | 2590 | BUG_ON(!wl); |
2595 | netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; | 2591 | netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; |
2596 | 2592 | ||
2597 | netdev->ethtool_ops = &gelic_wl_ethtool_ops; | 2593 | netdev->ethtool_ops = &gelic_wl_ethtool_ops; |
2598 | netdev->netdev_ops = &gelic_wl_netdevice_ops; | 2594 | netdev->netdev_ops = &gelic_wl_netdevice_ops; |
2599 | netdev->wireless_data = &wl->wireless_data; | 2595 | netdev->wireless_data = &wl->wireless_data; |
2600 | netdev->wireless_handlers = &gelic_wl_wext_handler_def; | 2596 | netdev->wireless_handlers = &gelic_wl_wext_handler_def; |
2601 | } | 2597 | } |
2602 | 2598 | ||
2603 | /* | 2599 | /* |
2604 | * driver probe/remove | 2600 | * driver probe/remove |
2605 | */ | 2601 | */ |
2606 | int __devinit gelic_wl_driver_probe(struct gelic_card *card) | 2602 | int __devinit gelic_wl_driver_probe(struct gelic_card *card) |
2607 | { | 2603 | { |
2608 | int ret; | 2604 | int ret; |
2609 | struct net_device *netdev; | 2605 | struct net_device *netdev; |
2610 | 2606 | ||
2611 | pr_debug("%s:start\n", __func__); | 2607 | pr_debug("%s:start\n", __func__); |
2612 | 2608 | ||
2613 | if (ps3_compare_firmware_version(1, 6, 0) < 0) | 2609 | if (ps3_compare_firmware_version(1, 6, 0) < 0) |
2614 | return 0; | 2610 | return 0; |
2615 | if (!card->vlan[GELIC_PORT_WIRELESS].tx) | 2611 | if (!card->vlan[GELIC_PORT_WIRELESS].tx) |
2616 | return 0; | 2612 | return 0; |
2617 | 2613 | ||
2618 | /* alloc netdevice for wireless */ | 2614 | /* alloc netdevice for wireless */ |
2619 | netdev = gelic_wl_alloc(card); | 2615 | netdev = gelic_wl_alloc(card); |
2620 | if (!netdev) | 2616 | if (!netdev) |
2621 | return -ENOMEM; | 2617 | return -ENOMEM; |
2622 | 2618 | ||
2623 | /* setup net_device structure */ | 2619 | /* setup net_device structure */ |
2624 | SET_NETDEV_DEV(netdev, &card->dev->core); | 2620 | SET_NETDEV_DEV(netdev, &card->dev->core); |
2625 | gelic_wl_setup_netdev_ops(netdev); | 2621 | gelic_wl_setup_netdev_ops(netdev); |
2626 | 2622 | ||
2627 | /* setup some of net_device and register it */ | 2623 | /* setup some of net_device and register it */ |
2628 | ret = gelic_net_setup_netdev(netdev, card); | 2624 | ret = gelic_net_setup_netdev(netdev, card); |
2629 | if (ret) | 2625 | if (ret) |
2630 | goto fail_setup; | 2626 | goto fail_setup; |
2631 | card->netdev[GELIC_PORT_WIRELESS] = netdev; | 2627 | card->netdev[GELIC_PORT_WIRELESS] = netdev; |
2632 | 2628 | ||
2633 | /* add enable wireless interrupt */ | 2629 | /* add enable wireless interrupt */ |
2634 | card->irq_mask |= GELIC_CARD_WLAN_EVENT_RECEIVED | | 2630 | card->irq_mask |= GELIC_CARD_WLAN_EVENT_RECEIVED | |
2635 | GELIC_CARD_WLAN_COMMAND_COMPLETED; | 2631 | GELIC_CARD_WLAN_COMMAND_COMPLETED; |
2636 | /* to allow wireless commands while both interfaces are down */ | 2632 | /* to allow wireless commands while both interfaces are down */ |
2637 | gelic_card_set_irq_mask(card, GELIC_CARD_WLAN_EVENT_RECEIVED | | 2633 | gelic_card_set_irq_mask(card, GELIC_CARD_WLAN_EVENT_RECEIVED | |
2638 | GELIC_CARD_WLAN_COMMAND_COMPLETED); | 2634 | GELIC_CARD_WLAN_COMMAND_COMPLETED); |
2639 | pr_debug("%s:end\n", __func__); | 2635 | pr_debug("%s:end\n", __func__); |
2640 | return 0; | 2636 | return 0; |
2641 | 2637 | ||
2642 | fail_setup: | 2638 | fail_setup: |
2643 | gelic_wl_free(port_wl(netdev_port(netdev))); | 2639 | gelic_wl_free(port_wl(netdev_port(netdev))); |
2644 | 2640 | ||
2645 | return ret; | 2641 | return ret; |
2646 | } | 2642 | } |
2647 | 2643 | ||
2648 | int gelic_wl_driver_remove(struct gelic_card *card) | 2644 | int gelic_wl_driver_remove(struct gelic_card *card) |
2649 | { | 2645 | { |
2650 | struct gelic_wl_info *wl; | 2646 | struct gelic_wl_info *wl; |
2651 | struct net_device *netdev; | 2647 | struct net_device *netdev; |
2652 | 2648 | ||
2653 | pr_debug("%s:start\n", __func__); | 2649 | pr_debug("%s:start\n", __func__); |
2654 | 2650 | ||
2655 | if (ps3_compare_firmware_version(1, 6, 0) < 0) | 2651 | if (ps3_compare_firmware_version(1, 6, 0) < 0) |
2656 | return 0; | 2652 | return 0; |
2657 | if (!card->vlan[GELIC_PORT_WIRELESS].tx) | 2653 | if (!card->vlan[GELIC_PORT_WIRELESS].tx) |
2658 | return 0; | 2654 | return 0; |
2659 | 2655 | ||
2660 | netdev = card->netdev[GELIC_PORT_WIRELESS]; | 2656 | netdev = card->netdev[GELIC_PORT_WIRELESS]; |
2661 | wl = port_wl(netdev_priv(netdev)); | 2657 | wl = port_wl(netdev_priv(netdev)); |
2662 | 2658 | ||
2663 | /* if the interface was not up, but associated */ | 2659 | /* if the interface was not up, but associated */ |
2664 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) | 2660 | if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) |
2665 | gelic_wl_disconnect(netdev); | 2661 | gelic_wl_disconnect(netdev); |
2666 | 2662 | ||
2667 | complete(&wl->cmd_done_intr); | 2663 | complete(&wl->cmd_done_intr); |
2668 | 2664 | ||
2669 | /* cancel all work queue */ | 2665 | /* cancel all work queue */ |
2670 | cancel_delayed_work(&wl->assoc_work); | 2666 | cancel_delayed_work(&wl->assoc_work); |
2671 | cancel_delayed_work(&wl->event_work); | 2667 | cancel_delayed_work(&wl->event_work); |
2672 | flush_workqueue(wl->eurus_cmd_queue); | 2668 | flush_workqueue(wl->eurus_cmd_queue); |
2673 | flush_workqueue(wl->event_queue); | 2669 | flush_workqueue(wl->event_queue); |
2674 | 2670 | ||
2675 | unregister_netdev(netdev); | 2671 | unregister_netdev(netdev); |
2676 | 2672 | ||
2677 | /* disable wireless interrupt */ | 2673 | /* disable wireless interrupt */ |
2678 | pr_debug("%s: disable intr\n", __func__); | 2674 | pr_debug("%s: disable intr\n", __func__); |
2679 | card->irq_mask &= ~(GELIC_CARD_WLAN_EVENT_RECEIVED | | 2675 | card->irq_mask &= ~(GELIC_CARD_WLAN_EVENT_RECEIVED | |
2680 | GELIC_CARD_WLAN_COMMAND_COMPLETED); | 2676 | GELIC_CARD_WLAN_COMMAND_COMPLETED); |
2681 | /* free bss list, netdev*/ | 2677 | /* free bss list, netdev*/ |
2682 | gelic_wl_free(wl); | 2678 | gelic_wl_free(wl); |
2683 | pr_debug("%s:end\n", __func__); | 2679 | pr_debug("%s:end\n", __func__); |
2684 | return 0; | 2680 | return 0; |
2685 | } | 2681 | } |
2686 | 2682 |