]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/ks7010/ks7010_sdio.c
staging: ks7010: remove zero comparison
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / ks7010 / ks7010_sdio.c
CommitLineData
13a9930d
WS
1/*
2 * Driver for KeyStream, KS7010 based SDIO cards.
3 *
13a9930d
WS
4 * Copyright (C) 2006-2008 KeyStream Corp.
5 * Copyright (C) 2009 Renesas Technology Corp.
c5d9a030 6 * Copyright (C) 2016 Sang Engineering, Wolfram Sang
13a9930d
WS
7 *
8 * This program is free software; you can redistribute it and/or modify
c5d9a030
WS
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13a9930d
WS
11 */
12
1c013a5c 13#include <linux/firmware.h>
13a9930d
WS
14#include <linux/mmc/card.h>
15#include <linux/mmc/sdio_func.h>
1c013a5c 16#include <linux/workqueue.h>
041c4d75 17#include <linux/atomic.h>
13a9930d
WS
18
19#include "ks_wlan.h"
20#include "ks_wlan_ioctl.h"
13a9930d 21#include "ks_hostif.h"
13a9930d
WS
22#include "ks7010_sdio.h"
23
24#define KS7010_FUNC_NUM 1
25#define KS7010_IO_BLOCK_SIZE 512
26#define KS7010_MAX_CLOCK 25000000
27
f9b5bd05 28static const struct sdio_device_id ks7010_sdio_ids[] = {
cdf6ecc5
WS
29 {SDIO_DEVICE(SDIO_VENDOR_ID_KS_CODE_A, SDIO_DEVICE_ID_KS_7010)},
30 {SDIO_DEVICE(SDIO_VENDOR_ID_KS_CODE_B, SDIO_DEVICE_ID_KS_7010)},
13a9930d
WS
31 { /* all zero */ }
32};
f9b5bd05 33MODULE_DEVICE_TABLE(sdio, ks7010_sdio_ids);
13a9930d 34
13a9930d
WS
35/* macro */
36
37#define inc_txqhead(priv) \
4fdaa0d7 38 (priv->tx_dev.qhead = (priv->tx_dev.qhead + 1) % TX_DEVICE_BUFF_SIZE)
13a9930d 39#define inc_txqtail(priv) \
4fdaa0d7 40 (priv->tx_dev.qtail = (priv->tx_dev.qtail + 1) % TX_DEVICE_BUFF_SIZE)
13a9930d 41#define cnt_txqbody(priv) \
4fdaa0d7 42 (((priv->tx_dev.qtail + TX_DEVICE_BUFF_SIZE) - (priv->tx_dev.qhead)) % TX_DEVICE_BUFF_SIZE)
13a9930d
WS
43
44#define inc_rxqhead(priv) \
4fdaa0d7 45 (priv->rx_dev.qhead = (priv->rx_dev.qhead + 1) % RX_DEVICE_BUFF_SIZE)
13a9930d 46#define inc_rxqtail(priv) \
4fdaa0d7 47 (priv->rx_dev.qtail = (priv->rx_dev.qtail + 1) % RX_DEVICE_BUFF_SIZE)
13a9930d 48#define cnt_rxqbody(priv) \
4fdaa0d7 49 (((priv->rx_dev.qtail + RX_DEVICE_BUFF_SIZE) - (priv->rx_dev.qhead)) % RX_DEVICE_BUFF_SIZE)
13a9930d 50
4c0d46d2
WS
51static int ks7010_sdio_read(struct ks_wlan_private *priv, unsigned int address,
52 unsigned char *buffer, int length)
53{
54 struct ks_sdio_card *card;
55 int rc;
56
57 card = priv->ks_wlan_hw.sdio_card;
58
59 if (length == 1) /* CMD52 */
60 *buffer = sdio_readb(card->func, address, &rc);
61 else /* CMD53 multi-block transfer */
62 rc = sdio_memcpy_fromio(card->func, buffer, address, length);
63
c133b9bd 64 if (rc)
4c0d46d2
WS
65 DPRINTK(1, "sdio error=%d size=%d\n", rc, length);
66
67 return rc;
68}
69
70static int ks7010_sdio_write(struct ks_wlan_private *priv, unsigned int address,
71 unsigned char *buffer, int length)
72{
73 struct ks_sdio_card *card;
74 int rc;
75
76 card = priv->ks_wlan_hw.sdio_card;
77
78 if (length == 1) /* CMD52 */
0af45479 79 sdio_writeb(card->func, *buffer, address, &rc);
4c0d46d2 80 else /* CMD53 */
0af45479 81 rc = sdio_memcpy_toio(card->func, address, buffer, length);
4c0d46d2 82
c133b9bd 83 if (rc)
4c0d46d2
WS
84 DPRINTK(1, "sdio error=%d size=%d\n", rc, length);
85
86 return rc;
87}
88
4433459a 89static void ks_wlan_hw_sleep_doze_request(struct ks_wlan_private *priv)
13a9930d
WS
90{
91 unsigned char rw_data;
92 int retval;
93
94 DPRINTK(4, "\n");
95
96 /* clear request */
cdf6ecc5 97 atomic_set(&priv->sleepstatus.doze_request, 0);
13a9930d 98
cdf6ecc5 99 if (atomic_read(&priv->sleepstatus.status) == 0) {
13a9930d 100 rw_data = GCR_B_DOZE;
cdf6ecc5
WS
101 retval =
102 ks7010_sdio_write(priv, GCR_B, &rw_data, sizeof(rw_data));
103 if (retval) {
13a9930d 104 DPRINTK(1, " error : GCR_B=%02X\n", rw_data);
f283dd69 105 goto set_sleep_mode;
13a9930d
WS
106 }
107 DPRINTK(4, "PMG SET!! : GCR_B=%02X\n", rw_data);
cdf6ecc5 108 DPRINTK(3, "sleep_mode=SLP_SLEEP\n");
13a9930d 109 atomic_set(&priv->sleepstatus.status, 1);
cdf6ecc5
WS
110 priv->last_doze = jiffies;
111 } else {
112 DPRINTK(1, "sleep_mode=%d\n", priv->sleep_mode);
13a9930d
WS
113 }
114
f283dd69 115set_sleep_mode:
13a9930d 116 priv->sleep_mode = atomic_read(&priv->sleepstatus.status);
13a9930d
WS
117}
118
4433459a 119static void ks_wlan_hw_sleep_wakeup_request(struct ks_wlan_private *priv)
13a9930d
WS
120{
121 unsigned char rw_data;
122 int retval;
123
124 DPRINTK(4, "\n");
125
126 /* clear request */
cdf6ecc5 127 atomic_set(&priv->sleepstatus.wakeup_request, 0);
13a9930d 128
cdf6ecc5 129 if (atomic_read(&priv->sleepstatus.status) == 1) {
13a9930d 130 rw_data = WAKEUP_REQ;
cdf6ecc5
WS
131 retval =
132 ks7010_sdio_write(priv, WAKEUP, &rw_data, sizeof(rw_data));
133 if (retval) {
13a9930d 134 DPRINTK(1, " error : WAKEUP=%02X\n", rw_data);
f283dd69 135 goto set_sleep_mode;
13a9930d
WS
136 }
137 DPRINTK(4, "wake up : WAKEUP=%02X\n", rw_data);
138 atomic_set(&priv->sleepstatus.status, 0);
cdf6ecc5 139 priv->last_wakeup = jiffies;
13a9930d 140 ++priv->wakeup_count;
cdf6ecc5
WS
141 } else {
142 DPRINTK(1, "sleep_mode=%d\n", priv->sleep_mode);
13a9930d
WS
143 }
144
f283dd69 145set_sleep_mode:
13a9930d 146 priv->sleep_mode = atomic_read(&priv->sleepstatus.status);
13a9930d
WS
147}
148
feedcf1a 149void ks_wlan_hw_wakeup_request(struct ks_wlan_private *priv)
13a9930d
WS
150{
151 unsigned char rw_data;
152 int retval;
153
154 DPRINTK(4, "\n");
cdf6ecc5 155 if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
13a9930d 156 rw_data = WAKEUP_REQ;
cdf6ecc5
WS
157 retval =
158 ks7010_sdio_write(priv, WAKEUP, &rw_data, sizeof(rw_data));
53638cef 159 if (retval)
13a9930d 160 DPRINTK(1, " error : WAKEUP=%02X\n", rw_data);
53638cef 161
13a9930d 162 DPRINTK(4, "wake up : WAKEUP=%02X\n", rw_data);
cdf6ecc5 163 priv->last_wakeup = jiffies;
13a9930d 164 ++priv->wakeup_count;
cdf6ecc5
WS
165 } else {
166 DPRINTK(1, "psstatus=%d\n",
167 atomic_read(&priv->psstatus.status));
13a9930d
WS
168 }
169}
170
4433459a 171static int _ks_wlan_hw_power_save(struct ks_wlan_private *priv)
13a9930d 172{
13a9930d
WS
173 unsigned char rw_data;
174 int retval;
175
cdf6ecc5 176 if (priv->reg.powermgt == POWMGT_ACTIVE_MODE)
7d359a84 177 return 0;
13a9930d 178
d5f1db31
TH
179 if (priv->reg.operation_mode != MODE_INFRASTRUCTURE ||
180 (priv->connect_status & CONNECT_STATUS_MASK) != CONNECT_STATUS)
181 return 0;
182
183 if (priv->dev_state != DEVICE_STATE_SLEEP)
184 return 0;
185
3188bc09
TH
186 if (atomic_read(&priv->psstatus.status) == PS_SNOOZE)
187 return 0;
188
189 DPRINTK(5, "\npsstatus.status=%d\npsstatus.confirm_wait=%d\npsstatus.snooze_guard=%d\ncnt_txqbody=%d\n",
190 atomic_read(&priv->psstatus.status),
191 atomic_read(&priv->psstatus.confirm_wait),
192 atomic_read(&priv->psstatus.snooze_guard),
193 cnt_txqbody(priv));
194
195 if (!atomic_read(&priv->psstatus.confirm_wait) &&
44c3cd5e
TH
196 !atomic_read(&priv->psstatus.snooze_guard) &&
197 !cnt_txqbody(priv)) {
dad5980e
TH
198 retval = ks7010_sdio_read(priv, INT_PENDING, &rw_data,
199 sizeof(rw_data));
3188bc09 200 if (retval) {
dad5980e 201 DPRINTK(1, " error : INT_PENDING=%02X\n", rw_data);
3188bc09 202 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
dad5980e 203 &priv->ks_wlan_hw.rw_wq, 1);
3188bc09
TH
204 return 0;
205 }
206 if (!rw_data) {
207 rw_data = GCR_B_DOZE;
dad5980e
TH
208 retval = ks7010_sdio_write(priv, GCR_B, &rw_data,
209 sizeof(rw_data));
d5f1db31 210 if (retval) {
dad5980e
TH
211 DPRINTK(1, " error : GCR_B=%02X\n", rw_data);
212 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
213 &priv->ks_wlan_hw.rw_wq, 1);
3188bc09 214 return 0;
13a9930d 215 }
dad5980e 216 DPRINTK(4, "PMG SET!! : GCR_B=%02X\n", rw_data);
3188bc09 217 atomic_set(&priv->psstatus.status, PS_SNOOZE);
dad5980e 218 DPRINTK(3, "psstatus.status=PS_SNOOZE\n");
d5f1db31 219 } else {
9f9d7030 220 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
dad5980e 221 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d 222 }
3188bc09
TH
223 } else {
224 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
dad5980e 225 &priv->ks_wlan_hw.rw_wq, 0);
13a9930d
WS
226 }
227
7d359a84 228 return 0;
13a9930d
WS
229}
230
feedcf1a 231int ks_wlan_hw_power_save(struct ks_wlan_private *priv)
13a9930d 232{
cdf6ecc5
WS
233 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
234 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d
WS
235 return 0;
236}
237
cdf6ecc5
WS
238static int enqueue_txdev(struct ks_wlan_private *priv, unsigned char *p,
239 unsigned long size,
71a476e4 240 void (*complete_handler)(void *arg1, void *arg2),
cdf6ecc5 241 void *arg1, void *arg2)
13a9930d
WS
242{
243 struct tx_device_buffer *sp;
aa6ca807 244 int rc;
13a9930d
WS
245
246 if (priv->dev_state < DEVICE_STATE_BOOT) {
aa6ca807
TH
247 rc = -EPERM;
248 goto err_complete;
13a9930d
WS
249 }
250
cdf6ecc5 251 if ((TX_DEVICE_BUFF_SIZE - 1) <= cnt_txqbody(priv)) {
13a9930d 252 /* in case of buffer overflow */
cdf6ecc5 253 DPRINTK(1, "tx buffer overflow\n");
aa6ca807
TH
254 rc = -EOVERFLOW;
255 goto err_complete;
13a9930d
WS
256 }
257
258 sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qtail];
259 sp->sendp = p;
260 sp->size = size;
261 sp->complete_handler = complete_handler;
262 sp->arg1 = arg1;
263 sp->arg2 = arg2;
264 inc_txqtail(priv);
265
266 return 0;
aa6ca807
TH
267
268err_complete:
269 kfree(p);
270 if (complete_handler)
271 (*complete_handler) (arg1, arg2);
272
273 return rc;
13a9930d
WS
274}
275
276/* write data */
cdf6ecc5
WS
277static int write_to_device(struct ks_wlan_private *priv, unsigned char *buffer,
278 unsigned long size)
13a9930d 279{
13a9930d
WS
280 unsigned char rw_data;
281 struct hostif_hdr *hdr;
aa6ca807 282 int rc;
697f9f7f 283
13a9930d 284 hdr = (struct hostif_hdr *)buffer;
13a9930d 285
cdf6ecc5
WS
286 DPRINTK(4, "size=%d\n", hdr->size);
287 if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) {
288 DPRINTK(1, "unknown event=%04X\n", hdr->event);
13a9930d
WS
289 return 0;
290 }
291
aa6ca807
TH
292 rc = ks7010_sdio_write(priv, DATA_WINDOW, buffer, size);
293 if (rc) {
294 DPRINTK(1, " write error : retval=%d\n", rc);
295 return rc;
13a9930d
WS
296 }
297
298 rw_data = WRITE_STATUS_BUSY;
aa6ca807
TH
299 rc = ks7010_sdio_write(priv, WRITE_STATUS, &rw_data, sizeof(rw_data));
300 if (rc) {
13a9930d 301 DPRINTK(1, " error : WRITE_STATUS=%02X\n", rw_data);
aa6ca807 302 return rc;
13a9930d
WS
303 }
304
305 return 0;
306}
307
308static void tx_device_task(void *dev)
309{
feedcf1a 310 struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
cdf6ecc5 311 struct tx_device_buffer *sp;
13a9930d
WS
312 int rc = 0;
313
314 DPRINTK(4, "\n");
cdf6ecc5
WS
315 if (cnt_txqbody(priv) > 0
316 && atomic_read(&priv->psstatus.status) != PS_SNOOZE) {
13a9930d 317 sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead];
cdf6ecc5 318 if (priv->dev_state >= DEVICE_STATE_BOOT) {
13a9930d 319 rc = write_to_device(priv, sp->sendp, sp->size);
cdf6ecc5
WS
320 if (rc) {
321 DPRINTK(1, "write_to_device error !!(%d)\n",
322 rc);
323 queue_delayed_work(priv->ks_wlan_hw.
324 ks7010sdio_wq,
325 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d
WS
326 return;
327 }
13a9930d 328 }
cdf6ecc5 329 kfree(sp->sendp); /* allocated memory free */
c7e65f4d 330 if (sp->complete_handler) /* TX Complete */
cdf6ecc5 331 (*sp->complete_handler) (sp->arg1, sp->arg2);
13a9930d
WS
332 inc_txqhead(priv);
333
cdf6ecc5
WS
334 if (cnt_txqbody(priv) > 0) {
335 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
336 &priv->ks_wlan_hw.rw_wq, 0);
13a9930d
WS
337 }
338 }
13a9930d
WS
339}
340
cdf6ecc5 341int ks_wlan_hw_tx(struct ks_wlan_private *priv, void *p, unsigned long size,
71a476e4 342 void (*complete_handler)(void *arg1, void *arg2),
cdf6ecc5 343 void *arg1, void *arg2)
13a9930d 344{
cdf6ecc5 345 int result = 0;
13a9930d 346 struct hostif_hdr *hdr;
697f9f7f 347
13a9930d
WS
348 hdr = (struct hostif_hdr *)p;
349
cdf6ecc5
WS
350 if (hdr->event < HIF_DATA_REQ || HIF_REQ_MAX < hdr->event) {
351 DPRINTK(1, "unknown event=%04X\n", hdr->event);
13a9930d
WS
352 return 0;
353 }
354
355 /* add event to hostt buffer */
356 priv->hostt.buff[priv->hostt.qtail] = hdr->event;
cdf6ecc5 357 priv->hostt.qtail = (priv->hostt.qtail + 1) % SME_EVENT_BUFF_SIZE;
13a9930d 358
cdf6ecc5 359 DPRINTK(4, "event=%04X\n", hdr->event);
13a9930d
WS
360 spin_lock(&priv->tx_dev.tx_dev_lock);
361 result = enqueue_txdev(priv, p, size, complete_handler, arg1, arg2);
362 spin_unlock(&priv->tx_dev.tx_dev_lock);
363
cdf6ecc5
WS
364 if (cnt_txqbody(priv) > 0) {
365 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
366 &priv->ks_wlan_hw.rw_wq, 0);
13a9930d
WS
367 }
368 return result;
369}
370
371static void rx_event_task(unsigned long dev)
372{
cdf6ecc5
WS
373 struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
374 struct rx_device_buffer *rp;
13a9930d 375
cdf6ecc5 376 DPRINTK(4, "\n");
13a9930d 377
cdf6ecc5 378 if (cnt_rxqbody(priv) > 0 && priv->dev_state >= DEVICE_STATE_BOOT) {
13a9930d
WS
379 rp = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qhead];
380 hostif_receive(priv, rp->data, rp->size);
381 inc_rxqhead(priv);
382
53638cef 383 if (cnt_rxqbody(priv) > 0)
13a9930d 384 tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task);
13a9930d 385 }
13a9930d
WS
386}
387
388static void ks_wlan_hw_rx(void *dev, uint16_t size)
389{
feedcf1a 390 struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
13a9930d
WS
391 int retval;
392 struct rx_device_buffer *rx_buffer;
393 struct hostif_hdr *hdr;
cdf6ecc5
WS
394 unsigned char read_status;
395 unsigned short event = 0;
13a9930d 396
cdf6ecc5 397 DPRINTK(4, "\n");
13a9930d
WS
398
399 /* receive data */
cdf6ecc5 400 if (cnt_rxqbody(priv) >= (RX_DEVICE_BUFF_SIZE - 1)) {
13a9930d 401 /* in case of buffer overflow */
71a476e4 402 DPRINTK(1, "rx buffer overflow\n");
13b05e46 403 return;
13a9930d
WS
404 }
405 rx_buffer = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qtail];
406
cdf6ecc5
WS
407 retval =
408 ks7010_sdio_read(priv, DATA_WINDOW, &rx_buffer->data[0],
409 hif_align_size(size));
53638cef 410 if (retval)
13b05e46 411 return;
13a9930d
WS
412
413 /* length check */
cdf6ecc5 414 if (size > 2046 || size == 0) {
3215bb1a
WS
415#ifdef KS_WLAN_DEBUG
416 if (KS_WLAN_DEBUG > 5)
cdf6ecc5
WS
417 print_hex_dump_bytes("INVALID DATA dump: ",
418 DUMP_PREFIX_OFFSET,
3215bb1a
WS
419 rx_buffer->data, 32);
420#endif
13a9930d
WS
421 /* rx_status update */
422 read_status = READ_STATUS_IDLE;
cdf6ecc5
WS
423 retval =
424 ks7010_sdio_write(priv, READ_STATUS, &read_status,
425 sizeof(read_status));
53638cef 426 if (retval)
13a9930d 427 DPRINTK(1, " error : READ_STATUS=%02X\n", read_status);
53638cef 428
13b05e46
TH
429 /* length check fail */
430 return;
13a9930d
WS
431 }
432
433 hdr = (struct hostif_hdr *)&rx_buffer->data[0];
434 rx_buffer->size = le16_to_cpu(hdr->size) + sizeof(hdr->size);
435 event = hdr->event;
436 inc_rxqtail(priv);
437
438 /* read status update */
439 read_status = READ_STATUS_IDLE;
cdf6ecc5
WS
440 retval =
441 ks7010_sdio_write(priv, READ_STATUS, &read_status,
442 sizeof(read_status));
53638cef 443 if (retval)
13a9930d 444 DPRINTK(1, " error : READ_STATUS=%02X\n", read_status);
53638cef 445
13a9930d
WS
446 DPRINTK(4, "READ_STATUS=%02X\n", read_status);
447
cdf6ecc5
WS
448 if (atomic_read(&priv->psstatus.confirm_wait)) {
449 if (IS_HIF_CONF(event)) {
13a9930d
WS
450 DPRINTK(4, "IS_HIF_CONF true !!\n");
451 atomic_dec(&priv->psstatus.confirm_wait);
452 }
453 }
454
455 /* rx_event_task((void *)priv); */
456 tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task);
13a9930d
WS
457}
458
459static void ks7010_rw_function(struct work_struct *work)
460{
461 struct hw_info_t *hw;
462 struct ks_wlan_private *priv;
463 unsigned char rw_data;
464 int retval;
465
466 hw = container_of(work, struct hw_info_t, rw_wq.work);
467 priv = container_of(hw, struct ks_wlan_private, ks_wlan_hw);
468
cdf6ecc5 469 DPRINTK(4, "\n");
13a9930d 470
cdf6ecc5
WS
471 /* wiat after DOZE */
472 if (time_after(priv->last_doze + ((30 * HZ) / 1000), jiffies)) {
c8abeaf8 473 DPRINTK(4, "wait after DOZE\n");
cdf6ecc5
WS
474 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
475 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d
WS
476 return;
477 }
478
479 /* wiat after WAKEUP */
cdf6ecc5 480 while (time_after(priv->last_wakeup + ((30 * HZ) / 1000), jiffies)) {
c8abeaf8 481 DPRINTK(4, "wait after WAKEUP\n");
9887b5e5
SG
482 dev_info(&priv->ks_wlan_hw.sdio_card->func->dev,
483 "wake: %lu %lu\n",
484 priv->last_wakeup + (30 * HZ) / 1000,
485 jiffies);
13a9930d
WS
486 msleep(30);
487 }
488
489 sdio_claim_host(priv->ks_wlan_hw.sdio_card->func);
490
491 /* power save wakeup */
cdf6ecc5
WS
492 if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
493 if (cnt_txqbody(priv) > 0) {
13a9930d 494 ks_wlan_hw_wakeup_request(priv);
cdf6ecc5
WS
495 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
496 &priv->ks_wlan_hw.rw_wq, 1);
13a9930d 497 }
f283dd69 498 goto err_release_host;
13a9930d
WS
499 }
500
501 /* sleep mode doze */
cdf6ecc5 502 if (atomic_read(&priv->sleepstatus.doze_request) == 1) {
13a9930d 503 ks_wlan_hw_sleep_doze_request(priv);
f283dd69 504 goto err_release_host;
13a9930d
WS
505 }
506 /* sleep mode wakeup */
cdf6ecc5 507 if (atomic_read(&priv->sleepstatus.wakeup_request) == 1) {
13a9930d 508 ks_wlan_hw_sleep_wakeup_request(priv);
f283dd69 509 goto err_release_host;
13a9930d
WS
510 }
511
512 /* read (WriteStatus/ReadDataSize FN1:00_0014) */
cdf6ecc5
WS
513 retval =
514 ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data, sizeof(rw_data));
515 if (retval) {
516 DPRINTK(1, " error : WSTATUS_RSIZE=%02X psstatus=%d\n", rw_data,
517 atomic_read(&priv->psstatus.status));
f283dd69 518 goto err_release_host;
13a9930d
WS
519 }
520 DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data);
521
cdf6ecc5
WS
522 if (rw_data & RSIZE_MASK) { /* Read schedule */
523 ks_wlan_hw_rx((void *)priv,
149ad082 524 (uint16_t)((rw_data & RSIZE_MASK) << 4));
13a9930d 525 }
53638cef 526 if ((rw_data & WSTATUS_MASK))
13a9930d 527 tx_device_task((void *)priv);
53638cef 528
13a9930d
WS
529 _ks_wlan_hw_power_save(priv);
530
f283dd69 531err_release_host:
13a9930d 532 sdio_release_host(priv->ks_wlan_hw.sdio_card->func);
13a9930d
WS
533}
534
13a9930d
WS
535static void ks_sdio_interrupt(struct sdio_func *func)
536{
537 int retval;
538 struct ks_sdio_card *card;
feedcf1a 539 struct ks_wlan_private *priv;
13a9930d
WS
540 unsigned char status, rsize, rw_data;
541
542 card = sdio_get_drvdata(func);
543 priv = card->priv;
544 DPRINTK(4, "\n");
545
cdf6ecc5
WS
546 if (priv->dev_state >= DEVICE_STATE_BOOT) {
547 retval =
548 ks7010_sdio_read(priv, INT_PENDING, &status,
549 sizeof(status));
550 if (retval) {
551 DPRINTK(1, "read INT_PENDING Failed!!(%d)\n", retval);
f283dd69 552 goto queue_delayed_work;
13a9930d
WS
553 }
554 DPRINTK(4, "INT_PENDING=%02X\n", rw_data);
555
556 /* schedule task for interrupt status */
557 /* bit7 -> Write General Communication B register */
558 /* read (General Communication B register) */
559 /* bit5 -> Write Status Idle */
560 /* bit2 -> Read Status Busy */
cdf6ecc5
WS
561 if (status & INT_GCR_B
562 || atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
563 retval =
564 ks7010_sdio_read(priv, GCR_B, &rw_data,
565 sizeof(rw_data));
566 if (retval) {
13a9930d 567 DPRINTK(1, " error : GCR_B=%02X\n", rw_data);
f283dd69 568 goto queue_delayed_work;
13a9930d
WS
569 }
570 /* DPRINTK(1, "GCR_B=%02X\n", rw_data); */
cdf6ecc5
WS
571 if (rw_data == GCR_B_ACTIVE) {
572 if (atomic_read(&priv->psstatus.status) ==
573 PS_SNOOZE) {
574 atomic_set(&priv->psstatus.status,
575 PS_WAKEUP);
576 priv->wakeup_count = 0;
13a9930d
WS
577 }
578 complete(&priv->psstatus.wakeup_wait);
579 }
13a9930d
WS
580 }
581
cdf6ecc5 582 do {
13a9930d 583 /* read (WriteStatus/ReadDataSize FN1:00_0014) */
cdf6ecc5
WS
584 retval =
585 ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data,
586 sizeof(rw_data));
587 if (retval) {
588 DPRINTK(1, " error : WSTATUS_RSIZE=%02X\n",
589 rw_data);
f283dd69 590 goto queue_delayed_work;
13a9930d
WS
591 }
592 DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data);
cdf6ecc5
WS
593 rsize = rw_data & RSIZE_MASK;
594 if (rsize) { /* Read schedule */
595 ks_wlan_hw_rx((void *)priv,
149ad082 596 (uint16_t)(rsize << 4));
13a9930d 597 }
cdf6ecc5 598 if (rw_data & WSTATUS_MASK) {
6cdd6538
TH
599 if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
600 if (cnt_txqbody(priv)) {
601 ks_wlan_hw_wakeup_request(priv);
602 queue_delayed_work
603 (priv->ks_wlan_hw.
604 ks7010sdio_wq,
605 &priv->ks_wlan_hw.
606 rw_wq, 1);
607 return;
13a9930d 608 }
cdf6ecc5 609 } else {
6cdd6538 610 tx_device_task((void *)priv);
cdf6ecc5 611 }
13a9930d 612 }
cdf6ecc5 613 } while (rsize);
13a9930d
WS
614 }
615
f283dd69 616queue_delayed_work:
cdf6ecc5
WS
617 queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
618 &priv->ks_wlan_hw.rw_wq, 0);
13a9930d
WS
619}
620
cdf6ecc5 621static int trx_device_init(struct ks_wlan_private *priv)
13a9930d
WS
622{
623 /* initialize values (tx) */
20358d13
NR
624 priv->tx_dev.qhead = 0;
625 priv->tx_dev.qtail = 0;
13a9930d
WS
626
627 /* initialize values (rx) */
20358d13
NR
628 priv->rx_dev.qhead = 0;
629 priv->rx_dev.qtail = 0;
13a9930d
WS
630
631 /* initialize spinLock (tx,rx) */
632 spin_lock_init(&priv->tx_dev.tx_dev_lock);
633 spin_lock_init(&priv->rx_dev.rx_dev_lock);
634
cdf6ecc5
WS
635 tasklet_init(&priv->ks_wlan_hw.rx_bh_task, rx_event_task,
636 (unsigned long)priv);
13a9930d
WS
637
638 return 0;
639}
640
cdf6ecc5 641static void trx_device_exit(struct ks_wlan_private *priv)
13a9930d 642{
cdf6ecc5 643 struct tx_device_buffer *sp;
13a9930d
WS
644
645 /* tx buffer clear */
cdf6ecc5 646 while (cnt_txqbody(priv) > 0) {
13a9930d 647 sp = &priv->tx_dev.tx_dev_buff[priv->tx_dev.qhead];
cdf6ecc5 648 kfree(sp->sendp); /* allocated memory free */
c7e65f4d 649 if (sp->complete_handler) /* TX Complete */
cdf6ecc5 650 (*sp->complete_handler) (sp->arg1, sp->arg2);
13a9930d
WS
651 inc_txqhead(priv);
652 }
653
654 tasklet_kill(&priv->ks_wlan_hw.rx_bh_task);
13a9930d 655}
cdf6ecc5 656
feedcf1a 657static int ks7010_sdio_update_index(struct ks_wlan_private *priv, u32 index)
13a9930d 658{
aa6ca807 659 int rc;
13a9930d 660 unsigned char *data_buf;
13a9930d
WS
661
662 data_buf = kmalloc(sizeof(u32), GFP_KERNEL);
aa6ca807
TH
663 if (!data_buf)
664 return -ENOMEM;
13a9930d
WS
665
666 memcpy(data_buf, &index, sizeof(index));
aa6ca807
TH
667 rc = ks7010_sdio_write(priv, WRITE_INDEX, data_buf, sizeof(index));
668 if (rc)
f283dd69 669 goto err_free_data_buf;
13a9930d 670
aa6ca807
TH
671 rc = ks7010_sdio_write(priv, READ_INDEX, data_buf, sizeof(index));
672 if (rc)
f283dd69 673 goto err_free_data_buf;
aa6ca807
TH
674
675 return 0;
676
f283dd69 677err_free_data_buf:
58043f25 678 kfree(data_buf);
aa6ca807 679
13a9930d
WS
680 return rc;
681}
682
0966c755 683#define ROM_BUFF_SIZE (64 * 1024)
feedcf1a 684static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address,
13a9930d
WS
685 unsigned char *data, unsigned int size)
686{
aa6ca807 687 int rc;
13a9930d 688 unsigned char *read_buf;
eeed92c0 689
13a9930d 690 read_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL);
aa6ca807
TH
691 if (!read_buf)
692 return -ENOMEM;
693
694 rc = ks7010_sdio_read(priv, address, read_buf, size);
695 if (rc)
f283dd69 696 goto err_free_read_buf;
13a9930d 697
aa6ca807
TH
698 rc = memcmp(data, read_buf, size);
699 if (rc) {
700 DPRINTK(0, "data compare error (%d)\n", rc);
f283dd69 701 goto err_free_read_buf;
13a9930d 702 }
aa6ca807
TH
703
704 return 0;
705
f283dd69 706err_free_read_buf:
58043f25 707 kfree(read_buf);
aa6ca807 708
13a9930d
WS
709 return rc;
710}
cdf6ecc5 711
c4730a92 712static int ks7010_upload_firmware(struct ks_wlan_private *priv,
cdf6ecc5 713 struct ks_sdio_card *card)
13a9930d 714{
cdf6ecc5
WS
715 unsigned int size, offset, n = 0;
716 unsigned char *rom_buf;
717 unsigned char rw_data = 0;
aa6ca807 718 int rc;
13a9930d
WS
719 int length;
720 const struct firmware *fw_entry = NULL;
13a9930d 721
13a9930d
WS
722 /* buffer allocate */
723 rom_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL);
369e1b69 724 if (!rom_buf)
aa6ca807 725 return -ENOMEM;
13a9930d
WS
726
727 sdio_claim_host(card->func);
728
729 /* Firmware running ? */
aa6ca807 730 rc = ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data));
cdf6ecc5
WS
731 if (rw_data == GCR_A_RUN) {
732 DPRINTK(0, "MAC firmware running ...\n");
aa6ca807 733 goto release_host_and_free;
13a9930d
WS
734 }
735
aa6ca807
TH
736 rc = request_firmware(&fw_entry, ROM_FILE, &priv->ks_wlan_hw.sdio_card->func->dev);
737 if (rc)
738 goto release_host_and_free;
6ee9169b 739
13a9930d 740 length = fw_entry->size;
13a9930d
WS
741
742 /* Load Program */
743 n = 0;
cdf6ecc5
WS
744 do {
745 if (length >= ROM_BUFF_SIZE) {
13a9930d
WS
746 size = ROM_BUFF_SIZE;
747 length = length - ROM_BUFF_SIZE;
cdf6ecc5
WS
748 } else {
749 size = length;
750 length = 0;
13a9930d 751 }
cdf6ecc5
WS
752 DPRINTK(4, "size = %d\n", size);
753 if (size == 0)
754 break;
755 memcpy(rom_buf, fw_entry->data + n, size);
13a9930d
WS
756 /* Update write index */
757 offset = n;
aa6ca807
TH
758 rc = ks7010_sdio_update_index(priv,
759 KS7010_IRAM_ADDRESS + offset);
760 if (rc)
761 goto release_firmware;
13a9930d
WS
762
763 /* Write data */
aa6ca807
TH
764 rc = ks7010_sdio_write(priv, DATA_WINDOW, rom_buf, size);
765 if (rc)
766 goto release_firmware;
13a9930d
WS
767
768 /* compare */
aa6ca807
TH
769 rc = ks7010_sdio_data_compare(priv, DATA_WINDOW, rom_buf, size);
770 if (rc)
771 goto release_firmware;
772
13a9930d
WS
773 n += size;
774
cdf6ecc5 775 } while (size);
13a9930d
WS
776
777 /* Remap request */
778 rw_data = GCR_A_REMAP;
aa6ca807
TH
779 rc = ks7010_sdio_write(priv, GCR_A, &rw_data, sizeof(rw_data));
780 if (rc)
781 goto release_firmware;
782
cdf6ecc5 783 DPRINTK(4, " REMAP Request : GCR_A=%02X\n", rw_data);
13a9930d
WS
784
785 /* Firmware running check */
786 for (n = 0; n < 50; ++n) {
cdf6ecc5 787 mdelay(10); /* wait_ms(10); */
aa6ca807
TH
788 rc = ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data));
789 if (rc)
790 goto release_firmware;
791
cdf6ecc5
WS
792 if (rw_data == GCR_A_RUN)
793 break;
13a9930d 794 }
cdf6ecc5 795 DPRINTK(4, "firmware wakeup (%d)!!!!\n", n);
13a9930d
WS
796 if ((50) <= n) {
797 DPRINTK(1, "firmware can't start\n");
aa6ca807
TH
798 rc = -EIO;
799 goto release_firmware;
13a9930d
WS
800 }
801
802 rc = 0;
803
aa6ca807 804 release_firmware:
13a9930d 805 release_firmware(fw_entry);
aa6ca807 806 release_host_and_free:
13a9930d 807 sdio_release_host(card->func);
58043f25 808 kfree(rom_buf);
aa6ca807 809
13a9930d
WS
810 return rc;
811}
812
e8593a8a 813static void ks7010_card_init(struct ks_wlan_private *priv)
13a9930d 814{
cdf6ecc5 815 DPRINTK(5, "\ncard_init_task()\n");
13a9930d
WS
816
817 /* init_waitqueue_head(&priv->confirm_wait); */
818 init_completion(&priv->confirm_wait);
819
cdf6ecc5 820 DPRINTK(5, "init_completion()\n");
13a9930d
WS
821
822 /* get mac address & firmware version */
823 hostif_sme_enqueue(priv, SME_START);
824
cdf6ecc5 825 DPRINTK(5, "hostif_sme_enqueu()\n");
13a9930d 826
cdf6ecc5
WS
827 if (!wait_for_completion_interruptible_timeout
828 (&priv->confirm_wait, 5 * HZ)) {
829 DPRINTK(1, "wait time out!! SME_START\n");
13a9930d
WS
830 }
831
53638cef 832 if (priv->mac_address_valid && priv->version_size)
13a9930d 833 priv->dev_state = DEVICE_STATE_PREINIT;
53638cef 834
13a9930d
WS
835 hostif_sme_enqueue(priv, SME_GET_EEPROM_CKSUM);
836
837 /* load initial wireless parameter */
838 hostif_sme_enqueue(priv, SME_STOP_REQUEST);
839
840 hostif_sme_enqueue(priv, SME_RTS_THRESHOLD_REQUEST);
841 hostif_sme_enqueue(priv, SME_FRAGMENTATION_THRESHOLD_REQUEST);
842
843 hostif_sme_enqueue(priv, SME_WEP_INDEX_REQUEST);
844 hostif_sme_enqueue(priv, SME_WEP_KEY1_REQUEST);
845 hostif_sme_enqueue(priv, SME_WEP_KEY2_REQUEST);
846 hostif_sme_enqueue(priv, SME_WEP_KEY3_REQUEST);
847 hostif_sme_enqueue(priv, SME_WEP_KEY4_REQUEST);
848
849 hostif_sme_enqueue(priv, SME_WEP_FLAG_REQUEST);
850 hostif_sme_enqueue(priv, SME_RSN_ENABLED_REQUEST);
851 hostif_sme_enqueue(priv, SME_MODE_SET_REQUEST);
852 hostif_sme_enqueue(priv, SME_START_REQUEST);
853
cdf6ecc5
WS
854 if (!wait_for_completion_interruptible_timeout
855 (&priv->confirm_wait, 5 * HZ)) {
856 DPRINTK(1, "wait time out!! wireless parameter set\n");
13a9930d
WS
857 }
858
cdf6ecc5 859 if (priv->dev_state >= DEVICE_STATE_PREINIT) {
13a9930d
WS
860 DPRINTK(1, "DEVICE READY!!\n");
861 priv->dev_state = DEVICE_STATE_READY;
cdf6ecc5
WS
862 } else {
863 DPRINTK(1, "dev_state=%d\n", priv->dev_state);
13a9930d
WS
864 }
865}
866
6ee9169b
WS
867static void ks7010_init_defaults(struct ks_wlan_private *priv)
868{
869 priv->reg.tx_rate = TX_RATE_AUTO;
870 priv->reg.preamble = LONG_PREAMBLE;
871 priv->reg.powermgt = POWMGT_ACTIVE_MODE;
872 priv->reg.scan_type = ACTIVE_SCAN;
873 priv->reg.beacon_lost_count = 20;
874 priv->reg.rts = 2347UL;
875 priv->reg.fragment = 2346UL;
876 priv->reg.phy_type = D_11BG_COMPATIBLE_MODE;
877 priv->reg.cts_mode = CTS_MODE_FALSE;
878 priv->reg.rate_set.body[11] = TX_RATE_54M;
879 priv->reg.rate_set.body[10] = TX_RATE_48M;
880 priv->reg.rate_set.body[9] = TX_RATE_36M;
881 priv->reg.rate_set.body[8] = TX_RATE_18M;
882 priv->reg.rate_set.body[7] = TX_RATE_9M;
883 priv->reg.rate_set.body[6] = TX_RATE_24M | BASIC_RATE;
884 priv->reg.rate_set.body[5] = TX_RATE_12M | BASIC_RATE;
885 priv->reg.rate_set.body[4] = TX_RATE_6M | BASIC_RATE;
886 priv->reg.rate_set.body[3] = TX_RATE_11M | BASIC_RATE;
887 priv->reg.rate_set.body[2] = TX_RATE_5M | BASIC_RATE;
888 priv->reg.rate_set.body[1] = TX_RATE_2M | BASIC_RATE;
889 priv->reg.rate_set.body[0] = TX_RATE_1M | BASIC_RATE;
890 priv->reg.tx_rate = TX_RATE_FULL_AUTO;
891 priv->reg.rate_set.size = 12;
892}
893
c4730a92 894static int ks7010_sdio_probe(struct sdio_func *func,
cdf6ecc5 895 const struct sdio_device_id *device)
13a9930d 896{
feedcf1a 897 struct ks_wlan_private *priv;
13a9930d
WS
898 struct ks_sdio_card *card;
899 struct net_device *netdev;
900 unsigned char rw_data;
2801d7a2 901 int ret;
13a9930d 902
c4730a92 903 DPRINTK(5, "ks7010_sdio_probe()\n");
13a9930d
WS
904
905 priv = NULL;
cdf6ecc5 906 netdev = NULL;
13a9930d 907
f3f2d351 908 /* initialize ks_sdio_card */
2d738bd2 909 card = kzalloc(sizeof(*card), GFP_KERNEL);
13a9930d
WS
910 if (!card)
911 return -ENOMEM;
912
cdf6ecc5 913 card->func = func;
13a9930d
WS
914 spin_lock_init(&card->lock);
915
13a9930d
WS
916 /*** Initialize SDIO ***/
917 sdio_claim_host(func);
918
919 /* bus setting */
920 /* Issue config request to override clock rate */
921
922 /* function blocksize set */
923 ret = sdio_set_block_size(func, KS7010_IO_BLOCK_SIZE);
cdf6ecc5
WS
924 DPRINTK(5, "multi_block=%d sdio_set_block_size()=%d %d\n",
925 func->card->cccr.multi_block, func->cur_blksize, ret);
13a9930d
WS
926
927 /* Allocate the slot current */
928
929 /* function enable */
930 ret = sdio_enable_func(func);
931 DPRINTK(5, "sdio_enable_func() %d\n", ret);
932 if (ret)
f283dd69 933 goto err_free_card;
13a9930d
WS
934
935 /* interrupt disable */
cdf6ecc5 936 sdio_writeb(func, 0, INT_ENABLE, &ret);
13a9930d 937 if (ret)
f283dd69 938 goto err_free_card;
cdf6ecc5 939 sdio_writeb(func, 0xff, INT_PENDING, &ret);
13a9930d 940 if (ret)
f283dd69 941 goto err_disable_func;
13a9930d
WS
942
943 /* setup interrupt handler */
944 ret = sdio_claim_irq(func, ks_sdio_interrupt);
945 if (ret)
f283dd69 946 goto err_disable_func;
13a9930d
WS
947
948 sdio_release_host(func);
949
950 sdio_set_drvdata(func, card);
951
952 DPRINTK(5, "class = 0x%X, vendor = 0x%X, "
cdf6ecc5 953 "device = 0x%X\n", func->class, func->vendor, func->device);
13a9930d
WS
954
955 /* private memory allocate */
956 netdev = alloc_etherdev(sizeof(*priv));
c7e65f4d 957 if (!netdev) {
9887b5e5 958 dev_err(&card->func->dev, "ks7010 : Unable to alloc new net device\n");
f283dd69 959 goto err_release_irq;
13a9930d 960 }
6634cff1 961 if (dev_alloc_name(netdev, "wlan%d") < 0) {
9887b5e5
SG
962 dev_err(&card->func->dev,
963 "ks7010 : Couldn't get name!\n");
f283dd69 964 goto err_free_netdev;
13a9930d
WS
965 }
966
967 priv = netdev_priv(netdev);
968
969 card->priv = priv;
970 SET_NETDEV_DEV(netdev, &card->func->dev); /* for create sysfs symlinks */
971
972 /* private memory initialize */
973 priv->ks_wlan_hw.sdio_card = card;
974 init_completion(&priv->ks_wlan_hw.ks7010_sdio_wait);
975 priv->ks_wlan_hw.read_buf = NULL;
976 priv->ks_wlan_hw.read_buf = kmalloc(RX_DATA_SIZE, GFP_KERNEL);
53638cef 977 if (!priv->ks_wlan_hw.read_buf)
f283dd69 978 goto err_free_netdev;
53638cef 979
13a9930d
WS
980 priv->dev_state = DEVICE_STATE_PREBOOT;
981 priv->net_dev = netdev;
982 priv->firmware_version[0] = '\0';
983 priv->version_size = 0;
984 priv->last_doze = jiffies; /* set current jiffies */
985 priv->last_wakeup = jiffies;
986 memset(&priv->nstats, 0, sizeof(priv->nstats));
987 memset(&priv->wstats, 0, sizeof(priv->wstats));
988
989 /* sleep mode */
cdf6ecc5
WS
990 atomic_set(&priv->sleepstatus.doze_request, 0);
991 atomic_set(&priv->sleepstatus.wakeup_request, 0);
992 atomic_set(&priv->sleepstatus.wakeup_request, 0);
13a9930d
WS
993
994 trx_device_init(priv);
995 hostif_init(priv);
cdf6ecc5 996 ks_wlan_net_start(netdev);
13a9930d 997
6ee9169b 998 ks7010_init_defaults(priv);
13a9930d
WS
999
1000 /* Upload firmware */
c4730a92 1001 ret = ks7010_upload_firmware(priv, card); /* firmware load */
cdf6ecc5 1002 if (ret) {
9887b5e5
SG
1003 dev_err(&card->func->dev,
1004 "ks7010: firmware load failed !! return code = %d\n",
1005 ret);
f283dd69 1006 goto err_free_read_buf;
13a9930d
WS
1007 }
1008
1009 /* interrupt setting */
1010 /* clear Interrupt status write (ARMtoSD_InterruptPending FN1:00_0024) */
1011 rw_data = 0xff;
1012 sdio_claim_host(func);
1013 ret = ks7010_sdio_write(priv, INT_PENDING, &rw_data, sizeof(rw_data));
1014 sdio_release_host(func);
53638cef 1015 if (ret)
13a9930d 1016 DPRINTK(1, " error : INT_PENDING=%02X\n", rw_data);
53638cef 1017
13a9930d
WS
1018 DPRINTK(4, " clear Interrupt : INT_PENDING=%02X\n", rw_data);
1019
13a9930d 1020 /* enable ks7010sdio interrupt (INT_GCR_B|INT_READ_STATUS|INT_WRITE_STATUS) */
cdf6ecc5 1021 rw_data = (INT_GCR_B | INT_READ_STATUS | INT_WRITE_STATUS);
13a9930d
WS
1022 sdio_claim_host(func);
1023 ret = ks7010_sdio_write(priv, INT_ENABLE, &rw_data, sizeof(rw_data));
1024 sdio_release_host(func);
53638cef 1025 if (ret)
f283dd69 1026 DPRINTK(1, " err : INT_ENABLE=%02X\n", rw_data);
53638cef 1027
13a9930d
WS
1028 DPRINTK(4, " enable Interrupt : INT_ENABLE=%02X\n", rw_data);
1029 priv->dev_state = DEVICE_STATE_BOOT;
1030
1031 priv->ks_wlan_hw.ks7010sdio_wq = create_workqueue("ks7010sdio_wq");
cdf6ecc5 1032 if (!priv->ks_wlan_hw.ks7010sdio_wq) {
13a9930d 1033 DPRINTK(1, "create_workqueue failed !!\n");
f283dd69 1034 goto err_free_read_buf;
13a9930d
WS
1035 }
1036
13a9930d 1037 INIT_DELAYED_WORK(&priv->ks_wlan_hw.rw_wq, ks7010_rw_function);
e8593a8a 1038 ks7010_card_init(priv);
13a9930d 1039
3fb54d75
WS
1040 ret = register_netdev(priv->net_dev);
1041 if (ret)
f283dd69 1042 goto err_free_read_buf;
3fb54d75 1043
13a9930d
WS
1044 return 0;
1045
f283dd69 1046 err_free_read_buf:
13a9930d
WS
1047 kfree(priv->ks_wlan_hw.read_buf);
1048 priv->ks_wlan_hw.read_buf = NULL;
f283dd69 1049 err_free_netdev:
13a9930d
WS
1050 free_netdev(priv->net_dev);
1051 card->priv = NULL;
f283dd69 1052 err_release_irq:
13a9930d
WS
1053 sdio_claim_host(func);
1054 sdio_release_irq(func);
f283dd69 1055 err_disable_func:
13a9930d 1056 sdio_disable_func(func);
f283dd69 1057 err_free_card:
13a9930d
WS
1058 sdio_release_host(func);
1059 sdio_set_drvdata(func, NULL);
1060 kfree(card);
2801d7a2 1061
13a9930d
WS
1062 return -ENODEV;
1063}
1064
c4730a92 1065static void ks7010_sdio_remove(struct sdio_func *func)
13a9930d
WS
1066{
1067 int ret;
1068 struct ks_sdio_card *card;
1069 struct ks_wlan_private *priv;
697f9f7f 1070
c4730a92 1071 DPRINTK(1, "ks7010_sdio_remove()\n");
13a9930d
WS
1072
1073 card = sdio_get_drvdata(func);
1074
c7e65f4d 1075 if (!card)
13a9930d
WS
1076 return;
1077
1078 DPRINTK(1, "priv = card->priv\n");
1079 priv = card->priv;
cdf6ecc5 1080 if (priv) {
803394d0
CIK
1081 struct net_device *netdev = priv->net_dev;
1082
13a9930d
WS
1083 ks_wlan_net_stop(netdev);
1084 DPRINTK(1, "ks_wlan_net_stop\n");
1085
1086 /* interrupt disable */
1087 sdio_claim_host(func);
cdf6ecc5
WS
1088 sdio_writeb(func, 0, INT_ENABLE, &ret);
1089 sdio_writeb(func, 0xff, INT_PENDING, &ret);
13a9930d
WS
1090 sdio_release_host(func);
1091 DPRINTK(1, "interrupt disable\n");
1092
1093 /* send stop request to MAC */
1094 {
1095 struct hostif_stop_request_t *pp;
697f9f7f 1096
cbb351cc 1097 pp = kzalloc(hif_align_size(sizeof(*pp)), GFP_KERNEL);
c7e65f4d 1098 if (!pp) {
cdf6ecc5
WS
1099 DPRINTK(3, "allocate memory failed..\n");
1100 return; /* to do goto ni suru */
13a9930d 1101 }
cdf6ecc5
WS
1102 pp->header.size =
1103 cpu_to_le16((uint16_t)
1104 (sizeof(*pp) -
1105 sizeof(pp->header.size)));
ca476515 1106 pp->header.event = cpu_to_le16((uint16_t)HIF_STOP_REQ);
13a9930d
WS
1107
1108 sdio_claim_host(func);
cdf6ecc5
WS
1109 write_to_device(priv, (unsigned char *)pp,
1110 hif_align_size(sizeof(*pp)));
13a9930d
WS
1111 sdio_release_host(func);
1112 kfree(pp);
1113 }
1114 DPRINTK(1, "STOP Req\n");
1115
cdf6ecc5 1116 if (priv->ks_wlan_hw.ks7010sdio_wq) {
13a9930d
WS
1117 flush_workqueue(priv->ks_wlan_hw.ks7010sdio_wq);
1118 destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_wq);
1119 }
cdf6ecc5
WS
1120 DPRINTK(1,
1121 "destroy_workqueue(priv->ks_wlan_hw.ks7010sdio_wq);\n");
13a9930d 1122
13a9930d
WS
1123 hostif_exit(priv);
1124 DPRINTK(1, "hostif_exit\n");
1125
3fb54d75 1126 unregister_netdev(netdev);
13a9930d
WS
1127
1128 trx_device_exit(priv);
58043f25 1129 kfree(priv->ks_wlan_hw.read_buf);
13a9930d
WS
1130 free_netdev(priv->net_dev);
1131 card->priv = NULL;
1132 }
1133
1134 sdio_claim_host(func);
1135 sdio_release_irq(func);
1136 DPRINTK(1, "sdio_release_irq()\n");
1137 sdio_disable_func(func);
1138 DPRINTK(1, "sdio_disable_func()\n");
1139 sdio_release_host(func);
1140
1141 sdio_set_drvdata(func, NULL);
1142
1143 kfree(card);
1144 DPRINTK(1, "kfree()\n");
1145
cdf6ecc5 1146 DPRINTK(5, " Bye !!\n");
13a9930d
WS
1147}
1148
4c0d46d2
WS
1149static struct sdio_driver ks7010_sdio_driver = {
1150 .name = "ks7010_sdio",
1151 .id_table = ks7010_sdio_ids,
1152 .probe = ks7010_sdio_probe,
1153 .remove = ks7010_sdio_remove,
1154};
1155
6b0cb0b0 1156module_driver(ks7010_sdio_driver, sdio_register_driver, sdio_unregister_driver);
e1240140
WS
1157MODULE_AUTHOR("Sang Engineering, Qi-Hardware, KeyStream");
1158MODULE_DESCRIPTION("Driver for KeyStream KS7010 based SDIO cards");
1159MODULE_LICENSE("GPL v2");
1160MODULE_FIRMWARE(ROM_FILE);