Commit 96764898 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/netdev-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/netdev-2.6:
  sky2: prevent dual port receiver problems
  x86_64: Check for bad dma address in b44 1GB DMA workaround
  The ixp2000 driver for the enp2611 was developed on a board with
parents 15eb7105 843a46f4
...@@ -149,6 +149,8 @@ static void enp2611_check_link_status(unsigned long __dummy) ...@@ -149,6 +149,8 @@ static void enp2611_check_link_status(unsigned long __dummy)
int status; int status;
dev = nds[i]; dev = nds[i];
if (dev == NULL)
continue;
status = pm3386_is_link_up(i); status = pm3386_is_link_up(i);
if (status && !netif_carrier_ok(dev)) { if (status && !netif_carrier_ok(dev)) {
...@@ -191,6 +193,7 @@ static void enp2611_set_port_admin_status(int port, int up) ...@@ -191,6 +193,7 @@ static void enp2611_set_port_admin_status(int port, int up)
static int __init enp2611_init_module(void) static int __init enp2611_init_module(void)
{ {
int ports;
int i; int i;
if (!machine_is_enp2611()) if (!machine_is_enp2611())
...@@ -199,7 +202,8 @@ static int __init enp2611_init_module(void) ...@@ -199,7 +202,8 @@ static int __init enp2611_init_module(void)
caleb_reset(); caleb_reset();
pm3386_reset(); pm3386_reset();
for (i = 0; i < 3; i++) { ports = pm3386_port_count();
for (i = 0; i < ports; i++) {
nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv)); nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv));
if (nds[i] == NULL) { if (nds[i] == NULL) {
while (--i >= 0) while (--i >= 0)
...@@ -215,8 +219,9 @@ static int __init enp2611_init_module(void) ...@@ -215,8 +219,9 @@ static int __init enp2611_init_module(void)
ixp2400_msf_init(&enp2611_msf_parameters); ixp2400_msf_init(&enp2611_msf_parameters);
if (ixpdev_init(3, nds, enp2611_set_port_admin_status)) { if (ixpdev_init(ports, nds, enp2611_set_port_admin_status)) {
for (i = 0; i < 3; i++) for (i = 0; i < ports; i++)
if (nds[i])
free_netdev(nds[i]); free_netdev(nds[i]);
return -EINVAL; return -EINVAL;
} }
......
...@@ -86,39 +86,52 @@ static void pm3386_port_reg_write(int port, int _reg, int spacing, u16 value) ...@@ -86,39 +86,52 @@ static void pm3386_port_reg_write(int port, int _reg, int spacing, u16 value)
pm3386_reg_write(port >> 1, reg, value); pm3386_reg_write(port >> 1, reg, value);
} }
int pm3386_secondary_present(void)
{
return pm3386_reg_read(1, 0) == 0x3386;
}
void pm3386_reset(void) void pm3386_reset(void)
{ {
u8 mac[3][6]; u8 mac[3][6];
int secondary;
secondary = pm3386_secondary_present();
/* Save programmed MAC addresses. */ /* Save programmed MAC addresses. */
pm3386_get_mac(0, mac[0]); pm3386_get_mac(0, mac[0]);
pm3386_get_mac(1, mac[1]); pm3386_get_mac(1, mac[1]);
if (secondary)
pm3386_get_mac(2, mac[2]); pm3386_get_mac(2, mac[2]);
/* Assert analog and digital reset. */ /* Assert analog and digital reset. */
pm3386_reg_write(0, 0x002, 0x0060); pm3386_reg_write(0, 0x002, 0x0060);
if (secondary)
pm3386_reg_write(1, 0x002, 0x0060); pm3386_reg_write(1, 0x002, 0x0060);
mdelay(1); mdelay(1);
/* Deassert analog reset. */ /* Deassert analog reset. */
pm3386_reg_write(0, 0x002, 0x0062); pm3386_reg_write(0, 0x002, 0x0062);
if (secondary)
pm3386_reg_write(1, 0x002, 0x0062); pm3386_reg_write(1, 0x002, 0x0062);
mdelay(10); mdelay(10);
/* Deassert digital reset. */ /* Deassert digital reset. */
pm3386_reg_write(0, 0x002, 0x0063); pm3386_reg_write(0, 0x002, 0x0063);
if (secondary)
pm3386_reg_write(1, 0x002, 0x0063); pm3386_reg_write(1, 0x002, 0x0063);
mdelay(10); mdelay(10);
/* Restore programmed MAC addresses. */ /* Restore programmed MAC addresses. */
pm3386_set_mac(0, mac[0]); pm3386_set_mac(0, mac[0]);
pm3386_set_mac(1, mac[1]); pm3386_set_mac(1, mac[1]);
if (secondary)
pm3386_set_mac(2, mac[2]); pm3386_set_mac(2, mac[2]);
/* Disable carrier on all ports. */ /* Disable carrier on all ports. */
pm3386_set_carrier(0, 0); pm3386_set_carrier(0, 0);
pm3386_set_carrier(1, 0); pm3386_set_carrier(1, 0);
if (secondary)
pm3386_set_carrier(2, 0); pm3386_set_carrier(2, 0);
} }
...@@ -127,6 +140,11 @@ static u16 swaph(u16 x) ...@@ -127,6 +140,11 @@ static u16 swaph(u16 x)
return ((x << 8) | (x >> 8)) & 0xffff; return ((x << 8) | (x >> 8)) & 0xffff;
} }
int pm3386_port_count(void)
{
return 2 + pm3386_secondary_present();
}
void pm3386_init_port(int port) void pm3386_init_port(int port)
{ {
int pm = port >> 1; int pm = port >> 1;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#define __PM3386_H #define __PM3386_H
void pm3386_reset(void); void pm3386_reset(void);
int pm3386_port_count(void);
void pm3386_init_port(int port); void pm3386_init_port(int port);
void pm3386_get_mac(int port, u8 *mac); void pm3386_get_mac(int port, u8 *mac);
void pm3386_set_mac(int port, u8 *mac); void pm3386_set_mac(int port, u8 *mac);
......
...@@ -1020,8 +1020,19 @@ static int sky2_up(struct net_device *dev) ...@@ -1020,8 +1020,19 @@ static int sky2_up(struct net_device *dev)
struct sky2_hw *hw = sky2->hw; struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port; unsigned port = sky2->port;
u32 ramsize, rxspace, imask; u32 ramsize, rxspace, imask;
int err = -ENOMEM; int err;
struct net_device *otherdev = hw->dev[sky2->port^1];
/* Block bringing up both ports at the same time on a dual port card.
* There is an unfixed bug where receiver gets confused and picks up
* packets out of order. Until this is fixed, prevent data corruption.
*/
if (otherdev && netif_running(otherdev)) {
printk(KERN_INFO PFX "dual port support is disabled.\n");
return -EBUSY;
}
err = -ENOMEM;
if (netif_msg_ifup(sky2)) if (netif_msg_ifup(sky2))
printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment