Data transfer on the link layer of the linux protocol stack - data transmission

  
 

Data transmission Before entering the send function, let's look at the e100_up()->e100_alloc_cbs function: static int e100_alloc_cbs(struct nic *nic){struct cb *cb;unsigned int i, count = nic-> ;params.cbs.count;nic->cuc_cmd = cuc_start;nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL;nic->cbs_avail = 0;

//Linear DMA mapping, here is the virtual address, nic->cbs = pci_alloc_consistent(nic->pdev,sizeof(struct cb) * count, &nic->cbs_dma_addr);if(! Nic->cbs)return -ENOMEM;//Create a circular send buffer for(cb = nic->cbs, i = 0; i < count; cb++, i++) {cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1;cb->dma_addr = Nic->cbs_dma_addr + i * sizeof(struct cb);cb->link = cpu_to_le32(nic->cbs_dma_addr +((i+1) % count) * sizeof(struct cb));cb->skb = NULL;}//Initialize each pointer so that it points to the buffer initial position nic->cb_to_use = nic->cb_to_send = ni C->cb_to_clean = nic->cbs;nic->cbs_avail = count;return 0;} In this code, the preparation for the transmission is completed and the send ring cache is established. When sending a number of plays, the data will eventually be sent to the dev->gt_hard_start_xmit function. In the e100 code, that is, e100_xmit_frame(). Go inside and look at: static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev){struct nic *nic = netdev_priv(netdev);int err;if(nic-> Flags & ich_10h_workaround) {e100_exec_cmd(nic, cuc_nop, 0); udelay(1);}err = e100_exec_cb(nic, skb, e100_xmit_prepare);switch(err) {case -ENOSPC:/* We queued the skb, but now We're out of space. */netif_stop_queue(netdev);break;case -ENOMEM:/* This is a hard error - log it. */DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\ " ;);netif_stop_queue(netdev);return 1;}netdev->trans_start = jiffies;return 0;} continue to trace into e100_exec_cb(nic, skb, e100_xmit_prepare); static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb , void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)){struct cb *cb;unsigned long flags;int err = 0;spin_lock_irqsave(&nic->cb_lock, flags);if( Unlikely(!nic->cbs_avail)) {err = -ENOMEM;goto err_unlock;}

//will skb Into the ring send buffer //cb_to_use: the current use position of the send buffer cb = nic-> cb_to_use; nic-> cb_to_use = cb-> next; nic-> cbs_avail--; cb->skb = skb; If(unlikely(!nic->cbs_avail))err = -ENOSPC;cb_prepare(nic, cb, skb);/* Order is important otherwise we'll be in a race with h/w:* set S-bit in Current first, then clear S-bit in previous. */cb->command

Copyright © Windows knowledge All Rights Reserved