Lines Matching +full:tx +full:- +full:buffer +full:- +full:descriptors
6 * SPDX-License-Identifier: Apache-2.0
27 * This driver references network data fragments with a zero-copy approach.
30 * and subsequent fragments have to be buswidth-aligned anyway.
38 /* size of pre-allocated packet fragments */
42 * Grace period to wait for TX descriptor/fragment availability.
51 #define DEC_WRAP(idx, size) ({ idx = (idx + size - 1) % size; })
59 #define TXDESC_PHYS_H(idx) hi32(p->tx_descs_phys + (idx) * sizeof(struct dwmac_dma_desc))
60 #define TXDESC_PHYS_L(idx) lo32(p->tx_descs_phys + (idx) * sizeof(struct dwmac_dma_desc))
61 #define RXDESC_PHYS_H(idx) hi32(p->rx_descs_phys + (idx) * sizeof(struct dwmac_dma_desc))
62 #define RXDESC_PHYS_L(idx) lo32(p->rx_descs_phys + (idx) * sizeof(struct dwmac_dma_desc))
64 #define TXDESC_PHYS_H(idx) phys_hi32(&p->tx_descs[idx])
65 #define TXDESC_PHYS_L(idx) phys_lo32(&p->tx_descs[idx])
66 #define RXDESC_PHYS_H(idx) phys_hi32(&p->rx_descs[idx])
67 #define RXDESC_PHYS_L(idx) phys_lo32(&p->rx_descs[idx])
72 /* trickery to avoid compiler warnings on 32-bit build targets */ in hi32()
101 struct dwmac_priv *p = dev->data; in dwmac_caps()
104 if (p->feature0 & MAC_HW_FEATURE0_GMIISEL) { in dwmac_caps()
108 if (p->feature0 & MAC_HW_FEATURE0_MIISEL) { in dwmac_caps()
123 for (frag = pkt->buffer; frag; frag = frag->frags) { in net_pkt_get_nbfrags()
131 struct dwmac_priv *p = dev->data; in dwmac_send()
145 d_idx = p->tx_desc_head; in dwmac_send()
146 frag = pkt->buffer; in dwmac_send()
149 k_sem_count_get(&p->free_tx_descs), in dwmac_send()
150 p->tx_desc_head, p->tx_desc_tail); in dwmac_send()
153 if (k_sem_take(&p->free_tx_descs, TX_AVAIL_WAIT) != 0) { in dwmac_send()
154 LOG_DBG("no more free tx descriptors"); in dwmac_send()
162 k_sem_give(&p->free_tx_descs); in dwmac_send()
165 sys_cache_data_flush_range(pinned->data, pinned->len); in dwmac_send()
166 p->tx_frags[d_idx] = pinned; in dwmac_send()
168 frag->data, pinned->data, pinned->len); in dwmac_send()
171 if (!frag->frags) { in dwmac_send()
178 d = &p->tx_descs[d_idx]; in dwmac_send()
179 d->des0 = phys_lo32(pinned->data); in dwmac_send()
180 d->des1 = phys_hi32(pinned->data); in dwmac_send()
181 d->des2 = pinned->len | des2_flags; in dwmac_send()
182 d->des3 = pkt_len | des3_flags; in dwmac_send()
184 /* clear the FD flag on subsequent descriptors */ in dwmac_send()
188 frag = frag->frags; in dwmac_send()
195 p->tx_desc_head = d_idx; in dwmac_send()
203 while (d_idx != p->tx_desc_head) { in dwmac_send()
206 frag = p->tx_frags[d_idx]; in dwmac_send()
208 k_sem_give(&p->free_tx_descs); in dwmac_send()
210 return -ENOMEM; in dwmac_send()
220 for (d_idx = p->tx_desc_tail; in dwmac_tx_release()
221 d_idx != p->tx_desc_head; in dwmac_tx_release()
222 INC_WRAP(d_idx, NB_TX_DESCS), k_sem_give(&p->free_tx_descs)) { in dwmac_tx_release()
225 k_sem_count_get(&p->free_tx_descs), in dwmac_tx_release()
226 p->tx_desc_tail, p->tx_desc_head); in dwmac_tx_release()
228 d = &p->tx_descs[d_idx]; in dwmac_tx_release()
229 des3_val = d->des3; in dwmac_tx_release()
238 frag = p->tx_frags[d_idx]; in dwmac_tx_release()
239 LOG_DBG("unref frag %p", frag->data); in dwmac_tx_release()
246 LOG_ERR("tx error (DES3 = 0x%08x)", des3_val); in dwmac_tx_release()
247 eth_stats_update_errors_tx(p->iface); in dwmac_tx_release()
251 p->tx_desc_tail = d_idx; in dwmac_tx_release()
261 for (d_idx = p->rx_desc_tail; in dwmac_receive()
262 d_idx != p->rx_desc_head; in dwmac_receive()
263 INC_WRAP(d_idx, NB_RX_DESCS), k_sem_give(&p->free_rx_descs)) { in dwmac_receive()
266 k_sem_count_get(&p->free_rx_descs), in dwmac_receive()
267 d_idx, p->rx_desc_head); in dwmac_receive()
269 d = &p->rx_descs[d_idx]; in dwmac_receive()
270 des3_val = d->des3; in dwmac_receive()
285 p->rx_bytes = 0; in dwmac_receive()
286 if (p->rx_pkt) { in dwmac_receive()
288 eth_stats_update_errors_rx(p->iface); in dwmac_receive()
289 net_pkt_unref(p->rx_pkt); in dwmac_receive()
291 p->rx_pkt = net_pkt_rx_alloc_on_iface(p->iface, K_NO_WAIT); in dwmac_receive()
292 if (!p->rx_pkt) { in dwmac_receive()
294 eth_stats_update_errors_rx(p->iface); in dwmac_receive()
298 if (!p->rx_pkt) { in dwmac_receive()
304 frag = p->rx_frags[d_idx]; in dwmac_receive()
305 p->rx_frags[d_idx] = NULL; in dwmac_receive()
307 frag->len = bytes_so_far - p->rx_bytes; in dwmac_receive()
308 p->rx_bytes = bytes_so_far; in dwmac_receive()
309 net_pkt_frag_add(p->rx_pkt, frag); in dwmac_receive()
316 net_pkt_get_len(p->rx_pkt), in dwmac_receive()
317 net_pkt_get_nbfrags(p->rx_pkt)); in dwmac_receive()
318 net_recv_data(p->iface, p->rx_pkt); in dwmac_receive()
321 eth_stats_update_errors_rx(p->iface); in dwmac_receive()
322 net_pkt_unref(p->rx_pkt); in dwmac_receive()
324 p->rx_pkt = NULL; in dwmac_receive()
327 p->rx_desc_tail = d_idx; in dwmac_receive()
340 d_idx = p->rx_desc_head; in dwmac_rx_refill_thread()
343 k_sem_count_get(&p->free_rx_descs), in dwmac_rx_refill_thread()
344 p->rx_desc_head, p->rx_desc_tail); in dwmac_rx_refill_thread()
347 if (k_sem_take(&p->free_rx_descs, K_FOREVER) != 0) { in dwmac_rx_refill_thread()
352 d = &p->rx_descs[d_idx]; in dwmac_rx_refill_thread()
354 __ASSERT(!(d->des3 & RDES3_OWN), in dwmac_rx_refill_thread()
356 d_idx, d->des3, k_sem_count_get(&p->free_rx_descs), in dwmac_rx_refill_thread()
357 p->rx_desc_head, p->rx_desc_tail); in dwmac_rx_refill_thread()
359 frag = p->rx_frags[d_idx]; in dwmac_rx_refill_thread()
366 k_sem_give(&p->free_rx_descs); in dwmac_rx_refill_thread()
369 LOG_DBG("new frag[%d] at %p", d_idx, frag->data); in dwmac_rx_refill_thread()
370 __ASSERT(frag->size == RX_FRAG_SIZE, ""); in dwmac_rx_refill_thread()
371 sys_cache_data_invd_range(frag->data, frag->size); in dwmac_rx_refill_thread()
372 p->rx_frags[d_idx] = frag; in dwmac_rx_refill_thread()
374 LOG_DBG("reusing frag[%d] at %p", d_idx, frag->data); in dwmac_rx_refill_thread()
378 d->des0 = phys_lo32(frag->data); in dwmac_rx_refill_thread()
379 d->des1 = phys_hi32(frag->data); in dwmac_rx_refill_thread()
380 d->des2 = 0; in dwmac_rx_refill_thread()
381 d->des3 = RDES3_BUF1V | RDES3_IOC | RDES3_OWN; in dwmac_rx_refill_thread()
387 p->rx_desc_head = INC_WRAP(d_idx, NB_RX_DESCS); in dwmac_rx_refill_thread()
437 struct dwmac_priv *p = ddev->data; in dwmac_isr()
445 ch = find_lsb_set(irq_status & 0xff) - 1; in dwmac_isr()
473 struct dwmac_priv *p = dev->data; in dwmac_set_config()
481 memcpy(p->mac_addr, config->mac_address.addr, sizeof(p->mac_addr)); in dwmac_set_config()
482 dwmac_set_mac_addr(p, p->mac_addr, 0); in dwmac_set_config()
483 net_if_set_link_addr(p->iface, p->mac_addr, in dwmac_set_config()
484 sizeof(p->mac_addr), NET_LINK_ETHERNET); in dwmac_set_config()
490 if (config->promisc_mode && in dwmac_set_config()
494 } else if (!config->promisc_mode && in dwmac_set_config()
499 ret = -EALREADY; in dwmac_set_config()
505 ret = -ENOTSUP; in dwmac_set_config()
514 struct dwmac_priv *p = net_if_get_device(iface)->data; in dwmac_iface_init()
517 __ASSERT(!p->iface, "interface already initialized?"); in dwmac_iface_init()
518 p->iface = iface; in dwmac_iface_init()
522 net_if_set_link_addr(iface, p->mac_addr, sizeof(p->mac_addr), in dwmac_iface_init()
524 dwmac_set_mac_addr(p, p->mac_addr, 0); in dwmac_iface_init()
527 * Semaphores are used to represent number of available descriptors. in dwmac_iface_init()
533 k_sem_init(&p->free_tx_descs, NB_TX_DESCS - 1, NB_TX_DESCS - 1); in dwmac_iface_init()
534 k_sem_init(&p->free_rx_descs, NB_RX_DESCS - 1, NB_RX_DESCS - 1); in dwmac_iface_init()
536 /* set up RX buffer refill thread */ in dwmac_iface_init()
537 k_thread_create(&p->rx_refill_thread, p->rx_refill_thread_stack, in dwmac_iface_init()
538 K_KERNEL_STACK_SIZEOF(p->rx_refill_thread_stack), in dwmac_iface_init()
541 k_thread_name_set(&p->rx_refill_thread, "dwmac_rx_refill"); in dwmac_iface_init()
543 /* start up TX/RX */ in dwmac_iface_init()
566 struct dwmac_priv *p = dev->data; in dwmac_probe()
579 "This driver expects DWC-ETHERNET version >= 4.00"); in dwmac_probe()
587 return -EIO; in dwmac_probe()
592 p->feature0 = REG_READ(MAC_HW_FEATURE0); in dwmac_probe()
593 p->feature1 = REG_READ(MAC_HW_FEATURE1); in dwmac_probe()
594 p->feature2 = REG_READ(MAC_HW_FEATURE2); in dwmac_probe()
595 p->feature3 = REG_READ(MAC_HW_FEATURE3); in dwmac_probe()
597 p->feature0, p->feature1, p->feature2, p->feature3); in dwmac_probe()
601 memset(p->tx_descs, 0, NB_TX_DESCS * sizeof(struct dwmac_dma_desc)); in dwmac_probe()
602 memset(p->rx_descs, 0, NB_RX_DESCS * sizeof(struct dwmac_dma_desc)); in dwmac_probe()
613 REG_WRITE(DMA_CHn_TXDESC_RING_LENGTH(0), NB_TX_DESCS - 1); in dwmac_probe()
614 REG_WRITE(DMA_CHn_RXDESC_RING_LENGTH(0), NB_RX_DESCS - 1); in dwmac_probe()