Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (35 commits)
  xen-netfront: rearrange netfront structure to separate tx and rx
  netdev: convert non-obvious instances to use ARRAY_SIZE()
  ucc_geth: Fix build break introduced by commit 09f75cd7bf
  gianfar: Fix regression caused by new napi interface
  gianfar: Cleanup compile warning caused by 0795af57
  gianfar: Fix compile regression caused by bea3348e
  add new prom.h for AU1x00
  update AU1000 get_ethernet_addr()
  MIPSsim: General cleanup
  Jazzsonic: Fix warning about unused variable.
  Remove msic_dcr_read() in axon_msi.c
  Use dcr_host_t.base in dcr_unmap()
  Add dcr_host_t.base in dcr_read()/dcr_write()
  Use dcr_host_t.base in ibm_emac_mal
  Update ibm_newemac to use dcr_host_t.base
  tehuti: possible leak in bdx_probe
  TC35815: Fix build
  SAA9730: Fix build
  AR7 ethernet
  myri10ge: update driver version to 1.3.2-1.287
  ...
This commit is contained in:
Linus Torvalds 2007-10-15 13:30:35 -07:00
commit 43d39ae0cf
51 changed files with 1914 additions and 325 deletions

View File

@ -281,6 +281,39 @@ downdelay
will be rounded down to the nearest multiple. The default will be rounded down to the nearest multiple. The default
value is 0. value is 0.
fail_over_mac
Specifies whether active-backup mode should set all slaves to
the same MAC address (the traditional behavior), or, when
enabled, change the bond's MAC address when changing the
active interface (i.e., fail over the MAC address itself).
Fail over MAC is useful for devices that cannot ever alter
their MAC address, or for devices that refuse incoming
broadcasts with their own source MAC (which interferes with
the ARP monitor).
The down side of fail over MAC is that every device on the
network must be updated via gratuitous ARP, vs. just updating
a switch or set of switches (which often takes place for any
traffic, not just ARP traffic, if the switch snoops incoming
traffic to update its tables) for the traditional method. If
the gratuitous ARP is lost, communication may be disrupted.
When fail over MAC is used in conjuction with the mii monitor,
devices which assert link up prior to being able to actually
transmit and receive are particularly susecptible to loss of
the gratuitous ARP, and an appropriate updelay setting may be
required.
A value of 0 disables fail over MAC, and is the default. A
value of 1 enables fail over MAC. This option is enabled
automatically if the first slave added cannot change its MAC
address. This option may be modified via sysfs only when no
slaves are present in the bond.
This option was added in bonding version 3.2.0.
lacp_rate lacp_rate
Option specifying the rate in which we'll ask our link partner Option specifying the rate in which we'll ask our link partner

View File

@ -33,7 +33,6 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA. * 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
@ -41,18 +40,16 @@
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
/* #define DEBUG_CMDLINE */ int prom_argc;
char **prom_argv;
extern int prom_argc; char **prom_envp;
extern char **prom_argv, **prom_envp;
char * __init_or_module prom_getcmdline(void) char * __init_or_module prom_getcmdline(void)
{ {
return &(arcs_cmdline[0]); return &(arcs_cmdline[0]);
} }
void prom_init_cmdline(void) void prom_init_cmdline(void)
{ {
char *cp; char *cp;
int actr; int actr;
@ -61,7 +58,7 @@ void prom_init_cmdline(void)
cp = &(arcs_cmdline[0]); cp = &(arcs_cmdline[0]);
while(actr < prom_argc) { while(actr < prom_argc) {
strcpy(cp, prom_argv[actr]); strcpy(cp, prom_argv[actr]);
cp += strlen(prom_argv[actr]); cp += strlen(prom_argv[actr]);
*cp++ = ' '; *cp++ = ' ';
actr++; actr++;
@ -70,10 +67,8 @@ void prom_init_cmdline(void)
--cp; --cp;
if (prom_argc > 1) if (prom_argc > 1)
*cp = '\0'; *cp = '\0';
} }
char *prom_getenv(char *envname) char *prom_getenv(char *envname)
{ {
/* /*
@ -95,21 +90,23 @@ char *prom_getenv(char *envname)
} }
env++; env++;
} }
return NULL; return NULL;
} }
inline unsigned char str2hexnum(unsigned char c) static inline unsigned char str2hexnum(unsigned char c)
{ {
if(c >= '0' && c <= '9') if (c >= '0' && c <= '9')
return c - '0'; return c - '0';
if(c >= 'a' && c <= 'f') if (c >= 'a' && c <= 'f')
return c - 'a' + 10; return c - 'a' + 10;
if(c >= 'A' && c <= 'F') if (c >= 'A' && c <= 'F')
return c - 'A' + 10; return c - 'A' + 10;
return 0; /* foo */ return 0; /* foo */
} }
inline void str2eaddr(unsigned char *ea, unsigned char *str) static inline void str2eaddr(unsigned char *ea, unsigned char *str)
{ {
int i; int i;
@ -124,35 +121,29 @@ inline void str2eaddr(unsigned char *ea, unsigned char *str)
} }
} }
int get_ethernet_addr(char *ethernet_addr) int prom_get_ethernet_addr(char *ethernet_addr)
{ {
char *ethaddr_str; char *ethaddr_str;
char *argptr;
ethaddr_str = prom_getenv("ethaddr"); /* Check the environment variables first */
ethaddr_str = prom_getenv("ethaddr");
if (!ethaddr_str) { if (!ethaddr_str) {
printk("ethaddr not set in boot prom\n"); /* Check command line */
return -1; argptr = prom_getcmdline();
ethaddr_str = strstr(argptr, "ethaddr=");
if (!ethaddr_str)
return -1;
ethaddr_str += strlen("ethaddr=");
} }
str2eaddr(ethernet_addr, ethaddr_str); str2eaddr(ethernet_addr, ethaddr_str);
#if 0
{
int i;
printk("get_ethernet_addr: ");
for (i=0; i<5; i++)
printk("%02x:", (unsigned char)*(ethernet_addr+i));
printk("%02x\n", *(ethernet_addr+i));
}
#endif
return 0; return 0;
} }
EXPORT_SYMBOL(prom_get_ethernet_addr);
void __init prom_free_prom_memory(void) void __init prom_free_prom_memory(void)
{ {
} }
EXPORT_SYMBOL(prom_getcmdline);
EXPORT_SYMBOL(get_ethernet_addr);
EXPORT_SYMBOL(str2eaddr);

View File

@ -40,10 +40,11 @@
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
#include <asm/reboot.h> #include <asm/reboot.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/time.h> #include <asm/time.h>
extern char * prom_getcmdline(void); #include <au1000.h>
#include <prom.h>
extern void __init board_setup(void); extern void __init board_setup(void);
extern void au1000_restart(char *); extern void au1000_restart(char *);
extern void au1000_halt(void); extern void au1000_halt(void);

View File

@ -31,15 +31,13 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
int prom_argc; #include <asm/addrspace.h>
char **prom_argv, **prom_envp; #include <asm/bootinfo.h>
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname); #include <prom.h>
const char *get_system_type(void) const char *get_system_type(void)
{ {

View File

@ -34,13 +34,11 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <asm/addrspace.h> #include <asm/addrspace.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
int prom_argc; #include <prom.h>
char **prom_argv, **prom_envp;
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname);
const char *get_system_type(void) const char *get_system_type(void)
{ {

View File

@ -30,15 +30,13 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
int prom_argc; #include <asm/addrspace.h>
char **prom_argv, **prom_envp; #include <asm/bootinfo.h>
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname); #include <prom.h>
const char *get_system_type(void) const char *get_system_type(void)
{ {

View File

@ -31,15 +31,13 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
int prom_argc; #include <asm/addrspace.h>
char **prom_argv, **prom_envp; #include <asm/bootinfo.h>
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname); #include <prom.h>
const char *get_system_type(void) const char *get_system_type(void)
{ {

View File

@ -41,8 +41,10 @@
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
#include <asm/reboot.h> #include <asm/reboot.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h> #include <au1000.h>
#include <au1xxx_dbdma.h>
#include <prom.h>
#ifdef CONFIG_MIPS_PB1200 #ifdef CONFIG_MIPS_PB1200
#include <asm/mach-pb1x00/pb1200.h> #include <asm/mach-pb1x00/pb1200.h>

View File

@ -31,15 +31,13 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
int prom_argc; #include <asm/addrspace.h>
char **prom_argv, **prom_envp; #include <asm/bootinfo.h>
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname); #include <prom.h>
const char *get_system_type(void) const char *get_system_type(void)
{ {

View File

@ -31,15 +31,13 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
int prom_argc; #include <asm/addrspace.h>
char **prom_argv, **prom_envp; #include <asm/bootinfo.h>
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname); #include <prom.h>
const char *get_system_type(void) const char *get_system_type(void)
{ {

View File

@ -31,15 +31,13 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
int prom_argc; #include <asm/addrspace.h>
char **prom_argv, **prom_envp; #include <asm/bootinfo.h>
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname); #include <prom.h>
const char *get_system_type(void) const char *get_system_type(void)
{ {

View File

@ -30,15 +30,13 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
int prom_argc; #include <asm/addrspace.h>
char **prom_argv, **prom_envp; #include <asm/bootinfo.h>
extern void __init prom_init_cmdline(void);
extern char *prom_getenv(char *envname); #include <prom.h>
const char *get_system_type(void) const char *get_system_type(void)
{ {

View File

@ -77,12 +77,7 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
{ {
pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
dcr_write(msic->dcr_host, msic->dcr_host.base + dcr_n, val); dcr_write(msic->dcr_host, dcr_n, val);
}
static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n)
{
return dcr_read(msic->dcr_host, msic->dcr_host.base + dcr_n);
} }
static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
@ -91,7 +86,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
u32 write_offset, msi; u32 write_offset, msi;
int idx; int idx;
write_offset = msic_dcr_read(msic, MSIC_WRITE_OFFSET_REG); write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
pr_debug("axon_msi: original write_offset 0x%x\n", write_offset); pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
/* write_offset doesn't wrap properly, so we have to mask it */ /* write_offset doesn't wrap properly, so we have to mask it */
@ -306,7 +301,7 @@ static int axon_msi_notify_reboot(struct notifier_block *nb,
list_for_each_entry(msic, &axon_msic_list, list) { list_for_each_entry(msic, &axon_msic_list, list) {
pr_debug("axon_msi: disabling %s\n", pr_debug("axon_msi: disabling %s\n",
msic->irq_host->of_node->full_name); msic->irq_host->of_node->full_name);
tmp = msic_dcr_read(msic, MSIC_CTRL_REG); tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
msic_dcr_write(msic, MSIC_CTRL_REG, tmp); msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
} }

View File

@ -126,13 +126,13 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
} }
EXPORT_SYMBOL_GPL(dcr_map); EXPORT_SYMBOL_GPL(dcr_map);
void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c) void dcr_unmap(dcr_host_t host, unsigned int dcr_c)
{ {
dcr_host_t h = host; dcr_host_t h = host;
if (h.token == NULL) if (h.token == NULL)
return; return;
h.token += dcr_n * h.stride; h.token += host.base * h.stride;
iounmap(h.token); iounmap(h.token);
h.token = NULL; h.token = NULL;
} }

View File

@ -156,7 +156,7 @@ static inline u32 _mpic_read(enum mpic_reg_type type,
switch(type) { switch(type) {
#ifdef CONFIG_PPC_DCR #ifdef CONFIG_PPC_DCR
case mpic_access_dcr: case mpic_access_dcr:
return dcr_read(rb->dhost, rb->dhost.base + reg); return dcr_read(rb->dhost, reg);
#endif #endif
case mpic_access_mmio_be: case mpic_access_mmio_be:
return in_be32(rb->base + (reg >> 2)); return in_be32(rb->base + (reg >> 2));
@ -173,7 +173,7 @@ static inline void _mpic_write(enum mpic_reg_type type,
switch(type) { switch(type) {
#ifdef CONFIG_PPC_DCR #ifdef CONFIG_PPC_DCR
case mpic_access_dcr: case mpic_access_dcr:
return dcr_write(rb->dhost, rb->dhost.base + reg, value); return dcr_write(rb->dhost, reg, value);
#endif #endif
case mpic_access_mmio_be: case mpic_access_mmio_be:
return out_be32(rb->base + (reg >> 2), value); return out_be32(rb->base + (reg >> 2), value);

View File

@ -349,6 +349,7 @@ struct ipoib_neigh {
struct sk_buff_head queue; struct sk_buff_head queue;
struct neighbour *neighbour; struct neighbour *neighbour;
struct net_device *dev;
struct list_head list; struct list_head list;
}; };
@ -365,7 +366,8 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh)
INFINIBAND_ALEN, sizeof(void *)); INFINIBAND_ALEN, sizeof(void *));
} }
struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh); struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh,
struct net_device *dev);
void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh); void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh);
extern struct workqueue_struct *ipoib_workqueue; extern struct workqueue_struct *ipoib_workqueue;

View File

@ -517,7 +517,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
struct ipoib_path *path; struct ipoib_path *path;
struct ipoib_neigh *neigh; struct ipoib_neigh *neigh;
neigh = ipoib_neigh_alloc(skb->dst->neighbour); neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
if (!neigh) { if (!neigh) {
++dev->stats.tx_dropped; ++dev->stats.tx_dropped;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
@ -692,9 +692,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
goto out; goto out;
} }
} else if (neigh->ah) { } else if (neigh->ah) {
if (unlikely(memcmp(&neigh->dgid.raw, if (unlikely((memcmp(&neigh->dgid.raw,
skb->dst->neighbour->ha + 4, skb->dst->neighbour->ha + 4,
sizeof(union ib_gid)))) { sizeof(union ib_gid))) ||
(neigh->dev != dev))) {
spin_lock(&priv->lock); spin_lock(&priv->lock);
/* /*
* It's safe to call ipoib_put_ah() inside * It's safe to call ipoib_put_ah() inside
@ -817,6 +818,13 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
unsigned long flags; unsigned long flags;
struct ipoib_ah *ah = NULL; struct ipoib_ah *ah = NULL;
neigh = *to_ipoib_neigh(n);
if (neigh) {
priv = netdev_priv(neigh->dev);
ipoib_dbg(priv, "neigh_destructor for bonding device: %s\n",
n->dev->name);
} else
return;
ipoib_dbg(priv, ipoib_dbg(priv,
"neigh_cleanup for %06x " IPOIB_GID_FMT "\n", "neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
IPOIB_QPN(n->ha), IPOIB_QPN(n->ha),
@ -824,13 +832,10 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
neigh = *to_ipoib_neigh(n); if (neigh->ah)
if (neigh) { ah = neigh->ah;
if (neigh->ah) list_del(&neigh->list);
ah = neigh->ah; ipoib_neigh_free(n->dev, neigh);
list_del(&neigh->list);
ipoib_neigh_free(n->dev, neigh);
}
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
@ -838,7 +843,8 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
ipoib_put_ah(ah); ipoib_put_ah(ah);
} }
struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour) struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour,
struct net_device *dev)
{ {
struct ipoib_neigh *neigh; struct ipoib_neigh *neigh;
@ -847,6 +853,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
return NULL; return NULL;
neigh->neighbour = neighbour; neigh->neighbour = neighbour;
neigh->dev = dev;
*to_ipoib_neigh(neighbour) = neigh; *to_ipoib_neigh(neighbour) = neigh;
skb_queue_head_init(&neigh->queue); skb_queue_head_init(&neigh->queue);
ipoib_cm_set(neigh, NULL); ipoib_cm_set(neigh, NULL);

View File

@ -705,7 +705,8 @@ out:
if (skb->dst && if (skb->dst &&
skb->dst->neighbour && skb->dst->neighbour &&
!*to_ipoib_neigh(skb->dst->neighbour)) { !*to_ipoib_neigh(skb->dst->neighbour)) {
struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour); struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour,
skb->dev);
if (neigh) { if (neigh) {
kref_get(&mcast->ah->ref); kref_get(&mcast->ah->ref);

View File

@ -1780,6 +1780,15 @@ config SC92031
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called sc92031. This is recommended. will be called sc92031. This is recommended.
config CPMAC
tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
depends on NET_ETHERNET && EXPERIMENTAL && AR7
select PHYLIB
select FIXED_PHY
select FIXED_MII_100_FDX
help
TI AR7 CPMAC Ethernet support
config NET_POCKET config NET_POCKET
bool "Pocket and portable adapters" bool "Pocket and portable adapters"
depends on PARPORT depends on PARPORT

View File

@ -159,6 +159,7 @@ obj-$(CONFIG_8139CP) += 8139cp.o
obj-$(CONFIG_8139TOO) += 8139too.o obj-$(CONFIG_8139TOO) += 8139too.o
obj-$(CONFIG_ZNET) += znet.o obj-$(CONFIG_ZNET) += znet.o
obj-$(CONFIG_LAN_SAA9730) += saa9730.o obj-$(CONFIG_LAN_SAA9730) += saa9730.o
obj-$(CONFIG_CPMAC) += cpmac.o
obj-$(CONFIG_DEPCA) += depca.o obj-$(CONFIG_DEPCA) += depca.o
obj-$(CONFIG_EWRK3) += ewrk3.o obj-$(CONFIG_EWRK3) += ewrk3.o
obj-$(CONFIG_ATP) += atp.o obj-$(CONFIG_ATP) += atp.o

View File

@ -54,13 +54,16 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <asm/cpu.h>
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/mach-au1x00/au1000.h> #include <au1000.h>
#include <asm/cpu.h> #include <prom.h>
#include "au1000_eth.h" #include "au1000_eth.h"
#ifdef AU1000_ETH_DEBUG #ifdef AU1000_ETH_DEBUG
@ -96,11 +99,6 @@ static void mdio_write(struct net_device *, int, int, u16);
static void au1000_adjust_link(struct net_device *); static void au1000_adjust_link(struct net_device *);
static void enable_mac(struct net_device *, int); static void enable_mac(struct net_device *, int);
// externs
extern int get_ethernet_addr(char *ethernet_addr);
extern void str2eaddr(unsigned char *ea, unsigned char *str);
extern char * prom_getcmdline(void);
/* /*
* Theory of operation * Theory of operation
* *
@ -619,7 +617,6 @@ static struct net_device * au1000_probe(int port_num)
struct au1000_private *aup = NULL; struct au1000_private *aup = NULL;
struct net_device *dev = NULL; struct net_device *dev = NULL;
db_dest_t *pDB, *pDBfree; db_dest_t *pDB, *pDBfree;
char *pmac, *argptr;
char ethaddr[6]; char ethaddr[6];
int irq, i, err; int irq, i, err;
u32 base, macen; u32 base, macen;
@ -677,21 +674,12 @@ static struct net_device * au1000_probe(int port_num)
au_macs[port_num] = aup; au_macs[port_num] = aup;
if (port_num == 0) { if (port_num == 0) {
/* Check the environment variables first */ if (prom_get_ethernet_addr(ethaddr) == 0)
if (get_ethernet_addr(ethaddr) == 0)
memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
else { else {
/* Check command line */ printk(KERN_INFO "%s: No MAC address found\n",
argptr = prom_getcmdline(); dev->name);
if ((pmac = strstr(argptr, "ethaddr=")) == NULL)
printk(KERN_INFO "%s: No MAC address found\n",
dev->name);
/* Use the hard coded MAC addresses */ /* Use the hard coded MAC addresses */
else {
str2eaddr(ethaddr, pmac + strlen("ethaddr="));
memcpy(au1000_mac_addr, ethaddr,
sizeof(au1000_mac_addr));
}
} }
setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);

View File

@ -98,6 +98,7 @@ static char *xmit_hash_policy = NULL;
static int arp_interval = BOND_LINK_ARP_INTERV; static int arp_interval = BOND_LINK_ARP_INTERV;
static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
static char *arp_validate = NULL; static char *arp_validate = NULL;
static int fail_over_mac = 0;
struct bond_params bonding_defaults; struct bond_params bonding_defaults;
module_param(max_bonds, int, 0); module_param(max_bonds, int, 0);
@ -131,6 +132,8 @@ module_param_array(arp_ip_target, charp, NULL, 0);
MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
module_param(arp_validate, charp, 0); module_param(arp_validate, charp, 0);
MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all"); MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
module_param(fail_over_mac, int, 0);
MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC. 0 of off (default), 1 for on.");
/*----------------------------- Global variables ----------------------------*/ /*----------------------------- Global variables ----------------------------*/
@ -1096,7 +1099,21 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
if (new_active) { if (new_active) {
bond_set_slave_active_flags(new_active); bond_set_slave_active_flags(new_active);
} }
bond_send_gratuitous_arp(bond);
/* when bonding does not set the slave MAC address, the bond MAC
* address is the one of the active slave.
*/
if (new_active && bond->params.fail_over_mac)
memcpy(bond->dev->dev_addr, new_active->dev->dev_addr,
new_active->dev->addr_len);
if (bond->curr_active_slave &&
test_bit(__LINK_STATE_LINKWATCH_PENDING,
&bond->curr_active_slave->dev->state)) {
dprintk("delaying gratuitous arp on %s\n",
bond->curr_active_slave->dev->name);
bond->send_grat_arp = 1;
} else
bond_send_gratuitous_arp(bond);
} }
} }
@ -1217,7 +1234,8 @@ static int bond_compute_features(struct bonding *bond)
struct slave *slave; struct slave *slave;
struct net_device *bond_dev = bond->dev; struct net_device *bond_dev = bond->dev;
unsigned long features = bond_dev->features; unsigned long features = bond_dev->features;
unsigned short max_hard_header_len = ETH_HLEN; unsigned short max_hard_header_len = max((u16)ETH_HLEN,
bond_dev->hard_header_len);
int i; int i;
features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES); features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES);
@ -1238,6 +1256,23 @@ static int bond_compute_features(struct bonding *bond)
return 0; return 0;
} }
static void bond_setup_by_slave(struct net_device *bond_dev,
struct net_device *slave_dev)
{
struct bonding *bond = bond_dev->priv;
bond_dev->neigh_setup = slave_dev->neigh_setup;
bond_dev->type = slave_dev->type;
bond_dev->hard_header_len = slave_dev->hard_header_len;
bond_dev->addr_len = slave_dev->addr_len;
memcpy(bond_dev->broadcast, slave_dev->broadcast,
slave_dev->addr_len);
bond->setup_by_slave = 1;
}
/* enslave device <slave> to bond device <master> */ /* enslave device <slave> to bond device <master> */
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{ {
@ -1258,8 +1293,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* bond must be initialized by bond_open() before enslaving */ /* bond must be initialized by bond_open() before enslaving */
if (!(bond_dev->flags & IFF_UP)) { if (!(bond_dev->flags & IFF_UP)) {
dprintk("Error, master_dev is not up\n"); printk(KERN_WARNING DRV_NAME
return -EPERM; " %s: master_dev is not up in bond_enslave\n",
bond_dev->name);
} }
/* already enslaved */ /* already enslaved */
@ -1312,14 +1348,42 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_undo_flags; goto err_undo_flags;
} }
/* set bonding device ether type by slave - bonding netdevices are
* created with ether_setup, so when the slave type is not ARPHRD_ETHER
* there is a need to override some of the type dependent attribs/funcs.
*
* bond ether type mutual exclusion - don't allow slaves of dissimilar
* ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond
*/
if (bond->slave_cnt == 0) {
if (slave_dev->type != ARPHRD_ETHER)
bond_setup_by_slave(bond_dev, slave_dev);
} else if (bond_dev->type != slave_dev->type) {
printk(KERN_ERR DRV_NAME ": %s ether type (%d) is different "
"from other slaves (%d), can not enslave it.\n",
slave_dev->name,
slave_dev->type, bond_dev->type);
res = -EINVAL;
goto err_undo_flags;
}
if (slave_dev->set_mac_address == NULL) { if (slave_dev->set_mac_address == NULL) {
printk(KERN_ERR DRV_NAME if (bond->slave_cnt == 0) {
": %s: Error: The slave device you specified does " printk(KERN_WARNING DRV_NAME
"not support setting the MAC address. " ": %s: Warning: The first slave device "
"Your kernel likely does not support slave " "specified does not support setting the MAC "
"devices.\n", bond_dev->name); "address. Enabling the fail_over_mac option.",
res = -EOPNOTSUPP; bond_dev->name);
goto err_undo_flags; bond->params.fail_over_mac = 1;
} else if (!bond->params.fail_over_mac) {
printk(KERN_ERR DRV_NAME
": %s: Error: The slave device specified "
"does not support setting the MAC address, "
"but fail_over_mac is not enabled.\n"
, bond_dev->name);
res = -EOPNOTSUPP;
goto err_undo_flags;
}
} }
new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
@ -1340,16 +1404,18 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
*/ */
memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
/* if (!bond->params.fail_over_mac) {
* Set slave to master's mac address. The application already /*
* set the master's mac address to that of the first slave * Set slave to master's mac address. The application already
*/ * set the master's mac address to that of the first slave
memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len); */
addr.sa_family = slave_dev->type; memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
res = dev_set_mac_address(slave_dev, &addr); addr.sa_family = slave_dev->type;
if (res) { res = dev_set_mac_address(slave_dev, &addr);
dprintk("Error %d calling set_mac_address\n", res); if (res) {
goto err_free; dprintk("Error %d calling set_mac_address\n", res);
goto err_free;
}
} }
res = netdev_set_master(slave_dev, bond_dev); res = netdev_set_master(slave_dev, bond_dev);
@ -1574,9 +1640,11 @@ err_close:
dev_close(slave_dev); dev_close(slave_dev);
err_restore_mac: err_restore_mac:
memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN); if (!bond->params.fail_over_mac) {
addr.sa_family = slave_dev->type; memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
dev_set_mac_address(slave_dev, &addr); addr.sa_family = slave_dev->type;
dev_set_mac_address(slave_dev, &addr);
}
err_free: err_free:
kfree(new_slave); kfree(new_slave);
@ -1749,10 +1817,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
/* close slave before restoring its mac address */ /* close slave before restoring its mac address */
dev_close(slave_dev); dev_close(slave_dev);
/* restore original ("permanent") mac address */ if (!bond->params.fail_over_mac) {
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); /* restore original ("permanent") mac address */
addr.sa_family = slave_dev->type; memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
dev_set_mac_address(slave_dev, &addr); addr.sa_family = slave_dev->type;
dev_set_mac_address(slave_dev, &addr);
}
slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
IFF_SLAVE_INACTIVE | IFF_BONDING | IFF_SLAVE_INACTIVE | IFF_BONDING |
@ -1763,6 +1833,35 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
return 0; /* deletion OK */ return 0; /* deletion OK */
} }
/*
* Destroy a bonding device.
* Must be under rtnl_lock when this function is called.
*/
void bond_destroy(struct bonding *bond)
{
bond_deinit(bond->dev);
bond_destroy_sysfs_entry(bond);
unregister_netdevice(bond->dev);
}
/*
* First release a slave and than destroy the bond if no more slaves iare left.
* Must be under rtnl_lock when this function is called.
*/
int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev)
{
struct bonding *bond = bond_dev->priv;
int ret;
ret = bond_release(bond_dev, slave_dev);
if ((ret == 0) && (bond->slave_cnt == 0)) {
printk(KERN_INFO DRV_NAME ": %s: destroying bond %s.\n",
bond_dev->name, bond_dev->name);
bond_destroy(bond);
}
return ret;
}
/* /*
* This function releases all slaves. * This function releases all slaves.
*/ */
@ -1839,10 +1938,12 @@ static int bond_release_all(struct net_device *bond_dev)
/* close slave before restoring its mac address */ /* close slave before restoring its mac address */
dev_close(slave_dev); dev_close(slave_dev);
/* restore original ("permanent") mac address*/ if (!bond->params.fail_over_mac) {
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); /* restore original ("permanent") mac address*/
addr.sa_family = slave_dev->type; memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
dev_set_mac_address(slave_dev, &addr); addr.sa_family = slave_dev->type;
dev_set_mac_address(slave_dev, &addr);
}
slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
IFF_SLAVE_INACTIVE); IFF_SLAVE_INACTIVE);
@ -2013,6 +2114,17 @@ void bond_mii_monitor(struct net_device *bond_dev)
* program could monitor the link itself if needed. * program could monitor the link itself if needed.
*/ */
if (bond->send_grat_arp) {
if (bond->curr_active_slave && test_bit(__LINK_STATE_LINKWATCH_PENDING,
&bond->curr_active_slave->dev->state))
dprintk("Needs to send gratuitous arp but not yet\n");
else {
dprintk("sending delayed gratuitous arp on on %s\n",
bond->curr_active_slave->dev->name);
bond_send_gratuitous_arp(bond);
bond->send_grat_arp = 0;
}
}
read_lock(&bond->curr_slave_lock); read_lock(&bond->curr_slave_lock);
oldcurrent = bond->curr_active_slave; oldcurrent = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock); read_unlock(&bond->curr_slave_lock);
@ -2414,7 +2526,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
if (bond->master_ip) { if (bond->master_ip) {
bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip, bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip,
bond->master_ip, 0); bond->master_ip, 0);
} }
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
@ -2951,9 +3063,15 @@ static void bond_info_show_master(struct seq_file *seq)
curr = bond->curr_active_slave; curr = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock); read_unlock(&bond->curr_slave_lock);
seq_printf(seq, "Bonding Mode: %s\n", seq_printf(seq, "Bonding Mode: %s",
bond_mode_name(bond->params.mode)); bond_mode_name(bond->params.mode));
if (bond->params.mode == BOND_MODE_ACTIVEBACKUP &&
bond->params.fail_over_mac)
seq_printf(seq, " (fail_over_mac)");
seq_printf(seq, "\n");
if (bond->params.mode == BOND_MODE_XOR || if (bond->params.mode == BOND_MODE_XOR ||
bond->params.mode == BOND_MODE_8023AD) { bond->params.mode == BOND_MODE_8023AD) {
seq_printf(seq, "Transmit Hash Policy: %s (%d)\n", seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
@ -3248,6 +3366,11 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
* ... Or is it this? * ... Or is it this?
*/ */
break; break;
case NETDEV_GOING_DOWN:
dprintk("slave %s is going down\n", slave_dev->name);
if (bond->setup_by_slave)
bond_release_and_destroy(bond_dev, slave_dev);
break;
case NETDEV_CHANGEMTU: case NETDEV_CHANGEMTU:
/* /*
* TODO: Should slaves be allowed to * TODO: Should slaves be allowed to
@ -3880,6 +4003,13 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None")); dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None"));
/*
* If fail_over_mac is enabled, do nothing and return success.
* Returning an error causes ifenslave to fail.
*/
if (bond->params.fail_over_mac)
return 0;
if (!is_valid_ether_addr(sa->sa_data)) { if (!is_valid_ether_addr(sa->sa_data)) {
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
} }
@ -4217,6 +4347,8 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
bond->current_arp_slave = NULL; bond->current_arp_slave = NULL;
bond->primary_slave = NULL; bond->primary_slave = NULL;
bond->dev = bond_dev; bond->dev = bond_dev;
bond->send_grat_arp = 0;
bond->setup_by_slave = 0;
INIT_LIST_HEAD(&bond->vlan_list); INIT_LIST_HEAD(&bond->vlan_list);
/* Initialize the device entry points */ /* Initialize the device entry points */
@ -4265,7 +4397,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond); bond_create_proc_entry(bond);
#endif #endif
list_add_tail(&bond->bond_list, &bond_dev_list); list_add_tail(&bond->bond_list, &bond_dev_list);
return 0; return 0;
@ -4599,6 +4730,11 @@ static int bond_check_params(struct bond_params *params)
primary = NULL; primary = NULL;
} }
if (fail_over_mac && (bond_mode != BOND_MODE_ACTIVEBACKUP))
printk(KERN_WARNING DRV_NAME
": Warning: fail_over_mac only affects "
"active-backup mode.\n");
/* fill params struct with the proper values */ /* fill params struct with the proper values */
params->mode = bond_mode; params->mode = bond_mode;
params->xmit_policy = xmit_hashtype; params->xmit_policy = xmit_hashtype;
@ -4610,6 +4746,7 @@ static int bond_check_params(struct bond_params *params)
params->use_carrier = use_carrier; params->use_carrier = use_carrier;
params->lacp_fast = lacp_fast; params->lacp_fast = lacp_fast;
params->primary[0] = 0; params->primary[0] = 0;
params->fail_over_mac = fail_over_mac;
if (primary) { if (primary) {
strncpy(params->primary, primary, IFNAMSIZ); strncpy(params->primary, primary, IFNAMSIZ);

View File

@ -164,9 +164,7 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t
printk(KERN_INFO DRV_NAME printk(KERN_INFO DRV_NAME
": %s is being deleted...\n", ": %s is being deleted...\n",
bond->dev->name); bond->dev->name);
bond_deinit(bond->dev); bond_destroy(bond);
bond_destroy_sysfs_entry(bond);
unregister_netdevice(bond->dev);
rtnl_unlock(); rtnl_unlock();
goto out; goto out;
} }
@ -260,17 +258,16 @@ static ssize_t bonding_store_slaves(struct device *d,
char command[IFNAMSIZ + 1] = { 0, }; char command[IFNAMSIZ + 1] = { 0, };
char *ifname; char *ifname;
int i, res, found, ret = count; int i, res, found, ret = count;
u32 original_mtu;
struct slave *slave; struct slave *slave;
struct net_device *dev = NULL; struct net_device *dev = NULL;
struct bonding *bond = to_bond(d); struct bonding *bond = to_bond(d);
/* Quick sanity check -- is the bond interface up? */ /* Quick sanity check -- is the bond interface up? */
if (!(bond->dev->flags & IFF_UP)) { if (!(bond->dev->flags & IFF_UP)) {
printk(KERN_ERR DRV_NAME printk(KERN_WARNING DRV_NAME
": %s: Unable to update slaves because interface is down.\n", ": %s: doing slave updates when interface is down.\n",
bond->dev->name); bond->dev->name);
ret = -EPERM;
goto out;
} }
/* Note: We can't hold bond->lock here, as bond_create grabs it. */ /* Note: We can't hold bond->lock here, as bond_create grabs it. */
@ -327,6 +324,7 @@ static ssize_t bonding_store_slaves(struct device *d,
} }
/* Set the slave's MTU to match the bond */ /* Set the slave's MTU to match the bond */
original_mtu = dev->mtu;
if (dev->mtu != bond->dev->mtu) { if (dev->mtu != bond->dev->mtu) {
if (dev->change_mtu) { if (dev->change_mtu) {
res = dev->change_mtu(dev, res = dev->change_mtu(dev,
@ -341,6 +339,9 @@ static ssize_t bonding_store_slaves(struct device *d,
} }
rtnl_lock(); rtnl_lock();
res = bond_enslave(bond->dev, dev); res = bond_enslave(bond->dev, dev);
bond_for_each_slave(bond, slave, i)
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0)
slave->original_mtu = original_mtu;
rtnl_unlock(); rtnl_unlock();
if (res) { if (res) {
ret = res; ret = res;
@ -353,13 +354,17 @@ static ssize_t bonding_store_slaves(struct device *d,
bond_for_each_slave(bond, slave, i) bond_for_each_slave(bond, slave, i)
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
dev = slave->dev; dev = slave->dev;
original_mtu = slave->original_mtu;
break; break;
} }
if (dev) { if (dev) {
printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n", printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n",
bond->dev->name, dev->name); bond->dev->name, dev->name);
rtnl_lock(); rtnl_lock();
res = bond_release(bond->dev, dev); if (bond->setup_by_slave)
res = bond_release_and_destroy(bond->dev, dev);
else
res = bond_release(bond->dev, dev);
rtnl_unlock(); rtnl_unlock();
if (res) { if (res) {
ret = res; ret = res;
@ -367,9 +372,9 @@ static ssize_t bonding_store_slaves(struct device *d,
} }
/* set the slave MTU to the default */ /* set the slave MTU to the default */
if (dev->change_mtu) { if (dev->change_mtu) {
dev->change_mtu(dev, 1500); dev->change_mtu(dev, original_mtu);
} else { } else {
dev->mtu = 1500; dev->mtu = original_mtu;
} }
} }
else { else {
@ -562,6 +567,54 @@ static ssize_t bonding_store_arp_validate(struct device *d,
static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
/*
* Show and store fail_over_mac. User only allowed to change the
* value when there are no slaves.
*/
static ssize_t bonding_show_fail_over_mac(struct device *d, struct device_attribute *attr, char *buf)
{
struct bonding *bond = to_bond(d);
return sprintf(buf, "%d\n", bond->params.fail_over_mac) + 1;
}
static ssize_t bonding_store_fail_over_mac(struct device *d, struct device_attribute *attr, const char *buf, size_t count)
{
int new_value;
int ret = count;
struct bonding *bond = to_bond(d);
if (bond->slave_cnt != 0) {
printk(KERN_ERR DRV_NAME
": %s: Can't alter fail_over_mac with slaves in bond.\n",
bond->dev->name);
ret = -EPERM;
goto out;
}
if (sscanf(buf, "%d", &new_value) != 1) {
printk(KERN_ERR DRV_NAME
": %s: no fail_over_mac value specified.\n",
bond->dev->name);
ret = -EINVAL;
goto out;
}
if ((new_value == 0) || (new_value == 1)) {
bond->params.fail_over_mac = new_value;
printk(KERN_INFO DRV_NAME ": %s: Setting fail_over_mac to %d.\n",
bond->dev->name, new_value);
} else {
printk(KERN_INFO DRV_NAME
": %s: Ignoring invalid fail_over_mac value %d.\n",
bond->dev->name, new_value);
}
out:
return ret;
}
static DEVICE_ATTR(fail_over_mac, S_IRUGO | S_IWUSR, bonding_show_fail_over_mac, bonding_store_fail_over_mac);
/* /*
* Show and set the arp timer interval. There are two tricky bits * Show and set the arp timer interval. There are two tricky bits
* here. First, if ARP monitoring is activated, then we must disable * here. First, if ARP monitoring is activated, then we must disable
@ -1383,6 +1436,7 @@ static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
static struct attribute *per_bond_attrs[] = { static struct attribute *per_bond_attrs[] = {
&dev_attr_slaves.attr, &dev_attr_slaves.attr,
&dev_attr_mode.attr, &dev_attr_mode.attr,
&dev_attr_fail_over_mac.attr,
&dev_attr_arp_validate.attr, &dev_attr_arp_validate.attr,
&dev_attr_arp_interval.attr, &dev_attr_arp_interval.attr,
&dev_attr_arp_ip_target.attr, &dev_attr_arp_ip_target.attr,

View File

@ -22,8 +22,8 @@
#include "bond_3ad.h" #include "bond_3ad.h"
#include "bond_alb.h" #include "bond_alb.h"
#define DRV_VERSION "3.1.3" #define DRV_VERSION "3.2.0"
#define DRV_RELDATE "June 13, 2007" #define DRV_RELDATE "September 13, 2007"
#define DRV_NAME "bonding" #define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
@ -128,6 +128,7 @@ struct bond_params {
int arp_interval; int arp_interval;
int arp_validate; int arp_validate;
int use_carrier; int use_carrier;
int fail_over_mac;
int updelay; int updelay;
int downdelay; int downdelay;
int lacp_fast; int lacp_fast;
@ -156,6 +157,7 @@ struct slave {
s8 link; /* one of BOND_LINK_XXXX */ s8 link; /* one of BOND_LINK_XXXX */
s8 state; /* one of BOND_STATE_XXXX */ s8 state; /* one of BOND_STATE_XXXX */
u32 original_flags; u32 original_flags;
u32 original_mtu;
u32 link_failure_count; u32 link_failure_count;
u16 speed; u16 speed;
u8 duplex; u8 duplex;
@ -185,6 +187,8 @@ struct bonding {
struct timer_list mii_timer; struct timer_list mii_timer;
struct timer_list arp_timer; struct timer_list arp_timer;
s8 kill_timers; s8 kill_timers;
s8 send_grat_arp;
s8 setup_by_slave;
struct net_device_stats stats; struct net_device_stats stats;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry; struct proc_dir_entry *proc_entry;
@ -292,6 +296,8 @@ static inline void bond_unset_master_alb_flags(struct bonding *bond)
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(char *name, struct bond_params *params, struct bonding **newbond); int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
void bond_destroy(struct bonding *bond);
int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev);
void bond_deinit(struct net_device *bond_dev); void bond_deinit(struct net_device *bond_dev);
int bond_create_sysfs(void); int bond_create_sysfs(void);
void bond_destroy_sysfs(void); void bond_destroy_sysfs(void);

View File

@ -4443,7 +4443,7 @@ static struct {
{REG_MAC_COLL_EXCESS}, {REG_MAC_COLL_EXCESS},
{REG_MAC_COLL_LATE} {REG_MAC_COLL_LATE}
}; };
#define CAS_REG_LEN (sizeof(ethtool_register_table)/sizeof(int)) #define CAS_REG_LEN ARRAY_SIZE(ethtool_register_table)
#define CAS_MAX_REGS (sizeof (u32)*CAS_REG_LEN) #define CAS_MAX_REGS (sizeof (u32)*CAS_REG_LEN)
static void cas_read_regs(struct cas *cp, u8 *ptr, int len) static void cas_read_regs(struct cas *cp, u8 *ptr, int len)

1174
drivers/net/cpmac.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -168,7 +168,6 @@ static int gfar_probe(struct platform_device *pdev)
struct gfar_private *priv = NULL; struct gfar_private *priv = NULL;
struct gianfar_platform_data *einfo; struct gianfar_platform_data *einfo;
struct resource *r; struct resource *r;
int idx;
int err = 0; int err = 0;
DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac);
@ -261,7 +260,9 @@ static int gfar_probe(struct platform_device *pdev)
dev->hard_start_xmit = gfar_start_xmit; dev->hard_start_xmit = gfar_start_xmit;
dev->tx_timeout = gfar_timeout; dev->tx_timeout = gfar_timeout;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
#ifdef CONFIG_GFAR_NAPI
netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT); netif_napi_add(dev, &priv->napi, gfar_poll, GFAR_DEV_WEIGHT);
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = gfar_netpoll; dev->poll_controller = gfar_netpoll;
#endif #endif
@ -931,9 +932,14 @@ tx_skb_fail:
/* Returns 0 for success. */ /* Returns 0 for success. */
static int gfar_enet_open(struct net_device *dev) static int gfar_enet_open(struct net_device *dev)
{ {
#ifdef CONFIG_GFAR_NAPI
struct gfar_private *priv = netdev_priv(dev);
#endif
int err; int err;
#ifdef CONFIG_GFAR_NAPI
napi_enable(&priv->napi); napi_enable(&priv->napi);
#endif
/* Initialize a bunch of registers */ /* Initialize a bunch of registers */
init_registers(dev); init_registers(dev);
@ -943,13 +949,17 @@ static int gfar_enet_open(struct net_device *dev)
err = init_phy(dev); err = init_phy(dev);
if(err) { if(err) {
#ifdef CONFIG_GFAR_NAPI
napi_disable(&priv->napi); napi_disable(&priv->napi);
#endif
return err; return err;
} }
err = startup_gfar(dev); err = startup_gfar(dev);
if (err) if (err)
#ifdef CONFIG_GFAR_NAPI
napi_disable(&priv->napi); napi_disable(&priv->napi);
#endif
netif_start_queue(dev); netif_start_queue(dev);
@ -1103,7 +1113,9 @@ static int gfar_close(struct net_device *dev)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
#ifdef CONFIG_GFAR_NAPI
napi_disable(&priv->napi); napi_disable(&priv->napi);
#endif
stop_gfar(dev); stop_gfar(dev);

View File

@ -413,7 +413,10 @@ static int __init mal_probe(struct ocp_device *ocpdev)
ocpdev->def->index); ocpdev->def->index);
return -ENOMEM; return -ENOMEM;
} }
mal->dcrbase = maldata->dcr_base;
/* XXX This only works for native dcr for now */
mal->dcrhost = dcr_map(NULL, maldata->dcr_base, 0);
mal->def = ocpdev->def; mal->def = ocpdev->def;
INIT_LIST_HEAD(&mal->poll_list); INIT_LIST_HEAD(&mal->poll_list);

View File

@ -191,7 +191,6 @@ struct mal_commac {
}; };
struct ibm_ocp_mal { struct ibm_ocp_mal {
int dcrbase;
dcr_host_t dcrhost; dcr_host_t dcrhost;
struct list_head poll_list; struct list_head poll_list;
@ -209,12 +208,12 @@ struct ibm_ocp_mal {
static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg) static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg)
{ {
return dcr_read(mal->dcrhost, mal->dcrbase + reg); return dcr_read(mal->dcrhost, reg);
} }
static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val) static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val)
{ {
dcr_write(mal->dcrhost, mal->dcrbase + reg, val); dcr_write(mal->dcrhost, reg, val);
} }
/* Register MAL devices */ /* Register MAL devices */

