]> err.no Git - linux-2.6/blob - drivers/net/wireless/bcm43xx/bcm43xx_pio.c
[PATCH] bcm43xx: Partially fix PIO code. Add Kconfig option for PIO or DMA mode ...
[linux-2.6] / drivers / net / wireless / bcm43xx / bcm43xx_pio.c
1 /*
2
3   Broadcom BCM43xx wireless driver
4
5   PIO Transmission
6
7   Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; see the file COPYING.  If not, write to
21   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22   Boston, MA 02110-1301, USA.
23
24 */
25
26 #include "bcm43xx.h"
27 #include "bcm43xx_pio.h"
28 #include "bcm43xx_main.h"
29
30 #include <linux/delay.h>
31
32
33 static void tx_start(struct bcm43xx_pioqueue *queue)
34 {
35         bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
36                           BCM43xx_PIO_TXCTL_INIT);
37 }
38
39 static void tx_octet(struct bcm43xx_pioqueue *queue,
40                      u8 octet)
41 {
42         if (queue->need_workarounds) {
43                 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
44                                   octet);
45                 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
46                                   BCM43xx_PIO_TXCTL_WRITEHI);
47         } else {
48                 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
49                                   BCM43xx_PIO_TXCTL_WRITEHI);
50                 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
51                                   octet);
52         }
53 }
54
55 static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
56                             const u8 *packet,
57                             unsigned int *pos)
58 {
59         const u8 *source;
60         unsigned int i = *pos;
61         u16 ret;
62
63         if (i < sizeof(*txhdr)) {
64                 source = (const u8 *)txhdr;
65         } else {
66                 source = packet;
67                 i -= sizeof(*txhdr);
68         }
69         ret = le16_to_cpu( *((u16 *)(source + i)) );
70         *pos += 2;
71
72         return ret;
73 }
74
75 static void tx_data(struct bcm43xx_pioqueue *queue,
76                     struct bcm43xx_txhdr *txhdr,
77                     const u8 *packet,
78                     unsigned int octets)
79 {
80         u16 data;
81         unsigned int i = 0;
82
83         if (queue->need_workarounds) {
84                 data = tx_get_next_word(txhdr, packet, &i);
85                 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
86         }
87         bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
88                           BCM43xx_PIO_TXCTL_WRITELO |
89                           BCM43xx_PIO_TXCTL_WRITEHI);
90         while (i < octets - 1) {
91                 data = tx_get_next_word(txhdr, packet, &i);
92                 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
93         }
94         if (octets % 2)
95                 tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]);
96 }
97
98 static void tx_complete(struct bcm43xx_pioqueue *queue,
99                         struct sk_buff *skb)
100 {
101         if (queue->need_workarounds) {
102                 bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
103                                   skb->data[skb->len - 1]);
104                 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
105                                   BCM43xx_PIO_TXCTL_WRITEHI |
106                                   BCM43xx_PIO_TXCTL_COMPLETE);
107         } else {
108                 bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
109                                   BCM43xx_PIO_TXCTL_COMPLETE);
110         }
111 }
112
113 static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
114                            int packetindex)
115 {
116         u16 cookie = 0x0000;
117
118         /* We use the upper 4 bits for the PIO
119          * controller ID and the lower 12 bits
120          * for the packet index (in the cache).
121          */
122         switch (queue->mmio_base) {
123         case BCM43xx_MMIO_PIO1_BASE:
124                 break;
125         case BCM43xx_MMIO_PIO2_BASE:
126                 cookie = 0x1000;
127                 break;
128         case BCM43xx_MMIO_PIO3_BASE:
129                 cookie = 0x2000;
130                 break;
131         case BCM43xx_MMIO_PIO4_BASE:
132                 cookie = 0x3000;
133                 break;
134         default:
135                 assert(0);
136         }
137         assert(((u16)packetindex & 0xF000) == 0x0000);
138         cookie |= (u16)packetindex;
139
140         return cookie;
141 }
142
143 static
144 struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm,
145                                        u16 cookie,
146                                        struct bcm43xx_pio_txpacket **packet)
147 {
148         struct bcm43xx_pio *pio = bcm->current_core->pio;
149         struct bcm43xx_pioqueue *queue = NULL;
150         int packetindex;
151
152         switch (cookie & 0xF000) {
153         case 0x0000:
154                 queue = pio->queue0;
155                 break;
156         case 0x1000:
157                 queue = pio->queue1;
158                 break;
159         case 0x2000:
160                 queue = pio->queue2;
161                 break;
162         case 0x3000:
163                 queue = pio->queue3;
164                 break;
165         default:
166                 assert(0);
167         }
168         packetindex = (cookie & 0x0FFF);
169         assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS);
170         *packet = &(queue->tx_packets_cache[packetindex]);
171
172         return queue;
173 }
174
175 static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
176                                   struct sk_buff *skb,
177                                   struct bcm43xx_pio_txpacket *packet)
178 {
179         struct bcm43xx_txhdr txhdr;
180         unsigned int octets;
181
182         assert(skb_shinfo(skb)->nr_frags == 0);
183         bcm43xx_generate_txhdr(queue->bcm,
184                                &txhdr, skb->data, skb->len,
185                                (packet->xmitted_frags == 0),
186                                generate_cookie(queue, pio_txpacket_getindex(packet)));
187
188         tx_start(queue);
189         octets = skb->len + sizeof(txhdr);
190         if (queue->need_workarounds)
191                 octets--;
192         tx_data(queue, &txhdr, (u8 *)skb->data, octets);
193         tx_complete(queue, skb);
194 }
195
196 static void free_txpacket(struct bcm43xx_pio_txpacket *packet,
197                           int irq_context)
198 {
199         struct bcm43xx_pioqueue *queue = packet->queue;
200
201         ieee80211_txb_free(packet->txb);
202         list_move(&packet->list, &queue->txfree);
203         queue->nr_txfree++;
204
205         assert(queue->tx_devq_used >= packet->xmitted_octets);
206         assert(queue->tx_devq_packets >= packet->xmitted_frags);
207         queue->tx_devq_used -= packet->xmitted_octets;
208         queue->tx_devq_packets -= packet->xmitted_frags;
209 }
210
211 static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
212 {
213         struct bcm43xx_pioqueue *queue = packet->queue;
214         struct ieee80211_txb *txb = packet->txb;
215         struct sk_buff *skb;
216         u16 octets;
217         int i;
218
219         for (i = packet->xmitted_frags; i < txb->nr_frags; i++) {
220                 skb = txb->fragments[i];
221
222                 octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
223                 assert(queue->tx_devq_size >= octets);
224                 assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS);
225                 assert(queue->tx_devq_used <= queue->tx_devq_size);
226                 /* Check if there is sufficient free space on the device
227                  * TX queue. If not, return and let the TX tasklet
228                  * retry later.
229                  */
230                 if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS)
231                         return -EBUSY;
232                 if (queue->tx_devq_used + octets > queue->tx_devq_size)
233                         return -EBUSY;
234                 /* Now poke the device. */
235                 pio_tx_write_fragment(queue, skb, packet);
236
237                 /* Account for the packet size.
238                  * (We must not overflow the device TX queue)
239                  */
240                 queue->tx_devq_packets++;
241                 queue->tx_devq_used += octets;
242
243                 assert(packet->xmitted_frags <= packet->txb->nr_frags);
244                 packet->xmitted_frags++;
245                 packet->xmitted_octets += octets;
246         }
247         list_move_tail(&packet->list, &queue->txrunning);
248
249         return 0;
250 }
251
252 static void tx_tasklet(unsigned long d)
253 {
254         struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d;
255         struct bcm43xx_private *bcm = queue->bcm;
256         unsigned long flags;
257         struct bcm43xx_pio_txpacket *packet, *tmp_packet;
258         int err;
259
260         spin_lock_irqsave(&bcm->lock, flags);
261         list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
262                 assert(packet->xmitted_frags < packet->txb->nr_frags);
263                 if (packet->xmitted_frags == 0) {
264                         int i;
265                         struct sk_buff *skb;
266
267                         /* Check if the device queue is big
268                          * enough for every fragment. If not, drop the
269                          * whole packet.
270                          */
271                         for (i = 0; i < packet->txb->nr_frags; i++) {
272                                 skb = packet->txb->fragments[i];
273                                 if (unlikely(skb->len > queue->tx_devq_size)) {
274                                         dprintkl(KERN_ERR PFX "PIO TX device queue too small. "
275                                                               "Dropping packet.\n");
276                                         free_txpacket(packet, 1);
277                                         goto next_packet;
278                                 }
279                         }
280                 }
281                 /* Try to transmit the packet.
282                  * This may not completely succeed.
283                  */
284                 err = pio_tx_packet(packet);
285                 if (err)
286                         break;
287         next_packet:
288                 continue;
289         }
290         spin_unlock_irqrestore(&bcm->lock, flags);
291 }
292
293 static void setup_txqueues(struct bcm43xx_pioqueue *queue)
294 {
295         struct bcm43xx_pio_txpacket *packet;
296         int i;
297
298         queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS;
299         for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) {
300                 packet = &(queue->tx_packets_cache[i]);
301
302                 packet->queue = queue;
303                 INIT_LIST_HEAD(&packet->list);
304
305                 list_add(&packet->list, &queue->txfree);
306         }
307 }
308
309 static
310 struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
311                                                  u16 pio_mmio_base)
312 {
313         struct bcm43xx_pioqueue *queue;
314         u32 value;
315         u16 qsize;
316
317         queue = kzalloc(sizeof(*queue), GFP_KERNEL);
318         if (!queue)
319                 goto out;
320
321         queue->bcm = bcm;
322         queue->mmio_base = pio_mmio_base;
323         queue->need_workarounds = (bcm->current_core->rev < 3);
324
325         INIT_LIST_HEAD(&queue->txfree);
326         INIT_LIST_HEAD(&queue->txqueue);
327         INIT_LIST_HEAD(&queue->txrunning);
328         tasklet_init(&queue->txtask, tx_tasklet,
329                      (unsigned long)queue);
330
331         value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
332         value |= BCM43xx_SBF_XFER_REG_BYTESWAP;
333         bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
334
335         qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
336         if (qsize <= BCM43xx_PIO_TXQADJUST) {
337                 printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize);
338                 goto err_freequeue;
339         }
340         qsize -= BCM43xx_PIO_TXQADJUST;
341         queue->tx_devq_size = qsize;
342
343         setup_txqueues(queue);
344
345 out:
346         return queue;
347
348 err_freequeue:
349         kfree(queue);
350         queue = NULL;
351         goto out;
352 }
353
354 static void cancel_transfers(struct bcm43xx_pioqueue *queue)
355 {
356         struct bcm43xx_pio_txpacket *packet, *tmp_packet;
357
358         netif_tx_disable(queue->bcm->net_dev);
359         assert(queue->bcm->shutting_down);
360         tasklet_disable(&queue->txtask);
361
362         list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
363                 free_txpacket(packet, 0);
364         list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
365                 free_txpacket(packet, 0);
366 }
367
368 static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
369 {
370         if (!queue)
371                 return;
372
373         cancel_transfers(queue);
374         kfree(queue);
375 }
376
377 void bcm43xx_pio_free(struct bcm43xx_private *bcm)
378 {
379         struct bcm43xx_pio *pio = bcm->current_core->pio;
380
381         bcm43xx_destroy_pioqueue(pio->queue3);
382         pio->queue3 = NULL;
383         bcm43xx_destroy_pioqueue(pio->queue2);
384         pio->queue2 = NULL;
385         bcm43xx_destroy_pioqueue(pio->queue1);
386         pio->queue1 = NULL;
387         bcm43xx_destroy_pioqueue(pio->queue0);
388         pio->queue0 = NULL;
389 }
390
391 int bcm43xx_pio_init(struct bcm43xx_private *bcm)
392 {
393         struct bcm43xx_pio *pio = bcm->current_core->pio;
394         struct bcm43xx_pioqueue *queue;
395         int err = -ENOMEM;
396
397         queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE);
398         if (!queue)
399                 goto out;
400         pio->queue0 = queue;
401
402         queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE);
403         if (!queue)
404                 goto err_destroy0;
405         pio->queue1 = queue;
406
407         queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE);
408         if (!queue)
409                 goto err_destroy1;
410         pio->queue2 = queue;
411
412         queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE);
413         if (!queue)
414                 goto err_destroy2;
415         pio->queue3 = queue;
416
417         if (bcm->current_core->rev < 3)
418                 bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
419
420         dprintk(KERN_INFO PFX "PIO initialized\n");
421         err = 0;
422 out:
423         return err;
424
425 err_destroy2:
426         bcm43xx_destroy_pioqueue(pio->queue2);
427         pio->queue2 = NULL;
428 err_destroy1:
429         bcm43xx_destroy_pioqueue(pio->queue1);
430         pio->queue1 = NULL;
431 err_destroy0:
432         bcm43xx_destroy_pioqueue(pio->queue0);
433         pio->queue0 = NULL;
434         goto out;
435 }
436
437 int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
438                    struct ieee80211_txb *txb)
439 {
440         struct bcm43xx_pioqueue *queue = bcm->current_core->pio->queue1;
441         struct bcm43xx_pio_txpacket *packet;
442         u16 tmp;
443
444         assert(!queue->tx_suspended);
445         assert(!list_empty(&queue->txfree));
446
447         tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
448         if (tmp & BCM43xx_PIO_TXCTL_SUSPEND)
449                 return -EBUSY;
450
451         packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
452         packet->txb = txb;
453         packet->xmitted_frags = 0;
454         packet->xmitted_octets = 0;
455         list_move_tail(&packet->list, &queue->txqueue);
456         queue->nr_txfree--;
457         assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
458
459         /* Suspend TX, if we are out of packets in the "free" queue. */
460         if (unlikely(list_empty(&queue->txfree))) {
461                 netif_stop_queue(queue->bcm->net_dev);
462                 queue->tx_suspended = 1;
463         }
464
465         tasklet_schedule(&queue->txtask);
466
467         return 0;
468 }
469
470 void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
471                                    struct bcm43xx_xmitstatus *status)
472 {
473         struct bcm43xx_pioqueue *queue;
474         struct bcm43xx_pio_txpacket *packet;
475
476         queue = parse_cookie(bcm, status->cookie, &packet);
477         assert(queue);
478 //TODO
479 if (!queue)
480 return;
481         free_txpacket(packet, 1);
482         if (unlikely(queue->tx_suspended)) {
483                 queue->tx_suspended = 0;
484                 netif_wake_queue(queue->bcm->net_dev);
485         }
486         /* If there are packets on the txqueue, poke the tasklet. */
487         if (!list_empty(&queue->txqueue))
488                 tasklet_schedule(&queue->txtask);
489 }
490
491 static void pio_rx_error(struct bcm43xx_pioqueue *queue,
492                          int clear_buffers,
493                          const char *error)
494 {
495         int i;
496
497         printkl("PIO RX error: %s\n", error);
498         bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
499                           BCM43xx_PIO_RXCTL_READY);
500         if (clear_buffers) {
501                 assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE);
502                 for (i = 0; i < 15; i++) {
503                         /* Dummy read. */
504                         bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
505                 }
506         }
507 }
508
509 void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
510 {
511         u16 preamble[21] = { 0 };
512         struct bcm43xx_rxhdr *rxhdr;
513         u16 tmp, len, rxflags2;
514         int i, preamble_readwords;
515         struct sk_buff *skb;
516
517 return;
518         tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
519         if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) {
520                 dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk.
521                 return;
522         }
523         bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
524                           BCM43xx_PIO_RXCTL_DATAAVAILABLE);
525
526         for (i = 0; i < 10; i++) {
527                 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
528                 if (tmp & BCM43xx_PIO_RXCTL_READY)
529                         goto data_ready;
530                 udelay(10);
531         }
532         dprintkl(KERN_ERR PFX "PIO RX timed out\n");
533         return;
534 data_ready:
535
536 //FIXME: endianess in this function.
537         len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
538         if (unlikely(len > 0x700)) {
539                 pio_rx_error(queue, 0, "len > 0x700");
540                 return;
541         }
542         if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) {
543                 pio_rx_error(queue, 0, "len == 0");
544                 return;
545         }
546         preamble[0] = cpu_to_le16(len);
547         if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE)
548                 preamble_readwords = 14 / sizeof(u16);
549         else
550                 preamble_readwords = 18 / sizeof(u16);
551         for (i = 0; i < preamble_readwords; i++) {
552                 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
553                 preamble[i + 1] = cpu_to_be16(tmp);//FIXME?
554         }
555         rxhdr = (struct bcm43xx_rxhdr *)preamble;
556         rxflags2 = le16_to_cpu(rxhdr->flags2);
557         if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) {
558                 pio_rx_error(queue,
559                              (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE),
560                              "invalid frame");
561                 return;
562         }
563         if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) {
564                 /* We received an xmit status. */
565                 struct bcm43xx_hwxmitstatus *hw;
566                 struct bcm43xx_xmitstatus stat;
567
568                 hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1);
569                 stat.cookie = le16_to_cpu(hw->cookie);
570                 stat.flags = hw->flags;
571                 stat.cnt1 = hw->cnt1;
572                 stat.cnt2 = hw->cnt2;
573                 stat.seq = le16_to_cpu(hw->seq);
574                 stat.unknown = le16_to_cpu(hw->unknown);
575
576                 bcm43xx_debugfs_log_txstat(queue->bcm, &stat);
577                 bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat);
578
579                 return;
580         }
581
582         skb = dev_alloc_skb(len);
583         if (unlikely(!skb)) {
584                 pio_rx_error(queue, 1, "OOM");
585                 return;
586         }
587         skb_put(skb, len);
588         for (i = 0; i < len - 1; i += 2) {
589                 tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
590                 *((u16 *)(skb->data + i)) = tmp;
591         }
592         if (len % 2) {
593                 tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
594                 skb->data[len - 1] = (tmp & 0x00FF);
595                 if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
596                         skb->data[0x20] = (tmp & 0xFF00) >> 8;
597                 else
598                         skb->data[0x1E] = (tmp & 0xFF00) >> 8;
599         }
600         bcm43xx_rx(queue->bcm, skb, rxhdr);
601 }
602
603 /* vim: set ts=8 sw=8 sts=8: */