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
a19d03a3
Commit
a19d03a3
authored
Mar 20, 2002
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge 2.4.x Sun GEM/HME net driver fixes.
parent
71c54597
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
306 additions
and
75 deletions
+306
-75
drivers/net/sungem.c
drivers/net/sungem.c
+287
-73
drivers/net/sungem.h
drivers/net/sungem.h
+5
-0
drivers/net/sunhme.c
drivers/net/sunhme.c
+14
-2
No files found.
drivers/net/sungem.c
View file @
a19d03a3
...
...
@@ -16,6 +16,8 @@
* I can at least detect gigabit with autoneg.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
...
...
@@ -35,9 +37,10 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/crc32.h>
#include <linux/random.h>
#include <asm/system.h>
#include <asm/bitops.h>
...
...
@@ -293,19 +296,119 @@ static int gem_txmac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_s
return
0
;
}
/* When we get a RX fifo overflow, the RX unit in GEM is probably hung
* so we do the following.
*
* If any part of the reset goes wrong, we return 1 and that causes the
* whole chip to be reset.
*/
static
int
gem_rxmac_reset
(
struct
gem
*
gp
)
{
struct
net_device
*
dev
=
gp
->
dev
;
int
limit
,
i
;
u64
desc_dma
;
u32
val
;
/* First, reset MAC RX. */
writel
(
gp
->
mac_rx_cfg
&
~
MAC_RXCFG_ENAB
,
gp
->
regs
+
MAC_RXCFG
);
for
(
limit
=
0
;
limit
<
5000
;
limit
++
)
{
if
(
!
(
readl
(
gp
->
regs
+
MAC_RXCFG
)
&
MAC_RXCFG_ENAB
))
break
;
udelay
(
10
);
}
if
(
limit
==
5000
)
{
printk
(
KERN_ERR
"%s: RX MAC will not disable, resetting whole "
"chip.
\n
"
,
dev
->
name
);
return
1
;
}
/* Second, disable RX DMA. */
writel
(
0
,
gp
->
regs
+
RXDMA_CFG
);
for
(
limit
=
0
;
limit
<
5000
;
limit
++
)
{
if
(
!
(
readl
(
gp
->
regs
+
RXDMA_CFG
)
&
RXDMA_CFG_ENABLE
))
break
;
udelay
(
10
);
}
if
(
limit
==
5000
)
{
printk
(
KERN_ERR
"%s: RX DMA will not disable, resetting whole "
"chip.
\n
"
,
dev
->
name
);
return
1
;
}
udelay
(
5000
);
/* Execute RX reset command. */
writel
(
gp
->
swrst_base
|
GREG_SWRST_RXRST
,
gp
->
regs
+
GREG_SWRST
);
for
(
limit
=
0
;
limit
<
5000
;
limit
++
)
{
if
(
!
(
readl
(
gp
->
regs
+
GREG_SWRST
)
&
GREG_SWRST_RXRST
))
break
;
udelay
(
10
);
}
if
(
limit
==
5000
)
{
printk
(
KERN_ERR
"%s: RX reset command will not execute, resetting "
"whole chip.
\n
"
,
dev
->
name
);
return
1
;
}
/* Refresh the RX ring. */
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
{
struct
gem_rxd
*
rxd
=
&
gp
->
init_block
->
rxd
[
i
];
if
(
gp
->
rx_skbs
[
i
]
==
NULL
)
{
printk
(
KERN_ERR
"%s: Parts of RX ring empty, resetting "
"whole chip.
\n
"
,
dev
->
name
);
return
1
;
}
rxd
->
status_word
=
cpu_to_le64
(
RXDCTRL_FRESH
(
gp
));
}
gp
->
rx_new
=
gp
->
rx_old
=
0
;
/* Now we must reprogram the rest of RX unit. */
desc_dma
=
(
u64
)
gp
->
gblock_dvma
;
desc_dma
+=
(
INIT_BLOCK_TX_RING_SIZE
*
sizeof
(
struct
gem_txd
));
writel
(
desc_dma
>>
32
,
gp
->
regs
+
RXDMA_DBHI
);
writel
(
desc_dma
&
0xffffffff
,
gp
->
regs
+
RXDMA_DBLOW
);
writel
(
RX_RING_SIZE
-
4
,
gp
->
regs
+
RXDMA_KICK
);
val
=
(
RXDMA_CFG_BASE
|
(
RX_OFFSET
<<
10
)
|
((
14
/
2
)
<<
13
)
|
RXDMA_CFG_FTHRESH_128
);
writel
(
val
,
gp
->
regs
+
RXDMA_CFG
);
if
(
readl
(
gp
->
regs
+
GREG_BIFCFG
)
&
GREG_BIFCFG_M66EN
)
writel
(((
5
&
RXDMA_BLANK_IPKTS
)
|
((
8
<<
12
)
&
RXDMA_BLANK_ITIME
)),
gp
->
regs
+
RXDMA_BLANK
);
else
writel
(((
5
&
RXDMA_BLANK_IPKTS
)
|
((
4
<<
12
)
&
RXDMA_BLANK_ITIME
)),
gp
->
regs
+
RXDMA_BLANK
);
val
=
(((
gp
->
rx_pause_off
/
64
)
<<
0
)
&
RXDMA_PTHRESH_OFF
);
val
|=
(((
gp
->
rx_pause_on
/
64
)
<<
12
)
&
RXDMA_PTHRESH_ON
);
writel
(
val
,
gp
->
regs
+
RXDMA_PTHRESH
);
val
=
readl
(
gp
->
regs
+
RXDMA_CFG
);
writel
(
val
|
RXDMA_CFG_ENABLE
,
gp
->
regs
+
RXDMA_CFG
);
writel
(
MAC_RXSTAT_RCV
,
gp
->
regs
+
MAC_RXMASK
);
val
=
readl
(
gp
->
regs
+
MAC_RXCFG
);
writel
(
val
|
MAC_RXCFG_ENAB
,
gp
->
regs
+
MAC_RXCFG
);
return
0
;
}
static
int
gem_rxmac_interrupt
(
struct
net_device
*
dev
,
struct
gem
*
gp
,
u32
gem_status
)
{
u32
rxmac_stat
=
readl
(
gp
->
regs
+
MAC_RXSTAT
);
int
ret
=
0
;
if
(
netif_msg_intr
(
gp
))
printk
(
KERN_DEBUG
"%s: rxmac interrupt, rxmac_stat: 0x%x
\n
"
,
gp
->
dev
->
name
,
rxmac_stat
);
if
(
rxmac_stat
&
MAC_RXSTAT_OFLW
)
{
printk
(
KERN_ERR
"%s: RX MAC fifo overflow.
\n
"
,
dev
->
name
);
gp
->
net_stats
.
rx_over_errors
++
;
gp
->
net_stats
.
rx_fifo_errors
++
;
ret
=
gem_rxmac_reset
(
gp
);
}
if
(
rxmac_stat
&
MAC_RXSTAT_ACE
)
...
...
@@ -320,7 +423,7 @@ static int gem_rxmac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_s
/* We do not track MAC_RXSTAT_FCE and MAC_RXSTAT_VCE
* events.
*/
return
0
;
return
ret
;
}
static
int
gem_mac_interrupt
(
struct
net_device
*
dev
,
struct
gem
*
gp
,
u32
gem_status
)
...
...
@@ -480,7 +583,7 @@ static int gem_abnormal_irq(struct net_device *dev, struct gem *gp, u32 gem_stat
return
0
;
do_reset:
gp
->
reset_task_pending
=
1
;
gp
->
reset_task_pending
=
2
;
schedule_task
(
&
gp
->
reset_task
);
return
1
;
...
...
@@ -542,7 +645,7 @@ static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_st
gp
->
tx_old
=
entry
;
if
(
netif_queue_stopped
(
dev
)
&&
TX_BUFFS_AVAIL
(
gp
)
>
0
)
TX_BUFFS_AVAIL
(
gp
)
>
(
MAX_SKB_FRAGS
+
1
)
)
netif_wake_queue
(
dev
);
}
...
...
@@ -717,7 +820,7 @@ static void gem_tx_timeout(struct net_device *dev)
spin_lock_irq
(
&
gp
->
lock
);
gp
->
reset_task_pending
=
1
;
gp
->
reset_task_pending
=
2
;
schedule_task
(
&
gp
->
reset_task
);
spin_unlock_irq
(
&
gp
->
lock
);
...
...
@@ -752,9 +855,12 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irq
(
&
gp
->
lock
);
/* This is a hard error, log it. */
if
(
TX_BUFFS_AVAIL
(
gp
)
<=
(
skb_shinfo
(
skb
)
->
nr_frags
+
1
))
{
netif_stop_queue
(
dev
);
spin_unlock_irq
(
&
gp
->
lock
);
printk
(
KERN_ERR
PFX
"%s: BUG! Tx Ring full when queue awake!
\n
"
,
dev
->
name
);
return
1
;
}
...
...
@@ -829,7 +935,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
gp
->
tx_new
=
entry
;
if
(
TX_BUFFS_AVAIL
(
gp
)
<=
0
)
if
(
TX_BUFFS_AVAIL
(
gp
)
<=
(
MAX_SKB_FRAGS
+
1
)
)
netif_stop_queue
(
dev
);
if
(
netif_msg_tx_queued
(
gp
))
...
...
@@ -844,19 +950,28 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
/* Jumbo-grams don't seem to work :-( */
#define GEM_MIN_MTU 68
#if 1
#define
MAX_MTU
1500
#define
GEM_MAX_MTU
1500
#else
#define
MAX_MTU
9000
#define
GEM_MAX_MTU
9000
#endif
static
int
gem_change_mtu
(
struct
net_device
*
dev
,
int
new_mtu
)
{
struct
gem
*
gp
=
dev
->
priv
;
if
(
new_mtu
<
0
||
new_mtu
>
MAX_MTU
)
if
(
new_mtu
<
GEM_MIN_MTU
||
new_mtu
>
GEM_
MAX_MTU
)
return
-
EINVAL
;
if
(
!
netif_running
(
dev
)
||
!
netif_device_present
(
dev
))
{
/* We'll just catch it later when the
* device is up'd or resumed.
*/
dev
->
mtu
=
new_mtu
;
return
0
;
}
spin_lock_irq
(
&
gp
->
lock
);
dev
->
mtu
=
new_mtu
;
gp
->
reset_task_pending
=
1
;
...
...
@@ -870,6 +985,7 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
#define STOP_TRIES 32
/* Must be invoked under gp->lock. */
static
void
gem_stop
(
struct
gem
*
gp
)
{
int
limit
;
...
...
@@ -879,7 +995,8 @@ static void gem_stop(struct gem *gp)
writel
(
0xffffffff
,
gp
->
regs
+
GREG_IMASK
);
/* Reset the chip */
writel
(
GREG_SWRST_TXRST
|
GREG_SWRST_RXRST
,
gp
->
regs
+
GREG_SWRST
);
writel
(
gp
->
swrst_base
|
GREG_SWRST_TXRST
|
GREG_SWRST_RXRST
,
gp
->
regs
+
GREG_SWRST
);
limit
=
STOP_TRIES
;
...
...
@@ -894,6 +1011,7 @@ static void gem_stop(struct gem *gp)
printk
(
KERN_ERR
"gem: SW reset is ghetto.
\n
"
);
}
/* Must be invoked under gp->lock. */
static
void
gem_start_dma
(
struct
gem
*
gp
)
{
unsigned
long
val
;
...
...
@@ -929,6 +1047,7 @@ static int phy_BCM5400_link_table[8][3] = {
{
1
,
0
,
1
},
/* 1000BT */
};
/* Must be invoked under gp->lock. */
static
void
gem_begin_auto_negotiation
(
struct
gem
*
gp
,
struct
ethtool_cmd
*
ep
)
{
u16
ctl
;
...
...
@@ -954,11 +1073,8 @@ static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
}
start_aneg:
spin_lock_irq
(
&
gp
->
lock
);
if
(
!
gp
->
hw_running
)
{
spin_unlock_irq
(
&
gp
->
lock
);
if
(
!
gp
->
hw_running
)
return
;
}
/* Configure PHY & start aneg */
ctl
=
phy_read
(
gp
,
MII_BMCR
);
...
...
@@ -973,11 +1089,10 @@ static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
phy_write
(
gp
,
MII_BMCR
,
ctl
);
gp
->
timer_ticks
=
0
;
gp
->
link_timer
.
expires
=
jiffies
+
((
12
*
HZ
)
/
10
);
add_timer
(
&
gp
->
link_timer
);
spin_unlock_irq
(
&
gp
->
lock
);
mod_timer
(
&
gp
->
link_timer
,
jiffies
+
((
12
*
HZ
)
/
10
));
}
/* Must be invoked under gp->lock. */
static
void
gem_read_mii_link_mode
(
struct
gem
*
gp
,
int
*
fd
,
int
*
spd
,
int
*
pause
)
{
u32
val
;
...
...
@@ -1021,6 +1136,8 @@ static void gem_read_mii_link_mode(struct gem *gp, int *fd, int *spd, int *pause
/* A link-up condition has occurred, initialize and enable the
* rest of the chip.
*
* Must be invoked under gp->lock.
*/
static
void
gem_set_link_modes
(
struct
gem
*
gp
)
{
...
...
@@ -1101,6 +1218,20 @@ static void gem_set_link_modes(struct gem *gp)
pause
=
1
;
}
if
(
netif_msg_link
(
gp
))
{
if
(
pause
)
{
printk
(
KERN_INFO
"%s: Pause is enabled "
"(rxfifo: %d off: %d on: %d)
\n
"
,
gp
->
dev
->
name
,
gp
->
rx_fifo_sz
,
gp
->
rx_pause_off
,
gp
->
rx_pause_on
);
}
else
{
printk
(
KERN_INFO
"%s: Pause is disabled
\n
"
,
gp
->
dev
->
name
);
}
}
if
(
!
full_duplex
)
writel
(
512
,
gp
->
regs
+
MAC_STIME
);
else
...
...
@@ -1115,6 +1246,7 @@ static void gem_set_link_modes(struct gem *gp)
gem_start_dma
(
gp
);
}
/* Must be invoked under gp->lock. */
static
int
gem_mdio_link_not_up
(
struct
gem
*
gp
)
{
u16
val
;
...
...
@@ -1158,7 +1290,7 @@ static int gem_mdio_link_not_up(struct gem *gp)
return
0
;
}
static
void
gem_init_rings
(
struct
gem
*
,
int
);
static
void
gem_init_rings
(
struct
gem
*
);
static
void
gem_init_hw
(
struct
gem
*
,
int
);
static
void
gem_reset_task
(
void
*
data
)
...
...
@@ -1169,24 +1301,27 @@ static void gem_reset_task(void *data)
* DMA stopped. Todo: Use this function for reset
* on error as well.
*/
if
(
gp
->
hw_running
&&
gp
->
opened
)
{
/* Make sure we don't get interrupts or tx packets */
spin_lock_irq
(
&
gp
->
lock
);
if
(
gp
->
hw_running
&&
gp
->
opened
)
{
/* Make sure we don't get interrupts or tx packets */
netif_stop_queue
(
gp
->
dev
);
writel
(
0xffffffff
,
gp
->
regs
+
GREG_IMASK
);
spin_unlock_irq
(
&
gp
->
lock
);
/* Reset the chip & rings */
gem_stop
(
gp
);
gem_init_rings
(
gp
,
0
);
gem_init_hw
(
gp
,
0
);
gem_init_rings
(
gp
);
gem_init_hw
(
gp
,
(
gp
->
reset_task_pending
==
2
));
netif_wake_queue
(
gp
->
dev
);
}
gp
->
reset_task_pending
=
0
;
spin_unlock_irq
(
&
gp
->
lock
);
}
static
void
gem_link_timer
(
unsigned
long
data
)
...
...
@@ -1196,13 +1331,14 @@ static void gem_link_timer(unsigned long data)
if
(
!
gp
->
hw_running
)
return
;
spin_lock_irq
(
&
gp
->
lock
);
/* If the link of task is still pending, we just
* reschedule the link timer
*/
if
(
gp
->
reset_task_pending
)
goto
restart
;
spin_lock_irq
(
&
gp
->
lock
);
if
(
gp
->
phy_type
==
phy_mii_mdio0
||
gp
->
phy_type
==
phy_mii_mdio1
)
{
u16
val
=
phy_read
(
gp
,
MII_BMSR
);
...
...
@@ -1247,16 +1383,15 @@ static void gem_link_timer(unsigned long data)
if
(
netif_msg_link
(
gp
))
printk
(
KERN_INFO
"%s: Link down
\n
"
,
gp
->
dev
->
name
);
gp
->
reset_task_pending
=
1
;
gp
->
reset_task_pending
=
2
;
schedule_task
(
&
gp
->
reset_task
);
restart
=
1
;
}
else
if
(
++
gp
->
timer_ticks
>
10
)
restart
=
gem_mdio_link_not_up
(
gp
);
if
(
restart
)
{
spin_unlock_irq
(
&
gp
->
lock
);
gem_begin_auto_negotiation
(
gp
,
NULL
);
return
;
goto
out_unlock
;
}
}
}
else
{
...
...
@@ -1273,11 +1408,12 @@ static void gem_link_timer(unsigned long data)
}
restart:
gp
->
link_timer
.
expires
=
jiffies
+
((
12
*
HZ
)
/
10
);
add_timer
(
&
gp
->
link_timer
);
mod_timer
(
&
gp
->
link_timer
,
jiffies
+
((
12
*
HZ
)
/
10
)
);
out_unlock:
spin_unlock_irq
(
&
gp
->
lock
);
}
/* Must be invoked under gp->lock. */
static
void
gem_clean_rings
(
struct
gem
*
gp
)
{
struct
gem_init_block
*
gb
=
gp
->
init_block
;
...
...
@@ -1311,7 +1447,9 @@ static void gem_clean_rings(struct gem *gp)
gp
->
tx_skbs
[
i
]
=
NULL
;
for
(
frag
=
0
;
frag
<=
skb_shinfo
(
skb
)
->
nr_frags
;
frag
++
)
{
txd
=
&
gb
->
txd
[
i
];
int
ent
=
i
&
(
TX_RING_SIZE
-
1
);
txd
=
&
gb
->
txd
[
ent
];
dma_addr
=
le64_to_cpu
(
txd
->
buffer
);
pci_unmap_page
(
gp
->
pdev
,
dma_addr
,
le64_to_cpu
(
txd
->
control_word
)
&
...
...
@@ -1325,16 +1463,14 @@ static void gem_clean_rings(struct gem *gp)
}
}
static
void
gem_init_rings
(
struct
gem
*
gp
,
int
from_irq
)
/* Must be invoked under gp->lock. */
static
void
gem_init_rings
(
struct
gem
*
gp
)
{
struct
gem_init_block
*
gb
=
gp
->
init_block
;
struct
net_device
*
dev
=
gp
->
dev
;
int
i
,
gfp_flags
=
GFP_KERNEL
;
int
i
;
dma_addr_t
dma_addr
;
if
(
from_irq
)
gfp_flags
=
GFP_ATOMIC
;
gp
->
rx_new
=
gp
->
rx_old
=
gp
->
tx_new
=
gp
->
tx_old
=
0
;
gem_clean_rings
(
gp
);
...
...
@@ -1343,7 +1479,7 @@ static void gem_init_rings(struct gem *gp, int from_irq)
struct
sk_buff
*
skb
;
struct
gem_rxd
*
rxd
=
&
gb
->
rxd
[
i
];
skb
=
gem_alloc_skb
(
RX_BUF_ALLOC_SIZE
(
gp
),
gfp_flags
);
skb
=
gem_alloc_skb
(
RX_BUF_ALLOC_SIZE
(
gp
),
GFP_ATOMIC
);
if
(
!
skb
)
{
rxd
->
buffer
=
0
;
rxd
->
status_word
=
0
;
...
...
@@ -1372,6 +1508,7 @@ static void gem_init_rings(struct gem *gp, int from_irq)
}
}
/* Must be invoked under gp->lock. */
static
int
gem_reset_one_mii_phy
(
struct
gem
*
gp
,
int
phy_addr
)
{
u16
val
;
...
...
@@ -1396,6 +1533,7 @@ static int gem_reset_one_mii_phy(struct gem *gp, int phy_addr)
return
(
limit
<=
0
);
}
/* Must be invoked under gp->lock. */
static
void
gem_init_bcm5201_phy
(
struct
gem
*
gp
)
{
u16
data
;
...
...
@@ -1405,6 +1543,7 @@ static void gem_init_bcm5201_phy(struct gem *gp)
phy_write
(
gp
,
MII_BCM5201_MULTIPHY
,
data
);
}
/* Must be invoked under gp->lock. */
static
void
gem_init_bcm5400_phy
(
struct
gem
*
gp
)
{
u16
data
;
...
...
@@ -1432,6 +1571,7 @@ static void gem_init_bcm5400_phy(struct gem *gp)
phy_write
(
gp
,
MII_BCM5400_AUXCONTROL
,
data
);
}
/* Must be invoked under gp->lock. */
static
void
gem_init_bcm5401_phy
(
struct
gem
*
gp
)
{
u16
data
;
...
...
@@ -1446,6 +1586,9 @@ static void gem_init_bcm5401_phy(struct gem *gp)
* WARNING ! OF and Darwin don't agree on the
* register addresses. OF seem to interpret the
* register numbers below as decimal
*
* Note: This should (and does) match tg3_init_5401phy_dsp
* in the tg3.c driver. -DaveM
*/
phy_write
(
gp
,
0x18
,
0x0c20
);
phy_write
(
gp
,
0x17
,
0x0012
);
...
...
@@ -1475,6 +1618,7 @@ static void gem_init_bcm5401_phy(struct gem *gp)
__phy_write
(
gp
,
MII_BCM5201_MULTIPHY
,
data
,
0x1f
);
}
/* Must be invoked under gp->lock. */
static
void
gem_init_bcm5411_phy
(
struct
gem
*
gp
)
{
u16
data
;
...
...
@@ -1501,6 +1645,7 @@ static void gem_init_bcm5411_phy(struct gem *gp)
phy_write
(
gp
,
MII_BCM5400_GB_CONTROL
,
data
);
}
/* Must be invoked under gp->lock. */
static
void
gem_init_phy
(
struct
gem
*
gp
)
{
u32
mifcfg
;
...
...
@@ -1649,7 +1794,9 @@ static void gem_init_phy(struct gem *gp)
val
&=
~
(
PCS_CFG_ENABLE
|
PCS_CFG_TO
);
writel
(
val
,
gp
->
regs
+
PCS_CFG
);
/* Advertise all capabilities. */
/* Advertise all capabilities except assymetric
* pause.
*/
val
=
readl
(
gp
->
regs
+
PCS_MIIADV
);
val
|=
(
PCS_MIIADV_FD
|
PCS_MIIADV_HD
|
PCS_MIIADV_SP
|
PCS_MIIADV_AP
);
...
...
@@ -1684,9 +1831,9 @@ static void gem_init_phy(struct gem *gp)
if
(
gp
->
phy_mod
!=
phymod_bcm5400
&&
gp
->
phy_mod
!=
phymod_bcm5401
&&
gp
->
phy_mod
!=
phymod_bcm5411
)
gp
->
link_cntl
&=
~
BMCR_SPD2
;
}
/* Must be invoked under gp->lock. */
static
void
gem_init_dma
(
struct
gem
*
gp
)
{
u64
desc_dma
=
(
u64
)
gp
->
gblock_dvma
;
...
...
@@ -1702,7 +1849,7 @@ static void gem_init_dma(struct gem *gp)
writel
(
0
,
gp
->
regs
+
TXDMA_KICK
);
val
=
(
RXDMA_CFG_BASE
|
(
RX_OFFSET
<<
10
)
|
((
14
/
2
)
<<
13
)
|
RXDMA_CFG_FTHRESH_
512
);
((
14
/
2
)
<<
13
)
|
RXDMA_CFG_FTHRESH_
128
);
writel
(
val
,
gp
->
regs
+
RXDMA_CFG
);
writel
(
desc_dma
>>
32
,
gp
->
regs
+
RXDMA_DBHI
);
...
...
@@ -1724,6 +1871,7 @@ static void gem_init_dma(struct gem *gp)
gp
->
regs
+
RXDMA_BLANK
);
}
/* Must be invoked under gp->lock. */
static
u32
gem_setup_multicast
(
struct
gem
*
gp
)
{
...
...
@@ -1766,10 +1914,10 @@ gem_setup_multicast(struct gem *gp)
return
rxcfg
;
}
/* Must be invoked under gp->lock. */
static
void
gem_init_mac
(
struct
gem
*
gp
)
{
unsigned
char
*
e
=
&
gp
->
dev
->
dev_addr
[
0
];
u32
rxcfg
;
if
(
gp
->
pdev
->
vendor
==
PCI_VENDOR_ID_SUN
&&
gp
->
pdev
->
device
==
PCI_DEVICE_ID_SUN_GEM
)
...
...
@@ -1780,7 +1928,10 @@ static void gem_init_mac(struct gem *gp)
writel
(
0x04
,
gp
->
regs
+
MAC_IPG2
);
writel
(
0x40
,
gp
->
regs
+
MAC_STIME
);
writel
(
0x40
,
gp
->
regs
+
MAC_MINFSZ
);
writel
(
0x20000000
|
(
gp
->
dev
->
mtu
+
18
),
gp
->
regs
+
MAC_MAXFSZ
);
/* Ethernet payload + header + FCS + optional VLAN tag. */
writel
(
0x20000000
|
(
gp
->
dev
->
mtu
+
ETH_HLEN
+
4
+
4
),
gp
->
regs
+
MAC_MAXFSZ
);
writel
(
0x07
,
gp
->
regs
+
MAC_PASIZE
);
writel
(
0x04
,
gp
->
regs
+
MAC_JAMSIZE
);
writel
(
0x10
,
gp
->
regs
+
MAC_ATTLIM
);
...
...
@@ -1806,7 +1957,7 @@ static void gem_init_mac(struct gem *gp)
writel
(
0
,
gp
->
regs
+
MAC_AF21MSK
);
writel
(
0
,
gp
->
regs
+
MAC_AF0MSK
);
rx
cfg
=
gem_setup_multicast
(
gp
);
gp
->
mac_rx_
cfg
=
gem_setup_multicast
(
gp
);
writel
(
0
,
gp
->
regs
+
MAC_NCOLL
);
writel
(
0
,
gp
->
regs
+
MAC_FASUCC
);
...
...
@@ -1824,7 +1975,7 @@ static void gem_init_mac(struct gem *gp)
* them once a link is established.
*/
writel
(
0
,
gp
->
regs
+
MAC_TXCFG
);
writel
(
rx
cfg
,
gp
->
regs
+
MAC_RXCFG
);
writel
(
gp
->
mac_rx_
cfg
,
gp
->
regs
+
MAC_RXCFG
);
writel
(
0
,
gp
->
regs
+
MAC_MCCFG
);
writel
(
0
,
gp
->
regs
+
MAC_XIFCFG
);
...
...
@@ -1841,6 +1992,7 @@ static void gem_init_mac(struct gem *gp)
writel
(
0xffffffff
,
gp
->
regs
+
MAC_MCMASK
);
}
/* Must be invoked under gp->lock. */
static
void
gem_init_pause_thresholds
(
struct
gem
*
gp
)
{
/* Calculate pause thresholds. Setting the OFF threshold to the
...
...
@@ -1851,8 +2003,9 @@ static void gem_init_pause_thresholds(struct gem *gp)
if
(
gp
->
rx_fifo_sz
<=
(
2
*
1024
))
{
gp
->
rx_pause_off
=
gp
->
rx_pause_on
=
gp
->
rx_fifo_sz
;
}
else
{
int
off
=
(
gp
->
rx_fifo_sz
-
(
5
*
1024
));
int
on
=
off
-
1024
;
int
max_frame
=
(
gp
->
dev
->
mtu
+
ETH_HLEN
+
4
+
4
+
64
)
&
~
63
;
int
off
=
(
gp
->
rx_fifo_sz
-
(
max_frame
*
2
));
int
on
=
off
-
max_frame
;
gp
->
rx_pause_off
=
off
;
gp
->
rx_pause_on
=
on
;
...
...
@@ -1861,7 +2014,10 @@ static void gem_init_pause_thresholds(struct gem *gp)
{
u32
cfg
;
cfg
=
GREG_CFG_IBURST
;
cfg
=
0
;
#if !defined(CONFIG_SPARC64) && !defined(CONFIG_ALPHA)
cfg
|=
GREG_CFG_IBURST
;
#endif
cfg
|=
((
31
<<
1
)
&
GREG_CFG_TXDMALIM
);
cfg
|=
((
31
<<
6
)
&
GREG_CFG_RXDMALIM
);
writel
(
cfg
,
gp
->
regs
+
GREG_CFG
);
...
...
@@ -1881,6 +2037,7 @@ static int gem_check_invariants(struct gem *gp)
gp
->
phy_type
=
phy_mii_mdio0
;
gp
->
tx_fifo_sz
=
readl
(
gp
->
regs
+
TXDMA_FSZ
)
*
64
;
gp
->
rx_fifo_sz
=
readl
(
gp
->
regs
+
RXDMA_FSZ
)
*
64
;
gp
->
swrst_base
=
0
;
return
0
;
}
...
...
@@ -1943,6 +2100,7 @@ static int gem_check_invariants(struct gem *gp)
gp
->
tx_fifo_sz
,
gp
->
rx_fifo_sz
);
return
-
1
;
}
gp
->
swrst_base
=
0
;
}
else
{
if
(
gp
->
tx_fifo_sz
!=
(
2
*
1024
)
||
gp
->
rx_fifo_sz
!=
(
2
*
1024
))
{
...
...
@@ -1950,12 +2108,14 @@ static int gem_check_invariants(struct gem *gp)
gp
->
tx_fifo_sz
,
gp
->
rx_fifo_sz
);
return
-
1
;
}
gp
->
swrst_base
=
(
64
/
4
)
<<
GREG_SWRST_CACHE_SHIFT
;
}
}
return
0
;
}
/* Must be invoked under gp->lock. */
static
void
gem_init_hw
(
struct
gem
*
gp
,
int
restart_link
)
{
/* On Apple's gmac, I initialize the PHY only after
...
...
@@ -1970,21 +2130,16 @@ static void gem_init_hw(struct gem *gp, int restart_link)
gem_init_mac
(
gp
);
gem_init_pause_thresholds
(
gp
);
spin_lock_irq
(
&
gp
->
lock
);
if
(
restart_link
)
{
/* Default aneg parameters */
gp
->
timer_ticks
=
0
;
gp
->
lstate
=
link_down
;
spin_unlock_irq
(
&
gp
->
lock
);
/* Can I advertise gigabit here ? I'd need BCM PHY docs... */
gem_begin_auto_negotiation
(
gp
,
NULL
);
}
else
{
if
(
gp
->
lstate
==
link_up
)
gem_set_link_modes
(
gp
);
spin_unlock_irq
(
&
gp
->
lock
);
}
}
...
...
@@ -2029,6 +2184,7 @@ static void gem_apple_powerdown(struct gem *gp)
#endif
/* CONFIG_ALL_PPC */
/* Must be invoked under gp->lock. */
static
void
gem_stop_phy
(
struct
gem
*
gp
)
{
u32
mifcfg
;
...
...
@@ -2100,14 +2256,21 @@ static void gem_shutdown(struct gem *gp)
schedule
();
/* Actually stop the chip */
spin_lock_irq
(
&
gp
->
lock
);
if
(
gp
->
pdev
->
vendor
==
PCI_VENDOR_ID_APPLE
)
{
gem_stop_phy
(
gp
);
spin_unlock_irq
(
&
gp
->
lock
);
#ifdef CONFIG_ALL_PPC
/* Power down the chip */
gem_apple_powerdown
(
gp
);
#endif
/* CONFIG_ALL_PPC */
}
else
}
else
{
gem_stop
(
gp
);
spin_unlock_irq
(
&
gp
->
lock
);
}
}
static
void
gem_pm_task
(
void
*
data
)
...
...
@@ -2142,14 +2305,19 @@ static void gem_pm_timer(unsigned long data)
static
int
gem_open
(
struct
net_device
*
dev
)
{
struct
gem
*
gp
=
dev
->
priv
;
int
hw_was_up
=
gp
->
hw_running
;
int
hw_was_up
;
down
(
&
gp
->
pm_sem
);
hw_was_up
=
gp
->
hw_running
;
/* Stop the PM timer/task */
del_timer
(
&
gp
->
pm_timer
);
flush_scheduled_tasks
();
/* The power-management semaphore protects the hw_running
* etc. state so it is safe to do this bit without gp->lock
*/
if
(
!
gp
->
hw_running
)
{
#ifdef CONFIG_ALL_PPC
/* First, we need to bring up the chip */
...
...
@@ -2158,18 +2326,26 @@ static int gem_open(struct net_device *dev)
gem_check_invariants
(
gp
);
}
#endif
/* CONFIG_ALL_PPC */
/* Reset the chip */
spin_lock_irq
(
&
gp
->
lock
);
gem_stop
(
gp
);
spin_unlock_irq
(
&
gp
->
lock
);
gp
->
hw_running
=
1
;
}
spin_lock_irq
(
&
gp
->
lock
);
/* We can now request the interrupt as we know it's masked
* on the controller
*/
if
(
request_irq
(
gp
->
pdev
->
irq
,
gem_interrupt
,
SA_SHIRQ
,
dev
->
name
,
(
void
*
)
dev
))
{
spin_unlock_irq
(
&
gp
->
lock
);
printk
(
KERN_ERR
"%s: failed to request irq !
\n
"
,
gp
->
dev
->
name
);
#ifdef CONFIG_ALL_PPC
if
(
!
hw_was_up
&&
gp
->
pdev
->
vendor
==
PCI_VENDOR_ID_APPLE
)
gem_apple_powerdown
(
gp
);
...
...
@@ -2183,13 +2359,15 @@ static int gem_open(struct net_device *dev)
}
/* Allocate & setup ring buffers */
gem_init_rings
(
gp
,
0
);
gem_init_rings
(
gp
);
/* Init & setup chip hardware */
gem_init_hw
(
gp
,
!
hw_was_up
);
gp
->
opened
=
1
;
spin_unlock_irq
(
&
gp
->
lock
);
up
(
&
gp
->
pm_sem
);
return
0
;
...
...
@@ -2209,8 +2387,6 @@ static int gem_close(struct net_device *dev)
writel
(
0xffffffff
,
gp
->
regs
+
GREG_IMASK
);
netif_stop_queue
(
dev
);
spin_unlock_irq
(
&
gp
->
lock
);
/* Stop chip */
gem_stop
(
gp
);
...
...
@@ -2220,6 +2396,8 @@ static int gem_close(struct net_device *dev)
/* Bye, the pm timer will finish the job */
free_irq
(
gp
->
pdev
->
irq
,
(
void
*
)
dev
);
spin_unlock_irq
(
&
gp
->
lock
);
/* Fire the PM timer that will shut us down in about 10 seconds */
gp
->
pm_timer
.
expires
=
jiffies
+
10
*
HZ
;
add_timer
(
&
gp
->
pm_timer
);
...
...
@@ -2245,21 +2423,21 @@ static int gem_suspend(struct pci_dev *pdev, u32 state)
/* If the driver is opened, we stop the DMA */
if
(
gp
->
opened
)
{
spin_lock_irq
(
&
gp
->
lock
);
/* Stop traffic, mark us closed */
netif_device_detach
(
dev
);
spin_lock_irq
(
&
gp
->
lock
);
writel
(
0xffffffff
,
gp
->
regs
+
GREG_IMASK
);
spin_unlock_irq
(
&
gp
->
lock
);
/* Stop chip */
gem_stop
(
gp
);
/* Get rid of ring buffers */
gem_clean_rings
(
gp
);
spin_unlock_irq
(
&
gp
->
lock
);
if
(
gp
->
pdev
->
vendor
==
PCI_VENDOR_ID_APPLE
)
disable_irq
(
gp
->
pdev
->
irq
);
}
...
...
@@ -2290,10 +2468,15 @@ static int gem_resume(struct pci_dev *pdev)
gem_check_invariants
(
gp
);
}
#endif
/* CONFIG_ALL_PPC */
spin_lock_irq
(
&
gp
->
lock
);
gem_stop
(
gp
);
gp
->
hw_running
=
1
;
gem_init_rings
(
gp
,
0
);
gem_init_rings
(
gp
);
gem_init_hw
(
gp
,
1
);
spin_unlock_irq
(
&
gp
->
lock
);
netif_device_attach
(
dev
);
if
(
gp
->
pdev
->
vendor
==
PCI_VENDOR_ID_APPLE
)
enable_irq
(
gp
->
pdev
->
irq
);
...
...
@@ -2309,6 +2492,8 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
struct
gem
*
gp
=
dev
->
priv
;
struct
net_device_stats
*
stats
=
&
gp
->
net_stats
;
spin_lock_irq
(
&
gp
->
lock
);
if
(
gp
->
hw_running
)
{
stats
->
rx_crc_errors
+=
readl
(
gp
->
regs
+
MAC_FCSERR
);
writel
(
0
,
gp
->
regs
+
MAC_FCSERR
);
...
...
@@ -2326,6 +2511,9 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
writel
(
0
,
gp
->
regs
+
MAC_ECOLL
);
writel
(
0
,
gp
->
regs
+
MAC_LCOLL
);
}
spin_unlock_irq
(
&
gp
->
lock
);
return
&
gp
->
net_stats
;
}
...
...
@@ -2338,10 +2526,12 @@ static void gem_set_multicast(struct net_device *dev)
if
(
!
gp
->
hw_running
)
return
;
spin_lock_irq
(
&
gp
->
lock
);
netif_stop_queue
(
dev
);
rxcfg
=
readl
(
gp
->
regs
+
MAC_RXCFG
);
rxcfg_new
=
gem_setup_multicast
(
gp
);
gp
->
mac_rx_cfg
=
rxcfg_new
=
gem_setup_multicast
(
gp
);
writel
(
rxcfg
&
~
MAC_RXCFG_ENAB
,
gp
->
regs
+
MAC_RXCFG
);
while
(
readl
(
gp
->
regs
+
MAC_RXCFG
)
&
MAC_RXCFG_ENAB
)
{
...
...
@@ -2355,8 +2545,9 @@ static void gem_set_multicast(struct net_device *dev)
writel
(
rxcfg
,
gp
->
regs
+
MAC_RXCFG
);
/* Hrm... we may walk on the reset task here... */
netif_wake_queue
(
dev
);
spin_unlock_irq
(
&
gp
->
lock
);
}
/* Eventually add support for changing the advertisement
...
...
@@ -2405,11 +2596,13 @@ static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user)
ecmd
.
phy_address
=
0
;
/* XXX fixed PHYAD */
/* Record PHY settings if HW is on. */
spin_lock_irq
(
&
gp
->
lock
);
if
(
gp
->
hw_running
)
{
bmcr
=
phy_read
(
gp
,
MII_BMCR
);
gem_read_mii_link_mode
(
gp
,
&
full_duplex
,
&
speed
,
&
pause
);
}
else
bmcr
=
0
;
spin_unlock_irq
(
&
gp
->
lock
);
if
(
bmcr
&
BMCR_ANENABLE
)
{
ecmd
.
autoneg
=
AUTONEG_ENABLE
;
ecmd
.
speed
=
speed
==
10
?
SPEED_10
:
(
speed
==
1000
?
SPEED_1000
:
SPEED_100
);
...
...
@@ -2443,18 +2636,22 @@ static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user)
ecmd
.
duplex
!=
DUPLEX_FULL
)))
return
-
EINVAL
;
/* Apply settings and restart link process */
if
(
gp
->
hw_running
)
del_timer
(
&
gp
->
link_timer
);
/* Apply settings and restart link process. */
spin_lock_irq
(
&
gp
->
lock
);
gem_begin_auto_negotiation
(
gp
,
&
ecmd
);
spin_unlock_irq
(
&
gp
->
lock
);
return
0
;
case
ETHTOOL_NWAY_RST
:
if
((
gp
->
link_cntl
&
BMCR_ANENABLE
)
==
0
)
return
-
EINVAL
;
if
(
gp
->
hw_running
)
del_timer
(
&
gp
->
link_timer
);
/* Restart link process. */
spin_lock_irq
(
&
gp
->
lock
);
gem_begin_auto_negotiation
(
gp
,
NULL
);
spin_unlock_irq
(
&
gp
->
lock
);
return
0
;
case
ETHTOOL_GWOL
:
...
...
@@ -2602,8 +2799,10 @@ static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
u32
rom_reg_orig
;
void
*
p
;
if
(
pdev
->
resource
[
PCI_ROM_RESOURCE
].
parent
==
NULL
)
pci_assign_resource
(
pdev
,
PCI_ROM_RESOURCE
);
if
(
pdev
->
resource
[
PCI_ROM_RESOURCE
].
parent
==
NULL
)
{
if
(
pci_assign_resource
(
pdev
,
PCI_ROM_RESOURCE
)
<
0
)
goto
use_random
;
}
pci_read_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
&
rom_reg_orig
);
pci_write_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
...
...
@@ -2617,6 +2816,15 @@ static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
iounmap
(
p
);
pci_write_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
rom_reg_orig
);
return
;
use_random:
/* Sun MAC prefix then 3 random bytes. */
dev_addr
[
0
]
=
0x08
;
dev_addr
[
1
]
=
0x00
;
dev_addr
[
2
]
=
0x20
;
get_random_bytes
(
dev_addr
,
3
);
return
;
}
#endif
/* not Sparc and not PPC */
...
...
@@ -2773,12 +2981,18 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
if
(
pdev
->
vendor
==
PCI_VENDOR_ID_APPLE
)
gem_apple_powerup
(
gp
);
#endif
spin_lock_irq
(
&
gp
->
lock
);
gem_stop
(
gp
);
spin_unlock_irq
(
&
gp
->
lock
);
if
(
gem_check_invariants
(
gp
))
goto
err_out_iounmap
;
spin_lock_irq
(
&
gp
->
lock
);
gp
->
hw_running
=
1
;
gem_init_phy
(
gp
);
gem_begin_auto_negotiation
(
gp
,
NULL
);
spin_unlock_irq
(
&
gp
->
lock
);
/* It is guarenteed that the returned buffer will be at least
* PAGE_SIZE aligned.
...
...
drivers/net/sungem.h
View file @
a19d03a3
...
...
@@ -94,6 +94,8 @@
#define GREG_SWRST_TXRST 0x00000001
/* TX Software Reset */
#define GREG_SWRST_RXRST 0x00000002
/* RX Software Reset */
#define GREG_SWRST_RSTOUT 0x00000004
/* Force RST# pin active */
#define GREG_SWRST_CACHESIZE 0x00ff0000
/* RIO only: cache line size */
#define GREG_SWRST_CACHE_SHIFT 16
/* TX DMA Registers */
#define TXDMA_KICK 0x2000UL
/* TX Kick Register */
...
...
@@ -986,6 +988,9 @@ struct gem {
int
mii_phy_addr
;
int
gigabit_capable
;
u32
mac_rx_cfg
;
u32
swrst_base
;
/* Autoneg & PHY control */
int
link_cntl
;
int
link_advertise
;
...
...
drivers/net/sunhme.c
View file @
a19d03a3
...
...
@@ -34,6 +34,7 @@ static char version[] =
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/crc32.h>
#include <linux/random.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
...
...
@@ -2929,8 +2930,10 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
if
(
is_quattro_p
(
pdev
))
index
=
PCI_SLOT
(
pdev
->
devfn
);
if
(
pdev
->
resource
[
PCI_ROM_RESOURCE
].
parent
==
NULL
)
pci_assign_resource
(
pdev
,
PCI_ROM_RESOURCE
);
if
(
pdev
->
resource
[
PCI_ROM_RESOURCE
].
parent
==
NULL
)
{
if
(
pci_assign_resource
(
pdev
,
PCI_ROM_RESOURCE
)
<
0
)
goto
use_random
;
}
pci_read_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
&
rom_reg_orig
);
pci_write_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
...
...
@@ -2944,6 +2947,15 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
iounmap
(
p
);
pci_write_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
rom_reg_orig
);
return
;
use_random:
/* Sun MAC prefix then 3 random bytes. */
dev_addr
[
0
]
=
0x08
;
dev_addr
[
1
]
=
0x00
;
dev_addr
[
2
]
=
0x20
;
get_random_bytes
(
dev_addr
,
3
);
return
;
}
#endif
/* !(__sparc__) */
...
...
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