View File

@ -461,6 +461,7 @@ static int __devinit mal_probe(struct of_device *ofdev,
struct mal_instance *mal; struct mal_instance *mal;
int err = 0, i, bd_size; int err = 0, i, bd_size;
int index = mal_count++; int index = mal_count++;
unsigned int dcr_base;
const u32 *prop; const u32 *prop;
u32 cfg; u32 cfg;
@ -497,14 +498,14 @@ static int __devinit mal_probe(struct of_device *ofdev,
} }
mal->num_rx_chans = prop[0]; mal->num_rx_chans = prop[0];
mal->dcr_base = dcr_resource_start(ofdev->node, 0); dcr_base = dcr_resource_start(ofdev->node, 0);
if (mal->dcr_base == 0) { if (dcr_base == 0) {
printk(KERN_ERR printk(KERN_ERR
"mal%d: can't find DCR resource!\n", index); "mal%d: can't find DCR resource!\n", index);
err = -ENODEV; err = -ENODEV;
goto fail; goto fail;
} }
mal->dcr_host = dcr_map(ofdev->node, mal->dcr_base, 0x100); mal->dcr_host = dcr_map(ofdev->node, dcr_base, 0x100);
if (!DCR_MAP_OK(mal->dcr_host)) { if (!DCR_MAP_OK(mal->dcr_host)) {
printk(KERN_ERR printk(KERN_ERR
"mal%d: failed to map DCRs !\n", index); "mal%d: failed to map DCRs !\n", index);
@ -626,7 +627,7 @@ static int __devinit mal_probe(struct of_device *ofdev,
fail2: fail2:
dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma); dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma);
fail_unmap: fail_unmap:
dcr_unmap(mal->dcr_host, mal->dcr_base, 0x100); dcr_unmap(mal->dcr_host, 0x100);
fail: fail:
kfree(mal); kfree(mal);

View File

@ -185,7 +185,6 @@ struct mal_commac {
struct mal_instance { struct mal_instance {
int version; int version;
int dcr_base;
dcr_host_t dcr_host; dcr_host_t dcr_host;
int num_tx_chans; /* Number of TX channels */ int num_tx_chans; /* Number of TX channels */
@ -213,12 +212,12 @@ struct mal_instance {
static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg) static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
{ {
return dcr_read(mal->dcr_host, mal->dcr_base + reg); return dcr_read(mal->dcr_host, reg);
} }
static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val) static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
{ {
dcr_write(mal->dcr_host, mal->dcr_base + reg, val); dcr_write(mal->dcr_host, reg, val);
} }
/* Register MAL devices */ /* Register MAL devices */

View File

@ -840,7 +840,7 @@ toshoboe_probe (struct toshoboe_cb *self)
/* test 1: SIR filter and back to back */ /* test 1: SIR filter and back to back */
for (j = 0; j < (sizeof (bauds) / sizeof (int)); ++j) for (j = 0; j < ARRAY_SIZE(bauds); ++j)
{ {
int fir = (j > 1); int fir = (j > 1);
toshoboe_stopchip (self); toshoboe_stopchip (self);

View File

@ -208,7 +208,6 @@ static int __init jazz_sonic_probe(struct platform_device *pdev)
struct sonic_local *lp; struct sonic_local *lp;
struct resource *res; struct resource *res;
int err = 0; int err = 0;
int i;
DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

View File

@ -7,12 +7,12 @@
#define DEBUG #define DEBUG
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/mips-boards/simint.h> #include <asm/mips-boards/simint.h>
#include "mipsnet.h" /* actual device IO mapping */ #include "mipsnet.h" /* actual device IO mapping */
@ -33,9 +33,8 @@ static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
if (available_len < len) if (available_len < len)
return -EFAULT; return -EFAULT;
for (; len > 0; len--, kdata++) { for (; len > 0; len--, kdata++)
*kdata = inb(mipsnet_reg_address(dev, rxDataBuffer)); *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
}
return inl(mipsnet_reg_address(dev, rxDataCount)); return inl(mipsnet_reg_address(dev, rxDataCount));
} }
@ -47,16 +46,15 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
char *buf_ptr = skb->data; char *buf_ptr = skb->data;
pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n", pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
dev->name, __FUNCTION__, skb->len); dev->name, __FUNCTION__, skb->len);
outl(skb->len, mipsnet_reg_address(dev, txDataCount)); outl(skb->len, mipsnet_reg_address(dev, txDataCount));
pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n", pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
dev->name, __FUNCTION__, skb->len); dev->name, __FUNCTION__, skb->len);
for (; count_to_go; buf_ptr++, count_to_go--) { for (; count_to_go; buf_ptr++, count_to_go--)
outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer)); outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
}
dev->stats.tx_packets++; dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len; dev->stats.tx_bytes += skb->len;
@ -67,7 +65,7 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev) static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
pr_debug("%s:%s(): transmitting %d bytes\n", pr_debug("%s:%s(): transmitting %d bytes\n",
dev->name, __FUNCTION__, skb->len); dev->name, __FUNCTION__, skb->len);
/* Only one packet at a time. Once TXDONE interrupt is serviced, the /* Only one packet at a time. Once TXDONE interrupt is serviced, the
* queue will be restarted. * queue will be restarted.
@ -83,7 +81,8 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
struct sk_buff *skb; struct sk_buff *skb;
size_t len = count; size_t len = count;
if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) { skb = alloc_skb(len + 2, GFP_KERNEL);
if (!skb) {
dev->stats.rx_dropped++; dev->stats.rx_dropped++;
return -ENOMEM; return -ENOMEM;
} }
@ -96,7 +95,7 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
pr_debug("%s:%s(): pushing RXed data to kernel\n", pr_debug("%s:%s(): pushing RXed data to kernel\n",
dev->name, __FUNCTION__); dev->name, __FUNCTION__);
netif_rx(skb); netif_rx(skb);
dev->stats.rx_packets++; dev->stats.rx_packets++;
@ -114,42 +113,44 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
if (irq == dev->irq) { if (irq == dev->irq) {
pr_debug("%s:%s(): irq %d for device\n", pr_debug("%s:%s(): irq %d for device\n",
dev->name, __FUNCTION__, irq); dev->name, __FUNCTION__, irq);
retval = IRQ_HANDLED; retval = IRQ_HANDLED;
interruptFlags = interruptFlags =
inl(mipsnet_reg_address(dev, interruptControl)); inl(mipsnet_reg_address(dev, interruptControl));
pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name, pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
__FUNCTION__, interruptFlags); __FUNCTION__, interruptFlags);
if (interruptFlags & MIPSNET_INTCTL_TXDONE) { if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
pr_debug("%s:%s(): got TXDone\n", pr_debug("%s:%s(): got TXDone\n",
dev->name, __FUNCTION__); dev->name, __FUNCTION__);
outl(MIPSNET_INTCTL_TXDONE, outl(MIPSNET_INTCTL_TXDONE,
mipsnet_reg_address(dev, interruptControl)); mipsnet_reg_address(dev, interruptControl));
// only one packet at a time, we are done. /* only one packet at a time, we are done. */
netif_wake_queue(dev); netif_wake_queue(dev);
} else if (interruptFlags & MIPSNET_INTCTL_RXDONE) { } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
pr_debug("%s:%s(): got RX data\n", pr_debug("%s:%s(): got RX data\n",
dev->name, __FUNCTION__); dev->name, __FUNCTION__);
mipsnet_get_fromdev(dev, mipsnet_get_fromdev(dev,
inl(mipsnet_reg_address(dev, rxDataCount))); inl(mipsnet_reg_address(dev, rxDataCount)));
pr_debug("%s:%s(): clearing RX int\n", pr_debug("%s:%s(): clearing RX int\n",
dev->name, __FUNCTION__); dev->name, __FUNCTION__);
outl(MIPSNET_INTCTL_RXDONE, outl(MIPSNET_INTCTL_RXDONE,
mipsnet_reg_address(dev, interruptControl)); mipsnet_reg_address(dev, interruptControl));
} else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) { } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
pr_debug("%s:%s(): got test interrupt\n", pr_debug("%s:%s(): got test interrupt\n",
dev->name, __FUNCTION__); dev->name, __FUNCTION__);
// TESTBIT is cleared on read. /*
// And takes effect after a write with 0 * TESTBIT is cleared on read.
* And takes effect after a write with 0
*/
outl(0, mipsnet_reg_address(dev, interruptControl)); outl(0, mipsnet_reg_address(dev, interruptControl));
} else { } else {
pr_debug("%s:%s(): no valid fags 0x%016llx\n", pr_debug("%s:%s(): no valid fags 0x%016llx\n",
dev->name, __FUNCTION__, interruptFlags); dev->name, __FUNCTION__, interruptFlags);
// Maybe shared IRQ, just ignore, no clearing. /* Maybe shared IRQ, just ignore, no clearing. */
retval = IRQ_NONE; retval = IRQ_NONE;
} }
@ -159,7 +160,7 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
retval = IRQ_NONE; retval = IRQ_NONE;
} }
return retval; return retval;
} //mipsnet_interrupt() }
static int mipsnet_open(struct net_device *dev) static int mipsnet_open(struct net_device *dev)
{ {
@ -171,18 +172,18 @@ static int mipsnet_open(struct net_device *dev)
if (err) { if (err) {
pr_debug("%s: %s(): can't get irq %d\n", pr_debug("%s: %s(): can't get irq %d\n",
dev->name, __FUNCTION__, dev->irq); dev->name, __FUNCTION__, dev->irq);
release_region(dev->base_addr, MIPSNET_IO_EXTENT); release_region(dev->base_addr, MIPSNET_IO_EXTENT);
return err; return err;
} }
pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n", pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
dev->name, __FUNCTION__, dev->base_addr, dev->irq); dev->name, __FUNCTION__, dev->base_addr, dev->irq);
netif_start_queue(dev); netif_start_queue(dev);
// test interrupt handler /* test interrupt handler */
outl(MIPSNET_INTCTL_TESTBIT, outl(MIPSNET_INTCTL_TESTBIT,
mipsnet_reg_address(dev, interruptControl)); mipsnet_reg_address(dev, interruptControl));
@ -199,8 +200,6 @@ static int mipsnet_close(struct net_device *dev)
static void mipsnet_set_mclist(struct net_device *dev) static void mipsnet_set_mclist(struct net_device *dev)
{ {
// we don't do anything
return;
} }
static int __init mipsnet_probe(struct device *dev) static int __init mipsnet_probe(struct device *dev)
@ -226,13 +225,13 @@ static int __init mipsnet_probe(struct device *dev)
*/ */
netdev->base_addr = 0x4200; netdev->base_addr = 0x4200;
netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 +
inl(mipsnet_reg_address(netdev, interruptInfo)); inl(mipsnet_reg_address(netdev, interruptInfo));
// Get the io region now, get irq on open() /* Get the io region now, get irq on open() */
if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) { if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} " pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
"for dev is not availble.\n", netdev->name, "for dev is not availble.\n", netdev->name,
__FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT); __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
err = -EBUSY; err = -EBUSY;
goto out_free_netdev; goto out_free_netdev;
} }

