Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
7190c16a
Commit
7190c16a
authored
May 27, 2004
by
Ganesh Venkatesan
Committed by
Jeff Garzik
May 27, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] e1000 6/7: ethtool_ops support
parent
8e101155
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
308 additions
and
417 deletions
+308
-417
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000.h
+1
-0
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_ethtool.c
+304
-414
drivers/net/e1000/e1000_main.c
drivers/net/e1000/e1000_main.c
+3
-3
No files found.
drivers/net/e1000/e1000.h
View file @
7190c16a
...
...
@@ -245,5 +245,6 @@ struct e1000_adapter {
uint32_t
pci_state
[
16
];
int
msg_enable
;
};
#endif
/* _E1000_H_ */
drivers/net/e1000/e1000_ethtool.c
View file @
7190c16a
...
...
@@ -53,7 +53,7 @@ struct e1000_stats {
#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \
offsetof(struct e1000_adapter, m)
static
struct
e1000_stats
e1000_gstrings_stats
[]
=
{
static
const
struct
e1000_stats
e1000_gstrings_stats
[]
=
{
{
"rx_packets"
,
E1000_STAT
(
net_stats
.
rx_packets
)
},
{
"tx_packets"
,
E1000_STAT
(
net_stats
.
tx_packets
)
},
{
"rx_bytes"
,
E1000_STAT
(
net_stats
.
rx_bytes
)
},
...
...
@@ -89,20 +89,22 @@ static struct e1000_stats e1000_gstrings_stats[] = {
{
"tx_flow_control_xon"
,
E1000_STAT
(
stats
.
xontxc
)
},
{
"tx_flow_control_xoff"
,
E1000_STAT
(
stats
.
xofftxc
)
},
{
"rx_csum_offload_good"
,
E1000_STAT
(
hw_csum_good
)
},
{
"rx_csum_offload_errors"
,
E1000_STAT
(
hw_csum_err
)
}
{
"rx_csum_offload_errors"
,
E1000_STAT
(
hw_csum_err
)
},
{
"rx_long_byte_count"
,
E1000_STAT
(
stats
.
gorcl
)
}
};
#define E1000_STATS_LEN \
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
static
char
e1000_gstrings_test
[][
ETH_GSTRING_LEN
]
=
{
static
c
onst
c
har
e1000_gstrings_test
[][
ETH_GSTRING_LEN
]
=
{
"Register test (offline)"
,
"Eeprom test (offline)"
,
"Interrupt test (offline)"
,
"Loopback test (offline)"
,
"Link test (on/offline)"
};
#define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN
static
void
e1000_
ethtool_gset
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_cmd
*
ecmd
)
static
int
e1000_
get_settings
(
struct
net_device
*
netdev
,
struct
ethtool_cmd
*
ecmd
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
if
(
hw
->
media_type
==
e1000_media_type_copper
)
{
...
...
@@ -169,11 +171,13 @@ e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
}
ecmd
->
autoneg
=
(
hw
->
autoneg
?
AUTONEG_ENABLE
:
AUTONEG_DISABLE
);
return
0
;
}
static
int
e1000_
ethtool_sset
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_cmd
*
ecmd
)
e1000_
set_settings
(
struct
net_device
*
netdev
,
struct
ethtool_cmd
*
ecmd
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
if
(
ecmd
->
autoneg
==
AUTONEG_ENABLE
)
{
...
...
@@ -195,42 +199,41 @@ e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
return
0
;
}
static
int
e1000_
ethtool_gpause
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_pauseparam
*
e
pause
)
static
void
e1000_
get_pauseparam
(
struct
net_device
*
netdev
,
struct
ethtool_pauseparam
*
pause
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
epause
->
autoneg
=
pause
->
autoneg
=
(
adapter
->
fc_autoneg
?
AUTONEG_ENABLE
:
AUTONEG_DISABLE
);
if
(
hw
->
fc
==
e1000_fc_rx_pause
)
e
pause
->
rx_pause
=
1
;
pause
->
rx_pause
=
1
;
else
if
(
hw
->
fc
==
e1000_fc_tx_pause
)
e
pause
->
tx_pause
=
1
;
pause
->
tx_pause
=
1
;
else
if
(
hw
->
fc
==
e1000_fc_full
)
{
e
pause
->
rx_pause
=
1
;
e
pause
->
tx_pause
=
1
;
pause
->
rx_pause
=
1
;
pause
->
tx_pause
=
1
;
}
return
0
;
}
static
int
e1000_
ethtool_spause
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_pauseparam
*
e
pause
)
e1000_
set_pauseparam
(
struct
net_device
*
netdev
,
struct
ethtool_pauseparam
*
pause
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
adapter
->
fc_autoneg
=
e
pause
->
autoneg
;
adapter
->
fc_autoneg
=
pause
->
autoneg
;
if
(
epause
->
rx_pause
&&
e
pause
->
tx_pause
)
if
(
pause
->
rx_pause
&&
pause
->
tx_pause
)
hw
->
fc
=
e1000_fc_full
;
else
if
(
epause
->
rx_pause
&&
!
e
pause
->
tx_pause
)
else
if
(
pause
->
rx_pause
&&
!
pause
->
tx_pause
)
hw
->
fc
=
e1000_fc_rx_pause
;
else
if
(
!
epause
->
rx_pause
&&
e
pause
->
tx_pause
)
else
if
(
!
pause
->
rx_pause
&&
pause
->
tx_pause
)
hw
->
fc
=
e1000_fc_tx_pause
;
else
if
(
!
epause
->
rx_pause
&&
!
e
pause
->
tx_pause
)
else
if
(
!
pause
->
rx_pause
&&
!
pause
->
tx_pause
)
hw
->
fc
=
e1000_fc_none
;
hw
->
original_fc
=
hw
->
fc
;
...
...
@@ -248,28 +251,124 @@ e1000_ethtool_spause(struct e1000_adapter *adapter,
return
0
;
}
static
uint32_t
e1000_get_rx_csum
(
struct
net_device
*
netdev
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
return
adapter
->
rx_csum
;
}
static
int
e1000_set_rx_csum
(
struct
net_device
*
netdev
,
uint32_t
data
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
adapter
->
rx_csum
=
data
;
if
(
netif_running
(
netdev
))
{
e1000_down
(
adapter
);
e1000_up
(
adapter
);
}
else
e1000_reset
(
adapter
);
return
0
;
}
static
uint32_t
e1000_get_tx_csum
(
struct
net_device
*
netdev
)
{
return
(
netdev
->
features
&
NETIF_F_HW_CSUM
)
!=
0
;
}
static
int
e1000_set_tx_csum
(
struct
net_device
*
netdev
,
uint32_t
data
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
if
(
adapter
->
hw
.
mac_type
<
e1000_82543
)
{
if
(
!
data
)
return
-
EINVAL
;
return
0
;
}
if
(
data
)
netdev
->
features
|=
NETIF_F_HW_CSUM
;
else
netdev
->
features
&=
~
NETIF_F_HW_CSUM
;
return
0
;
}
static
uint32_t
e1000_get_sg
(
struct
net_device
*
netdev
)
{
return
(
netdev
->
features
&
NETIF_F_SG
)
!=
0
;
}
static
int
e1000_set_sg
(
struct
net_device
*
netdev
,
uint32_t
data
)
{
if
(
data
)
netdev
->
features
|=
NETIF_F_SG
;
else
netdev
->
features
&=
~
NETIF_F_SG
;
return
0
;
}
#ifdef NETIF_F_TSO
static
uint32_t
e1000_get_tso
(
struct
net_device
*
netdev
)
{
return
(
netdev
->
features
&
NETIF_F_TSO
)
!=
0
;
}
static
int
e1000_set_tso
(
struct
net_device
*
netdev
,
uint32_t
data
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
if
((
adapter
->
hw
.
mac_type
<
e1000_82544
)
||
(
adapter
->
hw
.
mac_type
==
e1000_82547
))
return
data
?
-
EINVAL
:
0
;
if
(
data
)
netdev
->
features
|=
NETIF_F_TSO
;
else
netdev
->
features
&=
~
NETIF_F_TSO
;
return
0
;
}
#endif
/* NETIF_F_TSO */
static
uint32_t
e1000_get_msglevel
(
struct
net_device
*
netdev
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
return
adapter
->
msg_enable
;
}
static
void
e1000_ethtool_gdrvinfo
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_drvinfo
*
drvinfo
)
e1000_set_msglevel
(
struct
net_device
*
netdev
,
uint32_t
data
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
adapter
->
msg_enable
=
data
;
}
static
int
e1000_get_regs_len
(
struct
net_device
*
netdev
)
{
strncpy
(
drvinfo
->
driver
,
e1000_driver_name
,
32
);
strncpy
(
drvinfo
->
version
,
e1000_driver_version
,
32
);
strncpy
(
drvinfo
->
fw_version
,
"N/A"
,
32
);
strncpy
(
drvinfo
->
bus_info
,
pci_name
(
adapter
->
pdev
),
32
);
drvinfo
->
n_stats
=
E1000_STATS_LEN
;
drvinfo
->
testinfo_len
=
E1000_TEST_LEN
;
#define E1000_REGS_LEN 32
drvinfo
->
regdump_len
=
E1000_REGS_LEN
*
sizeof
(
uint32_t
);
drvinfo
->
eedump_len
=
adapter
->
hw
.
eeprom
.
word_size
*
2
;
return
E1000_REGS_LEN
*
sizeof
(
uint32_t
);
}
static
void
e1000_
ethtool_gregs
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_regs
*
regs
,
uint32_t
*
regs_buff
)
e1000_
get_regs
(
struct
net_device
*
netdev
,
struct
ethtool_regs
*
regs
,
void
*
p
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
uint32_t
*
regs_buff
=
p
;
uint16_t
phy_data
;
memset
(
p
,
0
,
E1000_REGS_LEN
*
sizeof
(
uint32_t
));
regs
->
version
=
(
1
<<
24
)
|
(
hw
->
revision_id
<<
16
)
|
hw
->
device_id
;
regs_buff
[
0
]
=
E1000_READ_REG
(
hw
,
CTRL
);
...
...
@@ -342,37 +441,39 @@ e1000_ethtool_gregs(struct e1000_adapter *adapter,
e1000_read_phy_reg
(
hw
,
PHY_1000T_STATUS
,
&
phy_data
);
regs_buff
[
24
]
=
(
uint32_t
)
phy_data
;
/* phy local receiver status */
regs_buff
[
25
]
=
regs_buff
[
24
];
/* phy remote receiver status */
}
return
;
static
int
e1000_get_eeprom_len
(
struct
net_device
*
netdev
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
return
adapter
->
hw
.
eeprom
.
word_size
*
2
;
}
static
int
e1000_
ethtool_geeprom
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_eeprom
*
eeprom
,
uint
16_t
*
eeprom_buff
)
e1000_
get_eeprom
(
struct
net_device
*
netdev
,
struct
ethtool_eeprom
*
eeprom
,
uint
8_t
*
bytes
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
uint16_t
*
eeprom_buff
;
int
first_word
,
last_word
;
int
ret_val
=
0
;
uint16_t
i
;
if
(
eeprom
->
len
==
0
)
{
ret_val
=
-
EINVAL
;
goto
geeprom_error
;
}
if
(
eeprom
->
len
==
0
)
return
-
EINVAL
;
eeprom
->
magic
=
hw
->
vendor_id
|
(
hw
->
device_id
<<
16
);
if
(
eeprom
->
offset
>
eeprom
->
offset
+
eeprom
->
len
)
{
ret_val
=
-
EINVAL
;
goto
geeprom_error
;
}
if
((
eeprom
->
offset
+
eeprom
->
len
)
>
(
hw
->
eeprom
.
word_size
*
2
))
eeprom
->
len
=
((
hw
->
eeprom
.
word_size
*
2
)
-
eeprom
->
offset
);
first_word
=
eeprom
->
offset
>>
1
;
last_word
=
(
eeprom
->
offset
+
eeprom
->
len
-
1
)
>>
1
;
eeprom_buff
=
kmalloc
(
sizeof
(
uint16_t
)
*
(
last_word
-
first_word
+
1
),
GFP_KERNEL
);
if
(
!
eeprom_buff
)
return
-
ENOMEM
;
if
(
hw
->
eeprom
.
type
==
e1000_eeprom_spi
)
ret_val
=
e1000_read_eeprom
(
hw
,
first_word
,
last_word
-
first_word
+
1
,
...
...
@@ -388,14 +489,19 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter,
for
(
i
=
0
;
i
<
last_word
-
first_word
+
1
;
i
++
)
le16_to_cpus
(
&
eeprom_buff
[
i
]);
geeprom_error:
memcpy
(
bytes
,
(
uint8_t
*
)
eeprom_buff
+
(
eeprom
->
offset
%
2
),
eeprom
->
len
);
kfree
(
eeprom_buff
);
return
ret_val
;
}
static
int
e1000_
ethtool_seeprom
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_eeprom
*
eeprom
,
void
*
user_data
)
e1000_
set_eeprom
(
struct
net_device
*
netdev
,
struct
ethtool_eeprom
*
eeprom
,
uint8_t
*
bytes
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
uint16_t
*
eeprom_buff
;
void
*
ptr
;
...
...
@@ -410,9 +516,6 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
max_len
=
hw
->
eeprom
.
word_size
*
2
;
if
((
eeprom
->
offset
+
eeprom
->
len
)
>
max_len
)
eeprom
->
len
=
(
max_len
-
eeprom
->
offset
);
first_word
=
eeprom
->
offset
>>
1
;
last_word
=
(
eeprom
->
offset
+
eeprom
->
len
-
1
)
>>
1
;
eeprom_buff
=
kmalloc
(
max_len
,
GFP_KERNEL
);
...
...
@@ -439,11 +542,7 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
for
(
i
=
0
;
i
<
last_word
-
first_word
+
1
;
i
++
)
le16_to_cpus
(
&
eeprom_buff
[
i
]);
if
((
ret_val
!=
0
)
||
copy_from_user
(
ptr
,
user_data
,
eeprom
->
len
))
{
ret_val
=
-
EFAULT
;
goto
seeprom_error
;
}
memcpy
(
ptr
,
bytes
,
eeprom
->
len
);
for
(
i
=
0
;
i
<
last_word
-
first_word
+
1
;
i
++
)
eeprom_buff
[
i
]
=
cpu_to_le16
(
eeprom_buff
[
i
]);
...
...
@@ -454,15 +553,31 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
if
((
ret_val
==
0
)
&&
first_word
<=
EEPROM_CHECKSUM_REG
)
e1000_update_eeprom_checksum
(
hw
);
seeprom_error:
kfree
(
eeprom_buff
);
return
ret_val
;
}
static
int
e1000_ethtool_gring
(
struct
e1000_adapter
*
adapter
,
static
void
e1000_get_drvinfo
(
struct
net_device
*
netdev
,
struct
ethtool_drvinfo
*
drvinfo
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
strncpy
(
drvinfo
->
driver
,
e1000_driver_name
,
32
);
strncpy
(
drvinfo
->
version
,
e1000_driver_version
,
32
);
strncpy
(
drvinfo
->
fw_version
,
"N/A"
,
32
);
strncpy
(
drvinfo
->
bus_info
,
pci_name
(
adapter
->
pdev
),
32
);
drvinfo
->
n_stats
=
E1000_STATS_LEN
;
drvinfo
->
testinfo_len
=
E1000_TEST_LEN
;
drvinfo
->
regdump_len
=
e1000_get_regs_len
(
netdev
);
drvinfo
->
eedump_len
=
e1000_get_eeprom_len
(
netdev
);
}
static
void
e1000_get_ringparam
(
struct
net_device
*
netdev
,
struct
ethtool_ringparam
*
ring
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
e1000_mac_type
mac_type
=
adapter
->
hw
.
mac_type
;
struct
e1000_desc_ring
*
txdr
=
&
adapter
->
tx_ring
;
struct
e1000_desc_ring
*
rxdr
=
&
adapter
->
rx_ring
;
...
...
@@ -477,14 +592,14 @@ e1000_ethtool_gring(struct e1000_adapter *adapter,
ring
->
tx_pending
=
txdr
->
count
;
ring
->
rx_mini_pending
=
0
;
ring
->
rx_jumbo_pending
=
0
;
return
0
;
}
static
int
e1000_
ethtool_sring
(
struct
e1000_adapter
*
adapter
,
e1000_
set_ringparam
(
struct
net_device
*
netdev
,
struct
ethtool_ringparam
*
ring
)
{
int
err
;
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
e1000_mac_type
mac_type
=
adapter
->
hw
.
mac_type
;
struct
e1000_desc_ring
*
txdr
=
&
adapter
->
tx_ring
;
struct
e1000_desc_ring
*
rxdr
=
&
adapter
->
rx_ring
;
...
...
@@ -538,6 +653,7 @@ e1000_ethtool_sring(struct e1000_adapter *adapter,
return
err
;
}
#define REG_PATTERN_TEST(R, M, W) \
{ \
uint32_t pat, value; \
...
...
@@ -628,6 +744,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
for
(
i
=
0
;
i
<
E1000_MC_TBL_SIZE
;
i
++
)
REG_PATTERN_TEST
(
MTA
+
(
i
<<
2
),
0xFFFFFFFF
,
0xFFFFFFFF
);
*
data
=
0
;
return
0
;
}
...
...
@@ -939,8 +1056,6 @@ e1000_phy_disable_receiver(struct e1000_adapter *adapter)
e1000_write_phy_reg
(
&
adapter
->
hw
,
30
,
0x8FFC
);
e1000_write_phy_reg
(
&
adapter
->
hw
,
29
,
0x001A
);
e1000_write_phy_reg
(
&
adapter
->
hw
,
30
,
0x8FF0
);
return
;
}
static
void
...
...
@@ -1219,7 +1334,7 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
for
(
i
=
0
;
i
<
64
;
i
++
)
{
e1000_create_lbtest_frame
(
txdr
->
buffer_info
[
i
].
skb
,
1024
);
pci_dma_sync_single
_for_device
(
pdev
,
txdr
->
buffer_info
[
i
].
dma
,
pci_dma_sync_single
(
pdev
,
txdr
->
buffer_info
[
i
].
dma
,
txdr
->
buffer_info
[
i
].
length
,
PCI_DMA_TODEVICE
);
}
...
...
@@ -1227,7 +1342,7 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
msec_delay
(
200
);
pci_dma_sync_single
_for_cpu
(
pdev
,
rxdr
->
buffer_info
[
0
].
dma
,
pci_dma_sync_single
(
pdev
,
rxdr
->
buffer_info
[
0
].
dma
,
rxdr
->
buffer_info
[
0
].
length
,
PCI_DMA_FROMDEVICE
);
return
e1000_check_lbtest_frame
(
rxdr
->
buffer_info
[
0
].
skb
,
1024
);
...
...
@@ -1258,14 +1373,26 @@ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
}
static
int
e1000_ethtool_test
(
struct
e1000_adapter
*
adapter
,
e1000_diag_test_count
(
struct
net_device
*
netdev
)
{
return
E1000_TEST_LEN
;
}
static
void
e1000_diag_test
(
struct
net_device
*
netdev
,
struct
ethtool_test
*
eth_test
,
uint64_t
*
data
)
{
boolean_t
if_running
=
netif_running
(
adapter
->
netdev
);
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
boolean_t
if_running
=
netif_running
(
netdev
);
if
(
eth_test
->
flags
==
ETH_TEST_FL_OFFLINE
)
{
/* Offline tests */
/* save speed, duplex, autoneg settings */
uint16_t
autoneg_advertised
=
adapter
->
hw
.
autoneg_advertised
;
uint8_t
forced_speed_duplex
=
adapter
->
hw
.
forced_speed_duplex
;
uint8_t
autoneg
=
adapter
->
hw
.
autoneg
;
/* Link test performed before hardware reset so autoneg doesn't
* interfere with test result */
if
(
e1000_link_test
(
adapter
,
&
data
[
4
]))
...
...
@@ -1291,6 +1418,10 @@ e1000_ethtool_test(struct e1000_adapter *adapter,
if
(
e1000_loopback_test
(
adapter
,
&
data
[
3
]))
eth_test
->
flags
|=
ETH_TEST_FL_FAILED
;
/* restore Autoneg/speed/duplex settings */
adapter
->
hw
.
autoneg_advertised
=
autoneg_advertised
;
adapter
->
hw
.
forced_speed_duplex
=
forced_speed_duplex
;
adapter
->
hw
.
autoneg
=
autoneg
;
e1000_reset
(
adapter
);
if
(
if_running
)
e1000_up
(
adapter
);
...
...
@@ -1305,12 +1436,12 @@ e1000_ethtool_test(struct e1000_adapter *adapter,
data
[
2
]
=
0
;
data
[
3
]
=
0
;
}
return
0
;
}
static
void
e1000_
ethtool_gwol
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_wolinfo
*
wol
)
e1000_
get_wol
(
struct
net_device
*
netdev
,
struct
ethtool_wolinfo
*
wol
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
switch
(
adapter
->
hw
.
device_id
)
{
...
...
@@ -1350,8 +1481,9 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
}
static
int
e1000_
ethtool_swol
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_wolinfo
*
wol
)
e1000_
set_wol
(
struct
net_device
*
netdev
,
struct
ethtool_wolinfo
*
wol
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
switch
(
adapter
->
hw
.
device_id
)
{
...
...
@@ -1387,7 +1519,6 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
return
0
;
}
/* toggle LED 4 times per second = 2 "blinks" per second */
#define E1000_ID_INTERVAL (HZ/4)
...
...
@@ -1408,8 +1539,13 @@ e1000_led_blink_callback(unsigned long data)
}
static
int
e1000_
ethtool_led_blink
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_value
*
id
)
e1000_
phys_id
(
struct
net_device
*
netdev
,
uint32_t
data
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
if
(
!
data
||
data
>
(
uint32_t
)(
MAX_SCHEDULE_TIMEOUT
/
HZ
))
data
=
(
uint32_t
)(
MAX_SCHEDULE_TIMEOUT
/
HZ
);
if
(
!
adapter
->
blink_timer
.
function
)
{
init_timer
(
&
adapter
->
blink_timer
);
adapter
->
blink_timer
.
function
=
e1000_led_blink_callback
;
...
...
@@ -1420,11 +1556,8 @@ e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id)
mod_timer
(
&
adapter
->
blink_timer
,
jiffies
);
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
id
->
data
)
schedule_timeout
(
id
->
data
*
HZ
);
else
schedule_timeout
(
MAX_SCHEDULE_TIMEOUT
);
schedule_timeout
(
data
*
HZ
);
del_timer_sync
(
&
adapter
->
blink_timer
);
e1000_led_off
(
&
adapter
->
hw
);
clear_bit
(
E1000_LED_ON
,
&
adapter
->
led_status
);
...
...
@@ -1433,345 +1566,102 @@ e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id)
return
0
;
}
int
e1000_
ethtool_ioctl
(
struct
net_device
*
netdev
,
struct
ifreq
*
ifr
)
static
int
e1000_
nway_reset
(
struct
net_device
*
netdev
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
void
*
addr
=
ifr
->
ifr_data
;
uint32_t
cmd
;
if
(
get_user
(
cmd
,
(
uint32_t
*
)
addr
))
return
-
EFAULT
;
switch
(
cmd
)
{
case
ETHTOOL_GSET
:
{
struct
ethtool_cmd
ecmd
=
{
ETHTOOL_GSET
};
e1000_ethtool_gset
(
adapter
,
&
ecmd
);
if
(
copy_to_user
(
addr
,
&
ecmd
,
sizeof
(
ecmd
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_SSET
:
{
struct
ethtool_cmd
ecmd
;
if
(
copy_from_user
(
&
ecmd
,
addr
,
sizeof
(
ecmd
)))
return
-
EFAULT
;
return
e1000_ethtool_sset
(
adapter
,
&
ecmd
);
}
case
ETHTOOL_GDRVINFO
:
{
struct
ethtool_drvinfo
drvinfo
=
{
ETHTOOL_GDRVINFO
};
e1000_ethtool_gdrvinfo
(
adapter
,
&
drvinfo
);
if
(
copy_to_user
(
addr
,
&
drvinfo
,
sizeof
(
drvinfo
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_GSTRINGS
:
{
struct
ethtool_gstrings
gstrings
=
{
ETHTOOL_GSTRINGS
};
char
*
strings
=
NULL
;
int
err
=
0
;
if
(
copy_from_user
(
&
gstrings
,
addr
,
sizeof
(
gstrings
)))
return
-
EFAULT
;
switch
(
gstrings
.
string_set
)
{
case
ETH_SS_TEST
:
gstrings
.
len
=
E1000_TEST_LEN
;
strings
=
kmalloc
(
E1000_TEST_LEN
*
ETH_GSTRING_LEN
,
GFP_KERNEL
);
if
(
!
strings
)
return
-
ENOMEM
;
memcpy
(
strings
,
e1000_gstrings_test
,
E1000_TEST_LEN
*
ETH_GSTRING_LEN
);
break
;
case
ETH_SS_STATS
:
{
int
i
;
gstrings
.
len
=
E1000_STATS_LEN
;
strings
=
kmalloc
(
E1000_STATS_LEN
*
ETH_GSTRING_LEN
,
GFP_KERNEL
);
if
(
!
strings
)
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
E1000_STATS_LEN
;
i
++
)
{
memcpy
(
&
strings
[
i
*
ETH_GSTRING_LEN
],
e1000_gstrings_stats
[
i
].
stat_string
,
ETH_GSTRING_LEN
);
}
break
;
}
default:
return
-
EOPNOTSUPP
;
}
if
(
copy_to_user
(
addr
,
&
gstrings
,
sizeof
(
gstrings
)))
err
=
-
EFAULT
;
addr
+=
offsetof
(
struct
ethtool_gstrings
,
data
);
if
(
!
err
&&
copy_to_user
(
addr
,
strings
,
gstrings
.
len
*
ETH_GSTRING_LEN
))
err
=
-
EFAULT
;
kfree
(
strings
);
return
err
;
}
case
ETHTOOL_GREGS
:
{
struct
ethtool_regs
regs
=
{
ETHTOOL_GREGS
};
uint32_t
regs_buff
[
E1000_REGS_LEN
];
if
(
copy_from_user
(
&
regs
,
addr
,
sizeof
(
regs
)))
return
-
EFAULT
;
memset
(
regs_buff
,
0
,
sizeof
(
regs_buff
));
if
(
regs
.
len
>
E1000_REGS_LEN
)
regs
.
len
=
E1000_REGS_LEN
;
e1000_ethtool_gregs
(
adapter
,
&
regs
,
regs_buff
);
if
(
copy_to_user
(
addr
,
&
regs
,
sizeof
(
regs
)))
return
-
EFAULT
;
addr
+=
offsetof
(
struct
ethtool_regs
,
data
);
if
(
copy_to_user
(
addr
,
regs_buff
,
regs
.
len
))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_NWAY_RST
:
{
if
(
netif_running
(
netdev
))
{
e1000_down
(
adapter
);
e1000_up
(
adapter
);
}
return
0
;
}
case
ETHTOOL_PHYS_ID
:
{
struct
ethtool_value
id
;
if
(
copy_from_user
(
&
id
,
addr
,
sizeof
(
id
)))
return
-
EFAULT
;
return
e1000_ethtool_led_blink
(
adapter
,
&
id
);
}
case
ETHTOOL_GLINK
:
{
struct
ethtool_value
link
=
{
ETHTOOL_GLINK
};
link
.
data
=
netif_carrier_ok
(
netdev
);
if
(
copy_to_user
(
addr
,
&
link
,
sizeof
(
link
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_GWOL
:
{
struct
ethtool_wolinfo
wol
=
{
ETHTOOL_GWOL
};
e1000_ethtool_gwol
(
adapter
,
&
wol
);
if
(
copy_to_user
(
addr
,
&
wol
,
sizeof
(
wol
))
!=
0
)
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_SWOL
:
{
struct
ethtool_wolinfo
wol
;
if
(
copy_from_user
(
&
wol
,
addr
,
sizeof
(
wol
))
!=
0
)
return
-
EFAULT
;
return
e1000_ethtool_swol
(
adapter
,
&
wol
);
}
case
ETHTOOL_GEEPROM
:
{
struct
ethtool_eeprom
eeprom
=
{
ETHTOOL_GEEPROM
};
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
uint16_t
*
eeprom_buff
;
void
*
ptr
;
int
err
=
0
;
if
(
copy_from_user
(
&
eeprom
,
addr
,
sizeof
(
eeprom
)))
return
-
EFAULT
;
eeprom_buff
=
kmalloc
(
hw
->
eeprom
.
word_size
*
2
,
GFP_KERNEL
);
if
(
!
eeprom_buff
)
return
-
ENOMEM
;
if
((
err
=
e1000_ethtool_geeprom
(
adapter
,
&
eeprom
,
eeprom_buff
)))
goto
err_geeprom_ioctl
;
if
(
copy_to_user
(
addr
,
&
eeprom
,
sizeof
(
eeprom
)))
{
err
=
-
EFAULT
;
goto
err_geeprom_ioctl
;
}
addr
+=
offsetof
(
struct
ethtool_eeprom
,
data
);
ptr
=
((
void
*
)
eeprom_buff
)
+
(
eeprom
.
offset
&
1
);
if
(
copy_to_user
(
addr
,
ptr
,
eeprom
.
len
))
err
=
-
EFAULT
;
}
err_geeprom_ioctl:
kfree
(
eeprom_buff
);
return
err
;
}
case
ETHTOOL_SEEPROM
:
{
struct
ethtool_eeprom
eeprom
;
static
uint32_t
e1000_get_link
(
struct
net_device
*
netdev
)
{
return
netif_carrier_ok
(
netdev
);
}
if
(
copy_from_user
(
&
eeprom
,
addr
,
sizeof
(
eeprom
)))
return
-
EFAULT
;
static
int
e1000_get_stats_count
(
struct
net_device
*
netdev
)
{
return
E1000_STATS_LEN
;
}
addr
+=
offsetof
(
struct
ethtool_eeprom
,
data
);
return
e1000_ethtool_seeprom
(
adapter
,
&
eeprom
,
addr
);
}
case
ETHTOOL_GRINGPARAM
:
{
struct
ethtool_ringparam
ering
=
{
ETHTOOL_GRINGPARAM
};
e1000_ethtool_gring
(
adapter
,
&
ering
);
if
(
copy_to_user
(
addr
,
&
ering
,
sizeof
(
ering
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_SRINGPARAM
:
{
struct
ethtool_ringparam
ering
;
if
(
copy_from_user
(
&
ering
,
addr
,
sizeof
(
ering
)))
return
-
EFAULT
;
return
e1000_ethtool_sring
(
adapter
,
&
ering
);
}
case
ETHTOOL_GPAUSEPARAM
:
{
struct
ethtool_pauseparam
epause
=
{
ETHTOOL_GPAUSEPARAM
};
e1000_ethtool_gpause
(
adapter
,
&
epause
);
if
(
copy_to_user
(
addr
,
&
epause
,
sizeof
(
epause
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_SPAUSEPARAM
:
{
struct
ethtool_pauseparam
epause
;
if
(
copy_from_user
(
&
epause
,
addr
,
sizeof
(
epause
)))
return
-
EFAULT
;
return
e1000_ethtool_spause
(
adapter
,
&
epause
);
}
case
ETHTOOL_GSTATS
:
{
struct
{
struct
ethtool_stats
eth_stats
;
uint64_t
data
[
E1000_STATS_LEN
];
}
stats
=
{
{
ETHTOOL_GSTATS
,
E1000_STATS_LEN
}
};
static
void
e1000_get_ethtool_stats
(
struct
net_device
*
netdev
,
struct
ethtool_stats
*
stats
,
uint64_t
*
data
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
int
i
;
e1000_update_stats
(
adapter
);
for
(
i
=
0
;
i
<
E1000_STATS_LEN
;
i
++
)
stats
.
data
[
i
]
=
(
e1000_gstrings_stats
[
i
].
sizeof_stat
==
sizeof
(
uint64_t
))
?
*
(
uint64_t
*
)((
char
*
)
adapter
+
e1000_gstrings_stats
[
i
].
stat_offset
)
:
*
(
uint32_t
*
)((
char
*
)
adapter
+
e1000_gstrings_stats
[
i
].
stat_offset
);
if
(
copy_to_user
(
addr
,
&
stats
,
sizeof
(
stats
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_TEST
:
{
struct
{
struct
ethtool_test
eth_test
;
uint64_t
data
[
E1000_TEST_LEN
];
}
test
=
{
{
ETHTOOL_TEST
}
};
int
err
;
if
(
copy_from_user
(
&
test
.
eth_test
,
addr
,
sizeof
(
test
.
eth_test
)))
return
-
EFAULT
;
test
.
eth_test
.
len
=
E1000_TEST_LEN
;
if
((
err
=
e1000_ethtool_test
(
adapter
,
&
test
.
eth_test
,
test
.
data
)))
return
err
;
if
(
copy_to_user
(
addr
,
&
test
,
sizeof
(
test
))
!=
0
)
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_GRXCSUM
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GRXCSUM
};
edata
.
data
=
adapter
->
rx_csum
;
if
(
copy_to_user
(
addr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_SRXCSUM
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
addr
,
sizeof
(
edata
)))
return
-
EFAULT
;
adapter
->
rx_csum
=
edata
.
data
;
if
(
netif_running
(
netdev
))
{
e1000_down
(
adapter
);
e1000_up
(
adapter
);
}
else
e1000_reset
(
adapter
);
return
0
;
}
case
ETHTOOL_GTXCSUM
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GTXCSUM
};
edata
.
data
=
(
netdev
->
features
&
NETIF_F_HW_CSUM
)
!=
0
;
if
(
copy_to_user
(
addr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_STXCSUM
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
addr
,
sizeof
(
edata
)))
return
-
EFAULT
;
if
(
adapter
->
hw
.
mac_type
<
e1000_82543
)
{
if
(
edata
.
data
!=
0
)
return
-
EINVAL
;
return
0
;
for
(
i
=
0
;
i
<
E1000_STATS_LEN
;
i
++
)
{
char
*
p
=
(
char
*
)
adapter
+
e1000_gstrings_stats
[
i
].
stat_offset
;
data
[
i
]
=
(
e1000_gstrings_stats
[
i
].
sizeof_stat
==
sizeof
(
uint64_t
))
?
*
(
uint64_t
*
)
p
:
*
(
uint32_t
*
)
p
;
}
}
if
(
edata
.
data
)
netdev
->
features
|=
NETIF_F_HW_CSUM
;
else
netdev
->
features
&=
~
NETIF_F_HW_CSUM
;
static
void
e1000_get_strings
(
struct
net_device
*
netdev
,
uint32_t
stringset
,
uint8_t
*
data
)
{
int
i
;
return
0
;
switch
(
stringset
)
{
case
ETH_SS_TEST
:
memcpy
(
data
,
*
e1000_gstrings_test
,
E1000_TEST_LEN
*
ETH_GSTRING_LEN
);
break
;
case
ETH_SS_STATS
:
for
(
i
=
0
;
i
<
E1000_STATS_LEN
;
i
++
)
{
memcpy
(
data
+
i
*
ETH_GSTRING_LEN
,
e1000_gstrings_stats
[
i
].
stat_string
,
ETH_GSTRING_LEN
);
}
case
ETHTOOL_GSG
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GSG
};
edata
.
data
=
(
netdev
->
features
&
NETIF_F_SG
)
!=
0
;
if
(
copy_to_user
(
addr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
break
;
}
case
ETHTOOL_SSG
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
addr
,
sizeof
(
edata
)))
return
-
EFAULT
;
if
(
edata
.
data
)
netdev
->
features
|=
NETIF_F_SG
;
else
netdev
->
features
&=
~
NETIF_F_SG
;
}
return
0
;
}
struct
ethtool_ops
e1000_ethtool_ops
=
{
.
get_settings
=
e1000_get_settings
,
.
set_settings
=
e1000_set_settings
,
.
get_drvinfo
=
e1000_get_drvinfo
,
.
get_regs_len
=
e1000_get_regs_len
,
.
get_regs
=
e1000_get_regs
,
.
get_wol
=
e1000_get_wol
,
.
set_wol
=
e1000_set_wol
,
.
get_msglevel
=
e1000_get_msglevel
,
.
set_msglevel
=
e1000_set_msglevel
,
.
nway_reset
=
e1000_nway_reset
,
.
get_link
=
e1000_get_link
,
.
get_eeprom_len
=
e1000_get_eeprom_len
,
.
get_eeprom
=
e1000_get_eeprom
,
.
set_eeprom
=
e1000_set_eeprom
,
.
get_ringparam
=
e1000_get_ringparam
,
.
set_ringparam
=
e1000_set_ringparam
,
.
get_pauseparam
=
e1000_get_pauseparam
,
.
set_pauseparam
=
e1000_set_pauseparam
,
.
get_rx_csum
=
e1000_get_rx_csum
,
.
set_rx_csum
=
e1000_set_rx_csum
,
.
get_tx_csum
=
e1000_get_tx_csum
,
.
set_tx_csum
=
e1000_set_tx_csum
,
.
get_sg
=
e1000_get_sg
,
.
set_sg
=
e1000_set_sg
,
#ifdef NETIF_F_TSO
case
ETHTOOL_GTSO
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GTSO
};
edata
.
data
=
(
netdev
->
features
&
NETIF_F_TSO
)
!=
0
;
if
(
copy_to_user
(
addr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_STSO
:
{
struct
ethtool_value
edata
;
if
(
copy_from_user
(
&
edata
,
addr
,
sizeof
(
edata
)))
return
-
EFAULT
;
if
((
adapter
->
hw
.
mac_type
<
e1000_82544
)
||
(
adapter
->
hw
.
mac_type
==
e1000_82547
))
{
if
(
edata
.
data
!=
0
)
return
-
EINVAL
;
return
0
;
}
if
(
edata
.
data
)
netdev
->
features
|=
NETIF_F_TSO
;
else
netdev
->
features
&=
~
NETIF_F_TSO
;
return
0
;
}
.
get_tso
=
e1000_get_tso
,
.
set_tso
=
e1000_set_tso
,
#endif
default:
return
-
EOPNOTSUPP
;
}
}
.
self_test_count
=
e1000_diag_test_count
,
.
self_test
=
e1000_diag_test
,
.
get_strings
=
e1000_get_strings
,
.
phys_id
=
e1000_phys_id
,
.
get_stats_count
=
e1000_get_stats_count
,
.
get_ethtool_stats
=
e1000_get_ethtool_stats
,
};
void
set_ethtool_ops
(
struct
net_device
*
netdev
)
{
SET_ETHTOOL_OPS
(
netdev
,
&
e1000_ethtool_ops
);
}
drivers/net/e1000/e1000_main.c
View file @
7190c16a
...
...
@@ -170,6 +170,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
static
int
e1000_ioctl
(
struct
net_device
*
netdev
,
struct
ifreq
*
ifr
,
int
cmd
);
static
int
e1000_mii_ioctl
(
struct
net_device
*
netdev
,
struct
ifreq
*
ifr
,
int
cmd
);
void
set_ethtool_ops
(
struct
net_device
*
netdev
);
static
void
e1000_enter_82542_rst
(
struct
e1000_adapter
*
adapter
);
static
void
e1000_leave_82542_rst
(
struct
e1000_adapter
*
adapter
);
static
inline
void
e1000_rx_checksum
(
struct
e1000_adapter
*
adapter
,
...
...
@@ -206,7 +207,7 @@ struct notifier_block e1000_notifier_reboot = {
/* Exported from other modules */
extern
void
e1000_check_options
(
struct
e1000_adapter
*
adapter
);
extern
int
e1000_ethtool_ioctl
(
struct
net_device
*
netdev
,
struct
ifreq
*
ifr
);
static
struct
pci_driver
e1000_driver
=
{
.
name
=
e1000_driver_name
,
...
...
@@ -446,6 +447,7 @@ e1000_probe(struct pci_dev *pdev,
netdev
->
set_mac_address
=
&
e1000_set_mac
;
netdev
->
change_mtu
=
&
e1000_change_mtu
;
netdev
->
do_ioctl
=
&
e1000_ioctl
;
set_ethtool_ops
(
netdev
);
netdev
->
tx_timeout
=
&
e1000_tx_timeout
;
netdev
->
watchdog_timeo
=
5
*
HZ
;
#ifdef CONFIG_E1000_NAPI
...
...
@@ -2497,8 +2499,6 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
case
SIOCGMIIREG
:
case
SIOCSMIIREG
:
return
e1000_mii_ioctl
(
netdev
,
ifr
,
cmd
);
case
SIOCETHTOOL
:
return
e1000_ethtool_ioctl
(
netdev
,
ifr
);
default:
return
-
EOPNOTSUPP
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment