spidev warning fix
[safe/jmp/linux-2.6] / drivers / net / sis190.c
index 2f69ba8..d470b19 100644 (file)
@@ -273,12 +273,14 @@ enum sis190_eeprom_address {
 
 enum sis190_feature {
        F_HAS_RGMII     = 1,
-       F_PHY_88E1111   = 2
+       F_PHY_88E1111   = 2,
+       F_PHY_BCM5461   = 4
 };
 
 struct sis190_private {
        void __iomem *mmio_addr;
        struct pci_dev *pci_dev;
+       struct net_device *dev;
        struct net_device_stats stats;
        spinlock_t lock;
        u32 rx_buf_sz;
@@ -321,23 +323,24 @@ static struct mii_chip_info {
         unsigned int type;
        u32 feature;
 } mii_chip_table[] = {
-       { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, 0 },
+       { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
+       { "Broadcom PHY AC131",   { 0x0143, 0xbc70 }, LAN, 0 },
        { "Agere PHY ET1101B",    { 0x0282, 0xf010 }, LAN, 0 },
        { "Marvell PHY 88E1111",  { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
        { "Realtek PHY RTL8201",  { 0x0000, 0x8200 }, LAN, 0 },
        { NULL, }
 };
 
-const static struct {
+static const struct {
        const char *name;
-       u8 version;             /* depend on docs */
-       u32 RxConfigMask;       /* clear the bits supported by this chip */
 } sis_chip_info[] = {
-       { DRV_NAME, 0x00, 0xff7e1880, },
+       { "SiS 190 PCI Fast Ethernet adapter" },
+       { "SiS 191 PCI Gigabit Ethernet adapter" },
 };
 
 static struct pci_device_id sis190_pci_tbl[] __devinitdata = {
        { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
+       { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
        { 0, },
 };
 
@@ -365,7 +368,7 @@ static const u32 sis190_intr_mask =
  * Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
  * The chips use a 64 element hash table based on the Ethernet CRC.
  */
-static int multicast_filter_limit = 32;
+static const int multicast_filter_limit = 32;
 
 static void __mdio_cmd(void __iomem *ioaddr, u32 ctl)
 {
@@ -545,7 +548,7 @@ static inline int sis190_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
                skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
                if (skb) {
                        skb_reserve(skb, NET_IP_ALIGN);
-                       eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
+                       skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
                        *sk_buff = skb;
                        sis190_give_to_asic(desc, rx_buf_sz);
                        ret = 0;
@@ -629,7 +632,6 @@ static int sis190_rx_interrupt(struct net_device *dev,
                        pci_action(tp->pci_dev, le32_to_cpu(desc->addr),
                                   tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
 
-                       skb->dev = dev;
                        skb_put(skb, pkt_size);
                        skb->protocol = eth_type_trans(skb, dev);
 
@@ -712,7 +714,7 @@ static void sis190_tx_interrupt(struct net_device *dev,
  * The interrupt handler does all of the Rx thread work and cleans up after
  * the Tx thread.
  */
-static irqreturn_t sis190_interrupt(int irq, void *__dev, struct pt_regs *regs)
+static irqreturn_t sis190_interrupt(int irq, void *__dev)
 {
        struct net_device *dev = __dev;
        struct sis190_private *tp = netdev_priv(dev);
@@ -757,7 +759,7 @@ static void sis190_netpoll(struct net_device *dev)
        struct pci_dev *pdev = tp->pci_dev;
 
        disable_irq(pdev->irq);
-       sis190_interrupt(pdev->irq, dev, NULL);
+       sis190_interrupt(pdev->irq, dev);
        enable_irq(pdev->irq);
 }
 #endif
@@ -820,9 +822,6 @@ static void sis190_set_rx_mode(struct net_device *dev)
        u16 rx_mode;
 
        if (dev->flags & IFF_PROMISC) {
-               /* Unconditionally log net taps. */
-               net_drv(tp, KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-                       dev->name);
                rx_mode =
                        AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
                        AcceptAllPhys;
@@ -841,7 +840,7 @@ static void sis190_set_rx_mode(struct net_device *dev)
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
                     i++, mclist = mclist->next) {
                        int bit_nr =
-                               ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
+                               ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f;
                        mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
                        rx_mode |= AcceptMulticast;
                }
@@ -899,16 +898,20 @@ static void sis190_hw_start(struct net_device *dev)
        netif_start_queue(dev);
 }
 
-static void sis190_phy_task(void * data)
+static void sis190_phy_task(struct work_struct *work)
 {
-       struct net_device *dev = data;
-       struct sis190_private *tp = netdev_priv(dev);
+       struct sis190_private *tp =
+               container_of(work, struct sis190_private, phy_task);
+       struct net_device *dev = tp->dev;
        void __iomem *ioaddr = tp->mmio_addr;
        int phy_id = tp->mii_if.phy_id;
        u16 val;
 
        rtnl_lock();
 
+       if (!netif_running(dev))
+               goto out_unlock;
+
        val = mdio_read(ioaddr, phy_id, MII_BMCR);
        if (val & BMCR_RESET) {
                // FIXME: needlessly high ?  -- FR 02/07/2005
@@ -960,13 +963,28 @@ static void sis190_phy_task(void * data)
 
                p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
 
+               if ((tp->features & F_HAS_RGMII) &&
+                   (tp->features & F_PHY_BCM5461)) {
+                       // Set Tx Delay in RGMII mode.
+                       mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
+                       udelay(200);
+                       mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
+                       p->ctl |= 0x03000000;
+               }
+
                SIS_W32(StationControl, p->ctl);
 
+               if (tp->features & F_HAS_RGMII) {
+                       SIS_W32(RGDelay, 0x0441);
+                       SIS_W32(RGDelay, 0x0440);
+               }
+
                net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name,
                         p->msg);
                netif_carrier_on(dev);
        }
 
+out_unlock:
        rtnl_unlock();
 }
 
@@ -1035,11 +1053,11 @@ static int sis190_open(struct net_device *dev)
        if (rc < 0)
                goto err_free_rx_1;
 
-       INIT_WORK(&tp->phy_task, sis190_phy_task, dev);
+       INIT_WORK(&tp->phy_task, sis190_phy_task);
 
        sis190_request_timer(dev);
 
-       rc = request_irq(dev->irq, sis190_interrupt, SA_SHIRQ, dev->name, dev);
+       rc = request_irq(dev->irq, sis190_interrupt, IRQF_SHARED, dev->name, dev);
        if (rc < 0)
                goto err_release_timer_2;
 
@@ -1088,8 +1106,6 @@ static void sis190_down(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       flush_scheduled_work();
-
        do {
                spin_lock_irq(&tp->lock);
 
@@ -1141,8 +1157,7 @@ static int sis190_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dma_addr_t mapping;
 
        if (unlikely(skb->len < ETH_ZLEN)) {
-               skb = skb_padto(skb, ETH_ZLEN);
-               if (!skb) {
+               if (skb_padto(skb, ETH_ZLEN)) {
                        tp->stats.tx_dropped++;
                        goto out;
                }
@@ -1425,6 +1440,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        tp = netdev_priv(dev);
+       tp->dev = dev;
        tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT);
 
        rc = pci_enable_device(pdev);
@@ -1548,7 +1564,7 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
        for (i = 0; i < MAC_ADDR_LEN / 2; i++) {
                __le16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
 
-               ((u16 *)dev->dev_addr)[0] = le16_to_cpu(w);
+               ((u16 *)dev->dev_addr)[i] = le16_to_cpu(w);
        }
 
        sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
@@ -1577,6 +1593,9 @@ static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
                  pci_name(pdev));
 
        isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0965, NULL);
+       if (!isa_bridge)
+               isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0966, NULL);
+
        if (!isa_bridge) {
                net_probe(tp, KERN_INFO "%s: Can not find ISA bridge.\n",
                          pci_name(pdev));
@@ -1736,7 +1755,7 @@ static void sis190_set_msglevel(struct net_device *dev, u32 value)
        tp->msg_enable = value;
 }
 
-static struct ethtool_ops sis190_ethtool_ops = {
+static const struct ethtool_ops sis190_ethtool_ops = {
        .get_settings   = sis190_get_settings,
        .set_settings   = sis190_set_settings,
        .get_drvinfo    = sis190_get_drvinfo,
@@ -1776,6 +1795,8 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
                goto out;
        }
 
+       pci_set_drvdata(pdev, dev);
+
        tp = netdev_priv(dev);
        ioaddr = tp->mmio_addr;
 
@@ -1785,7 +1806,7 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
 
        sis190_init_rxfilter(dev);
 
-       INIT_WORK(&tp->phy_task, sis190_phy_task, dev);
+       INIT_WORK(&tp->phy_task, sis190_phy_task);
 
        dev->open = sis190_open;
        dev->stop = sis190_close;
@@ -1812,8 +1833,6 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
        if (rc < 0)
                goto err_remove_mii;
 
-       pci_set_drvdata(pdev, dev);
-
        net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
               "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
               pci_name(pdev), sis_chip_info[ent->driver_data].name,
@@ -1843,6 +1862,7 @@ static void __devexit sis190_remove_one(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
 
        sis190_mii_remove(dev);
+       flush_scheduled_work();
        unregister_netdev(dev);
        sis190_release_board(pdev);
        pci_set_drvdata(pdev, NULL);
@@ -1857,7 +1877,7 @@ static struct pci_driver sis190_pci_driver = {
 
 static int __init sis190_init_module(void)
 {
-       return pci_module_init(&sis190_pci_driver);
+       return pci_register_driver(&sis190_pci_driver);
 }
 
 static void __exit sis190_cleanup_module(void)