View File

@ -9,32 +9,34 @@
/* /*
* Id of this Net device, as seen by the core. * Id of this Net device, as seen by the core.
*/ */
#define MIPS_NET_DEV_ID ((uint64_t) \ #define MIPS_NET_DEV_ID ((uint64_t) \
((uint64_t)'M'<< 0)| \ ((uint64_t) 'M' << 0)| \
((uint64_t)'I'<< 8)| \ ((uint64_t) 'I' << 8)| \
((uint64_t)'P'<<16)| \ ((uint64_t) 'P' << 16)| \
((uint64_t)'S'<<24)| \ ((uint64_t) 'S' << 24)| \
((uint64_t)'N'<<32)| \ ((uint64_t) 'N' << 32)| \
((uint64_t)'E'<<40)| \ ((uint64_t) 'E' << 40)| \
((uint64_t)'T'<<48)| \ ((uint64_t) 'T' << 48)| \
((uint64_t)'0'<<56)) ((uint64_t) '0' << 56))
/* /*
* Net status/control block as seen by sw in the core. * Net status/control block as seen by sw in the core.
* (Why not use bit fields? can't be bothered with cross-platform struct * (Why not use bit fields? can't be bothered with cross-platform struct
* packing.) * packing.)
*/ */
typedef struct _net_control_block { struct net_control_block {
/// dev info for probing /*
/// reads as MIPSNET%d where %d is some form of version * dev info for probing
uint64_t devId; /*0x00 */ * reads as MIPSNET%d where %d is some form of version
*/
uint64_t devId; /* 0x00 */
/* /*
* read only busy flag. * read only busy flag.
* Set and cleared by the Net Device to indicate that an rx or a tx * Set and cleared by the Net Device to indicate that an rx or a tx
* is in progress. * is in progress.
*/ */
uint32_t busy; /*0x08 */ uint32_t busy; /* 0x08 */
/* /*
* Set by the Net Device. * Set by the Net Device.
@ -43,16 +45,16 @@ typedef struct _net_control_block {
* rxDataBuffer. The value will decrease till 0 until all the data * rxDataBuffer. The value will decrease till 0 until all the data
* from rxDataBuffer has been read. * from rxDataBuffer has been read.
*/ */
uint32_t rxDataCount; /*0x0c */ uint32_t rxDataCount; /* 0x0c */
#define MIPSNET_MAX_RXTX_DATACOUNT (1<<16) #define MIPSNET_MAX_RXTX_DATACOUNT (1<<16)
/* /*
* Settable from the MIPS core, cleared by the Net Device. * Settable from the MIPS core, cleared by the Net Device. The core
* The core should set the number of bytes it wants to send, * should set the number of bytes it wants to send, then it should
* then it should write those bytes of data to txDataBuffer. * write those bytes of data to txDataBuffer. The device will clear
* The device will clear txDataCount has been processed (not necessarily sent). * txDataCount has been processed (not necessarily sent).
*/ */
uint32_t txDataCount; /*0x10 */ uint32_t txDataCount; /* 0x10 */
/* /*
* Interrupt control * Interrupt control
@ -69,39 +71,42 @@ typedef struct _net_control_block {
* To clear the test interrupt, write 0 to this register. * To clear the test interrupt, write 0 to this register.
*/ */
uint32_t interruptControl; /*0x14 */ uint32_t interruptControl; /*0x14 */
#define MIPSNET_INTCTL_TXDONE ((uint32_t)(1<< 0)) #define MIPSNET_INTCTL_TXDONE ((uint32_t)(1 << 0))
#define MIPSNET_INTCTL_RXDONE ((uint32_t)(1<< 1)) #define MIPSNET_INTCTL_RXDONE ((uint32_t)(1 << 1))
#define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1<<31)) #define MIPSNET_INTCTL_TESTBIT ((uint32_t)(1 << 31))
#define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE|MIPSNET_INTCTL_RXDONE|MIPSNET_INTCTL_TESTBIT) #define MIPSNET_INTCTL_ALLSOURCES (MIPSNET_INTCTL_TXDONE | \
MIPSNET_INTCTL_RXDONE | \
MIPSNET_INTCTL_TESTBIT)
/* /*
* Readonly core-specific interrupt info for the device to signal the core. * Readonly core-specific interrupt info for the device to signal the
* The meaning of the contents of this field might change. * core. The meaning of the contents of this field might change.
*
* TODO: the whole memIntf interrupt scheme is messy: the device should
* have no control what so ever of what VPE/register set is being
* used. The MemIntf should only expose interrupt lines, and
* something in the config should be responsible for the
* line<->core/vpe bindings.
*/ */
/*###\todo: the whole memIntf interrupt scheme is messy: the device should have uint32_t interruptInfo; /* 0x18 */
* no control what so ever of what VPE/register set is being used.
* The MemIntf should only expose interrupt lines, and something in the
* config should be responsible for the line<->core/vpe bindings.
*/
uint32_t interruptInfo; /*0x18 */
/* /*
* This is where the received data is read out. * This is where the received data is read out.
* There is more data to read until rxDataReady is 0. * There is more data to read until rxDataReady is 0.
* Only 1 byte at this regs offset is used. * Only 1 byte at this regs offset is used.
*/ */
uint32_t rxDataBuffer; /*0x1c */ uint32_t rxDataBuffer; /* 0x1c */
/* /*
* This is where the data to transmit is written. * This is where the data to transmit is written. Data should be
* Data should be written for the amount specified in the txDataCount register. * written for the amount specified in the txDataCount register. Only
* Only 1 byte at this regs offset is used. * 1 byte at this regs offset is used.
*/ */
uint32_t txDataBuffer; /*0x20 */ uint32_t txDataBuffer; /* 0x20 */
} MIPS_T_NetControl; };
#define MIPSNET_IO_EXTENT 0x40 /* being generous */ #define MIPSNET_IO_EXTENT 0x40 /* being generous */
#define field_offset(field) ((int)&((MIPS_T_NetControl*)(0))->field) #define field_offset(field) (offsetof(struct net_control_block, field))
#endif /* __MIPSNET_H */ #endif /* __MIPSNET_H */

View File

@ -75,7 +75,7 @@
#include "myri10ge_mcp.h" #include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h" #include "myri10ge_mcp_gen_header.h"
#define MYRI10GE_VERSION_STR "1.3.2-1.269" #define MYRI10GE_VERSION_STR "1.3.2-1.287"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com"); MODULE_AUTHOR("Maintainer: help@myri.com");
@ -214,6 +214,8 @@ struct myri10ge_priv {
unsigned long serial_number; unsigned long serial_number;
int vendor_specific_offset; int vendor_specific_offset;
int fw_multicast_support; int fw_multicast_support;
unsigned long features;
u32 max_tso6;
u32 read_dma; u32 read_dma;
u32 write_dma; u32 write_dma;
u32 read_write_dma; u32 read_write_dma;
@ -311,6 +313,7 @@ MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");
#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
static void myri10ge_set_multicast_list(struct net_device *dev); static void myri10ge_set_multicast_list(struct net_device *dev);
static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev);
static inline void put_be32(__be32 val, __be32 __iomem * p) static inline void put_be32(__be32 val, __be32 __iomem * p)
{ {
@ -612,6 +615,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
__be32 buf[16]; __be32 buf[16];
u32 dma_low, dma_high, size; u32 dma_low, dma_high, size;
int status, i; int status, i;
struct myri10ge_cmd cmd;
size = 0; size = 0;
status = myri10ge_load_hotplug_firmware(mgp, &size); status = myri10ge_load_hotplug_firmware(mgp, &size);
@ -688,6 +692,14 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
dev_info(&mgp->pdev->dev, "handoff confirmed\n"); dev_info(&mgp->pdev->dev, "handoff confirmed\n");
myri10ge_dummy_rdma(mgp, 1); myri10ge_dummy_rdma(mgp, 1);
/* probe for IPv6 TSO support */
mgp->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO;
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE,
&cmd, 0);
if (status == 0) {
mgp->max_tso6 = cmd.data0;
mgp->features |= NETIF_F_TSO6;
}
return 0; return 0;
} }
@ -1047,7 +1059,8 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN; hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN;
/* allocate an skb to attach the page(s) to. */ /* allocate an skb to attach the page(s) to. This is done
* after trying LRO, so as to avoid skb allocation overheads */
skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16); skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
if (unlikely(skb == NULL)) { if (unlikely(skb == NULL)) {
@ -1217,7 +1230,8 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
static int myri10ge_poll(struct napi_struct *napi, int budget) static int myri10ge_poll(struct napi_struct *napi, int budget)
{ {
struct myri10ge_priv *mgp = container_of(napi, struct myri10ge_priv, napi); struct myri10ge_priv *mgp =
container_of(napi, struct myri10ge_priv, napi);
struct net_device *netdev = mgp->dev; struct net_device *netdev = mgp->dev;
struct myri10ge_rx_done *rx_done = &mgp->rx_done; struct myri10ge_rx_done *rx_done = &mgp->rx_done;
int work_done; int work_done;
@ -1382,6 +1396,18 @@ static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
return 0; return 0;
} }
static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled)
{
struct myri10ge_priv *mgp = netdev_priv(netdev);
unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO);
if (tso_enabled)
netdev->features |= flags;
else
netdev->features &= ~flags;
return 0;
}
static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
@ -1506,7 +1532,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = {
.set_rx_csum = myri10ge_set_rx_csum, .set_rx_csum = myri10ge_set_rx_csum,
.set_tx_csum = ethtool_op_set_tx_hw_csum, .set_tx_csum = ethtool_op_set_tx_hw_csum,
.set_sg = ethtool_op_set_sg, .set_sg = ethtool_op_set_sg,
.set_tso = ethtool_op_set_tso, .set_tso = myri10ge_set_tso,
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
.get_strings = myri10ge_get_strings, .get_strings = myri10ge_get_strings,
.get_sset_count = myri10ge_get_sset_count, .get_sset_count = myri10ge_get_sset_count,
@ -2164,7 +2190,8 @@ again:
pseudo_hdr_offset = cksum_offset + skb->csum_offset; pseudo_hdr_offset = cksum_offset + skb->csum_offset;
/* If the headers are excessively large, then we must /* If the headers are excessively large, then we must
* fall back to a software checksum */ * fall back to a software checksum */
if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { if (unlikely(!mss && (cksum_offset > 255 ||
pseudo_hdr_offset > 127))) {
if (skb_checksum_help(skb)) if (skb_checksum_help(skb))
goto drop; goto drop;
cksum_offset = 0; cksum_offset = 0;
@ -2184,9 +2211,18 @@ again:
/* negative cum_len signifies to the /* negative cum_len signifies to the
* send loop that we are still in the * send loop that we are still in the
* header portion of the TSO packet. * header portion of the TSO packet.
* TSO header must be at most 134 bytes long */ * TSO header can be at most 1KB long */
cum_len = -(skb_transport_offset(skb) + tcp_hdrlen(skb)); cum_len = -(skb_transport_offset(skb) + tcp_hdrlen(skb));
/* for IPv6 TSO, the checksum offset stores the
* TCP header length, to save the firmware from
* the need to parse the headers */
if (skb_is_gso_v6(skb)) {
cksum_offset = tcp_hdrlen(skb);
/* Can only handle headers <= max_tso6 long */
if (unlikely(-cum_len > mgp->max_tso6))
return myri10ge_sw_tso(skb, dev);
}
/* for TSO, pseudo_hdr_offset holds mss. /* for TSO, pseudo_hdr_offset holds mss.
* The firmware figures out where to put * The firmware figures out where to put
* the checksum by parsing the header. */ * the checksum by parsing the header. */
@ -2301,10 +2337,12 @@ again:
req++; req++;
count++; count++;
rdma_count++; rdma_count++;
if (unlikely(cksum_offset > seglen)) if (cksum_offset != 0 && !(mss && skb_is_gso_v6(skb))) {
cksum_offset -= seglen; if (unlikely(cksum_offset > seglen))
else cksum_offset -= seglen;
cksum_offset = 0; else
cksum_offset = 0;
}
} }
if (frag_idx == frag_cnt) if (frag_idx == frag_cnt)
break; break;
@ -2387,6 +2425,41 @@ drop:
} }
static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
{
struct sk_buff *segs, *curr;
struct myri10ge_priv *mgp = dev->priv;
int status;
segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
if (unlikely(IS_ERR(segs)))
goto drop;
while (segs) {
curr = segs;
segs = segs->next;
curr->next = NULL;
status = myri10ge_xmit(curr, dev);
if (status != 0) {
dev_kfree_skb_any(curr);
if (segs != NULL) {
curr = segs;
segs = segs->next;
curr->next = NULL;
dev_kfree_skb_any(segs);
}
goto drop;
}
}
dev_kfree_skb_any(skb);
return 0;
drop:
dev_kfree_skb_any(skb);
mgp->stats.tx_dropped += 1;
return 0;
}
static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
{ {
struct myri10ge_priv *mgp = netdev_priv(dev); struct myri10ge_priv *mgp = netdev_priv(dev);
@ -2706,7 +2779,6 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
struct myri10ge_priv *mgp; struct myri10ge_priv *mgp;
@ -2787,7 +2859,6 @@ abort_with_enabled:
return -EIO; return -EIO;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp)
@ -2954,8 +3025,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mgp = netdev_priv(netdev); mgp = netdev_priv(netdev);
mgp->dev = netdev; mgp->dev = netdev;
netif_napi_add(netdev, &mgp->napi, netif_napi_add(netdev, &mgp->napi, myri10ge_poll, myri10ge_napi_weight);
myri10ge_poll, myri10ge_napi_weight);
mgp->pdev = pdev; mgp->pdev = pdev;
mgp->csum_flag = MXGEFW_FLAGS_CKSUM; mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
mgp->pause = myri10ge_flow_control; mgp->pause = myri10ge_flow_control;
@ -3077,7 +3147,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->change_mtu = myri10ge_change_mtu; netdev->change_mtu = myri10ge_change_mtu;
netdev->set_multicast_list = myri10ge_set_multicast_list; netdev->set_multicast_list = myri10ge_set_multicast_list;
netdev->set_mac_address = myri10ge_set_mac_address; netdev->set_mac_address = myri10ge_set_mac_address;
netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; netdev->features = mgp->features;
if (dac_enabled) if (dac_enabled)
netdev->features |= NETIF_F_HIGHDMA; netdev->features |= NETIF_F_HIGHDMA;

View File

@ -10,7 +10,7 @@ struct mcp_dma_addr {
__be32 low; __be32 low;
}; };
/* 4 Bytes */ /* 4 Bytes. 8 Bytes for NDIS drivers. */
struct mcp_slot { struct mcp_slot {
__sum16 checksum; __sum16 checksum;
__be16 length; __be16 length;
@ -205,8 +205,87 @@ enum myri10ge_mcp_cmd_type {
/* same than DMA_TEST (same args) but abort with UNALIGNED on unaligned /* same than DMA_TEST (same args) but abort with UNALIGNED on unaligned
* chipset */ * chipset */
MXGEFW_CMD_UNALIGNED_STATUS MXGEFW_CMD_UNALIGNED_STATUS,
/* return data = boolean, true if the chipset is known to be unaligned */ /* return data = boolean, true if the chipset is known to be unaligned */
MXGEFW_CMD_ALWAYS_USE_N_BIG_BUFFERS,
/* data0 = number of big buffers to use. It must be 0 or a power of 2.
* 0 indicates that the NIC consumes as many buffers as they are required
* for packet. This is the default behavior.
* A power of 2 number indicates that the NIC always uses the specified
* number of buffers for each big receive packet.
* It is up to the driver to ensure that this value is big enough for
* the NIC to be able to receive maximum-sized packets.
*/
MXGEFW_CMD_GET_MAX_RSS_QUEUES,
MXGEFW_CMD_ENABLE_RSS_QUEUES,
/* data0 = number of slices n (0, 1, ..., n-1) to enable
* data1 = interrupt mode. 0=share one INTx/MSI, 1=use one MSI-X per queue.
* If all queues share one interrupt, the driver must have set
* RSS_SHARED_INTERRUPT_DMA before enabling queues.
*/
MXGEFW_CMD_GET_RSS_SHARED_INTERRUPT_MASK_OFFSET,
MXGEFW_CMD_SET_RSS_SHARED_INTERRUPT_DMA,
/* data0, data1 = bus address lsw, msw */
MXGEFW_CMD_GET_RSS_TABLE_OFFSET,
/* get the offset of the indirection table */
MXGEFW_CMD_SET_RSS_TABLE_SIZE,
/* set the size of the indirection table */
MXGEFW_CMD_GET_RSS_KEY_OFFSET,
/* get the offset of the secret key */
MXGEFW_CMD_RSS_KEY_UPDATED,
/* tell nic that the secret key's been updated */
MXGEFW_CMD_SET_RSS_ENABLE,
/* data0 = enable/disable rss
* 0: disable rss. nic does not distribute receive packets.
* 1: enable rss. nic distributes receive packets among queues.
* data1 = hash type
* 1: IPV4
* 2: TCP_IPV4
* 3: IPV4 | TCP_IPV4
*/
MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE,
/* Return data = the max. size of the entire headers of a IPv6 TSO packet.
* If the header size of a IPv6 TSO packet is larger than the specified
* value, then the driver must not use TSO.
* This size restriction only applies to IPv6 TSO.
* For IPv4 TSO, the maximum size of the headers is fixed, and the NIC
* always has enough header buffer to store maximum-sized headers.
*/
MXGEFW_CMD_SET_TSO_MODE,
/* data0 = TSO mode.
* 0: Linux/FreeBSD style (NIC default)
* 1: NDIS/NetBSD style
*/
MXGEFW_CMD_MDIO_READ,
/* data0 = dev_addr (PMA/PMD or PCS ...), data1 = register/addr */
MXGEFW_CMD_MDIO_WRITE,
/* data0 = dev_addr, data1 = register/addr, data2 = value */
MXGEFW_CMD_XFP_I2C_READ,
/* Starts to get a fresh copy of one byte or of the whole xfp i2c table, the
* obtained data is cached inside the xaui-xfi chip :
* data0 : "all" flag : 0 => get one byte, 1=> get 256 bytes,
* data1 : if (data0 == 0): index of byte to refresh [ not used otherwise ]
* The operation might take ~1ms for a single byte or ~65ms when refreshing all 256 bytes
* During the i2c operation, MXGEFW_CMD_XFP_I2C_READ or MXGEFW_CMD_XFP_BYTE attempts
* will return MXGEFW_CMD_ERROR_BUSY
*/
MXGEFW_CMD_XFP_BYTE,
/* Return the last obtained copy of a given byte in the xfp i2c table
* (copy cached during the last relevant MXGEFW_CMD_XFP_I2C_READ)
* data0 : index of the desired table entry
* Return data = the byte stored at the requested index in the table
*/
MXGEFW_CMD_GET_VPUMP_OFFSET,
/* Return data = NIC memory offset of mcp_vpump_public_global */
MXGEFW_CMD_RESET_VPUMP,
/* Resets the VPUMP state */
}; };
enum myri10ge_mcp_cmd_status { enum myri10ge_mcp_cmd_status {
@ -220,7 +299,10 @@ enum myri10ge_mcp_cmd_status {
MXGEFW_CMD_ERROR_BAD_PORT, MXGEFW_CMD_ERROR_BAD_PORT,
MXGEFW_CMD_ERROR_RESOURCES, MXGEFW_CMD_ERROR_RESOURCES,
MXGEFW_CMD_ERROR_MULTICAST, MXGEFW_CMD_ERROR_MULTICAST,
MXGEFW_CMD_ERROR_UNALIGNED MXGEFW_CMD_ERROR_UNALIGNED,
MXGEFW_CMD_ERROR_NO_MDIO,
MXGEFW_CMD_ERROR_XFP_FAILURE,
MXGEFW_CMD_ERROR_XFP_ABSENT
}; };
#define MXGEFW_OLD_IRQ_DATA_LEN 40 #define MXGEFW_OLD_IRQ_DATA_LEN 40

View File

@ -1576,7 +1576,7 @@ static int netdev_open(struct net_device *dev)
/* Set the timer to check for link beat. */ /* Set the timer to check for link beat. */
init_timer(&np->timer); init_timer(&np->timer);
np->timer.expires = jiffies + NATSEMI_TIMER_FREQ; np->timer.expires = round_jiffies(jiffies + NATSEMI_TIMER_FREQ);
np->timer.data = (unsigned long)dev; np->timer.data = (unsigned long)dev;
np->timer.function = &netdev_timer; /* timer handler */ np->timer.function = &netdev_timer; /* timer handler */
add_timer(&np->timer); add_timer(&np->timer);
@ -1856,7 +1856,11 @@ static void netdev_timer(unsigned long data)
next_tick = 1; next_tick = 1;
} }
} }
mod_timer(&np->timer, jiffies + next_tick);
if (next_tick > 1)
mod_timer(&np->timer, round_jiffies(jiffies + next_tick));
else
mod_timer(&np->timer, jiffies + next_tick);
} }
static void dump_ring(struct net_device *dev) static void dump_ring(struct net_device *dev)
@ -3310,13 +3314,19 @@ static int natsemi_resume (struct pci_dev *pdev)
{ {
struct net_device *dev = pci_get_drvdata (pdev); struct net_device *dev = pci_get_drvdata (pdev);
struct netdev_private *np = netdev_priv(dev); struct netdev_private *np = netdev_priv(dev);
int ret = 0;
rtnl_lock(); rtnl_lock();
if (netif_device_present(dev)) if (netif_device_present(dev))
goto out; goto out;
if (netif_running(dev)) { if (netif_running(dev)) {
BUG_ON(!np->hands_off); BUG_ON(!np->hands_off);
pci_enable_device(pdev); ret = pci_enable_device(pdev);
if (ret < 0) {
dev_err(&pdev->dev,
"pci_enable_device() failed: %d\n", ret);
goto out;
}
/* pci_power_on(pdev); */ /* pci_power_on(pdev); */
napi_enable(&np->napi); napi_enable(&np->napi);
@ -3331,12 +3341,12 @@ static int natsemi_resume (struct pci_dev *pdev)
spin_unlock_irq(&np->lock); spin_unlock_irq(&np->lock);
enable_irq(dev->irq); enable_irq(dev->irq);
mod_timer(&np->timer, jiffies + 1*HZ); mod_timer(&np->timer, round_jiffies(jiffies + 1*HZ));
} }
netif_device_attach(dev); netif_device_attach(dev);
out: out:
rtnl_unlock(); rtnl_unlock();
return 0; return ret;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */

View File

@ -93,7 +93,7 @@ static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr
bus_width = *(volatile unsigned char *)ABWCR; bus_width = *(volatile unsigned char *)ABWCR;
bus_width &= 1 << ((base_addr >> 21) & 7); bus_width &= 1 << ((base_addr >> 21) & 7);
for (i = 0; i < sizeof(reg_offset) / sizeof(u32); i++) for (i = 0; i < ARRAY_SIZE(reg_offset); i++)
if (bus_width == 0) if (bus_width == 0)
reg_offset[i] = i * 2 + 1; reg_offset[i] = i * 2 + 1;
else else
@ -115,7 +115,7 @@ static int h8300_ne_irq[] = {EXT_IRQ5};
static inline int init_dev(struct net_device *dev) static inline int init_dev(struct net_device *dev)
{ {
if (h8300_ne_count < (sizeof(h8300_ne_base) / sizeof(unsigned long))) { if (h8300_ne_count < ARRAY_SIZE(h8300_ne_base)) {
dev->base_addr = h8300_ne_base[h8300_ne_count]; dev->base_addr = h8300_ne_base[h8300_ne_count];
dev->irq = h8300_ne_irq[h8300_ne_count]; dev->irq = h8300_ne_irq[h8300_ne_count];
h8300_ne_count++; h8300_ne_count++;

View File

@ -97,13 +97,16 @@ static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp)
&lp->evm_saa9730_regs->InterruptBlock1); &lp->evm_saa9730_regs->InterruptBlock1);
} }
static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp) static void __used show_saa9730_regs(struct net_device *dev)
{ {
struct lan_saa9730_private *lp = netdev_priv(dev);
int i, j; int i, j;
printk("TxmBufferA = %p\n", lp->TxmBuffer[0][0]); printk("TxmBufferA = %p\n", lp->TxmBuffer[0][0]);
printk("TxmBufferB = %p\n", lp->TxmBuffer[1][0]); printk("TxmBufferB = %p\n", lp->TxmBuffer[1][0]);
printk("RcvBufferA = %p\n", lp->RcvBuffer[0][0]); printk("RcvBufferA = %p\n", lp->RcvBuffer[0][0]);
printk("RcvBufferB = %p\n", lp->RcvBuffer[1][0]); printk("RcvBufferB = %p\n", lp->RcvBuffer[1][0]);
for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) { for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
printk("TxmBuffer[%d][%d] = %x\n", i, j, printk("TxmBuffer[%d][%d] = %x\n", i, j,
@ -146,11 +149,13 @@ static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp)
readl(&lp->lan_saa9730_regs->RxCtl)); readl(&lp->lan_saa9730_regs->RxCtl));
printk("lp->lan_saa9730_regs->RxStatus = %x\n", printk("lp->lan_saa9730_regs->RxStatus = %x\n",
readl(&lp->lan_saa9730_regs->RxStatus)); readl(&lp->lan_saa9730_regs->RxStatus));
for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
writel(i, &lp->lan_saa9730_regs->CamAddress); writel(i, &lp->lan_saa9730_regs->CamAddress);
printk("lp->lan_saa9730_regs->CamData = %x\n", printk("lp->lan_saa9730_regs->CamData = %x\n",
readl(&lp->lan_saa9730_regs->CamData)); readl(&lp->lan_saa9730_regs->CamData));
} }
printk("dev->stats.tx_packets = %lx\n", dev->stats.tx_packets); printk("dev->stats.tx_packets = %lx\n", dev->stats.tx_packets);
printk("dev->stats.tx_errors = %lx\n", dev->stats.tx_errors); printk("dev->stats.tx_errors = %lx\n", dev->stats.tx_errors);
printk("dev->stats.tx_aborted_errors = %lx\n", printk("dev->stats.tx_aborted_errors = %lx\n",
@ -855,7 +860,7 @@ static void lan_saa9730_tx_timeout(struct net_device *dev)
/* Transmitter timeout, serious problems */ /* Transmitter timeout, serious problems */
dev->stats.tx_errors++; dev->stats.tx_errors++;
printk("%s: transmit timed out, reset\n", dev->name); printk("%s: transmit timed out, reset\n", dev->name);
/*show_saa9730_regs(lp); */ /*show_saa9730_regs(dev); */
lan_saa9730_restart(lp); lan_saa9730_restart(lp);
dev->trans_start = jiffies; dev->trans_start = jiffies;

View File

@ -1461,7 +1461,6 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
} }
return IRQ_NONE; return IRQ_NONE;
#else #else
struct tc35815_local *lp = dev->priv;
int handled; int handled;
u32 status; u32 status;

