|
我最近在学习e100代码时,有个地方不能理解,哪位大哥帮我解答一下?
e100发送数据的函数是:static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
其中它调用了err = e100_exec_cb(nic, skb, e100_xmit_prepare);
e100_exec_cb的定义如下:
static 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;
}
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 |= cpu_to_le16(cb_s);
wmb();
cb->prev->command &= cpu_to_le16(~cb_s);
while(nic->cb_to_send != nic->cb_to_use) {
if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd,
nic->cb_to_send->dma_addr))) {
/* Ok, here's where things get sticky. It's
* possible that we can't schedule the command
* because the controller is too busy, so
* let's just queue the command and try again
* when another command is scheduled. */
if(err == -ENOSPC) {
//request a reset
schedule_work(&nic->tx_timeout_task);
}
break;
} else {
nic->cuc_cmd = cuc_resume;
nic->cb_to_send = nic->cb_to_send->next;
}
}
err_unlock:
spin_unlock_irqrestore(&nic->cb_lock, flags);
return err;
}
e100_xmit_prepare的定义如下:
static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
struct sk_buff *skb)
{
cb->command = nic->tx_command;
/* interrupt every 16 packets regardless of delay */
if((nic->cbs_avail & ~15) == nic->cbs_avail)
cb->command |= cpu_to_le16(cb_i);
cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
cb->u.tcb.tcb_byte_count = 0;
cb->u.tcb.threshold = nic->tx_threshold;
cb->u.tcb.tbd_count = 1;
cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
skb->data, skb->len, PCI_DMA_TODEVICE));
/* check for mapping failure? */
cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
}
从e100_exec_cb中可以看到发送数据用的DMA 地址是:nic->cb_to_send->dma_addr
但是在e100_xmit_prepare中,它把要发送的数据的地址映射到cb->u.tcb.tbd.buf_addr。
到底是怎么回事啊? |
|