Tangled for many days, finally understand the b440x processing.
In the last chapter, through the interrupt, the final NIC calls B44_rx () to receive the message
For some of the parameters in this function, you can understand this:
The number of buffers allocated by the bp->rx_cons– processor to the buffer area code
bp->rx_pending–
bp->rx_prod– The last buffer number of the current buffer
Here is the manual of the parameter b440x to understand the function of the following registers:
#define
b44_dmarx_addr 0x0214ul/* DMA RX Descriptor Ring Address */
#define B44_DMARX_PTR 0x0218ul/* DMA RX Last Posted descriptor/
#define B44_DMARX_STAT 0x021cul/* DMA Rx Current Active Desc. + Status * *
Only B44_rx (), b44_dmarx_addr stores the base address of the ring buffer, b44_dmarx_ptr stores the last buffer number of the ring buffer, both of which are set by processing; b44_dmarx_ The stat stores the state and the buffer area code currently processed by the NIC, which can only be set by the NIC.
DMA is also important in network adapters:
In the network card initialization phase, B44_open ()-> b44_alloc_consistent ()
Bp->rx_buffers = Kzalloc (size, GFP);
size = b44_rx_ring_size * sizeof (struct ring_info)
bp->rx_ring = Ssb_dma_alloc_consistent (Bp->sdev, SIZE, & AMP;BP->RX_RING_DMA, GFP);
Size = Dma_table_bytes
Rx_ring is the virtual address of the DMA map, RX_RIND_DMA is the bus address of the DMA map, and this address will be written to the B44_DMARX_ADDR register as the base address of the ring buffer.
Bw32 (BP, b44_dmarx_addr, BP->RX_RING_DMA + bp->dma_offset);
Later in Rx_init_rings ()-> B44_ALLOC_RX_SKB ()
mapping = Ssb_dma_map_single (bp->sdev, Skb->data,rx_pkt_buf_sz,dma_from_device);
Rx_buffers is DMA mapped and the mapped address is stored in rx_ring
Dp->addr = Cpu_to_le32 ((u32) mapping + bp->dma_offset); DP is one of the rx_ring
The approximate process of DMA:
Not accurate, but can refer to the general meaning of
The network card reads B44_DMARX_ADDR and B44_dmarx_stat registers, obtains the next processing struct DMA_DESC, then finds the message buffer according to Dma_desc in addr, Through the DMA processor, the NIC receives the message copy to the addr address, the process CPU is not involved.
prod– the buffer area code that the network card [hardware] handles to
Prod = Br32 (BP, B44_dmarx_stat) & Dmarx_stat_cdmask;
Prod/= sizeof (struct dma_desc);
Cons = bp->rx_cons;
Based on the analysis above, prod reads the B44_DMARX_STAT registers, stores the buffer area code that the NIC is currently working on, and the buffer area code that the cons storage processor handles.
while (cons!= prod && budget > 0) {
Processing the message at the current moment all packets received by the NIC, each processing a message cons will add 1, because it is a ring buffer, so here with the equivalent, rather than size comparison.
struct
ring_info *rp = &bp->rx_buffers[cons];
struct Sk_buff *skb = rp->skb;
dma_addr_t map = rp->mapping;
SKB and map are saved as a closed address, which is used after the swap buffer.
Ssb_dma_sync_single_for_cpu (Bp->sdev, Map,rx_pkt_buf_sz,dma_from_device);
CPU to obtain rx_buffer[cons] control, at this time the NIC can no longer handle the buffer.
RH = (struct Rx_header *) skb->data;
Len = Le16_to_cpu (Rh->len);
.. len-
= 4;