View File

@ -1906,7 +1906,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/************** pci *****************/ /************** pci *****************/
if ((err = pci_enable_device(pdev))) /* it trigers interrupt, dunno why. */ if ((err = pci_enable_device(pdev))) /* it trigers interrupt, dunno why. */
RET(err); /* it's not a problem though */ goto err_pci; /* it's not a problem though */
if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) && if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
!(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) { !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
@ -2076,6 +2076,7 @@ err_out_res:
pci_release_regions(pdev); pci_release_regions(pdev);
err_dma: err_dma:
pci_disable_device(pdev); pci_disable_device(pdev);
err_pci:
vfree(nic); vfree(nic);
RET(err); RET(err);

View File

@ -9034,7 +9034,7 @@ static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len)
int i; int i;
u32 j; u32 j;
for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) { for (i = 0; i < ARRAY_SIZE(test_pattern); i++) {
for (j = 0; j < len; j += 4) { for (j = 0; j < len; j += 4) {
u32 val; u32 val;

View File

@ -1041,7 +1041,7 @@ static struct InfoLeaf infoleaf_array[] = {
{DC21142, dc21142_infoleaf}, {DC21142, dc21142_infoleaf},
{DC21143, dc21143_infoleaf} {DC21143, dc21143_infoleaf}
}; };
#define INFOLEAF_SIZE (sizeof(infoleaf_array)/(sizeof(int)+sizeof(int *))) #define INFOLEAF_SIZE ARRAY_SIZE(infoleaf_array)
/* /*
** List the SROM info block functions ** List the SROM info block functions
@ -1056,7 +1056,7 @@ static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = {
compact_infoblock compact_infoblock
}; };
#define COMPACT (sizeof(dc_infoblock)/sizeof(int *) - 1) #define COMPACT (ARRAY_SIZE(dc_infoblock) - 1)
/* /*
** Miscellaneous defines... ** Miscellaneous defines...

View File

@ -63,7 +63,7 @@
#define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1 #define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1
void uec_set_ethtool_ops(struct net_device *netdev); void uec_set_ethtool_ops(struct net_device *netdev);
static DEFINE_SPINLOCK(ugeth_lock); static DEFINE_SPINLOCK(ugeth_lock);
static struct { static struct {
@ -3454,9 +3454,12 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
u16 length, howmany = 0; u16 length, howmany = 0;
u32 bd_status; u32 bd_status;
u8 *bdBuffer; u8 *bdBuffer;
struct net_device * dev;
ugeth_vdbg("%s: IN", __FUNCTION__); ugeth_vdbg("%s: IN", __FUNCTION__);
dev = ugeth->dev;
/* collect received buffers */ /* collect received buffers */
bd = ugeth->rxBd[rxQ]; bd = ugeth->rxBd[rxQ];

View File

@ -1342,11 +1342,11 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
if (flp->initialized) if (flp->initialized)
return(-EINVAL); return(-EINVAL);
for(i=0;i < sizeof(valid_port) / sizeof (int) ; i++) for(i=0; i < ARRAY_SIZE(valid_port); i++)
if (valid_port[i] == map->base_addr) if (valid_port[i] == map->base_addr)
break; break;
if (i == sizeof(valid_port) / sizeof(int)) if (i == ARRAY_SIZE(valid_port))
return(-EINVAL); return(-EINVAL);
if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){ if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
@ -1487,12 +1487,12 @@ got_type:
} }
} }
for(i=0;i < sizeof(valid_mem) / sizeof (int) ; i++) for(i=0; i < ARRAY_SIZE(valid_mem); i++)
if (valid_mem[i] == map->mem_start) if (valid_mem[i] == map->mem_start)
break; break;
err = -EINVAL; err = -EINVAL;
if (i == sizeof(valid_mem) / sizeof(int)) if (i == ARRAY_SIZE(valid_mem))
goto fail2; goto fail2;
if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E) if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E)

