1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
| /**
* netcard_ethtool_ops - ethtool操作函数集
*
* 提供用户空间ethtool工具访问设备信息和配置的接口
*/
static const struct ethtool_ops netcard_ethtool_ops = {
.get_settings = netcard_get_settings,
.set_settings = netcard_set_settings,
.get_drvinfo = netcard_get_drvinfo,
.get_regs_len = netcard_get_regs_len,
.get_regs = netcard_get_regs,
.get_wol = netcard_get_wol,
.set_wol = netcard_set_wol,
.nway_reset = netcard_nway_reset,
.get_link = ethtool_op_get_link,
.get_eeprom_len = netcard_get_eeprom_len,
.get_eeprom = netcard_get_eeprom,
.set_eeprom = netcard_set_eeprom,
.get_ringparam = netcard_get_ringparam,
.set_ringparam = netcard_set_ringparam,
.get_pauseparam = netcard_get_pauseparam,
.set_pauseparam = netcard_set_pauseparam,
.self_test = netcard_diag_test,
.get_strings = netcard_get_strings,
.get_sset_count = netcard_get_sset_count,
.get_ethtool_stats = netcard_get_ethtool_stats,
.get_coalesce = netcard_get_coalesce,
.set_coalesce = netcard_set_coalesce,
};
/**
* netcard_get_drvinfo - 获取驱动信息
* @netdev: 网络设备
* @drvinfo: 驱动信息结构
*/
static void netcard_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct netcard_adapter *adapter = netdev_priv(netdev);
strlcpy(drvinfo->driver, "netcard", sizeof(drvinfo->driver));
strlcpy(drvinfo->version, NETCARD_DRIVER_VERSION,
sizeof(drvinfo->version));
strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
drvinfo->regdump_len = netcard_get_regs_len(netdev);
drvinfo->eedump_len = netcard_get_eeprom_len(netdev);
}
/**
* netcard_get_ringparam - 获取环形缓冲区参数
* @netdev: 网络设备
* @ring: 环形参数结构
*/
static void netcard_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct netcard_adapter *adapter = netdev_priv(netdev);
ring->rx_max_pending = NETCARD_MAX_RXD;
ring->tx_max_pending = NETCARD_MAX_TXD;
ring->rx_pending = adapter->rx_ring_count;
ring->tx_pending = adapter->tx_ring_count;
}
/**
* netcard_set_ringparam - 设置环形缓冲区参数
* @netdev: 网络设备
* @ring: 新的环形参数
*
* 返回值:成功返回0,失败返回负错误码
*/
static int netcard_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct netcard_adapter *adapter = netdev_priv(netdev);
struct netcard_adapter temp_adapter;
int err = 0;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
if (ring->tx_pending > NETCARD_MAX_TXD ||
ring->tx_pending < NETCARD_MIN_TXD ||
ring->rx_pending > NETCARD_MAX_RXD ||
ring->rx_pending < NETCARD_MIN_RXD) {
return -EINVAL;
}
if (ring->tx_pending == adapter->tx_ring_count &&
ring->rx_pending == adapter->rx_ring_count) {
/* 没有变化 */
return 0;
}
while (test_and_set_bit(__NETCARD_RESETTING, &adapter->state))
usleep_range(1000, 2000);
if (!netif_running(adapter->netdev)) {
/* 接口未运行,直接更改参数 */
adapter->tx_ring_count = ring->tx_pending;
adapter->rx_ring_count = ring->rx_pending;
goto clear_reset;
}
/* 保存旧的适配器配置 */
memcpy(&temp_adapter, adapter, sizeof(struct netcard_adapter));
/* 设置新的环大小 */
adapter->tx_ring_count = ring->tx_pending;
adapter->rx_ring_count = ring->rx_pending;
/* 重新分配环形缓冲区 */
err = netcard_setup_all_rings(adapter);
if (err) {
/* 恢复旧的配置 */
memcpy(adapter, &temp_adapter, sizeof(struct netcard_adapter));
netcard_setup_all_rings(adapter);
}
clear_reset:
clear_bit(__NETCARD_RESETTING, &adapter->state);
return err;
}
/**
* netcard_get_ethtool_stats - 获取ethtool统计信息
* @netdev: 网络设备
* @stats: 统计信息结构
* @data: 数据数组
*/
static void netcard_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
struct netcard_adapter *adapter = netdev_priv(netdev);
u64 *queue_stat;
int i;
char *p;
netcard_update_stats(adapter);
for (i = 0; i < NETCARD_GLOBAL_STATS_LEN; i++) {
p = (char *)adapter + netcard_gstrings_stats[i].stat_offset;
data[i] = (netcard_gstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
}
|