Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: axienet: Upgrade descriptors to hold 64-bit addresses

Newer revisions of the AXI DMA IP (>= v7.1) support 64-bit addresses,
both for the descriptors itself, as well as for the buffers they are
pointing to.
This is realised by adding "MSB" words for the next and phys pointer
right behind the existing address word, now named "LSB". These MSB words
live in formerly reserved areas of the descriptor.

If the hardware supports it, write both words when setting an address.
The buffer address is handled by two wrapper functions, the two
occasions where we set the next pointers are open coded.

For now this is guarded by a flag which we don't set yet.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Andre Przywara and committed by
David S. Miller
4e958f33 6a00d0dd

+83 -39
+5 -4
drivers/net/ethernet/xilinx/xilinx_axienet.h
··· 328 328 #define XAE_FEATURE_PARTIAL_TX_CSUM (1 << 1) 329 329 #define XAE_FEATURE_FULL_RX_CSUM (1 << 2) 330 330 #define XAE_FEATURE_FULL_TX_CSUM (1 << 3) 331 + #define XAE_FEATURE_DMA_64BIT (1 << 4) 331 332 332 333 #define XAE_NO_CSUM_OFFLOAD 0 333 334 ··· 341 340 /** 342 341 * struct axidma_bd - Axi Dma buffer descriptor layout 343 342 * @next: MM2S/S2MM Next Descriptor Pointer 344 - * @reserved1: Reserved and not used 343 + * @next_msb: MM2S/S2MM Next Descriptor Pointer (high 32 bits) 345 344 * @phys: MM2S/S2MM Buffer Address 346 - * @reserved2: Reserved and not used 345 + * @phys_msb: MM2S/S2MM Buffer Address (high 32 bits) 347 346 * @reserved3: Reserved and not used 348 347 * @reserved4: Reserved and not used 349 348 * @cntrl: MM2S/S2MM Control value ··· 356 355 */ 357 356 struct axidma_bd { 358 357 u32 next; /* Physical address of next buffer descriptor */ 359 - u32 reserved1; 358 + u32 next_msb; /* high 32 bits for IP >= v7.1, reserved on older IP */ 360 359 u32 phys; 361 - u32 reserved2; 360 + u32 phys_msb; /* for IP >= v7.1, reserved for older IP */ 362 361 u32 reserved3; 363 362 u32 reserved4; 364 363 u32 cntrl;
+78 -35
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
··· 153 153 axienet_dma_out32(lp, reg, lower_32_bits(addr)); 154 154 } 155 155 156 + static void desc_set_phys_addr(struct axienet_local *lp, dma_addr_t addr, 157 + struct axidma_bd *desc) 158 + { 159 + desc->phys = lower_32_bits(addr); 160 + if (lp->features & XAE_FEATURE_DMA_64BIT) 161 + desc->phys_msb = upper_32_bits(addr); 162 + } 163 + 164 + static dma_addr_t desc_get_phys_addr(struct axienet_local *lp, 165 + struct axidma_bd *desc) 166 + { 167 + dma_addr_t ret = desc->phys; 168 + 169 + if (lp->features & XAE_FEATURE_DMA_64BIT) 170 + ret |= ((dma_addr_t)desc->phys_msb << 16) << 16; 171 + 172 + return ret; 173 + } 174 + 156 175 /** 157 176 * axienet_dma_bd_release - Release buffer descriptor rings 158 177 * @ndev: Pointer to the net_device structure ··· 195 176 return; 196 177 197 178 for (i = 0; i < lp->rx_bd_num; i++) { 179 + dma_addr_t phys; 180 + 198 181 /* A NULL skb means this descriptor has not been initialised 199 182 * at all. 200 183 */ ··· 209 188 * descriptor size, after it had been successfully allocated. 210 189 * So a non-zero value in there means we need to unmap it. 211 190 */ 212 - if (lp->rx_bd_v[i].cntrl) 213 - dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys, 191 + if (lp->rx_bd_v[i].cntrl) { 192 + phys = desc_get_phys_addr(lp, &lp->rx_bd_v[i]); 193 + dma_unmap_single(ndev->dev.parent, phys, 214 194 lp->max_frm_size, DMA_FROM_DEVICE); 195 + } 215 196 } 216 197 217 198 dma_free_coherent(ndev->dev.parent, ··· 258 235 goto out; 259 236 260 237 for (i = 0; i < lp->tx_bd_num; i++) { 261 - lp->tx_bd_v[i].next = lp->tx_bd_p + 262 - sizeof(*lp->tx_bd_v) * 263 - ((i + 1) % lp->tx_bd_num); 238 + dma_addr_t addr = lp->tx_bd_p + 239 + sizeof(*lp->tx_bd_v) * 240 + ((i + 1) % lp->tx_bd_num); 241 + 242 + lp->tx_bd_v[i].next = lower_32_bits(addr); 243 + if (lp->features & XAE_FEATURE_DMA_64BIT) 244 + lp->tx_bd_v[i].next_msb = upper_32_bits(addr); 264 245 } 265 246 266 247 for (i = 0; i < lp->rx_bd_num; i++) { 267 - lp->rx_bd_v[i].next = lp->rx_bd_p + 268 - sizeof(*lp->rx_bd_v) * 269 - ((i + 1) % lp->rx_bd_num); 248 + dma_addr_t addr; 249 + 250 + addr = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * 251 + ((i + 1) % lp->rx_bd_num); 252 + lp->rx_bd_v[i].next = lower_32_bits(addr); 253 + if (lp->features & XAE_FEATURE_DMA_64BIT) 254 + lp->rx_bd_v[i].next_msb = upper_32_bits(addr); 270 255 271 256 skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size); 272 257 if (!skb) 273 258 goto out; 274 259 275 260 lp->rx_bd_v[i].skb = skb; 276 - lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent, 277 - skb->data, 278 - lp->max_frm_size, 279 - DMA_FROM_DEVICE); 280 - if (dma_mapping_error(ndev->dev.parent, lp->rx_bd_v[i].phys)) { 261 + addr = dma_map_single(ndev->dev.parent, skb->data, 262 + lp->max_frm_size, DMA_FROM_DEVICE); 263 + if (dma_mapping_error(ndev->dev.parent, addr)) { 281 264 netdev_err(ndev, "DMA mapping error\n"); 282 265 goto out; 283 266 } 267 + desc_set_phys_addr(lp, addr, &lp->rx_bd_v[i]); 284 268 285 269 lp->rx_bd_v[i].cntrl = lp->max_frm_size; 286 270 } ··· 604 574 struct axidma_bd *cur_p; 605 575 int max_bds = nr_bds; 606 576 unsigned int status; 577 + dma_addr_t phys; 607 578 int i; 608 579 609 580 if (max_bds == -1) ··· 620 589 if (nr_bds == -1 && !(status & XAXIDMA_BD_STS_COMPLETE_MASK)) 621 590 break; 622 591 623 - dma_unmap_single(ndev->dev.parent, cur_p->phys, 624 - (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK), 625 - DMA_TO_DEVICE); 592 + phys = desc_get_phys_addr(lp, cur_p); 593 + dma_unmap_single(ndev->dev.parent, phys, 594 + (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK), 595 + DMA_TO_DEVICE); 626 596 627 597 if (cur_p->skb && (status & XAXIDMA_BD_STS_COMPLETE_MASK)) 628 598 dev_consume_skb_irq(cur_p->skb); ··· 719 687 u32 csum_start_off; 720 688 u32 csum_index_off; 721 689 skb_frag_t *frag; 722 - dma_addr_t tail_p; 690 + dma_addr_t tail_p, phys; 723 691 struct axienet_local *lp = netdev_priv(ndev); 724 692 struct axidma_bd *cur_p; 725 693 u32 orig_tail_ptr = lp->tx_bd_tail; ··· 758 726 cur_p->app0 |= 2; /* Tx Full Checksum Offload Enabled */ 759 727 } 760 728 761 - cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, 762 - skb_headlen(skb), DMA_TO_DEVICE); 763 - if (unlikely(dma_mapping_error(ndev->dev.parent, cur_p->phys))) { 729 + phys = dma_map_single(ndev->dev.parent, skb->data, 730 + skb_headlen(skb), DMA_TO_DEVICE); 731 + if (unlikely(dma_mapping_error(ndev->dev.parent, phys))) { 764 732 if (net_ratelimit()) 765 733 netdev_err(ndev, "TX DMA mapping error\n"); 766 734 ndev->stats.tx_dropped++; 767 735 return NETDEV_TX_OK; 768 736 } 737 + desc_set_phys_addr(lp, phys, cur_p); 769 738 cur_p->cntrl = skb_headlen(skb) | XAXIDMA_BD_CTRL_TXSOF_MASK; 770 739 771 740 for (ii = 0; ii < num_frag; ii++) { ··· 774 741 lp->tx_bd_tail = 0; 775 742 cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; 776 743 frag = &skb_shinfo(skb)->frags[ii]; 777 - cur_p->phys = dma_map_single(ndev->dev.parent, 778 - skb_frag_address(frag), 779 - skb_frag_size(frag), 780 - DMA_TO_DEVICE); 781 - if (unlikely(dma_mapping_error(ndev->dev.parent, cur_p->phys))) { 744 + phys = dma_map_single(ndev->dev.parent, 745 + skb_frag_address(frag), 746 + skb_frag_size(frag), 747 + DMA_TO_DEVICE); 748 + if (unlikely(dma_mapping_error(ndev->dev.parent, phys))) { 782 749 if (net_ratelimit()) 783 750 netdev_err(ndev, "TX DMA mapping error\n"); 784 751 ndev->stats.tx_dropped++; ··· 788 755 789 756 return NETDEV_TX_OK; 790 757 } 758 + desc_set_phys_addr(lp, phys, cur_p); 791 759 cur_p->cntrl = skb_frag_size(frag); 792 760 } 793 761 ··· 827 793 cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; 828 794 829 795 while ((cur_p->status & XAXIDMA_BD_STS_COMPLETE_MASK)) { 796 + dma_addr_t phys; 797 + 830 798 tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci; 831 799 832 - dma_unmap_single(ndev->dev.parent, cur_p->phys, 833 - lp->max_frm_size, 800 + phys = desc_get_phys_addr(lp, cur_p); 801 + dma_unmap_single(ndev->dev.parent, phys, lp->max_frm_size, 834 802 DMA_FROM_DEVICE); 835 803 836 804 skb = cur_p->skb; ··· 868 832 if (!new_skb) 869 833 return; 870 834 871 - cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data, 872 - lp->max_frm_size, 873 - DMA_FROM_DEVICE); 874 - if (unlikely(dma_mapping_error(ndev->dev.parent, cur_p->phys))) { 835 + phys = dma_map_single(ndev->dev.parent, new_skb->data, 836 + lp->max_frm_size, 837 + DMA_FROM_DEVICE); 838 + if (unlikely(dma_mapping_error(ndev->dev.parent, phys))) { 875 839 if (net_ratelimit()) 876 840 netdev_err(ndev, "RX DMA mapping error\n"); 877 841 dev_kfree_skb(new_skb); 878 842 return; 879 843 } 844 + desc_set_phys_addr(lp, phys, cur_p); 880 845 881 846 cur_p->cntrl = lp->max_frm_size; 882 847 cur_p->status = 0; ··· 922 885 return IRQ_NONE; 923 886 if (status & XAXIDMA_IRQ_ERROR_MASK) { 924 887 dev_err(&ndev->dev, "DMA Tx error 0x%x\n", status); 925 - dev_err(&ndev->dev, "Current BD is at: 0x%x\n", 888 + dev_err(&ndev->dev, "Current BD is at: 0x%x%08x\n", 889 + (lp->tx_bd_v[lp->tx_bd_ci]).phys_msb, 926 890 (lp->tx_bd_v[lp->tx_bd_ci]).phys); 927 891 928 892 cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); ··· 972 934 return IRQ_NONE; 973 935 if (status & XAXIDMA_IRQ_ERROR_MASK) { 974 936 dev_err(&ndev->dev, "DMA Rx error 0x%x\n", status); 975 - dev_err(&ndev->dev, "Current BD is at: 0x%x\n", 937 + dev_err(&ndev->dev, "Current BD is at: 0x%x%08x\n", 938 + (lp->rx_bd_v[lp->rx_bd_ci]).phys_msb, 976 939 (lp->rx_bd_v[lp->rx_bd_ci]).phys); 977 940 978 941 cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); ··· 1655 1616 1656 1617 for (i = 0; i < lp->tx_bd_num; i++) { 1657 1618 cur_p = &lp->tx_bd_v[i]; 1658 - if (cur_p->cntrl) 1659 - dma_unmap_single(ndev->dev.parent, cur_p->phys, 1619 + if (cur_p->cntrl) { 1620 + dma_addr_t addr = desc_get_phys_addr(lp, cur_p); 1621 + 1622 + dma_unmap_single(ndev->dev.parent, addr, 1660 1623 (cur_p->cntrl & 1661 1624 XAXIDMA_BD_CTRL_LENGTH_MASK), 1662 1625 DMA_TO_DEVICE); 1626 + } 1663 1627 if (cur_p->skb) 1664 1628 dev_kfree_skb_irq(cur_p->skb); 1665 1629 cur_p->phys = 0; 1630 + cur_p->phys_msb = 0; 1666 1631 cur_p->cntrl = 0; 1667 1632 cur_p->status = 0; 1668 1633 cur_p->app0 = 0;