View File

@ -74,22 +74,12 @@ struct netfront_info {
struct napi_struct napi; struct napi_struct napi;
struct xen_netif_tx_front_ring tx; unsigned int evtchn;
struct xen_netif_rx_front_ring rx; struct xenbus_device *xbdev;
spinlock_t tx_lock; spinlock_t tx_lock;
spinlock_t rx_lock; struct xen_netif_tx_front_ring tx;
int tx_ring_ref;
unsigned int evtchn;
/* Receive-ring batched refills. */
#define RX_MIN_TARGET 8
#define RX_DFL_MIN_TARGET 64
#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
unsigned rx_min_target, rx_max_target, rx_target;
struct sk_buff_head rx_batch;
struct timer_list rx_refill_timer;
/* /*
* {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries * {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries
@ -108,14 +98,23 @@ struct netfront_info {
grant_ref_t grant_tx_ref[NET_TX_RING_SIZE]; grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
unsigned tx_skb_freelist; unsigned tx_skb_freelist;
spinlock_t rx_lock ____cacheline_aligned_in_smp;
struct xen_netif_rx_front_ring rx;
int rx_ring_ref;
/* Receive-ring batched refills. */
#define RX_MIN_TARGET 8
#define RX_DFL_MIN_TARGET 64
#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
unsigned rx_min_target, rx_max_target, rx_target;
struct sk_buff_head rx_batch;
struct timer_list rx_refill_timer;
struct sk_buff *rx_skbs[NET_RX_RING_SIZE]; struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
grant_ref_t gref_rx_head; grant_ref_t gref_rx_head;
grant_ref_t grant_rx_ref[NET_RX_RING_SIZE]; grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
struct xenbus_device *xbdev;
int tx_ring_ref;
int rx_ring_ref;
unsigned long rx_pfn_array[NET_RX_RING_SIZE]; unsigned long rx_pfn_array[NET_RX_RING_SIZE];
struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1]; struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
struct mmu_update rx_mmu[NET_RX_RING_SIZE]; struct mmu_update rx_mmu[NET_RX_RING_SIZE];

