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
92d3a215
Commit
92d3a215
authored
Feb 04, 2004
by
Carl-Daniel Hailfinger
Committed by
Jeff Garzik
Feb 04, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] [2.6] Update forcedeth to 0.23
This is a multi-part message in MIME format.
parent
f5e52e1b
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
127 additions
and
52 deletions
+127
-52
drivers/net/forcedeth.c
drivers/net/forcedeth.c
+127
-52
No files found.
drivers/net/forcedeth.c
View file @
92d3a215
...
...
@@ -60,15 +60,24 @@
* addresses, really stop rx if already running
* in start_rx, clean up a bit.
* (C) Carl-Daniel Hailfinger
* 0.20: 07 Dev 2003: alloc fixes
* 0.20: 07 Dec 2003: alloc fixes
* 0.21: 12 Jan 2004: additional alloc fix, nic polling fix.
* 0.22: 19 Jan 2004: reprogram timer to a sane rate, avoid lockup
* on close.
* (C) Carl-Daniel Hailfinger, Manfred Spraul
* 0.23: 26 Jan 2004: various small cleanups
*
* Known bugs:
* The irq handling is wrong - no tx done interrupts are generated.
* This means recovery from netif_stop_queue only happens in the hw timer
* interrupt (1/2 second on nForce2, 1/100 second on nForce3), or if an
* rx packet arrives by chance.
* We suspect that on some hardware no TX done interrupts are generated.
* This means recovery from netif_stop_queue only happens if the hw timer
* interrupt fires (100 times/second, configurable with NVREG_POLL_DEFAULT)
* and the timer is active in the IRQMask, or if a rx packet arrives by chance.
* If your hardware reliably generates tx done interrupts, then you can remove
* DEV_NEED_TIMERIRQ from the driver_data flags.
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
#define FORCEDETH_VERSION "0.
19
"
#define FORCEDETH_VERSION "0.
23
"
#include <linux/module.h>
#include <linux/types.h>
...
...
@@ -104,6 +113,7 @@
#define DEV_NEED_LASTPACKET1 0x0001
#define DEV_IRQMASK_1 0x0002
#define DEV_IRQMASK_2 0x0004
#define DEV_NEED_TIMERIRQ 0x0008
enum
{
NvRegIrqStatus
=
0x000
,
...
...
@@ -124,7 +134,12 @@ enum {
NvRegUnknownSetupReg6
=
0x008
,
#define NVREG_UNKSETUP6_VAL 3
/*
* NVREG_POLL_DEFAULT is the interval length of the timer source on the nic
* NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms
*/
NvRegPollingInterval
=
0x00c
,
#define NVREG_POLL_DEFAULT 970
NvRegMisc1
=
0x080
,
#define NVREG_MISC1_HD 0x02
#define NVREG_MISC1_FORCE 0x3b0f3c
...
...
@@ -286,7 +301,7 @@ struct ring_desc {
#define NV_WAKEUPMASKENTRIES 4
/* General driver defaults */
#define NV_WATCHDOG_TIMEO (
2
*HZ)
#define NV_WATCHDOG_TIMEO (
5
*HZ)
#define DEFAULT_MTU 1500
/* also maximum supported, at least for now */
#define RX_RING 128
...
...
@@ -520,12 +535,12 @@ static void txrx_reset(struct net_device *dev)
}
/*
* get_stats: dev->get_stats function
*
nv_
get_stats: dev->get_stats function
* Get latest stats value from the nic.
* Called with read_lock(&dev_base_lock) held for read -
* only synchronized against unregister_netdevice.
*/
static
struct
net_device_stats
*
get_stats
(
struct
net_device
*
dev
)
static
struct
net_device_stats
*
nv_
get_stats
(
struct
net_device
*
dev
)
{
struct
fe_priv
*
np
=
get_nvpriv
(
dev
);
...
...
@@ -536,14 +551,55 @@ static struct net_device_stats *get_stats(struct net_device *dev)
return
&
np
->
stats
;
}
static
int
nv_ethtool_ioctl
(
struct
net_device
*
dev
,
void
*
useraddr
)
{
struct
fe_priv
*
np
=
get_nvpriv
(
dev
);
u32
ethcmd
;
if
(
copy_from_user
(
&
ethcmd
,
useraddr
,
sizeof
(
ethcmd
)))
return
-
EFAULT
;
switch
(
ethcmd
)
{
case
ETHTOOL_GDRVINFO
:
{
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
strcpy
(
info
.
driver
,
"forcedeth"
);
strcpy
(
info
.
version
,
FORCEDETH_VERSION
);
strcpy
(
info
.
bus_info
,
pci_name
(
np
->
pci_dev
));
if
(
copy_to_user
(
useraddr
,
&
info
,
sizeof
(
info
)))
return
-
EFAULT
;
return
0
;
}
case
ETHTOOL_GLINK
:
{
struct
ethtool_value
edata
=
{
ETHTOOL_GLINK
};
edata
.
data
=
!!
netif_carrier_ok
(
dev
);
if
(
copy_to_user
(
useraddr
,
&
edata
,
sizeof
(
edata
)))
return
-
EFAULT
;
return
0
;
}
default:
break
;
}
return
-
EOPNOTSUPP
;
}
/*
* n
ic
_ioctl: dev->do_ioctl function
* n
v
_ioctl: dev->do_ioctl function
* Called with rtnl_lock held.
*/
static
int
n
ic
_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
static
int
n
v
_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
{
return
-
EOPNOTSUPP
;
switch
(
cmd
)
{
case
SIOCETHTOOL
:
return
nv_ethtool_ioctl
(
dev
,
(
void
*
)
rq
->
ifr_data
);
default:
return
-
EOPNOTSUPP
;
}
}
/*
...
...
@@ -661,10 +717,10 @@ static void drain_ring(struct net_device *dev)
}
/*
* start_xmit: dev->hard_start_xmit function
*
nv_
start_xmit: dev->hard_start_xmit function
* Called with dev->xmit_lock held.
*/
static
int
start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
static
int
nv_
start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
fe_priv
*
np
=
get_nvpriv
(
dev
);
int
nr
=
np
->
next_tx
%
TX_RING
;
...
...
@@ -679,7 +735,7 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irq
(
&
np
->
lock
);
wmb
();
np
->
tx_ring
[
nr
].
Flags
=
np
->
tx_flags
;
dprintk
(
KERN_DEBUG
"%s: start_xmit: packet packet %d queued for transmission.
\n
"
,
dprintk
(
KERN_DEBUG
"%s:
nv_
start_xmit: packet packet %d queued for transmission.
\n
"
,
dev
->
name
,
np
->
next_tx
);
{
int
j
;
...
...
@@ -698,6 +754,7 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue
(
dev
);
spin_unlock_irq
(
&
np
->
lock
);
writel
(
NVREG_TXRXCTL_KICK
,
get_hwbase
(
dev
)
+
NvRegTxRxControl
);
pci_push
(
get_hwbase
(
dev
));
return
0
;
}
...
...
@@ -743,10 +800,10 @@ static void tx_done(struct net_device *dev)
}
/*
* tx_timeout: dev->tx_timeout function
*
nv_
tx_timeout: dev->tx_timeout function
* Called with dev->xmit_lock held.
*/
static
void
tx_timeout
(
struct
net_device
*
dev
)
static
void
nv_
tx_timeout
(
struct
net_device
*
dev
)
{
struct
fe_priv
*
np
=
get_nvpriv
(
dev
);
u8
*
base
=
get_hwbase
(
dev
);
...
...
@@ -797,13 +854,13 @@ static void rx_process(struct net_device *dev)
break
;
/* still owned by hardware, */
/*
* the packet is for us - immediately tear down the pci mapping, and
* prefetch the first cacheline of the packet.
* the packet is for us - immediately tear down the pci mapping.
* TODO: check if a prefetch of the first cacheline improves
* the performance.
*/
pci_unmap_single
(
np
->
pci_dev
,
np
->
rx_dma
[
i
],
np
->
rx_skbuff
[
i
]
->
len
,
PCI_DMA_FROMDEVICE
);
prefetch
(
np
->
rx_skbuff
[
i
]
->
data
);
{
int
j
;
...
...
@@ -870,10 +927,10 @@ static void rx_process(struct net_device *dev)
}
/*
* change_mtu: dev->change_mtu function
*
nv_
change_mtu: dev->change_mtu function
* Called with dev_base_lock held for read.
*/
static
int
change_mtu
(
struct
net_device
*
dev
,
int
new_mtu
)
static
int
nv_
change_mtu
(
struct
net_device
*
dev
,
int
new_mtu
)
{
if
(
new_mtu
>
DEFAULT_MTU
)
return
-
EINVAL
;
...
...
@@ -882,10 +939,10 @@ static int change_mtu(struct net_device *dev, int new_mtu)
}
/*
*
change_mtu: dev->change_mtu
function
*
nv_set_multicast: dev->set_multicast
function
* Called with dev->xmit_lock held.
*/
static
void
set_multicast
(
struct
net_device
*
dev
)
static
void
nv_
set_multicast
(
struct
net_device
*
dev
)
{
struct
fe_priv
*
np
=
get_nvpriv
(
dev
);
u8
*
base
=
get_hwbase
(
dev
);
...
...
@@ -1098,13 +1155,13 @@ static void do_nic_poll(unsigned long data)
enable_irq
(
dev
->
irq
);
}
static
int
open
(
struct
net_device
*
dev
)
static
int
nv_
open
(
struct
net_device
*
dev
)
{
struct
fe_priv
*
np
=
get_nvpriv
(
dev
);
u8
*
base
=
get_hwbase
(
dev
);
int
ret
,
oom
,
i
;
dprintk
(
KERN_DEBUG
"
forcedeth: ope
n
\n
"
);
dprintk
(
KERN_DEBUG
"
nv_open: begi
n
\n
"
);
/* 1) erase previous misconfiguration */
/* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
...
...
@@ -1152,17 +1209,23 @@ static int open(struct net_device *dev)
for
(
i
=
1
;
i
<
32
;
i
++
)
{
int
id1
,
id2
;
spin_lock_irq
(
&
np
->
lock
);
id1
=
mii_rw
(
dev
,
i
,
MII_PHYSID1
,
MII_READ
);
if
(
id1
<
0
)
spin_unlock_irq
(
&
np
->
lock
);
if
(
id1
<
0
||
id1
==
0xffff
)
continue
;
spin_lock_irq
(
&
np
->
lock
);
id2
=
mii_rw
(
dev
,
i
,
MII_PHYSID2
,
MII_READ
);
if
(
id2
<
0
)
spin_unlock_irq
(
&
np
->
lock
);
if
(
id2
<
0
||
id2
==
0xffff
)
continue
;
dprintk
(
KERN_DEBUG
"%s: open: Found PHY %04x:%04x at address %d.
\n
"
,
dev
->
name
,
id1
,
id2
,
i
);
np
->
phyaddr
=
i
;
spin_lock_irq
(
&
np
->
lock
);
update_linkspeed
(
dev
);
spin_unlock_irq
(
&
np
->
lock
);
break
;
}
...
...
@@ -1185,6 +1248,7 @@ static int open(struct net_device *dev)
writel
(
NVREG_RNDSEED_FORCE
|
(
i
&
NVREG_RNDSEED_MASK
),
base
+
NvRegRandomSeed
);
writel
(
NVREG_UNKSETUP1_VAL
,
base
+
NvRegUnknownSetupReg1
);
writel
(
NVREG_UNKSETUP2_VAL
,
base
+
NvRegUnknownSetupReg2
);
writel
(
NVREG_POLL_DEFAULT
,
base
+
NvRegPollingInterval
);
writel
(
NVREG_UNKSETUP6_VAL
,
base
+
NvRegUnknownSetupReg6
);
writel
((
np
->
phyaddr
<<
NVREG_ADAPTCTL_PHYSHIFT
)
|
NVREG_ADAPTCTL_PHYVALID
,
base
+
NvRegAdapterControl
);
...
...
@@ -1198,9 +1262,9 @@ static int open(struct net_device *dev)
base
+
NvRegRingSizes
);
i
=
readl
(
base
+
NvRegPowerState
);
if
(
(
i
&
NVREG_POWERSTATE_POWEREDUP
)
==
0
)
{
if
(
(
i
&
NVREG_POWERSTATE_POWEREDUP
)
==
0
)
writel
(
NVREG_POWERSTATE_POWEREDUP
|
i
,
base
+
NvRegPowerState
);
}
pci_push
(
base
);
udelay
(
10
);
writel
(
readl
(
base
+
NvRegPowerState
)
|
NVREG_POWERSTATE_VALID
,
base
+
NvRegPowerState
);
...
...
@@ -1232,7 +1296,9 @@ static int open(struct net_device *dev)
netif_start_queue
(
dev
);
if
(
oom
)
mod_timer
(
&
np
->
oom_kick
,
jiffies
+
OOM_REFILL
);
if
(
!
(
mii_rw
(
dev
,
np
->
phyaddr
,
MII_BMSR
,
MII_READ
)
&
BMSR_ANEGCOMPLETE
))
{
if
(
mii_rw
(
dev
,
np
->
phyaddr
,
MII_BMSR
,
MII_READ
)
&
BMSR_ANEGCOMPLETE
)
{
netif_carrier_on
(
dev
);
}
else
{
printk
(
"%s: no link during initialization.
\n
"
,
dev
->
name
);
netif_carrier_off
(
dev
);
}
...
...
@@ -1245,9 +1311,10 @@ static int open(struct net_device *dev)
return
ret
;
}
static
int
close
(
struct
net_device
*
dev
)
static
int
nv_
close
(
struct
net_device
*
dev
)
{
struct
fe_priv
*
np
=
get_nvpriv
(
dev
);
u8
*
base
;
spin_lock_irq
(
&
np
->
lock
);
np
->
in_shutdown
=
1
;
...
...
@@ -1261,6 +1328,13 @@ static int close(struct net_device *dev)
spin_lock_irq
(
&
np
->
lock
);
stop_tx
(
dev
);
stop_rx
(
dev
);
base
=
get_hwbase
(
dev
);
/* disable interrupts on the nic or we will lock up */
writel
(
0
,
base
+
NvRegIrqMask
);
pci_push
(
base
);
dprintk
(
KERN_INFO
"%s: Irqmask is zero again
\n
"
,
dev
->
name
);
spin_unlock_irq
(
&
np
->
lock
);
free_irq
(
dev
->
irq
,
dev
);
...
...
@@ -1272,7 +1346,7 @@ static int close(struct net_device *dev)
return
0
;
}
static
int
__devinit
probe_nic
(
struct
pci_dev
*
pci_dev
,
const
struct
pci_device_id
*
id
)
static
int
__devinit
nv_probe
(
struct
pci_dev
*
pci_dev
,
const
struct
pci_device_id
*
id
)
{
struct
net_device
*
dev
;
struct
fe_priv
*
np
;
...
...
@@ -1281,11 +1355,11 @@ static int __devinit probe_nic(struct pci_dev *pci_dev, const struct pci_device_
int
err
,
i
;
dev
=
alloc_etherdev
(
sizeof
(
struct
fe_priv
));
np
=
get_nvpriv
(
dev
);
err
=
-
ENOMEM
;
if
(
!
dev
)
goto
out
;
np
=
get_nvpriv
(
dev
);
np
->
pci_dev
=
pci_dev
;
spin_lock_init
(
&
np
->
lock
);
SET_MODULE_OWNER
(
dev
);
...
...
@@ -1333,7 +1407,7 @@ static int __devinit probe_nic(struct pci_dev *pci_dev, const struct pci_device_
err
=
-
ENOMEM
;
dev
->
base_addr
=
(
unsigned
long
)
ioremap
(
addr
,
NV_PCI_REGSZ
);
if
(
!
dev
->
base_addr
)
goto
out_
disable
;
goto
out_
relreg
;
dev
->
irq
=
pci_dev
->
irq
;
np
->
rx_ring
=
pci_alloc_consistent
(
pci_dev
,
sizeof
(
struct
ring_desc
)
*
(
RX_RING
+
TX_RING
),
&
np
->
ring_addr
);
...
...
@@ -1341,19 +1415,18 @@ static int __devinit probe_nic(struct pci_dev *pci_dev, const struct pci_device_
goto
out_unmap
;
np
->
tx_ring
=
&
np
->
rx_ring
[
RX_RING
];
dev
->
open
=
open
;
dev
->
stop
=
close
;
dev
->
hard_start_xmit
=
start_xmit
;
dev
->
get_stats
=
get_stats
;
dev
->
change_mtu
=
change_mtu
;
dev
->
set_multicast_list
=
set_multicast
;
dev
->
do_ioctl
=
n
ic
_ioctl
;
dev
->
tx_timeout
=
tx_timeout
;
dev
->
open
=
nv_
open
;
dev
->
stop
=
nv_
close
;
dev
->
hard_start_xmit
=
nv_
start_xmit
;
dev
->
get_stats
=
nv_
get_stats
;
dev
->
change_mtu
=
nv_
change_mtu
;
dev
->
set_multicast_list
=
nv_
set_multicast
;
dev
->
do_ioctl
=
n
v
_ioctl
;
dev
->
tx_timeout
=
nv_
tx_timeout
;
dev
->
watchdog_timeo
=
NV_WATCHDOG_TIMEO
;
pci_set_drvdata
(
pci_dev
,
dev
);
/* read the mac address */
base
=
get_hwbase
(
dev
);
np
->
orig_mac
[
0
]
=
readl
(
base
+
NvRegMacAddrA
);
...
...
@@ -1393,6 +1466,8 @@ static int __devinit probe_nic(struct pci_dev *pci_dev, const struct pci_device_
np
->
irqmask
=
NVREG_IRQMASK_WANTED_1
;
if
(
id
->
driver_data
&
DEV_IRQMASK_2
)
np
->
irqmask
=
NVREG_IRQMASK_WANTED_2
;
if
(
id
->
driver_data
&
DEV_NEED_TIMERIRQ
)
np
->
irqmask
|=
NVREG_IRQ_TIMER
;
err
=
register_netdev
(
dev
);
if
(
err
)
{
...
...
@@ -1408,6 +1483,7 @@ static int __devinit probe_nic(struct pci_dev *pci_dev, const struct pci_device_
out_freering:
pci_free_consistent
(
np
->
pci_dev
,
sizeof
(
struct
ring_desc
)
*
(
RX_RING
+
TX_RING
),
np
->
rx_ring
,
np
->
ring_addr
);
pci_set_drvdata
(
pci_dev
,
NULL
);
out_unmap:
iounmap
(
get_hwbase
(
dev
));
out_relreg:
...
...
@@ -1416,12 +1492,11 @@ static int __devinit probe_nic(struct pci_dev *pci_dev, const struct pci_device_
pci_disable_device
(
pci_dev
);
out_free:
free_netdev
(
dev
);
pci_set_drvdata
(
pci_dev
,
NULL
);
out:
return
err
;
}
static
void
__devexit
remove_nic
(
struct
pci_dev
*
pci_dev
)
static
void
__devexit
nv_remove
(
struct
pci_dev
*
pci_dev
)
{
struct
net_device
*
dev
=
pci_get_drvdata
(
pci_dev
);
struct
fe_priv
*
np
=
get_nvpriv
(
dev
);
...
...
@@ -1430,7 +1505,7 @@ static void __devexit remove_nic(struct pci_dev *pci_dev)
unregister_netdev
(
dev
);
/* special op: write back the misordered MAC address - otherwise
* the next
probe_nic
would see a wrong address.
* the next
nv_probe
would see a wrong address.
*/
writel
(
np
->
orig_mac
[
0
],
base
+
NvRegMacAddrA
);
writel
(
np
->
orig_mac
[
1
],
base
+
NvRegMacAddrB
);
...
...
@@ -1450,21 +1525,21 @@ static struct pci_device_id pci_tbl[] = {
.
device
=
0x1C3
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
driver_data
=
DEV_IRQMASK_1
,
.
driver_data
=
DEV_IRQMASK_1
|
DEV_NEED_TIMERIRQ
,
},
{
/* nForce2 Ethernet Controller */
.
vendor
=
PCI_VENDOR_ID_NVIDIA
,
.
device
=
0x0066
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
driver_data
=
DEV_NEED_LASTPACKET1
|
DEV_IRQMASK_2
,
.
driver_data
=
DEV_NEED_LASTPACKET1
|
DEV_IRQMASK_2
|
DEV_NEED_TIMERIRQ
,
},
{
/* nForce3 Ethernet Controller */
.
vendor
=
PCI_VENDOR_ID_NVIDIA
,
.
device
=
0x00D6
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
.
driver_data
=
DEV_NEED_LASTPACKET1
|
DEV_IRQMASK_2
,
.
driver_data
=
DEV_NEED_LASTPACKET1
|
DEV_IRQMASK_2
|
DEV_NEED_TIMERIRQ
,
},
{
0
,},
};
...
...
@@ -1472,8 +1547,8 @@ static struct pci_device_id pci_tbl[] = {
static
struct
pci_driver
driver
=
{
.
name
=
"forcedeth"
,
.
id_table
=
pci_tbl
,
.
probe
=
probe_nic
,
.
remove
=
__devexit_p
(
remove_nic
),
.
probe
=
nv_probe
,
.
remove
=
__devexit_p
(
nv_remove
),
};
...
...
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