Lines Matching +full:mbi +full:- +full:ranges

1 // SPDX-License-Identifier: GPL-2.0-only
41 struct airoha_qdma *qdma = irq_bank->qdma; in airoha_qdma_set_irqmask()
42 int bank = irq_bank - &qdma->irq_banks[0]; in airoha_qdma_set_irqmask()
45 if (WARN_ON_ONCE(index >= ARRAY_SIZE(irq_bank->irqmask))) in airoha_qdma_set_irqmask()
48 spin_lock_irqsave(&irq_bank->irq_lock, flags); in airoha_qdma_set_irqmask()
50 irq_bank->irqmask[index] &= ~clear; in airoha_qdma_set_irqmask()
51 irq_bank->irqmask[index] |= set; in airoha_qdma_set_irqmask()
53 irq_bank->irqmask[index]); in airoha_qdma_set_irqmask()
59 spin_unlock_irqrestore(&irq_bank->irq_lock, flags); in airoha_qdma_set_irqmask()
76 struct airoha_eth *eth = port->qdma->eth; in airoha_set_macaddr()
107 struct airoha_eth *eth = port->qdma->eth; in airoha_set_vip_for_gdm_port()
110 switch (port->id) { in airoha_set_vip_for_gdm_port()
138 for (p = 1; p <= ARRAY_SIZE(eth->ports); p++) in airoha_fe_maccr_init()
203 /* ETH->ETH_P_1905 (0x893a) */ in airoha_fe_vip_setup()
257 all_rsv += (val - orig_val); in airoha_fe_set_pse_oq_rsv()
264 tmp = fq_limit - all_rsv - 0x20; in airoha_fe_set_pse_oq_rsv()
269 tmp = fq_limit - all_rsv - 0x100; in airoha_fe_set_pse_oq_rsv()
332 for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM3] - 1; q++) in airoha_fe_pse_ports_init()
481 /* connect RxRing1 and RxRing15 to PSE Port0 OQ-1 in airoha_fe_init()
482 * connect other rings to PSE Port0 OQ-0 in airoha_fe_init()
499 /* NPU Core-3, NPU Bridge Channel-3 */ in airoha_fe_init()
504 /* QDMA LAN, RX Ring-22 */ in airoha_fe_init()
518 /* default aging mode for mbi unlock issue */ in airoha_fe_init()
554 struct airoha_qdma *qdma = q->qdma; in airoha_qdma_fill_rx_queue()
555 int qid = q - &qdma->q_rx[0]; in airoha_qdma_fill_rx_queue()
558 while (q->queued < q->ndesc - 1) { in airoha_qdma_fill_rx_queue()
559 struct airoha_queue_entry *e = &q->entry[q->head]; in airoha_qdma_fill_rx_queue()
560 struct airoha_qdma_desc *desc = &q->desc[q->head]; in airoha_qdma_fill_rx_queue()
565 page = page_pool_dev_alloc_frag(q->page_pool, &offset, in airoha_qdma_fill_rx_queue()
566 q->buf_size); in airoha_qdma_fill_rx_queue()
570 q->head = (q->head + 1) % q->ndesc; in airoha_qdma_fill_rx_queue()
571 q->queued++; in airoha_qdma_fill_rx_queue()
574 e->buf = page_address(page) + offset; in airoha_qdma_fill_rx_queue()
575 e->dma_addr = page_pool_get_dma_addr(page) + offset; in airoha_qdma_fill_rx_queue()
576 e->dma_len = SKB_WITH_OVERHEAD(q->buf_size); in airoha_qdma_fill_rx_queue()
578 val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len); in airoha_qdma_fill_rx_queue()
579 WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); in airoha_qdma_fill_rx_queue()
580 WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr)); in airoha_qdma_fill_rx_queue()
581 val = FIELD_PREP(QDMA_DESC_NEXT_ID_MASK, q->head); in airoha_qdma_fill_rx_queue()
582 WRITE_ONCE(desc->data, cpu_to_le32(val)); in airoha_qdma_fill_rx_queue()
583 WRITE_ONCE(desc->msg0, 0); in airoha_qdma_fill_rx_queue()
584 WRITE_ONCE(desc->msg1, 0); in airoha_qdma_fill_rx_queue()
585 WRITE_ONCE(desc->msg2, 0); in airoha_qdma_fill_rx_queue()
586 WRITE_ONCE(desc->msg3, 0); in airoha_qdma_fill_rx_queue()
590 FIELD_PREP(RX_RING_CPU_IDX_MASK, q->head)); in airoha_qdma_fill_rx_queue()
599 u32 port, sport, msg1 = le32_to_cpu(desc->msg1); in airoha_qdma_get_gdm_port()
607 port = sport - 1; in airoha_qdma_get_gdm_port()
610 return -EINVAL; in airoha_qdma_get_gdm_port()
613 return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; in airoha_qdma_get_gdm_port()
618 enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); in airoha_qdma_rx_process()
619 struct airoha_qdma *qdma = q->qdma; in airoha_qdma_rx_process()
620 struct airoha_eth *eth = qdma->eth; in airoha_qdma_rx_process()
621 int qid = q - &qdma->q_rx[0]; in airoha_qdma_rx_process()
625 struct airoha_queue_entry *e = &q->entry[q->tail]; in airoha_qdma_rx_process()
626 struct airoha_qdma_desc *desc = &q->desc[q->tail]; in airoha_qdma_rx_process()
627 u32 hash, reason, msg1 = le32_to_cpu(desc->msg1); in airoha_qdma_rx_process()
628 struct page *page = virt_to_head_page(e->buf); in airoha_qdma_rx_process()
629 u32 desc_ctrl = le32_to_cpu(desc->ctrl); in airoha_qdma_rx_process()
636 q->tail = (q->tail + 1) % q->ndesc; in airoha_qdma_rx_process()
637 q->queued--; in airoha_qdma_rx_process()
639 dma_sync_single_for_cpu(eth->dev, e->dma_addr, in airoha_qdma_rx_process()
640 SKB_WITH_OVERHEAD(q->buf_size), dir); in airoha_qdma_rx_process()
643 data_len = q->skb ? q->buf_size in airoha_qdma_rx_process()
644 : SKB_WITH_OVERHEAD(q->buf_size); in airoha_qdma_rx_process()
649 if (p < 0 || !eth->ports[p]) in airoha_qdma_rx_process()
652 port = eth->ports[p]; in airoha_qdma_rx_process()
653 if (!q->skb) { /* first buffer */ in airoha_qdma_rx_process()
654 q->skb = napi_build_skb(e->buf, q->buf_size); in airoha_qdma_rx_process()
655 if (!q->skb) in airoha_qdma_rx_process()
658 __skb_put(q->skb, len); in airoha_qdma_rx_process()
659 skb_mark_for_recycle(q->skb); in airoha_qdma_rx_process()
660 q->skb->dev = port->dev; in airoha_qdma_rx_process()
661 q->skb->protocol = eth_type_trans(q->skb, port->dev); in airoha_qdma_rx_process()
662 q->skb->ip_summed = CHECKSUM_UNNECESSARY; in airoha_qdma_rx_process()
663 skb_record_rx_queue(q->skb, qid); in airoha_qdma_rx_process()
665 struct skb_shared_info *shinfo = skb_shinfo(q->skb); in airoha_qdma_rx_process()
666 int nr_frags = shinfo->nr_frags; in airoha_qdma_rx_process()
668 if (nr_frags >= ARRAY_SIZE(shinfo->frags)) in airoha_qdma_rx_process()
671 skb_add_rx_frag(q->skb, nr_frags, page, in airoha_qdma_rx_process()
672 e->buf - page_address(page), len, in airoha_qdma_rx_process()
673 q->buf_size); in airoha_qdma_rx_process()
679 if (netdev_uses_dsa(port->dev)) { in airoha_qdma_rx_process()
686 le32_to_cpu(desc->msg0)); in airoha_qdma_rx_process()
688 if (sptag < ARRAY_SIZE(port->dsa_meta) && in airoha_qdma_rx_process()
689 port->dsa_meta[sptag]) in airoha_qdma_rx_process()
690 skb_dst_set_noref(q->skb, in airoha_qdma_rx_process()
691 &port->dsa_meta[sptag]->dst); in airoha_qdma_rx_process()
696 skb_set_hash(q->skb, jhash_1word(hash, 0), in airoha_qdma_rx_process()
701 airoha_ppe_check_skb(&eth->ppe->dev, q->skb, hash, in airoha_qdma_rx_process()
705 napi_gro_receive(&q->napi, q->skb); in airoha_qdma_rx_process()
706 q->skb = NULL; in airoha_qdma_rx_process()
709 if (q->skb) { in airoha_qdma_rx_process()
710 dev_kfree_skb(q->skb); in airoha_qdma_rx_process()
711 q->skb = NULL; in airoha_qdma_rx_process()
713 page_pool_put_full_page(q->page_pool, page, true); in airoha_qdma_rx_process()
727 cur = airoha_qdma_rx_process(q, budget - done); in airoha_qdma_rx_napi_poll()
732 struct airoha_qdma *qdma = q->qdma; in airoha_qdma_rx_napi_poll()
733 int i, qid = q - &qdma->q_rx[0]; in airoha_qdma_rx_napi_poll()
737 for (i = 0; i < ARRAY_SIZE(qdma->irq_banks); i++) { in airoha_qdma_rx_napi_poll()
741 airoha_qdma_irq_enable(&qdma->irq_banks[i], intr_reg, in airoha_qdma_rx_napi_poll()
759 .dev = qdma->eth->dev, in airoha_qdma_init_rx_queue()
760 .napi = &q->napi, in airoha_qdma_init_rx_queue()
762 struct airoha_eth *eth = qdma->eth; in airoha_qdma_init_rx_queue()
763 int qid = q - &qdma->q_rx[0], thr; in airoha_qdma_init_rx_queue()
766 q->buf_size = PAGE_SIZE / 2; in airoha_qdma_init_rx_queue()
767 q->ndesc = ndesc; in airoha_qdma_init_rx_queue()
768 q->qdma = qdma; in airoha_qdma_init_rx_queue()
770 q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), in airoha_qdma_init_rx_queue()
772 if (!q->entry) in airoha_qdma_init_rx_queue()
773 return -ENOMEM; in airoha_qdma_init_rx_queue()
775 q->page_pool = page_pool_create(&pp_params); in airoha_qdma_init_rx_queue()
776 if (IS_ERR(q->page_pool)) { in airoha_qdma_init_rx_queue()
777 int err = PTR_ERR(q->page_pool); in airoha_qdma_init_rx_queue()
779 q->page_pool = NULL; in airoha_qdma_init_rx_queue()
783 q->desc = dmam_alloc_coherent(eth->dev, q->ndesc * sizeof(*q->desc), in airoha_qdma_init_rx_queue()
785 if (!q->desc) in airoha_qdma_init_rx_queue()
786 return -ENOMEM; in airoha_qdma_init_rx_queue()
788 netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); in airoha_qdma_init_rx_queue()
799 FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head)); in airoha_qdma_init_rx_queue()
809 struct airoha_eth *eth = q->qdma->eth; in airoha_qdma_cleanup_rx_queue()
811 while (q->queued) { in airoha_qdma_cleanup_rx_queue()
812 struct airoha_queue_entry *e = &q->entry[q->tail]; in airoha_qdma_cleanup_rx_queue()
813 struct page *page = virt_to_head_page(e->buf); in airoha_qdma_cleanup_rx_queue()
815 dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len, in airoha_qdma_cleanup_rx_queue()
816 page_pool_get_dma_dir(q->page_pool)); in airoha_qdma_cleanup_rx_queue()
817 page_pool_put_full_page(q->page_pool, page, false); in airoha_qdma_cleanup_rx_queue()
818 q->tail = (q->tail + 1) % q->ndesc; in airoha_qdma_cleanup_rx_queue()
819 q->queued--; in airoha_qdma_cleanup_rx_queue()
827 for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { in airoha_qdma_init_rx()
831 /* rx-queue not binded to irq */ in airoha_qdma_init_rx()
835 err = airoha_qdma_init_rx_queue(&qdma->q_rx[i], qdma, in airoha_qdma_init_rx()
853 qdma = irq_q->qdma; in airoha_qdma_tx_napi_poll()
854 id = irq_q - &qdma->q_tx_irq[0]; in airoha_qdma_tx_napi_poll()
855 eth = qdma->eth; in airoha_qdma_tx_napi_poll()
859 head = head % irq_q->size; in airoha_qdma_tx_napi_poll()
863 u32 qid, val = irq_q->q[head]; in airoha_qdma_tx_napi_poll()
873 irq_q->q[head] = 0xff; /* mark as done */ in airoha_qdma_tx_napi_poll()
874 head = (head + 1) % irq_q->size; in airoha_qdma_tx_napi_poll()
875 irq_queued--; in airoha_qdma_tx_napi_poll()
879 if (qid >= ARRAY_SIZE(qdma->q_tx)) in airoha_qdma_tx_napi_poll()
882 q = &qdma->q_tx[qid]; in airoha_qdma_tx_napi_poll()
883 if (!q->ndesc) in airoha_qdma_tx_napi_poll()
887 if (index >= q->ndesc) in airoha_qdma_tx_napi_poll()
890 spin_lock_bh(&q->lock); in airoha_qdma_tx_napi_poll()
892 if (!q->queued) in airoha_qdma_tx_napi_poll()
895 desc = &q->desc[index]; in airoha_qdma_tx_napi_poll()
896 desc_ctrl = le32_to_cpu(desc->ctrl); in airoha_qdma_tx_napi_poll()
902 e = &q->entry[index]; in airoha_qdma_tx_napi_poll()
903 skb = e->skb; in airoha_qdma_tx_napi_poll()
905 dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, in airoha_qdma_tx_napi_poll()
908 WRITE_ONCE(desc->msg0, 0); in airoha_qdma_tx_napi_poll()
909 WRITE_ONCE(desc->msg1, 0); in airoha_qdma_tx_napi_poll()
910 q->queued--; in airoha_qdma_tx_napi_poll()
912 /* completion ring can report out-of-order indexes if hw QoS in airoha_qdma_tx_napi_poll()
914 * to same DMA ring. Take into account possible out-of-order in airoha_qdma_tx_napi_poll()
917 while (q->tail != q->head && !q->entry[q->tail].dma_addr) in airoha_qdma_tx_napi_poll()
918 q->tail = (q->tail + 1) % q->ndesc; in airoha_qdma_tx_napi_poll()
924 txq = netdev_get_tx_queue(skb->dev, queue); in airoha_qdma_tx_napi_poll()
925 netdev_tx_completed_queue(txq, 1, skb->len); in airoha_qdma_tx_napi_poll()
927 q->ndesc - q->queued >= q->free_thr) in airoha_qdma_tx_napi_poll()
933 spin_unlock_bh(&q->lock); in airoha_qdma_tx_napi_poll()
947 airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX0, in airoha_qdma_tx_napi_poll()
956 struct airoha_eth *eth = qdma->eth; in airoha_qdma_init_tx_queue()
957 int i, qid = q - &qdma->q_tx[0]; in airoha_qdma_init_tx_queue()
960 spin_lock_init(&q->lock); in airoha_qdma_init_tx_queue()
961 q->ndesc = size; in airoha_qdma_init_tx_queue()
962 q->qdma = qdma; in airoha_qdma_init_tx_queue()
963 q->free_thr = 1 + MAX_SKB_FRAGS; in airoha_qdma_init_tx_queue()
965 q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), in airoha_qdma_init_tx_queue()
967 if (!q->entry) in airoha_qdma_init_tx_queue()
968 return -ENOMEM; in airoha_qdma_init_tx_queue()
970 q->desc = dmam_alloc_coherent(eth->dev, q->ndesc * sizeof(*q->desc), in airoha_qdma_init_tx_queue()
972 if (!q->desc) in airoha_qdma_init_tx_queue()
973 return -ENOMEM; in airoha_qdma_init_tx_queue()
975 for (i = 0; i < q->ndesc; i++) { in airoha_qdma_init_tx_queue()
979 WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val)); in airoha_qdma_init_tx_queue()
988 FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); in airoha_qdma_init_tx_queue()
990 FIELD_PREP(TX_RING_DMA_IDX_MASK, q->head)); in airoha_qdma_init_tx_queue()
998 int id = irq_q - &qdma->q_tx_irq[0]; in airoha_qdma_tx_irq_init()
999 struct airoha_eth *eth = qdma->eth; in airoha_qdma_tx_irq_init()
1002 netif_napi_add_tx(eth->napi_dev, &irq_q->napi, in airoha_qdma_tx_irq_init()
1004 irq_q->q = dmam_alloc_coherent(eth->dev, size * sizeof(u32), in airoha_qdma_tx_irq_init()
1006 if (!irq_q->q) in airoha_qdma_tx_irq_init()
1007 return -ENOMEM; in airoha_qdma_tx_irq_init()
1009 memset(irq_q->q, 0xff, size * sizeof(u32)); in airoha_qdma_tx_irq_init()
1010 irq_q->size = size; in airoha_qdma_tx_irq_init()
1011 irq_q->qdma = qdma; in airoha_qdma_tx_irq_init()
1026 for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) { in airoha_qdma_init_tx()
1027 err = airoha_qdma_tx_irq_init(&qdma->q_tx_irq[i], qdma, in airoha_qdma_init_tx()
1033 for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { in airoha_qdma_init_tx()
1034 err = airoha_qdma_init_tx_queue(&qdma->q_tx[i], qdma, in airoha_qdma_init_tx()
1045 struct airoha_eth *eth = q->qdma->eth; in airoha_qdma_cleanup_tx_queue()
1047 spin_lock_bh(&q->lock); in airoha_qdma_cleanup_tx_queue()
1048 while (q->queued) { in airoha_qdma_cleanup_tx_queue()
1049 struct airoha_queue_entry *e = &q->entry[q->tail]; in airoha_qdma_cleanup_tx_queue()
1051 dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, in airoha_qdma_cleanup_tx_queue()
1053 dev_kfree_skb_any(e->skb); in airoha_qdma_cleanup_tx_queue()
1054 e->skb = NULL; in airoha_qdma_cleanup_tx_queue()
1056 q->tail = (q->tail + 1) % q->ndesc; in airoha_qdma_cleanup_tx_queue()
1057 q->queued--; in airoha_qdma_cleanup_tx_queue()
1059 spin_unlock_bh(&q->lock); in airoha_qdma_cleanup_tx_queue()
1065 struct airoha_eth *eth = qdma->eth; in airoha_qdma_init_hfwd_queues()
1066 int id = qdma - &eth->qdma[0]; in airoha_qdma_init_hfwd_queues()
1071 name = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d-buf", id); in airoha_qdma_init_hfwd_queues()
1073 return -ENOMEM; in airoha_qdma_init_hfwd_queues()
1076 index = of_property_match_string(eth->dev->of_node, in airoha_qdma_init_hfwd_queues()
1077 "memory-region-names", name); in airoha_qdma_init_hfwd_queues()
1085 np = of_parse_phandle(eth->dev->of_node, "memory-region", in airoha_qdma_init_hfwd_queues()
1088 return -ENODEV; in airoha_qdma_init_hfwd_queues()
1092 dma_addr = rmem->base; in airoha_qdma_init_hfwd_queues()
1096 num_desc = div_u64(rmem->size, buf_size); in airoha_qdma_init_hfwd_queues()
1099 if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, in airoha_qdma_init_hfwd_queues()
1101 return -ENOMEM; in airoha_qdma_init_hfwd_queues()
1107 if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) in airoha_qdma_init_hfwd_queues()
1108 return -ENOMEM; in airoha_qdma_init_hfwd_queues()
1150 /* fast-tick 25us */ in airoha_qdma_init_qos()
1184 /* Tx-cpu transferred count */ in airoha_qdma_init_qos_stats()
1190 /* Tx-fwd transferred count */ in airoha_qdma_init_qos_stats()
1204 for (i = 0; i < ARRAY_SIZE(qdma->irq_banks); i++) { in airoha_qdma_hw_init()
1208 airoha_qdma_irq_enable(&qdma->irq_banks[i], QDMA_INT_REG_IDX0, in airoha_qdma_hw_init()
1210 airoha_qdma_irq_enable(&qdma->irq_banks[i], QDMA_INT_REG_IDX1, in airoha_qdma_hw_init()
1212 airoha_qdma_irq_enable(&qdma->irq_banks[i], QDMA_INT_REG_IDX2, in airoha_qdma_hw_init()
1214 airoha_qdma_irq_enable(&qdma->irq_banks[i], QDMA_INT_REG_IDX3, in airoha_qdma_hw_init()
1218 airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX0, in airoha_qdma_hw_init()
1220 airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX4, in airoha_qdma_hw_init()
1224 for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { in airoha_qdma_hw_init()
1225 if (!qdma->q_tx[i].ndesc) in airoha_qdma_hw_init()
1249 for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { in airoha_qdma_hw_init()
1250 if (!qdma->q_rx[i].ndesc) in airoha_qdma_hw_init()
1267 struct airoha_qdma *qdma = irq_bank->qdma; in airoha_irq_handler()
1269 u32 intr[ARRAY_SIZE(irq_bank->irqmask)]; in airoha_irq_handler()
1274 intr[i] &= irq_bank->irqmask[i]; in airoha_irq_handler()
1278 if (!test_bit(DEV_STATE_INITIALIZED, &qdma->eth->state)) in airoha_irq_handler()
1293 for (i = 0; rx_intr_mask && i < ARRAY_SIZE(qdma->q_rx); i++) { in airoha_irq_handler()
1294 if (!qdma->q_rx[i].ndesc) in airoha_irq_handler()
1298 napi_schedule(&qdma->q_rx[i].napi); in airoha_irq_handler()
1302 for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) { in airoha_irq_handler()
1308 napi_schedule(&qdma->q_tx_irq[i].napi); in airoha_irq_handler()
1318 struct airoha_eth *eth = qdma->eth; in airoha_qdma_init_irq_banks()
1319 int i, id = qdma - &eth->qdma[0]; in airoha_qdma_init_irq_banks()
1321 for (i = 0; i < ARRAY_SIZE(qdma->irq_banks); i++) { in airoha_qdma_init_irq_banks()
1322 struct airoha_irq_bank *irq_bank = &qdma->irq_banks[i]; in airoha_qdma_init_irq_banks()
1326 spin_lock_init(&irq_bank->irq_lock); in airoha_qdma_init_irq_banks()
1327 irq_bank->qdma = qdma; in airoha_qdma_init_irq_banks()
1329 irq_bank->irq = platform_get_irq(pdev, irq_index); in airoha_qdma_init_irq_banks()
1330 if (irq_bank->irq < 0) in airoha_qdma_init_irq_banks()
1331 return irq_bank->irq; in airoha_qdma_init_irq_banks()
1333 name = devm_kasprintf(eth->dev, GFP_KERNEL, in airoha_qdma_init_irq_banks()
1336 return -ENOMEM; in airoha_qdma_init_irq_banks()
1338 err = devm_request_irq(eth->dev, irq_bank->irq, in airoha_qdma_init_irq_banks()
1352 int err, id = qdma - &eth->qdma[0]; in airoha_qdma_init()
1355 qdma->eth = eth; in airoha_qdma_init()
1356 res = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d", id); in airoha_qdma_init()
1358 return -ENOMEM; in airoha_qdma_init()
1360 qdma->regs = devm_platform_ioremap_resource_byname(pdev, res); in airoha_qdma_init()
1361 if (IS_ERR(qdma->regs)) in airoha_qdma_init()
1362 return dev_err_probe(eth->dev, PTR_ERR(qdma->regs), in airoha_qdma_init()
1390 err = reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), in airoha_hw_init()
1391 eth->xsi_rsts); in airoha_hw_init()
1395 err = reset_control_bulk_assert(ARRAY_SIZE(eth->rsts), eth->rsts); in airoha_hw_init()
1400 err = reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts); in airoha_hw_init()
1409 for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { in airoha_hw_init()
1410 err = airoha_qdma_init(pdev, eth, &eth->qdma[i]); in airoha_hw_init()
1419 set_bit(DEV_STATE_INITIALIZED, &eth->state); in airoha_hw_init()
1428 for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { in airoha_hw_cleanup()
1429 if (!qdma->q_rx[i].ndesc) in airoha_hw_cleanup()
1432 netif_napi_del(&qdma->q_rx[i].napi); in airoha_hw_cleanup()
1433 airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]); in airoha_hw_cleanup()
1434 if (qdma->q_rx[i].page_pool) in airoha_hw_cleanup()
1435 page_pool_destroy(qdma->q_rx[i].page_pool); in airoha_hw_cleanup()
1438 for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) in airoha_hw_cleanup()
1439 netif_napi_del(&qdma->q_tx_irq[i].napi); in airoha_hw_cleanup()
1441 for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { in airoha_hw_cleanup()
1442 if (!qdma->q_tx[i].ndesc) in airoha_hw_cleanup()
1445 airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); in airoha_hw_cleanup()
1453 for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) in airoha_qdma_start_napi()
1454 napi_enable(&qdma->q_tx_irq[i].napi); in airoha_qdma_start_napi()
1456 for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { in airoha_qdma_start_napi()
1457 if (!qdma->q_rx[i].ndesc) in airoha_qdma_start_napi()
1460 napi_enable(&qdma->q_rx[i].napi); in airoha_qdma_start_napi()
1468 for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) in airoha_qdma_stop_napi()
1469 napi_disable(&qdma->q_tx_irq[i].napi); in airoha_qdma_stop_napi()
1471 for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { in airoha_qdma_stop_napi()
1472 if (!qdma->q_rx[i].ndesc) in airoha_qdma_stop_napi()
1475 napi_disable(&qdma->q_rx[i].napi); in airoha_qdma_stop_napi()
1481 struct airoha_eth *eth = port->qdma->eth; in airoha_update_hw_stats()
1484 spin_lock(&port->stats.lock); in airoha_update_hw_stats()
1485 u64_stats_update_begin(&port->stats.syncp); in airoha_update_hw_stats()
1488 val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id)); in airoha_update_hw_stats()
1489 port->stats.tx_ok_pkts += ((u64)val << 32); in airoha_update_hw_stats()
1490 val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_L(port->id)); in airoha_update_hw_stats()
1491 port->stats.tx_ok_pkts += val; in airoha_update_hw_stats()
1493 val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_H(port->id)); in airoha_update_hw_stats()
1494 port->stats.tx_ok_bytes += ((u64)val << 32); in airoha_update_hw_stats()
1495 val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_L(port->id)); in airoha_update_hw_stats()
1496 port->stats.tx_ok_bytes += val; in airoha_update_hw_stats()
1498 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_DROP_CNT(port->id)); in airoha_update_hw_stats()
1499 port->stats.tx_drops += val; in airoha_update_hw_stats()
1501 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_BC_CNT(port->id)); in airoha_update_hw_stats()
1502 port->stats.tx_broadcast += val; in airoha_update_hw_stats()
1504 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_MC_CNT(port->id)); in airoha_update_hw_stats()
1505 port->stats.tx_multicast += val; in airoha_update_hw_stats()
1507 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_RUNT_CNT(port->id)); in airoha_update_hw_stats()
1508 port->stats.tx_len[i] += val; in airoha_update_hw_stats()
1510 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_H(port->id)); in airoha_update_hw_stats()
1511 port->stats.tx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1512 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_L(port->id)); in airoha_update_hw_stats()
1513 port->stats.tx_len[i++] += val; in airoha_update_hw_stats()
1515 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_H(port->id)); in airoha_update_hw_stats()
1516 port->stats.tx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1517 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_L(port->id)); in airoha_update_hw_stats()
1518 port->stats.tx_len[i++] += val; in airoha_update_hw_stats()
1520 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_H(port->id)); in airoha_update_hw_stats()
1521 port->stats.tx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1522 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_L(port->id)); in airoha_update_hw_stats()
1523 port->stats.tx_len[i++] += val; in airoha_update_hw_stats()
1525 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_H(port->id)); in airoha_update_hw_stats()
1526 port->stats.tx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1527 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_L(port->id)); in airoha_update_hw_stats()
1528 port->stats.tx_len[i++] += val; in airoha_update_hw_stats()
1530 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_H(port->id)); in airoha_update_hw_stats()
1531 port->stats.tx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1532 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_L(port->id)); in airoha_update_hw_stats()
1533 port->stats.tx_len[i++] += val; in airoha_update_hw_stats()
1535 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_H(port->id)); in airoha_update_hw_stats()
1536 port->stats.tx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1537 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_L(port->id)); in airoha_update_hw_stats()
1538 port->stats.tx_len[i++] += val; in airoha_update_hw_stats()
1540 val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_LONG_CNT(port->id)); in airoha_update_hw_stats()
1541 port->stats.tx_len[i++] += val; in airoha_update_hw_stats()
1544 val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_H(port->id)); in airoha_update_hw_stats()
1545 port->stats.rx_ok_pkts += ((u64)val << 32); in airoha_update_hw_stats()
1546 val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_L(port->id)); in airoha_update_hw_stats()
1547 port->stats.rx_ok_pkts += val; in airoha_update_hw_stats()
1549 val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_H(port->id)); in airoha_update_hw_stats()
1550 port->stats.rx_ok_bytes += ((u64)val << 32); in airoha_update_hw_stats()
1551 val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_L(port->id)); in airoha_update_hw_stats()
1552 port->stats.rx_ok_bytes += val; in airoha_update_hw_stats()
1554 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_DROP_CNT(port->id)); in airoha_update_hw_stats()
1555 port->stats.rx_drops += val; in airoha_update_hw_stats()
1557 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_BC_CNT(port->id)); in airoha_update_hw_stats()
1558 port->stats.rx_broadcast += val; in airoha_update_hw_stats()
1560 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_MC_CNT(port->id)); in airoha_update_hw_stats()
1561 port->stats.rx_multicast += val; in airoha_update_hw_stats()
1563 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ERROR_DROP_CNT(port->id)); in airoha_update_hw_stats()
1564 port->stats.rx_errors += val; in airoha_update_hw_stats()
1566 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_CRC_ERR_CNT(port->id)); in airoha_update_hw_stats()
1567 port->stats.rx_crc_error += val; in airoha_update_hw_stats()
1569 val = airoha_fe_rr(eth, REG_FE_GDM_RX_OVERFLOW_DROP_CNT(port->id)); in airoha_update_hw_stats()
1570 port->stats.rx_over_errors += val; in airoha_update_hw_stats()
1572 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_FRAG_CNT(port->id)); in airoha_update_hw_stats()
1573 port->stats.rx_fragment += val; in airoha_update_hw_stats()
1575 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_JABBER_CNT(port->id)); in airoha_update_hw_stats()
1576 port->stats.rx_jabber += val; in airoha_update_hw_stats()
1579 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_RUNT_CNT(port->id)); in airoha_update_hw_stats()
1580 port->stats.rx_len[i] += val; in airoha_update_hw_stats()
1582 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_H(port->id)); in airoha_update_hw_stats()
1583 port->stats.rx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1584 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_L(port->id)); in airoha_update_hw_stats()
1585 port->stats.rx_len[i++] += val; in airoha_update_hw_stats()
1587 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_H(port->id)); in airoha_update_hw_stats()
1588 port->stats.rx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1589 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_L(port->id)); in airoha_update_hw_stats()
1590 port->stats.rx_len[i++] += val; in airoha_update_hw_stats()
1592 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_H(port->id)); in airoha_update_hw_stats()
1593 port->stats.rx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1594 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_L(port->id)); in airoha_update_hw_stats()
1595 port->stats.rx_len[i++] += val; in airoha_update_hw_stats()
1597 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_H(port->id)); in airoha_update_hw_stats()
1598 port->stats.rx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1599 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_L(port->id)); in airoha_update_hw_stats()
1600 port->stats.rx_len[i++] += val; in airoha_update_hw_stats()
1602 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_H(port->id)); in airoha_update_hw_stats()
1603 port->stats.rx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1604 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_L(port->id)); in airoha_update_hw_stats()
1605 port->stats.rx_len[i++] += val; in airoha_update_hw_stats()
1607 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_H(port->id)); in airoha_update_hw_stats()
1608 port->stats.rx_len[i] += ((u64)val << 32); in airoha_update_hw_stats()
1609 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_L(port->id)); in airoha_update_hw_stats()
1610 port->stats.rx_len[i++] += val; in airoha_update_hw_stats()
1612 val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_LONG_CNT(port->id)); in airoha_update_hw_stats()
1613 port->stats.rx_len[i++] += val; in airoha_update_hw_stats()
1616 airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id), in airoha_update_hw_stats()
1619 u64_stats_update_end(&port->stats.syncp); in airoha_update_hw_stats()
1620 spin_unlock(&port->stats.lock); in airoha_update_hw_stats()
1625 int err, len = ETH_HLEN + dev->mtu + ETH_FCS_LEN; in airoha_dev_open()
1627 struct airoha_qdma *qdma = port->qdma; in airoha_dev_open()
1635 airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), in airoha_dev_open()
1638 airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), in airoha_dev_open()
1641 airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), in airoha_dev_open()
1649 atomic_inc(&qdma->users); in airoha_dev_open()
1657 struct airoha_qdma *qdma = port->qdma; in airoha_dev_stop()
1665 for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) in airoha_dev_stop()
1668 if (atomic_dec_and_test(&qdma->users)) { in airoha_dev_stop()
1673 for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { in airoha_dev_stop()
1674 if (!qdma->q_tx[i].ndesc) in airoha_dev_stop()
1677 airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); in airoha_dev_stop()
1693 airoha_set_macaddr(port, dev->dev_addr); in airoha_dev_set_macaddr()
1700 u32 pse_port = port->id == 3 ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4; in airhoha_set_gdm2_loopback()
1701 struct airoha_eth *eth = port->qdma->eth; in airhoha_set_gdm2_loopback()
1702 u32 chan = port->id == 3 ? 4 : 0; in airhoha_set_gdm2_loopback()
1725 if (port->id == 3) { in airhoha_set_gdm2_loopback()
1753 struct airoha_eth *eth = port->qdma->eth; in airoha_dev_init()
1756 airoha_set_macaddr(port, dev->dev_addr); in airoha_dev_init()
1758 switch (port->id) { in airoha_dev_init()
1762 if (!eth->ports[1]) in airoha_dev_init()
1773 airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), pse_port); in airoha_dev_init()
1786 start = u64_stats_fetch_begin(&port->stats.syncp); in airoha_dev_get_stats64()
1787 storage->rx_packets = port->stats.rx_ok_pkts; in airoha_dev_get_stats64()
1788 storage->tx_packets = port->stats.tx_ok_pkts; in airoha_dev_get_stats64()
1789 storage->rx_bytes = port->stats.rx_ok_bytes; in airoha_dev_get_stats64()
1790 storage->tx_bytes = port->stats.tx_ok_bytes; in airoha_dev_get_stats64()
1791 storage->multicast = port->stats.rx_multicast; in airoha_dev_get_stats64()
1792 storage->rx_errors = port->stats.rx_errors; in airoha_dev_get_stats64()
1793 storage->rx_dropped = port->stats.rx_drops; in airoha_dev_get_stats64()
1794 storage->tx_dropped = port->stats.tx_drops; in airoha_dev_get_stats64()
1795 storage->rx_crc_errors = port->stats.rx_crc_error; in airoha_dev_get_stats64()
1796 storage->rx_over_errors = port->stats.rx_over_errors; in airoha_dev_get_stats64()
1797 } while (u64_stats_fetch_retry(&port->stats.syncp, start)); in airoha_dev_get_stats64()
1803 struct airoha_eth *eth = port->qdma->eth; in airoha_dev_change_mtu()
1806 airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), in airoha_dev_change_mtu()
1809 WRITE_ONCE(dev->mtu, mtu); in airoha_dev_change_mtu()
1824 channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id; in airoha_dev_select_queue()
1826 queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */ in airoha_dev_select_queue()
1829 return queue < dev->num_tx_queues ? queue : 0; in airoha_dev_select_queue()
1842 if (dev->dsa_ptr->tag_ops->proto != DSA_TAG_PROTO_MTK) in airoha_get_dsa_tag()
1848 ehdr = (struct ethhdr *)skb->data; in airoha_get_dsa_tag()
1849 tag = be16_to_cpu(ehdr->h_proto); in airoha_get_dsa_tag()
1854 ehdr->h_proto = cpu_to_be16(ETH_P_8021Q); in airoha_get_dsa_tag()
1858 ehdr->h_proto = cpu_to_be16(ETH_P_8021AD); in airoha_get_dsa_tag()
1865 memmove(skb->data + MTK_HDR_LEN, skb->data, 2 * ETH_ALEN); in airoha_get_dsa_tag()
1878 u32 tail = q->tail <= q->head ? q->tail + q->ndesc : q->tail; in airoha_dev_tx_queue_busy()
1879 u32 index = q->head + nr_frags; in airoha_dev_tx_queue_busy()
1881 /* completion napi can free out-of-order tx descriptors if hw QoS is in airoha_dev_tx_queue_busy()
1883 * DMA ring. Take into account possible out-of-order reports checking in airoha_dev_tx_queue_busy()
1894 struct airoha_qdma *qdma = port->qdma; in airoha_dev_xmit()
1903 qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx); in airoha_dev_xmit()
1911 if (skb->ip_summed == CHECKSUM_PARTIAL) in airoha_dev_xmit()
1921 if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | in airoha_dev_xmit()
1923 __be16 csum = cpu_to_be16(skb_shinfo(skb)->gso_size); in airoha_dev_xmit()
1925 tcp_hdr(skb)->check = (__force __sum16)csum; in airoha_dev_xmit()
1930 fport = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; in airoha_dev_xmit()
1934 q = &qdma->q_tx[qid]; in airoha_dev_xmit()
1935 if (WARN_ON_ONCE(!q->ndesc)) in airoha_dev_xmit()
1938 spin_lock_bh(&q->lock); in airoha_dev_xmit()
1941 nr_frags = 1 + skb_shinfo(skb)->nr_frags; in airoha_dev_xmit()
1946 spin_unlock_bh(&q->lock); in airoha_dev_xmit()
1951 data = skb->data; in airoha_dev_xmit()
1952 index = q->head; in airoha_dev_xmit()
1955 struct airoha_qdma_desc *desc = &q->desc[index]; in airoha_dev_xmit()
1956 struct airoha_queue_entry *e = &q->entry[index]; in airoha_dev_xmit()
1957 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; in airoha_dev_xmit()
1961 addr = dma_map_single(dev->dev.parent, data, len, in airoha_dev_xmit()
1963 if (unlikely(dma_mapping_error(dev->dev.parent, addr))) in airoha_dev_xmit()
1966 index = (index + 1) % q->ndesc; in airoha_dev_xmit()
1969 if (i < nr_frags - 1) in airoha_dev_xmit()
1971 WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); in airoha_dev_xmit()
1972 WRITE_ONCE(desc->addr, cpu_to_le32(addr)); in airoha_dev_xmit()
1974 WRITE_ONCE(desc->data, cpu_to_le32(val)); in airoha_dev_xmit()
1975 WRITE_ONCE(desc->msg0, cpu_to_le32(msg0)); in airoha_dev_xmit()
1976 WRITE_ONCE(desc->msg1, cpu_to_le32(msg1)); in airoha_dev_xmit()
1977 WRITE_ONCE(desc->msg2, cpu_to_le32(0xffff)); in airoha_dev_xmit()
1979 e->skb = i ? NULL : skb; in airoha_dev_xmit()
1980 e->dma_addr = addr; in airoha_dev_xmit()
1981 e->dma_len = len; in airoha_dev_xmit()
1987 q->head = index; in airoha_dev_xmit()
1988 q->queued += i; in airoha_dev_xmit()
1991 netdev_tx_sent_queue(txq, skb->len); in airoha_dev_xmit()
1996 FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); in airoha_dev_xmit()
1998 if (q->ndesc - q->queued < q->free_thr) in airoha_dev_xmit()
2001 spin_unlock_bh(&q->lock); in airoha_dev_xmit()
2006 for (i--; i >= 0; i--) { in airoha_dev_xmit()
2007 index = (q->head + i) % q->ndesc; in airoha_dev_xmit()
2008 dma_unmap_single(dev->dev.parent, q->entry[index].dma_addr, in airoha_dev_xmit()
2009 q->entry[index].dma_len, DMA_TO_DEVICE); in airoha_dev_xmit()
2012 spin_unlock_bh(&q->lock); in airoha_dev_xmit()
2015 dev->stats.tx_dropped++; in airoha_dev_xmit()
2024 struct airoha_eth *eth = port->qdma->eth; in airoha_ethtool_get_drvinfo()
2026 strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); in airoha_ethtool_get_drvinfo()
2027 strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); in airoha_ethtool_get_drvinfo()
2038 start = u64_stats_fetch_begin(&port->stats.syncp); in airoha_ethtool_get_mac_stats()
2039 stats->MulticastFramesXmittedOK = port->stats.tx_multicast; in airoha_ethtool_get_mac_stats()
2040 stats->BroadcastFramesXmittedOK = port->stats.tx_broadcast; in airoha_ethtool_get_mac_stats()
2041 stats->BroadcastFramesReceivedOK = port->stats.rx_broadcast; in airoha_ethtool_get_mac_stats()
2042 } while (u64_stats_fetch_retry(&port->stats.syncp, start)); in airoha_ethtool_get_mac_stats()
2059 const struct ethtool_rmon_hist_range **ranges) in airoha_ethtool_get_rmon_stats() argument
2062 struct airoha_hw_stats *hw_stats = &port->stats; in airoha_ethtool_get_rmon_stats()
2066 ARRAY_SIZE(hw_stats->tx_len) + 1); in airoha_ethtool_get_rmon_stats()
2068 ARRAY_SIZE(hw_stats->rx_len) + 1); in airoha_ethtool_get_rmon_stats()
2070 *ranges = airoha_ethtool_rmon_ranges; in airoha_ethtool_get_rmon_stats()
2075 start = u64_stats_fetch_begin(&port->stats.syncp); in airoha_ethtool_get_rmon_stats()
2076 stats->fragments = hw_stats->rx_fragment; in airoha_ethtool_get_rmon_stats()
2077 stats->jabbers = hw_stats->rx_jabber; in airoha_ethtool_get_rmon_stats()
2078 for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1; in airoha_ethtool_get_rmon_stats()
2080 stats->hist[i] = hw_stats->rx_len[i]; in airoha_ethtool_get_rmon_stats()
2081 stats->hist_tx[i] = hw_stats->tx_len[i]; in airoha_ethtool_get_rmon_stats()
2083 } while (u64_stats_fetch_retry(&port->stats.syncp, start)); in airoha_ethtool_get_rmon_stats()
2093 airoha_qdma_clear(port->qdma, REG_QUEUE_CLOSE_CFG(channel), in airoha_qdma_set_chan_tx_sched()
2100 airoha_qdma_wr(port->qdma, REG_TXWRR_WEIGHT_CFG, in airoha_qdma_set_chan_tx_sched()
2108 true, port->qdma, in airoha_qdma_set_chan_tx_sched()
2114 airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3), in airoha_qdma_set_chan_tx_sched()
2134 struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; in airoha_qdma_set_tx_ets_sched()
2139 if (p->bands > AIROHA_NUM_QOS_QUEUES) in airoha_qdma_set_tx_ets_sched()
2140 return -EINVAL; in airoha_qdma_set_tx_ets_sched()
2142 for (i = 0; i < p->bands; i++) { in airoha_qdma_set_tx_ets_sched()
2143 if (!p->quanta[i]) in airoha_qdma_set_tx_ets_sched()
2148 if (nstrict == AIROHA_NUM_QOS_QUEUES - 1) in airoha_qdma_set_tx_ets_sched()
2149 return -EINVAL; in airoha_qdma_set_tx_ets_sched()
2156 if (p->priomap[p->bands - i - 1] != i) in airoha_qdma_set_tx_ets_sched()
2157 return -EINVAL; in airoha_qdma_set_tx_ets_sched()
2160 for (i = 0; i < p->bands - nstrict; i++) { in airoha_qdma_set_tx_ets_sched()
2161 if (p->priomap[i] != nstrict + i) in airoha_qdma_set_tx_ets_sched()
2162 return -EINVAL; in airoha_qdma_set_tx_ets_sched()
2164 w[i] = p->weights[nstrict + i]; in airoha_qdma_set_tx_ets_sched()
2169 else if (nstrict < AIROHA_NUM_QOS_QUEUES - 1) in airoha_qdma_set_tx_ets_sched()
2180 u64 cpu_tx_packets = airoha_qdma_rr(port->qdma, in airoha_qdma_get_tx_ets_stats()
2182 u64 fwd_tx_packets = airoha_qdma_rr(port->qdma, in airoha_qdma_get_tx_ets_stats()
2184 u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) + in airoha_qdma_get_tx_ets_stats()
2185 (fwd_tx_packets - port->fwd_tx_packets); in airoha_qdma_get_tx_ets_stats()
2186 _bstats_update(opt->stats.bstats, 0, tx_packets); in airoha_qdma_get_tx_ets_stats()
2188 port->cpu_tx_packets = cpu_tx_packets; in airoha_qdma_get_tx_ets_stats()
2189 port->fwd_tx_packets = fwd_tx_packets; in airoha_qdma_get_tx_ets_stats()
2199 if (opt->parent == TC_H_ROOT) in airoha_tc_setup_qdisc_ets()
2200 return -EINVAL; in airoha_tc_setup_qdisc_ets()
2202 channel = TC_H_MAJ(opt->handle) >> 16; in airoha_tc_setup_qdisc_ets()
2205 switch (opt->command) { in airoha_tc_setup_qdisc_ets()
2214 return -EOPNOTSUPP; in airoha_tc_setup_qdisc_ets()
2232 return -ETIMEDOUT; in airoha_qdma_get_rl_param()
2294 return -EINVAL; in airoha_qdma_set_rl_token_bucket()
2298 return -EINVAL; in airoha_qdma_set_rl_token_bucket()
2353 return -ETIMEDOUT; in airoha_qdma_get_trtcm_param()
2390 return -EINVAL; in airoha_qdma_set_trtcm_config()
2408 return -EINVAL; in airoha_qdma_set_trtcm_token_bucket()
2415 return -EINVAL; in airoha_qdma_set_trtcm_token_bucket()
2419 return -EINVAL; in airoha_qdma_set_trtcm_token_bucket()
2447 err = airoha_qdma_set_trtcm_config(port->qdma, channel, in airoha_qdma_set_tx_rate_limit()
2453 err = airoha_qdma_set_trtcm_token_bucket(port->qdma, channel, in airoha_qdma_set_tx_rate_limit()
2466 u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; in airoha_tc_htb_alloc_leaf_queue()
2467 u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */ in airoha_tc_htb_alloc_leaf_queue()
2468 struct net_device *dev = port->dev; in airoha_tc_htb_alloc_leaf_queue()
2469 int num_tx_queues = dev->real_num_tx_queues; in airoha_tc_htb_alloc_leaf_queue()
2472 if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { in airoha_tc_htb_alloc_leaf_queue()
2473 NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); in airoha_tc_htb_alloc_leaf_queue()
2474 return -EINVAL; in airoha_tc_htb_alloc_leaf_queue()
2477 err = airoha_qdma_set_tx_rate_limit(port, channel, rate, opt->quantum); in airoha_tc_htb_alloc_leaf_queue()
2479 NL_SET_ERR_MSG_MOD(opt->extack, in airoha_tc_htb_alloc_leaf_queue()
2484 if (opt->command == TC_HTB_NODE_MODIFY) in airoha_tc_htb_alloc_leaf_queue()
2489 airoha_qdma_set_tx_rate_limit(port, channel, 0, opt->quantum); in airoha_tc_htb_alloc_leaf_queue()
2490 NL_SET_ERR_MSG_MOD(opt->extack, in airoha_tc_htb_alloc_leaf_queue()
2495 set_bit(channel, port->qos_sq_bmap); in airoha_tc_htb_alloc_leaf_queue()
2496 opt->qid = AIROHA_NUM_TX_RING + channel; in airoha_tc_htb_alloc_leaf_queue()
2505 struct airoha_qdma *qdma = port->qdma; in airoha_qdma_set_rx_meter()
2508 for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { in airoha_qdma_set_rx_meter()
2511 if (!qdma->q_rx[i].ndesc) in airoha_qdma_set_rx_meter()
2529 const struct flow_action *actions = &f->rule->action; in airoha_tc_matchall_act_validate()
2533 NL_SET_ERR_MSG_MOD(f->common.extack, in airoha_tc_matchall_act_validate()
2535 return -EINVAL; in airoha_tc_matchall_act_validate()
2539 NL_SET_ERR_MSG_MOD(f->common.extack, in airoha_tc_matchall_act_validate()
2541 return -EOPNOTSUPP; in airoha_tc_matchall_act_validate()
2544 act = &actions->entries[0]; in airoha_tc_matchall_act_validate()
2545 if (act->id != FLOW_ACTION_POLICE) { in airoha_tc_matchall_act_validate()
2546 NL_SET_ERR_MSG_MOD(f->common.extack, "unsupported action"); in airoha_tc_matchall_act_validate()
2547 return -EOPNOTSUPP; in airoha_tc_matchall_act_validate()
2550 if (act->police.exceed.act_id != FLOW_ACTION_DROP) { in airoha_tc_matchall_act_validate()
2551 NL_SET_ERR_MSG_MOD(f->common.extack, in airoha_tc_matchall_act_validate()
2553 return -EOPNOTSUPP; in airoha_tc_matchall_act_validate()
2556 if (act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { in airoha_tc_matchall_act_validate()
2557 NL_SET_ERR_MSG_MOD(f->common.extack, in airoha_tc_matchall_act_validate()
2559 return -EOPNOTSUPP; in airoha_tc_matchall_act_validate()
2562 if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT && in airoha_tc_matchall_act_validate()
2564 NL_SET_ERR_MSG_MOD(f->common.extack, in airoha_tc_matchall_act_validate()
2566 return -EOPNOTSUPP; in airoha_tc_matchall_act_validate()
2569 if (act->police.peakrate_bytes_ps || act->police.avrate || in airoha_tc_matchall_act_validate()
2570 act->police.overhead || act->police.mtu) { in airoha_tc_matchall_act_validate()
2571 NL_SET_ERR_MSG_MOD(f->common.extack, in airoha_tc_matchall_act_validate()
2573 return -EOPNOTSUPP; in airoha_tc_matchall_act_validate()
2586 switch (f->command) { in airoha_dev_tc_matchall()
2595 act = &f->rule->action.entries[0]; in airoha_dev_tc_matchall()
2596 if (act->police.rate_pkt_ps) { in airoha_dev_tc_matchall()
2597 rate = act->police.rate_pkt_ps; in airoha_dev_tc_matchall()
2598 bucket_size = act->police.burst_pkt; in airoha_dev_tc_matchall()
2601 rate = div_u64(act->police.rate_bytes_ps, 1000); in airoha_dev_tc_matchall()
2603 bucket_size = act->police.burst; in airoha_dev_tc_matchall()
2611 return -EOPNOTSUPP; in airoha_dev_tc_matchall()
2620 struct airoha_eth *eth = port->qdma->eth; in airoha_dev_setup_tc_block_cb()
2623 return -EOPNOTSUPP; in airoha_dev_setup_tc_block_cb()
2627 return airoha_ppe_setup_tc_block_cb(&eth->ppe->dev, type_data); in airoha_dev_setup_tc_block_cb()
2631 return -EOPNOTSUPP; in airoha_dev_setup_tc_block_cb()
2642 if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) in airoha_dev_setup_tc_block()
2643 return -EOPNOTSUPP; in airoha_dev_setup_tc_block()
2645 f->driver_block_list = &block_cb_list; in airoha_dev_setup_tc_block()
2646 switch (f->command) { in airoha_dev_setup_tc_block()
2648 block_cb = flow_block_cb_lookup(f->block, cb, port->dev); in airoha_dev_setup_tc_block()
2653 block_cb = flow_block_cb_alloc(cb, port->dev, port->dev, NULL); in airoha_dev_setup_tc_block()
2659 list_add_tail(&block_cb->driver_list, &block_cb_list); in airoha_dev_setup_tc_block()
2662 block_cb = flow_block_cb_lookup(f->block, cb, port->dev); in airoha_dev_setup_tc_block()
2664 return -ENOENT; in airoha_dev_setup_tc_block()
2668 list_del(&block_cb->driver_list); in airoha_dev_setup_tc_block()
2672 return -EOPNOTSUPP; in airoha_dev_setup_tc_block()
2678 struct net_device *dev = port->dev; in airoha_tc_remove_htb_queue()
2680 netif_set_real_num_tx_queues(dev, dev->real_num_tx_queues - 1); in airoha_tc_remove_htb_queue()
2682 clear_bit(queue, port->qos_sq_bmap); in airoha_tc_remove_htb_queue()
2688 u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; in airoha_tc_htb_delete_leaf_queue()
2690 if (!test_bit(channel, port->qos_sq_bmap)) { in airoha_tc_htb_delete_leaf_queue()
2691 NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); in airoha_tc_htb_delete_leaf_queue()
2692 return -EINVAL; in airoha_tc_htb_delete_leaf_queue()
2704 for_each_set_bit(q, port->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS) in airoha_tc_htb_destroy()
2713 u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; in airoha_tc_get_htb_get_leaf_queue()
2715 if (!test_bit(channel, port->qos_sq_bmap)) { in airoha_tc_get_htb_get_leaf_queue()
2716 NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); in airoha_tc_get_htb_get_leaf_queue()
2717 return -EINVAL; in airoha_tc_get_htb_get_leaf_queue()
2720 opt->qid = AIROHA_NUM_TX_RING + channel; in airoha_tc_get_htb_get_leaf_queue()
2728 switch (opt->command) { in airoha_tc_setup_qdisc_htb()
2743 return -EOPNOTSUPP; in airoha_tc_setup_qdisc_htb()
2763 return -EOPNOTSUPP; in airoha_dev_tc_setup()
2789 for (i = 0; i < ARRAY_SIZE(port->dsa_meta); i++) { in airoha_metadata_dst_alloc()
2795 return -ENOMEM; in airoha_metadata_dst_alloc()
2797 md_dst->u.port_info.port_id = i; in airoha_metadata_dst_alloc()
2798 port->dsa_meta[i] = md_dst; in airoha_metadata_dst_alloc()
2808 for (i = 0; i < ARRAY_SIZE(port->dsa_meta); i++) { in airoha_metadata_dst_free()
2809 if (!port->dsa_meta[i]) in airoha_metadata_dst_free()
2812 metadata_dst_free(port->dsa_meta[i]); in airoha_metadata_dst_free()
2821 for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { in airoha_is_valid_gdm_port()
2822 if (eth->ports[i] == port) in airoha_is_valid_gdm_port()
2840 dev_err(eth->dev, "missing gdm port id\n"); in airoha_alloc_gdm_port()
2841 return -EINVAL; in airoha_alloc_gdm_port()
2845 p = id - 1; in airoha_alloc_gdm_port()
2847 if (!id || id > ARRAY_SIZE(eth->ports)) { in airoha_alloc_gdm_port()
2848 dev_err(eth->dev, "invalid gdm port id: %d\n", id); in airoha_alloc_gdm_port()
2849 return -EINVAL; in airoha_alloc_gdm_port()
2852 if (eth->ports[p]) { in airoha_alloc_gdm_port()
2853 dev_err(eth->dev, "duplicate gdm port id: %d\n", id); in airoha_alloc_gdm_port()
2854 return -EINVAL; in airoha_alloc_gdm_port()
2857 dev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*port), in airoha_alloc_gdm_port()
2861 dev_err(eth->dev, "alloc_etherdev failed\n"); in airoha_alloc_gdm_port()
2862 return -ENOMEM; in airoha_alloc_gdm_port()
2865 qdma = &eth->qdma[index % AIROHA_MAX_NUM_QDMA]; in airoha_alloc_gdm_port()
2866 dev->netdev_ops = &airoha_netdev_ops; in airoha_alloc_gdm_port()
2867 dev->ethtool_ops = &airoha_ethtool_ops; in airoha_alloc_gdm_port()
2868 dev->max_mtu = AIROHA_MAX_MTU; in airoha_alloc_gdm_port()
2869 dev->watchdog_timeo = 5 * HZ; in airoha_alloc_gdm_port()
2870 dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | in airoha_alloc_gdm_port()
2874 dev->features |= dev->hw_features; in airoha_alloc_gdm_port()
2875 dev->vlan_features = dev->hw_features; in airoha_alloc_gdm_port()
2876 dev->dev.of_node = np; in airoha_alloc_gdm_port()
2877 dev->irq = qdma->irq_banks[0].irq; in airoha_alloc_gdm_port()
2878 SET_NETDEV_DEV(dev, eth->dev); in airoha_alloc_gdm_port()
2887 if (err == -EPROBE_DEFER) in airoha_alloc_gdm_port()
2891 dev_info(eth->dev, "generated random MAC address %pM\n", in airoha_alloc_gdm_port()
2892 dev->dev_addr); in airoha_alloc_gdm_port()
2896 u64_stats_init(&port->stats.syncp); in airoha_alloc_gdm_port()
2897 spin_lock_init(&port->stats.lock); in airoha_alloc_gdm_port()
2898 port->qdma = qdma; in airoha_alloc_gdm_port()
2899 port->dev = dev; in airoha_alloc_gdm_port()
2900 port->id = id; in airoha_alloc_gdm_port()
2901 eth->ports[p] = port; in airoha_alloc_gdm_port()
2924 eth = devm_kzalloc(&pdev->dev, sizeof(*eth), GFP_KERNEL); in airoha_probe()
2926 return -ENOMEM; in airoha_probe()
2928 eth->dev = &pdev->dev; in airoha_probe()
2930 err = dma_set_mask_and_coherent(eth->dev, DMA_BIT_MASK(32)); in airoha_probe()
2932 dev_err(eth->dev, "failed configuring DMA mask\n"); in airoha_probe()
2936 eth->fe_regs = devm_platform_ioremap_resource_byname(pdev, "fe"); in airoha_probe()
2937 if (IS_ERR(eth->fe_regs)) in airoha_probe()
2938 return dev_err_probe(eth->dev, PTR_ERR(eth->fe_regs), in airoha_probe()
2941 eth->rsts[0].id = "fe"; in airoha_probe()
2942 eth->rsts[1].id = "pdma"; in airoha_probe()
2943 eth->rsts[2].id = "qdma"; in airoha_probe()
2944 err = devm_reset_control_bulk_get_exclusive(eth->dev, in airoha_probe()
2945 ARRAY_SIZE(eth->rsts), in airoha_probe()
2946 eth->rsts); in airoha_probe()
2948 dev_err(eth->dev, "failed to get bulk reset lines\n"); in airoha_probe()
2952 eth->xsi_rsts[0].id = "xsi-mac"; in airoha_probe()
2953 eth->xsi_rsts[1].id = "hsi0-mac"; in airoha_probe()
2954 eth->xsi_rsts[2].id = "hsi1-mac"; in airoha_probe()
2955 eth->xsi_rsts[3].id = "hsi-mac"; in airoha_probe()
2956 eth->xsi_rsts[4].id = "xfp-mac"; in airoha_probe()
2957 err = devm_reset_control_bulk_get_exclusive(eth->dev, in airoha_probe()
2958 ARRAY_SIZE(eth->xsi_rsts), in airoha_probe()
2959 eth->xsi_rsts); in airoha_probe()
2961 dev_err(eth->dev, "failed to get bulk xsi reset lines\n"); in airoha_probe()
2965 eth->napi_dev = alloc_netdev_dummy(0); in airoha_probe()
2966 if (!eth->napi_dev) in airoha_probe()
2967 return -ENOMEM; in airoha_probe()
2970 eth->napi_dev->threaded = true; in airoha_probe()
2971 strscpy(eth->napi_dev->name, "qdma_eth", sizeof(eth->napi_dev->name)); in airoha_probe()
2978 for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) in airoha_probe()
2979 airoha_qdma_start_napi(&eth->qdma[i]); in airoha_probe()
2982 for_each_child_of_node(pdev->dev.of_node, np) { in airoha_probe()
2983 if (!of_device_is_compatible(np, "airoha,eth-mac")) in airoha_probe()
2999 for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) in airoha_probe()
3000 airoha_qdma_stop_napi(&eth->qdma[i]); in airoha_probe()
3003 for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) in airoha_probe()
3004 airoha_hw_cleanup(&eth->qdma[i]); in airoha_probe()
3006 for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { in airoha_probe()
3007 struct airoha_gdm_port *port = eth->ports[i]; in airoha_probe()
3009 if (port && port->dev->reg_state == NETREG_REGISTERED) { in airoha_probe()
3010 unregister_netdev(port->dev); in airoha_probe()
3014 free_netdev(eth->napi_dev); in airoha_probe()
3025 for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { in airoha_remove()
3026 airoha_qdma_stop_napi(&eth->qdma[i]); in airoha_remove()
3027 airoha_hw_cleanup(&eth->qdma[i]); in airoha_remove()
3030 for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { in airoha_remove()
3031 struct airoha_gdm_port *port = eth->ports[i]; in airoha_remove()
3036 airoha_dev_stop(port->dev); in airoha_remove()
3037 unregister_netdev(port->dev); in airoha_remove()
3040 free_netdev(eth->napi_dev); in airoha_remove()
3047 { .compatible = "airoha,en7581-eth" },