提交 3d963f5b 编写于 作者: L Linus Torvalds

Merge refs/heads/upstream from master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

-------
PHY Abstraction Layer
(Updated 2005-07-21)
Purpose
Most network devices consist of set of registers which provide an interface
to a MAC layer, which communicates with the physical connection through a
PHY. The PHY concerns itself with negotiating link parameters with the link
partner on the other side of the network connection (typically, an ethernet
cable), and provides a register interface to allow drivers to determine what
settings were chosen, and to configure what settings are allowed.
While these devices are distinct from the network devices, and conform to a
standard layout for the registers, it has been common practice to integrate
the PHY management code with the network driver. This has resulted in large
amounts of redundant code. Also, on embedded systems with multiple (and
sometimes quite different) ethernet controllers connected to the same
management bus, it is difficult to ensure safe use of the bus.
Since the PHYs are devices, and the management busses through which they are
accessed are, in fact, busses, the PHY Abstraction Layer treats them as such.
In doing so, it has these goals:
1) Increase code-reuse
2) Increase overall code-maintainability
3) Speed development time for new network drivers, and for new systems
Basically, this layer is meant to provide an interface to PHY devices which
allows network driver writers to write as little code as possible, while
still providing a full feature set.
The MDIO bus
Most network devices are connected to a PHY by means of a management bus.
Different devices use different busses (though some share common interfaces).
In order to take advantage of the PAL, each bus interface needs to be
registered as a distinct device.
1) read and write functions must be implemented. Their prototypes are:
int write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
int read(struct mii_bus *bus, int mii_id, int regnum);
mii_id is the address on the bus for the PHY, and regnum is the register
number. These functions are guaranteed not to be called from interrupt
time, so it is safe for them to block, waiting for an interrupt to signal
the operation is complete
2) A reset function is necessary. This is used to return the bus to an
initialized state.
3) A probe function is needed. This function should set up anything the bus
driver needs, setup the mii_bus structure, and register with the PAL using
mdiobus_register. Similarly, there's a remove function to undo all of
that (use mdiobus_unregister).
4) Like any driver, the device_driver structure must be configured, and init
exit functions are used to register the driver.
5) The bus must also be declared somewhere as a device, and registered.
As an example for how one driver implemented an mdio bus driver, see
drivers/net/gianfar_mii.c and arch/ppc/syslib/mpc85xx_devices.c
Connecting to a PHY
Sometime during startup, the network driver needs to establish a connection
between the PHY device, and the network device. At this time, the PHY's bus
and drivers need to all have been loaded, so it is ready for the connection.
At this point, there are several ways to connect to the PHY:
1) The PAL handles everything, and only calls the network driver when
the link state changes, so it can react.
2) The PAL handles everything except interrupts (usually because the
controller has the interrupt registers).
3) The PAL handles everything, but checks in with the driver every second,
allowing the network driver to react first to any changes before the PAL
does.
4) The PAL serves only as a library of functions, with the network device
manually calling functions to update status, and configure the PHY
Letting the PHY Abstraction Layer do Everything
If you choose option 1 (The hope is that every driver can, but to still be
useful to drivers that can't), connecting to the PHY is simple:
First, you need a function to react to changes in the link state. This
function follows this protocol:
static void adjust_link(struct net_device *dev);
Next, you need to know the device name of the PHY connected to this device.
The name will look something like, "phy0:0", where the first number is the
bus id, and the second is the PHY's address on that bus.
Now, to connect, just call this function:
phydev = phy_connect(dev, phy_name, &adjust_link, flags);
phydev is a pointer to the phy_device structure which represents the PHY. If
phy_connect is successful, it will return the pointer. dev, here, is the
pointer to your net_device. Once done, this function will have started the
PHY's software state machine, and registered for the PHY's interrupt, if it
has one. The phydev structure will be populated with information about the
current state, though the PHY will not yet be truly operational at this
point.
flags is a u32 which can optionally contain phy-specific flags.
This is useful if the system has put hardware restrictions on
the PHY/controller, of which the PHY needs to be aware.
Now just make sure that phydev->supported and phydev->advertising have any
values pruned from them which don't make sense for your controller (a 10/100
controller may be connected to a gigabit capable PHY, so you would need to
mask off SUPPORTED_1000baseT*). See include/linux/ethtool.h for definitions
for these bitfields. Note that you should not SET any bits, or the PHY may
get put into an unsupported state.
Lastly, once the controller is ready to handle network traffic, you call
phy_start(phydev). This tells the PAL that you are ready, and configures the
PHY to connect to the network. If you want to handle your own interrupts,
just set phydev->irq to PHY_IGNORE_INTERRUPT before you call phy_start.
Similarly, if you don't want to use interrupts, set phydev->irq to PHY_POLL.
When you want to disconnect from the network (even if just briefly), you call
phy_stop(phydev).
Keeping Close Tabs on the PAL
It is possible that the PAL's built-in state machine needs a little help to
keep your network device and the PHY properly in sync. If so, you can
register a helper function when connecting to the PHY, which will be called
every second before the state machine reacts to any changes. To do this, you
need to manually call phy_attach() and phy_prepare_link(), and then call
phy_start_machine() with the second argument set to point to your special
handler.
Currently there are no examples of how to use this functionality, and testing
on it has been limited because the author does not have any drivers which use
it (they all use option 1). So Caveat Emptor.
Doing it all yourself
There's a remote chance that the PAL's built-in state machine cannot track
the complex interactions between the PHY and your network device. If this is
so, you can simply call phy_attach(), and not call phy_start_machine or
phy_prepare_link(). This will mean that phydev->state is entirely yours to
handle (phy_start and phy_stop toggle between some of the states, so you
might need to avoid them).
An effort has been made to make sure that useful functionality can be
accessed without the state-machine running, and most of these functions are
descended from functions which did not interact with a complex state-machine.
However, again, no effort has been made so far to test running without the
state machine, so tryer beware.
Here is a brief rundown of the functions:
int phy_read(struct phy_device *phydev, u16 regnum);
int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
Simple read/write primitives. They invoke the bus's read/write function
pointers.
void phy_print_status(struct phy_device *phydev);
A convenience function to print out the PHY status neatly.
int phy_clear_interrupt(struct phy_device *phydev);
int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
Clear the PHY's interrupt, and configure which ones are allowed,
respectively. Currently only supports all on, or all off.
int phy_enable_interrupts(struct phy_device *phydev);
int phy_disable_interrupts(struct phy_device *phydev);
Functions which enable/disable PHY interrupts, clearing them
before and after, respectively.
int phy_start_interrupts(struct phy_device *phydev);
int phy_stop_interrupts(struct phy_device *phydev);
Requests the IRQ for the PHY interrupts, then enables them for
start, or disables then frees them for stop.
struct phy_device * phy_attach(struct net_device *dev, const char *phy_id,
u32 flags);
Attaches a network device to a particular PHY, binding the PHY to a generic
driver if none was found during bus initialization. Passes in
any phy-specific flags as needed.
int phy_start_aneg(struct phy_device *phydev);
Using variables inside the phydev structure, either configures advertising
and resets autonegotiation, or disables autonegotiation, and configures
forced settings.
static inline int phy_read_status(struct phy_device *phydev);
Fills the phydev structure with up-to-date information about the current
settings in the PHY.
void phy_sanitize_settings(struct phy_device *phydev)
Resolves differences between currently desired settings, and
supported settings for the given PHY device. Does not make
the changes in the hardware, though.
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
Ethtool convenience functions.
int phy_mii_ioctl(struct phy_device *phydev,
struct mii_ioctl_data *mii_data, int cmd);
The MII ioctl. Note that this function will completely screw up the state
machine if you write registers like BMCR, BMSR, ADVERTISE, etc. Best to
use this only to write registers which are not standard, and don't set off
a renegotiation.
PHY Device Drivers
With the PHY Abstraction Layer, adding support for new PHYs is
quite easy. In some cases, no work is required at all! However,
many PHYs require a little hand-holding to get up-and-running.
Generic PHY driver
If the desired PHY doesn't have any errata, quirks, or special
features you want to support, then it may be best to not add
support, and let the PHY Abstraction Layer's Generic PHY Driver
do all of the work.
Writing a PHY driver
If you do need to write a PHY driver, the first thing to do is
make sure it can be matched with an appropriate PHY device.
This is done during bus initialization by reading the device's
UID (stored in registers 2 and 3), then comparing it to each
driver's phy_id field by ANDing it with each driver's
phy_id_mask field. Also, it needs a name. Here's an example:
static struct phy_driver dm9161_driver = {
.phy_id = 0x0181b880,
.name = "Davicom DM9161E",
.phy_id_mask = 0x0ffffff0,
...
}
Next, you need to specify what features (speed, duplex, autoneg,
etc) your PHY device and driver support. Most PHYs support
PHY_BASIC_FEATURES, but you can look in include/mii.h for other
features.
Each driver consists of a number of function pointers:
config_init: configures PHY into a sane state after a reset.
For instance, a Davicom PHY requires descrambling disabled.
probe: Does any setup needed by the driver
suspend/resume: power management
config_aneg: Changes the speed/duplex/negotiation settings
read_status: Reads the current speed/duplex/negotiation settings
ack_interrupt: Clear a pending interrupt
config_intr: Enable or disable interrupts
remove: Does any driver take-down
Of these, only config_aneg and read_status are required to be
assigned by the driver code. The rest are optional. Also, it is
preferred to use the generic phy driver's versions of these two
functions if at all possible: genphy_read_status and
genphy_config_aneg. If this is not possible, it is likely that
you only need to perform some actions before and after invoking
these functions, and so your functions will wrap the generic
ones.
Feel free to look at the Marvell, Cicada, and Davicom drivers in
drivers/net/phy/ for examples (the lxt and qsemi drivers have
not been tested as of this writing)
...@@ -131,6 +131,8 @@ config NET_SB1000 ...@@ -131,6 +131,8 @@ config NET_SB1000
source "drivers/net/arcnet/Kconfig" source "drivers/net/arcnet/Kconfig"
source "drivers/net/phy/Kconfig"
# #
# Ethernet # Ethernet
# #
......
...@@ -65,6 +65,7 @@ obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o ...@@ -65,6 +65,7 @@ obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
# #
obj-$(CONFIG_MII) += mii.o obj-$(CONFIG_MII) += mii.o
obj-$(CONFIG_PHYLIB) += phy/
obj-$(CONFIG_SUNDANCE) += sundance.o obj-$(CONFIG_SUNDANCE) += sundance.o
obj-$(CONFIG_HAMACHI) += hamachi.o obj-$(CONFIG_HAMACHI) += hamachi.o
......
...@@ -87,7 +87,6 @@ extern struct net_device *mvme147lance_probe(int unit); ...@@ -87,7 +87,6 @@ extern struct net_device *mvme147lance_probe(int unit);
extern struct net_device *tc515_probe(int unit); extern struct net_device *tc515_probe(int unit);
extern struct net_device *lance_probe(int unit); extern struct net_device *lance_probe(int unit);
extern struct net_device *mace_probe(int unit); extern struct net_device *mace_probe(int unit);
extern struct net_device *macsonic_probe(int unit);
extern struct net_device *mac8390_probe(int unit); extern struct net_device *mac8390_probe(int unit);
extern struct net_device *mac89x0_probe(int unit); extern struct net_device *mac89x0_probe(int unit);
extern struct net_device *mc32_probe(int unit); extern struct net_device *mc32_probe(int unit);
...@@ -284,9 +283,6 @@ static struct devprobe2 m68k_probes[] __initdata = { ...@@ -284,9 +283,6 @@ static struct devprobe2 m68k_probes[] __initdata = {
#ifdef CONFIG_MACMACE /* Mac 68k Quadra AV builtin Ethernet */ #ifdef CONFIG_MACMACE /* Mac 68k Quadra AV builtin Ethernet */
{mace_probe, 0}, {mace_probe, 0},
#endif #endif
#ifdef CONFIG_MACSONIC /* Mac SONIC-based Ethernet of all sorts */
{macsonic_probe, 0},
#endif
#ifdef CONFIG_MAC8390 /* NuBus NS8390-based cards */ #ifdef CONFIG_MAC8390 /* NuBus NS8390-based cards */
{mac8390_probe, 0}, {mac8390_probe, 0},
#endif #endif
...@@ -318,17 +314,9 @@ static void __init ethif_probe2(int unit) ...@@ -318,17 +314,9 @@ static void __init ethif_probe2(int unit)
#ifdef CONFIG_TR #ifdef CONFIG_TR
/* Token-ring device probe */ /* Token-ring device probe */
extern int ibmtr_probe_card(struct net_device *); extern int ibmtr_probe_card(struct net_device *);
extern struct net_device *sk_isa_probe(int unit);
extern struct net_device *proteon_probe(int unit);
extern struct net_device *smctr_probe(int unit); extern struct net_device *smctr_probe(int unit);
static struct devprobe2 tr_probes2[] __initdata = { static struct devprobe2 tr_probes2[] __initdata = {
#ifdef CONFIG_SKISA
{sk_isa_probe, 0},
#endif
#ifdef CONFIG_PROTEON
{proteon_probe, 0},
#endif
#ifdef CONFIG_SMCTR #ifdef CONFIG_SMCTR
{smctr_probe, 0}, {smctr_probe, 0},
#endif #endif
......
...@@ -1106,18 +1106,13 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav ...@@ -1106,18 +1106,13 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
} }
} }
if (found) { if (!found)
/* a slave was found that is using the mac address return 0;
* of the new slave
*/
printk(KERN_ERR DRV_NAME
": Error: the hw address of slave %s is not "
"unique - cannot enslave it!",
slave->dev->name);
return -EINVAL;
}
return 0; /* Try setting slave mac to bond address and fall-through
to code handling that situation below... */
alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
bond->alb_info.rlb_enabled);
} }
/* The slave's address is equal to the address of the bond. /* The slave's address is equal to the address of the bond.
......
...@@ -1604,6 +1604,44 @@ static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_ ...@@ -1604,6 +1604,44 @@ static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_
return 0; return 0;
} }
#define BOND_INTERSECT_FEATURES \
(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
/*
* Compute the features available to the bonding device by
* intersection of all of the slave devices' BOND_INTERSECT_FEATURES.
* Call this after attaching or detaching a slave to update the
* bond's features.
*/
static int bond_compute_features(struct bonding *bond)
{
int i;
struct slave *slave;
struct net_device *bond_dev = bond->dev;
int features = bond->bond_features;
bond_for_each_slave(bond, slave, i) {
struct net_device * slave_dev = slave->dev;
if (i == 0) {
features |= BOND_INTERSECT_FEATURES;
}
features &=
~(~slave_dev->features & BOND_INTERSECT_FEATURES);
}
/* turn off NETIF_F_SG if we need a csum and h/w can't do it */
if ((features & NETIF_F_SG) &&
!(features & (NETIF_F_IP_CSUM |
NETIF_F_NO_CSUM |
NETIF_F_HW_CSUM))) {
features &= ~NETIF_F_SG;
}
bond_dev->features = features;
return 0;
}
/* enslave device <slave> to bond device <master> */ /* enslave device <slave> to bond device <master> */
static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{ {
...@@ -1811,6 +1849,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de ...@@ -1811,6 +1849,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
new_slave->delay = 0; new_slave->delay = 0;
new_slave->link_failure_count = 0; new_slave->link_failure_count = 0;
bond_compute_features(bond);
if (bond->params.miimon && !bond->params.use_carrier) { if (bond->params.miimon && !bond->params.use_carrier) {
link_reporting = bond_check_dev_link(bond, slave_dev, 1); link_reporting = bond_check_dev_link(bond, slave_dev, 1);
...@@ -2015,7 +2055,7 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de ...@@ -2015,7 +2055,7 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
err_undo_flags: err_undo_flags:
bond_dev->features = old_features; bond_dev->features = old_features;
return res; return res;
} }
...@@ -2100,6 +2140,8 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de ...@@ -2100,6 +2140,8 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
/* release the slave from its bond */ /* release the slave from its bond */
bond_detach_slave(bond, slave); bond_detach_slave(bond, slave);
bond_compute_features(bond);
if (bond->primary_slave == slave) { if (bond->primary_slave == slave) {
bond->primary_slave = NULL; bond->primary_slave = NULL;
} }
...@@ -2243,6 +2285,8 @@ static int bond_release_all(struct net_device *bond_dev) ...@@ -2243,6 +2285,8 @@ static int bond_release_all(struct net_device *bond_dev)
bond_alb_deinit_slave(bond, slave); bond_alb_deinit_slave(bond, slave);
} }
bond_compute_features(bond);
/* now that the slave is detached, unlock and perform /* now that the slave is detached, unlock and perform
* all the undo steps that should not be called from * all the undo steps that should not be called from
* within a lock. * within a lock.
...@@ -3588,6 +3632,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond ...@@ -3588,6 +3632,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond
static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev) static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev)
{ {
struct net_device *bond_dev = slave_dev->master; struct net_device *bond_dev = slave_dev->master;
struct bonding *bond = bond_dev->priv;
switch (event) { switch (event) {
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
...@@ -3626,6 +3671,9 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave ...@@ -3626,6 +3671,9 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
* TODO: handle changing the primary's name * TODO: handle changing the primary's name
*/ */
break; break;
case NETDEV_FEAT_CHANGE:
bond_compute_features(bond);
break;
default: default:
break; break;
} }
...@@ -4526,6 +4574,11 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode) ...@@ -4526,6 +4574,11 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode)
} }
} }
static struct ethtool_ops bond_ethtool_ops = {
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
};
/* /*
* Does not allocate but creates a /proc entry. * Does not allocate but creates a /proc entry.
* Allowed to fail. * Allowed to fail.
...@@ -4555,6 +4608,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par ...@@ -4555,6 +4608,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
bond_dev->stop = bond_close; bond_dev->stop = bond_close;
bond_dev->get_stats = bond_get_stats; bond_dev->get_stats = bond_get_stats;
bond_dev->do_ioctl = bond_do_ioctl; bond_dev->do_ioctl = bond_do_ioctl;
bond_dev->ethtool_ops = &bond_ethtool_ops;
bond_dev->set_multicast_list = bond_set_multicast_list; bond_dev->set_multicast_list = bond_set_multicast_list;
bond_dev->change_mtu = bond_change_mtu; bond_dev->change_mtu = bond_change_mtu;
bond_dev->set_mac_address = bond_set_mac_address; bond_dev->set_mac_address = bond_set_mac_address;
...@@ -4591,6 +4645,8 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par ...@@ -4591,6 +4645,8 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER); NETIF_F_HW_VLAN_FILTER);
bond->bond_features = bond_dev->features;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond); bond_create_proc_entry(bond);
#endif #endif
......
...@@ -211,6 +211,9 @@ struct bonding { ...@@ -211,6 +211,9 @@ struct bonding {
struct bond_params params; struct bond_params params;
struct list_head vlan_list; struct list_head vlan_list;
struct vlan_group *vlgrp; struct vlan_group *vlgrp;
/* the features the bonding device supports, independently
* of any slaves */
int bond_features;
}; };
/** /**
......
...@@ -2767,7 +2767,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) ...@@ -2767,7 +2767,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
" next_to_use <%x>\n" " next_to_use <%x>\n"
" next_to_clean <%x>\n" " next_to_clean <%x>\n"
"buffer_info[next_to_clean]\n" "buffer_info[next_to_clean]\n"
" dma <%zx>\n" " dma <%llx>\n"
" time_stamp <%lx>\n" " time_stamp <%lx>\n"
" next_to_watch <%x>\n" " next_to_watch <%x>\n"
" jiffies <%lx>\n" " jiffies <%lx>\n"
...@@ -2776,7 +2776,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) ...@@ -2776,7 +2776,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
E1000_READ_REG(&adapter->hw, TDT), E1000_READ_REG(&adapter->hw, TDT),
tx_ring->next_to_use, tx_ring->next_to_use,
i, i,
tx_ring->buffer_info[i].dma, (unsigned long long)tx_ring->buffer_info[i].dma,
tx_ring->buffer_info[i].time_stamp, tx_ring->buffer_info[i].time_stamp,
eop, eop,
jiffies, jiffies,
......
...@@ -1263,8 +1263,8 @@ speedo_init_rx_ring(struct net_device *dev) ...@@ -1263,8 +1263,8 @@ speedo_init_rx_ring(struct net_device *dev)
for (i = 0; i < RX_RING_SIZE; i++) { for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *skb; struct sk_buff *skb;
skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
/* XXX: do we really want to call this before the NULL check? --hch */ if (skb)
rx_align(skb); /* Align IP on 16 byte boundary */ rx_align(skb); /* Align IP on 16 byte boundary */
sp->rx_skbuff[i] = skb; sp->rx_skbuff[i] = skb;
if (skb == NULL) if (skb == NULL)
break; /* OK. Just initially short of Rx bufs. */ break; /* OK. Just initially short of Rx bufs. */
...@@ -1654,8 +1654,8 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry) ...@@ -1654,8 +1654,8 @@ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
struct sk_buff *skb; struct sk_buff *skb;
/* Get a fresh skbuff to replace the consumed one. */ /* Get a fresh skbuff to replace the consumed one. */
skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD)); skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
/* XXX: do we really want to call this before the NULL check? --hch */ if (skb)
rx_align(skb); /* Align IP on 16 byte boundary */ rx_align(skb); /* Align IP on 16 byte boundary */
sp->rx_skbuff[entry] = skb; sp->rx_skbuff[entry] = skb;
if (skb == NULL) { if (skb == NULL) {
sp->rx_ringp[entry] = NULL; sp->rx_ringp[entry] = NULL;
......
此差异已折叠。
config MKISS config MKISS
tristate "Serial port KISS driver" tristate "Serial port KISS driver"
depends on AX25 && BROKEN_ON_SMP depends on AX25
---help--- ---help---
KISS is a protocol used for the exchange of data between a computer KISS is a protocol used for the exchange of data between a computer
and a Terminal Node Controller (a small embedded system commonly and a Terminal Node Controller (a small embedded system commonly
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/hdlcdrv.h> #include <linux/hdlcdrv.h>
#include <linux/baycom.h> #include <linux/baycom.h>
#include <linux/jiffies.h>
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
/* prototypes for ax25_encapsulate and ax25_rebuild_header */ /* prototypes for ax25_encapsulate and ax25_rebuild_header */
#include <net/ax25.h> #include <net/ax25.h>
...@@ -287,7 +288,7 @@ static inline void baycom_int_freq(struct baycom_state *bc) ...@@ -287,7 +288,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency * measure the interrupt frequency
*/ */
bc->debug_vals.cur_intcnt++; bc->debug_vals.cur_intcnt++;
if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) { if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies; bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt; bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0; bc->debug_vals.cur_intcnt = 0;
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
#include <linux/baycom.h> #include <linux/baycom.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/jiffies.h>
#include <asm/bug.h> #include <asm/bug.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -165,7 +166,7 @@ static void __inline__ baycom_int_freq(struct baycom_state *bc) ...@@ -165,7 +166,7 @@ static void __inline__ baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency * measure the interrupt frequency
*/ */
bc->debug_vals.cur_intcnt++; bc->debug_vals.cur_intcnt++;
if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) { if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies; bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt; bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0; bc->debug_vals.cur_intcnt = 0;
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <linux/hdlcdrv.h> #include <linux/hdlcdrv.h>
#include <linux/baycom.h> #include <linux/baycom.h>
#include <linux/jiffies.h>
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
...@@ -159,7 +160,7 @@ static inline void baycom_int_freq(struct baycom_state *bc) ...@@ -159,7 +160,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency * measure the interrupt frequency
*/ */
bc->debug_vals.cur_intcnt++; bc->debug_vals.cur_intcnt++;
if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) { if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies; bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt; bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0; bc->debug_vals.cur_intcnt = 0;
......
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
#include <asm/io.h> #include <asm/io.h>
#include <linux/hdlcdrv.h> #include <linux/hdlcdrv.h>
#include <linux/baycom.h> #include <linux/baycom.h>
#include <linux/jiffies.h>
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
...@@ -150,7 +151,7 @@ static inline void baycom_int_freq(struct baycom_state *bc) ...@@ -150,7 +151,7 @@ static inline void baycom_int_freq(struct baycom_state *bc)
* measure the interrupt frequency * measure the interrupt frequency
*/ */
bc->debug_vals.cur_intcnt++; bc->debug_vals.cur_intcnt++;
if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) { if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
bc->debug_vals.last_jiffies = cur_jiffies; bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt; bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0; bc->debug_vals.cur_intcnt = 0;
......
此差异已折叠。
...@@ -119,7 +119,7 @@ struct ixgb_adapter; ...@@ -119,7 +119,7 @@ struct ixgb_adapter;
* so a DMA handle can be stored along with the buffer */ * so a DMA handle can be stored along with the buffer */
struct ixgb_buffer { struct ixgb_buffer {
struct sk_buff *skb; struct sk_buff *skb;
uint64_t dma; dma_addr_t dma;
unsigned long time_stamp; unsigned long time_stamp;
uint16_t length; uint16_t length;
uint16_t next_to_watch; uint16_t next_to_watch;
......
...@@ -565,24 +565,6 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw, ...@@ -565,24 +565,6 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
} }
} }
/******************************************************************************
* return the compatibility flags from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* compatibility flags if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_compatibility(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->compatibility));
return(0);
}
/****************************************************************************** /******************************************************************************
* return the Printed Board Assembly number from EEPROM * return the Printed Board Assembly number from EEPROM
...@@ -602,81 +584,6 @@ ixgb_get_ee_pba_number(struct ixgb_hw *hw) ...@@ -602,81 +584,6 @@ ixgb_get_ee_pba_number(struct ixgb_hw *hw)
return(0); return(0);
} }
/******************************************************************************
* return the Initialization Control Word 1 from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Initialization Control Word 1 if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->init_ctrl_reg_1));
return(0);
}
/******************************************************************************
* return the Initialization Control Word 2 from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Initialization Control Word 2 if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->init_ctrl_reg_2));
return(0);
}
/******************************************************************************
* return the Subsystem Id from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Subsystem Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_subsystem_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->subsystem_id));
return(0);
}
/******************************************************************************
* return the Sub Vendor Id from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Sub Vendor Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_subvendor_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->subvendor_id));
return(0);
}
/****************************************************************************** /******************************************************************************
* return the Device Id from EEPROM * return the Device Id from EEPROM
...@@ -694,81 +601,6 @@ ixgb_get_ee_device_id(struct ixgb_hw *hw) ...@@ -694,81 +601,6 @@ ixgb_get_ee_device_id(struct ixgb_hw *hw)
if(ixgb_check_and_get_eeprom_data(hw) == TRUE) if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->device_id)); return (le16_to_cpu(ee_map->device_id));
return(0); return (0);
}
/******************************************************************************
* return the Vendor Id from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* Device Id if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_vendor_id(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->vendor_id));
return(0);
}
/******************************************************************************
* return the Software Defined Pins Register from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* SDP Register if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint16_t
ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->swdpins_reg));
return(0);
} }
/******************************************************************************
* return the D3 Power Management Bits from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* D3 Power Management Bits if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint8_t
ixgb_get_ee_d3_power(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->d3_power));
return(0);
}
/******************************************************************************
* return the D0 Power Management Bits from EEPROM
*
* hw - Struct containing variables accessed by shared code
*
* Returns:
* D0 Power Management Bits if EEPROM contents are valid, 0 otherwise
******************************************************************************/
uint8_t
ixgb_get_ee_d0_power(struct ixgb_hw *hw)
{
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
return (le16_to_cpu(ee_map->d0_power));
return(0);
}
...@@ -98,10 +98,10 @@ static struct ixgb_stats ixgb_gstrings_stats[] = { ...@@ -98,10 +98,10 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
static int static int
ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
ecmd->port = PORT_FIBRE; ecmd->port = PORT_FIBRE;
ecmd->transceiver = XCVR_EXTERNAL; ecmd->transceiver = XCVR_EXTERNAL;
...@@ -120,7 +120,7 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ...@@ -120,7 +120,7 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
static int static int
ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
if(ecmd->autoneg == AUTONEG_ENABLE || if(ecmd->autoneg == AUTONEG_ENABLE ||
ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL) ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
...@@ -130,6 +130,12 @@ ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ...@@ -130,6 +130,12 @@ ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ixgb_down(adapter, TRUE); ixgb_down(adapter, TRUE);
ixgb_reset(adapter); ixgb_reset(adapter);
ixgb_up(adapter); ixgb_up(adapter);
/* be optimistic about our link, since we were up before */
adapter->link_speed = 10000;
adapter->link_duplex = FULL_DUPLEX;
netif_carrier_on(netdev);
netif_wake_queue(netdev);
} else } else
ixgb_reset(adapter); ixgb_reset(adapter);
...@@ -140,7 +146,7 @@ static void ...@@ -140,7 +146,7 @@ static void
ixgb_get_pauseparam(struct net_device *netdev, ixgb_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause) struct ethtool_pauseparam *pause)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw; struct ixgb_hw *hw = &adapter->hw;
pause->autoneg = AUTONEG_DISABLE; pause->autoneg = AUTONEG_DISABLE;
...@@ -159,7 +165,7 @@ static int ...@@ -159,7 +165,7 @@ static int
ixgb_set_pauseparam(struct net_device *netdev, ixgb_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause) struct ethtool_pauseparam *pause)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw; struct ixgb_hw *hw = &adapter->hw;
if(pause->autoneg == AUTONEG_ENABLE) if(pause->autoneg == AUTONEG_ENABLE)
...@@ -177,6 +183,11 @@ ixgb_set_pauseparam(struct net_device *netdev, ...@@ -177,6 +183,11 @@ ixgb_set_pauseparam(struct net_device *netdev,
if(netif_running(adapter->netdev)) { if(netif_running(adapter->netdev)) {
ixgb_down(adapter, TRUE); ixgb_down(adapter, TRUE);
ixgb_up(adapter); ixgb_up(adapter);
/* be optimistic about our link, since we were up before */
adapter->link_speed = 10000;
adapter->link_duplex = FULL_DUPLEX;
netif_carrier_on(netdev);
netif_wake_queue(netdev);
} else } else
ixgb_reset(adapter); ixgb_reset(adapter);
...@@ -186,19 +197,26 @@ ixgb_set_pauseparam(struct net_device *netdev, ...@@ -186,19 +197,26 @@ ixgb_set_pauseparam(struct net_device *netdev,
static uint32_t static uint32_t
ixgb_get_rx_csum(struct net_device *netdev) ixgb_get_rx_csum(struct net_device *netdev)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
return adapter->rx_csum; return adapter->rx_csum;
} }
static int static int
ixgb_set_rx_csum(struct net_device *netdev, uint32_t data) ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
adapter->rx_csum = data; adapter->rx_csum = data;
if(netif_running(netdev)) { if(netif_running(netdev)) {
ixgb_down(adapter,TRUE); ixgb_down(adapter,TRUE);
ixgb_up(adapter); ixgb_up(adapter);
/* be optimistic about our link, since we were up before */
adapter->link_speed = 10000;
adapter->link_duplex = FULL_DUPLEX;
netif_carrier_on(netdev);
netif_wake_queue(netdev);
} else } else
ixgb_reset(adapter); ixgb_reset(adapter);
return 0; return 0;
...@@ -246,14 +264,15 @@ static void ...@@ -246,14 +264,15 @@ static void
ixgb_get_regs(struct net_device *netdev, ixgb_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p) struct ethtool_regs *regs, void *p)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw; struct ixgb_hw *hw = &adapter->hw;
uint32_t *reg = p; uint32_t *reg = p;
uint32_t *reg_start = reg; uint32_t *reg_start = reg;
uint8_t i; uint8_t i;
/* the 1 (one) below indicates an attempt at versioning, if the /* the 1 (one) below indicates an attempt at versioning, if the
* interface in ethtool or the driver this 1 should be incremented */ * interface in ethtool or the driver changes, this 1 should be
* incremented */
regs->version = (1<<24) | hw->revision_id << 16 | hw->device_id; regs->version = (1<<24) | hw->revision_id << 16 | hw->device_id;
/* General Registers */ /* General Registers */
...@@ -283,7 +302,8 @@ ixgb_get_regs(struct net_device *netdev, ...@@ -283,7 +302,8 @@ ixgb_get_regs(struct net_device *netdev,
*reg++ = IXGB_READ_REG(hw, RAIDC); /* 19 */ *reg++ = IXGB_READ_REG(hw, RAIDC); /* 19 */
*reg++ = IXGB_READ_REG(hw, RXCSUM); /* 20 */ *reg++ = IXGB_READ_REG(hw, RXCSUM); /* 20 */
for (i = 0; i < IXGB_RAR_ENTRIES; i++) { /* there are 16 RAR entries in hardware, we only use 3 */
for(i = 0; i < 16; i++) {
*reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */ *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
*reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */ *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
} }
...@@ -391,7 +411,7 @@ static int ...@@ -391,7 +411,7 @@ static int
ixgb_get_eeprom(struct net_device *netdev, ixgb_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, uint8_t *bytes) struct ethtool_eeprom *eeprom, uint8_t *bytes)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw; struct ixgb_hw *hw = &adapter->hw;
uint16_t *eeprom_buff; uint16_t *eeprom_buff;
int i, max_len, first_word, last_word; int i, max_len, first_word, last_word;
...@@ -439,7 +459,7 @@ static int ...@@ -439,7 +459,7 @@ static int
ixgb_set_eeprom(struct net_device *netdev, ixgb_set_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, uint8_t *bytes) struct ethtool_eeprom *eeprom, uint8_t *bytes)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw; struct ixgb_hw *hw = &adapter->hw;
uint16_t *eeprom_buff; uint16_t *eeprom_buff;
void *ptr; void *ptr;
...@@ -497,7 +517,7 @@ static void ...@@ -497,7 +517,7 @@ static void
ixgb_get_drvinfo(struct net_device *netdev, ixgb_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo) struct ethtool_drvinfo *drvinfo)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
strncpy(drvinfo->driver, ixgb_driver_name, 32); strncpy(drvinfo->driver, ixgb_driver_name, 32);
strncpy(drvinfo->version, ixgb_driver_version, 32); strncpy(drvinfo->version, ixgb_driver_version, 32);
...@@ -512,7 +532,7 @@ static void ...@@ -512,7 +532,7 @@ static void
ixgb_get_ringparam(struct net_device *netdev, ixgb_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring) struct ethtool_ringparam *ring)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_desc_ring *txdr = &adapter->tx_ring; struct ixgb_desc_ring *txdr = &adapter->tx_ring;
struct ixgb_desc_ring *rxdr = &adapter->rx_ring; struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
...@@ -530,7 +550,7 @@ static int ...@@ -530,7 +550,7 @@ static int
ixgb_set_ringparam(struct net_device *netdev, ixgb_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring) struct ethtool_ringparam *ring)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_desc_ring *txdr = &adapter->tx_ring; struct ixgb_desc_ring *txdr = &adapter->tx_ring;
struct ixgb_desc_ring *rxdr = &adapter->rx_ring; struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new; struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new;
...@@ -573,6 +593,11 @@ ixgb_set_ringparam(struct net_device *netdev, ...@@ -573,6 +593,11 @@ ixgb_set_ringparam(struct net_device *netdev,
adapter->tx_ring = tx_new; adapter->tx_ring = tx_new;
if((err = ixgb_up(adapter))) if((err = ixgb_up(adapter)))
return err; return err;
/* be optimistic about our link, since we were up before */
adapter->link_speed = 10000;
adapter->link_duplex = FULL_DUPLEX;
netif_carrier_on(netdev);
netif_wake_queue(netdev);
} }
return 0; return 0;
...@@ -607,7 +632,7 @@ ixgb_led_blink_callback(unsigned long data) ...@@ -607,7 +632,7 @@ ixgb_led_blink_callback(unsigned long data)
static int static int
ixgb_phys_id(struct net_device *netdev, uint32_t data) ixgb_phys_id(struct net_device *netdev, uint32_t data)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
...@@ -643,7 +668,7 @@ static void ...@@ -643,7 +668,7 @@ static void
ixgb_get_ethtool_stats(struct net_device *netdev, ixgb_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, uint64_t *data) struct ethtool_stats *stats, uint64_t *data)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
int i; int i;
ixgb_update_stats(adapter); ixgb_update_stats(adapter);
......
...@@ -822,17 +822,8 @@ extern void ixgb_clear_vfta(struct ixgb_hw *hw); ...@@ -822,17 +822,8 @@ extern void ixgb_clear_vfta(struct ixgb_hw *hw);
/* Access functions to eeprom data */ /* Access functions to eeprom data */
void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr); void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
uint16_t ixgb_get_ee_compatibility(struct ixgb_hw *hw);
uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw); uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_subsystem_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_subvendor_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_device_id(struct ixgb_hw *hw); uint16_t ixgb_get_ee_device_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_vendor_id(struct ixgb_hw *hw);
uint16_t ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw);
uint8_t ixgb_get_ee_d3_power(struct ixgb_hw *hw);
uint8_t ixgb_get_ee_d0_power(struct ixgb_hw *hw);
boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw); boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw);
uint16_t ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index); uint16_t ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index);
......
...@@ -29,6 +29,11 @@ ...@@ -29,6 +29,11 @@
#include "ixgb.h" #include "ixgb.h"
/* Change Log /* Change Log
* 1.0.96 04/19/05
* - Make needlessly global code static -- bunk@stusta.de
* - ethtool cleanup -- shemminger@osdl.org
* - Support for MODULE_VERSION -- linville@tuxdriver.com
* - add skb_header_cloned check to the tso path -- herbert@apana.org.au
* 1.0.88 01/05/05 * 1.0.88 01/05/05
* - include fix to the condition that determines when to quit NAPI - Robert Olsson * - include fix to the condition that determines when to quit NAPI - Robert Olsson
* - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
...@@ -47,10 +52,9 @@ char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver"; ...@@ -47,10 +52,9 @@ char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
#else #else
#define DRIVERNAPI "-NAPI" #define DRIVERNAPI "-NAPI"
#endif #endif
#define DRV_VERSION "1.0.100-k2"DRIVERNAPI
#define DRV_VERSION "1.0.95-k2"DRIVERNAPI
char ixgb_driver_version[] = DRV_VERSION; char ixgb_driver_version[] = DRV_VERSION;
char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
/* ixgb_pci_tbl - PCI Device ID Table /* ixgb_pci_tbl - PCI Device ID Table
* *
...@@ -145,10 +149,12 @@ MODULE_LICENSE("GPL"); ...@@ -145,10 +149,12 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
/* some defines for controlling descriptor fetches in h/w */ /* some defines for controlling descriptor fetches in h/w */
#define RXDCTL_PTHRESH_DEFAULT 128 /* chip considers prefech below this */
#define RXDCTL_HTHRESH_DEFAULT 16 /* chip will only prefetch if tail is
pushed this many descriptors from head */
#define RXDCTL_WTHRESH_DEFAULT 16 /* chip writes back at this many or RXT0 */ #define RXDCTL_WTHRESH_DEFAULT 16 /* chip writes back at this many or RXT0 */
#define RXDCTL_PTHRESH_DEFAULT 0 /* chip considers prefech below
* this */
#define RXDCTL_HTHRESH_DEFAULT 0 /* chip will only prefetch if tail
* is pushed this many descriptors
* from head */
/** /**
* ixgb_init_module - Driver Registration Routine * ixgb_init_module - Driver Registration Routine
...@@ -376,7 +382,7 @@ ixgb_probe(struct pci_dev *pdev, ...@@ -376,7 +382,7 @@ ixgb_probe(struct pci_dev *pdev,
SET_NETDEV_DEV(netdev, &pdev->dev); SET_NETDEV_DEV(netdev, &pdev->dev);
pci_set_drvdata(pdev, netdev); pci_set_drvdata(pdev, netdev);
adapter = netdev->priv; adapter = netdev_priv(netdev);
adapter->netdev = netdev; adapter->netdev = netdev;
adapter->pdev = pdev; adapter->pdev = pdev;
adapter->hw.back = adapter; adapter->hw.back = adapter;
...@@ -512,7 +518,7 @@ static void __devexit ...@@ -512,7 +518,7 @@ static void __devexit
ixgb_remove(struct pci_dev *pdev) ixgb_remove(struct pci_dev *pdev)
{ {
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
unregister_netdev(netdev); unregister_netdev(netdev);
...@@ -583,7 +589,7 @@ ixgb_sw_init(struct ixgb_adapter *adapter) ...@@ -583,7 +589,7 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
static int static int
ixgb_open(struct net_device *netdev) ixgb_open(struct net_device *netdev)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
int err; int err;
/* allocate transmit descriptors */ /* allocate transmit descriptors */
...@@ -626,7 +632,7 @@ ixgb_open(struct net_device *netdev) ...@@ -626,7 +632,7 @@ ixgb_open(struct net_device *netdev)
static int static int
ixgb_close(struct net_device *netdev) ixgb_close(struct net_device *netdev)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
ixgb_down(adapter, TRUE); ixgb_down(adapter, TRUE);
...@@ -1017,7 +1023,7 @@ ixgb_clean_rx_ring(struct ixgb_adapter *adapter) ...@@ -1017,7 +1023,7 @@ ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
static int static int
ixgb_set_mac(struct net_device *netdev, void *p) ixgb_set_mac(struct net_device *netdev, void *p)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p; struct sockaddr *addr = p;
if(!is_valid_ether_addr(addr->sa_data)) if(!is_valid_ether_addr(addr->sa_data))
...@@ -1043,7 +1049,7 @@ ixgb_set_mac(struct net_device *netdev, void *p) ...@@ -1043,7 +1049,7 @@ ixgb_set_mac(struct net_device *netdev, void *p)
static void static void
ixgb_set_multi(struct net_device *netdev) ixgb_set_multi(struct net_device *netdev)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw; struct ixgb_hw *hw = &adapter->hw;
struct dev_mc_list *mc_ptr; struct dev_mc_list *mc_ptr;
uint32_t rctl; uint32_t rctl;
...@@ -1371,7 +1377,7 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags) ...@@ -1371,7 +1377,7 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
static int static int
ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
unsigned int first; unsigned int first;
unsigned int tx_flags = 0; unsigned int tx_flags = 0;
unsigned long flags; unsigned long flags;
...@@ -1425,7 +1431,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -1425,7 +1431,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
static void static void
ixgb_tx_timeout(struct net_device *netdev) ixgb_tx_timeout(struct net_device *netdev)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
/* Do the reset outside of interrupt context */ /* Do the reset outside of interrupt context */
schedule_work(&adapter->tx_timeout_task); schedule_work(&adapter->tx_timeout_task);
...@@ -1434,7 +1440,7 @@ ixgb_tx_timeout(struct net_device *netdev) ...@@ -1434,7 +1440,7 @@ ixgb_tx_timeout(struct net_device *netdev)
static void static void
ixgb_tx_timeout_task(struct net_device *netdev) ixgb_tx_timeout_task(struct net_device *netdev)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
ixgb_down(adapter, TRUE); ixgb_down(adapter, TRUE);
ixgb_up(adapter); ixgb_up(adapter);
...@@ -1451,7 +1457,7 @@ ixgb_tx_timeout_task(struct net_device *netdev) ...@@ -1451,7 +1457,7 @@ ixgb_tx_timeout_task(struct net_device *netdev)
static struct net_device_stats * static struct net_device_stats *
ixgb_get_stats(struct net_device *netdev) ixgb_get_stats(struct net_device *netdev)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
return &adapter->net_stats; return &adapter->net_stats;
} }
...@@ -1467,7 +1473,7 @@ ixgb_get_stats(struct net_device *netdev) ...@@ -1467,7 +1473,7 @@ ixgb_get_stats(struct net_device *netdev)
static int static int
ixgb_change_mtu(struct net_device *netdev, int new_mtu) ixgb_change_mtu(struct net_device *netdev, int new_mtu)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH; int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH; int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
...@@ -1522,7 +1528,8 @@ ixgb_update_stats(struct ixgb_adapter *adapter) ...@@ -1522,7 +1528,8 @@ ixgb_update_stats(struct ixgb_adapter *adapter)
multi |= ((u64)IXGB_READ_REG(&adapter->hw, MPRCH) << 32); multi |= ((u64)IXGB_READ_REG(&adapter->hw, MPRCH) << 32);
/* fix up multicast stats by removing broadcasts */ /* fix up multicast stats by removing broadcasts */
multi -= bcast; if(multi >= bcast)
multi -= bcast;
adapter->stats.mprcl += (multi & 0xFFFFFFFF); adapter->stats.mprcl += (multi & 0xFFFFFFFF);
adapter->stats.mprch += (multi >> 32); adapter->stats.mprch += (multi >> 32);
...@@ -1641,7 +1648,7 @@ static irqreturn_t ...@@ -1641,7 +1648,7 @@ static irqreturn_t
ixgb_intr(int irq, void *data, struct pt_regs *regs) ixgb_intr(int irq, void *data, struct pt_regs *regs)
{ {
struct net_device *netdev = data; struct net_device *netdev = data;
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
struct ixgb_hw *hw = &adapter->hw; struct ixgb_hw *hw = &adapter->hw;
uint32_t icr = IXGB_READ_REG(hw, ICR); uint32_t icr = IXGB_READ_REG(hw, ICR);
#ifndef CONFIG_IXGB_NAPI #ifndef CONFIG_IXGB_NAPI
...@@ -1688,7 +1695,7 @@ ixgb_intr(int irq, void *data, struct pt_regs *regs) ...@@ -1688,7 +1695,7 @@ ixgb_intr(int irq, void *data, struct pt_regs *regs)
static int static int
ixgb_clean(struct net_device *netdev, int *budget) ixgb_clean(struct net_device *netdev, int *budget)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
int work_to_do = min(*budget, netdev->quota); int work_to_do = min(*budget, netdev->quota);
int tx_cleaned; int tx_cleaned;
int work_done = 0; int work_done = 0;
...@@ -2017,7 +2024,7 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter) ...@@ -2017,7 +2024,7 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
static void static void
ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
uint32_t ctrl, rctl; uint32_t ctrl, rctl;
ixgb_irq_disable(adapter); ixgb_irq_disable(adapter);
...@@ -2055,7 +2062,7 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ...@@ -2055,7 +2062,7 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
static void static void
ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index; uint32_t vfta, index;
/* add VID to filter table */ /* add VID to filter table */
...@@ -2069,7 +2076,7 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) ...@@ -2069,7 +2076,7 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
static void static void
ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
{ {
struct ixgb_adapter *adapter = netdev->priv; struct ixgb_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index; uint32_t vfta, index;
ixgb_irq_disable(adapter); ixgb_irq_disable(adapter);
......
/* /*
* sonic.c * jazzsonic.c
*
* (C) 2005 Finn Thain
*
* Converted to DMA API, and (from the mac68k project) introduced
* dhd's support for 16-bit cards.
* *
* (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
* *
...@@ -28,8 +33,8 @@ ...@@ -28,8 +33,8 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dma-mapping.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -44,22 +49,20 @@ static struct platform_device *jazz_sonic_device; ...@@ -44,22 +49,20 @@ static struct platform_device *jazz_sonic_device;
#define SONIC_MEM_SIZE 0x100 #define SONIC_MEM_SIZE 0x100
#define SREGS_PAD(n) u16 n;
#include "sonic.h" #include "sonic.h"
/* /*
* Macros to access SONIC registers * Macros to access SONIC registers
*/ */
#define SONIC_READ(reg) (*((volatile unsigned int *)base_addr+reg)) #define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg))
#define SONIC_WRITE(reg,val) \ #define SONIC_WRITE(reg,val) \
do { \ do { \
*((volatile unsigned int *)base_addr+(reg)) = (val); \ *((volatile unsigned int *)dev->base_addr+(reg)) = (val); \
} while (0) } while (0)
/* use 0 for production, 1 for verification, >2 for debug */ /* use 0 for production, 1 for verification, >1 for debug */
#ifdef SONIC_DEBUG #ifdef SONIC_DEBUG
static unsigned int sonic_debug = SONIC_DEBUG; static unsigned int sonic_debug = SONIC_DEBUG;
#else #else
...@@ -85,18 +88,18 @@ static unsigned short known_revisions[] = ...@@ -85,18 +88,18 @@ static unsigned short known_revisions[] =
0xffff /* end of list */ 0xffff /* end of list */
}; };
static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr, static int __init sonic_probe1(struct net_device *dev)
unsigned int irq)
{ {
static unsigned version_printed; static unsigned version_printed;
unsigned int silicon_revision; unsigned int silicon_revision;
unsigned int val; unsigned int val;
struct sonic_local *lp; struct sonic_local *lp = netdev_priv(dev);
int err = -ENODEV; int err = -ENODEV;
int i; int i;
if (!request_mem_region(base_addr, SONIC_MEM_SIZE, jazz_sonic_string)) if (!request_mem_region(dev->base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
return -EBUSY; return -EBUSY;
/* /*
* get the Silicon Revision ID. If this is one of the known * get the Silicon Revision ID. If this is one of the known
* one assume that we found a SONIC ethernet controller at * one assume that we found a SONIC ethernet controller at
...@@ -120,11 +123,7 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr, ...@@ -120,11 +123,7 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
if (sonic_debug && version_printed++ == 0) if (sonic_debug && version_printed++ == 0)
printk(version); printk(version);
printk("%s: Sonic ethernet found at 0x%08lx, ", dev->name, base_addr); printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr);
/* Fill in the 'dev' fields. */
dev->base_addr = base_addr;
dev->irq = irq;
/* /*
* Put the sonic into software reset, then * Put the sonic into software reset, then
...@@ -138,84 +137,44 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr, ...@@ -138,84 +137,44 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
dev->dev_addr[i*2+1] = val >> 8; dev->dev_addr[i*2+1] = val >> 8;
} }
printk("HW Address ");
for (i = 0; i < 6; i++) {
printk("%2.2x", dev->dev_addr[i]);
if (i<5)
printk(":");
}
printk(" IRQ %d\n", irq);
err = -ENOMEM; err = -ENOMEM;
/* Initialize the device structure. */ /* Initialize the device structure. */
if (dev->priv == NULL) {
/*
* the memory be located in the same 64kb segment
*/
lp = NULL;
i = 0;
do {
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if ((unsigned long) lp >> 16
!= ((unsigned long)lp + sizeof(*lp) ) >> 16) {
/* FIXME, free the memory later */
kfree(lp);
lp = NULL;
}
} while (lp == NULL && i++ < 20);
if (lp == NULL) {
printk("%s: couldn't allocate memory for descriptors\n",
dev->name);
goto out;
}
memset(lp, 0, sizeof(struct sonic_local)); lp->dma_bitmode = SONIC_BITMODE32;
/* get the virtual dma address */
lp->cda_laddr = vdma_alloc(CPHYSADDR(lp),sizeof(*lp));
if (lp->cda_laddr == ~0UL) {
printk("%s: couldn't get DMA page entry for "
"descriptors\n", dev->name);
goto out1;
}
lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda);
lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda);
lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra);
/* allocate receive buffer area */
/* FIXME, maybe we should use skbs */
lp->rba = kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL);
if (!lp->rba) {
printk("%s: couldn't allocate receive buffers\n",
dev->name);
goto out2;
}
/* get virtual dma address */ /* Allocate the entire chunk of memory for the descriptors.
lp->rba_laddr = vdma_alloc(CPHYSADDR(lp->rba), Note that this cannot cross a 64K boundary. */
SONIC_NUM_RRS * SONIC_RBSIZE); if ((lp->descriptors = dma_alloc_coherent(lp->device,
if (lp->rba_laddr == ~0UL) { SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
printk("%s: couldn't get DMA page entry for receive " &lp->descriptors_laddr, GFP_KERNEL)) == NULL) {
"buffers\n",dev->name); printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id);
goto out3; goto out;
}
/* now convert pointer to KSEG1 pointer */
lp->rba = (char *)KSEG1ADDR(lp->rba);
flush_cache_all();
dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
} }
lp = (struct sonic_local *)dev->priv; /* Now set up the pointers to point to the appropriate places */
lp->cda = lp->descriptors;
lp->tda = lp->cda + (SIZEOF_SONIC_CDA
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->cda_laddr = lp->descriptors_laddr;
lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
* SONIC_BUS_SCALE(lp->dma_bitmode));
dev->open = sonic_open; dev->open = sonic_open;
dev->stop = sonic_close; dev->stop = sonic_close;
dev->hard_start_xmit = sonic_send_packet; dev->hard_start_xmit = sonic_send_packet;
dev->get_stats = sonic_get_stats; dev->get_stats = sonic_get_stats;
dev->set_multicast_list = &sonic_multicast_list; dev->set_multicast_list = &sonic_multicast_list;
dev->tx_timeout = sonic_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
/* /*
...@@ -226,14 +185,8 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr, ...@@ -226,14 +185,8 @@ static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
SONIC_WRITE(SONIC_MPT,0xffff); SONIC_WRITE(SONIC_MPT,0xffff);
return 0; return 0;
out3:
kfree(lp->rba);
out2:
vdma_free(lp->cda_laddr);
out1:
kfree(lp);
out: out:
release_region(base_addr, SONIC_MEM_SIZE); release_region(dev->base_addr, SONIC_MEM_SIZE);
return err; return err;
} }
...@@ -245,7 +198,6 @@ static int __init jazz_sonic_probe(struct device *device) ...@@ -245,7 +198,6 @@ static int __init jazz_sonic_probe(struct device *device)
{ {
struct net_device *dev; struct net_device *dev;
struct sonic_local *lp; struct sonic_local *lp;
unsigned long base_addr;
int err = 0; int err = 0;
int i; int i;
...@@ -255,21 +207,26 @@ static int __init jazz_sonic_probe(struct device *device) ...@@ -255,21 +207,26 @@ static int __init jazz_sonic_probe(struct device *device)
if (mips_machgroup != MACH_GROUP_JAZZ) if (mips_machgroup != MACH_GROUP_JAZZ)
return -ENODEV; return -ENODEV;
dev = alloc_etherdev(0); dev = alloc_etherdev(sizeof(struct sonic_local));
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
lp = netdev_priv(dev);
lp->device = device;
SET_NETDEV_DEV(dev, device);
SET_MODULE_OWNER(dev);
netdev_boot_setup_check(dev); netdev_boot_setup_check(dev);
base_addr = dev->base_addr;
if (base_addr >= KSEG0) { /* Check a single specified location. */ if (dev->base_addr >= KSEG0) { /* Check a single specified location. */
err = sonic_probe1(dev, base_addr, dev->irq); err = sonic_probe1(dev);
} else if (base_addr != 0) { /* Don't probe at all. */ } else if (dev->base_addr != 0) { /* Don't probe at all. */
err = -ENXIO; err = -ENXIO;
} else { } else {
for (i = 0; sonic_portlist[i].port; i++) { for (i = 0; sonic_portlist[i].port; i++) {
int io = sonic_portlist[i].port; dev->base_addr = sonic_portlist[i].port;
if (sonic_probe1(dev, io, sonic_portlist[i].irq) == 0) dev->irq = sonic_portlist[i].irq;
if (sonic_probe1(dev) == 0)
break; break;
} }
if (!sonic_portlist[i].port) if (!sonic_portlist[i].port)
...@@ -281,14 +238,17 @@ static int __init jazz_sonic_probe(struct device *device) ...@@ -281,14 +238,17 @@ static int __init jazz_sonic_probe(struct device *device)
if (err) if (err)
goto out1; goto out1;
printk("%s: MAC ", dev->name);
for (i = 0; i < 6; i++) {
printk("%2.2x", dev->dev_addr[i]);
if (i < 5)
printk(":");
}
printk(" IRQ %d\n", dev->irq);
return 0; return 0;
out1: out1:
lp = dev->priv;
vdma_free(lp->rba_laddr);
kfree(lp->rba);
vdma_free(lp->cda_laddr);
kfree(lp);
release_region(dev->base_addr, SONIC_MEM_SIZE); release_region(dev->base_addr, SONIC_MEM_SIZE);
out: out:
free_netdev(dev); free_netdev(dev);
...@@ -296,21 +256,22 @@ static int __init jazz_sonic_probe(struct device *device) ...@@ -296,21 +256,22 @@ static int __init jazz_sonic_probe(struct device *device)
return err; return err;
} }
/* MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
* SONIC uses a normal IRQ module_param(sonic_debug, int, 0);
*/ MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
#define sonic_request_irq request_irq
#define sonic_free_irq free_irq
#define sonic_chiptomem(x) KSEG1ADDR(vdma_log2phys(x)) #define SONIC_IRQ_FLAG SA_INTERRUPT
#include "sonic.c" #include "sonic.c"
static int __devexit jazz_sonic_device_remove (struct device *device) static int __devexit jazz_sonic_device_remove (struct device *device)
{ {
struct net_device *dev = device->driver_data; struct net_device *dev = device->driver_data;
struct sonic_local* lp = netdev_priv(dev);
unregister_netdev (dev); unregister_netdev (dev);
dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
lp->descriptors, lp->descriptors_laddr);
release_region (dev->base_addr, SONIC_MEM_SIZE); release_region (dev->base_addr, SONIC_MEM_SIZE);
free_netdev (dev); free_netdev (dev);
...@@ -323,7 +284,7 @@ static struct device_driver jazz_sonic_driver = { ...@@ -323,7 +284,7 @@ static struct device_driver jazz_sonic_driver = {
.probe = jazz_sonic_probe, .probe = jazz_sonic_probe,
.remove = __devexit_p(jazz_sonic_device_remove), .remove = __devexit_p(jazz_sonic_device_remove),
}; };
static void jazz_sonic_platform_release (struct device *device) static void jazz_sonic_platform_release (struct device *device)
{ {
struct platform_device *pldev; struct platform_device *pldev;
...@@ -336,10 +297,11 @@ static void jazz_sonic_platform_release (struct device *device) ...@@ -336,10 +297,11 @@ static void jazz_sonic_platform_release (struct device *device)
static int __init jazz_sonic_init_module(void) static int __init jazz_sonic_init_module(void)
{ {
struct platform_device *pldev; struct platform_device *pldev;
int err;
if (driver_register(&jazz_sonic_driver)) { if ((err = driver_register(&jazz_sonic_driver))) {
printk(KERN_ERR "Driver registration failed\n"); printk(KERN_ERR "Driver registration failed\n");
return -ENOMEM; return err;
} }
jazz_sonic_device = NULL; jazz_sonic_device = NULL;
......
...@@ -68,6 +68,7 @@ static DEFINE_PER_CPU(struct net_device_stats, loopback_stats); ...@@ -68,6 +68,7 @@ static DEFINE_PER_CPU(struct net_device_stats, loopback_stats);
* of largesending device modulo TCP checksum, which is ignored for loopback. * of largesending device modulo TCP checksum, which is ignored for loopback.
*/ */
#ifdef LOOPBACK_TSO
static void emulate_large_send_offload(struct sk_buff *skb) static void emulate_large_send_offload(struct sk_buff *skb)
{ {
struct iphdr *iph = skb->nh.iph; struct iphdr *iph = skb->nh.iph;
...@@ -119,6 +120,7 @@ static void emulate_large_send_offload(struct sk_buff *skb) ...@@ -119,6 +120,7 @@ static void emulate_large_send_offload(struct sk_buff *skb)
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
#endif /* LOOPBACK_TSO */
/* /*
* The higher levels take care of making this non-reentrant (it's * The higher levels take care of making this non-reentrant (it's
...@@ -130,12 +132,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -130,12 +132,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
skb_orphan(skb); skb_orphan(skb);
skb->protocol=eth_type_trans(skb,dev); skb->protocol = eth_type_trans(skb,dev);
skb->dev=dev; skb->dev = dev;
#ifndef LOOPBACK_MUST_CHECKSUM #ifndef LOOPBACK_MUST_CHECKSUM
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
#endif #endif
#ifdef LOOPBACK_TSO
if (skb_shinfo(skb)->tso_size) { if (skb_shinfo(skb)->tso_size) {
BUG_ON(skb->protocol != htons(ETH_P_IP)); BUG_ON(skb->protocol != htons(ETH_P_IP));
BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP); BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
...@@ -143,14 +146,14 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -143,14 +146,14 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
emulate_large_send_offload(skb); emulate_large_send_offload(skb);
return 0; return 0;
} }
#endif
dev->last_rx = jiffies; dev->last_rx = jiffies;
lb_stats = &per_cpu(loopback_stats, get_cpu()); lb_stats = &per_cpu(loopback_stats, get_cpu());
lb_stats->rx_bytes += skb->len; lb_stats->rx_bytes += skb->len;
lb_stats->tx_bytes += skb->len; lb_stats->tx_bytes = lb_stats->rx_bytes;
lb_stats->rx_packets++; lb_stats->rx_packets++;
lb_stats->tx_packets++; lb_stats->tx_packets = lb_stats->rx_packets;
put_cpu(); put_cpu();
netif_rx(skb); netif_rx(skb);
...@@ -208,9 +211,12 @@ struct net_device loopback_dev = { ...@@ -208,9 +211,12 @@ struct net_device loopback_dev = {
.type = ARPHRD_LOOPBACK, /* 0x0001*/ .type = ARPHRD_LOOPBACK, /* 0x0001*/
.rebuild_header = eth_rebuild_header, .rebuild_header = eth_rebuild_header,
.flags = IFF_LOOPBACK, .flags = IFF_LOOPBACK,
.features = NETIF_F_SG|NETIF_F_FRAGLIST .features = NETIF_F_SG | NETIF_F_FRAGLIST
|NETIF_F_NO_CSUM|NETIF_F_HIGHDMA #ifdef LOOPBACK_TSO
|NETIF_F_LLTX, | NETIF_F_TSO
#endif
| NETIF_F_NO_CSUM | NETIF_F_HIGHDMA
| NETIF_F_LLTX,
.ethtool_ops = &loopback_ethtool_ops, .ethtool_ops = &loopback_ethtool_ops,
}; };
......
此差异已折叠。
...@@ -1157,16 +1157,20 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1157,16 +1157,20 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!skb_shinfo(skb)->nr_frags) { if (!skb_shinfo(skb)->nr_frags) {
linear: linear:
if (skb->ip_summed != CHECKSUM_HW) { if (skb->ip_summed != CHECKSUM_HW) {
/* Errata BTS #50, IHL must be 5 if no HW checksum */
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC; ETH_TX_FIRST_DESC |
ETH_TX_LAST_DESC |
5 << ETH_TX_IHL_SHIFT;
pkt_info.l4i_chk = 0; pkt_info.l4i_chk = 0;
} else { } else {
u32 ipheader = skb->nh.iph->ihl << 11;
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC | ETH_TX_FIRST_DESC |
ETH_GEN_TCP_UDP_CHECKSUM | ETH_TX_LAST_DESC |
ETH_GEN_IP_V_4_CHECKSUM | ipheader; ETH_GEN_TCP_UDP_CHECKSUM |
ETH_GEN_IP_V_4_CHECKSUM |
skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */ /* CPU already calculated pseudo header checksum. */
if (skb->nh.iph->protocol == IPPROTO_UDP) { if (skb->nh.iph->protocol == IPPROTO_UDP) {
pkt_info.cmd_sts |= ETH_UDP_FRAME; pkt_info.cmd_sts |= ETH_UDP_FRAME;
...@@ -1193,7 +1197,6 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1193,7 +1197,6 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_bytes += pkt_info.byte_cnt; stats->tx_bytes += pkt_info.byte_cnt;
} else { } else {
unsigned int frag; unsigned int frag;
u32 ipheader;
/* Since hardware can't handle unaligned fragments smaller /* Since hardware can't handle unaligned fragments smaller
* than 9 bytes, if we find any, we linearize the skb * than 9 bytes, if we find any, we linearize the skb
...@@ -1222,12 +1225,16 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1222,12 +1225,16 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
DMA_TO_DEVICE); DMA_TO_DEVICE);
pkt_info.l4i_chk = 0; pkt_info.l4i_chk = 0;
pkt_info.return_info = 0; pkt_info.return_info = 0;
pkt_info.cmd_sts = ETH_TX_FIRST_DESC;
if (skb->ip_summed == CHECKSUM_HW) { if (skb->ip_summed != CHECKSUM_HW)
ipheader = skb->nh.iph->ihl << 11; /* Errata BTS #50, IHL must be 5 if no HW checksum */
pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM | pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
ETH_GEN_IP_V_4_CHECKSUM | ipheader; 5 << ETH_TX_IHL_SHIFT;
else {
pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
ETH_GEN_TCP_UDP_CHECKSUM |
ETH_GEN_IP_V_4_CHECKSUM |
skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
/* CPU already calculated pseudo header checksum. */ /* CPU already calculated pseudo header checksum. */
if (skb->nh.iph->protocol == IPPROTO_UDP) { if (skb->nh.iph->protocol == IPPROTO_UDP) {
pkt_info.cmd_sts |= ETH_UDP_FRAME; pkt_info.cmd_sts |= ETH_UDP_FRAME;
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
/* Checksum offload for Tx works for most packets, but /* Checksum offload for Tx works for most packets, but
* fails if previous packet sent did not use hw csum * fails if previous packet sent did not use hw csum
*/ */
#undef MV643XX_CHECKSUM_OFFLOAD_TX #define MV643XX_CHECKSUM_OFFLOAD_TX
#define MV643XX_NAPI #define MV643XX_NAPI
#define MV643XX_TX_FAST_REFILL #define MV643XX_TX_FAST_REFILL
#undef MV643XX_RX_QUEUE_FILL_ON_TASK /* Does not work, yet */ #undef MV643XX_RX_QUEUE_FILL_ON_TASK /* Does not work, yet */
...@@ -217,6 +217,8 @@ ...@@ -217,6 +217,8 @@
#define ETH_TX_ENABLE_INTERRUPT (BIT23) #define ETH_TX_ENABLE_INTERRUPT (BIT23)
#define ETH_AUTO_MODE (BIT30) #define ETH_AUTO_MODE (BIT30)
#define ETH_TX_IHL_SHIFT 11
/* typedefs */ /* typedefs */
typedef enum _eth_func_ret_status { typedef enum _eth_func_ret_status {
......
...@@ -486,9 +486,9 @@ struct netdrv_private { ...@@ -486,9 +486,9 @@ struct netdrv_private {
MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>"); MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>");
MODULE_DESCRIPTION ("Skeleton for a PCI Fast Ethernet driver"); MODULE_DESCRIPTION ("Skeleton for a PCI Fast Ethernet driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM (multicast_filter_limit, "i"); module_param(multicast_filter_limit, int, 0);
MODULE_PARM (max_interrupt_work, "i"); module_param(max_interrupt_work, int, 0);
MODULE_PARM (media, "1-" __MODULE_STRING(8) "i"); module_param_array(media, int, NULL, 0);
MODULE_PARM_DESC (multicast_filter_limit, "pci-skeleton maximum number of filtered multicast addresses"); MODULE_PARM_DESC (multicast_filter_limit, "pci-skeleton maximum number of filtered multicast addresses");
MODULE_PARM_DESC (max_interrupt_work, "pci-skeleton maximum events handled per interrupt"); MODULE_PARM_DESC (max_interrupt_work, "pci-skeleton maximum events handled per interrupt");
MODULE_PARM_DESC (media, "pci-skeleton: Bits 0-3: media type, bit 17: full duplex"); MODULE_PARM_DESC (media, "pci-skeleton: Bits 0-3: media type, bit 17: full duplex");
......
...@@ -134,7 +134,7 @@ typedef struct local_info_t { ...@@ -134,7 +134,7 @@ typedef struct local_info_t {
u_char mc_filter[8]; u_char mc_filter[8];
} local_info_t; } local_info_t;
#define MC_FILTERBREAK 64 #define MC_FILTERBREAK 8
/*====================================================================*/ /*====================================================================*/
/* /*
...@@ -1012,7 +1012,7 @@ static void fjn_reset(struct net_device *dev) ...@@ -1012,7 +1012,7 @@ static void fjn_reset(struct net_device *dev)
outb(BANK_1U, ioaddr + CONFIG_1); outb(BANK_1U, ioaddr + CONFIG_1);
/* set the multicast table to accept none. */ /* set the multicast table to accept none. */
for (i = 0; i < 6; i++) for (i = 0; i < 8; i++)
outb(0x00, ioaddr + MAR_ADR + i); outb(0x00, ioaddr + MAR_ADR + i);
/* Switch to bank 2 (runtime mode) */ /* Switch to bank 2 (runtime mode) */
...@@ -1269,6 +1269,16 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1269,6 +1269,16 @@ static void set_rx_mode(struct net_device *dev)
u_long flags; u_long flags;
int i; int i;
int saved_config_0 = inb(ioaddr + CONFIG_0);
local_irq_save(flags);
/* Disable Tx and Rx */
if (sram_config == 0)
outb(CONFIG0_RST, ioaddr + CONFIG_0);
else
outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
if (dev->flags & IFF_PROMISC) { if (dev->flags & IFF_PROMISC) {
/* Unconditionally log net taps. */ /* Unconditionally log net taps. */
printk("%s: Promiscuous mode enabled.\n", dev->name); printk("%s: Promiscuous mode enabled.\n", dev->name);
...@@ -1290,20 +1300,23 @@ static void set_rx_mode(struct net_device *dev) ...@@ -1290,20 +1300,23 @@ static void set_rx_mode(struct net_device *dev)
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist = mclist->next) { i++, mclist = mclist->next) {
unsigned int bit = unsigned int bit =
ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f; ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26;
mc_filter[bit >> 3] |= (1 << bit); mc_filter[bit >> 3] |= (1 << (bit & 7));
} }
outb(2, ioaddr + RX_MODE); /* Use normal mode. */
} }
local_irq_save(flags);
if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) { if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
int saved_bank = inb(ioaddr + CONFIG_1); int saved_bank = inb(ioaddr + CONFIG_1);
/* Switch to bank 1 and set the multicast table. */ /* Switch to bank 1 and set the multicast table. */
outb(0xe4, ioaddr + CONFIG_1); outb(0xe4, ioaddr + CONFIG_1);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
outb(mc_filter[i], ioaddr + 8 + i); outb(mc_filter[i], ioaddr + MAR_ADR + i);
memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter)); memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
outb(saved_bank, ioaddr + CONFIG_1); outb(saved_bank, ioaddr + CONFIG_1);
} }
outb(saved_config_0, ioaddr + CONFIG_0);
local_irq_restore(flags); local_irq_restore(flags);
} }
#
# PHY Layer Configuration
#
menu "PHY device support"
config PHYLIB
tristate "PHY Device support and infrastructure"
depends on NET_ETHERNET
help
Ethernet controllers are usually attached to PHY
devices. This option provides infrastructure for
managing PHY devices.
config PHYCONTROL
bool " Support for automatically handling PHY state changes"
depends on PHYLIB
help
Adds code to perform all the work for keeping PHY link
state (speed/duplex/etc) up-to-date. Also handles
interrupts.
comment "MII PHY device drivers"
depends on PHYLIB
config MARVELL_PHY
tristate "Drivers for Marvell PHYs"
depends on PHYLIB
---help---
Currently has a driver for the 88E1011S
config DAVICOM_PHY
tristate "Drivers for Davicom PHYs"
depends on PHYLIB
---help---
Currently supports dm9161e and dm9131
config QSEMI_PHY
tristate "Drivers for Quality Semiconductor PHYs"
depends on PHYLIB
---help---
Currently supports the qs6612
config LXT_PHY
tristate "Drivers for the Intel LXT PHYs"
depends on PHYLIB
---help---
Currently supports the lxt970, lxt971
config CICADA_PHY
tristate "Drivers for the Cicada PHYs"
depends on PHYLIB
---help---
Currently supports the cis8204
endmenu
# Makefile for Linux PHY drivers
libphy-objs := phy.o phy_device.o mdio_bus.o
obj-$(CONFIG_PHYLIB) += libphy.o
obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_DAVICOM_PHY) += davicom.o
obj-$(CONFIG_CICADA_PHY) += cicada.o
obj-$(CONFIG_LXT_PHY) += lxt.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
/*
* drivers/net/phy/cicada.c
*
* Driver for Cicada PHYs
*
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
/* Cicada Extended Control Register 1 */
#define MII_CIS8201_EXT_CON1 0x17
#define MII_CIS8201_EXTCON1_INIT 0x0000
/* Cicada Interrupt Mask Register */
#define MII_CIS8201_IMASK 0x19
#define MII_CIS8201_IMASK_IEN 0x8000
#define MII_CIS8201_IMASK_SPEED 0x4000
#define MII_CIS8201_IMASK_LINK 0x2000
#define MII_CIS8201_IMASK_DUPLEX 0x1000
#define MII_CIS8201_IMASK_MASK 0xf000
/* Cicada Interrupt Status Register */
#define MII_CIS8201_ISTAT 0x1a
#define MII_CIS8201_ISTAT_STATUS 0x8000
#define MII_CIS8201_ISTAT_SPEED 0x4000
#define MII_CIS8201_ISTAT_LINK 0x2000
#define MII_CIS8201_ISTAT_DUPLEX 0x1000
/* Cicada Auxiliary Control/Status Register */
#define MII_CIS8201_AUX_CONSTAT 0x1c
#define MII_CIS8201_AUXCONSTAT_INIT 0x0004
#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020
#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018
#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010
#define MII_CIS8201_AUXCONSTAT_100 0x0008
MODULE_DESCRIPTION("Cicadia PHY driver");
MODULE_AUTHOR("Andy Fleming");
MODULE_LICENSE("GPL");
static int cis820x_config_init(struct phy_device *phydev)
{
int err;
err = phy_write(phydev, MII_CIS8201_AUX_CONSTAT,
MII_CIS8201_AUXCONSTAT_INIT);
if (err < 0)
return err;
err = phy_write(phydev, MII_CIS8201_EXT_CON1,
MII_CIS8201_EXTCON1_INIT);
return err;
}
static int cis820x_ack_interrupt(struct phy_device *phydev)
{
int err = phy_read(phydev, MII_CIS8201_ISTAT);
return (err < 0) ? err : 0;
}
static int cis820x_config_intr(struct phy_device *phydev)
{
int err;
if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
err = phy_write(phydev, MII_CIS8201_IMASK,
MII_CIS8201_IMASK_MASK);
else
err = phy_write(phydev, MII_CIS8201_IMASK, 0);
return err;
}
/* Cicada 820x */
static struct phy_driver cis8204_driver = {
.phy_id = 0x000fc440,
.name = "Cicada Cis8204",
.phy_id_mask = 0x000fffc0,
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = &cis820x_config_init,
.config_aneg = &genphy_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &cis820x_ack_interrupt,
.config_intr = &cis820x_config_intr,
.driver = { .owner = THIS_MODULE,},
};
static int __init cis8204_init(void)
{
return phy_driver_register(&cis8204_driver);
}
static void __exit cis8204_exit(void)
{
phy_driver_unregister(&cis8204_driver);
}
module_init(cis8204_init);
module_exit(cis8204_exit);
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -187,6 +187,7 @@ static struct pci_device_id rtl8169_pci_tbl[] = { ...@@ -187,6 +187,7 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), }, { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), },
{ PCI_DEVICE(0x16ec, 0x0116), }, { PCI_DEVICE(0x16ec, 0x0116), },
{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024, },
{0,}, {0,},
}; };
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -214,8 +214,6 @@ enum { ...@@ -214,8 +214,6 @@ enum {
/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ /* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
enum { enum {
IS_ERR_MSK = 0x00003fff,/* All Error bits */
IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */ IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */
IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */ IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */
IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */ IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */
...@@ -230,6 +228,12 @@ enum { ...@@ -230,6 +228,12 @@ enum {
IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */ IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */
IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */ IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */
IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */ IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */
IS_ERR_MSK = IS_IRQ_MST_ERR | IS_IRQ_STAT
| IS_NO_STAT_M1 | IS_NO_STAT_M2
| IS_RAM_RD_PAR | IS_RAM_WR_PAR
| IS_M1_PAR_ERR | IS_M2_PAR_ERR
| IS_R1_PAR_ERR | IS_R2_PAR_ERR,
}; };
/* B2_TST_CTRL1 8 bit Test Control Register 1 */ /* B2_TST_CTRL1 8 bit Test Control Register 1 */
...@@ -2456,24 +2460,17 @@ struct skge_hw { ...@@ -2456,24 +2460,17 @@ struct skge_hw {
u8 chip_id; u8 chip_id;
u8 chip_rev; u8 chip_rev;
u8 phy_type; u8 copper;
u8 pmd_type;
u16 phy_addr;
u8 ports; u8 ports;
u32 ram_size; u32 ram_size;
u32 ram_offset; u32 ram_offset;
u16 phy_addr;
struct tasklet_struct ext_tasklet; struct tasklet_struct ext_tasklet;
spinlock_t phy_lock; spinlock_t phy_lock;
}; };
static inline int iscopper(const struct skge_hw *hw)
{
return (hw->pmd_type == 'T');
}
enum { enum {
FLOW_MODE_NONE = 0, /* No Flow-Control */ FLOW_MODE_NONE = 0, /* No Flow-Control */
FLOW_MODE_LOC_SEND = 1, /* Local station sends PAUSE */ FLOW_MODE_LOC_SEND = 1, /* Local station sends PAUSE */
......
此差异已折叠。
此差异已折叠。
...@@ -84,7 +84,7 @@ config 3C359 ...@@ -84,7 +84,7 @@ config 3C359
config TMS380TR config TMS380TR
tristate "Generic TMS380 Token Ring ISA/PCI adapter support" tristate "Generic TMS380 Token Ring ISA/PCI adapter support"
depends on TR && (PCI || ISA && ISA_DMA_API) depends on TR && (PCI || ISA && ISA_DMA_API || MCA)
select FW_LOADER select FW_LOADER
---help--- ---help---
This driver provides generic support for token ring adapters This driver provides generic support for token ring adapters
...@@ -158,7 +158,7 @@ config ABYSS ...@@ -158,7 +158,7 @@ config ABYSS
config MADGEMC config MADGEMC
tristate "Madge Smart 16/4 Ringnode MicroChannel" tristate "Madge Smart 16/4 Ringnode MicroChannel"
depends on TR && TMS380TR && MCA_LEGACY depends on TR && TMS380TR && MCA
help help
This tms380 module supports the Madge Smart 16/4 MC16 and MC32 This tms380 module supports the Madge Smart 16/4 MC16 and MC32
MicroChannel adapters. MicroChannel adapters.
......
...@@ -139,7 +139,7 @@ static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_ ...@@ -139,7 +139,7 @@ static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_
*/ */
dev->base_addr += 0x10; dev->base_addr += 0x10;
ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev); ret = tmsdev_init(dev, &pdev->dev);
if (ret) { if (ret) {
printk("%s: unable to get memory for dev->priv.\n", printk("%s: unable to get memory for dev->priv.\n",
dev->name); dev->name);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -17,8 +17,7 @@ ...@@ -17,8 +17,7 @@
int tms380tr_open(struct net_device *dev); int tms380tr_open(struct net_device *dev);
int tms380tr_close(struct net_device *dev); int tms380tr_close(struct net_device *dev);
irqreturn_t tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs); irqreturn_t tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
int tmsdev_init(struct net_device *dev, unsigned long dmalimit, int tmsdev_init(struct net_device *dev, struct device *pdev);
struct pci_dev *pdev);
void tmsdev_term(struct net_device *dev); void tmsdev_term(struct net_device *dev);
void tms380tr_wait(unsigned long time); void tms380tr_wait(unsigned long time);
...@@ -719,7 +718,7 @@ struct s_TPL { /* Transmit Parameter List (align on even word boundaries) */ ...@@ -719,7 +718,7 @@ struct s_TPL { /* Transmit Parameter List (align on even word boundaries) */
struct sk_buff *Skb; struct sk_buff *Skb;
unsigned char TPLIndex; unsigned char TPLIndex;
volatile unsigned char BusyFlag;/* Flag: TPL busy? */ volatile unsigned char BusyFlag;/* Flag: TPL busy? */
dma_addr_t DMABuff; /* DMA IO bus address from pci_map */ dma_addr_t DMABuff; /* DMA IO bus address from dma_map */
}; };
/* ---------------------Receive Functions-------------------------------* /* ---------------------Receive Functions-------------------------------*
...@@ -1060,7 +1059,7 @@ struct s_RPL { /* Receive Parameter List */ ...@@ -1060,7 +1059,7 @@ struct s_RPL { /* Receive Parameter List */
struct sk_buff *Skb; struct sk_buff *Skb;
SKB_STAT SkbStat; SKB_STAT SkbStat;
int RPLIndex; int RPLIndex;
dma_addr_t DMABuff; /* DMA IO bus address from pci_map */ dma_addr_t DMABuff; /* DMA IO bus address from dma_map */
}; };
/* Information that need to be kept for each board. */ /* Information that need to be kept for each board. */
...@@ -1091,7 +1090,7 @@ typedef struct net_local { ...@@ -1091,7 +1090,7 @@ typedef struct net_local {
RPL *RplTail; RPL *RplTail;
unsigned char LocalRxBuffers[RPL_NUM][DEFAULT_PACKET_SIZE]; unsigned char LocalRxBuffers[RPL_NUM][DEFAULT_PACKET_SIZE];
struct pci_dev *pdev; struct device *pdev;
int DataRate; int DataRate;
unsigned char ScbInUse; unsigned char ScbInUse;
unsigned short CMDqueue; unsigned short CMDqueue;
......
...@@ -100,7 +100,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic ...@@ -100,7 +100,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
unsigned int pci_irq_line; unsigned int pci_irq_line;
unsigned long pci_ioaddr; unsigned long pci_ioaddr;
struct card_info *cardinfo = &card_info_table[ent->driver_data]; struct card_info *cardinfo = &card_info_table[ent->driver_data];
if (versionprinted++ == 0) if (versionprinted++ == 0)
printk("%s", version); printk("%s", version);
...@@ -143,7 +143,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic ...@@ -143,7 +143,7 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
printk(":%2.2x", dev->dev_addr[i]); printk(":%2.2x", dev->dev_addr[i]);
printk("\n"); printk("\n");
ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev); ret = tmsdev_init(dev, &pdev->dev);
if (ret) { if (ret) {
printk("%s: unable to get memory for dev->priv.\n", dev->name); printk("%s: unable to get memory for dev->priv.\n", dev->name);
goto err_out_irq; goto err_out_irq;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册