Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
acf0f100
Commit
acf0f100
authored
May 29, 2005
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge of /home/davem/src/GIT/tg3-2.6/
parents
79158229
1b628151
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
556 additions
and
15 deletions
+556
-15
drivers/net/tg3.c
drivers/net/tg3.c
+556
-15
No files found.
drivers/net/tg3.c
View file @
acf0f100
...
...
@@ -133,6 +133,8 @@
/* number of ETHTOOL_GSTATS u64's */
#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
#define TG3_NUM_TEST 6
static
char
version
[]
__devinitdata
=
DRV_MODULE_NAME
".c:v"
DRV_MODULE_VERSION
" ("
DRV_MODULE_RELDATE
")
\n
"
;
...
...
@@ -316,6 +318,17 @@ static struct {
{
"nic_tx_threshold_hit"
}
};
static
struct
{
const
char
string
[
ETH_GSTRING_LEN
];
}
ethtool_test_keys
[
TG3_NUM_TEST
]
=
{
{
"nvram test (online) "
},
{
"link test (online) "
},
{
"register test (offline)"
},
{
"memory test (offline)"
},
{
"loopback test (offline)"
},
{
"interrupt test (offline)"
},
};
static
void
tg3_write_indirect_reg32
(
struct
tg3
*
tp
,
u32
off
,
u32
val
)
{
if
((
tp
->
tg3_flags
&
TG3_FLAG_PCIX_TARGET_HWBUG
)
!=
0
)
{
...
...
@@ -3070,7 +3083,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
}
static
int
tg3_init_hw
(
struct
tg3
*
);
static
int
tg3_halt
(
struct
tg3
*
,
int
);
static
int
tg3_halt
(
struct
tg3
*
,
int
,
int
);
#ifdef CONFIG_NET_POLL_CONTROLLER
static
void
tg3_poll_controller
(
struct
net_device
*
dev
)
...
...
@@ -3094,7 +3107,7 @@ static void tg3_reset_task(void *_data)
restart_timer
=
tp
->
tg3_flags2
&
TG3_FLG2_RESTART_TIMER
;
tp
->
tg3_flags2
&=
~
TG3_FLG2_RESTART_TIMER
;
tg3_halt
(
tp
,
0
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
0
);
tg3_init_hw
(
tp
);
tg3_netif_start
(
tp
);
...
...
@@ -3440,7 +3453,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
spin_lock_irq
(
&
tp
->
lock
);
spin_lock
(
&
tp
->
tx_lock
);
tg3_halt
(
tp
,
1
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
tg3_set_mtu
(
dev
,
tp
,
new_mtu
);
...
...
@@ -4131,19 +4144,19 @@ static void tg3_stop_fw(struct tg3 *tp)
}
/* tp->lock is held. */
static
int
tg3_halt
(
struct
tg3
*
tp
,
int
silent
)
static
int
tg3_halt
(
struct
tg3
*
tp
,
int
kind
,
int
silent
)
{
int
err
;
tg3_stop_fw
(
tp
);
tg3_write_sig_pre_reset
(
tp
,
RESET_KIND_SHUTDOWN
);
tg3_write_sig_pre_reset
(
tp
,
kind
);
tg3_abort_hw
(
tp
,
silent
);
err
=
tg3_chip_reset
(
tp
);
tg3_write_sig_legacy
(
tp
,
RESET_KIND_SHUTDOWN
);
tg3_write_sig_post_reset
(
tp
,
RESET_KIND_SHUTDOWN
);
tg3_write_sig_legacy
(
tp
,
kind
);
tg3_write_sig_post_reset
(
tp
,
kind
);
if
(
err
)
return
err
;
...
...
@@ -4357,7 +4370,12 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
*/
tp
->
tg3_flags
|=
TG3_FLAG_PCIX_TARGET_HWBUG
;
/* It is possible that bootcode is still loading at this point.
* Get the nvram lock first before halting the cpu.
*/
tg3_nvram_lock
(
tp
);
err
=
tg3_halt_cpu
(
tp
,
cpu_base
);
tg3_nvram_unlock
(
tp
);
if
(
err
)
goto
out
;
...
...
@@ -5881,6 +5899,9 @@ static int tg3_test_interrupt(struct tg3 *tp)
int
err
,
i
;
u32
int_mbox
=
0
;
if
(
!
netif_running
(
dev
))
return
-
ENODEV
;
tg3_disable_ints
(
tp
);
free_irq
(
tp
->
pdev
->
irq
,
dev
);
...
...
@@ -5984,7 +6005,7 @@ static int tg3_test_msi(struct tg3 *tp)
spin_lock_irq
(
&
tp
->
lock
);
spin_lock
(
&
tp
->
tx_lock
);
tg3_halt
(
tp
,
1
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
err
=
tg3_init_hw
(
tp
);
spin_unlock
(
&
tp
->
tx_lock
);
...
...
@@ -6060,7 +6081,7 @@ static int tg3_open(struct net_device *dev)
err
=
tg3_init_hw
(
tp
);
if
(
err
)
{
tg3_halt
(
tp
,
1
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
tg3_free_rings
(
tp
);
}
else
{
if
(
tp
->
tg3_flags
&
TG3_FLAG_TAGGED_STATUS
)
...
...
@@ -6104,7 +6125,7 @@ static int tg3_open(struct net_device *dev)
pci_disable_msi
(
tp
->
pdev
);
tp
->
tg3_flags2
&=
~
TG3_FLG2_USING_MSI
;
}
tg3_halt
(
tp
,
1
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
tg3_free_rings
(
tp
);
tg3_free_consistent
(
tp
);
...
...
@@ -6377,7 +6398,7 @@ static int tg3_close(struct net_device *dev)
tg3_disable_ints
(
tp
);
tg3_halt
(
tp
,
1
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
tg3_free_rings
(
tp
);
tp
->
tg3_flags
&=
~
(
TG3_FLAG_INIT_COMPLETE
|
...
...
@@ -7097,7 +7118,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
tp
->
tx_pending
=
ering
->
tx_pending
;
if
(
netif_running
(
dev
))
{
tg3_halt
(
tp
,
1
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
tg3_init_hw
(
tp
);
tg3_netif_start
(
tp
);
}
...
...
@@ -7140,7 +7161,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
tp
->
tg3_flags
&=
~
TG3_FLAG_TX_PAUSE
;
if
(
netif_running
(
dev
))
{
tg3_halt
(
tp
,
1
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
tg3_init_hw
(
tp
);
tg3_netif_start
(
tp
);
}
...
...
@@ -7199,12 +7220,20 @@ static int tg3_get_stats_count (struct net_device *dev)
return
TG3_NUM_STATS
;
}
static
int
tg3_get_test_count
(
struct
net_device
*
dev
)
{
return
TG3_NUM_TEST
;
}
static
void
tg3_get_strings
(
struct
net_device
*
dev
,
u32
stringset
,
u8
*
buf
)
{
switch
(
stringset
)
{
case
ETH_SS_STATS
:
memcpy
(
buf
,
&
ethtool_stats_keys
,
sizeof
(
ethtool_stats_keys
));
break
;
case
ETH_SS_TEST
:
memcpy
(
buf
,
&
ethtool_test_keys
,
sizeof
(
ethtool_test_keys
));
break
;
default:
WARN_ON
(
1
);
/* we need a WARN() */
break
;
...
...
@@ -7218,6 +7247,516 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
memcpy
(
tmp_stats
,
tg3_get_estats
(
tp
),
sizeof
(
tp
->
estats
));
}
#define NVRAM_TEST_SIZE 0x100
static
int
tg3_test_nvram
(
struct
tg3
*
tp
)
{
u32
*
buf
,
csum
;
int
i
,
j
,
err
=
0
;
buf
=
kmalloc
(
NVRAM_TEST_SIZE
,
GFP_KERNEL
);
if
(
buf
==
NULL
)
return
-
ENOMEM
;
for
(
i
=
0
,
j
=
0
;
i
<
NVRAM_TEST_SIZE
;
i
+=
4
,
j
++
)
{
u32
val
;
if
((
err
=
tg3_nvram_read
(
tp
,
i
,
&
val
))
!=
0
)
break
;
buf
[
j
]
=
cpu_to_le32
(
val
);
}
if
(
i
<
NVRAM_TEST_SIZE
)
goto
out
;
err
=
-
EIO
;
if
(
cpu_to_be32
(
buf
[
0
])
!=
TG3_EEPROM_MAGIC
)
goto
out
;
/* Bootstrap checksum at offset 0x10 */
csum
=
calc_crc
((
unsigned
char
*
)
buf
,
0x10
);
if
(
csum
!=
cpu_to_le32
(
buf
[
0x10
/
4
]))
goto
out
;
/* Manufacturing block starts at offset 0x74, checksum at 0xfc */
csum
=
calc_crc
((
unsigned
char
*
)
&
buf
[
0x74
/
4
],
0x88
);
if
(
csum
!=
cpu_to_le32
(
buf
[
0xfc
/
4
]))
goto
out
;
err
=
0
;
out:
kfree
(
buf
);
return
err
;
}
#define TG3_SERDES_TIMEOUT_SEC 2
#define TG3_COPPER_TIMEOUT_SEC 6
static
int
tg3_test_link
(
struct
tg3
*
tp
)
{
int
i
,
max
;
if
(
!
netif_running
(
tp
->
dev
))
return
-
ENODEV
;
if
(
tp
->
tg3_flags2
&
TG3_FLG2_PHY_SERDES
)
max
=
TG3_SERDES_TIMEOUT_SEC
;
else
max
=
TG3_COPPER_TIMEOUT_SEC
;
for
(
i
=
0
;
i
<
max
;
i
++
)
{
if
(
netif_carrier_ok
(
tp
->
dev
))
return
0
;
if
(
msleep_interruptible
(
1000
))
break
;
}
return
-
EIO
;
}
/* Only test the commonly used registers */
static
int
tg3_test_registers
(
struct
tg3
*
tp
)
{
int
i
,
is_5705
;
u32
offset
,
read_mask
,
write_mask
,
val
,
save_val
,
read_val
;
static
struct
{
u16
offset
;
u16
flags
;
#define TG3_FL_5705 0x1
#define TG3_FL_NOT_5705 0x2
#define TG3_FL_NOT_5788 0x4
u32
read_mask
;
u32
write_mask
;
}
reg_tbl
[]
=
{
/* MAC Control Registers */
{
MAC_MODE
,
TG3_FL_NOT_5705
,
0x00000000
,
0x00ef6f8c
},
{
MAC_MODE
,
TG3_FL_5705
,
0x00000000
,
0x01ef6b8c
},
{
MAC_STATUS
,
TG3_FL_NOT_5705
,
0x03800107
,
0x00000000
},
{
MAC_STATUS
,
TG3_FL_5705
,
0x03800100
,
0x00000000
},
{
MAC_ADDR_0_HIGH
,
0x0000
,
0x00000000
,
0x0000ffff
},
{
MAC_ADDR_0_LOW
,
0x0000
,
0x00000000
,
0xffffffff
},
{
MAC_RX_MTU_SIZE
,
0x0000
,
0x00000000
,
0x0000ffff
},
{
MAC_TX_MODE
,
0x0000
,
0x00000000
,
0x00000070
},
{
MAC_TX_LENGTHS
,
0x0000
,
0x00000000
,
0x00003fff
},
{
MAC_RX_MODE
,
TG3_FL_NOT_5705
,
0x00000000
,
0x000007fc
},
{
MAC_RX_MODE
,
TG3_FL_5705
,
0x00000000
,
0x000007dc
},
{
MAC_HASH_REG_0
,
0x0000
,
0x00000000
,
0xffffffff
},
{
MAC_HASH_REG_1
,
0x0000
,
0x00000000
,
0xffffffff
},
{
MAC_HASH_REG_2
,
0x0000
,
0x00000000
,
0xffffffff
},
{
MAC_HASH_REG_3
,
0x0000
,
0x00000000
,
0xffffffff
},
/* Receive Data and Receive BD Initiator Control Registers. */
{
RCVDBDI_JUMBO_BD
+
0
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
RCVDBDI_JUMBO_BD
+
4
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
RCVDBDI_JUMBO_BD
+
8
,
TG3_FL_NOT_5705
,
0x00000000
,
0x00000003
},
{
RCVDBDI_JUMBO_BD
+
0xc
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
RCVDBDI_STD_BD
+
0
,
0x0000
,
0x00000000
,
0xffffffff
},
{
RCVDBDI_STD_BD
+
4
,
0x0000
,
0x00000000
,
0xffffffff
},
{
RCVDBDI_STD_BD
+
8
,
0x0000
,
0x00000000
,
0xffff0002
},
{
RCVDBDI_STD_BD
+
0xc
,
0x0000
,
0x00000000
,
0xffffffff
},
/* Receive BD Initiator Control Registers. */
{
RCVBDI_STD_THRESH
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
RCVBDI_STD_THRESH
,
TG3_FL_5705
,
0x00000000
,
0x000003ff
},
{
RCVBDI_JUMBO_THRESH
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
/* Host Coalescing Control Registers. */
{
HOSTCC_MODE
,
TG3_FL_NOT_5705
,
0x00000000
,
0x00000004
},
{
HOSTCC_MODE
,
TG3_FL_5705
,
0x00000000
,
0x000000f6
},
{
HOSTCC_RXCOL_TICKS
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_RXCOL_TICKS
,
TG3_FL_5705
,
0x00000000
,
0x000003ff
},
{
HOSTCC_TXCOL_TICKS
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_TXCOL_TICKS
,
TG3_FL_5705
,
0x00000000
,
0x000003ff
},
{
HOSTCC_RXMAX_FRAMES
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_RXMAX_FRAMES
,
TG3_FL_5705
|
TG3_FL_NOT_5788
,
0x00000000
,
0x000000ff
},
{
HOSTCC_TXMAX_FRAMES
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_TXMAX_FRAMES
,
TG3_FL_5705
|
TG3_FL_NOT_5788
,
0x00000000
,
0x000000ff
},
{
HOSTCC_RXCOAL_TICK_INT
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_TXCOAL_TICK_INT
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_RXCOAL_MAXF_INT
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_RXCOAL_MAXF_INT
,
TG3_FL_5705
|
TG3_FL_NOT_5788
,
0x00000000
,
0x000000ff
},
{
HOSTCC_TXCOAL_MAXF_INT
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_TXCOAL_MAXF_INT
,
TG3_FL_5705
|
TG3_FL_NOT_5788
,
0x00000000
,
0x000000ff
},
{
HOSTCC_STAT_COAL_TICKS
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_STATS_BLK_HOST_ADDR
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_STATS_BLK_HOST_ADDR
+
4
,
TG3_FL_NOT_5705
,
0x00000000
,
0xffffffff
},
{
HOSTCC_STATUS_BLK_HOST_ADDR
,
0x0000
,
0x00000000
,
0xffffffff
},
{
HOSTCC_STATUS_BLK_HOST_ADDR
+
4
,
0x0000
,
0x00000000
,
0xffffffff
},
{
HOSTCC_STATS_BLK_NIC_ADDR
,
0x0000
,
0xffffffff
,
0x00000000
},
{
HOSTCC_STATUS_BLK_NIC_ADDR
,
0x0000
,
0xffffffff
,
0x00000000
},
/* Buffer Manager Control Registers. */
{
BUFMGR_MB_POOL_ADDR
,
0x0000
,
0x00000000
,
0x007fff80
},
{
BUFMGR_MB_POOL_SIZE
,
0x0000
,
0x00000000
,
0x007fffff
},
{
BUFMGR_MB_RDMA_LOW_WATER
,
0x0000
,
0x00000000
,
0x0000003f
},
{
BUFMGR_MB_MACRX_LOW_WATER
,
0x0000
,
0x00000000
,
0x000001ff
},
{
BUFMGR_MB_HIGH_WATER
,
0x0000
,
0x00000000
,
0x000001ff
},
{
BUFMGR_DMA_DESC_POOL_ADDR
,
TG3_FL_NOT_5705
,
0xffffffff
,
0x00000000
},
{
BUFMGR_DMA_DESC_POOL_SIZE
,
TG3_FL_NOT_5705
,
0xffffffff
,
0x00000000
},
/* Mailbox Registers */
{
GRCMBOX_RCVSTD_PROD_IDX
+
4
,
0x0000
,
0x00000000
,
0x000001ff
},
{
GRCMBOX_RCVJUMBO_PROD_IDX
+
4
,
TG3_FL_NOT_5705
,
0x00000000
,
0x000001ff
},
{
GRCMBOX_RCVRET_CON_IDX_0
+
4
,
0x0000
,
0x00000000
,
0x000007ff
},
{
GRCMBOX_SNDHOST_PROD_IDX_0
+
4
,
0x0000
,
0x00000000
,
0x000001ff
},
{
0xffff
,
0x0000
,
0x00000000
,
0x00000000
},
};
if
(
tp
->
tg3_flags2
&
TG3_FLG2_5705_PLUS
)
is_5705
=
1
;
else
is_5705
=
0
;
for
(
i
=
0
;
reg_tbl
[
i
].
offset
!=
0xffff
;
i
++
)
{
if
(
is_5705
&&
(
reg_tbl
[
i
].
flags
&
TG3_FL_NOT_5705
))
continue
;
if
(
!
is_5705
&&
(
reg_tbl
[
i
].
flags
&
TG3_FL_5705
))
continue
;
if
((
tp
->
tg3_flags2
&
TG3_FLG2_IS_5788
)
&&
(
reg_tbl
[
i
].
flags
&
TG3_FL_NOT_5788
))
continue
;
offset
=
(
u32
)
reg_tbl
[
i
].
offset
;
read_mask
=
reg_tbl
[
i
].
read_mask
;
write_mask
=
reg_tbl
[
i
].
write_mask
;
/* Save the original register content */
save_val
=
tr32
(
offset
);
/* Determine the read-only value. */
read_val
=
save_val
&
read_mask
;
/* Write zero to the register, then make sure the read-only bits
* are not changed and the read/write bits are all zeros.
*/
tw32
(
offset
,
0
);
val
=
tr32
(
offset
);
/* Test the read-only and read/write bits. */
if
(((
val
&
read_mask
)
!=
read_val
)
||
(
val
&
write_mask
))
goto
out
;
/* Write ones to all the bits defined by RdMask and WrMask, then
* make sure the read-only bits are not changed and the
* read/write bits are all ones.
*/
tw32
(
offset
,
read_mask
|
write_mask
);
val
=
tr32
(
offset
);
/* Test the read-only bits. */
if
((
val
&
read_mask
)
!=
read_val
)
goto
out
;
/* Test the read/write bits. */
if
((
val
&
write_mask
)
!=
write_mask
)
goto
out
;
tw32
(
offset
,
save_val
);
}
return
0
;
out:
printk
(
KERN_ERR
PFX
"Register test failed at offset %x
\n
"
,
offset
);
tw32
(
offset
,
save_val
);
return
-
EIO
;
}
static
int
tg3_do_mem_test
(
struct
tg3
*
tp
,
u32
offset
,
u32
len
)
{
static
u32
test_pattern
[]
=
{
0x00000000
,
0xffffffff
,
0xaa55a55a
};
int
i
;
u32
j
;
for
(
i
=
0
;
i
<
sizeof
(
test_pattern
)
/
sizeof
(
u32
);
i
++
)
{
for
(
j
=
0
;
j
<
len
;
j
+=
4
)
{
u32
val
;
tg3_write_mem
(
tp
,
offset
+
j
,
test_pattern
[
i
]);
tg3_read_mem
(
tp
,
offset
+
j
,
&
val
);
if
(
val
!=
test_pattern
[
i
])
return
-
EIO
;
}
}
return
0
;
}
static
int
tg3_test_memory
(
struct
tg3
*
tp
)
{
static
struct
mem_entry
{
u32
offset
;
u32
len
;
}
mem_tbl_570x
[]
=
{
{
0x00000000
,
0x01000
},
{
0x00002000
,
0x1c000
},
{
0xffffffff
,
0x00000
}
},
mem_tbl_5705
[]
=
{
{
0x00000100
,
0x0000c
},
{
0x00000200
,
0x00008
},
{
0x00000b50
,
0x00400
},
{
0x00004000
,
0x00800
},
{
0x00006000
,
0x01000
},
{
0x00008000
,
0x02000
},
{
0x00010000
,
0x0e000
},
{
0xffffffff
,
0x00000
}
};
struct
mem_entry
*
mem_tbl
;
int
err
=
0
;
int
i
;
if
(
tp
->
tg3_flags2
&
TG3_FLG2_5705_PLUS
)
mem_tbl
=
mem_tbl_5705
;
else
mem_tbl
=
mem_tbl_570x
;
for
(
i
=
0
;
mem_tbl
[
i
].
offset
!=
0xffffffff
;
i
++
)
{
if
((
err
=
tg3_do_mem_test
(
tp
,
mem_tbl
[
i
].
offset
,
mem_tbl
[
i
].
len
))
!=
0
)
break
;
}
return
err
;
}
static
int
tg3_test_loopback
(
struct
tg3
*
tp
)
{
u32
mac_mode
,
send_idx
,
rx_start_idx
,
rx_idx
,
tx_idx
,
opaque_key
;
u32
desc_idx
;
struct
sk_buff
*
skb
,
*
rx_skb
;
u8
*
tx_data
;
dma_addr_t
map
;
int
num_pkts
,
tx_len
,
rx_len
,
i
,
err
;
struct
tg3_rx_buffer_desc
*
desc
;
if
(
!
netif_running
(
tp
->
dev
))
return
-
ENODEV
;
err
=
-
EIO
;
tg3_abort_hw
(
tp
,
1
);
/* Clearing this flag to keep interrupts disabled */
tp
->
tg3_flags
&=
~
TG3_FLAG_INIT_COMPLETE
;
tg3_reset_hw
(
tp
);
mac_mode
=
(
tp
->
mac_mode
&
~
MAC_MODE_PORT_MODE_MASK
)
|
MAC_MODE_PORT_INT_LPBACK
|
MAC_MODE_LINK_POLARITY
|
MAC_MODE_PORT_MODE_GMII
;
tw32
(
MAC_MODE
,
mac_mode
);
tx_len
=
1514
;
skb
=
dev_alloc_skb
(
tx_len
);
tx_data
=
skb_put
(
skb
,
tx_len
);
memcpy
(
tx_data
,
tp
->
dev
->
dev_addr
,
6
);
memset
(
tx_data
+
6
,
0x0
,
8
);
tw32
(
MAC_RX_MTU_SIZE
,
tx_len
+
4
);
for
(
i
=
14
;
i
<
tx_len
;
i
++
)
tx_data
[
i
]
=
(
u8
)
(
i
&
0xff
);
map
=
pci_map_single
(
tp
->
pdev
,
skb
->
data
,
tx_len
,
PCI_DMA_TODEVICE
);
tw32_f
(
HOSTCC_MODE
,
tp
->
coalesce_mode
|
HOSTCC_MODE_ENABLE
|
HOSTCC_MODE_NOW
);
udelay
(
10
);
rx_start_idx
=
tp
->
hw_status
->
idx
[
0
].
rx_producer
;
send_idx
=
0
;
num_pkts
=
0
;
tg3_set_txd
(
tp
,
send_idx
,
map
,
tx_len
,
0
,
1
);
send_idx
++
;
num_pkts
++
;
tw32_tx_mbox
(
MAILBOX_SNDHOST_PROD_IDX_0
+
TG3_64BIT_REG_LOW
,
send_idx
);
tr32
(
MAILBOX_SNDHOST_PROD_IDX_0
+
TG3_64BIT_REG_LOW
);
udelay
(
10
);
for
(
i
=
0
;
i
<
10
;
i
++
)
{
tw32_f
(
HOSTCC_MODE
,
tp
->
coalesce_mode
|
HOSTCC_MODE_ENABLE
|
HOSTCC_MODE_NOW
);
udelay
(
10
);
tx_idx
=
tp
->
hw_status
->
idx
[
0
].
tx_consumer
;
rx_idx
=
tp
->
hw_status
->
idx
[
0
].
rx_producer
;
if
((
tx_idx
==
send_idx
)
&&
(
rx_idx
==
(
rx_start_idx
+
num_pkts
)))
break
;
}
pci_unmap_single
(
tp
->
pdev
,
map
,
tx_len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb
(
skb
);
if
(
tx_idx
!=
send_idx
)
goto
out
;
if
(
rx_idx
!=
rx_start_idx
+
num_pkts
)
goto
out
;
desc
=
&
tp
->
rx_rcb
[
rx_start_idx
];
desc_idx
=
desc
->
opaque
&
RXD_OPAQUE_INDEX_MASK
;
opaque_key
=
desc
->
opaque
&
RXD_OPAQUE_RING_MASK
;
if
(
opaque_key
!=
RXD_OPAQUE_RING_STD
)
goto
out
;
if
((
desc
->
err_vlan
&
RXD_ERR_MASK
)
!=
0
&&
(
desc
->
err_vlan
!=
RXD_ERR_ODD_NIBBLE_RCVD_MII
))
goto
out
;
rx_len
=
((
desc
->
idx_len
&
RXD_LEN_MASK
)
>>
RXD_LEN_SHIFT
)
-
4
;
if
(
rx_len
!=
tx_len
)
goto
out
;
rx_skb
=
tp
->
rx_std_buffers
[
desc_idx
].
skb
;
map
=
pci_unmap_addr
(
&
tp
->
rx_std_buffers
[
desc_idx
],
mapping
);
pci_dma_sync_single_for_cpu
(
tp
->
pdev
,
map
,
rx_len
,
PCI_DMA_FROMDEVICE
);
for
(
i
=
14
;
i
<
tx_len
;
i
++
)
{
if
(
*
(
rx_skb
->
data
+
i
)
!=
(
u8
)
(
i
&
0xff
))
goto
out
;
}
err
=
0
;
/* tg3_free_rings will unmap and free the rx_skb */
out:
return
err
;
}
static
void
tg3_self_test
(
struct
net_device
*
dev
,
struct
ethtool_test
*
etest
,
u64
*
data
)
{
struct
tg3
*
tp
=
netdev_priv
(
dev
);
memset
(
data
,
0
,
sizeof
(
u64
)
*
TG3_NUM_TEST
);
if
(
tg3_test_nvram
(
tp
)
!=
0
)
{
etest
->
flags
|=
ETH_TEST_FL_FAILED
;
data
[
0
]
=
1
;
}
if
(
tg3_test_link
(
tp
)
!=
0
)
{
etest
->
flags
|=
ETH_TEST_FL_FAILED
;
data
[
1
]
=
1
;
}
if
(
etest
->
flags
&
ETH_TEST_FL_OFFLINE
)
{
if
(
netif_running
(
dev
))
tg3_netif_stop
(
tp
);
spin_lock_irq
(
&
tp
->
lock
);
spin_lock
(
&
tp
->
tx_lock
);
tg3_halt
(
tp
,
RESET_KIND_SUSPEND
,
1
);
tg3_nvram_lock
(
tp
);
tg3_halt_cpu
(
tp
,
RX_CPU_BASE
);
if
(
!
(
tp
->
tg3_flags2
&
TG3_FLG2_5705_PLUS
))
tg3_halt_cpu
(
tp
,
TX_CPU_BASE
);
tg3_nvram_unlock
(
tp
);
if
(
tg3_test_registers
(
tp
)
!=
0
)
{
etest
->
flags
|=
ETH_TEST_FL_FAILED
;
data
[
2
]
=
1
;
}
if
(
tg3_test_memory
(
tp
)
!=
0
)
{
etest
->
flags
|=
ETH_TEST_FL_FAILED
;
data
[
3
]
=
1
;
}
if
(
tg3_test_loopback
(
tp
)
!=
0
)
{
etest
->
flags
|=
ETH_TEST_FL_FAILED
;
data
[
4
]
=
1
;
}
spin_unlock
(
&
tp
->
tx_lock
);
spin_unlock_irq
(
&
tp
->
lock
);
if
(
tg3_test_interrupt
(
tp
)
!=
0
)
{
etest
->
flags
|=
ETH_TEST_FL_FAILED
;
data
[
5
]
=
1
;
}
spin_lock_irq
(
&
tp
->
lock
);
spin_lock
(
&
tp
->
tx_lock
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
if
(
netif_running
(
dev
))
{
tp
->
tg3_flags
|=
TG3_FLAG_INIT_COMPLETE
;
tg3_init_hw
(
tp
);
tg3_netif_start
(
tp
);
}
spin_unlock
(
&
tp
->
tx_lock
);
spin_unlock_irq
(
&
tp
->
lock
);
}
}
static
int
tg3_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
,
int
cmd
)
{
struct
mii_ioctl_data
*
data
=
if_mii
(
ifr
);
...
...
@@ -7331,6 +7870,8 @@ static struct ethtool_ops tg3_ethtool_ops = {
.
get_tso
=
ethtool_op_get_tso
,
.
set_tso
=
tg3_set_tso
,
#endif
.
self_test_count
=
tg3_get_test_count
,
.
self_test
=
tg3_self_test
,
.
get_strings
=
tg3_get_strings
,
.
get_stats_count
=
tg3_get_stats_count
,
.
get_ethtool_stats
=
tg3_get_ethtool_stats
,
...
...
@@ -9478,7 +10019,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
(
tr32
(
WDMAC_MODE
)
&
WDMAC_MODE_ENABLE
))
{
pci_save_state
(
tp
->
pdev
);
tw32
(
MEMARB_MODE
,
MEMARB_MODE_ENABLE
);
tg3_halt
(
tp
,
1
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
}
err
=
tg3_test_dma
(
tp
);
...
...
@@ -9605,7 +10146,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
spin_lock_irq
(
&
tp
->
lock
);
spin_lock
(
&
tp
->
tx_lock
);
tg3_halt
(
tp
,
1
);
tg3_halt
(
tp
,
RESET_KIND_SHUTDOWN
,
1
);
spin_unlock
(
&
tp
->
tx_lock
);
spin_unlock_irq
(
&
tp
->
lock
);
...
...
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