Linux内核里的ixgb驱动代码走读
创始人
2024-05-29 15:42:36
0

代码结构介绍

Linux内核里的ixgb目录为linux/drivers/net/ethernet/intel/ixgb/

目录下内容有

# ls
ixgb_ee.c  ixgb_ee.h  ixgb_ethtool.c  ixgb.h  ixgb_hw.c  ixgb_hw.h  ixgb_ids.h  ixgb_main.c  ixgb_osdep.h  ixgb_param.c  Makefile

ixgb_main.c为ixgb驱动主要实现;

ixgb_hw.c实现了直接操作硬件的接口,主要是对硬件寄存器操作的一层封装,比如phy的读写,led的控制等;

ixgb_ethtool.c主要实现了netdev->ethtool_ops = &ixgb_ethtool_ops;即,网卡的ethtool系列操作;

ixgb_ee.c主要实现了针对网卡设备上的eeprom操作。

具体函数介绍

ixgb_init_module

ixgb驱动的入口函数为ixgb_init_module,当驱动被加载是调用

static int __init
ixgb_init_module(void)
{pr_info("%s\n", ixgb_driver_string);pr_info("%s\n", ixgb_copyright);return pci_register_driver(&ixgb_driver);
}module_init(ixgb_init_module);
/* ixgb_main.c */

pci_register_driver(&ixgb_driver); 将ixgb_driver注册上去,ixgb_driver的实例为

static struct pci_driver ixgb_driver = {.name     = ixgb_driver_name,.id_table = ixgb_pci_tbl,.probe    = ixgb_probe,.remove   = ixgb_remove,.err_handler = &ixgb_err_handler
};
/* ixgb_main.c */

ixgb_probe

当pci bus上匹配到device和driver时,会调用probe函数,probe函数的具体实现如下:

static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{/* PCI设备的初始化 */err = pci_enable_device(pdev);err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));err = pci_request_regions(pdev, ixgb_driver_name);pci_set_master(pdev);netdev = alloc_etherdev(sizeof(struct ixgb_adapter));SET_NETDEV_DEV(netdev, &pdev->dev);pci_set_drvdata(pdev, netdev);/* adapter结构体的初始化 */adapter = netdev_priv(netdev);adapter->netdev = netdev;adapter->pdev = pdev;adapter->hw.back = adapter;adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);adapter->hw.hw_addr = pci_ioremap_bar(pdev, BAR_0);adapter->hw.io_base = pci_resource_start(pdev, i);adapter->bd_number = cards_found;adapter->link_speed = 0;adapter->link_duplex = 0;/* ixgb_netdev_ops是网卡设备操作的重点结构体 */netdev->netdev_ops = &ixgb_netdev_ops;ixgb_set_ethtool_ops(netdev);netdev->watchdog_timeo = 5 * HZ;/* NAPI的poll函数为ixgb_clean,将其挂上结构体 */netif_napi_add(netdev, &adapter->napi, ixgb_clean);/* 设置网卡设备的四有结构体 *//* ixgb_sw_init函数里主要将PCI设备信息和网路设置如MTU信息初始化到adapter->hw */err = ixgb_sw_init(adapter);netdev->hw_features = NETIF_F_SG |NETIF_F_TSO |NETIF_F_HW_CSUM |NETIF_F_HW_VLAN_CTAG_TX |NETIF_F_HW_VLAN_CTAG_RX;netdev->features = netdev->hw_features |NETIF_F_HW_VLAN_CTAG_FILTER;netdev->hw_features |= NETIF_F_RXCSUM;netdev->features |= NETIF_F_HIGHDMA;netdev->vlan_features |= NETIF_F_HIGHDMA;/* MTU range: 68 - 16114 */netdev->min_mtu = ETH_MIN_MTU;netdev->max_mtu = IXGB_MAX_JUMBO_FRAME_SIZE - ETH_HLEN;/* 初始化定时器 */timer_setup(&adapter->watchdog_timer, ixgb_watchdog, 0);INIT_WORK(&adapter->tx_timeout_task, ixgb_tx_timeout_task);/* 注册设备 */err = register_netdev(netdev);/* carrier off reporting is important to ethtool even BEFORE open */netif_carrier_off(netdev);ixgb_check_options(adapter);/* 用新的配置重新硬件, ixgb_reset内的重点函数是ixgb_init_hw */ixgb_reset(adapter);cards_found++;return 0;
}
/* ixgb_main.c */

ixgb_probe函数里涉及到的初始化结构体ixgb_netdev_ops实现如下:

