r8169: mac address change support
authorFrancois Romieu <romieu@fr.zoreil.com>
Sun, 14 May 2006 10:18:44 +0000 (12:18 +0200)
committerFrancois Romieu <romieu@electric-eye.fr.zoreil.com>
Wed, 26 Jul 2006 21:23:12 +0000 (23:23 +0200)
Fix for http://bugzilla.kernel.org/show_bug.cgi?id=6032.

Cc: Tim Mattox <tmattox@gmail.com>
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
drivers/net/r8169.c

index 4c2f575..e8786c4 100644 (file)
@@ -1382,6 +1382,41 @@ static void rtl8169_netpoll(struct net_device *dev)
 }
 #endif
 
+static void __rtl8169_set_mac_addr(struct net_device *dev, void __iomem *ioaddr)
+{
+       unsigned int i, j;
+
+       RTL_W8(Cfg9346, Cfg9346_Unlock);
+       for (i = 0; i < 2; i++) {
+               __le32 l = 0;
+
+               for (j = 0; j < 4; j++) {
+                       l <<= 8;
+                       l |= dev->dev_addr[4*i + j];
+               }
+               RTL_W32(MAC0 + 4*i, cpu_to_be32(l));
+       }
+       RTL_W8(Cfg9346, Cfg9346_Lock);
+}
+
+static int rtl8169_set_mac_addr(struct net_device *dev, void *p)
+{
+       struct rtl8169_private *tp = netdev_priv(dev);
+       struct sockaddr *addr = p;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EINVAL;
+
+       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+       if (netif_running(dev)) {
+               spin_lock_irq(&tp->lock);
+               __rtl8169_set_mac_addr(dev, tp->mmio_addr);
+               spin_unlock_irq(&tp->lock);
+       }
+       return 0;
+}
+
 static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
                                  void __iomem *ioaddr)
 {
@@ -1609,6 +1644,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->stop = rtl8169_close;
        dev->tx_timeout = rtl8169_tx_timeout;
        dev->set_multicast_list = rtl8169_set_rx_mode;
+       dev->set_mac_address = rtl8169_set_mac_addr;
        dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
        dev->irq = pdev->irq;
        dev->base_addr = (unsigned long) ioaddr;
@@ -1842,6 +1878,8 @@ rtl8169_hw_start(struct net_device *dev)
        /* Enable all known interrupts by setting the interrupt mask. */
        RTL_W16(IntrMask, rtl8169_intr_mask);
 
+       __rtl8169_set_mac_addr(dev, ioaddr);
+
        netif_start_queue(dev);
 }