diff options
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r-- | drivers/net/forcedeth.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 4d38acbac4ef..1e691024868f 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -90,6 +90,7 @@ | |||
90 | * 0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of | 90 | * 0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of |
91 | * per-packet flags. | 91 | * per-packet flags. |
92 | * 0.39: 18 Jul 2005: Add 64bit descriptor support. | 92 | * 0.39: 18 Jul 2005: Add 64bit descriptor support. |
93 | * 0.40: 19 Jul 2005: Add support for mac address change. | ||
93 | * | 94 | * |
94 | * Known bugs: | 95 | * Known bugs: |
95 | * We suspect that on some hardware no TX done interrupts are generated. | 96 | * We suspect that on some hardware no TX done interrupts are generated. |
@@ -101,7 +102,7 @@ | |||
101 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few | 102 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few |
102 | * superfluous timer interrupts from the nic. | 103 | * superfluous timer interrupts from the nic. |
103 | */ | 104 | */ |
104 | #define FORCEDETH_VERSION "0.39" | 105 | #define FORCEDETH_VERSION "0.40" |
105 | #define DRV_NAME "forcedeth" | 106 | #define DRV_NAME "forcedeth" |
106 | 107 | ||
107 | #include <linux/module.h> | 108 | #include <linux/module.h> |
@@ -1416,6 +1417,54 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) | |||
1416 | return 0; | 1417 | return 0; |
1417 | } | 1418 | } |
1418 | 1419 | ||
1420 | static void nv_copy_mac_to_hw(struct net_device *dev) | ||
1421 | { | ||
1422 | u8 *base = get_hwbase(dev); | ||
1423 | u32 mac[2]; | ||
1424 | |||
1425 | mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) + | ||
1426 | (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24); | ||
1427 | mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8); | ||
1428 | |||
1429 | writel(mac[0], base + NvRegMacAddrA); | ||
1430 | writel(mac[1], base + NvRegMacAddrB); | ||
1431 | } | ||
1432 | |||
1433 | /* | ||
1434 | * nv_set_mac_address: dev->set_mac_address function | ||
1435 | * Called with rtnl_lock() held. | ||
1436 | */ | ||
1437 | static int nv_set_mac_address(struct net_device *dev, void *addr) | ||
1438 | { | ||
1439 | struct fe_priv *np = get_nvpriv(dev); | ||
1440 | struct sockaddr *macaddr = (struct sockaddr*)addr; | ||
1441 | |||
1442 | if(!is_valid_ether_addr(macaddr->sa_data)) | ||
1443 | return -EADDRNOTAVAIL; | ||
1444 | |||
1445 | /* synchronized against open : rtnl_lock() held by caller */ | ||
1446 | memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN); | ||
1447 | |||
1448 | if (netif_running(dev)) { | ||
1449 | spin_lock_bh(&dev->xmit_lock); | ||
1450 | spin_lock_irq(&np->lock); | ||
1451 | |||
1452 | /* stop rx engine */ | ||
1453 | nv_stop_rx(dev); | ||
1454 | |||
1455 | /* set mac address */ | ||
1456 | nv_copy_mac_to_hw(dev); | ||
1457 | |||
1458 | /* restart rx engine */ | ||
1459 | nv_start_rx(dev); | ||
1460 | spin_unlock_irq(&np->lock); | ||
1461 | spin_unlock_bh(&dev->xmit_lock); | ||
1462 | } else { | ||
1463 | nv_copy_mac_to_hw(dev); | ||
1464 | } | ||
1465 | return 0; | ||
1466 | } | ||
1467 | |||
1419 | /* | 1468 | /* |
1420 | * nv_set_multicast: dev->set_multicast function | 1469 | * nv_set_multicast: dev->set_multicast function |
1421 | * Called with dev->xmit_lock held. | 1470 | * Called with dev->xmit_lock held. |
@@ -2047,16 +2096,7 @@ static int nv_open(struct net_device *dev) | |||
2047 | np->in_shutdown = 0; | 2096 | np->in_shutdown = 0; |
2048 | 2097 | ||
2049 | /* 3) set mac address */ | 2098 | /* 3) set mac address */ |
2050 | { | 2099 | nv_copy_mac_to_hw(dev); |
2051 | u32 mac[2]; | ||
2052 | |||
2053 | mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) + | ||
2054 | (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24); | ||
2055 | mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8); | ||
2056 | |||
2057 | writel(mac[0], base + NvRegMacAddrA); | ||
2058 | writel(mac[1], base + NvRegMacAddrB); | ||
2059 | } | ||
2060 | 2100 | ||
2061 | /* 4) give hw rings */ | 2101 | /* 4) give hw rings */ |
2062 | writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr); | 2102 | writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr); |
@@ -2302,6 +2342,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2302 | dev->hard_start_xmit = nv_start_xmit; | 2342 | dev->hard_start_xmit = nv_start_xmit; |
2303 | dev->get_stats = nv_get_stats; | 2343 | dev->get_stats = nv_get_stats; |
2304 | dev->change_mtu = nv_change_mtu; | 2344 | dev->change_mtu = nv_change_mtu; |
2345 | dev->set_mac_address = nv_set_mac_address; | ||
2305 | dev->set_multicast_list = nv_set_multicast; | 2346 | dev->set_multicast_list = nv_set_multicast; |
2306 | #ifdef CONFIG_NET_POLL_CONTROLLER | 2347 | #ifdef CONFIG_NET_POLL_CONTROLLER |
2307 | dev->poll_controller = nv_poll_controller; | 2348 | dev->poll_controller = nv_poll_controller; |