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
nexedi
linux
Commits
3b9fb4e8
Commit
3b9fb4e8
authored
May 25, 2003
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge redhat.com:/garz/repo/linus-2.5
into redhat.com:/garz/repo/net-drivers-2.5
parents
dc2f9764
26da9f9f
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1425 additions
and
295 deletions
+1425
-295
drivers/net/arcnet/arcnet.c
drivers/net/arcnet/arcnet.c
+3
-2
drivers/net/e100/e100.h
drivers/net/e100/e100.h
+18
-12
drivers/net/e100/e100_main.c
drivers/net/e100/e100_main.c
+218
-83
drivers/net/e100/e100_phy.c
drivers/net/e100/e100_phy.c
+5
-2
drivers/net/e100/e100_test.c
drivers/net/e100/e100_test.c
+110
-45
drivers/net/e1000/Makefile
drivers/net/e1000/Makefile
+1
-1
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000.h
+4
-1
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_ethtool.c
+934
-25
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.c
+13
-10
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_hw.h
+5
-3
drivers/net/e1000/e1000_main.c
drivers/net/e1000/e1000_main.c
+62
-83
drivers/net/fc/iph5526.c
drivers/net/fc/iph5526.c
+10
-8
drivers/net/fec.c
drivers/net/fec.c
+13
-5
drivers/net/fmv18x.c
drivers/net/fmv18x.c
+3
-3
drivers/net/hamradio/scc.c
drivers/net/hamradio/scc.c
+4
-3
drivers/net/myri_sbus.c
drivers/net/myri_sbus.c
+3
-1
drivers/net/seeq8005.c
drivers/net/seeq8005.c
+7
-2
drivers/net/sunqe.c
drivers/net/sunqe.c
+1
-0
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/lanstreamer.c
+3
-2
drivers/net/tulip/de4x5.c
drivers/net/tulip/de4x5.c
+1
-1
drivers/net/wan/lmc/lmc_main.c
drivers/net/wan/lmc/lmc_main.c
+6
-2
include/linux/arcdevice.h
include/linux/arcdevice.h
+1
-1
No files found.
drivers/net/arcnet/arcnet.c
View file @
3b9fb4e8
...
...
@@ -671,7 +671,7 @@ static void arcnet_timeout(struct net_device *dev)
* interrupts. Establish which device needs attention, and call the correct
* chipset interrupt handler.
*/
void
arcnet_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
irqreturn_t
arcnet_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
dev
=
dev_id
;
struct
arcnet_local
*
lp
;
...
...
@@ -696,7 +696,7 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ACOMMAND
(
CFLAGScmd
|
RESETclear
);
AINTMASK
(
0
);
spin_unlock
(
&
arcnet_lock
);
return
;
return
IRQ_HANDLED
;
}
BUGMSG
(
D_DURING
,
"in arcnet_inthandler (status=%Xh, intmask=%Xh)
\n
"
,
...
...
@@ -864,6 +864,7 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
AINTMASK
(
lp
->
intmask
);
spin_unlock
(
&
arcnet_lock
);
return
IRQ_RETVAL
(
didsomething
);
}
...
...
drivers/net/e100/e100.h
View file @
3b9fb4e8
...
...
@@ -60,7 +60,14 @@
#include <linux/if_vlan.h>
#include <linux/mii.h>
#define E100_REGS_LEN 1
#define E100_CABLE_UNKNOWN 0
#define E100_CABLE_OK 1
#define E100_CABLE_OPEN_NEAR 2
/* Open Circuit Near End */
#define E100_CABLE_OPEN_FAR 3
/* Open Circuit Far End */
#define E100_CABLE_SHORT_NEAR 4
/* Short Circuit Near End */
#define E100_CABLE_SHORT_FAR 5
/* Short Circuit Far End */
#define E100_REGS_LEN 2
/*
* Configure parameters for buffers per controller.
* If the machine this is being used on is a faster machine (i.e. > 150MHz)
...
...
@@ -105,8 +112,6 @@
#define E100_MAX_CU_IDLE_WAIT 50
/* Max udelays in wait_cus_idle */
/* HWI feature related constant */
#define HWI_MAX_LOOP 100
#define MAX_SAME_RESULTS 3
#define HWI_REGISTER_GRANULARITY 80
/* register granularity = 80 Cm */
#define HWI_NEAR_END_BOUNDARY 1000
/* Near end is defined as < 10 meters */
...
...
@@ -942,7 +947,6 @@ struct e100_private {
#ifdef CONFIG_PM
u32
pci_state
[
16
];
#endif
char
ifname
[
IFNAMSIZ
];
#ifdef E100_CU_DEBUG
u8
last_cmd
;
u8
last_sub_cmd
;
...
...
@@ -956,7 +960,10 @@ struct e100_private {
#define E100_SPEED_100_FULL 4
/********* function prototypes *************/
extern
int
e100_open
(
struct
net_device
*
);
extern
int
e100_close
(
struct
net_device
*
);
extern
void
e100_isolate_driver
(
struct
e100_private
*
bdp
);
extern
unsigned
char
e100_hw_init
(
struct
e100_private
*
);
extern
void
e100_sw_reset
(
struct
e100_private
*
bdp
,
u32
reset_cmd
);
extern
u8
e100_start_cu
(
struct
e100_private
*
bdp
,
tcb_t
*
tcb
);
extern
void
e100_free_non_tx_cmd
(
struct
e100_private
*
bdp
,
...
...
@@ -981,14 +988,13 @@ extern unsigned char e100_cu_unknown_state(struct e100_private *bdp);
#define TEST_TIMEOUT 0x08
enum
test_offsets
{
E100_EEPROM_TEST_FAIL
=
0
,
E100_CHIP_TIMEOUT
,
E100_ROM_TEST_FAIL
,
E100_REG_TEST_FAIL
,
E100_MAC_TEST_FAIL
,
E100_LPBK_MAC_FAIL
,
E100_LPBK_PHY_FAIL
,
E100_MAX_TEST_RES
test_link
,
test_eeprom
,
test_self_test
,
test_loopback_mac
,
test_loopback_phy
,
cable_diag
,
max_test_res
,
/* must be last */
};
#endif
drivers/net/e100/e100_main.c
View file @
3b9fb4e8
...
...
@@ -45,6 +45,24 @@
**********************************************************************/
/* Change Log
*
* 2.3.13 05/08/03
* o Feature remove: /proc/net/PRO_LAN_Adapters support gone completely
* o Feature remove: IDIAG support (use ethtool -t instead)
* o Cleanup: fixed spelling mistakes found by community
* o Feature add: ethtool cable diag test
* o Feature add: ethtool parameter support (ring size, xsum, flow ctrl)
* o Cleanup: move e100_asf_enable under CONFIG_PM to avoid warning
* [Stephen Rothwell (sfr@canb.auug.org.au)]
* o Bug fix: don't call any netif_carrier_* until netdev registered.
* [Andrew Morton (akpm@digeo.com)]
* o Cleanup: replace (skb->len - skb->data_len) with skb_headlen(skb)
* [jmorris@intercode.com.au]
* o Bug fix: cleanup of Tx skbs after running ethtool diags
* o Bug fix: incorrect reporting of ethtool diag overall results
* o Bug fix: must hold xmit_lock before stopping queue in ethtool
* operations that require reset h/w and driver structures.
* o Bug fix: statistic command failure would stop statistic collection.
*
* 2.2.21 02/11/03
* o Removed marketing brand strings. Instead, Using generic string
...
...
@@ -61,21 +79,6 @@
* o New feature: added ICH5 support
*
* 2.1.27 11/20/02
* o Bug fix: Device command timeout due to SMBus processing during init
* o Bug fix: Not setting/clearing I (Interrupt) bit in tcb correctly
* o Bug fix: Not using EEPROM WoL setting as default in ethtool
* o Bug fix: Not able to set autoneg on using ethtool when interface down
* o Bug fix: Not able to change speed/duplex using ethtool/mii
* when interface up
* o Bug fix: Ethtool shows autoneg on when forced to 100/Full
* o Bug fix: Compiler error when CONFIG_PROC_FS not defined
* o Bug fix: 2.5.44 e100 doesn't load with preemptive kernel enabled
* (sleep while holding spinlock)
* o Bug fix: 2.1.24-k1 doesn't display complete statistics
* o Bug fix: System panic due to NULL watchdog timer dereference during
* ifconfig down, rmmod and insmod
*
* 2.1.24 10/7/02
*/
#include <linux/config.h>
...
...
@@ -121,14 +124,13 @@ extern void e100_config_wol(struct e100_private *bdp);
extern
u32
e100_run_diag
(
struct
net_device
*
dev
,
u64
*
test_info
,
u32
flags
);
static
int
e100_ethtool_test
(
struct
net_device
*
,
struct
ifreq
*
);
static
int
e100_ethtool_gstrings
(
struct
net_device
*
,
struct
ifreq
*
);
static
char
*
test_strings
[]
=
{
"E100_EEPROM_TEST_FAIL"
,
"E100_CHIP_TIMEOUT"
,
"E100_ROM_TEST_FAIL"
,
"E100_REG_TEST_FAIL"
,
"E100_MAC_TEST_FAIL"
,
"E100_LPBK_MAC_FAIL"
,
"E100_LPBK_PHY_FAIL"
static
char
test_strings
[][
ETH_GSTRING_LEN
]
=
{
"Link test (on/offline)"
,
"Eeprom test (on/offline)"
,
"Self test (offline)"
,
"Mac loopback (offline)"
,
"Phy loopback (offline)"
,
"Cable diagnostic (offline)"
};
static
int
e100_ethtool_led_blink
(
struct
net_device
*
,
struct
ifreq
*
);
...
...
@@ -139,10 +141,10 @@ static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *,
nxmit_cb_entry_t
*
);
static
void
e100_free_nontx_list
(
struct
e100_private
*
);
static
void
e100_non_tx_background
(
unsigned
long
);
static
inline
void
e100_tx_skb_free
(
struct
e100_private
*
bdp
,
tcb_t
*
tcb
);
/* Global Data structures and variables */
char
e100_copyright
[]
__devinitdata
=
"Copyright (c) 2003 Intel Corporation"
;
char
e100_driver_version
[]
=
"2.
2.21
-k1"
;
char
e100_driver_version
[]
=
"2.
3.13
-k1"
;
const
char
*
e100_full_driver_name
=
"Intel(R) PRO/100 Network Driver"
;
char
e100_short_driver_name
[]
=
"e100"
;
static
int
e100nics
=
0
;
...
...
@@ -155,6 +157,7 @@ static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
static
int
e100_notify_reboot
(
struct
notifier_block
*
,
unsigned
long
event
,
void
*
ptr
);
static
int
e100_suspend
(
struct
pci_dev
*
pcid
,
u32
state
);
static
int
e100_resume
(
struct
pci_dev
*
pcid
);
static
unsigned
char
e100_asf_enabled
(
struct
e100_private
*
bdp
);
struct
notifier_block
e100_notifier_reboot
=
{
.
notifier_call
=
e100_notify_reboot
,
.
next
=
NULL
,
...
...
@@ -182,8 +185,6 @@ struct notifier_block e100_notifier_reboot = {
static
u8
e100_D101M_checksum
(
struct
e100_private
*
,
struct
sk_buff
*
);
static
u8
e100_D102_check_checksum
(
rfd_t
*
);
static
int
e100_ioctl
(
struct
net_device
*
,
struct
ifreq
*
,
int
);
static
int
e100_open
(
struct
net_device
*
);
static
int
e100_close
(
struct
net_device
*
);
static
int
e100_change_mtu
(
struct
net_device
*
,
int
);
static
int
e100_xmit_frame
(
struct
sk_buff
*
,
struct
net_device
*
);
static
unsigned
char
e100_init
(
struct
e100_private
*
);
...
...
@@ -193,7 +194,6 @@ struct net_device_stats *e100_get_stats(struct net_device *);
static
irqreturn_t
e100intr
(
int
,
void
*
,
struct
pt_regs
*
);
static
void
e100_print_brd_conf
(
struct
e100_private
*
);
static
void
e100_set_multi
(
struct
net_device
*
);
void
e100_set_speed_duplex
(
struct
e100_private
*
);
static
u8
e100_pci_setup
(
struct
pci_dev
*
,
struct
e100_private
*
);
static
u8
e100_sw_init
(
struct
e100_private
*
);
...
...
@@ -215,7 +215,6 @@ u16 e100_eeprom_calculate_chksum(struct e100_private *adapter);
static
unsigned
char
e100_clr_cntrs
(
struct
e100_private
*
);
static
unsigned
char
e100_load_microcode
(
struct
e100_private
*
);
static
unsigned
char
e100_hw_init
(
struct
e100_private
*
);
static
unsigned
char
e100_setup_iaaddr
(
struct
e100_private
*
,
u8
*
);
static
unsigned
char
e100_update_stats
(
struct
e100_private
*
bdp
);
...
...
@@ -228,7 +227,6 @@ static void e100_set_bool_option(struct e100_private *bdp, int, u32, int,
char
*
);
unsigned
char
e100_wait_exec_cmplx
(
struct
e100_private
*
,
u32
,
u8
,
u8
);
void
e100_exec_cmplx
(
struct
e100_private
*
,
u32
,
u8
);
static
unsigned
char
e100_asf_enabled
(
struct
e100_private
*
bdp
);
/**
* e100_get_rx_struct - retrieve cell to hold skb buff from the pool
...
...
@@ -616,6 +614,10 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
goto
err_dealloc
;
}
if
((
rc
=
register_netdev
(
dev
))
!=
0
)
{
goto
err_pci
;
}
if
(((
bdp
->
pdev
->
device
>
0x1030
)
&&
(
bdp
->
pdev
->
device
<
0x103F
))
||
((
bdp
->
pdev
->
device
>=
0x1050
)
...
...
@@ -645,7 +647,7 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
printk
(
KERN_ERR
"e100: Failed to initialize, instance #%d
\n
"
,
e100nics
);
rc
=
-
ENODEV
;
goto
err_
pci
;
goto
err_
unregister_netdev
;
}
/* Check if checksum is valid */
...
...
@@ -655,7 +657,7 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
printk
(
KERN_ERR
"e100: Corrupted EEPROM on instance #%d
\n
"
,
e100nics
);
rc
=
-
ENODEV
;
goto
err_
pci
;
goto
err_
unregister_netdev
;
}
dev
->
vlan_rx_register
=
e100_vlan_rx_register
;
...
...
@@ -679,12 +681,6 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
e100_get_speed_duplex_caps
(
bdp
);
if
((
rc
=
register_netdev
(
dev
))
!=
0
)
{
goto
err_pci
;
}
memcpy
(
bdp
->
ifname
,
dev
->
name
,
IFNAMSIZ
);
bdp
->
ifname
[
IFNAMSIZ
-
1
]
=
0
;
printk
(
KERN_NOTICE
"e100: %s: %s
\n
"
,
bdp
->
device
->
name
,
"Intel(R) PRO/100 Network Connection"
);
...
...
@@ -709,6 +705,8 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
goto
out
;
err_unregister_netdev:
unregister_netdev
(
dev
);
err_pci:
iounmap
(
bdp
->
scb
);
pci_release_regions
(
pcid
);
...
...
@@ -974,7 +972,7 @@ e100_set_bool_option(struct e100_private *bdp, int val, u32 mask,
}
}
static
int
int
e100_open
(
struct
net_device
*
dev
)
{
struct
e100_private
*
bdp
;
...
...
@@ -1033,7 +1031,7 @@ e100_open(struct net_device *dev)
return
rc
;
}
static
int
int
e100_close
(
struct
net_device
*
dev
)
{
struct
e100_private
*
bdp
=
dev
->
priv
;
...
...
@@ -1285,10 +1283,8 @@ e100_init(struct e100_private *bdp)
/* read NIC's part number */
e100_rd_pwa_no
(
bdp
);
if
(
!
e100_hw_init
(
bdp
))
{
printk
(
KERN_ERR
"e100: hw init failed
\n
"
);
if
(
!
e100_hw_init
(
bdp
))
return
false
;
}
/* Interrupts are enabled after device reset */
e100_disable_clear_intr
(
bdp
);
...
...
@@ -1330,6 +1326,8 @@ e100_sw_init(struct e100_private *bdp)
spin_lock_init
(
&
(
bdp
->
bd_non_tx_lock
));
spin_lock_init
(
&
(
bdp
->
config_lock
));
spin_lock_init
(
&
(
bdp
->
mdi_access_lock
));
/* Initialize configuration data */
e100_config_init
(
bdp
);
return
1
;
}
...
...
@@ -1384,11 +1382,11 @@ e100_tco_workaround(struct e100_private *bdp)
* true - If the adapter was initialized
* false - If the adapter failed initialization
*/
unsigned
char
__devinit
unsigned
char
e100_hw_init
(
struct
e100_private
*
bdp
)
{
if
(
!
e100_phy_init
(
bdp
))
return
false
;
goto
err
;
e100_sw_reset
(
bdp
,
PORT_SELECTIVE_RESET
);
...
...
@@ -1398,27 +1396,25 @@ e100_hw_init(struct e100_private *bdp)
/* Load the CU BASE (set to 0, because we use linear mode) */
if
(
!
e100_wait_exec_cmplx
(
bdp
,
0
,
SCB_CUC_LOAD_BASE
,
0
))
return
false
;
goto
err
;
if
(
!
e100_wait_exec_cmplx
(
bdp
,
0
,
SCB_RUC_LOAD_BASE
,
0
))
return
false
;
goto
err
;
/* Load interrupt microcode */
if
(
e100_load_microcode
(
bdp
))
{
bdp
->
flags
|=
DF_UCODE_LOADED
;
}
e100_config_init
(
bdp
);
if
(
!
e100_config
(
bdp
))
{
return
false
;
}
if
(
!
e100_config
(
bdp
))
goto
err
;
if
(
!
e100_setup_iaaddr
(
bdp
,
bdp
->
device
->
dev_addr
))
return
false
;
goto
err
;
/* Clear the internal counters */
if
(
!
e100_clr_cntrs
(
bdp
))
return
false
;
goto
err
;
/* Change for 82558 enhancement */
/* If 82558/9 and if the user has enabled flow control, set up the
...
...
@@ -1431,6 +1427,9 @@ e100_hw_init(struct e100_private *bdp)
}
return
true
;
err:
printk
(
KERN_ERR
"e100: hw init failed
\n
"
);
return
false
;
}
/**
...
...
@@ -1591,9 +1590,22 @@ e100_alloc_tcb_pool(struct e100_private *bdp)
void
e100_free_tcb_pool
(
struct
e100_private
*
bdp
)
{
tcb_t
*
tcb
;
int
i
;
/* Return tx skbs */
for
(
i
=
0
;
i
<
bdp
->
params
.
TxDescriptors
;
i
++
)
{
tcb
=
bdp
->
tcb_pool
.
data
;
tcb
+=
bdp
->
tcb_pool
.
head
;
e100_tx_skb_free
(
bdp
,
tcb
);
if
(
NEXT_TCB_TOUSE
(
bdp
->
tcb_pool
.
head
)
==
bdp
->
tcb_pool
.
tail
)
break
;
bdp
->
tcb_pool
.
head
=
NEXT_TCB_TOUSE
(
bdp
->
tcb_pool
.
head
);
}
pci_free_consistent
(
bdp
->
pdev
,
sizeof
(
tcb_t
)
*
bdp
->
params
.
TxDescriptors
,
bdp
->
tcb_pool
.
data
,
bdp
->
tcb_phys
);
bdp
->
tcb_pool
.
head
=
0
;
bdp
->
tcb_pool
.
tail
=
1
;
bdp
->
tcb_phys
=
0
;
}
...
...
@@ -1747,12 +1759,10 @@ e100_watchdog(struct net_device *dev)
e100_set_multi
(
dev
);
}
}
/* Update the statistics needed by the upper interface */
/* This should be the last statistic related command
* as it's async. now */
e100_dump_stats_cntrs
(
bdp
);
}
/* Issue command to dump statistics from device. */
/* Check for command completion on next watchdog timer. */
e100_dump_stats_cntrs
(
bdp
);
wmb
();
...
...
@@ -2544,6 +2554,7 @@ e100_update_stats(struct e100_private *bdp)
pcmd_complete
=
e100_cmd_complete_location
(
bdp
);
if
(
*
pcmd_complete
!=
le32_to_cpu
(
DUMP_RST_STAT_COMPLETED
)
&&
*
pcmd_complete
!=
le32_to_cpu
(
DUMP_STAT_COMPLETED
))
{
*
pcmd_complete
=
0
;
return
false
;
}
...
...
@@ -3041,23 +3052,6 @@ e100_isolate_driver(struct e100_private *bdp)
e100_sw_reset
(
bdp
,
PORT_SELECTIVE_RESET
);
}
void
e100_set_speed_duplex
(
struct
e100_private
*
bdp
)
{
int
carrier_ok
;
/* Device may lose link with some siwtches when */
/* changing speed/duplex to non-autoneg. e100 */
/* needs to remember carrier state in order to */
/* start watchdog timer for recovering link */
if
((
carrier_ok
=
netif_carrier_ok
(
bdp
->
device
)))
e100_isolate_driver
(
bdp
);
e100_phy_set_speed_duplex
(
bdp
,
true
);
e100_config_fc
(
bdp
);
/* re-config flow-control if necessary */
e100_config
(
bdp
);
if
(
carrier_ok
)
e100_deisolate_driver
(
bdp
,
false
);
}
static
void
e100_tcb_add_C_bit
(
struct
e100_private
*
bdp
)
{
...
...
@@ -3213,6 +3207,144 @@ e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
case
ETHTOOL_PHYS_ID
:
rc
=
e100_ethtool_led_blink
(
dev
,
ifr
);
break
;
#ifdef ETHTOOL_GRINGPARAM
case
ETHTOOL_GRINGPARAM
:
{
struct
ethtool_ringparam
ering
;
struct
e100_private
*
bdp
=
dev
->
priv
;
memset
((
void
*
)
&
ering
,
0
,
sizeof
(
ering
));
ering
.
rx_max_pending
=
E100_MAX_RFD
;
ering
.
tx_max_pending
=
E100_MAX_TCB
;
ering
.
rx_pending
=
bdp
->
params
.
RxDescriptors
;
ering
.
tx_pending
=
bdp
->
params
.
TxDescriptors
;
rc
=
copy_to_user
(
ifr
->
ifr_data
,
&
ering
,
sizeof
(
ering
))
?
-
EFAULT
:
0
;
return
rc
;
}
#endif
#ifdef ETHTOOL_SRINGPARAM
case
ETHTOOL_SRINGPARAM
:
{
struct
ethtool_ringparam
ering
;
struct
e100_private
*
bdp
=
dev
->
priv
;
if
(
copy_from_user
(
&
ering
,
ifr
->
ifr_data
,
sizeof
(
ering
)))
return
-
EFAULT
;
if
(
ering
.
rx_pending
>
E100_MAX_RFD
||
ering
.
rx_pending
<
E100_MIN_RFD
)
return
-
EINVAL
;
if
(
ering
.
tx_pending
>
E100_MAX_TCB
||
ering
.
tx_pending
<
E100_MIN_TCB
)
return
-
EINVAL
;
if
(
netif_running
(
dev
))
{
spin_lock_bh
(
&
dev
->
xmit_lock
);
e100_close
(
dev
);
spin_unlock_bh
(
&
dev
->
xmit_lock
);
/* Use new values to open interface */
bdp
->
params
.
RxDescriptors
=
ering
.
rx_pending
;
bdp
->
params
.
TxDescriptors
=
ering
.
tx_pending
;
e100_hw_init
(
bdp
);
e100_open
(
dev
);
}
else
{
bdp
->
params
.
RxDescriptors
=
ering
.
rx_pending
;
bdp
->
params
.
TxDescriptors
=
ering
.
tx_pending
;
}
return
0
;
}
#endif
#ifdef ETHTOOL_GPAUSEPARAM
case
ETHTOOL_GPAUSEPARAM
:
{
struct
ethtool_pauseparam
epause
;
struct
e100_private
*
bdp
=
dev
->
priv
;
memset
((
void
*
)
&
epause
,
0
,
sizeof
(
epause
));
if
((
bdp
->
flags
&
IS_BACHELOR
)
&&
(
bdp
->
params
.
b_params
&
PRM_FC
))
{
epause
.
autoneg
=
1
;
if
(
bdp
->
flags
&&
DF_LINK_FC_CAP
)
{
epause
.
rx_pause
=
1
;
epause
.
tx_pause
=
1
;
}
if
(
bdp
->
flags
&&
DF_LINK_FC_TX_ONLY
)
epause
.
tx_pause
=
1
;
}
rc
=
copy_to_user
(
ifr
->
ifr_data
,
&
epause
,
sizeof
(
epause
))
?
-
EFAULT
:
0
;
return
rc
;
}
#endif
#ifdef ETHTOOL_SPAUSEPARAM
case
ETHTOOL_SPAUSEPARAM
:
{
struct
ethtool_pauseparam
epause
;
struct
e100_private
*
bdp
=
dev
->
priv
;
if
(
!
(
bdp
->
flags
&
IS_BACHELOR
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
epause
,
ifr
->
ifr_data
,
sizeof
(
epause
)))
return
-
EFAULT
;
if
(
epause
.
autoneg
==
1
)
bdp
->
params
.
b_params
|=
PRM_FC
;
else
bdp
->
params
.
b_params
&=
~
PRM_FC
;
if
(
netif_running
(
dev
))
{
spin_lock_bh
(
&
dev
->
xmit_lock
);
e100_close
(
dev
);
spin_unlock_bh
(
&
dev
->
xmit_lock
);
e100_hw_init
(
bdp
);
e100_open
(
dev
);
}
return
0
;
}
#endif
#ifdef ETHTOOL_GRXCSUM
case
ETHTOOL_GRXCSUM
:
case
ETHTOOL_GTXCSUM
:
case
ETHTOOL_GSG
:
{
struct
ethtool_value
eval
;
struct
e100_private
*
bdp
=
dev
->
priv
;
memset
((
void
*
)
&
eval
,
0
,
sizeof
(
eval
));
if
((
ecmd
.
cmd
==
ETHTOOL_GRXCSUM
)
&&
(
bdp
->
params
.
b_params
&
PRM_XSUMRX
))
eval
.
data
=
1
;
else
eval
.
data
=
0
;
rc
=
copy_to_user
(
ifr
->
ifr_data
,
&
eval
,
sizeof
(
eval
))
?
-
EFAULT
:
0
;
return
rc
;
}
#endif
#ifdef ETHTOOL_SRXCSUM
case
ETHTOOL_SRXCSUM
:
case
ETHTOOL_STXCSUM
:
case
ETHTOOL_SSG
:
{
struct
ethtool_value
eval
;
struct
e100_private
*
bdp
=
dev
->
priv
;
if
(
copy_from_user
(
&
eval
,
ifr
->
ifr_data
,
sizeof
(
eval
)))
return
-
EFAULT
;
if
(
ecmd
.
cmd
==
ETHTOOL_SRXCSUM
)
{
if
(
eval
.
data
==
1
)
{
if
(
bdp
->
rev_id
>=
D101MA_REV_ID
)
bdp
->
params
.
b_params
|=
PRM_XSUMRX
;
else
return
-
EINVAL
;
}
else
{
if
(
bdp
->
rev_id
>=
D101MA_REV_ID
)
bdp
->
params
.
b_params
&=
~
PRM_XSUMRX
;
else
return
0
;
}
}
else
{
if
(
eval
.
data
==
1
)
return
-
EINVAL
;
else
return
0
;
}
if
(
netif_running
(
dev
))
{
spin_lock_bh
(
&
dev
->
xmit_lock
);
e100_close
(
dev
);
spin_unlock_bh
(
&
dev
->
xmit_lock
);
e100_hw_init
(
bdp
);
e100_open
(
dev
);
}
return
0
;
}
#endif
default:
break
;
}
//switch
...
...
@@ -3364,14 +3496,14 @@ e100_ethtool_test(struct net_device *dev, struct ifreq *ifr)
struct
ethtool_test
*
info
;
int
rc
=
-
EFAULT
;
info
=
kmalloc
(
sizeof
(
*
info
)
+
E100_MAX_TEST_RES
*
sizeof
(
u64
),
info
=
kmalloc
(
sizeof
(
*
info
)
+
max_test_res
*
sizeof
(
u64
),
GFP_ATOMIC
);
if
(
!
info
)
return
-
ENOMEM
;
memset
((
void
*
)
info
,
0
,
sizeof
(
*
info
)
+
E100_MAX_TEST_RES
*
sizeof
(
u64
));
max_test_res
*
sizeof
(
u64
));
if
(
copy_from_user
(
info
,
ifr
->
ifr_data
,
sizeof
(
*
info
)))
goto
exit
;
...
...
@@ -3379,7 +3511,7 @@ e100_ethtool_test(struct net_device *dev, struct ifreq *ifr)
info
->
flags
=
e100_run_diag
(
dev
,
info
->
data
,
info
->
flags
);
if
(
!
copy_to_user
(
ifr
->
ifr_data
,
info
,
sizeof
(
*
info
)
+
E100_MAX_TEST_RES
*
sizeof
(
u64
)))
sizeof
(
*
info
)
+
max_test_res
*
sizeof
(
u64
)))
rc
=
0
;
exit:
kfree
(
info
);
...
...
@@ -3393,6 +3525,7 @@ e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr)
u32
regs_buff
[
E100_REGS_LEN
];
struct
ethtool_regs
regs
=
{
ETHTOOL_GREGS
};
void
*
addr
=
ifr
->
ifr_data
;
u16
mdi_reg
;
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
...
...
@@ -3405,6 +3538,8 @@ e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr)
regs_buff
[
0
]
=
readb
(
&
(
bdp
->
scb
->
scb_cmd_hi
))
<<
24
|
readb
(
&
(
bdp
->
scb
->
scb_cmd_low
))
<<
16
|
readw
(
&
(
bdp
->
scb
->
scb_status
));
e100_mdi_read
(
bdp
,
MII_NCONFIG
,
bdp
->
phy_addr
,
&
mdi_reg
);
regs_buff
[
1
]
=
mdi_reg
;
if
(
copy_to_user
(
addr
,
&
regs
,
sizeof
(
regs
)))
return
-
EFAULT
;
...
...
@@ -3454,7 +3589,7 @@ e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr)
info
.
n_stats
=
E100_STATS_LEN
;
info
.
regdump_len
=
E100_REGS_LEN
*
sizeof
(
u32
);
info
.
eedump_len
=
(
bdp
->
eeprom_size
<<
1
);
info
.
testinfo_len
=
E100_MAX_TEST_RES
;
info
.
testinfo_len
=
max_test_res
;
if
(
copy_to_user
(
ifr
->
ifr_data
,
&
info
,
sizeof
(
info
)))
return
-
EFAULT
;
...
...
@@ -3804,15 +3939,15 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr)
switch
(
info
.
string_set
)
{
case
ETH_SS_TEST
:
{
int
ret
=
0
;
if
(
info
.
len
>
E100_MAX_TEST_RES
)
info
.
len
=
E100_MAX_TEST_RES
;
if
(
info
.
len
>
max_test_res
)
info
.
len
=
max_test_res
;
strings
=
kmalloc
(
info
.
len
*
ETH_GSTRING_LEN
,
GFP_ATOMIC
);
if
(
!
strings
)
return
-
ENOMEM
;
memset
(
strings
,
0
,
info
.
len
*
ETH_GSTRING_LEN
);
for
(
i
=
0
;
i
<
info
.
len
;
i
++
)
{
sprintf
(
strings
+
i
*
ETH_GSTRING_LEN
,
"%
-31
s"
,
sprintf
(
strings
+
i
*
ETH_GSTRING_LEN
,
"%s"
,
test_strings
[
i
]);
}
if
(
copy_to_user
(
ifr
->
ifr_data
,
&
info
,
sizeof
(
info
)))
...
...
@@ -4164,7 +4299,6 @@ e100_resume(struct pci_dev *pcid)
return
0
;
}
#endif
/* CONFIG_PM */
/**
* e100_asf_enabled - checks if ASF is configured on the current adaper
...
...
@@ -4190,6 +4324,7 @@ e100_asf_enabled(struct e100_private *bdp)
}
return
false
;
}
#endif
/* CONFIG_PM */
#ifdef E100_CU_DEBUG
unsigned
char
...
...
drivers/net/e100/e100_phy.c
View file @
3b9fb4e8
...
...
@@ -628,8 +628,6 @@ e100_force_speed_duplex(struct e100_private *bdp)
u16
control
;
unsigned
long
expires
;
e100_phy_reset
(
bdp
);
bdp
->
flags
|=
DF_SPEED_FORCED
;
e100_mdi_read
(
bdp
,
MII_BMCR
,
bdp
->
phy_addr
,
&
control
);
...
...
@@ -912,6 +910,10 @@ e100_phy_reset(struct e100_private *bdp)
u16
ctrl_reg
;
ctrl_reg
=
BMCR_RESET
;
e100_mdi_write
(
bdp
,
MII_BMCR
,
bdp
->
phy_addr
,
ctrl_reg
);
/* ieee 802.3 : The reset process shall be completed */
/* within 0.5 seconds from the settting of PHY reset bit. */
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
/
2
);
}
unsigned
char
__devinit
...
...
@@ -928,6 +930,7 @@ e100_phy_init(struct e100_private *bdp)
bdp
->
PhyDelay
=
0
;
bdp
->
zlock_state
=
ZLOCK_INITIAL
;
e100_phy_reset
(
bdp
);
e100_phy_set_speed_duplex
(
bdp
,
false
);
e100_fix_polarity
(
bdp
);
...
...
drivers/net/e100/e100_test.c
View file @
3b9fb4e8
...
...
@@ -25,7 +25,7 @@
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*******************************************************************************/
#include "e100.h"
#include "e100
_phy
.h"
#include "e100_config.h"
extern
u16
e100_eeprom_read
(
struct
e100_private
*
,
u16
);
...
...
@@ -46,6 +46,7 @@ static u8 e100_diag_loopback_alloc(struct e100_private *);
static
void
e100_diag_loopback_cu_ru_exec
(
struct
e100_private
*
);
static
u8
e100_diag_check_pkt
(
u8
*
);
static
void
e100_diag_loopback_free
(
struct
e100_private
*
);
static
int
e100_cable_diag
(
struct
e100_private
*
bdp
);
#define LB_PACKET_SIZE 1500
...
...
@@ -60,46 +61,52 @@ u32
e100_run_diag
(
struct
net_device
*
dev
,
u64
*
test_info
,
u32
flags
)
{
struct
e100_private
*
bdp
=
dev
->
priv
;
u8
test_result
=
true
;
e100_isolate_driver
(
bdp
);
u8
test_result
=
0
;
if
(
!
e100_get_link_state
(
bdp
))
{
test_result
=
ETH_TEST_FL_FAILED
;
test_info
[
test_link
]
=
true
;
}
if
(
!
e100_diag_eeprom
(
dev
))
{
test_result
=
ETH_TEST_FL_FAILED
;
test_info
[
test_eeprom
]
=
true
;
}
if
(
flags
&
ETH_TEST_FL_OFFLINE
)
{
u8
fail_mask
;
fail_mask
=
e100_diag_selftest
(
dev
);
if
(
fail_mask
)
{
test_result
=
false
;
if
(
fail_mask
&
REGISTER_TEST_FAIL
)
test_info
[
E100_REG_TEST_FAIL
]
=
true
;
if
(
fail_mask
&
ROM_TEST_FAIL
)
test_info
[
E100_ROM_TEST_FAIL
]
=
true
;
if
(
fail_mask
&
SELF_TEST_FAIL
)
test_info
[
E100_MAC_TEST_FAIL
]
=
true
;
if
(
fail_mask
&
TEST_TIMEOUT
)
test_info
[
E100_CHIP_TIMEOUT
]
=
true
;
if
(
netif_running
(
dev
))
{
spin_lock_bh
(
&
dev
->
xmit_lock
);
e100_close
(
dev
);
spin_unlock_bh
(
&
dev
->
xmit_lock
);
}
if
(
e100_diag_selftest
(
dev
))
{
test_result
=
ETH_TEST_FL_FAILED
;
test_info
[
test_self_test
]
=
true
;
}
fail_mask
=
e100_diag_loopback
(
dev
);
if
(
fail_mask
)
{
test_result
=
false
;
test_result
=
ETH_TEST_FL_FAILED
;
if
(
fail_mask
&
PHY_LOOPBACK
)
test_info
[
E100_LPBK_PHY_FAIL
]
=
true
;
test_info
[
test_loopback_phy
]
=
true
;
if
(
fail_mask
&
MAC_LOOPBACK
)
test_info
[
E100_LPBK_MAC_FAIL
]
=
true
;
test_info
[
test_loopback_mac
]
=
true
;
}
}
if
(
!
e100_diag_eeprom
(
dev
))
{
test_result
=
false
;
test_info
[
E100_EEPROM_TEST_FAIL
]
=
true
;
test_info
[
cable_diag
]
=
e100_cable_diag
(
bdp
);
/* Need hw init regardless of netif_running */
e100_hw_init
(
bdp
);
if
(
netif_running
(
dev
))
{
e100_open
(
dev
);
}
}
else
{
test_info
[
test_self_test
]
=
false
;
test_info
[
test_loopback_phy
]
=
false
;
test_info
[
test_loopback_mac
]
=
false
;
test_info
[
cable_diag
]
=
false
;
}
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
*
2
);
e100_deisolate_driver
(
bdp
,
false
);
return
flags
|
(
test_result
?
0
:
ETH_TEST_FL_FAILED
);
return
flags
|
test_result
;
}
/**
...
...
@@ -126,8 +133,6 @@ e100_diag_selftest(struct net_device *dev)
}
}
e100_configure_device
(
bdp
);
return
retval
;
}
...
...
@@ -165,14 +170,14 @@ e100_diag_loopback (struct net_device *dev)
u8
rc
=
0
;
printk
(
KERN_DEBUG
"%s: PHY loopback test starts
\n
"
,
dev
->
name
);
e100_
sw_reset
(
dev
->
priv
,
PORT_SELECTIVE_RESET
);
e100_
hw_init
(
dev
->
priv
);
if
(
!
e100_diag_one_loopback
(
dev
,
PHY_LOOPBACK
))
{
rc
|=
PHY_LOOPBACK
;
}
printk
(
KERN_DEBUG
"%s: PHY loopback test ends
\n
"
,
dev
->
name
);
printk
(
KERN_DEBUG
"%s: MAC loopback test starts
\n
"
,
dev
->
name
);
e100_
sw_reset
(
dev
->
priv
,
PORT_SELECTIVE_RESET
);
e100_
hw_init
(
dev
->
priv
);
if
(
!
e100_diag_one_loopback
(
dev
,
MAC_LOOPBACK
))
{
rc
|=
MAC_LOOPBACK
;
}
...
...
@@ -257,15 +262,10 @@ e100_diag_config_loopback(struct e100_private* bdp,
if
(
set_loopback
)
/* Set PHY loopback mode */
e100_phy_set_loopback
(
bdp
);
else
{
/* Back to normal speed and duplex */
if
(
bdp
->
params
.
e100_speed_duplex
==
E100_AUTONEG
)
/* Reset PHY and do autoneg */
e100_phy_autoneg
(
bdp
);
else
/* Reset PHY and force speed and duplex */
e100_force_speed_duplex
(
bdp
);
}
/* Wait for PHY state change */
else
/* Reset PHY loopback mode */
e100_phy_reset
(
bdp
);
/* Wait for PHY state change */
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
);
}
else
{
/* For MAC loopback wait 500 msec to take effect */
...
...
@@ -348,10 +348,6 @@ static void
e100_diag_loopback_cu_ru_exec
(
struct
e100_private
*
bdp
)
{
/*load CU & RU base */
if
(
!
e100_wait_exec_cmplx
(
bdp
,
0
,
SCB_CUC_LOAD_BASE
,
0
))
printk
(
KERN_ERR
"e100: SCB_CUC_LOAD_BASE failed
\n
"
);
if
(
!
e100_wait_exec_cmplx
(
bdp
,
0
,
SCB_RUC_LOAD_BASE
,
0
))
printk
(
KERN_ERR
"e100: SCB_RUC_LOAD_BASE failed!
\n
"
);
if
(
!
e100_wait_exec_cmplx
(
bdp
,
bdp
->
loopback
.
dma_handle
,
SCB_RUC_START
,
0
))
printk
(
KERN_ERR
"e100: SCB_RUC_START failed!
\n
"
);
...
...
@@ -433,3 +429,72 @@ e100_diag_loopback_free (struct e100_private *bdp)
bdp
->
loopback
.
dma_handle
);
}
static
int
e100_cable_diag
(
struct
e100_private
*
bdp
)
{
int
saved_open_circut
=
0xffff
;
int
saved_short_circut
=
0xffff
;
int
saved_distance
=
0xffff
;
int
saved_same
=
0
;
int
cable_status
=
E100_CABLE_UNKNOWN
;
int
i
;
/* If we have link, */
if
(
e100_get_link_state
(
bdp
))
return
E100_CABLE_OK
;
if
(
bdp
->
rev_id
<
D102_REV_ID
)
return
E100_CABLE_UNKNOWN
;
/* Disable MDI/MDI-X auto switching */
e100_mdi_write
(
bdp
,
MII_NCONFIG
,
bdp
->
phy_addr
,
MDI_MDIX_RESET_ALL_MASK
);
/* Set to 100 Full as required by cable test */
e100_mdi_write
(
bdp
,
MII_BMCR
,
bdp
->
phy_addr
,
BMCR_SPEED100
|
BMCR_FULLDPLX
);
/* Test up to 100 times */
for
(
i
=
0
;
i
<
100
;
i
++
)
{
u16
ctrl_reg
;
int
distance
,
open_circut
,
short_circut
,
near_end
;
/* Enable and execute cable test */
e100_mdi_write
(
bdp
,
HWI_CONTROL_REG
,
bdp
->
phy_addr
,
(
HWI_TEST_ENABLE
|
HWI_TEST_EXECUTE
));
/* Wait for cable test finished */
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
/
100
+
1
);
/* Read results */
e100_mdi_read
(
bdp
,
HWI_CONTROL_REG
,
bdp
->
phy_addr
,
&
ctrl_reg
);
distance
=
ctrl_reg
&
HWI_TEST_DISTANCE
;
open_circut
=
ctrl_reg
&
HWI_TEST_HIGHZ_PROBLEM
;
short_circut
=
ctrl_reg
&
HWI_TEST_LOWZ_PROBLEM
;
if
((
distance
==
saved_distance
)
&&
(
open_circut
==
saved_open_circut
)
&&
(
short_circut
==
saved_short_circut
))
saved_same
++
;
else
{
saved_same
=
0
;
saved_distance
=
distance
;
saved_open_circut
=
open_circut
;
saved_short_circut
=
short_circut
;
}
/* If results are the same 3 times */
if
(
saved_same
==
3
)
{
near_end
=
((
distance
*
HWI_REGISTER_GRANULARITY
)
<
HWI_NEAR_END_BOUNDARY
);
if
(
open_circut
)
cable_status
=
(
near_end
)
?
E100_CABLE_OPEN_NEAR
:
E100_CABLE_OPEN_FAR
;
if
(
short_circut
)
cable_status
=
(
near_end
)
?
E100_CABLE_SHORT_NEAR
:
E100_CABLE_SHORT_FAR
;
break
;
}
}
/* Reset cable test */
e100_mdi_write
(
bdp
,
HWI_CONTROL_REG
,
bdp
->
phy_addr
,
HWI_RESET_ALL_MASK
);
return
cable_status
;
}
drivers/net/e1000/Makefile
View file @
3b9fb4e8
################################################################################
#
#
# Copyright(c) 1999 - 200
2
Intel Corporation. All rights reserved.
# Copyright(c) 1999 - 200
3
Intel Corporation. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
...
...
drivers/net/e1000/e1000.h
View file @
3b9fb4e8
...
...
@@ -134,6 +134,7 @@ struct e1000_buffer {
uint64_t
dma
;
unsigned
long
length
;
unsigned
long
time_stamp
;
unsigned
int
next_to_watch
;
};
struct
e1000_desc_ring
{
...
...
@@ -169,7 +170,6 @@ struct e1000_adapter {
struct
timer_list
watchdog_timer
;
struct
timer_list
phy_info_timer
;
struct
vlan_group
*
vlgrp
;
char
*
id_string
;
uint32_t
bd_number
;
uint32_t
rx_buffer_len
;
uint32_t
part_num
;
...
...
@@ -218,6 +218,9 @@ struct e1000_adapter {
struct
e1000_phy_info
phy_info
;
struct
e1000_phy_stats
phy_stats
;
uint32_t
test_icr
;
struct
e1000_desc_ring
test_tx_ring
;
struct
e1000_desc_ring
test_rx_ring
;
uint32_t
pci_state
[
16
];
...
...
drivers/net/e1000/e1000_ethtool.c
View file @
3b9fb4e8
...
...
@@ -40,15 +40,60 @@ extern void e1000_down(struct e1000_adapter *adapter);
extern
void
e1000_reset
(
struct
e1000_adapter
*
adapter
);
extern
int
e1000_set_spd_dplx
(
struct
e1000_adapter
*
adapter
,
uint16_t
spddplx
);
static
char
e1000_gstrings_stats
[][
ETH_GSTRING_LEN
]
=
{
"rx_packets"
,
"tx_packets"
,
"rx_bytes"
,
"tx_bytes"
,
"rx_errors"
,
"tx_errors"
,
"rx_dropped"
,
"tx_dropped"
,
"multicast"
,
"collisions"
,
"rx_length_errors"
,
"rx_over_errors"
,
"rx_crc_errors"
,
"rx_frame_errors"
,
"rx_fifo_errors"
,
"rx_missed_errors"
,
"tx_aborted_errors"
,
"tx_carrier_errors"
,
"tx_fifo_errors"
,
"tx_heartbeat_errors"
,
"tx_window_errors"
,
struct
e1000_stats
{
char
stat_string
[
ETH_GSTRING_LEN
];
int
sizeof_stat
;
int
stat_offset
;
};
#define E1000_STATS_LEN sizeof(e1000_gstrings_stats) / ETH_GSTRING_LEN
#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \
offsetof(struct e1000_adapter, m)
static
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
)
},
{
"tx_bytes"
,
E1000_STAT
(
net_stats
.
tx_bytes
)
},
{
"rx_errors"
,
E1000_STAT
(
net_stats
.
rx_errors
)
},
{
"tx_errors"
,
E1000_STAT
(
net_stats
.
tx_errors
)
},
{
"rx_dropped"
,
E1000_STAT
(
net_stats
.
rx_dropped
)
},
{
"tx_dropped"
,
E1000_STAT
(
net_stats
.
tx_dropped
)
},
{
"multicast"
,
E1000_STAT
(
net_stats
.
multicast
)
},
{
"collisions"
,
E1000_STAT
(
net_stats
.
collisions
)
},
{
"rx_length_errors"
,
E1000_STAT
(
net_stats
.
rx_length_errors
)
},
{
"rx_over_errors"
,
E1000_STAT
(
net_stats
.
rx_over_errors
)
},
{
"rx_crc_errors"
,
E1000_STAT
(
net_stats
.
rx_crc_errors
)
},
{
"rx_frame_errors"
,
E1000_STAT
(
net_stats
.
rx_frame_errors
)
},
{
"rx_fifo_errors"
,
E1000_STAT
(
net_stats
.
rx_fifo_errors
)
},
{
"rx_missed_errors"
,
E1000_STAT
(
net_stats
.
rx_missed_errors
)
},
{
"tx_aborted_errors"
,
E1000_STAT
(
net_stats
.
tx_aborted_errors
)
},
{
"tx_carrier_errors"
,
E1000_STAT
(
net_stats
.
tx_carrier_errors
)
},
{
"tx_fifo_errors"
,
E1000_STAT
(
net_stats
.
tx_fifo_errors
)
},
{
"tx_heartbeat_errors"
,
E1000_STAT
(
net_stats
.
tx_heartbeat_errors
)
},
{
"tx_window_errors"
,
E1000_STAT
(
net_stats
.
tx_window_errors
)
},
{
"tx_abort_late_coll"
,
E1000_STAT
(
stats
.
latecol
)
},
{
"tx_deferred_ok"
,
E1000_STAT
(
stats
.
dc
)
},
{
"tx_single_coll_ok"
,
E1000_STAT
(
stats
.
scc
)
},
{
"tx_multi_coll_ok"
,
E1000_STAT
(
stats
.
mcc
)
},
{
"rx_long_length_errors"
,
E1000_STAT
(
stats
.
roc
)
},
{
"rx_short_length_errors"
,
E1000_STAT
(
stats
.
ruc
)
},
{
"rx_align_errors"
,
E1000_STAT
(
stats
.
algnerrc
)
},
{
"tx_tcp_seg_good"
,
E1000_STAT
(
stats
.
tsctc
)
},
{
"tx_tcp_seg_failed"
,
E1000_STAT
(
stats
.
tsctfc
)
},
{
"rx_flow_control_xon"
,
E1000_STAT
(
stats
.
xonrxc
)
},
{
"rx_flow_control_xoff"
,
E1000_STAT
(
stats
.
xoffrxc
)
},
{
"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
)
}
};
#define E1000_STATS_LEN \
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
static
char
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
)
...
...
@@ -154,6 +199,7 @@ e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
strncpy
(
drvinfo
->
fw_version
,
"N/A"
,
32
);
strncpy
(
drvinfo
->
bus_info
,
adapter
->
pdev
->
slot_name
,
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
;
...
...
@@ -164,6 +210,7 @@ e1000_ethtool_gregs(struct e1000_adapter *adapter,
struct
ethtool_regs
*
regs
,
uint32_t
*
regs_buff
)
{
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
uint16_t
phy_data
;
regs
->
version
=
(
1
<<
24
)
|
(
hw
->
revision_id
<<
16
)
|
hw
->
device_id
;
...
...
@@ -182,6 +229,62 @@ e1000_ethtool_gregs(struct e1000_adapter *adapter,
regs_buff
[
10
]
=
E1000_READ_REG
(
hw
,
TDT
);
regs_buff
[
11
]
=
E1000_READ_REG
(
hw
,
TIDV
);
regs_buff
[
12
]
=
adapter
->
hw
.
phy_type
;
/* PHY type (IGP=1, M88=0) */
if
(
hw
->
phy_type
==
e1000_phy_igp
)
{
e1000_write_phy_reg
(
hw
,
IGP01E1000_PHY_PAGE_SELECT
,
IGP01E1000_PHY_AGC_A
);
e1000_read_phy_reg
(
hw
,
IGP01E1000_PHY_AGC_A
&
IGP01E1000_PHY_PAGE_SELECT
,
&
phy_data
);
regs_buff
[
13
]
=
(
uint32_t
)
phy_data
;
/* cable length */
e1000_write_phy_reg
(
hw
,
IGP01E1000_PHY_PAGE_SELECT
,
IGP01E1000_PHY_AGC_B
);
e1000_read_phy_reg
(
hw
,
IGP01E1000_PHY_AGC_B
&
IGP01E1000_PHY_PAGE_SELECT
,
&
phy_data
);
regs_buff
[
14
]
=
(
uint32_t
)
phy_data
;
/* cable length */
e1000_write_phy_reg
(
hw
,
IGP01E1000_PHY_PAGE_SELECT
,
IGP01E1000_PHY_AGC_C
);
e1000_read_phy_reg
(
hw
,
IGP01E1000_PHY_AGC_C
&
IGP01E1000_PHY_PAGE_SELECT
,
&
phy_data
);
regs_buff
[
15
]
=
(
uint32_t
)
phy_data
;
/* cable length */
e1000_write_phy_reg
(
hw
,
IGP01E1000_PHY_PAGE_SELECT
,
IGP01E1000_PHY_AGC_D
);
e1000_read_phy_reg
(
hw
,
IGP01E1000_PHY_AGC_D
&
IGP01E1000_PHY_PAGE_SELECT
,
&
phy_data
);
regs_buff
[
16
]
=
(
uint32_t
)
phy_data
;
/* cable length */
regs_buff
[
17
]
=
0
;
/* extended 10bt distance (not needed) */
e1000_write_phy_reg
(
hw
,
IGP01E1000_PHY_PAGE_SELECT
,
0x0
);
e1000_read_phy_reg
(
hw
,
IGP01E1000_PHY_PORT_STATUS
&
IGP01E1000_PHY_PAGE_SELECT
,
&
phy_data
);
regs_buff
[
18
]
=
(
uint32_t
)
phy_data
;
/* cable polarity */
e1000_write_phy_reg
(
hw
,
IGP01E1000_PHY_PAGE_SELECT
,
IGP01E1000_PHY_PCS_INIT_REG
);
e1000_read_phy_reg
(
hw
,
IGP01E1000_PHY_PCS_INIT_REG
&
IGP01E1000_PHY_PAGE_SELECT
,
&
phy_data
);
regs_buff
[
19
]
=
(
uint32_t
)
phy_data
;
/* cable polarity */
regs_buff
[
20
]
=
0
;
/* polarity correction enabled (always) */
regs_buff
[
22
]
=
0
;
/* phy receive errors (unavailable) */
regs_buff
[
23
]
=
regs_buff
[
18
];
/* mdix mode */
e1000_write_phy_reg
(
hw
,
IGP01E1000_PHY_PAGE_SELECT
,
0x0
);
}
else
{
e1000_read_phy_reg
(
hw
,
M88E1000_PHY_SPEC_STATUS
,
&
phy_data
);
regs_buff
[
13
]
=
(
uint32_t
)
phy_data
;
/* cable length */
regs_buff
[
14
]
=
0
;
/* Dummy (to align w/ IGP phy reg dump) */
regs_buff
[
15
]
=
0
;
/* Dummy (to align w/ IGP phy reg dump) */
regs_buff
[
16
]
=
0
;
/* Dummy (to align w/ IGP phy reg dump) */
e1000_read_phy_reg
(
hw
,
M88E1000_PHY_SPEC_CTRL
,
&
phy_data
);
regs_buff
[
17
]
=
(
uint32_t
)
phy_data
;
/* extended 10bt distance */
regs_buff
[
18
]
=
regs_buff
[
13
];
/* cable polarity */
regs_buff
[
19
]
=
0
;
/* Dummy (to align w/ IGP phy reg dump) */
regs_buff
[
20
]
=
regs_buff
[
17
];
/* polarity correction */
/* phy receive errors */
regs_buff
[
22
]
=
adapter
->
phy_stats
.
receive_errors
;
regs_buff
[
23
]
=
regs_buff
[
13
];
/* mdix mode */
}
regs_buff
[
21
]
=
adapter
->
phy_stats
.
idle_errors
;
/* phy idle errors */
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
;
}
...
...
@@ -219,7 +322,7 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter,
uint16_t
i
;
for
(
i
=
0
;
i
<
last_word
-
first_word
+
1
;
i
++
)
if
((
ret_val
=
e1000_read_eeprom
(
hw
,
first_word
+
i
,
1
,
&
eeprom_buff
[
i
])))
&
eeprom_buff
[
i
])))
break
;
}
geeprom_error:
...
...
@@ -249,7 +352,7 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
first_word
=
eeprom
->
offset
>>
1
;
last_word
=
(
eeprom
->
offset
+
eeprom
->
len
-
1
)
>>
1
;
eeprom_buff
=
kmalloc
(
max_len
,
GFP_KERNEL
);
if
(
eeprom_buff
==
NULL
)
if
(
!
eeprom_buff
)
return
-
ENOMEM
;
ptr
=
(
void
*
)
eeprom_buff
;
...
...
@@ -284,6 +387,765 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
return
ret_val
;
}
#define REG_PATTERN_TEST(R, M, W) \
{ \
uint32_t pat, value; \
uint32_t test[] = \
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \
E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
value = E1000_READ_REG(&adapter->hw, R); \
if(value != (test[pat] & W & M)) { \
*data = (adapter->hw.mac_type < e1000_82543) ? \
E1000_82542_##R : E1000_##R; \
return 1; \
} \
} \
}
#define REG_SET_AND_CHECK(R, M, W) \
{ \
uint32_t value; \
E1000_WRITE_REG(&adapter->hw, R, W & M); \
value = E1000_READ_REG(&adapter->hw, R); \
if ((W & M) != (value & M)) { \
*data = (adapter->hw.mac_type < e1000_82543) ? \
E1000_82542_##R : E1000_##R; \
return 1; \
} \
}
static
int
e1000_reg_test
(
struct
e1000_adapter
*
adapter
,
uint64_t
*
data
)
{
uint32_t
value
;
uint32_t
i
;
/* The status register is Read Only, so a write should fail.
* Some bits that get toggled are ignored.
*/
value
=
(
E1000_READ_REG
(
&
adapter
->
hw
,
STATUS
)
&
(
0xFFFFF833
));
E1000_WRITE_REG
(
&
adapter
->
hw
,
STATUS
,
(
0xFFFFFFFF
));
if
(
value
!=
(
E1000_READ_REG
(
&
adapter
->
hw
,
STATUS
)
&
(
0xFFFFF833
)))
{
*
data
=
1
;
return
1
;
}
REG_PATTERN_TEST
(
FCAL
,
0xFFFFFFFF
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
FCAH
,
0x0000FFFF
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
FCT
,
0x0000FFFF
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
VET
,
0x0000FFFF
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
RDTR
,
0x0000FFFF
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
RDBAH
,
0xFFFFFFFF
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
RDLEN
,
0x000FFF80
,
0x000FFFFF
);
REG_PATTERN_TEST
(
RDH
,
0x0000FFFF
,
0x0000FFFF
);
REG_PATTERN_TEST
(
RDT
,
0x0000FFFF
,
0x0000FFFF
);
REG_PATTERN_TEST
(
FCRTH
,
0x0000FFF8
,
0x0000FFF8
);
REG_PATTERN_TEST
(
FCTTV
,
0x0000FFFF
,
0x0000FFFF
);
REG_PATTERN_TEST
(
TIPG
,
0x3FFFFFFF
,
0x3FFFFFFF
);
REG_PATTERN_TEST
(
TDBAH
,
0xFFFFFFFF
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
TDLEN
,
0x000FFF80
,
0x000FFFFF
);
REG_SET_AND_CHECK
(
RCTL
,
0xFFFFFFFF
,
0x00000000
);
REG_SET_AND_CHECK
(
RCTL
,
0x06DFB3FE
,
0x003FFFFB
);
REG_SET_AND_CHECK
(
TCTL
,
0xFFFFFFFF
,
0x00000000
);
if
(
adapter
->
hw
.
mac_type
>=
e1000_82543
)
{
REG_SET_AND_CHECK
(
RCTL
,
0x06DFB3FE
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
RDBAL
,
0xFFFFFFF0
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
TXCW
,
0xC000FFFF
,
0x0000FFFF
);
REG_PATTERN_TEST
(
TDBAL
,
0xFFFFFFF0
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
TIDV
,
0x0000FFFF
,
0x0000FFFF
);
for
(
i
=
0
;
i
<
E1000_RAR_ENTRIES
;
i
++
)
{
REG_PATTERN_TEST
(
RA
+
((
i
<<
1
)
<<
2
),
0xFFFFFFFF
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
RA
+
(((
i
<<
1
)
+
1
)
<<
2
),
0x8003FFFF
,
0xFFFFFFFF
);
}
}
else
{
REG_SET_AND_CHECK
(
RCTL
,
0xFFFFFFFF
,
0x01FFFFFF
);
REG_PATTERN_TEST
(
RDBAL
,
0xFFFFF000
,
0xFFFFFFFF
);
REG_PATTERN_TEST
(
TXCW
,
0x0000FFFF
,
0x0000FFFF
);
REG_PATTERN_TEST
(
TDBAL
,
0xFFFFF000
,
0xFFFFFFFF
);
}
for
(
i
=
0
;
i
<
E1000_MC_TBL_SIZE
;
i
++
)
REG_PATTERN_TEST
(
MTA
+
(
i
<<
2
),
0xFFFFFFFF
,
0xFFFFFFFF
);
return
0
;
}
static
int
e1000_eeprom_test
(
struct
e1000_adapter
*
adapter
,
uint64_t
*
data
)
{
uint16_t
temp
;
uint16_t
checksum
=
0
;
uint16_t
i
;
*
data
=
0
;
/* Read and add up the contents of the EEPROM */
for
(
i
=
0
;
i
<
(
EEPROM_CHECKSUM_REG
+
1
);
i
++
)
{
if
((
e1000_read_eeprom
(
&
adapter
->
hw
,
i
,
1
,
&
temp
))
<
0
)
{
*
data
=
1
;
break
;
}
checksum
+=
temp
;
}
/* If Checksum is not Correct return error else test passed */
if
((
checksum
!=
(
uint16_t
)
EEPROM_SUM
)
&&
!
(
*
data
))
*
data
=
2
;
return
*
data
;
}
static
irqreturn_t
e1000_test_intr
(
int
irq
,
void
*
data
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
netdev
=
(
struct
net_device
*
)
data
;
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
adapter
->
test_icr
|=
E1000_READ_REG
(
&
adapter
->
hw
,
ICR
);
return
IRQ_HANDLED
;
}
static
int
e1000_intr_test
(
struct
e1000_adapter
*
adapter
,
uint64_t
*
data
)
{
struct
net_device
*
netdev
=
adapter
->
netdev
;
uint32_t
icr
,
mask
,
i
=
0
;
*
data
=
0
;
/* Hook up test interrupt handler just for this test */
if
(
request_irq
(
netdev
->
irq
,
&
e1000_test_intr
,
SA_SHIRQ
,
netdev
->
name
,
netdev
))
{
*
data
=
1
;
return
-
1
;
}
/* Disable all the interrupts */
E1000_WRITE_REG
(
&
adapter
->
hw
,
IMC
,
0xFFFFFFFF
);
msec_delay
(
10
);
/* Interrupts are disabled, so read interrupt cause
* register (icr) twice to verify that there are no interrupts
* pending. icr is clear on read.
*/
icr
=
E1000_READ_REG
(
&
adapter
->
hw
,
ICR
);
icr
=
E1000_READ_REG
(
&
adapter
->
hw
,
ICR
);
if
(
icr
!=
0
)
{
/* if icr is non-zero, there is no point
* running other interrupt tests.
*/
*
data
=
2
;
i
=
10
;
}
/* Test each interrupt */
for
(;
i
<
10
;
i
++
)
{
/* Interrupt to test */
mask
=
1
<<
i
;
/* Disable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted. If
* an interrupt was posted to the bus, the
* test failed.
*/
adapter
->
test_icr
=
0
;
E1000_WRITE_REG
(
&
adapter
->
hw
,
IMC
,
mask
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
ICS
,
mask
);
msec_delay
(
10
);
if
(
adapter
->
test_icr
&
mask
)
{
*
data
=
3
;
break
;
}
/* Enable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted. If
* an interrupt was not posted to the bus, the
* test failed.
*/
adapter
->
test_icr
=
0
;
E1000_WRITE_REG
(
&
adapter
->
hw
,
IMS
,
mask
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
ICS
,
mask
);
msec_delay
(
10
);
if
(
!
(
adapter
->
test_icr
&
mask
))
{
*
data
=
4
;
break
;
}
/* Disable the other interrupts to be reported in
* the cause register and then force the other
* interrupts and see if any get posted. If
* an interrupt was posted to the bus, the
* test failed.
*/
adapter
->
test_icr
=
0
;
E1000_WRITE_REG
(
&
adapter
->
hw
,
IMC
,
~
mask
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
ICS
,
~
mask
);
msec_delay
(
10
);
if
(
adapter
->
test_icr
)
{
*
data
=
5
;
break
;
}
}
/* Disable all the interrupts */
E1000_WRITE_REG
(
&
adapter
->
hw
,
IMC
,
0xFFFFFFFF
);
msec_delay
(
10
);
/* Unhook test interrupt handler */
free_irq
(
netdev
->
irq
,
netdev
);
return
*
data
;
}
static
void
e1000_free_desc_rings
(
struct
e1000_adapter
*
adapter
)
{
struct
e1000_desc_ring
*
txdr
=
&
adapter
->
test_tx_ring
;
struct
e1000_desc_ring
*
rxdr
=
&
adapter
->
test_rx_ring
;
struct
pci_dev
*
pdev
=
adapter
->
pdev
;
int
i
;
if
(
txdr
->
desc
&&
txdr
->
buffer_info
)
{
for
(
i
=
0
;
i
<
txdr
->
count
;
i
++
)
{
if
(
txdr
->
buffer_info
[
i
].
dma
)
pci_unmap_single
(
pdev
,
txdr
->
buffer_info
[
i
].
dma
,
txdr
->
buffer_info
[
i
].
length
,
PCI_DMA_TODEVICE
);
if
(
txdr
->
buffer_info
[
i
].
skb
)
dev_kfree_skb
(
txdr
->
buffer_info
[
i
].
skb
);
}
}
if
(
rxdr
->
desc
&&
rxdr
->
buffer_info
)
{
for
(
i
=
0
;
i
<
rxdr
->
count
;
i
++
)
{
if
(
rxdr
->
buffer_info
[
i
].
dma
)
pci_unmap_single
(
pdev
,
rxdr
->
buffer_info
[
i
].
dma
,
rxdr
->
buffer_info
[
i
].
length
,
PCI_DMA_FROMDEVICE
);
if
(
rxdr
->
buffer_info
[
i
].
skb
)
dev_kfree_skb
(
rxdr
->
buffer_info
[
i
].
skb
);
}
}
if
(
txdr
->
desc
)
pci_free_consistent
(
pdev
,
txdr
->
size
,
txdr
->
desc
,
txdr
->
dma
);
if
(
rxdr
->
desc
)
pci_free_consistent
(
pdev
,
rxdr
->
size
,
rxdr
->
desc
,
rxdr
->
dma
);
if
(
txdr
->
buffer_info
)
kfree
(
txdr
->
buffer_info
);
if
(
rxdr
->
buffer_info
)
kfree
(
rxdr
->
buffer_info
);
return
;
}
static
int
e1000_setup_desc_rings
(
struct
e1000_adapter
*
adapter
)
{
struct
e1000_desc_ring
*
txdr
=
&
adapter
->
test_tx_ring
;
struct
e1000_desc_ring
*
rxdr
=
&
adapter
->
test_rx_ring
;
struct
pci_dev
*
pdev
=
adapter
->
pdev
;
uint32_t
rctl
;
int
size
,
i
,
ret_val
;
/* Setup Tx descriptor ring and Tx buffers */
txdr
->
count
=
80
;
size
=
txdr
->
count
*
sizeof
(
struct
e1000_buffer
);
if
(
!
(
txdr
->
buffer_info
=
kmalloc
(
size
,
GFP_KERNEL
)))
{
ret_val
=
1
;
goto
err_nomem
;
}
memset
(
txdr
->
buffer_info
,
0
,
size
);
txdr
->
size
=
txdr
->
count
*
sizeof
(
struct
e1000_tx_desc
);
E1000_ROUNDUP
(
txdr
->
size
,
4096
);
if
(
!
(
txdr
->
desc
=
pci_alloc_consistent
(
pdev
,
txdr
->
size
,
&
txdr
->
dma
)))
{
ret_val
=
2
;
goto
err_nomem
;
}
memset
(
txdr
->
desc
,
0
,
txdr
->
size
);
txdr
->
next_to_use
=
txdr
->
next_to_clean
=
0
;
E1000_WRITE_REG
(
&
adapter
->
hw
,
TDBAL
,
((
uint64_t
)
txdr
->
dma
&
0x00000000FFFFFFFF
));
E1000_WRITE_REG
(
&
adapter
->
hw
,
TDBAH
,
((
uint64_t
)
txdr
->
dma
>>
32
));
E1000_WRITE_REG
(
&
adapter
->
hw
,
TDLEN
,
txdr
->
count
*
sizeof
(
struct
e1000_tx_desc
));
E1000_WRITE_REG
(
&
adapter
->
hw
,
TDH
,
0
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
TDT
,
0
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
TCTL
,
E1000_TCTL_PSP
|
E1000_TCTL_EN
|
E1000_COLLISION_THRESHOLD
<<
E1000_CT_SHIFT
|
E1000_FDX_COLLISION_DISTANCE
<<
E1000_COLD_SHIFT
);
for
(
i
=
0
;
i
<
txdr
->
count
;
i
++
)
{
struct
e1000_tx_desc
*
tx_desc
=
E1000_TX_DESC
(
*
txdr
,
i
);
struct
sk_buff
*
skb
;
unsigned
int
size
=
1024
;
if
(
!
(
skb
=
alloc_skb
(
size
,
GFP_KERNEL
)))
{
ret_val
=
3
;
goto
err_nomem
;
}
skb_put
(
skb
,
size
);
txdr
->
buffer_info
[
i
].
skb
=
skb
;
txdr
->
buffer_info
[
i
].
length
=
skb
->
len
;
txdr
->
buffer_info
[
i
].
dma
=
pci_map_single
(
pdev
,
skb
->
data
,
skb
->
len
,
PCI_DMA_TODEVICE
);
tx_desc
->
buffer_addr
=
cpu_to_le64
(
txdr
->
buffer_info
[
i
].
dma
);
tx_desc
->
lower
.
data
=
cpu_to_le32
(
skb
->
len
);
tx_desc
->
lower
.
data
|=
E1000_TXD_CMD_EOP
;
tx_desc
->
lower
.
data
|=
E1000_TXD_CMD_IFCS
;
tx_desc
->
lower
.
data
|=
E1000_TXD_CMD_RPS
;
tx_desc
->
upper
.
data
=
0
;
}
/* Setup Rx descriptor ring and Rx buffers */
rxdr
->
count
=
80
;
size
=
rxdr
->
count
*
sizeof
(
struct
e1000_buffer
);
if
(
!
(
rxdr
->
buffer_info
=
kmalloc
(
size
,
GFP_KERNEL
)))
{
ret_val
=
4
;
goto
err_nomem
;
}
memset
(
rxdr
->
buffer_info
,
0
,
size
);
rxdr
->
size
=
rxdr
->
count
*
sizeof
(
struct
e1000_rx_desc
);
if
(
!
(
rxdr
->
desc
=
pci_alloc_consistent
(
pdev
,
rxdr
->
size
,
&
rxdr
->
dma
)))
{
ret_val
=
5
;
goto
err_nomem
;
}
memset
(
rxdr
->
desc
,
0
,
rxdr
->
size
);
rxdr
->
next_to_use
=
rxdr
->
next_to_clean
=
0
;
rctl
=
E1000_READ_REG
(
&
adapter
->
hw
,
RCTL
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
RCTL
,
rctl
&
~
E1000_RCTL_EN
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
RDBAL
,
((
uint64_t
)
rxdr
->
dma
&
0xFFFFFFFF
));
E1000_WRITE_REG
(
&
adapter
->
hw
,
RDBAH
,
((
uint64_t
)
rxdr
->
dma
>>
32
));
E1000_WRITE_REG
(
&
adapter
->
hw
,
RDLEN
,
rxdr
->
size
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
RDH
,
0
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
RDT
,
0
);
rctl
=
E1000_RCTL_EN
|
E1000_RCTL_BAM
|
E1000_RCTL_SZ_2048
|
E1000_RCTL_LBM_NO
|
E1000_RCTL_RDMTS_HALF
|
(
adapter
->
hw
.
mc_filter_type
<<
E1000_RCTL_MO_SHIFT
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
RCTL
,
rctl
);
for
(
i
=
0
;
i
<
rxdr
->
count
;
i
++
)
{
struct
e1000_rx_desc
*
rx_desc
=
E1000_RX_DESC
(
*
rxdr
,
i
);
struct
sk_buff
*
skb
;
if
(
!
(
skb
=
alloc_skb
(
E1000_RXBUFFER_2048
+
2
,
GFP_KERNEL
)))
{
ret_val
=
6
;
goto
err_nomem
;
}
skb_reserve
(
skb
,
2
);
rxdr
->
buffer_info
[
i
].
skb
=
skb
;
rxdr
->
buffer_info
[
i
].
length
=
E1000_RXBUFFER_2048
;
rxdr
->
buffer_info
[
i
].
dma
=
pci_map_single
(
pdev
,
skb
->
data
,
E1000_RXBUFFER_2048
,
PCI_DMA_FROMDEVICE
);
rx_desc
->
buffer_addr
=
cpu_to_le64
(
rxdr
->
buffer_info
[
i
].
dma
);
memset
(
skb
->
data
,
0x00
,
skb
->
len
);
}
return
0
;
err_nomem:
e1000_free_desc_rings
(
adapter
);
return
ret_val
;
}
static
void
e1000_phy_disable_receiver
(
struct
e1000_adapter
*
adapter
)
{
/* Write out to PHY registers 29 and 30 to disable the Receiver. */
e1000_write_phy_reg
(
&
adapter
->
hw
,
29
,
0x001F
);
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
e1000_phy_reset_clk_and_crs
(
struct
e1000_adapter
*
adapter
)
{
uint16_t
phy_reg
;
/* Because we reset the PHY above, we need to re-force TX_CLK in the
* Extended PHY Specific Control Register to 25MHz clock. This
* value defaults back to a 2.5MHz clock when the PHY is reset.
*/
e1000_read_phy_reg
(
&
adapter
->
hw
,
M88E1000_EXT_PHY_SPEC_CTRL
,
&
phy_reg
);
phy_reg
|=
M88E1000_EPSCR_TX_CLK_25
;
e1000_write_phy_reg
(
&
adapter
->
hw
,
M88E1000_EXT_PHY_SPEC_CTRL
,
phy_reg
);
/* In addition, because of the s/w reset above, we need to enable
* CRS on TX. This must be set for both full and half duplex
* operation.
*/
e1000_read_phy_reg
(
&
adapter
->
hw
,
M88E1000_PHY_SPEC_CTRL
,
&
phy_reg
);
phy_reg
|=
M88E1000_PSCR_ASSERT_CRS_ON_TX
;
e1000_write_phy_reg
(
&
adapter
->
hw
,
M88E1000_PHY_SPEC_CTRL
,
phy_reg
);
}
static
int
e1000_nonintegrated_phy_loopback
(
struct
e1000_adapter
*
adapter
)
{
uint32_t
ctrl_reg
;
uint16_t
phy_reg
;
/* Setup the Device Control Register for PHY loopback test. */
ctrl_reg
=
E1000_READ_REG
(
&
adapter
->
hw
,
CTRL
);
ctrl_reg
|=
(
E1000_CTRL_ILOS
|
/* Invert Loss-Of-Signal */
E1000_CTRL_FRCSPD
|
/* Set the Force Speed Bit */
E1000_CTRL_FRCDPX
|
/* Set the Force Duplex Bit */
E1000_CTRL_SPD_1000
|
/* Force Speed to 1000 */
E1000_CTRL_FD
);
/* Force Duplex to FULL */
E1000_WRITE_REG
(
&
adapter
->
hw
,
CTRL
,
ctrl_reg
);
/* Read the PHY Specific Control Register (0x10) */
e1000_read_phy_reg
(
&
adapter
->
hw
,
M88E1000_PHY_SPEC_CTRL
,
&
phy_reg
);
/* Clear Auto-Crossover bits in PHY Specific Control Register
* (bits 6:5).
*/
phy_reg
&=
~
M88E1000_PSCR_AUTO_X_MODE
;
e1000_write_phy_reg
(
&
adapter
->
hw
,
M88E1000_PHY_SPEC_CTRL
,
phy_reg
);
/* Perform software reset on the PHY */
e1000_phy_reset
(
&
adapter
->
hw
);
/* Have to setup TX_CLK and TX_CRS after software reset */
e1000_phy_reset_clk_and_crs
(
adapter
);
e1000_write_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
0x8100
);
/* Wait for reset to complete. */
udelay
(
500
);
/* Have to setup TX_CLK and TX_CRS after software reset */
e1000_phy_reset_clk_and_crs
(
adapter
);
/* Write out to PHY registers 29 and 30 to disable the Receiver. */
e1000_phy_disable_receiver
(
adapter
);
/* Set the loopback bit in the PHY control register. */
e1000_read_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
&
phy_reg
);
phy_reg
|=
MII_CR_LOOPBACK
;
e1000_write_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
phy_reg
);
/* Setup TX_CLK and TX_CRS one more time. */
e1000_phy_reset_clk_and_crs
(
adapter
);
/* Check Phy Configuration */
e1000_read_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
&
phy_reg
);
if
(
phy_reg
!=
0x4100
)
return
9
;
e1000_read_phy_reg
(
&
adapter
->
hw
,
M88E1000_EXT_PHY_SPEC_CTRL
,
&
phy_reg
);
if
(
phy_reg
!=
0x0070
)
return
10
;
e1000_read_phy_reg
(
&
adapter
->
hw
,
29
,
&
phy_reg
);
if
(
phy_reg
!=
0x001A
)
return
11
;
return
0
;
}
static
int
e1000_integrated_phy_loopback
(
struct
e1000_adapter
*
adapter
)
{
uint32_t
ctrl_reg
=
0
;
uint32_t
stat_reg
=
0
;
adapter
->
hw
.
autoneg
=
FALSE
;
if
(
adapter
->
hw
.
phy_type
==
e1000_phy_m88
)
{
/* Auto-MDI/MDIX Off */
e1000_write_phy_reg
(
&
adapter
->
hw
,
M88E1000_PHY_SPEC_CTRL
,
0x0808
);
/* reset to update Auto-MDI/MDIX */
e1000_write_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
0x9140
);
/* autoneg off */
e1000_write_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
0x8140
);
}
/* force 1000, set loopback */
e1000_write_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
0x4140
);
/* Now set up the MAC to the same speed/duplex as the PHY. */
ctrl_reg
=
E1000_READ_REG
(
&
adapter
->
hw
,
CTRL
);
ctrl_reg
&=
~
E1000_CTRL_SPD_SEL
;
/* Clear the speed sel bits */
ctrl_reg
|=
(
E1000_CTRL_FRCSPD
|
/* Set the Force Speed Bit */
E1000_CTRL_FRCDPX
|
/* Set the Force Duplex Bit */
E1000_CTRL_SPD_1000
|
/* Force Speed to 1000 */
E1000_CTRL_FD
);
/* Force Duplex to FULL */
if
(
adapter
->
hw
.
media_type
==
e1000_media_type_copper
&&
adapter
->
hw
.
phy_type
==
e1000_phy_m88
)
{
ctrl_reg
|=
E1000_CTRL_ILOS
;
/* Invert Loss of Signal */
}
else
{
/* Set the ILOS bit on the fiber Nic is half
* duplex link is detected. */
stat_reg
=
E1000_READ_REG
(
&
adapter
->
hw
,
STATUS
);
if
((
stat_reg
&
E1000_STATUS_FD
)
==
0
)
ctrl_reg
|=
(
E1000_CTRL_ILOS
|
E1000_CTRL_SLU
);
}
E1000_WRITE_REG
(
&
adapter
->
hw
,
CTRL
,
ctrl_reg
);
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
if
(
adapter
->
hw
.
phy_type
==
e1000_phy_m88
)
e1000_phy_disable_receiver
(
adapter
);
udelay
(
500
);
return
0
;
}
static
int
e1000_set_phy_loopback
(
struct
e1000_adapter
*
adapter
)
{
uint16_t
phy_reg
=
0
;
uint16_t
count
=
0
;
switch
(
adapter
->
hw
.
mac_type
)
{
case
e1000_82543
:
if
(
adapter
->
hw
.
media_type
==
e1000_media_type_copper
)
{
/* Attempt to setup Loopback mode on Non-integrated PHY.
* Some PHY registers get corrupted at random, so
* attempt this 10 times.
*/
while
(
e1000_nonintegrated_phy_loopback
(
adapter
)
&&
count
++
<
10
);
if
(
count
<
11
)
return
0
;
}
break
;
case
e1000_82544
:
case
e1000_82540
:
case
e1000_82545
:
case
e1000_82546
:
case
e1000_82541
:
case
e1000_82547
:
return
e1000_integrated_phy_loopback
(
adapter
);
break
;
default:
/* Default PHY loopback work is to read the MII
* control register and assert bit 14 (loopback mode).
*/
e1000_read_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
&
phy_reg
);
phy_reg
|=
MII_CR_LOOPBACK
;
e1000_write_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
phy_reg
);
return
0
;
break
;
}
return
8
;
}
static
int
e1000_setup_loopback_test
(
struct
e1000_adapter
*
adapter
)
{
uint32_t
rctl
;
if
(
adapter
->
hw
.
media_type
==
e1000_media_type_fiber
)
{
if
(
adapter
->
hw
.
mac_type
==
e1000_82545
||
adapter
->
hw
.
mac_type
==
e1000_82546
)
return
e1000_set_phy_loopback
(
adapter
);
else
{
rctl
=
E1000_READ_REG
(
&
adapter
->
hw
,
RCTL
);
rctl
|=
E1000_RCTL_LBM_TCVR
;
E1000_WRITE_REG
(
&
adapter
->
hw
,
RCTL
,
rctl
);
return
0
;
}
}
else
if
(
adapter
->
hw
.
media_type
==
e1000_media_type_copper
)
return
e1000_set_phy_loopback
(
adapter
);
return
7
;
}
static
void
e1000_loopback_cleanup
(
struct
e1000_adapter
*
adapter
)
{
uint32_t
rctl
;
uint16_t
phy_reg
;
rctl
=
E1000_READ_REG
(
&
adapter
->
hw
,
RCTL
);
rctl
&=
~
(
E1000_RCTL_LBM_TCVR
|
E1000_RCTL_LBM_MAC
);
E1000_WRITE_REG
(
&
adapter
->
hw
,
RCTL
,
rctl
);
if
(
adapter
->
hw
.
media_type
==
e1000_media_type_copper
||
(
adapter
->
hw
.
media_type
==
e1000_media_type_fiber
&&
(
adapter
->
hw
.
mac_type
==
e1000_82545
||
adapter
->
hw
.
mac_type
==
e1000_82546
)))
{
adapter
->
hw
.
autoneg
=
TRUE
;
e1000_read_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
&
phy_reg
);
if
(
phy_reg
&
MII_CR_LOOPBACK
)
{
phy_reg
&=
~
MII_CR_LOOPBACK
;
e1000_write_phy_reg
(
&
adapter
->
hw
,
PHY_CTRL
,
phy_reg
);
e1000_phy_reset
(
&
adapter
->
hw
);
}
}
}
static
void
e1000_create_lbtest_frame
(
struct
sk_buff
*
skb
,
unsigned
int
frame_size
)
{
memset
(
skb
->
data
,
0xFF
,
frame_size
);
frame_size
=
(
frame_size
%
2
)
?
(
frame_size
-
1
)
:
frame_size
;
memset
(
&
skb
->
data
[
frame_size
/
2
],
0xAA
,
frame_size
/
2
-
1
);
memset
(
&
skb
->
data
[
frame_size
/
2
+
10
],
0xBE
,
1
);
memset
(
&
skb
->
data
[
frame_size
/
2
+
12
],
0xAF
,
1
);
}
static
int
e1000_check_lbtest_frame
(
struct
sk_buff
*
skb
,
unsigned
int
frame_size
)
{
frame_size
=
(
frame_size
%
2
)
?
(
frame_size
-
1
)
:
frame_size
;
if
(
*
(
skb
->
data
+
3
)
==
0xFF
)
{
if
((
*
(
skb
->
data
+
frame_size
/
2
+
10
)
==
0xBE
)
&&
(
*
(
skb
->
data
+
frame_size
/
2
+
12
)
==
0xAF
))
{
return
0
;
}
}
return
13
;
}
static
int
e1000_run_loopback_test
(
struct
e1000_adapter
*
adapter
)
{
struct
e1000_desc_ring
*
txdr
=
&
adapter
->
test_tx_ring
;
struct
e1000_desc_ring
*
rxdr
=
&
adapter
->
test_rx_ring
;
struct
pci_dev
*
pdev
=
adapter
->
pdev
;
int
i
;
E1000_WRITE_REG
(
&
adapter
->
hw
,
RDT
,
rxdr
->
count
-
1
);
for
(
i
=
0
;
i
<
64
;
i
++
)
{
e1000_create_lbtest_frame
(
txdr
->
buffer_info
[
i
].
skb
,
1024
);
pci_dma_sync_single
(
pdev
,
txdr
->
buffer_info
[
i
].
dma
,
txdr
->
buffer_info
[
i
].
length
,
PCI_DMA_TODEVICE
);
}
E1000_WRITE_REG
(
&
adapter
->
hw
,
TDT
,
i
);
msec_delay
(
200
);
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
);
}
static
int
e1000_loopback_test
(
struct
e1000_adapter
*
adapter
,
uint64_t
*
data
)
{
if
((
*
data
=
e1000_setup_desc_rings
(
adapter
)))
goto
err_loopback
;
if
((
*
data
=
e1000_setup_loopback_test
(
adapter
)))
goto
err_loopback
;
*
data
=
e1000_run_loopback_test
(
adapter
);
e1000_loopback_cleanup
(
adapter
);
e1000_free_desc_rings
(
adapter
);
err_loopback:
return
*
data
;
}
static
int
e1000_link_test
(
struct
e1000_adapter
*
adapter
,
uint64_t
*
data
)
{
*
data
=
0
;
e1000_check_for_link
(
&
adapter
->
hw
);
if
(
!
(
E1000_READ_REG
(
&
adapter
->
hw
,
STATUS
)
&
E1000_STATUS_LU
))
{
*
data
=
1
;
}
return
*
data
;
}
static
int
e1000_ethtool_test
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_test
*
eth_test
,
uint64_t
*
data
)
{
boolean_t
if_running
=
netif_running
(
adapter
->
netdev
);
if
(
eth_test
->
flags
==
ETH_TEST_FL_OFFLINE
)
{
/* Offline tests */
/* Link test performed before hardware reset so autoneg doesn't
* interfere with test result */
if
(
e1000_link_test
(
adapter
,
&
data
[
4
]))
eth_test
->
flags
|=
ETH_TEST_FL_FAILED
;
if
(
if_running
)
e1000_down
(
adapter
);
e1000_reset
(
adapter
);
if
(
e1000_reg_test
(
adapter
,
&
data
[
0
]))
eth_test
->
flags
|=
ETH_TEST_FL_FAILED
;
e1000_reset
(
adapter
);
if
(
e1000_eeprom_test
(
adapter
,
&
data
[
1
]))
eth_test
->
flags
|=
ETH_TEST_FL_FAILED
;
e1000_reset
(
adapter
);
if
(
e1000_intr_test
(
adapter
,
&
data
[
2
]))
eth_test
->
flags
|=
ETH_TEST_FL_FAILED
;
e1000_reset
(
adapter
);
if
(
e1000_loopback_test
(
adapter
,
&
data
[
3
]))
eth_test
->
flags
|=
ETH_TEST_FL_FAILED
;
e1000_reset
(
adapter
);
if
(
if_running
)
e1000_up
(
adapter
);
}
else
{
/* Online tests */
if
(
e1000_link_test
(
adapter
,
&
data
[
4
]))
eth_test
->
flags
|=
ETH_TEST_FL_FAILED
;
/* Offline tests aren't run; pass by default */
data
[
0
]
=
0
;
data
[
1
]
=
0
;
data
[
2
]
=
0
;
data
[
3
]
=
0
;
}
return
0
;
}
static
void
e1000_ethtool_gwol
(
struct
e1000_adapter
*
adapter
,
struct
ethtool_wolinfo
*
wol
)
{
...
...
@@ -443,24 +1305,46 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
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_STATS
:
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
=
*
e1000_gstrings_stats
;
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
)))
return
-
EFAULT
;
err
=
-
EFAULT
;
addr
+=
offsetof
(
struct
ethtool_gstrings
,
data
);
if
(
copy_to_user
(
addr
,
strings
,
if
(
!
err
&&
copy_to_user
(
addr
,
strings
,
gstrings
.
len
*
ETH_GSTRING_LEN
))
return
-
EFAULT
;
return
0
;
err
=
-
EFAULT
;
kfree
(
strings
);
return
err
;
}
case
ETHTOOL_GREGS
:
{
struct
ethtool_regs
regs
=
{
ETHTOOL_GREGS
};
...
...
@@ -522,16 +1406,14 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
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
==
NULL
)
if
(
!
eeprom_buff
)
return
-
ENOMEM
;
if
(
copy_from_user
(
&
eeprom
,
addr
,
sizeof
(
eeprom
)))
{
err
=
-
EFAULT
;
goto
err_geeprom_ioctl
;
}
if
((
err
=
e1000_ethtool_geeprom
(
adapter
,
&
eeprom
,
eeprom_buff
)))
goto
err_geeprom_ioctl
;
...
...
@@ -565,18 +1447,45 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
}
case
ETHTOOL_GSTATS
:
{
struct
{
struct
ethtool_stats
cmd
;
struct
ethtool_stats
eth_stats
;
uint64_t
data
[
E1000_STATS_LEN
];
}
stats
=
{
{
ETHTOOL_GSTATS
,
E1000_STATS_LEN
}
};
int
i
;
for
(
i
=
0
;
i
<
E1000_STATS_LEN
;
i
++
)
stats
.
data
[
i
]
=
((
unsigned
long
*
)
&
adapter
->
net_stats
)[
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
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
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
;
}
default:
return
-
EOPNOTSUPP
;
}
...
...
drivers/net/e1000/e1000_hw.c
View file @
3b9fb4e8
...
...
@@ -185,6 +185,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
break
;
case
E1000_DEV_ID_82546EB_COPPER
:
case
E1000_DEV_ID_82546EB_FIBER
:
case
E1000_DEV_ID_82546EB_QUAD_COPPER
:
hw
->
mac_type
=
e1000_82546
;
break
;
case
E1000_DEV_ID_82541EI
:
...
...
@@ -288,9 +289,7 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Configure activity LED after PHY reset */
led_ctrl
=
E1000_READ_REG
(
hw
,
LEDCTL
);
led_ctrl
&=
IGP_ACTIVITY_LED_MASK
;
led_ctrl
|=
IGP_ACTIVITY_LED_ENABLE
;
if
(
hw
->
mac_type
==
e1000_82547
)
led_ctrl
|=
IGP_LED3_MODE
;
led_ctrl
|=
(
IGP_ACTIVITY_LED_ENABLE
|
IGP_LED3_MODE
);
E1000_WRITE_REG
(
hw
,
LEDCTL
,
led_ctrl
);
}
...
...
@@ -737,9 +736,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
/* Configure activity LED after PHY reset */
led_ctrl
=
E1000_READ_REG
(
hw
,
LEDCTL
);
led_ctrl
&=
IGP_ACTIVITY_LED_MASK
;
led_ctrl
|=
IGP_ACTIVITY_LED_ENABLE
;
if
(
hw
->
mac_type
==
e1000_82547
)
led_ctrl
|=
IGP_LED3_MODE
;
led_ctrl
|=
(
IGP_ACTIVITY_LED_ENABLE
|
IGP_LED3_MODE
);
E1000_WRITE_REG
(
hw
,
LEDCTL
,
led_ctrl
);
if
(
hw
->
autoneg_advertised
==
ADVERTISE_1000_FULL
)
{
...
...
@@ -2293,9 +2290,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
/* Configure activity LED after PHY reset */
led_ctrl
=
E1000_READ_REG
(
hw
,
LEDCTL
);
led_ctrl
&=
IGP_ACTIVITY_LED_MASK
;
led_ctrl
|=
IGP_ACTIVITY_LED_ENABLE
;
if
(
hw
->
mac_type
==
e1000_82547
)
led_ctrl
|=
IGP_LED3_MODE
;
led_ctrl
|=
(
IGP_ACTIVITY_LED_ENABLE
|
IGP_LED3_MODE
);
E1000_WRITE_REG
(
hw
,
LEDCTL
,
led_ctrl
);
}
}
...
...
@@ -3801,6 +3796,7 @@ e1000_setup_led(struct e1000_hw *hw)
case
E1000_DEV_ID_82540EM_LOM
:
case
E1000_DEV_ID_82545EM_COPPER
:
case
E1000_DEV_ID_82546EB_COPPER
:
case
E1000_DEV_ID_82546EB_QUAD_COPPER
:
case
E1000_DEV_ID_82541EI
:
case
E1000_DEV_ID_82541EP
:
case
E1000_DEV_ID_82547EI
:
...
...
@@ -3842,6 +3838,7 @@ e1000_cleanup_led(struct e1000_hw *hw)
case
E1000_DEV_ID_82545EM_FIBER
:
case
E1000_DEV_ID_82546EB_COPPER
:
case
E1000_DEV_ID_82546EB_FIBER
:
case
E1000_DEV_ID_82546EB_QUAD_COPPER
:
case
E1000_DEV_ID_82541EI
:
case
E1000_DEV_ID_82541EP
:
case
E1000_DEV_ID_82547EI
:
...
...
@@ -3896,6 +3893,7 @@ e1000_led_on(struct e1000_hw *hw)
case
E1000_DEV_ID_82540EM_LOM
:
case
E1000_DEV_ID_82545EM_COPPER
:
case
E1000_DEV_ID_82546EB_COPPER
:
case
E1000_DEV_ID_82546EB_QUAD_COPPER
:
case
E1000_DEV_ID_82541EI
:
case
E1000_DEV_ID_82541EP
:
case
E1000_DEV_ID_82547EI
:
...
...
@@ -3949,6 +3947,7 @@ e1000_led_off(struct e1000_hw *hw)
case
E1000_DEV_ID_82540EM_LOM
:
case
E1000_DEV_ID_82545EM_COPPER
:
case
E1000_DEV_ID_82546EB_COPPER
:
case
E1000_DEV_ID_82546EB_QUAD_COPPER
:
case
E1000_DEV_ID_82541EI
:
case
E1000_DEV_ID_82541EP
:
case
E1000_DEV_ID_82547EI
:
...
...
@@ -4206,7 +4205,11 @@ e1000_get_bus_info(struct e1000_hw *hw)
status
=
E1000_READ_REG
(
hw
,
STATUS
);
hw
->
bus_type
=
(
status
&
E1000_STATUS_PCIX_MODE
)
?
e1000_bus_type_pcix
:
e1000_bus_type_pci
;
if
(
hw
->
bus_type
==
e1000_bus_type_pci
)
{
if
(
hw
->
device_id
==
E1000_DEV_ID_82546EB_QUAD_COPPER
)
{
hw
->
bus_speed
=
(
hw
->
bus_type
==
e1000_bus_type_pci
)
?
e1000_bus_speed_66
:
e1000_bus_speed_120
;
}
else
if
(
hw
->
bus_type
==
e1000_bus_type_pci
)
{
hw
->
bus_speed
=
(
status
&
E1000_STATUS_PCI66
)
?
e1000_bus_speed_66
:
e1000_bus_speed_33
;
}
else
{
...
...
drivers/net/e1000/e1000_hw.h
View file @
3b9fb4e8
...
...
@@ -99,6 +99,7 @@ typedef enum {
e1000_bus_speed_33
,
e1000_bus_speed_66
,
e1000_bus_speed_100
,
e1000_bus_speed_120
,
e1000_bus_speed_133
,
e1000_bus_speed_reserved
}
e1000_bus_speed
;
...
...
@@ -314,10 +315,11 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
#define E1000_DEV_ID_82545EM_FIBER 0x1011
#define E1000_DEV_ID_82546EB_COPPER 0x1010
#define E1000_DEV_ID_82546EB_FIBER 0x1012
#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
#define E1000_DEV_ID_82541EI 0x1013
#define E1000_DEV_ID_82541EP 0x1018
#define E1000_DEV_ID_82547EI 0x1019
#define NUM_DEV_IDS
19
#define NUM_DEV_IDS
20
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
...
...
@@ -601,7 +603,7 @@ struct e1000_ffvt_entry {
#define E1000_EECD 0x00010
/* EEPROM/Flash Control - RW */
#define E1000_EERD 0x00014
/* EEPROM Read - RW */
#define E1000_CTRL_EXT 0x00018
/* Extended Device Control - RW */
#define E1000_FLA 0x0001C
/* Flash Access
Register
- RW */
#define E1000_FLA 0x0001C
/* Flash Access - RW */
#define E1000_MDIC 0x00020
/* MDI Control - RW */
#define E1000_FCAL 0x00028
/* Flow Control Address Low - RW */
#define E1000_FCAH 0x0002C
/* Flow Control Address High -RW */
...
...
@@ -730,6 +732,7 @@ struct e1000_ffvt_entry {
* the registers function in the same manner.
*/
#define E1000_82542_CTRL E1000_CTRL
#define E1000_82542_CTRL_DUP E1000_CTRL_DUP
#define E1000_82542_STATUS E1000_STATUS
#define E1000_82542_EECD E1000_EECD
#define E1000_82542_EERD E1000_EERD
...
...
@@ -1485,7 +1488,6 @@ struct e1000_hw {
#define E1000_COLLISION_DISTANCE 64
#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_GB_HDX_COLLISION_DISTANCE 512
#define E1000_COLD_SHIFT 12
/* The number of Transmit and Receive Descriptors must be a multiple of 8 */
...
...
drivers/net/e1000/e1000_main.c
View file @
3b9fb4e8
...
...
@@ -30,7 +30,14 @@
/* Change Log
*
* 5.0.43 3/5/03
* 5.1.11 5/6/03
* o Feature: Added support for 82546EB (Quad-port) hardware.
* o Feature: Added support for Diagnostics through Ethtool.
* o Cleanup: Removed /proc support.
* o Cleanup: Removed proprietary IDIAG interface.
* o Bug fix: TSO bug fixes.
*
* 5.0.42 3/5/03
* o Feature: Added support for 82541 and 82547 hardware.
* o Feature: Added support for Intel Gigabit PHY (IGP) and a variety of
* eeproms.
...
...
@@ -46,51 +53,22 @@
* shared interrupt instances.
*
* 4.4.18 11/27/02
* o Feature: Added user-settable knob for interrupt throttle rate (ITR).
* o Cleanup: removed large static array allocations.
* o Cleanup: C99 struct initializer format.
* o Bug fix: restore VLAN settings when interface is brought up.
* o Bug fix: return cleanly in probe if error in detecting MAC type.
* o Bug fix: Wake up on magic packet by default only if enabled in eeprom.
* o Bug fix: Validate MAC address in set_mac.
* o Bug fix: Throw away zero-length Tx skbs.
* o Bug fix: Make ethtool EEPROM acceses work on older versions of ethtool.
*
* 4.4.12 10/15/02
*/
char
e1000_driver_name
[]
=
"e1000"
;
char
e1000_driver_string
[]
=
"Intel(R) PRO/1000 Network Driver"
;
char
e1000_driver_version
[]
=
"5.
0.43-k3
"
;
char
e1000_driver_version
[]
=
"5.
1.11-k1
"
;
char
e1000_copyright
[]
=
"Copyright (c) 1999-2003 Intel Corporation."
;
/* e1000_pci_tbl - PCI Device ID Table
*
* Private driver_data field (last one) stores an index into e1000_strings
* Wildcard entries (PCI_ANY_ID) should come last
* Last entry must be all 0s
*
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask,
String Index
}
* Class, Class Mask,
private data (not used)
}
*/
static
struct
pci_device_id
e1000_pci_tbl
[]
__devinitdata
=
{
/* Intel(R) PRO/1000 Network Connection */
{
0x8086
,
0x1000
,
0x8086
,
0x1000
,
0
,
0
,
0
},
{
0x8086
,
0x1001
,
0x8086
,
0x1003
,
0
,
0
,
0
},
{
0x8086
,
0x1004
,
0x8086
,
0x1004
,
0
,
0
,
0
},
{
0x8086
,
0x1008
,
0x8086
,
0x1107
,
0
,
0
,
0
},
{
0x8086
,
0x1009
,
0x8086
,
0x1109
,
0
,
0
,
0
},
{
0x8086
,
0x100C
,
0x8086
,
0x1112
,
0
,
0
,
0
},
{
0x8086
,
0x100E
,
0x8086
,
0x001E
,
0
,
0
,
0
},
/* Compaq Gigabit Ethernet Server Adapter */
{
0x8086
,
0x1000
,
0x0E11
,
PCI_ANY_ID
,
0
,
0
,
1
},
{
0x8086
,
0x1001
,
0x0E11
,
PCI_ANY_ID
,
0
,
0
,
1
},
{
0x8086
,
0x1004
,
0x0E11
,
PCI_ANY_ID
,
0
,
0
,
1
},
/* IBM Mobile, Desktop & Server Adapters */
{
0x8086
,
0x1000
,
0x1014
,
PCI_ANY_ID
,
0
,
0
,
2
},
{
0x8086
,
0x1001
,
0x1014
,
PCI_ANY_ID
,
0
,
0
,
2
},
{
0x8086
,
0x1004
,
0x1014
,
PCI_ANY_ID
,
0
,
0
,
2
},
/* Generic */
{
0x8086
,
0x1000
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
0x8086
,
0x1001
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
0x8086
,
0x1004
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
...
...
@@ -106,6 +84,7 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
{
0x8086
,
0x1016
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
0x8086
,
0x1017
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
0x8086
,
0x101E
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
0x8086
,
0x101D
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
0x8086
,
0x1013
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
0x8086
,
0x1019
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
/* required last entry */
...
...
@@ -114,12 +93,6 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE
(
pci
,
e1000_pci_tbl
);
static
char
*
e1000_strings
[]
=
{
"Intel(R) PRO/1000 Network Connection"
,
"HP Gigabit Ethernet Server Adapter"
,
"IBM Mobile, Desktop & Server Adapters"
};
/* Local Function Prototypes */
int
e1000_up
(
struct
e1000_adapter
*
adapter
);
...
...
@@ -130,7 +103,7 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
static
int
e1000_init_module
(
void
);
static
void
e1000_exit_module
(
void
);
static
int
e1000_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
);
static
void
e1000_remove
(
struct
pci_dev
*
pdev
);
static
void
__devexit
e1000_remove
(
struct
pci_dev
*
pdev
);
static
int
e1000_sw_init
(
struct
e1000_adapter
*
adapter
);
static
int
e1000_open
(
struct
net_device
*
netdev
);
static
int
e1000_close
(
struct
net_device
*
netdev
);
...
...
@@ -195,7 +168,6 @@ struct notifier_block e1000_notifier_reboot = {
.
priority
=
0
};
/* Exported from other modules */
extern
void
e1000_check_options
(
struct
e1000_adapter
*
adapter
);
...
...
@@ -234,8 +206,9 @@ e1000_init_module(void)
printk
(
KERN_INFO
"%s
\n
"
,
e1000_copyright
);
ret
=
pci_module_init
(
&
e1000_driver
);
if
(
ret
>=
0
)
if
(
ret
>=
0
)
{
register_reboot_notifier
(
&
e1000_notifier_reboot
);
}
return
ret
;
}
...
...
@@ -439,7 +412,6 @@ e1000_probe(struct pci_dev *pdev,
netdev
->
base_addr
=
adapter
->
hw
.
io_base
;
adapter
->
bd_number
=
cards_found
;
adapter
->
id_string
=
e1000_strings
[
ent
->
driver_data
];
/* setup the private structure */
...
...
@@ -500,15 +472,14 @@ e1000_probe(struct pci_dev *pdev,
(
void
(
*
)(
void
*
))
e1000_tx_timeout_task
,
netdev
);
register_netdev
(
netdev
);
memcpy
(
adapter
->
ifname
,
netdev
->
name
,
IFNAMSIZ
);
adapter
->
ifname
[
IFNAMSIZ
-
1
]
=
0
;
/* we're going to reset, so assume we have no link for now */
netif_carrier_off
(
netdev
);
netif_stop_queue
(
netdev
);
printk
(
KERN_INFO
"%s: %s
\n
"
,
netdev
->
name
,
adapter
->
id_string
);
printk
(
KERN_INFO
"%s: Intel(R) PRO/1000 Network Connection
\n
"
,
netdev
->
name
);
e1000_check_options
(
adapter
);
/* Initial Wake on LAN setting
...
...
@@ -568,7 +539,6 @@ e1000_remove(struct pci_dev *pdev)
e1000_phy_hw_reset
(
&
adapter
->
hw
);
iounmap
(
adapter
->
hw
.
hw_addr
);
pci_release_regions
(
pdev
);
...
...
@@ -831,8 +801,9 @@ e1000_configure_tx(struct e1000_adapter *adapter)
e1000_config_collision_dist
(
&
adapter
->
hw
);
/* Setup Transmit Descriptor Settings for this adapter */
adapter
->
txd_cmd
=
E1000_TXD_CMD_IFCS
|
E1000_TXD_CMD_IDE
;
/* Setup Transmit Descriptor Settings for eop descriptor */
adapter
->
txd_cmd
=
E1000_TXD_CMD_IDE
|
E1000_TXD_CMD_EOP
|
E1000_TXD_CMD_IFCS
;
if
(
adapter
->
hw
.
report_tx_early
==
1
)
adapter
->
txd_cmd
|=
E1000_TXD_CMD_RS
;
...
...
@@ -1435,7 +1406,7 @@ e1000_watchdog(unsigned long data)
#define E1000_TX_FLAGS_VLAN_SHIFT 16
static
inline
boolean_t
e1000_tso
(
struct
e1000_adapter
*
adapter
,
struct
sk_buff
*
skb
,
int
tx_flags
)
e1000_tso
(
struct
e1000_adapter
*
adapter
,
struct
sk_buff
*
skb
)
{
#ifdef NETIF_F_TSO
struct
e1000_context_desc
*
context_desc
;
...
...
@@ -1471,7 +1442,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags)
context_desc
->
upper_setup
.
tcp_fields
.
tucse
=
cpu_to_le16
(
tucse
);
context_desc
->
tcp_seg_setup
.
fields
.
mss
=
cpu_to_le16
(
mss
);
context_desc
->
tcp_seg_setup
.
fields
.
hdr_len
=
hdr_len
;
context_desc
->
cmd_and_length
=
cpu_to_le32
(
adapter
->
txd_cmd
|
context_desc
->
cmd_and_length
=
cpu_to_le32
(
E1000_TXD_CMD_DEXT
|
E1000_TXD_CMD_TSE
|
E1000_TXD_CMD_IP
|
E1000_TXD_CMD_TCP
|
(
skb
->
len
-
(
hdr_len
)));
...
...
@@ -1504,8 +1475,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
context_desc
->
upper_setup
.
tcp_fields
.
tucso
=
cso
;
context_desc
->
upper_setup
.
tcp_fields
.
tucse
=
0
;
context_desc
->
tcp_seg_setup
.
data
=
0
;
context_desc
->
cmd_and_length
=
cpu_to_le32
(
adapter
->
txd_cmd
|
E1000_TXD_CMD_DEXT
);
context_desc
->
cmd_and_length
=
cpu_to_le32
(
E1000_TXD_CMD_DEXT
);
if
(
++
i
==
adapter
->
tx_ring
.
count
)
i
=
0
;
adapter
->
tx_ring
.
next_to_use
=
i
;
...
...
@@ -1520,7 +1490,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
static
inline
int
e1000_tx_map
(
struct
e1000_adapter
*
adapter
,
struct
sk_buff
*
skb
)
e1000_tx_map
(
struct
e1000_adapter
*
adapter
,
struct
sk_buff
*
skb
,
unsigned
int
first
)
{
struct
e1000_desc_ring
*
tx_ring
=
&
adapter
->
tx_ring
;
int
len
=
skb
->
len
,
offset
=
0
,
size
,
count
=
0
,
i
;
...
...
@@ -1588,6 +1559,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
}
if
(
--
i
<
0
)
i
=
tx_ring
->
count
-
1
;
tx_ring
->
buffer_info
[
i
].
skb
=
skb
;
tx_ring
->
buffer_info
[
first
].
next_to_watch
=
i
;
return
count
;
}
...
...
@@ -1597,12 +1569,9 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
{
struct
e1000_desc_ring
*
tx_ring
=
&
adapter
->
tx_ring
;
struct
e1000_tx_desc
*
tx_desc
=
NULL
;
uint32_t
txd_upper
,
txd_lower
;
uint32_t
txd_upper
=
0
,
txd_lower
=
E1000_TXD_CMD_IFCS
;
int
i
;
txd_upper
=
0
;
txd_lower
=
adapter
->
txd_cmd
;
if
(
tx_flags
&
E1000_TX_FLAGS_TSO
)
{
txd_lower
|=
E1000_TXD_CMD_DEXT
|
E1000_TXD_DTYP_D
|
E1000_TXD_CMD_TSE
;
...
...
@@ -1630,7 +1599,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
if
(
++
i
==
tx_ring
->
count
)
i
=
0
;
}
tx_desc
->
lower
.
data
|=
cpu_to_le32
(
E1000_TXD_CMD_EOP
);
tx_desc
->
lower
.
data
|=
cpu_to_le32
(
adapter
->
txd_cmd
);
/* Force memory writes to complete before letting h/w
* know there are new descriptors to fetch. (Only
...
...
@@ -1690,6 +1659,7 @@ static int
e1000_xmit_frame
(
struct
sk_buff
*
skb
,
struct
net_device
*
netdev
)
{
struct
e1000_adapter
*
adapter
=
netdev
->
priv
;
unsigned
int
first
;
int
tx_flags
=
0
;
if
(
skb
->
len
<=
0
)
{
...
...
@@ -1715,12 +1685,14 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tx_flags
|=
(
vlan_tx_tag_get
(
skb
)
<<
E1000_TX_FLAGS_VLAN_SHIFT
);
}
if
(
e1000_tso
(
adapter
,
skb
,
tx_flags
))
first
=
adapter
->
tx_ring
.
next_to_use
;
if
(
e1000_tso
(
adapter
,
skb
))
tx_flags
|=
E1000_TX_FLAGS_TSO
;
else
if
(
e1000_tx_csum
(
adapter
,
skb
))
tx_flags
|=
E1000_TX_FLAGS_CSUM
;
e1000_tx_queue
(
adapter
,
e1000_tx_map
(
adapter
,
skb
),
tx_flags
);
e1000_tx_queue
(
adapter
,
e1000_tx_map
(
adapter
,
skb
,
first
),
tx_flags
);
netdev
->
trans_start
=
jiffies
;
...
...
@@ -1952,6 +1924,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
}
if
((
hw
->
mac_type
<=
e1000_82546
)
&&
(
hw
->
phy_type
==
e1000_phy_m88
)
&&
!
e1000_read_phy_reg
(
hw
,
M88E1000_RX_ERR_CNTR
,
&
phy_tmp
))
adapter
->
phy_stats
.
receive_errors
+=
phy_tmp
;
}
...
...
@@ -2069,39 +2042,47 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
struct
e1000_desc_ring
*
tx_ring
=
&
adapter
->
tx_ring
;
struct
net_device
*
netdev
=
adapter
->
netdev
;
struct
pci_dev
*
pdev
=
adapter
->
pdev
;
struct
e1000_tx_desc
*
tx_desc
;
int
i
,
cleaned
=
FALSE
;
struct
e1000_tx_desc
*
tx_desc
,
*
eop_desc
;
struct
e1000_buffer
*
buffer_info
;
int
i
,
eop
,
cleaned
=
FALSE
;
i
=
tx_ring
->
next_to_clean
;
tx_desc
=
E1000_TX_DESC
(
*
tx_ring
,
i
);
eop
=
tx_ring
->
buffer_info
[
i
].
next_to_watch
;
eop_desc
=
E1000_TX_DESC
(
*
tx_ring
,
eop
);
while
(
tx
_desc
->
upper
.
data
&
cpu_to_le32
(
E1000_TXD_STAT_DD
))
{
while
(
eop
_desc
->
upper
.
data
&
cpu_to_le32
(
E1000_TXD_STAT_DD
))
{
cleaned
=
TRUE
;
for
(
cleaned
=
FALSE
;
!
cleaned
;
)
{
tx_desc
=
E1000_TX_DESC
(
*
tx_ring
,
i
);
buffer_info
=
&
tx_ring
->
buffer_info
[
i
];
if
(
tx_ring
->
buffer_info
[
i
].
dma
)
{
if
(
buffer_info
->
dma
)
{
pci_unmap_page
(
pdev
,
tx_ring
->
buffer_info
[
i
].
dma
,
tx_ring
->
buffer_info
[
i
].
length
,
PCI_DMA_TODEVICE
);
pci_unmap_page
(
pdev
,
buffer_info
->
dma
,
buffer_info
->
length
,
PCI_DMA_TODEVICE
);
tx_ring
->
buffer_info
[
i
].
dma
=
0
;
}
buffer_info
->
dma
=
0
;
}
if
(
tx_ring
->
buffer_info
[
i
].
skb
)
{
if
(
buffer_info
->
skb
)
{
dev_kfree_skb_any
(
tx_ring
->
buffer_info
[
i
].
skb
);
dev_kfree_skb_any
(
buffer_info
->
skb
);
tx_ring
->
buffer_info
[
i
].
skb
=
NULL
;
}
buffer_info
->
skb
=
NULL
;
}
tx_desc
->
buffer_addr
=
0
;
tx_desc
->
lower
.
data
=
0
;
tx_desc
->
upper
.
data
=
0
;
tx_desc
->
buffer_addr
=
0
;
tx_desc
->
lower
.
data
=
0
;
tx_desc
->
upper
.
data
=
0
;
if
(
++
i
==
tx_ring
->
count
)
i
=
0
;
tx_desc
=
E1000_TX_DESC
(
*
tx_ring
,
i
);
cleaned
=
(
i
==
eop
);
if
(
++
i
==
tx_ring
->
count
)
i
=
0
;
}
eop
=
tx_ring
->
buffer_info
[
i
].
next_to_watch
;
eop_desc
=
E1000_TX_DESC
(
*
tx_ring
,
eop
);
}
tx_ring
->
next_to_clean
=
i
;
...
...
@@ -2224,7 +2205,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
netif_rx
(
skb
);
}
#endif
/* CONFIG_E1000_NAPI */
netdev
->
last_rx
=
jiffies
;
rx_desc
->
status
=
0
;
...
...
@@ -2677,7 +2657,6 @@ e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
return
NOTIFY_DONE
;
}
static
int
e1000_suspend
(
struct
pci_dev
*
pdev
,
uint32_t
state
)
{
...
...
drivers/net/fc/iph5526.c
View file @
3b9fb4e8
...
...
@@ -134,7 +134,7 @@ clone_list[] __initdata = {
{
0
,}
};
static
void
tachyon_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
irqreturn_t
tachyon_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
void
tachyon_interrupt_handler
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
int
initialize_register_pointers
(
struct
fc_info
*
fi
);
...
...
@@ -623,7 +623,7 @@ u_int bus_addr, bus_indx_addr, i;
}
static
void
tachyon_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
tachyon_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
Scsi_Host
*
host
=
dev_id
;
struct
iph5526_hostdata
*
hostdata
=
(
struct
iph5526_hostdata
*
)
host
->
hostdata
;
...
...
@@ -632,6 +632,7 @@ u_long flags;
spin_lock_irqsave
(
&
fi
->
fc_lock
,
flags
);
tachyon_interrupt_handler
(
irq
,
dev_id
,
regs
);
spin_unlock_irqrestore
(
&
fi
->
fc_lock
,
flags
);
return
IRQ_HANDLED
;
}
static
void
tachyon_interrupt_handler
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
...
...
@@ -3720,12 +3721,13 @@ struct fc_info *fi = (struct fc_info*)dev->priv;
int
iph5526_detect
(
Scsi_Host_Template
*
tmpt
)
{
struct
Scsi_Host
*
host
=
NULL
;
struct
iph5526_hostdata
*
hostdata
;
struct
fc_info
*
fi
=
NULL
;
int
no_of_hosts
=
0
,
timeout
,
i
,
j
,
count
=
0
;
u_int
pci_maddr
=
0
;
struct
pci_dev
*
pdev
=
NULL
;
struct
Scsi_Host
*
host
=
NULL
;
struct
iph5526_hostdata
*
hostdata
;
struct
fc_info
*
fi
=
NULL
;
int
no_of_hosts
=
0
,
i
,
j
,
count
=
0
;
u_int
pci_maddr
=
0
;
struct
pci_dev
*
pdev
=
NULL
;
unsigned
long
timeout
;
tmpt
->
proc_name
=
"iph5526"
;
if
(
pci_present
()
==
0
)
{
...
...
drivers/net/fec.c
View file @
3b9fb4e8
...
...
@@ -188,7 +188,7 @@ struct fec_enet_private {
static
int
fec_enet_open
(
struct
net_device
*
dev
);
static
int
fec_enet_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
static
void
fec_enet_mii
(
struct
net_device
*
dev
);
static
void
fec_enet_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
irqreturn_t
fec_enet_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
void
fec_enet_tx
(
struct
net_device
*
dev
);
static
void
fec_enet_rx
(
struct
net_device
*
dev
);
static
int
fec_enet_close
(
struct
net_device
*
dev
);
...
...
@@ -393,12 +393,13 @@ fec_timeout(struct net_device *dev)
/* The interrupt handler.
* This is called from the MPC core interrupt.
*/
static
void
static
irqreturn_t
fec_enet_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
dev
=
dev_id
;
volatile
fec_t
*
fecp
;
uint
int_events
;
int
handled
=
0
;
fecp
=
(
volatile
fec_t
*
)
dev
->
base_addr
;
...
...
@@ -413,20 +414,27 @@ fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
/* Handle receive event in its own function.
*/
if
(
int_events
&
FEC_ENET_RXF
)
if
(
int_events
&
FEC_ENET_RXF
)
{
handled
=
1
;
fec_enet_rx
(
dev
);
}
/* Transmit OK, or non-fatal error. Update the buffer
descriptors. FEC handles all errors, we just discover
them as part of the transmit process.
*/
if
(
int_events
&
FEC_ENET_TXF
)
if
(
int_events
&
FEC_ENET_TXF
)
{
handled
=
1
;
fec_enet_tx
(
dev
);
}
if
(
int_events
&
FEC_ENET_MII
)
if
(
int_events
&
FEC_ENET_MII
)
{
handled
=
1
;
fec_enet_mii
(
dev
);
}
}
return
IRQ_RETVAL
(
handled
);
}
...
...
drivers/net/fmv18x.c
View file @
3b9fb4e8
...
...
@@ -114,7 +114,7 @@ extern int fmv18x_probe(struct net_device *dev);
static
int
fmv18x_probe1
(
struct
net_device
*
dev
,
short
ioaddr
);
static
int
net_open
(
struct
net_device
*
dev
);
static
int
net_send_packet
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
static
void
net_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
irqreturn_t
net_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
void
net_rx
(
struct
net_device
*
dev
);
static
void
net_timeout
(
struct
net_device
*
dev
);
static
int
net_close
(
struct
net_device
*
dev
);
...
...
@@ -423,7 +423,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
/* The typical workload of the driver:
Handle the network interface interrupts. */
static
void
static
irqreturn_t
net_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
dev
=
dev_id
;
...
...
@@ -476,7 +476,7 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock
(
&
lp
->
lock
);
}
}
return
;
return
IRQ_RETVAL
(
status
)
;
}
/* We have a good packet(s), get it/them out of the buffers. */
...
...
drivers/net/hamradio/scc.c
View file @
3b9fb4e8
...
...
@@ -199,7 +199,7 @@ static void z8530_init(void);
static
void
init_channel
(
struct
scc_channel
*
scc
);
static
void
scc_key_trx
(
struct
scc_channel
*
scc
,
char
tx
);
static
void
scc_isr
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
irqreturn_t
scc_isr
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
void
scc_init_timer
(
struct
scc_channel
*
scc
);
static
int
scc_net_setup
(
struct
scc_channel
*
scc
,
unsigned
char
*
name
,
int
addev
);
...
...
@@ -625,7 +625,7 @@ static void scc_isr_dispatch(struct scc_channel *scc, int vector)
#define SCC_IRQTIMEOUT 30000
static
void
scc_isr
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
scc_isr
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
unsigned
char
vector
;
struct
scc_channel
*
scc
;
...
...
@@ -653,7 +653,7 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
if
(
k
==
SCC_IRQTIMEOUT
)
printk
(
KERN_WARNING
"z8530drv: endless loop in scc_isr()?
\n
"
);
return
;
return
IRQ_HANDLED
;
}
/* Find the SCC generating the interrupt by polling all attached SCCs
...
...
@@ -701,6 +701,7 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
}
else
ctrl
++
;
}
return
IRQ_HANDLED
;
}
...
...
drivers/net/myri_sbus.c
View file @
3b9fb4e8
...
...
@@ -541,6 +541,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct
myri_channel
*
chan
=
&
mp
->
shmem
->
channel
;
unsigned
long
flags
;
u32
status
;
int
handled
=
0
;
spin_lock_irqsave
(
&
mp
->
irq_lock
,
flags
);
...
...
@@ -549,6 +550,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if
(
status
&
ISTAT_HOST
)
{
u32
softstate
;
handled
=
1
;
DIRQ
((
"IRQ_DISAB "
));
myri_disable_irq
(
lregs
,
mp
->
cregs
);
softstate
=
sbus_readl
(
&
chan
->
state
);
...
...
@@ -568,7 +570,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock_irqrestore
(
&
mp
->
irq_lock
,
flags
);
return
IRQ_
HANDLED
;
return
IRQ_
RETVAL
(
handled
)
;
}
static
int
myri_open
(
struct
net_device
*
dev
)
...
...
drivers/net/seeq8005.c
View file @
3b9fb4e8
...
...
@@ -84,7 +84,7 @@ static int seeq8005_probe1(struct net_device *dev, int ioaddr);
static
int
seeq8005_open
(
struct
net_device
*
dev
);
static
void
seeq8005_timeout
(
struct
net_device
*
dev
);
static
int
seeq8005_send_packet
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
static
void
seeq8005_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
irqreturn_t
seeq8005_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
void
seeq8005_rx
(
struct
net_device
*
dev
);
static
int
seeq8005_close
(
struct
net_device
*
dev
);
static
struct
net_device_stats
*
seeq8005_get_stats
(
struct
net_device
*
dev
);
...
...
@@ -400,11 +400,12 @@ static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
/* The typical workload of the driver:
Handle the network interface interrupts. */
static
void
seeq8005_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
seeq8005_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
dev
=
dev_id
;
struct
net_local
*
lp
;
int
ioaddr
,
status
,
boguscount
=
0
;
int
handled
=
0
;
ioaddr
=
dev
->
base_addr
;
lp
=
(
struct
net_local
*
)
dev
->
priv
;
...
...
@@ -416,17 +417,20 @@ static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
if
(
status
&
SEEQSTAT_WINDOW_INT
)
{
handled
=
1
;
outw
(
SEEQCMD_WINDOW_INT_ACK
|
(
status
&
SEEQCMD_INT_MASK
),
SEEQ_CMD
);
if
(
net_debug
)
{
printk
(
"%s: window int!
\n
"
,
dev
->
name
);
}
}
if
(
status
&
SEEQSTAT_TX_INT
)
{
handled
=
1
;
outw
(
SEEQCMD_TX_INT_ACK
|
(
status
&
SEEQCMD_INT_MASK
),
SEEQ_CMD
);
lp
->
stats
.
tx_packets
++
;
netif_wake_queue
(
dev
);
/* Inform upper layers. */
}
if
(
status
&
SEEQSTAT_RX_INT
)
{
handled
=
1
;
/* Got a packet(s). */
seeq8005_rx
(
dev
);
}
...
...
@@ -436,6 +440,7 @@ static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if
(
net_debug
>
2
)
{
printk
(
"%s: eoi
\n
"
,
dev
->
name
);
}
return
IRQ_RETVAL
(
handled
);
}
/* We have a good packet(s), get it/them out of the buffers. */
...
...
drivers/net/sunqe.c
View file @
3b9fb4e8
...
...
@@ -124,6 +124,7 @@ static void qe_init_rings(struct sunqe *qep)
qb
->
qe_rxd
[
i
].
rx_flags
=
(
RXD_OWN
|
((
RXD_PKT_SZ
)
&
RXD_LENGTH
));
}
return
IRQ_HANDLED
;
}
static
int
qe_init
(
struct
sunqe
*
qep
,
int
from_irq
)
...
...
drivers/net/tokenring/lanstreamer.c
View file @
3b9fb4e8
...
...
@@ -201,7 +201,7 @@ static int streamer_open(struct net_device *dev);
static
int
streamer_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
static
int
streamer_close
(
struct
net_device
*
dev
);
static
void
streamer_set_rx_mode
(
struct
net_device
*
dev
);
static
void
streamer_interrupt
(
int
irq
,
void
*
dev_id
,
static
irqreturn_t
streamer_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
struct
net_device_stats
*
streamer_get_stats
(
struct
net_device
*
dev
);
static
int
streamer_set_mac_address
(
struct
net_device
*
dev
,
void
*
addr
);
...
...
@@ -1021,7 +1021,7 @@ static void streamer_rx(struct net_device *dev)
}
/* end for all completed rx descriptors */
}
static
void
streamer_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
streamer_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
dev_id
;
struct
streamer_private
*
streamer_priv
=
...
...
@@ -1142,6 +1142,7 @@ static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
/* while() */
spin_unlock
(
&
streamer_priv
->
streamer_lock
)
;
return
IRQ_HANDLED
;
}
static
int
streamer_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
...
...
drivers/net/tulip/de4x5.c
View file @
3b9fb4e8
...
...
@@ -2027,7 +2027,7 @@ set_multicast_list(struct net_device *dev)
}
}
return
;
return
IRQ_HANDLED
;
}
/*
...
...
drivers/net/wan/lmc/lmc_main.c
View file @
3b9fb4e8
...
...
@@ -117,7 +117,7 @@ static int lmc_rx (struct net_device *dev);
static
int
lmc_open
(
struct
net_device
*
dev
);
static
int
lmc_close
(
struct
net_device
*
dev
);
static
struct
net_device_stats
*
lmc_get_stats
(
struct
net_device
*
dev
);
static
void
lmc_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
static
irqreturn_t
lmc_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
static
int
lmc_set_config
(
struct
net_device
*
dev
,
struct
ifmap
*
map
);
static
void
lmc_initcsrs
(
lmc_softc_t
*
const
sc
,
lmc_csrptr_t
csr_base
,
size_t
csr_size
);
static
void
lmc_softreset
(
lmc_softc_t
*
const
);
...
...
@@ -1388,7 +1388,7 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/
/* Interrupt handling routine. This will take an incoming packet, or clean
* up after a trasmit.
*/
static
void
lmc_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
)
/*fold00*/
static
irqreturn_t
lmc_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
)
/*fold00*/
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
dev_instance
;
lmc_softc_t
*
sc
;
...
...
@@ -1398,6 +1398,7 @@ static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*
unsigned
int
badtx
;
u32
firstcsr
;
int
max_work
=
LMC_RXDESCS
;
int
handled
=
0
;
lmc_trace
(
dev
,
"lmc_interrupt in"
);
...
...
@@ -1421,6 +1422,8 @@ static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*
/* always go through this loop at least once */
while
(
csr
&
sc
->
lmc_intrmask
)
{
handled
=
1
;
/*
* Clear interrupt bits, we handle all case below
*/
...
...
@@ -1580,6 +1583,7 @@ static void lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*
spin_unlock
(
&
sc
->
lmc_lock
);
lmc_trace
(
dev
,
"lmc_interrupt out"
);
return
IRQ_RETVAL
(
handled
);
}
static
int
lmc_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
/*fold00*/
...
...
include/linux/arcdevice.h
View file @
3b9fb4e8
...
...
@@ -329,7 +329,7 @@ void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc);
#endif
void
arcnet_unregister_proto
(
struct
ArcProto
*
proto
);
void
arcnet_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
irqreturn_t
arcnet_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
void
arcdev_setup
(
struct
net_device
*
dev
);
void
arcnet_rx
(
struct
net_device
*
dev
,
int
bufnum
);
...
...
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