Lines Matching +full:dma +full:- +full:safe +full:- +full:map

1 // SPDX-License-Identifier: GPL-2.0-only
7 * Converted to DMA API, added zero-copy buffer handling, and
8 * (from the mac68k project) introduced dhd's support for 16-bit cards.
15 * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
19 * And... partially rewritten again by David Huggins-Daines in order
21 * 16-bit DMA.
23 * (C) 1999 David Huggins-Daines <dhd@debian.org>
28 * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook,
33 * Application Note AN-746, the files "lance.c" and "ibmlana.c". See also
39 static int sonic_debug = -1;
47 lp->msg_enable = netif_msg_init(sonic_debug, 0); in sonic_msg_init()
61 lp->descriptors = in sonic_alloc_descriptors()
62 dma_alloc_coherent(lp->device, in sonic_alloc_descriptors()
64 SONIC_BUS_SCALE(lp->dma_bitmode), in sonic_alloc_descriptors()
65 &lp->descriptors_laddr, GFP_KERNEL); in sonic_alloc_descriptors()
67 if (!lp->descriptors) in sonic_alloc_descriptors()
68 return -ENOMEM; in sonic_alloc_descriptors()
70 lp->cda = lp->descriptors; in sonic_alloc_descriptors()
71 lp->tda = lp->cda + SIZEOF_SONIC_CDA * in sonic_alloc_descriptors()
72 SONIC_BUS_SCALE(lp->dma_bitmode); in sonic_alloc_descriptors()
73 lp->rda = lp->tda + SIZEOF_SONIC_TD * SONIC_NUM_TDS * in sonic_alloc_descriptors()
74 SONIC_BUS_SCALE(lp->dma_bitmode); in sonic_alloc_descriptors()
75 lp->rra = lp->rda + SIZEOF_SONIC_RD * SONIC_NUM_RDS * in sonic_alloc_descriptors()
76 SONIC_BUS_SCALE(lp->dma_bitmode); in sonic_alloc_descriptors()
78 lp->cda_laddr = lp->descriptors_laddr; in sonic_alloc_descriptors()
79 lp->tda_laddr = lp->cda_laddr + SIZEOF_SONIC_CDA * in sonic_alloc_descriptors()
80 SONIC_BUS_SCALE(lp->dma_bitmode); in sonic_alloc_descriptors()
81 lp->rda_laddr = lp->tda_laddr + SIZEOF_SONIC_TD * SONIC_NUM_TDS * in sonic_alloc_descriptors()
82 SONIC_BUS_SCALE(lp->dma_bitmode); in sonic_alloc_descriptors()
83 lp->rra_laddr = lp->rda_laddr + SIZEOF_SONIC_RD * SONIC_NUM_RDS * in sonic_alloc_descriptors()
84 SONIC_BUS_SCALE(lp->dma_bitmode); in sonic_alloc_descriptors()
94 * there is non-reboot way to recover if something goes wrong.
103 spin_lock_init(&lp->lock); in sonic_open()
109 i--; in sonic_open()
110 dev_kfree_skb(lp->rx_skb[i]); in sonic_open()
111 lp->rx_skb[i] = NULL; in sonic_open()
114 dev->name); in sonic_open()
115 return -ENOMEM; in sonic_open()
117 /* align IP header unless DMA requires otherwise */ in sonic_open()
118 if (SONIC_BUS_SCALE(lp->dma_bitmode) == 2) in sonic_open()
120 lp->rx_skb[i] = skb; in sonic_open()
124 dma_addr_t laddr = dma_map_single(lp->device, skb_put(lp->rx_skb[i], SONIC_RBSIZE), in sonic_open()
126 if (dma_mapping_error(lp->device, laddr)) { in sonic_open()
128 i--; in sonic_open()
129 dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE); in sonic_open()
130 lp->rx_laddr[i] = (dma_addr_t)0; in sonic_open()
133 dev_kfree_skb(lp->rx_skb[i]); in sonic_open()
134 lp->rx_skb[i] = NULL; in sonic_open()
136 printk(KERN_ERR "%s: couldn't map rx DMA buffers\n", in sonic_open()
137 dev->name); in sonic_open()
138 return -ENOMEM; in sonic_open()
140 lp->rx_laddr[i] = laddr; in sonic_open()
198 if(lp->tx_laddr[i]) { in sonic_close()
199 dma_unmap_single(lp->device, lp->tx_laddr[i], lp->tx_len[i], DMA_TO_DEVICE); in sonic_close()
200 lp->tx_laddr[i] = (dma_addr_t)0; in sonic_close()
202 if(lp->tx_skb[i]) { in sonic_close()
203 dev_kfree_skb(lp->tx_skb[i]); in sonic_close()
204 lp->tx_skb[i] = NULL; in sonic_close()
210 if(lp->rx_laddr[i]) { in sonic_close()
211 dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE); in sonic_close()
212 lp->rx_laddr[i] = (dma_addr_t)0; in sonic_close()
214 if(lp->rx_skb[i]) { in sonic_close()
215 dev_kfree_skb(lp->rx_skb[i]); in sonic_close()
216 lp->rx_skb[i] = NULL; in sonic_close()
228 * put the Sonic into software-reset mode and in sonic_tx_timeout()
229 * disable all interrupts before releasing DMA buffers in sonic_tx_timeout()
237 /* We could resend the original skbs. Easier to re-initialise. */ in sonic_tx_timeout()
239 if(lp->tx_laddr[i]) { in sonic_tx_timeout()
240 dma_unmap_single(lp->device, lp->tx_laddr[i], lp->tx_len[i], DMA_TO_DEVICE); in sonic_tx_timeout()
241 lp->tx_laddr[i] = (dma_addr_t)0; in sonic_tx_timeout()
243 if(lp->tx_skb[i]) { in sonic_tx_timeout()
244 dev_kfree_skb(lp->tx_skb[i]); in sonic_tx_timeout()
245 lp->tx_skb[i] = NULL; in sonic_tx_timeout()
250 lp->stats.tx_errors++; in sonic_tx_timeout()
283 length = skb->len; in sonic_send_packet()
291 * Map the packet data into the logical DMA address space in sonic_send_packet()
294 laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE); in sonic_send_packet()
295 if (dma_mapping_error(lp->device, laddr)) { in sonic_send_packet()
296 pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name); in sonic_send_packet()
301 spin_lock_irqsave(&lp->lock, flags); in sonic_send_packet()
303 entry = (lp->eol_tx + 1) & SONIC_TDS_MASK; in sonic_send_packet()
314 sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK, ~SONIC_EOL & in sonic_send_packet()
315 sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK)); in sonic_send_packet()
321 lp->tx_len[entry] = length; in sonic_send_packet()
322 lp->tx_laddr[entry] = laddr; in sonic_send_packet()
323 lp->tx_skb[entry] = skb; in sonic_send_packet()
325 lp->eol_tx = entry; in sonic_send_packet()
328 if (lp->tx_skb[entry]) { in sonic_send_packet()
335 spin_unlock_irqrestore(&lp->lock, flags); in sonic_send_packet()
353 * Secondly, it makes sonic_interrupt() re-entrant, as that is required in sonic_interrupt()
356 spin_lock_irqsave(&lp->lock, flags); in sonic_interrupt()
360 spin_unlock_irqrestore(&lp->lock, flags); in sonic_interrupt()
374 int entry = lp->cur_tx; in sonic_interrupt()
383 * { clear, set } => the TD is available for re-use in sonic_interrupt()
388 while (lp->tx_skb[entry] != NULL) { in sonic_interrupt()
393 lp->stats.tx_packets++; in sonic_interrupt()
394 lp->stats.tx_bytes += sonic_tda_get(dev, entry, SONIC_TD_PKTSIZE); in sonic_interrupt()
398 lp->stats.tx_aborted_errors++; in sonic_interrupt()
401 lp->stats.tx_carrier_errors++; in sonic_interrupt()
403 lp->stats.tx_window_errors++; in sonic_interrupt()
405 lp->stats.tx_fifo_errors++; in sonic_interrupt()
409 dev_consume_skb_irq(lp->tx_skb[entry]); in sonic_interrupt()
410 lp->tx_skb[entry] = NULL; in sonic_interrupt()
411 /* and unmap DMA buffer */ in sonic_interrupt()
412 dma_unmap_single(lp->device, lp->tx_laddr[entry], lp->tx_len[entry], DMA_TO_DEVICE); in sonic_interrupt()
413 lp->tx_laddr[entry] = (dma_addr_t)0; in sonic_interrupt()
423 if (freed_some || lp->tx_skb[entry] == NULL) in sonic_interrupt()
425 lp->cur_tx = entry; in sonic_interrupt()
446 lp->stats.rx_frame_errors += 65536; in sonic_interrupt()
448 lp->stats.rx_crc_errors += 65536; in sonic_interrupt()
450 lp->stats.rx_missed_errors += 65536; in sonic_interrupt()
470 dev->name); in sonic_interrupt()
471 /* ... to help debug DMA problems causing endless interrupts. */ in sonic_interrupt()
479 spin_unlock_irqrestore(&lp->lock, flags); in sonic_interrupt()
492 if (addr == lp->rx_laddr[i]) in index_from_addr()
496 return -ENOENT; in index_from_addr()
499 /* Allocate and map a new skb to be used as a receive buffer. */
507 if (SONIC_BUS_SCALE(lp->dma_bitmode) == 2) in sonic_alloc_rb()
510 *new_addr = dma_map_single(lp->device, skb_put(*new_skb, SONIC_RBSIZE), in sonic_alloc_rb()
512 if (dma_mapping_error(lp->device, *new_addr)) { in sonic_alloc_rb()
558 int entry = lp->cur_rx; in sonic_rx()
559 int prev_entry = lp->eol_rx; in sonic_rx()
580 struct sk_buff *used_skb = lp->rx_skb[i]; in sonic_rx()
584 dma_unmap_single(lp->device, addr, SONIC_RBSIZE, in sonic_rx()
590 used_skb->protocol = eth_type_trans(used_skb, in sonic_rx()
593 lp->stats.rx_packets++; in sonic_rx()
594 lp->stats.rx_bytes += pkt_len; in sonic_rx()
596 lp->rx_skb[i] = new_skb; in sonic_rx()
597 lp->rx_laddr[i] = new_laddr; in sonic_rx()
599 /* Failed to obtain a new buffer so re-use it */ in sonic_rx()
601 lp->stats.rx_dropped++; in sonic_rx()
604 * it's safe to clear RBE after processing this packet. in sonic_rx()
619 lp->cur_rx = entry; in sonic_rx()
621 if (prev_entry != lp->eol_rx) { in sonic_rx()
625 sonic_rda_put(dev, lp->eol_rx, SONIC_RD_LINK, ~SONIC_EOL & in sonic_rx()
626 sonic_rda_get(dev, lp->eol_rx, SONIC_RD_LINK)); in sonic_rx()
627 lp->eol_rx = prev_entry; in sonic_rx()
644 lp->stats.rx_crc_errors += SONIC_READ(SONIC_CRCT); in sonic_get_stats()
646 lp->stats.rx_frame_errors += SONIC_READ(SONIC_FAET); in sonic_get_stats()
648 lp->stats.rx_missed_errors += SONIC_READ(SONIC_MPT); in sonic_get_stats()
651 return &lp->stats; in sonic_get_stats()
669 if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ in sonic_multicast_list()
672 if ((dev->flags & IFF_ALLMULTI) || in sonic_multicast_list()
683 addr = ha->addr; in sonic_multicast_list()
691 SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff); in sonic_multicast_list()
694 spin_lock_irqsave(&lp->lock, flags); in sonic_multicast_list()
698 spin_unlock_irqrestore(&lp->lock, flags); in sonic_multicast_list()
717 * put the Sonic into software-reset mode and in sonic_init()
742 u16 bufadr_l = (unsigned long)lp->rx_laddr[i] & 0xffff; in sonic_init()
743 u16 bufadr_h = (unsigned long)lp->rx_laddr[i] >> 16; in sonic_init()
754 SONIC_WRITE(SONIC_RWP, sonic_rr_addr(dev, SONIC_NUM_RRS - 1)); in sonic_init()
755 SONIC_WRITE(SONIC_URRA, lp->rra_laddr >> 16); in sonic_init()
756 SONIC_WRITE(SONIC_EOBC, (SONIC_RBSIZE >> 1) - (lp->dma_bitmode ? 2 : 1)); in sonic_init()
780 lp->rda_laddr + in sonic_init()
781 ((i+1) * SIZEOF_SONIC_RD * SONIC_BUS_SCALE(lp->dma_bitmode))); in sonic_init()
784 sonic_rda_put(dev, SONIC_NUM_RDS - 1, SONIC_RD_LINK, in sonic_init()
785 (lp->rda_laddr & 0xffff) | SONIC_EOL); in sonic_init()
786 lp->eol_rx = SONIC_NUM_RDS - 1; in sonic_init()
787 lp->cur_rx = 0; in sonic_init()
788 SONIC_WRITE(SONIC_URDA, lp->rda_laddr >> 16); in sonic_init()
789 SONIC_WRITE(SONIC_CRDA, lp->rda_laddr & 0xffff); in sonic_init()
803 (lp->tda_laddr & 0xffff) + in sonic_init()
804 (i + 1) * SIZEOF_SONIC_TD * SONIC_BUS_SCALE(lp->dma_bitmode)); in sonic_init()
805 lp->tx_skb[i] = NULL; in sonic_init()
808 sonic_tda_put(dev, SONIC_NUM_TDS - 1, SONIC_TD_LINK, in sonic_init()
809 (lp->tda_laddr & 0xffff)); in sonic_init()
811 SONIC_WRITE(SONIC_UTDA, lp->tda_laddr >> 16); in sonic_init()
812 SONIC_WRITE(SONIC_CTDA, lp->tda_laddr & 0xffff); in sonic_init()
813 lp->cur_tx = 0; in sonic_init()
814 lp->eol_tx = SONIC_NUM_TDS - 1; in sonic_init()
819 sonic_cda_put(dev, 0, SONIC_CD_CAP0, dev->dev_addr[1] << 8 | dev->dev_addr[0]); in sonic_init()
820 sonic_cda_put(dev, 0, SONIC_CD_CAP1, dev->dev_addr[3] << 8 | dev->dev_addr[2]); in sonic_init()
821 sonic_cda_put(dev, 0, SONIC_CD_CAP2, dev->dev_addr[5] << 8 | dev->dev_addr[4]); in sonic_init()
830 SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff); in sonic_init()