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
2a69bf42
Commit
2a69bf42
authored
Sep 12, 2006
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge tag 'r8169-20060912-00' of
git://electric-eye.fr.zoreil.com/home/romieu/linux-2.6
into tmp
parents
cb930205
b39fe41f
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
380 additions
and
276 deletions
+380
-276
drivers/net/r8169.c
drivers/net/r8169.c
+380
-276
No files found.
drivers/net/r8169.c
View file @
2a69bf42
...
...
@@ -6,26 +6,26 @@
History:
Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>.
May 20 2002 - Add link status force-mode and TBI mode support.
2004 - Massive updates. See kernel SCM system for details.
2004 - Massive updates. See kernel SCM system for details.
=========================================================================
1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
Command: 'insmod r8169 media = SET_MEDIA'
Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
SET_MEDIA can be:
_10_Half = 0x01
_10_Full = 0x02
_100_Half = 0x04
_100_Full = 0x08
_1000_Full = 0x10
2. Support TBI mode.
=========================================================================
VERSION 1.1 <2002/10/4>
The bit4:0 of MII register 4 is called "selector field", and have to be
00001b to indicate support of IEEE std 802.3 during NWay process of
exchanging Link Code Word (FLP).
exchanging Link Code Word (FLP).
VERSION 1.2 <2002/11/30>
...
...
@@ -81,10 +81,10 @@ VERSION 2.2LK <2005/01/25>
#ifdef RTL8169_DEBUG
#define assert(expr) \
if
(!(expr)) { \
printk( "Assertion failed! %s,%s,%s,line=%d\n", \
#expr,__FILE__,__FUNCTION__,__LINE__); \
}
if
(!(expr)) { \
printk( "Assertion failed! %s,%s,%s,line=%d\n", \
#expr,__FILE__,__FUNCTION__,__LINE__); \
}
#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0)
#else
#define assert(expr) do {} while (0)
...
...
@@ -150,11 +150,16 @@ static const int multicast_filter_limit = 32;
#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
enum
mac_version
{
RTL_GIGA_MAC_VER_B
=
0x00
,
/* RTL_GIGA_MAC_VER_C = 0x03, */
RTL_GIGA_MAC_VER_D
=
0x01
,
RTL_GIGA_MAC_VER_E
=
0x02
,
RTL_GIGA_MAC_VER_X
=
0x04
/* Greater than RTL_GIGA_MAC_VER_E */
RTL_GIGA_MAC_VER_01
=
0x00
,
RTL_GIGA_MAC_VER_02
=
0x01
,
RTL_GIGA_MAC_VER_03
=
0x02
,
RTL_GIGA_MAC_VER_04
=
0x03
,
RTL_GIGA_MAC_VER_05
=
0x04
,
RTL_GIGA_MAC_VER_11
=
0x0b
,
RTL_GIGA_MAC_VER_12
=
0x0c
,
RTL_GIGA_MAC_VER_13
=
0x0d
,
RTL_GIGA_MAC_VER_14
=
0x0e
,
RTL_GIGA_MAC_VER_15
=
0x0f
};
enum
phy_version
{
...
...
@@ -166,7 +171,6 @@ enum phy_version {
RTL_GIGA_PHY_VER_H
=
0x08
,
/* PHY Reg 0x03 bit0-3 == 0x0003 */
};
#define _R(NAME,MAC,MASK) \
{ .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
...
...
@@ -175,19 +179,44 @@ static const struct {
u8
mac_version
;
u32
RxConfigMask
;
/* Clears the bits supported by this chip */
}
rtl_chip_info
[]
=
{
_R
(
"RTL8169"
,
RTL_GIGA_MAC_VER_B
,
0xff7e1880
),
_R
(
"RTL8169s/8110s"
,
RTL_GIGA_MAC_VER_D
,
0xff7e1880
),
_R
(
"RTL8169s/8110s"
,
RTL_GIGA_MAC_VER_E
,
0xff7e1880
),
_R
(
"RTL8169s/8110s"
,
RTL_GIGA_MAC_VER_X
,
0xff7e1880
),
_R
(
"RTL8169"
,
RTL_GIGA_MAC_VER_01
,
0xff7e1880
),
_R
(
"RTL8169s/8110s"
,
RTL_GIGA_MAC_VER_02
,
0xff7e1880
),
_R
(
"RTL8169s/8110s"
,
RTL_GIGA_MAC_VER_03
,
0xff7e1880
),
_R
(
"RTL8169sb/8110sb"
,
RTL_GIGA_MAC_VER_04
,
0xff7e1880
),
_R
(
"RTL8169sc/8110sc"
,
RTL_GIGA_MAC_VER_05
,
0xff7e1880
),
_R
(
"RTL8168b/8111b"
,
RTL_GIGA_MAC_VER_11
,
0xff7e1880
),
// PCI-E
_R
(
"RTL8168b/8111b"
,
RTL_GIGA_MAC_VER_12
,
0xff7e1880
),
// PCI-E
_R
(
"RTL8101e"
,
RTL_GIGA_MAC_VER_13
,
0xff7e1880
),
// PCI-E 8139
_R
(
"RTL8100e"
,
RTL_GIGA_MAC_VER_14
,
0xff7e1880
),
// PCI-E 8139
_R
(
"RTL8100e"
,
RTL_GIGA_MAC_VER_15
,
0xff7e1880
)
// PCI-E 8139
};
#undef _R
enum
cfg_version
{
RTL_CFG_0
=
0x00
,
RTL_CFG_1
,
RTL_CFG_2
};
static
const
struct
{
unsigned
int
region
;
unsigned
int
align
;
}
rtl_cfg_info
[]
=
{
[
RTL_CFG_0
]
=
{
1
,
NET_IP_ALIGN
},
[
RTL_CFG_1
]
=
{
2
,
NET_IP_ALIGN
},
[
RTL_CFG_2
]
=
{
2
,
8
}
};
static
struct
pci_device_id
rtl8169_pci_tbl
[]
=
{
{
PCI_DEVICE
(
PCI_VENDOR_ID_REALTEK
,
0x8169
),
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_REALTEK
,
0x8129
),
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_DLINK
,
0x4300
),
},
{
PCI_DEVICE
(
0x16ec
,
0x0116
),
},
{
PCI_VENDOR_ID_LINKSYS
,
0x1032
,
PCI_ANY_ID
,
0x0024
,
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_REALTEK
,
0x8129
),
0
,
0
,
RTL_CFG_0
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_REALTEK
,
0x8136
),
0
,
0
,
RTL_CFG_2
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_REALTEK
,
0x8167
),
0
,
0
,
RTL_CFG_1
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_REALTEK
,
0x8168
),
0
,
0
,
RTL_CFG_2
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_REALTEK
,
0x8169
),
0
,
0
,
RTL_CFG_0
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_DLINK
,
0x4300
),
0
,
0
,
RTL_CFG_0
},
{
PCI_DEVICE
(
0x16ec
,
0x0116
),
0
,
0
,
RTL_CFG_0
},
{
PCI_VENDOR_ID_LINKSYS
,
0x1032
,
PCI_ANY_ID
,
0x0024
,
0
,
0
,
RTL_CFG_0
},
{
0
,},
};
...
...
@@ -257,10 +286,11 @@ enum RTL8169_register_content {
RxOK
=
0x01
,
/* RxStatusDesc */
RxRES
=
0x00200000
,
RxCRC
=
0x00080000
,
RxRUNT
=
0x00100000
,
RxRWT
=
0x00400000
,
RxFOVF
=
(
1
<<
23
),
RxRWT
=
(
1
<<
22
),
RxRES
=
(
1
<<
21
),
RxRUNT
=
(
1
<<
20
),
RxCRC
=
(
1
<<
19
),
/* ChipCmdBits */
CmdReset
=
0x10
,
...
...
@@ -326,30 +356,6 @@ enum RTL8169_register_content {
LinkStatus
=
0x02
,
FullDup
=
0x01
,
/* GIGABIT_PHY_registers */
PHY_CTRL_REG
=
0
,
PHY_STAT_REG
=
1
,
PHY_AUTO_NEGO_REG
=
4
,
PHY_1000_CTRL_REG
=
9
,
/* GIGABIT_PHY_REG_BIT */
PHY_Restart_Auto_Nego
=
0x0200
,
PHY_Enable_Auto_Nego
=
0x1000
,
/* PHY_STAT_REG = 1 */
PHY_Auto_Neco_Comp
=
0x0020
,
/* PHY_AUTO_NEGO_REG = 4 */
PHY_Cap_10_Half
=
0x0020
,
PHY_Cap_10_Full
=
0x0040
,
PHY_Cap_100_Half
=
0x0080
,
PHY_Cap_100_Full
=
0x0100
,
/* PHY_1000_CTRL_REG = 9 */
PHY_Cap_1000_Full
=
0x0200
,
PHY_Cap_Null
=
0x0
,
/* _MediaType */
_10_Half
=
0x01
,
_10_Full
=
0x02
,
...
...
@@ -433,6 +439,7 @@ struct rtl8169_private {
dma_addr_t
RxPhyAddr
;
struct
sk_buff
*
Rx_skbuff
[
NUM_RX_DESC
];
/* Rx data buffers */
struct
ring_info
tx_skb
[
NUM_TX_DESC
];
/* Tx data buffers */
unsigned
align
;
unsigned
rx_buf_sz
;
struct
timer_list
timer
;
u16
cp_cmd
;
...
...
@@ -488,12 +495,7 @@ static const u16 rtl8169_intr_mask =
static
const
u16
rtl8169_napi_event
=
RxOK
|
RxOverflow
|
RxFIFOOver
|
TxOK
|
TxErr
;
static
const
unsigned
int
rtl8169_rx_config
=
(
RX_FIFO_THRESH
<<
RxCfgFIFOShift
)
|
(
RX_DMA_BURST
<<
RxCfgDMAShift
);
#define PHY_Cap_10_Half_Or_Less PHY_Cap_10_Half
#define PHY_Cap_10_Full_Or_Less PHY_Cap_10_Full | PHY_Cap_10_Half_Or_Less
#define PHY_Cap_100_Half_Or_Less PHY_Cap_100_Half | PHY_Cap_10_Full_Or_Less
#define PHY_Cap_100_Full_Or_Less PHY_Cap_100_Full | PHY_Cap_100_Half_Or_Less
(
RX_FIFO_THRESH
<<
RxCfgFIFOShift
)
|
(
RX_DMA_BURST
<<
RxCfgDMAShift
);
static
void
mdio_write
(
void
__iomem
*
ioaddr
,
int
RegAddr
,
int
value
)
{
...
...
@@ -503,7 +505,7 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
for
(
i
=
20
;
i
>
0
;
i
--
)
{
/* Check if the RTL8169 has completed writing to the specified MII register */
if
(
!
(
RTL_R32
(
PHYAR
)
&
0x80000000
))
if
(
!
(
RTL_R32
(
PHYAR
)
&
0x80000000
))
break
;
udelay
(
25
);
}
...
...
@@ -547,7 +549,7 @@ static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr)
static
unsigned
int
rtl8169_xmii_reset_pending
(
void
__iomem
*
ioaddr
)
{
return
mdio_read
(
ioaddr
,
0
)
&
0x8000
;
return
mdio_read
(
ioaddr
,
MII_BMCR
)
&
BMCR_RESET
;
}
static
unsigned
int
rtl8169_tbi_link_ok
(
void
__iomem
*
ioaddr
)
...
...
@@ -569,8 +571,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
{
unsigned
int
val
;
val
=
(
mdio_read
(
ioaddr
,
PHY_CTRL_REG
)
|
0x8000
)
&
0xffff
;
mdio_write
(
ioaddr
,
PHY_CTRL_REG
,
val
);
val
=
(
mdio_read
(
ioaddr
,
MII_BMCR
)
|
BMCR_RESET
)
&
0xffff
;
mdio_write
(
ioaddr
,
MII_BMCR
,
val
);
}
static
void
rtl8169_check_link_status
(
struct
net_device
*
dev
,
...
...
@@ -608,7 +610,7 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
{
SPEED_1000
,
DUPLEX_FULL
,
AUTONEG_ENABLE
,
0xff
}
},
*
p
;
unsigned
char
option
;
option
=
((
idx
<
MAX_UNITS
)
&&
(
idx
>=
0
))
?
media
[
idx
]
:
0xff
;
if
((
option
!=
0xff
)
&&
!
idx
&&
netif_msg_drv
(
&
debug
))
...
...
@@ -650,9 +652,9 @@ static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
if
(
options
&
UWF
)
wol
->
wolopts
|=
WAKE_UCAST
;
if
(
options
&
BWF
)
wol
->
wolopts
|=
WAKE_BCAST
;
wol
->
wolopts
|=
WAKE_BCAST
;
if
(
options
&
MWF
)
wol
->
wolopts
|=
WAKE_MCAST
;
wol
->
wolopts
|=
WAKE_MCAST
;
out_unlock:
spin_unlock_irq
(
&
tp
->
lock
);
...
...
@@ -745,38 +747,57 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
void
__iomem
*
ioaddr
=
tp
->
mmio_addr
;
int
auto_nego
,
giga_ctrl
;
auto_nego
=
mdio_read
(
ioaddr
,
PHY_AUTO_NEGO_REG
);
auto_nego
&=
~
(
PHY_Cap_10_Half
|
PHY_Cap_10_Full
|
PHY_Cap_100_Half
|
PHY_Cap_100_Full
);
giga_ctrl
=
mdio_read
(
ioaddr
,
PHY_1000_CTRL_REG
);
giga_ctrl
&=
~
(
PHY_Cap_1000_Full
|
PHY_Cap_Null
);
auto_nego
=
mdio_read
(
ioaddr
,
MII_ADVERTISE
);
auto_nego
&=
~
(
ADVERTISE_10HALF
|
ADVERTISE_10FULL
|
ADVERTISE_100HALF
|
ADVERTISE_100FULL
);
giga_ctrl
=
mdio_read
(
ioaddr
,
MII_CTRL1000
);
giga_ctrl
&=
~
(
ADVERTISE_1000FULL
|
ADVERTISE_1000HALF
);
if
(
autoneg
==
AUTONEG_ENABLE
)
{
auto_nego
|=
(
PHY_Cap_10_Half
|
PHY_Cap_10_Full
|
PHY_Cap_100_Half
|
PHY_Cap_100_Full
);
giga_ctrl
|=
PHY_Cap_1000_Full
;
auto_nego
|=
(
ADVERTISE_10HALF
|
ADVERTISE_10FULL
|
ADVERTISE_100HALF
|
ADVERTISE_100FULL
);
giga_ctrl
|=
ADVERTISE_1000FULL
|
ADVERTISE_1000HALF
;
}
else
{
if
(
speed
==
SPEED_10
)
auto_nego
|=
PHY_Cap_10_Half
|
PHY_Cap_10_Full
;
auto_nego
|=
ADVERTISE_10HALF
|
ADVERTISE_10FULL
;
else
if
(
speed
==
SPEED_100
)
auto_nego
|=
PHY_Cap_100_Half
|
PHY_Cap_100_Full
;
auto_nego
|=
ADVERTISE_100HALF
|
ADVERTISE_100FULL
;
else
if
(
speed
==
SPEED_1000
)
giga_ctrl
|=
PHY_Cap_1000_Full
;
giga_ctrl
|=
ADVERTISE_1000FULL
|
ADVERTISE_1000HALF
;
if
(
duplex
==
DUPLEX_HALF
)
auto_nego
&=
~
(
PHY_Cap_10_Full
|
PHY_Cap_100_Full
);
auto_nego
&=
~
(
ADVERTISE_10FULL
|
ADVERTISE_100FULL
);
if
(
duplex
==
DUPLEX_FULL
)
auto_nego
&=
~
(
PHY_Cap_10_Half
|
PHY_Cap_100_Half
);
auto_nego
&=
~
(
ADVERTISE_10HALF
|
ADVERTISE_100HALF
);
/* This tweak comes straight from Realtek's driver. */
if
((
speed
==
SPEED_100
)
&&
(
duplex
==
DUPLEX_HALF
)
&&
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_13
))
{
auto_nego
=
ADVERTISE_100HALF
|
ADVERTISE_CSMA
;
}
}
/* The 8100e/8101e do Fast Ethernet only. */
if
((
tp
->
mac_version
==
RTL_GIGA_MAC_VER_13
)
||
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_14
)
||
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_15
))
{
if
((
giga_ctrl
&
(
ADVERTISE_1000FULL
|
ADVERTISE_1000HALF
))
&&
netif_msg_link
(
tp
))
{
printk
(
KERN_INFO
"%s: PHY does not support 1000Mbps.
\n
"
,
dev
->
name
);
}
giga_ctrl
&=
~
(
ADVERTISE_1000FULL
|
ADVERTISE_1000HALF
);
}
auto_nego
|=
ADVERTISE_PAUSE_CAP
|
ADVERTISE_PAUSE_ASYM
;
tp
->
phy_auto_nego_reg
=
auto_nego
;
tp
->
phy_1000_ctrl_reg
=
giga_ctrl
;
mdio_write
(
ioaddr
,
PHY_AUTO_NEGO_REG
,
auto_nego
);
mdio_write
(
ioaddr
,
PHY_1000_CTRL_REG
,
giga_ctrl
);
mdio_write
(
ioaddr
,
PHY_CTRL_REG
,
PHY_Enable_Auto_Nego
|
PHY_Restart_Auto_Nego
);
mdio_write
(
ioaddr
,
MII_ADVERTISE
,
auto_nego
);
mdio_write
(
ioaddr
,
MII_CTRL1000
,
giga_ctrl
);
mdio_write
(
ioaddr
,
MII_BMCR
,
BMCR_ANENABLE
|
BMCR_ANRESTART
);
return
0
;
}
...
...
@@ -788,7 +809,7 @@ static int rtl8169_set_speed(struct net_device *dev,
ret
=
tp
->
set_speed
(
dev
,
autoneg
,
speed
,
duplex
);
if
(
netif_running
(
dev
)
&&
(
tp
->
phy_1000_ctrl_reg
&
PHY_Cap_1000_Full
))
if
(
netif_running
(
dev
)
&&
(
tp
->
phy_1000_ctrl_reg
&
ADVERTISE_1000FULL
))
mod_timer
(
&
tp
->
timer
,
jiffies
+
RTL8169_PHY_TIMEOUT
);
return
ret
;
...
...
@@ -803,7 +824,7 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
spin_lock_irqsave
(
&
tp
->
lock
,
flags
);
ret
=
rtl8169_set_speed
(
dev
,
cmd
->
autoneg
,
cmd
->
speed
,
cmd
->
duplex
);
spin_unlock_irqrestore
(
&
tp
->
lock
,
flags
);
return
ret
;
}
...
...
@@ -936,20 +957,20 @@ static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
SUPPORTED_100baseT_Full
|
SUPPORTED_1000baseT_Full
|
SUPPORTED_Autoneg
|
SUPPORTED_TP
;
SUPPORTED_TP
;
cmd
->
autoneg
=
1
;
cmd
->
advertising
=
ADVERTISED_TP
|
ADVERTISED_Autoneg
;
if
(
tp
->
phy_auto_nego_reg
&
PHY_Cap_10_Half
)
if
(
tp
->
phy_auto_nego_reg
&
ADVERTISE_10HALF
)
cmd
->
advertising
|=
ADVERTISED_10baseT_Half
;
if
(
tp
->
phy_auto_nego_reg
&
PHY_Cap_10_Full
)
if
(
tp
->
phy_auto_nego_reg
&
ADVERTISE_10FULL
)
cmd
->
advertising
|=
ADVERTISED_10baseT_Full
;
if
(
tp
->
phy_auto_nego_reg
&
PHY_Cap_100_Half
)
if
(
tp
->
phy_auto_nego_reg
&
ADVERTISE_100HALF
)
cmd
->
advertising
|=
ADVERTISED_100baseT_Half
;
if
(
tp
->
phy_auto_nego_reg
&
PHY_Cap_100_Full
)
if
(
tp
->
phy_auto_nego_reg
&
ADVERTISE_100FULL
)
cmd
->
advertising
|=
ADVERTISED_100baseT_Full
;
if
(
tp
->
phy_1000_ctrl_reg
&
PHY_Cap_1000_Full
)
if
(
tp
->
phy_1000_ctrl_reg
&
ADVERTISE_1000FULL
)
cmd
->
advertising
|=
ADVERTISED_1000baseT_Full
;
status
=
RTL_R8
(
PHYstatus
);
...
...
@@ -961,6 +982,11 @@ static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
else
if
(
status
&
_10bps
)
cmd
->
speed
=
SPEED_10
;
if
(
status
&
TxFlowCtrl
)
cmd
->
advertising
|=
ADVERTISED_Asym_Pause
;
if
(
status
&
RxFlowCtrl
)
cmd
->
advertising
|=
ADVERTISED_Pause
;
cmd
->
duplex
=
((
status
&
_1000bpsF
)
||
(
status
&
FullDup
))
?
DUPLEX_FULL
:
DUPLEX_HALF
;
}
...
...
@@ -981,15 +1007,15 @@ static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static
void
rtl8169_get_regs
(
struct
net_device
*
dev
,
struct
ethtool_regs
*
regs
,
void
*
p
)
{
struct
rtl8169_private
*
tp
=
netdev_priv
(
dev
);
unsigned
long
flags
;
struct
rtl8169_private
*
tp
=
netdev_priv
(
dev
);
unsigned
long
flags
;
if
(
regs
->
len
>
R8169_REGS_SIZE
)
regs
->
len
=
R8169_REGS_SIZE
;
if
(
regs
->
len
>
R8169_REGS_SIZE
)
regs
->
len
=
R8169_REGS_SIZE
;
spin_lock_irqsave
(
&
tp
->
lock
,
flags
);
memcpy_fromio
(
p
,
tp
->
mmio_addr
,
regs
->
len
);
spin_unlock_irqrestore
(
&
tp
->
lock
,
flags
);
spin_lock_irqsave
(
&
tp
->
lock
,
flags
);
memcpy_fromio
(
p
,
tp
->
mmio_addr
,
regs
->
len
);
spin_unlock_irqrestore
(
&
tp
->
lock
,
flags
);
}
static
u32
rtl8169_get_msglevel
(
struct
net_device
*
dev
)
...
...
@@ -1071,7 +1097,7 @@ static void rtl8169_get_ethtool_stats(struct net_device *dev,
RTL_W32
(
CounterAddrLow
,
0
);
RTL_W32
(
CounterAddrHigh
,
0
);
data
[
0
]
=
le64_to_cpu
(
counters
->
tx_packets
);
data
[
0
]
=
le64_to_cpu
(
counters
->
tx_packets
);
data
[
1
]
=
le64_to_cpu
(
counters
->
rx_packets
);
data
[
2
]
=
le64_to_cpu
(
counters
->
tx_errors
);
data
[
3
]
=
le32_to_cpu
(
counters
->
rx_errors
);
...
...
@@ -1131,7 +1157,7 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum
val
=
mdio_read
(
ioaddr
,
reg
);
val
=
(
bitval
==
1
)
?
val
|
(
bitval
<<
bitnum
)
:
val
&
~
(
0x0001
<<
bitnum
);
mdio_write
(
ioaddr
,
reg
,
val
&
0xffff
);
mdio_write
(
ioaddr
,
reg
,
val
&
0xffff
);
}
static
void
rtl8169_get_mac_version
(
struct
rtl8169_private
*
tp
,
void
__iomem
*
ioaddr
)
...
...
@@ -1140,10 +1166,16 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
u32
mask
;
int
mac_version
;
}
mac_info
[]
=
{
{
0x1
<<
28
,
RTL_GIGA_MAC_VER_X
},
{
0x1
<<
26
,
RTL_GIGA_MAC_VER_E
},
{
0x1
<<
23
,
RTL_GIGA_MAC_VER_D
},
{
0x00000000
,
RTL_GIGA_MAC_VER_B
}
/* Catch-all */
{
0x38800000
,
RTL_GIGA_MAC_VER_15
},
{
0x38000000
,
RTL_GIGA_MAC_VER_12
},
{
0x34000000
,
RTL_GIGA_MAC_VER_13
},
{
0x30800000
,
RTL_GIGA_MAC_VER_14
},
{
0x30000000
,
RTL_GIGA_MAC_VER_11
},
{
0x18000000
,
RTL_GIGA_MAC_VER_05
},
{
0x10000000
,
RTL_GIGA_MAC_VER_04
},
{
0x04000000
,
RTL_GIGA_MAC_VER_03
},
{
0x00800000
,
RTL_GIGA_MAC_VER_02
},
{
0x00000000
,
RTL_GIGA_MAC_VER_01
}
/* Catch-all */
},
*
p
=
mac_info
;
u32
reg
;
...
...
@@ -1155,24 +1187,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
static
void
rtl8169_print_mac_version
(
struct
rtl8169_private
*
tp
)
{
struct
{
int
version
;
char
*
msg
;
}
mac_print
[]
=
{
{
RTL_GIGA_MAC_VER_E
,
"RTL_GIGA_MAC_VER_E"
},
{
RTL_GIGA_MAC_VER_D
,
"RTL_GIGA_MAC_VER_D"
},
{
RTL_GIGA_MAC_VER_B
,
"RTL_GIGA_MAC_VER_B"
},
{
0
,
NULL
}
},
*
p
;
for
(
p
=
mac_print
;
p
->
msg
;
p
++
)
{
if
(
tp
->
mac_version
==
p
->
version
)
{
dprintk
(
"mac_version == %s (%04d)
\n
"
,
p
->
msg
,
p
->
version
);
return
;
}
}
dprintk
(
"mac_version == Unknown
\n
"
);
dprintk
(
"mac_version = 0x%02x
\n
"
,
tp
->
mac_version
);
}
static
void
rtl8169_get_phy_version
(
struct
rtl8169_private
*
tp
,
void
__iomem
*
ioaddr
)
...
...
@@ -1189,7 +1204,7 @@ static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *io
},
*
p
=
phy_info
;
u16
reg
;
reg
=
mdio_read
(
ioaddr
,
3
)
&
0xffff
;
reg
=
mdio_read
(
ioaddr
,
MII_PHYSID2
)
&
0xffff
;
while
((
reg
&
p
->
mask
)
!=
p
->
set
)
p
++
;
tp
->
phy_version
=
p
->
phy_version
;
...
...
@@ -1257,7 +1272,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
rtl8169_print_mac_version
(
tp
);
rtl8169_print_phy_version
(
tp
);
if
(
tp
->
mac_version
<=
RTL_GIGA_MAC_VER_
B
)
if
(
tp
->
mac_version
<=
RTL_GIGA_MAC_VER_
01
)
return
;
if
(
tp
->
phy_version
>=
RTL_GIGA_PHY_VER_H
)
return
;
...
...
@@ -1267,7 +1282,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
/* Shazam ! */
if
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_
X
)
{
if
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_
04
)
{
mdio_write
(
ioaddr
,
31
,
0x0001
);
mdio_write
(
ioaddr
,
9
,
0x273a
);
mdio_write
(
ioaddr
,
14
,
0x7bfb
);
...
...
@@ -1306,16 +1321,16 @@ static void rtl8169_phy_timer(unsigned long __opaque)
void
__iomem
*
ioaddr
=
tp
->
mmio_addr
;
unsigned
long
timeout
=
RTL8169_PHY_TIMEOUT
;
assert
(
tp
->
mac_version
>
RTL_GIGA_MAC_VER_
B
);
assert
(
tp
->
mac_version
>
RTL_GIGA_MAC_VER_
01
);
assert
(
tp
->
phy_version
<
RTL_GIGA_PHY_VER_H
);
if
(
!
(
tp
->
phy_1000_ctrl_reg
&
PHY_Cap_1000_Full
))
if
(
!
(
tp
->
phy_1000_ctrl_reg
&
ADVERTISE_1000FULL
))
return
;
spin_lock_irq
(
&
tp
->
lock
);
if
(
tp
->
phy_reset_pending
(
ioaddr
))
{
/*
/*
* A busy loop could burn quite a few cycles on nowadays CPU.
* Let's delay the execution of the timer for a few ticks.
*/
...
...
@@ -1342,7 +1357,7 @@ static inline void rtl8169_delete_timer(struct net_device *dev)
struct
rtl8169_private
*
tp
=
netdev_priv
(
dev
);
struct
timer_list
*
timer
=
&
tp
->
timer
;
if
((
tp
->
mac_version
<=
RTL_GIGA_MAC_VER_
B
)
||
if
((
tp
->
mac_version
<=
RTL_GIGA_MAC_VER_
01
)
||
(
tp
->
phy_version
>=
RTL_GIGA_PHY_VER_H
))
return
;
...
...
@@ -1354,7 +1369,7 @@ static inline void rtl8169_request_timer(struct net_device *dev)
struct
rtl8169_private
*
tp
=
netdev_priv
(
dev
);
struct
timer_list
*
timer
=
&
tp
->
timer
;
if
((
tp
->
mac_version
<=
RTL_GIGA_MAC_VER_
B
)
||
if
((
tp
->
mac_version
<=
RTL_GIGA_MAC_VER_
01
)
||
(
tp
->
phy_version
>=
RTL_GIGA_PHY_VER_H
))
return
;
...
...
@@ -1382,6 +1397,41 @@ static void rtl8169_netpoll(struct net_device *dev)
}
#endif
static
void
__rtl8169_set_mac_addr
(
struct
net_device
*
dev
,
void
__iomem
*
ioaddr
)
{
unsigned
int
i
,
j
;
RTL_W8
(
Cfg9346
,
Cfg9346_Unlock
);
for
(
i
=
0
;
i
<
2
;
i
++
)
{
__le32
l
=
0
;
for
(
j
=
0
;
j
<
4
;
j
++
)
{
l
<<=
8
;
l
|=
dev
->
dev_addr
[
4
*
i
+
j
];
}
RTL_W32
(
MAC0
+
4
*
i
,
cpu_to_be32
(
l
));
}
RTL_W8
(
Cfg9346
,
Cfg9346_Lock
);
}
static
int
rtl8169_set_mac_addr
(
struct
net_device
*
dev
,
void
*
p
)
{
struct
rtl8169_private
*
tp
=
netdev_priv
(
dev
);
struct
sockaddr
*
addr
=
p
;
if
(
!
is_valid_ether_addr
(
addr
->
sa_data
))
return
-
EINVAL
;
memcpy
(
dev
->
dev_addr
,
addr
->
sa_data
,
dev
->
addr_len
);
if
(
netif_running
(
dev
))
{
spin_lock_irq
(
&
tp
->
lock
);
__rtl8169_set_mac_addr
(
dev
,
tp
->
mmio_addr
);
spin_unlock_irq
(
&
tp
->
lock
);
}
return
0
;
}
static
void
rtl8169_release_board
(
struct
pci_dev
*
pdev
,
struct
net_device
*
dev
,
void
__iomem
*
ioaddr
)
{
...
...
@@ -1391,23 +1441,87 @@ static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
free_netdev
(
dev
);
}
static
void
rtl8169_init_phy
(
struct
net_device
*
dev
,
struct
rtl8169_private
*
tp
)
{
void
__iomem
*
ioaddr
=
tp
->
mmio_addr
;
static
int
board_idx
=
-
1
;
u8
autoneg
,
duplex
;
u16
speed
;
board_idx
++
;
rtl8169_hw_phy_config
(
dev
);
dprintk
(
"Set MAC Reg C+CR Offset 0x82h = 0x01h
\n
"
);
RTL_W8
(
0x82
,
0x01
);
if
(
tp
->
mac_version
<
RTL_GIGA_MAC_VER_03
)
{
dprintk
(
"Set PCI Latency=0x40
\n
"
);
pci_write_config_byte
(
tp
->
pci_dev
,
PCI_LATENCY_TIMER
,
0x40
);
}
if
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_02
)
{
dprintk
(
"Set MAC Reg C+CR Offset 0x82h = 0x01h
\n
"
);
RTL_W8
(
0x82
,
0x01
);
dprintk
(
"Set PHY Reg 0x0bh = 0x00h
\n
"
);
mdio_write
(
ioaddr
,
0x0b
,
0x0000
);
//w 0x0b 15 0 0
}
rtl8169_link_option
(
board_idx
,
&
autoneg
,
&
speed
,
&
duplex
);
rtl8169_set_speed
(
dev
,
autoneg
,
speed
,
duplex
);
if
((
RTL_R8
(
PHYstatus
)
&
TBI_Enable
)
&&
netif_msg_link
(
tp
))
printk
(
KERN_INFO
PFX
"%s: TBI auto-negotiating
\n
"
,
dev
->
name
);
}
static
int
rtl8169_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
,
int
cmd
)
{
struct
rtl8169_private
*
tp
=
netdev_priv
(
dev
);
struct
mii_ioctl_data
*
data
=
if_mii
(
ifr
);
if
(
!
netif_running
(
dev
))
return
-
ENODEV
;
switch
(
cmd
)
{
case
SIOCGMIIPHY
:
data
->
phy_id
=
32
;
/* Internal PHY */
return
0
;
case
SIOCGMIIREG
:
data
->
val_out
=
mdio_read
(
tp
->
mmio_addr
,
data
->
reg_num
&
0x1f
);
return
0
;
case
SIOCSMIIREG
:
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
mdio_write
(
tp
->
mmio_addr
,
data
->
reg_num
&
0x1f
,
data
->
val_in
);
return
0
;
}
return
-
EOPNOTSUPP
;
}
static
int
__devinit
rtl8169_init_board
(
struct
pci_dev
*
pdev
,
struct
net_device
**
dev_out
,
void
__iomem
**
ioaddr_out
)
rtl8169_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
void
__iomem
*
ioaddr
;
struct
net_device
*
dev
;
const
unsigned
int
region
=
rtl_cfg_info
[
ent
->
driver_data
].
region
;
struct
rtl8169_private
*
tp
;
int
rc
=
-
ENOMEM
,
i
,
acpi_idle_state
=
0
,
pm_cap
;
struct
net_device
*
dev
;
void
__iomem
*
ioaddr
;
unsigned
int
i
,
pm_cap
;
int
rc
;
assert
(
ioaddr_out
!=
NULL
);
if
(
netif_msg_drv
(
&
debug
))
{
printk
(
KERN_INFO
"%s Gigabit Ethernet driver %s loaded
\n
"
,
MODULENAME
,
RTL8169_VERSION
);
}
/* dev zeroed in alloc_etherdev */
dev
=
alloc_etherdev
(
sizeof
(
*
tp
));
if
(
dev
==
NULL
)
{
if
(
!
dev
)
{
if
(
netif_msg_drv
(
&
debug
))
dev_err
(
&
pdev
->
dev
,
"unable to alloc new ethernet
\n
"
);
goto
err_out
;
rc
=
-
ENOMEM
;
goto
out
;
}
SET_MODULE_OWNER
(
dev
);
...
...
@@ -1420,48 +1534,53 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
if
(
rc
<
0
)
{
if
(
netif_msg_probe
(
tp
))
dev_err
(
&
pdev
->
dev
,
"enable failure
\n
"
);
goto
err_out_free_dev
;
goto
err_out_free_dev
_1
;
}
rc
=
pci_set_mwi
(
pdev
);
if
(
rc
<
0
)
goto
err_out_disable
;
goto
err_out_disable
_2
;
/* save power state before pci_enable_device overwrites it */
pm_cap
=
pci_find_capability
(
pdev
,
PCI_CAP_ID_PM
);
if
(
pm_cap
)
{
u16
pwr_command
;
u16
pwr_command
,
acpi_idle_state
;
pci_read_config_word
(
pdev
,
pm_cap
+
PCI_PM_CTRL
,
&
pwr_command
);
acpi_idle_state
=
pwr_command
&
PCI_PM_CTRL_STATE_MASK
;
}
else
{
if
(
netif_msg_probe
(
tp
))
if
(
netif_msg_probe
(
tp
))
{
dev_err
(
&
pdev
->
dev
,
"PowerManagement capability not found.
\n
"
);
"PowerManagement capability not found.
\n
"
);
}
}
/* make sure PCI base addr 1 is MMIO */
if
(
!
(
pci_resource_flags
(
pdev
,
1
)
&
IORESOURCE_MEM
))
{
if
(
netif_msg_probe
(
tp
))
if
(
!
(
pci_resource_flags
(
pdev
,
region
)
&
IORESOURCE_MEM
))
{
if
(
netif_msg_probe
(
tp
))
{
dev_err
(
&
pdev
->
dev
,
"region #1 not an MMIO resource, aborting
\n
"
);
"region #%d not an MMIO resource, aborting
\n
"
,
region
);
}
rc
=
-
ENODEV
;
goto
err_out_mwi
;
goto
err_out_mwi
_3
;
}
/* check for weird/broken PCI region reporting */
if
(
pci_resource_len
(
pdev
,
1
)
<
R8169_REGS_SIZE
)
{
if
(
netif_msg_probe
(
tp
))
if
(
pci_resource_len
(
pdev
,
region
)
<
R8169_REGS_SIZE
)
{
if
(
netif_msg_probe
(
tp
))
{
dev_err
(
&
pdev
->
dev
,
"Invalid PCI region size(s), aborting
\n
"
);
"Invalid PCI region size(s), aborting
\n
"
);
}
rc
=
-
ENODEV
;
goto
err_out_mwi
;
goto
err_out_mwi
_3
;
}
rc
=
pci_request_regions
(
pdev
,
MODULENAME
);
if
(
rc
<
0
)
{
if
(
netif_msg_probe
(
tp
))
dev_err
(
&
pdev
->
dev
,
"could not request regions.
\n
"
);
goto
err_out_mwi
;
goto
err_out_mwi
_3
;
}
tp
->
cp_cmd
=
PCIMulRW
|
RxChkSum
;
...
...
@@ -1473,22 +1592,23 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
}
else
{
rc
=
pci_set_dma_mask
(
pdev
,
DMA_32BIT_MASK
);
if
(
rc
<
0
)
{
if
(
netif_msg_probe
(
tp
))
if
(
netif_msg_probe
(
tp
))
{
dev_err
(
&
pdev
->
dev
,
"DMA configuration failed.
\n
"
);
goto
err_out_free_res
;
"DMA configuration failed.
\n
"
);
}
goto
err_out_free_res_4
;
}
}
pci_set_master
(
pdev
);
/* ioremap MMIO region */
ioaddr
=
ioremap
(
pci_resource_start
(
pdev
,
1
),
R8169_REGS_SIZE
);
if
(
ioaddr
==
NULL
)
{
ioaddr
=
ioremap
(
pci_resource_start
(
pdev
,
region
),
R8169_REGS_SIZE
);
if
(
!
ioaddr
)
{
if
(
netif_msg_probe
(
tp
))
dev_err
(
&
pdev
->
dev
,
"cannot remap MMIO, aborting
\n
"
);
rc
=
-
EIO
;
goto
err_out_free_res
;
goto
err_out_free_res
_4
;
}
/* Unneeded ? Don't mess with Mrs. Murphy. */
...
...
@@ -1498,10 +1618,10 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
RTL_W8
(
ChipCmd
,
CmdReset
);
/* Check that the chip has finished the reset. */
for
(
i
=
100
0
;
i
>
0
;
i
--
)
{
for
(
i
=
100
;
i
>
0
;
i
--
)
{
if
((
RTL_R8
(
ChipCmd
)
&
CmdReset
)
==
0
)
break
;
udelay
(
10
);
msleep_interruptible
(
1
);
}
/* Identify chip attached to board */
...
...
@@ -1519,8 +1639,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
/* Unknown chip: assume array element #0, original RTL-8169 */
if
(
netif_msg_probe
(
tp
))
{
dev_printk
(
KERN_DEBUG
,
&
pdev
->
dev
,
"unknown chip version, assuming %s
\n
"
,
rtl_chip_info
[
0
].
name
);
"unknown chip version, assuming %s
\n
"
,
rtl_chip_info
[
0
].
name
);
}
i
++
;
}
...
...
@@ -1531,56 +1651,6 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
RTL_W8
(
Config5
,
RTL_R8
(
Config5
)
&
PMEStatus
);
RTL_W8
(
Cfg9346
,
Cfg9346_Lock
);
*
ioaddr_out
=
ioaddr
;
*
dev_out
=
dev
;
out:
return
rc
;
err_out_free_res:
pci_release_regions
(
pdev
);
err_out_mwi:
pci_clear_mwi
(
pdev
);
err_out_disable:
pci_disable_device
(
pdev
);
err_out_free_dev:
free_netdev
(
dev
);
err_out:
*
ioaddr_out
=
NULL
;
*
dev_out
=
NULL
;
goto
out
;
}
static
int
__devinit
rtl8169_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
struct
net_device
*
dev
=
NULL
;
struct
rtl8169_private
*
tp
;
void
__iomem
*
ioaddr
=
NULL
;
static
int
board_idx
=
-
1
;
u8
autoneg
,
duplex
;
u16
speed
;
int
i
,
rc
;
assert
(
pdev
!=
NULL
);
assert
(
ent
!=
NULL
);
board_idx
++
;
if
(
netif_msg_drv
(
&
debug
))
{
printk
(
KERN_INFO
"%s Gigabit Ethernet driver %s loaded
\n
"
,
MODULENAME
,
RTL8169_VERSION
);
}
rc
=
rtl8169_init_board
(
pdev
,
&
dev
,
&
ioaddr
);
if
(
rc
)
return
rc
;
tp
=
netdev_priv
(
dev
);
assert
(
ioaddr
!=
NULL
);
if
(
RTL_R8
(
PHYstatus
)
&
TBI_Enable
)
{
tp
->
set_speed
=
rtl8169_set_speed_tbi
;
tp
->
get_settings
=
rtl8169_gset_tbi
;
...
...
@@ -1588,13 +1658,15 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp
->
phy_reset_pending
=
rtl8169_tbi_reset_pending
;
tp
->
link_ok
=
rtl8169_tbi_link_ok
;
tp
->
phy_1000_ctrl_reg
=
PHY_Cap_1000_Full
;
/* Implied by TBI */
tp
->
phy_1000_ctrl_reg
=
ADVERTISE_1000FULL
;
/* Implied by TBI */
}
else
{
tp
->
set_speed
=
rtl8169_set_speed_xmii
;
tp
->
get_settings
=
rtl8169_gset_xmii
;
tp
->
phy_reset_enable
=
rtl8169_xmii_reset_enable
;
tp
->
phy_reset_pending
=
rtl8169_xmii_reset_pending
;
tp
->
link_ok
=
rtl8169_xmii_link_ok
;
dev
->
do_ioctl
=
rtl8169_ioctl
;
}
/* Get MAC address. FIXME: read EEPROM */
...
...
@@ -1609,6 +1681,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev
->
stop
=
rtl8169_close
;
dev
->
tx_timeout
=
rtl8169_tx_timeout
;
dev
->
set_multicast_list
=
rtl8169_set_rx_mode
;
dev
->
set_mac_address
=
rtl8169_set_mac_addr
;
dev
->
watchdog_timeo
=
RTL8169_TX_TIMEOUT
;
dev
->
irq
=
pdev
->
irq
;
dev
->
base_addr
=
(
unsigned
long
)
ioaddr
;
...
...
@@ -1632,19 +1705,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp
->
intr_mask
=
0xffff
;
tp
->
pci_dev
=
pdev
;
tp
->
mmio_addr
=
ioaddr
;
tp
->
align
=
rtl_cfg_info
[
ent
->
driver_data
].
align
;
spin_lock_init
(
&
tp
->
lock
);
rc
=
register_netdev
(
dev
);
if
(
rc
)
{
rtl8169_release_board
(
pdev
,
dev
,
ioaddr
);
return
rc
;
}
if
(
netif_msg_probe
(
tp
))
{
printk
(
KERN_DEBUG
"%s: Identified chip type is '%s'.
\n
"
,
dev
->
name
,
rtl_chip_info
[
tp
->
chipset
].
name
);
}
if
(
rc
<
0
)
goto
err_out_unmap_5
;
pci_set_drvdata
(
pdev
,
dev
);
...
...
@@ -1653,38 +1720,29 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
"IRQ %d
\n
"
,
dev
->
name
,
rtl_chip_info
[
ent
->
driver_data
].
name
,
rtl_chip_info
[
tp
->
chipset
].
name
,
dev
->
base_addr
,
dev
->
dev_addr
[
0
],
dev
->
dev_addr
[
1
],
dev
->
dev_addr
[
2
],
dev
->
dev_addr
[
3
],
dev
->
dev_addr
[
4
],
dev
->
dev_addr
[
5
],
dev
->
irq
);
}
rtl8169_hw_phy_config
(
dev
);
dprintk
(
"Set MAC Reg C+CR Offset 0x82h = 0x01h
\n
"
);
RTL_W8
(
0x82
,
0x01
);
rtl8169_init_phy
(
dev
,
tp
);
if
(
tp
->
mac_version
<
RTL_GIGA_MAC_VER_E
)
{
dprintk
(
"Set PCI Latency=0x40
\n
"
);
pci_write_config_byte
(
pdev
,
PCI_LATENCY_TIMER
,
0x40
);
}
if
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_D
)
{
dprintk
(
"Set MAC Reg C+CR Offset 0x82h = 0x01h
\n
"
);
RTL_W8
(
0x82
,
0x01
);
dprintk
(
"Set PHY Reg 0x0bh = 0x00h
\n
"
);
mdio_write
(
ioaddr
,
0x0b
,
0x0000
);
//w 0x0b 15 0 0
}
rtl8169_link_option
(
board_idx
,
&
autoneg
,
&
speed
,
&
duplex
);
rtl8169_set_speed
(
dev
,
autoneg
,
speed
,
duplex
);
if
((
RTL_R8
(
PHYstatus
)
&
TBI_Enable
)
&&
netif_msg_link
(
tp
))
printk
(
KERN_INFO
PFX
"%s: TBI auto-negotiating
\n
"
,
dev
->
name
);
out:
return
rc
;
return
0
;
err_out_unmap_5:
iounmap
(
ioaddr
);
err_out_free_res_4:
pci_release_regions
(
pdev
);
err_out_mwi_3:
pci_clear_mwi
(
pdev
);
err_out_disable_2:
pci_disable_device
(
pdev
);
err_out_free_dev_1:
free_netdev
(
dev
);
goto
out
;
}
static
void
__devexit
...
...
@@ -1780,20 +1838,41 @@ rtl8169_hw_start(struct net_device *dev)
{
struct
rtl8169_private
*
tp
=
netdev_priv
(
dev
);
void
__iomem
*
ioaddr
=
tp
->
mmio_addr
;
struct
pci_dev
*
pdev
=
tp
->
pci_dev
;
u32
i
;
/* Soft reset the chip. */
RTL_W8
(
ChipCmd
,
CmdReset
);
/* Check that the chip has finished the reset. */
for
(
i
=
100
0
;
i
>
0
;
i
--
)
{
for
(
i
=
100
;
i
>
0
;
i
--
)
{
if
((
RTL_R8
(
ChipCmd
)
&
CmdReset
)
==
0
)
break
;
udelay
(
10
);
msleep_interruptible
(
1
);
}
if
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_13
)
{
pci_write_config_word
(
pdev
,
0x68
,
0x00
);
pci_write_config_word
(
pdev
,
0x69
,
0x08
);
}
/* Undocumented stuff. */
if
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_05
)
{
u16
cmd
;
/* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */
if
((
RTL_R8
(
Config2
)
&
0x07
)
&
0x01
)
RTL_W32
(
0x7c
,
0x0007ffff
);
RTL_W32
(
0x7c
,
0x0007ff00
);
pci_read_config_word
(
pdev
,
PCI_COMMAND
,
&
cmd
);
cmd
=
cmd
&
0xef
;
pci_write_config_word
(
pdev
,
PCI_COMMAND
,
cmd
);
}
RTL_W8
(
Cfg9346
,
Cfg9346_Unlock
);
RTL_W8
(
ChipCmd
,
CmdTxEnb
|
CmdRxEnb
);
RTL_W8
(
EarlyTxThres
,
EarlyTxThld
);
/* Low hurts. Let's disable the filtering. */
...
...
@@ -1805,32 +1884,40 @@ rtl8169_hw_start(struct net_device *dev)
RTL_W32
(
RxConfig
,
i
);
/* Set DMA burst size and Interframe Gap Time */
RTL_W32
(
TxConfig
,
(
TX_DMA_BURST
<<
TxDMAShift
)
|
(
InterFrameGap
<<
TxInterFrameGapShift
));
tp
->
cp_cmd
|=
RTL_R16
(
CPlusCmd
);
RTL_W16
(
CPlusCmd
,
tp
->
cp_cmd
);
RTL_W32
(
TxConfig
,
(
TX_DMA_BURST
<<
TxDMAShift
)
|
(
InterFrameGap
<<
TxInterFrameGapShift
));
tp
->
cp_cmd
|=
RTL_R16
(
CPlusCmd
)
|
PCIMulRW
;
if
((
tp
->
mac_version
==
RTL_GIGA_MAC_VER_
D
)
||
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_
E
))
{
if
((
tp
->
mac_version
==
RTL_GIGA_MAC_VER_
02
)
||
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_
03
))
{
dprintk
(
KERN_INFO
PFX
"Set MAC Reg C+CR Offset 0xE0. "
"Bit-3 and bit-14 MUST be 1
\n
"
);
tp
->
cp_cmd
|=
(
1
<<
14
)
|
PCIMulRW
;
RTL_W16
(
CPlusCmd
,
tp
->
cp_cmd
);
tp
->
cp_cmd
|=
(
1
<<
14
);
}
RTL_W16
(
CPlusCmd
,
tp
->
cp_cmd
);
/*
* Undocumented corner. Supposedly:
* (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
*/
RTL_W16
(
IntrMitigate
,
0x0000
);
RTL_W32
(
TxDescStartAddrLow
,
((
u64
)
tp
->
TxPhyAddr
&
DMA_32BIT_MASK
));
/*
* Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
* register to be written before TxDescAddrLow to work.
* Switching from MMIO to I/O access fixes the issue as well.
*/
RTL_W32
(
TxDescStartAddrHigh
,
((
u64
)
tp
->
TxPhyAddr
>>
32
));
RTL_W32
(
RxDescAddrLow
,
((
u64
)
tp
->
R
xPhyAddr
&
DMA_32BIT_MASK
));
RTL_W32
(
TxDescStartAddrLow
,
((
u64
)
tp
->
T
xPhyAddr
&
DMA_32BIT_MASK
));
RTL_W32
(
RxDescAddrHigh
,
((
u64
)
tp
->
RxPhyAddr
>>
32
));
RTL_W32
(
RxDescAddrLow
,
((
u64
)
tp
->
RxPhyAddr
&
DMA_32BIT_MASK
));
RTL_W8
(
ChipCmd
,
CmdTxEnb
|
CmdRxEnb
);
RTL_W8
(
Cfg9346
,
Cfg9346_Lock
);
udelay
(
10
);
/* Initially a 10 us delay. Turned it into a PCI commit. - FR */
RTL_R8
(
IntrMask
);
RTL_W32
(
RxMissed
,
0
);
...
...
@@ -1842,6 +1929,8 @@ rtl8169_hw_start(struct net_device *dev)
/* Enable all known interrupts by setting the interrupt mask. */
RTL_W16
(
IntrMask
,
rtl8169_intr_mask
);
__rtl8169_set_mac_addr
(
dev
,
ioaddr
);
netif_start_queue
(
dev
);
}
...
...
@@ -1910,17 +1999,18 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
}
static
int
rtl8169_alloc_rx_skb
(
struct
pci_dev
*
pdev
,
struct
sk_buff
**
sk_buff
,
struct
RxDesc
*
desc
,
int
rx_buf_sz
)
struct
RxDesc
*
desc
,
int
rx_buf_sz
,
unsigned
int
align
)
{
struct
sk_buff
*
skb
;
dma_addr_t
mapping
;
int
ret
=
0
;
skb
=
dev_alloc_skb
(
rx_buf_sz
+
NET_IP_ALIGN
);
skb
=
dev_alloc_skb
(
rx_buf_sz
+
align
);
if
(
!
skb
)
goto
err_out
;
skb_reserve
(
skb
,
NET_IP_ALIGN
);
skb_reserve
(
skb
,
align
);
*
sk_buff
=
skb
;
mapping
=
pci_map_single
(
pdev
,
skb
->
data
,
rx_buf_sz
,
...
...
@@ -1953,15 +2043,15 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
u32
start
,
u32
end
)
{
u32
cur
;
for
(
cur
=
start
;
end
-
cur
>
0
;
cur
++
)
{
int
ret
,
i
=
cur
%
NUM_RX_DESC
;
if
(
tp
->
Rx_skbuff
[
i
])
continue
;
ret
=
rtl8169_alloc_rx_skb
(
tp
->
pci_dev
,
tp
->
Rx_skbuff
+
i
,
tp
->
RxDescArray
+
i
,
tp
->
rx_buf_sz
);
tp
->
RxDescArray
+
i
,
tp
->
rx_buf_sz
,
tp
->
align
);
if
(
ret
<
0
)
break
;
}
...
...
@@ -2190,8 +2280,8 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
dma_addr_t
mapping
;
u32
status
,
len
;
u32
opts1
;
int
ret
=
0
;
int
ret
=
NETDEV_TX_OK
;
if
(
unlikely
(
TX_BUFFS_AVAIL
(
tp
)
<
skb_shinfo
(
skb
)
->
nr_frags
))
{
if
(
netif_msg_drv
(
tp
))
{
printk
(
KERN_ERR
...
...
@@ -2255,7 +2345,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
err_stop:
netif_stop_queue
(
dev
);
ret
=
1
;
ret
=
NETDEV_TX_BUSY
;
err_update_stats:
tp
->
stats
.
tx_dropped
++
;
goto
out
;
...
...
@@ -2372,16 +2462,17 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
}
static
inline
int
rtl8169_try_rx_copy
(
struct
sk_buff
**
sk_buff
,
int
pkt_size
,
struct
RxDesc
*
desc
,
int
rx_buf_sz
)
struct
RxDesc
*
desc
,
int
rx_buf_sz
,
unsigned
int
align
)
{
int
ret
=
-
1
;
if
(
pkt_size
<
rx_copybreak
)
{
struct
sk_buff
*
skb
;
skb
=
dev_alloc_skb
(
pkt_size
+
NET_IP_ALIGN
);
skb
=
dev_alloc_skb
(
pkt_size
+
align
);
if
(
skb
)
{
skb_reserve
(
skb
,
NET_IP_ALIGN
);
skb_reserve
(
skb
,
align
);
eth_copy_and_sum
(
skb
,
sk_buff
[
0
]
->
data
,
pkt_size
,
0
);
*
sk_buff
=
skb
;
rtl8169_mark_to_asic
(
desc
,
rx_buf_sz
);
...
...
@@ -2427,6 +2518,10 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
tp
->
stats
.
rx_length_errors
++
;
if
(
status
&
RxCRC
)
tp
->
stats
.
rx_crc_errors
++
;
if
(
status
&
RxFOVF
)
{
rtl8169_schedule_work
(
dev
,
rtl8169_reset_task
);
tp
->
stats
.
rx_fifo_errors
++
;
}
rtl8169_mark_to_asic
(
desc
,
tp
->
rx_buf_sz
);
}
else
{
struct
sk_buff
*
skb
=
tp
->
Rx_skbuff
[
entry
];
...
...
@@ -2447,13 +2542,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
}
rtl8169_rx_csum
(
skb
,
desc
);
pci_dma_sync_single_for_cpu
(
tp
->
pci_dev
,
le64_to_cpu
(
desc
->
addr
),
tp
->
rx_buf_sz
,
PCI_DMA_FROMDEVICE
);
if
(
rtl8169_try_rx_copy
(
&
skb
,
pkt_size
,
desc
,
tp
->
rx_buf_sz
))
{
tp
->
rx_buf_sz
,
tp
->
align
))
{
pci_action
=
pci_unmap_single
;
tp
->
Rx_skbuff
[
entry
]
=
NULL
;
}
...
...
@@ -2543,7 +2638,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
__netif_rx_schedule
(
dev
);
else
if
(
netif_msg_intr
(
tp
))
{
printk
(
KERN_INFO
"%s: interrupt %04x taken in poll
\n
"
,
dev
->
name
,
status
);
dev
->
name
,
status
);
}
break
;
#else
...
...
@@ -2716,6 +2811,15 @@ rtl8169_set_rx_mode(struct net_device *dev)
tmp
=
rtl8169_rx_config
|
rx_mode
|
(
RTL_R32
(
RxConfig
)
&
rtl_chip_info
[
tp
->
chipset
].
RxConfigMask
);
if
((
tp
->
mac_version
==
RTL_GIGA_MAC_VER_11
)
||
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_12
)
||
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_13
)
||
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_14
)
||
(
tp
->
mac_version
==
RTL_GIGA_MAC_VER_15
))
{
mc_filter
[
0
]
=
0xffffffff
;
mc_filter
[
1
]
=
0xffffffff
;
}
RTL_W32
(
RxConfig
,
tmp
);
RTL_W32
(
MAR0
+
0
,
mc_filter
[
0
]);
RTL_W32
(
MAR0
+
4
,
mc_filter
[
1
]);
...
...
@@ -2741,7 +2845,7 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
RTL_W32
(
RxMissed
,
0
);
spin_unlock_irqrestore
(
&
tp
->
lock
,
flags
);
}
return
&
tp
->
stats
;
}
...
...
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