static const struct net_device_ops ixgb_netdev_ops = {.ndo_open               = ixgb_open,.ndo_stop               = ixgb_close,.ndo_start_xmit         = ixgb_xmit_frame,.ndo_set_rx_mode        = ixgb_set_multi,.ndo_validate_addr      = eth_validate_addr,.ndo_set_mac_address    = ixgb_set_mac,.ndo_change_mtu         = ixgb_change_mtu,.ndo_tx_timeout         = ixgb_tx_timeout,.ndo_vlan_rx_add_vid    = ixgb_vlan_rx_add_vid,.ndo_vlan_rx_kill_vid   = ixgb_vlan_rx_kill_vid,.ndo_fix_features       = ixgb_fix_features,.ndo_set_features       = ixgb_set_features,
};
/* ixgb_main.c */

ixgb_open

每当网络接口被UP激活的时候,ixgb_open函数都会被调用,ixgb_open的具体实现如下:

static int ixgb_open(struct net_device *netdev)
{struct ixgb_adapter *adapter = netdev_priv(netdev);/* 分配发送数据包的描述体资源,使用dma_alloc_coherent初始化TX Descriptor Ring */err = ixgb_setup_tx_resources(adapter);netif_carrier_off(netdev);/* 分配接收数据包的描述体资源,使用dma_alloc_coherent初始化RX Descriptor Ring */err = ixgb_setup_rx_resources(adapter);/* 将网卡接口UP起来的一系列操作 */err = ixgb_up(adapter);/* 允许上层协议栈调用网卡设备的hard_start_xmit功能 */netif_start_queue(netdev);return 0;err_up:ixgb_free_rx_resources(adapter);
err_setup_rx:ixgb_free_tx_resources(adapter);
err_setup_tx:ixgb_reset(adapter);return err;
}
/* ixgb_main.c */

ixgb_close

当网络接口被link down的时候,ixgb_close函数被调用,ixgb_close的具体实现如下:

static int
ixgb_close(struct net_device *netdev)
{struct ixgb_adapter *adapter = netdev_priv(netdev);ixgb_down(adapter, true);ixgb_free_tx_resources(adapter);ixgb_free_rx_resources(adapter);return 0;
}
/* ixgb_main.c */

ixgb_xmit_frame

当协议栈要发送数据包时,会调用ixgb_xmit_frame,ixgb_xmit_frame的具体实现如下:

static netdev_tx_t ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{struct ixgb_adapter *adapter = netdev_priv(netdev);unsigned int first;unsigned int tx_flags = 0;int vlan_id = 0;int count = 0;int tso;first = adapter->tx_ring.next_to_use;/* 是否做TCP Segment Offload,即TCP字段硬件卸载 */tso = ixgb_tso(adapter, skb);if (likely(tso))tx_flags |= IXGB_TX_FLAGS_TSO;else if (ixgb_tx_csum(adapter, skb)) /* 是否做校验和的硬件卸载 */tx_flags |= IXGB_TX_FLAGS_CSUM;/* ixgb_tx_map为网卡具体发送数据包的函数* 实际操作是使用buffer_info->dma = dma_map_single(&pdev->dev, skb->data + offset,size, DMA_TO_DEVICE);* 将发送数据包skb->data映射到host与NIC交互的TX Ring的DMA空间上。*/count = ixgb_tx_map(adapter, skb, first); if (count) {/* 根据count,遍历填充tx_desc,把数据包交给网卡设备发出去* tx_desc->buff_addr = cpu_to_le64(buffer_info->dma);*/ixgb_tx_queue(adapter, count, vlan_id, tx_flags);/* Make sure there is space in the ring for the next send. */ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED);} else {dev_kfree_skb_any(skb);adapter->tx_ring.buffer_info[first].time_stamp = 0;adapter->tx_ring.next_to_use = first;}return NETDEV_TX_OK;
}
/* ixgb_main.c */

ixgb_clean

网卡的收数据包部分,采用NAPI机制,即在ixgb_probe函数里有

netif_napi_add(netdev, &adapter->napi, ixgb_clean);执行语句,其中ixgb_clean为NAPI Polling函数,让我们来看看ixgb_clean的具体实现:

static int ixgb_clean(struct napi_struct *napi, int budget)
{struct ixgb_adapter *adapter = container_of(napi, struct ixgb_adapter, napi);int work_done = 0;ixgb_clean_tx_irq(adapter);ixgb_clean_rx_irq(adapter, &work_done, budget);/* If budget not fully consumed, exit the polling mode */if (work_done < budget) {napi_complete_done(napi, work_done);if (!test_bit(__IXGB_DOWN, &adapter->flags))ixgb_irq_enable(adapter);}return work_done;
}

设置网卡的features,网络协议栈会查询这些feature了解网卡的能力做对数据包做不同的处理,比如网卡是否支持tso的硬件卸载,是否支持checksum的硬件卸载都在features里有所体现

static int ixgb_set_features(struct net_device *netdev, netdev_features_t features)
{struct ixgb_adapter *adapter = netdev_priv(netdev);netdev_features_t changed = features ^ netdev->features;if (!(changed & (NETIF_F_RXCSUM|NETIF_F_HW_VLAN_CTAG_RX)))return 0;adapter->rx_csum = !!(features & NETIF_F_RXCSUM);if (netif_running(netdev)) {ixgb_down(adapter, true);ixgb_up(adapter);ixgb_set_speed_duplex(netdev);} elseixgb_reset(adapter);return 0;
}
/* ixgb_main.c */

相关内容

热门资讯

Python|位运算|数组|动... 目录 1、只出现一次的数字(位运算,数组) 示例 选项代...
张岱的人物生平 张岱的人物生平张岱(414年-484年),字景山,吴郡吴县(今江苏苏州)人。南朝齐大臣。祖父张敞,东...
西游西后传演员女人物 西游西后传演员女人物西游西后传演员女人物 孙悟空 六小龄童 唐僧 徐少华 ...
名人故事中贾岛作诗内容简介 名人故事中贾岛作诗内容简介有一次,贾岛骑驴闯了官道.他正琢磨着一句诗,名叫《题李凝幽居》全诗如下:闲...
和男朋友一起优秀的文案? 和男朋友一起优秀的文案?1.希望是惟一所有的人都共同享有的好处;一无所有的人,仍拥有希望。2.生活,...
戴玉手镯的好处 戴玉手镯好还是... 戴玉手镯的好处 戴玉手镯好还是碧玺好 女人戴玉?戴玉好还是碧玺好点佩戴手镯,以和田玉手镯为佳!相嫌滑...
依然什么意思? 依然什么意思?依然(汉语词语)依然,汉语词汇。拼音:yī    rán基本解释:副词,指照往常、依旧...
高尔基的散文诗 高尔基的散文诗《海燕》、《大学》、《母亲》、《童年》这些都是比较出名的一些代表作。
心在飞扬作者简介 心在飞扬作者简介心在飞扬作者简介如下。根据相关公开资料查询,心在飞扬是一位优秀的小说作者,他的小说作...
卡什坦卡的故事赏析? 卡什坦卡的故事赏析?讲了一只小狗的故事, 我也是近来才读到这篇小说. 作家对动物的拟人描写真是惟妙...
林绍涛为简艾拿绿豆糕是哪一集 林绍涛为简艾拿绿豆糕是哪一集第三十二集。 贾宽认为是阎帅间接导致刘映霞住了院,第二天上班,他按捺不...
小爱同学是女生吗小安同学什么意... 小爱同学是女生吗小安同学什么意思 小爱同学,小安同学说你是女生。小安是男的。
内分泌失调导致脸上长斑,怎么调... 内分泌失调导致脸上长斑,怎么调理内分泌失调导致脸上长斑,怎么调理先调理内分泌,去看中医吧,另外用好的...
《魔幻仙境》刺客,骑士人物属性... 《魔幻仙境》刺客,骑士人物属性加点魔幻仙境骑士2功1体质
很喜欢她,该怎么办? 很喜欢她,该怎么办?太冷静了!! 太理智了!爱情是需要冲劲的~不要考虑着考虑那~否则缘...
言情小说作家 言情小说作家我比较喜欢匪我思存的,很虐,很悲,还有梅子黄时雨,笙离,叶萱,还有安宁的《温暖的玄》 小...
两个以名人的名字命名的风景名胜... 两个以名人的名字命名的风景名胜?快太白楼,李白。尚志公园,赵尚志。
幼儿教育的代表人物及其著作 幼儿教育的代表人物及其著作卡尔威特的《卡尔威特的教育》,小卡尔威特,他儿子成了天才后写的《小卡尔威特...
海贼王中为什么说路飞打凯多靠霸... 海贼王中为什么说路飞打凯多靠霸气升级?凯多是靠霸气升级吗?因为之前刚到时确实打不过人家因为路飞的实力...
运气不好拜财神有用吗运气不好拜... 运气不好拜财神有用吗运气不好拜财神有没有用1、运气不好拜财神有用。2、拜财神上香前先点蜡烛,照亮人神...