View File

@ -0,0 +1,13 @@
#ifndef __AU1X00_PROM_H
#define __AU1X00_PROM_H
extern int prom_argc;
extern char **prom_argv;
extern char **prom_envp;
extern void prom_init_cmdline(void);
extern char *prom_getcmdline(void);
extern char *prom_getenv(char *envname);
extern int prom_get_ethernet_addr(char *ethernet_addr);
#endif

View File

@ -33,16 +33,16 @@ typedef struct {
extern dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n, extern dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
unsigned int dcr_c); unsigned int dcr_c);
extern void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c); extern void dcr_unmap(dcr_host_t host, unsigned int dcr_c);
static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n) static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n)
{ {
return in_be32(host.token + dcr_n * host.stride); return in_be32(host.token + ((host.base + dcr_n) * host.stride));
} }
static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value) static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value)
{ {
out_be32(host.token + dcr_n * host.stride, value); out_be32(host.token + ((host.base + dcr_n) * host.stride), value);
} }
extern u64 of_translate_dcr_address(struct device_node *dev, extern u64 of_translate_dcr_address(struct device_node *dev,

View File

@ -29,9 +29,9 @@ typedef struct {
#define DCR_MAP_OK(host) (1) #define DCR_MAP_OK(host) (1)
#define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) }) #define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) })
#define dcr_unmap(host, dcr_n, dcr_c) do {} while (0) #define dcr_unmap(host, dcr_c) do {} while (0)
#define dcr_read(host, dcr_n) mfdcr(dcr_n) #define dcr_read(host, dcr_n) mfdcr(dcr_n + host.base)
#define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value) #define dcr_write(host, dcr_n, value) mtdcr(dcr_n + host.base, value)
/* Device Control Registers */ /* Device Control Registers */
void __mtdcr(int reg, unsigned int val); void __mtdcr(int reg, unsigned int val);

View File

@ -1781,6 +1781,11 @@ static inline int skb_is_gso(const struct sk_buff *skb)
return skb_shinfo(skb)->gso_size; return skb_shinfo(skb)->gso_size;
} }
static inline int skb_is_gso_v6(const struct sk_buff *skb)
{
return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6;
}
static inline void skb_forward_csum(struct sk_buff *skb) static inline void skb_forward_csum(struct sk_buff *skb)
{ {
/* Unfortunately we don't support this one. Any brave souls? */ /* Unfortunately we don't support this one. Any brave souls? */