net_device_ops的ndo_open和ndo_start_xmit函数
来源:互联网 发布:家用路由器 知乎 编辑:程序博客网 时间:2024/06/06 10:46
net_device_ops的ndo_open 函数实在dev_open->__dev_open 中打开的.
if (!ret && ops->ndo_open)
ret = ops->ndo_open(dev);
static int hns_nic_net_open(struct net_device *ndev)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
struct hnae_handle *h = priv->ae_handle;
int ret;
//如果是testing 则退出
if (test_bit(NIC_STATE_TESTING, &priv->state))
return -EBUSY;
priv->link = 0;
netif_carrier_off(ndev);
//设置tx queue的个数
ret = netif_set_real_num_tx_queues(ndev, h->q_num);
if (ret < 0) {
netdev_err(ndev, "netif_set_real_num_tx_queues fail, ret=%d!\n",
ret);
return ret;
}
//设置rx queue的个数
ret = netif_set_real_num_rx_queues(ndev, h->q_num);
if (ret < 0) {
netdev_err(ndev,
"netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
return ret;
}
ret = hns_nic_net_up(ndev);
if (ret) {
netdev_err(ndev,
"hns net up fail, ret=%d!\n", ret);
return ret;
}
return 0;
}
static int hns_nic_net_up(struct net_device *ndev)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
struct hnae_handle *h = priv->ae_handle;
int i, j;
int ret;
//初始化中断,并设置中断函数为hns_irq_handle,每个rx和tx queue都对应一个中断
ret = hns_nic_init_irq(priv);
if (ret != 0) {
netdev_err(ndev, "hns init irq failed! ret=%d\n", ret);
return ret;
}
for (i = 0; i < h->q_num * 2; i++) {
//使能中断,使能napi
ret = hns_nic_ring_open(ndev, i);
if (ret)
goto out_has_some_queues;
}
//设置mac地址
ret = h->dev->ops->set_mac_addr(h, ndev->dev_addr);
if (ret)
goto out_set_mac_addr_err;
//hns的start函数为null
ret = h->dev->ops->start ? h->dev->ops->start(h) : 0;
if (ret)
goto out_start_err;
//启动phy
if (ndev->phydev)
phy_start(ndev->phydev);
clear_bit(NIC_STATE_DOWN, &priv->state);
修改time 每一秒到期一次
(void)mod_timer(&priv->service_timer, jiffies + SERVICE_TIMER_HZ);
return 0;
out_start_err:
netif_stop_queue(ndev);
out_set_mac_addr_err:
out_has_some_queues:
for (j = i - 1; j >= 0; j--)
hns_nic_ring_close(ndev, j);
set_bit(NIC_STATE_DOWN, &priv->state);
return ret;
}
static int hns_nic_init_irq(struct hns_nic_priv *priv)
{
struct hnae_handle *h = priv->ae_handle;
struct hns_nic_ring_data *rd;
int i;
int ret;
int cpu;
//这里的rx和tx的queue 个数都是h->q_num,因此h->q_num * 2表示为每个rx和tx都申请一个中断
for (i = 0; i < h->q_num * 2; i++) {
rd = &priv->ring_data[i];
if (rd->ring->irq_init_flag == RCB_IRQ_INITED)
break;
snprintf(rd->ring->ring_name, RCB_RING_NAME_LEN,
"%s-%s%d", priv->netdev->name,
(is_tx_ring(rd->ring) ? "tx" : "rx"), rd->queue_index);
rd->ring->ring_name[RCB_RING_NAME_LEN - 1] = '\0';
//中断的处理函数为hns_irq_handle
ret = request_irq(rd->ring->irq,
hns_irq_handle, 0, rd->ring->ring_name, rd);
if (ret) {
netdev_err(priv->netdev, "request irq(%d) fail\n",
rd->ring->irq);
return ret;
}
//为了要设置irq的affinity,暂时disable irq
disable_irq(rd->ring->irq);
cpu = hns_nic_init_affinity_mask(h->q_num, i,
rd->ring, &rd->mask);
//通过irq_set_affinity_hint 设置irq affintiy
if (cpu_online(cpu))
irq_set_affinity_hint(rd->ring->irq,
&rd->mask);
rd->ring->irq_init_flag = RCB_IRQ_INITED;
}
return 0;
}
static int hns_nic_ring_open(struct net_device *netdev, int idx)
{
struct hns_nic_priv *priv = netdev_priv(netdev);
struct hnae_handle *h = priv->ae_handle;
//先是能napi 再使能中断
napi_enable(&priv->ring_data[idx].napi);
enable_irq(priv->ring_data[idx].ring->irq);
h->dev->ops->toggle_ring_irq(priv->ring_data[idx].ring, 0);
return 0;
}
要从协议层想设备中发送数据,会调用dev_queue_xmit函数。
dev_queue_xmit->__dev_queue_xmit->dev_hard_start_xmit->xmit_one->netdev_start_xmit->__netdev_start_xmit
static inline netdev_tx_t __netdev_start_xmit(const struct net_device_ops *ops,
struct sk_buff *skb, struct net_device *dev,
bool more)
{
skb->xmit_more = more ? 1 : 0;
return ops->ndo_start_xmit(skb, dev);
}
最终调用net device自己的ndo_start_xmit函数来发送,下面这个hns_nic_netdev_ops 中的ndo_start_xmit对应的函数是hns_nic_net_xmit
static const struct net_device_ops hns_nic_netdev_ops = {
.ndo_open = hns_nic_net_open,
.ndo_start_xmit = hns_nic_net_xmit,
};
static netdev_tx_t hns_nic_net_xmit(struct sk_buff *skb,
struct net_device *ndev)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
int ret;
assert(skb->queue_mapping < ndev->ae_handle->q_num);
ret = hns_nic_net_xmit_hw(ndev, skb,
&tx_ring_data(priv, skb->queue_mapping));
if (ret == NETDEV_TX_OK) {
netif_trans_update(ndev);
ndev->stats.tx_bytes += skb->len;
ndev->stats.tx_packets++;
}
return (netdev_tx_t)ret;
}
最终调用hns_nic_net_xmit_hw 发送数据
int hns_nic_net_xmit_hw(struct net_device *ndev,
struct sk_buff *skb,
struct hns_nic_ring_data *ring_data)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
struct hnae_ring *ring = ring_data->ring;
struct device *dev = ring_to_dev(ring);
struct netdev_queue *dev_queue;
struct skb_frag_struct *frag;
int buf_num;
int seg_num;
dma_addr_t dma;
int size, next_to_use;
int i;
switch (priv->ops.maybe_stop_tx(&skb, &buf_num, ring)) {
case -EBUSY:
ring->stats.tx_busy++;
goto out_net_tx_busy;
case -ENOMEM:
ring->stats.sw_err_cnt++;
netdev_err(ndev, "no memory to xmit!\n");
goto out_err_tx_ok;
default:
break;
}
/* no. of segments (plus a header) */
seg_num = skb_shinfo(skb)->nr_frags + 1;
next_to_use = ring->next_to_use;
/* fill the first part */
//得到skb的size
size = skb_headlen(skb);
dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma)) {
netdev_err(ndev, "TX head DMA map failed\n");
ring->stats.sw_err_cnt++;
goto out_err_tx_ok;
}
//填充需要发送的数据
priv->ops.fill_desc(ring, skb, size, dma, seg_num == 1 ? 1 : 0,
buf_num, DESC_TYPE_SKB, ndev->mtu);
/* fill the fragments */
for (i = 1; i < seg_num; i++) {
frag = &skb_shinfo(skb)->frags[i - 1];
size = skb_frag_size(frag);
dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma)) {
netdev_err(ndev, "TX frag(%d) DMA map failed\n", i);
ring->stats.sw_err_cnt++;
goto out_map_frag_fail;
}
priv->ops.fill_desc(ring, skb_frag_page(frag), size, dma,
seg_num - 1 == i ? 1 : 0, buf_num,
DESC_TYPE_PAGE, ndev->mtu);
}
/*complete translate all packets*/
dev_queue = netdev_get_tx_queue(ndev, skb->queue_mapping);
netdev_tx_sent_queue(dev_queue, skb->len);
wmb(); /* commit all data before submit */
assert(skb->queue_mapping < priv->ae_handle->q_num);
//触发硬件发送数据
hnae_queue_xmit(priv->ae_handle->qs[skb->queue_mapping], buf_num);
ring->stats.tx_pkts++;
ring->stats.tx_bytes += skb->len;
return NETDEV_TX_OK;
out_map_frag_fail:
while (ring->next_to_use != next_to_use) {
unfill_desc(ring);
if (ring->next_to_use != next_to_use)
dma_unmap_page(dev,
ring->desc_cb[ring->next_to_use].dma,
ring->desc_cb[ring->next_to_use].length,
DMA_TO_DEVICE);
else
dma_unmap_single(dev,
ring->desc_cb[next_to_use].dma,
ring->desc_cb[next_to_use].length,
DMA_TO_DEVICE);
}
out_err_tx_ok:
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
out_net_tx_busy:
netif_stop_subqueue(ndev, skb->queue_mapping);
/* Herbert's original patch had:
* smp_mb__after_netif_stop_queue();
* but since that doesn't exist yet, just open code it.
*/
smp_mb();
return NETDEV_TX_BUSY;
}
if (!ret && ops->ndo_open)
ret = ops->ndo_open(dev);
static int hns_nic_net_open(struct net_device *ndev)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
struct hnae_handle *h = priv->ae_handle;
int ret;
//如果是testing 则退出
if (test_bit(NIC_STATE_TESTING, &priv->state))
return -EBUSY;
priv->link = 0;
netif_carrier_off(ndev);
//设置tx queue的个数
ret = netif_set_real_num_tx_queues(ndev, h->q_num);
if (ret < 0) {
netdev_err(ndev, "netif_set_real_num_tx_queues fail, ret=%d!\n",
ret);
return ret;
}
//设置rx queue的个数
ret = netif_set_real_num_rx_queues(ndev, h->q_num);
if (ret < 0) {
netdev_err(ndev,
"netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
return ret;
}
ret = hns_nic_net_up(ndev);
if (ret) {
netdev_err(ndev,
"hns net up fail, ret=%d!\n", ret);
return ret;
}
return 0;
}
static int hns_nic_net_up(struct net_device *ndev)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
struct hnae_handle *h = priv->ae_handle;
int i, j;
int ret;
//初始化中断,并设置中断函数为hns_irq_handle,每个rx和tx queue都对应一个中断
ret = hns_nic_init_irq(priv);
if (ret != 0) {
netdev_err(ndev, "hns init irq failed! ret=%d\n", ret);
return ret;
}
for (i = 0; i < h->q_num * 2; i++) {
//使能中断,使能napi
ret = hns_nic_ring_open(ndev, i);
if (ret)
goto out_has_some_queues;
}
//设置mac地址
ret = h->dev->ops->set_mac_addr(h, ndev->dev_addr);
if (ret)
goto out_set_mac_addr_err;
//hns的start函数为null
ret = h->dev->ops->start ? h->dev->ops->start(h) : 0;
if (ret)
goto out_start_err;
//启动phy
if (ndev->phydev)
phy_start(ndev->phydev);
clear_bit(NIC_STATE_DOWN, &priv->state);
修改time 每一秒到期一次
(void)mod_timer(&priv->service_timer, jiffies + SERVICE_TIMER_HZ);
return 0;
out_start_err:
netif_stop_queue(ndev);
out_set_mac_addr_err:
out_has_some_queues:
for (j = i - 1; j >= 0; j--)
hns_nic_ring_close(ndev, j);
set_bit(NIC_STATE_DOWN, &priv->state);
return ret;
}
static int hns_nic_init_irq(struct hns_nic_priv *priv)
{
struct hnae_handle *h = priv->ae_handle;
struct hns_nic_ring_data *rd;
int i;
int ret;
int cpu;
//这里的rx和tx的queue 个数都是h->q_num,因此h->q_num * 2表示为每个rx和tx都申请一个中断
for (i = 0; i < h->q_num * 2; i++) {
rd = &priv->ring_data[i];
if (rd->ring->irq_init_flag == RCB_IRQ_INITED)
break;
snprintf(rd->ring->ring_name, RCB_RING_NAME_LEN,
"%s-%s%d", priv->netdev->name,
(is_tx_ring(rd->ring) ? "tx" : "rx"), rd->queue_index);
rd->ring->ring_name[RCB_RING_NAME_LEN - 1] = '\0';
//中断的处理函数为hns_irq_handle
ret = request_irq(rd->ring->irq,
hns_irq_handle, 0, rd->ring->ring_name, rd);
if (ret) {
netdev_err(priv->netdev, "request irq(%d) fail\n",
rd->ring->irq);
return ret;
}
//为了要设置irq的affinity,暂时disable irq
disable_irq(rd->ring->irq);
cpu = hns_nic_init_affinity_mask(h->q_num, i,
rd->ring, &rd->mask);
//通过irq_set_affinity_hint 设置irq affintiy
if (cpu_online(cpu))
irq_set_affinity_hint(rd->ring->irq,
&rd->mask);
rd->ring->irq_init_flag = RCB_IRQ_INITED;
}
return 0;
}
static int hns_nic_ring_open(struct net_device *netdev, int idx)
{
struct hns_nic_priv *priv = netdev_priv(netdev);
struct hnae_handle *h = priv->ae_handle;
//先是能napi 再使能中断
napi_enable(&priv->ring_data[idx].napi);
enable_irq(priv->ring_data[idx].ring->irq);
h->dev->ops->toggle_ring_irq(priv->ring_data[idx].ring, 0);
return 0;
}
要从协议层想设备中发送数据,会调用dev_queue_xmit函数。
dev_queue_xmit->__dev_queue_xmit->dev_hard_start_xmit->xmit_one->netdev_start_xmit->__netdev_start_xmit
static inline netdev_tx_t __netdev_start_xmit(const struct net_device_ops *ops,
struct sk_buff *skb, struct net_device *dev,
bool more)
{
skb->xmit_more = more ? 1 : 0;
return ops->ndo_start_xmit(skb, dev);
}
最终调用net device自己的ndo_start_xmit函数来发送,下面这个hns_nic_netdev_ops 中的ndo_start_xmit对应的函数是hns_nic_net_xmit
static const struct net_device_ops hns_nic_netdev_ops = {
.ndo_open = hns_nic_net_open,
.ndo_start_xmit = hns_nic_net_xmit,
};
static netdev_tx_t hns_nic_net_xmit(struct sk_buff *skb,
struct net_device *ndev)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
int ret;
assert(skb->queue_mapping < ndev->ae_handle->q_num);
ret = hns_nic_net_xmit_hw(ndev, skb,
&tx_ring_data(priv, skb->queue_mapping));
if (ret == NETDEV_TX_OK) {
netif_trans_update(ndev);
ndev->stats.tx_bytes += skb->len;
ndev->stats.tx_packets++;
}
return (netdev_tx_t)ret;
}
最终调用hns_nic_net_xmit_hw 发送数据
int hns_nic_net_xmit_hw(struct net_device *ndev,
struct sk_buff *skb,
struct hns_nic_ring_data *ring_data)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
struct hnae_ring *ring = ring_data->ring;
struct device *dev = ring_to_dev(ring);
struct netdev_queue *dev_queue;
struct skb_frag_struct *frag;
int buf_num;
int seg_num;
dma_addr_t dma;
int size, next_to_use;
int i;
switch (priv->ops.maybe_stop_tx(&skb, &buf_num, ring)) {
case -EBUSY:
ring->stats.tx_busy++;
goto out_net_tx_busy;
case -ENOMEM:
ring->stats.sw_err_cnt++;
netdev_err(ndev, "no memory to xmit!\n");
goto out_err_tx_ok;
default:
break;
}
/* no. of segments (plus a header) */
seg_num = skb_shinfo(skb)->nr_frags + 1;
next_to_use = ring->next_to_use;
/* fill the first part */
//得到skb的size
size = skb_headlen(skb);
dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma)) {
netdev_err(ndev, "TX head DMA map failed\n");
ring->stats.sw_err_cnt++;
goto out_err_tx_ok;
}
//填充需要发送的数据
priv->ops.fill_desc(ring, skb, size, dma, seg_num == 1 ? 1 : 0,
buf_num, DESC_TYPE_SKB, ndev->mtu);
/* fill the fragments */
for (i = 1; i < seg_num; i++) {
frag = &skb_shinfo(skb)->frags[i - 1];
size = skb_frag_size(frag);
dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma)) {
netdev_err(ndev, "TX frag(%d) DMA map failed\n", i);
ring->stats.sw_err_cnt++;
goto out_map_frag_fail;
}
priv->ops.fill_desc(ring, skb_frag_page(frag), size, dma,
seg_num - 1 == i ? 1 : 0, buf_num,
DESC_TYPE_PAGE, ndev->mtu);
}
/*complete translate all packets*/
dev_queue = netdev_get_tx_queue(ndev, skb->queue_mapping);
netdev_tx_sent_queue(dev_queue, skb->len);
wmb(); /* commit all data before submit */
assert(skb->queue_mapping < priv->ae_handle->q_num);
//触发硬件发送数据
hnae_queue_xmit(priv->ae_handle->qs[skb->queue_mapping], buf_num);
ring->stats.tx_pkts++;
ring->stats.tx_bytes += skb->len;
return NETDEV_TX_OK;
out_map_frag_fail:
while (ring->next_to_use != next_to_use) {
unfill_desc(ring);
if (ring->next_to_use != next_to_use)
dma_unmap_page(dev,
ring->desc_cb[ring->next_to_use].dma,
ring->desc_cb[ring->next_to_use].length,
DMA_TO_DEVICE);
else
dma_unmap_single(dev,
ring->desc_cb[next_to_use].dma,
ring->desc_cb[next_to_use].length,
DMA_TO_DEVICE);
}
out_err_tx_ok:
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
out_net_tx_busy:
netif_stop_subqueue(ndev, skb->queue_mapping);
/* Herbert's original patch had:
* smp_mb__after_netif_stop_queue();
* but since that doesn't exist yet, just open code it.
*/
smp_mb();
return NETDEV_TX_BUSY;
}
阅读全文
0 0
- net_device_ops的ndo_open和ndo_start_xmit函数
- net_device_ops
- dm9000驱动理解四(dm9000操作函数集net_device_ops)
- struct net_device_ops 详解
- net_device & net_device_ops .
- DM9000网卡驱动源码分析系列05 - net_device_ops(ioctl ...)
- SQLite的FLOOR函数和POWER函数和TYPEOF函数
- C++的函数和模板函数
- 指针函数和函数指针的区别
- 函数指针和函数引用的区别
- 宏、函数和宏函数的区别?
- 函数指针和函数引用的区别
- 指针函数和函数指针的区别
- 指针函数和函数指针的区别
- C++的函数和模板函数
- 内联函数和普通函数的区别
- 虚函数和抽象函数的区别
- 函数指针和指针函数的区别
- HDOJ 1026 Ignatius and the Princess I (BFS+优先队列+记录路径)
- MyBatis增强工具pndao-帮你自动写SQL
- Hadoop全分布集群问题及配置
- java运算符
- Redis 安装
- net_device_ops的ndo_open和ndo_start_xmit函数
- 线段的重叠
- android判断APP是否在前台
- Spring学习笔记二
- IntelliJ Idea各种技巧设置笔记和错误解决
- Effective c++(3th) Item9:绝不要在构造和析构期间调用虚拟函数
- es6 promise的使用
- hihocoder 1044 : 状态压缩·一
- Kotlin入门教程——目录索引