]> err.no Git - linux-2.6/blobdiff - drivers/net/r8169.c
Fix a potential NULL pointer dereference in write_bulk_callback() in drivers/net...
[linux-2.6] / drivers / net / r8169.c
index d8862cd84f3de0bb106efa3727e8b09ecb593c6f..bb6896ae31517c46b098dafcf1f35a28232112b3 100644 (file)
@@ -182,6 +182,7 @@ static struct {
 
 enum rtl_registers {
        MAC0            = 0,    /* Ethernet hardware address. */
+       MAC4            = 4,
        MAR0            = 8,    /* Multicast filter. */
        CounterAddrLow          = 0x10,
        CounterAddrHigh         = 0x14,
@@ -362,15 +363,15 @@ enum desc_status_bit {
 #define RsvdMask       0x3fffc000
 
 struct TxDesc {
-       u32 opts1;
-       u32 opts2;
-       u64 addr;
+       __le32 opts1;
+       __le32 opts2;
+       __le64 addr;
 };
 
 struct RxDesc {
-       u32 opts1;
-       u32 opts2;
-       u64 addr;
+       __le32 opts1;
+       __le32 opts2;
+       __le64 addr;
 };
 
 struct ring_info {
@@ -1379,6 +1380,40 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
                printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
 }
 
+static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
+{
+       void __iomem *ioaddr = tp->mmio_addr;
+       u32 high;
+       u32 low;
+
+       low  = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
+       high = addr[4] | (addr[5] << 8);
+
+       spin_lock_irq(&tp->lock);
+
+       RTL_W8(Cfg9346, Cfg9346_Unlock);
+       RTL_W32(MAC0, low);
+       RTL_W32(MAC4, high);
+       RTL_W8(Cfg9346, Cfg9346_Lock);
+
+       spin_unlock_irq(&tp->lock);
+}
+
+static int rtl_set_mac_address(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 -EADDRNOTAVAIL;
+
+       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+       rtl_rar_set(tp, dev->dev_addr);
+
+       return 0;
+}
+
 static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
@@ -1415,7 +1450,7 @@ static const struct rtl_cfg_info {
        [RTL_CFG_0] = {
                .hw_start       = rtl_hw_start_8169,
                .region         = 1,
-               .align          = 2,
+               .align          = 0,
                .intr_event     = SYSErr | LinkChg | RxOverflow |
                                  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
                .napi_event     = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
@@ -1610,6 +1645,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->irq = pdev->irq;
        dev->base_addr = (unsigned long) ioaddr;
        dev->change_mtu = rtl8169_change_mtu;
+       dev->set_mac_address = rtl_set_mac_address;
 
 #ifdef CONFIG_R8169_NAPI
        dev->poll = rtl8169_poll;
@@ -1646,15 +1682,17 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_set_drvdata(pdev, dev);
 
        if (netif_msg_probe(tp)) {
+               u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff;
+
                printk(KERN_INFO "%s: %s at 0x%lx, "
                       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
-                      "IRQ %d\n",
+                      "XID %08x IRQ %d\n",
                       dev->name,
                       rtl_chip_info[tp->chipset].name,
                       dev->base_addr,
                       dev->dev_addr[0], dev->dev_addr[1],
                       dev->dev_addr[2], dev->dev_addr[3],
-                      dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+                      dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq);
        }
 
        rtl8169_init_phy(dev, tp);
@@ -2076,12 +2114,15 @@ static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
 {
        struct sk_buff *skb;
        dma_addr_t mapping;
+       unsigned int pad;
+
+       pad = align ? align : NET_IP_ALIGN;
 
-       skb = netdev_alloc_skb(dev, rx_buf_sz + align);
+       skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
        if (!skb)
                goto err_out;
 
-       skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
+       skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
 
        mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
                                 PCI_DMA_FROMDEVICE);
@@ -2297,7 +2338,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
 {
        struct skb_shared_info *info = skb_shinfo(skb);
        unsigned int cur_frag, entry;
-       struct TxDesc *txd;
+       struct TxDesc * uninitialized_var(txd);
 
        entry = tp->cur_tx;
        for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
@@ -2912,10 +2953,11 @@ static void rtl_set_rx_mode(struct net_device *dev)
                mc_filter[1] = 0xffffffff;
        }
 
-       RTL_W32(RxConfig, tmp);
        RTL_W32(MAR0 + 0, mc_filter[0]);
        RTL_W32(MAR0 + 4, mc_filter[1]);
 
+       RTL_W32(RxConfig, tmp);
+
        spin_unlock_irqrestore(&tp->lock, flags);
 }