Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / net / dm9000.c
index 7c38f61..d835086 100644 (file)
 #define CARDNAME       "dm9000"
 #define DRV_VERSION    "1.31"
 
-#ifdef CONFIG_BLACKFIN
-#define readsb insb
-#define readsw insw
-#define readsl insl
-#define writesb        outsb
-#define writesw        outsw
-#define writesl        outsl
-#define DEFAULT_TRIGGER IRQF_TRIGGER_HIGH
-#else
-#define DEFAULT_TRIGGER (0)
-#endif
-
 /*
  * Transmit timeout, default 5 seconds.
  */
@@ -149,7 +137,7 @@ typedef struct board_info {
 
 static inline board_info_t *to_dm9000_board(struct net_device *dev)
 {
-       return dev->priv;
+       return netdev_priv(dev);
 }
 
 /* DM9000 network board routine ---------------------------- */
@@ -343,6 +331,8 @@ static int dm9000_wait_eeprom(board_info_t *db)
                if ((status & EPCR_ERRE) == 0)
                        break;
 
+               msleep(1);
+
                if (timeout-- < 0) {
                        dev_dbg(db->dev, "timeout waiting EEPROM\n");
                        break;
@@ -552,15 +542,48 @@ static const struct ethtool_ops dm9000_ethtool_ops = {
        .set_eeprom             = dm9000_set_eeprom,
 };
 
+static void dm9000_show_carrier(board_info_t *db,
+                               unsigned carrier, unsigned nsr)
+{
+       struct net_device *ndev = db->ndev;
+       unsigned ncr = dm9000_read_locked(db, DM9000_NCR);
+
+       if (carrier)
+               dev_info(db->dev, "%s: link up, %dMbps, %s-duplex, no LPA\n",
+                        ndev->name, (nsr & NSR_SPEED) ? 10 : 100,
+                        (ncr & NCR_FDX) ? "full" : "half");
+       else
+               dev_info(db->dev, "%s: link down\n", ndev->name);
+}
+
 static void
 dm9000_poll_work(struct work_struct *w)
 {
-       struct delayed_work *dw = container_of(w, struct delayed_work, work);
+       struct delayed_work *dw = to_delayed_work(w);
        board_info_t *db = container_of(dw, board_info_t, phy_poll);
+       struct net_device *ndev = db->ndev;
+
+       if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
+           !(db->flags & DM9000_PLATF_EXT_PHY)) {
+               unsigned nsr = dm9000_read_locked(db, DM9000_NSR);
+               unsigned old_carrier = netif_carrier_ok(ndev) ? 1 : 0;
+               unsigned new_carrier;
 
-       mii_check_media(&db->mii, netif_msg_link(db), 0);
+               new_carrier = (nsr & NSR_LINKST) ? 1 : 0;
+
+               if (old_carrier != new_carrier) {
+                       if (netif_msg_link(db))
+                               dm9000_show_carrier(db, new_carrier, nsr);
+
+                       if (!new_carrier)
+                               netif_carrier_off(ndev);
+                       else
+                               netif_carrier_on(ndev);
+               }
+       } else
+               mii_check_media(&db->mii, netif_msg_link(db), 0);
        
-       if (netif_running(db->ndev))
+       if (netif_running(ndev))
                dm9000_schedule_poll(db);
 }
 
@@ -603,7 +626,7 @@ static unsigned char dm9000_type_to_char(enum dm9000_type type)
 static void
 dm9000_hash_table(struct net_device *dev)
 {
-       board_info_t *db = (board_info_t *) dev->priv;
+       board_info_t *db = netdev_priv(dev);
        struct dev_mc_list *mcptr = dev->mc_list;
        int mc_cnt = dev->mc_count;
        int i, oft;
@@ -654,7 +677,7 @@ dm9000_hash_table(struct net_device *dev)
 static void
 dm9000_init_dm9000(struct net_device *dev)
 {
-       board_info_t *db = dev->priv;
+       board_info_t *db = netdev_priv(dev);
        unsigned int imr;
 
        dm9000_dbg(db, 1, "entering %s\n", __func__);
@@ -700,7 +723,7 @@ dm9000_init_dm9000(struct net_device *dev)
 /* Our watchdog timed out. Called by the networking layer */
 static void dm9000_timeout(struct net_device *dev)
 {
-       board_info_t *db = (board_info_t *) dev->priv;
+       board_info_t *db = netdev_priv(dev);
        u8 reg_save;
        unsigned long flags;
 
@@ -728,7 +751,7 @@ static int
 dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        unsigned long flags;
-       board_info_t *db = dev->priv;
+       board_info_t *db = netdev_priv(dev);
 
        dm9000_dbg(db, 3, "%s:\n", __func__);
 
@@ -808,7 +831,7 @@ struct dm9000_rxhdr {
 static void
 dm9000_rx(struct net_device *dev)
 {
-       board_info_t *db = (board_info_t *) dev->priv;
+       board_info_t *db = netdev_priv(dev);
        struct dm9000_rxhdr rxhdr;
        struct sk_buff *skb;
        u8 rxbyte, *rdptr;
@@ -856,19 +879,22 @@ dm9000_rx(struct net_device *dev)
                        dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
                }
 
-               if (rxhdr.RxStatus & 0xbf) {
+               /* rxhdr.RxStatus is identical to RSR register. */
+               if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
+                                     RSR_PLE | RSR_RWTO |
+                                     RSR_LCS | RSR_RF)) {
                        GoodPacket = false;
-                       if (rxhdr.RxStatus & 0x01) {
+                       if (rxhdr.RxStatus & RSR_FOE) {
                                if (netif_msg_rx_err(db))
                                        dev_dbg(db->dev, "fifo error\n");
                                dev->stats.rx_fifo_errors++;
                        }
-                       if (rxhdr.RxStatus & 0x02) {
+                       if (rxhdr.RxStatus & RSR_CE) {
                                if (netif_msg_rx_err(db))
                                        dev_dbg(db->dev, "crc error\n");
                                dev->stats.rx_crc_errors++;
                        }
-                       if (rxhdr.RxStatus & 0x80) {
+                       if (rxhdr.RxStatus & RSR_RF) {
                                if (netif_msg_rx_err(db))
                                        dev_dbg(db->dev, "length error\n");
                                dev->stats.rx_length_errors++;
@@ -902,15 +928,17 @@ dm9000_rx(struct net_device *dev)
 static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
-       board_info_t *db = dev->priv;
+       board_info_t *db = netdev_priv(dev);
        int int_status;
+       unsigned long flags;
        u8 reg_save;
 
        dm9000_dbg(db, 3, "entering %s\n", __func__);
 
        /* A real interrupt coming */
 
-       spin_lock(&db->lock);
+       /* holders of db->lock must always block IRQs */
+       spin_lock_irqsave(&db->lock, flags);
 
        /* Save previous register address */
        reg_save = readb(db->io_addr);
@@ -946,7 +974,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
        /* Restore previous register address */
        writeb(reg_save, db->io_addr);
 
-       spin_unlock(&db->lock);
+       spin_unlock_irqrestore(&db->lock, flags);
 
        return IRQ_HANDLED;
 }
@@ -970,7 +998,7 @@ static void dm9000_poll_controller(struct net_device *dev)
 static int
 dm9000_open(struct net_device *dev)
 {
-       board_info_t *db = dev->priv;
+       board_info_t *db = netdev_priv(dev);
        unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
 
        if (netif_msg_ifup(db))
@@ -979,11 +1007,9 @@ dm9000_open(struct net_device *dev)
        /* If there is no IRQ type specified, default to something that
         * may work, and tell the user that this is a problem */
 
-       if (irqflags == IRQF_TRIGGER_NONE) {
+       if (irqflags == IRQF_TRIGGER_NONE)
                dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
-               irqflags = DEFAULT_TRIGGER;
-       }
-       
+
        irqflags |= IRQF_SHARED;
 
        if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev))
@@ -1022,7 +1048,7 @@ static void dm9000_msleep(board_info_t *db, unsigned int ms)
 static int
 dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
 {
-       board_info_t *db = (board_info_t *) dev->priv;
+       board_info_t *db = netdev_priv(dev);
        unsigned long flags;
        unsigned int reg_save;
        int ret;
@@ -1037,7 +1063,7 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
        /* Fill the phyxcer register into REG_0C */
        iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
-       iow(db, DM9000_EPCR, 0xc);      /* Issue phyxcer read command */
+       iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);   /* Issue phyxcer read command */
 
        writeb(reg_save, db->io_addr);
        spin_unlock_irqrestore(&db->lock,flags);
@@ -1069,7 +1095,7 @@ static void
 dm9000_phy_write(struct net_device *dev,
                 int phyaddr_unused, int reg, int value)
 {
-       board_info_t *db = (board_info_t *) dev->priv;
+       board_info_t *db = netdev_priv(dev);
        unsigned long flags;
        unsigned long reg_save;
 
@@ -1088,7 +1114,7 @@ dm9000_phy_write(struct net_device *dev,
        iow(db, DM9000_EPDRL, value);
        iow(db, DM9000_EPDRH, value >> 8);
 
-       iow(db, DM9000_EPCR, 0xa);      /* Issue phyxcer write command */
+       iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);   /* Issue phyxcer write command */
 
        writeb(reg_save, db->io_addr);
        spin_unlock_irqrestore(&db->lock, flags);
@@ -1110,7 +1136,7 @@ dm9000_phy_write(struct net_device *dev,
 static void
 dm9000_shutdown(struct net_device *dev)
 {
-       board_info_t *db = dev->priv;
+       board_info_t *db = netdev_priv(dev);
 
        /* RESET device */
        dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
@@ -1126,7 +1152,7 @@ dm9000_shutdown(struct net_device *dev)
 static int
 dm9000_stop(struct net_device *ndev)
 {
-       board_info_t *db = ndev->priv;
+       board_info_t *db = netdev_priv(ndev);
 
        if (netif_msg_ifdown(db))
                dev_dbg(db->dev, "shutting down %s\n", ndev->name);
@@ -1173,7 +1199,7 @@ dm9000_probe(struct platform_device *pdev)
        dev_dbg(&pdev->dev, "dm9000_probe()\n");
 
        /* setup board info structure */
-       db = ndev->priv;
+       db = netdev_priv(ndev);
        memset(db, 0, sizeof(*db));
 
        db->dev = &pdev->dev;
@@ -1267,6 +1293,10 @@ dm9000_probe(struct platform_device *pdev)
                db->flags = pdata->flags;
        }
 
+#ifdef CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL
+       db->flags |= DM9000_PLATF_SIMPLE_PHY;
+#endif
+
        dm9000_reset(db);
 
        /* try multiple times, DM9000 sometimes gets the read wrong */
@@ -1337,6 +1367,11 @@ dm9000_probe(struct platform_device *pdev)
        for (i = 0; i < 6; i += 2)
                dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);
 
+       if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) {
+               mac_src = "platform data";
+               memcpy(ndev->dev_addr, pdata->dev_addr, 6);
+       }
+
        if (!is_valid_ether_addr(ndev->dev_addr)) {
                /* try reading from mac */
                
@@ -1352,13 +1387,11 @@ dm9000_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, ndev);
        ret = register_netdev(ndev);
 
-       if (ret == 0) {
-               DECLARE_MAC_BUF(mac);
-               printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %s (%s)\n",
+       if (ret == 0)
+               printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n",
                       ndev->name, dm9000_type_to_char(db->type),
                       db->io_addr, db->io_data, ndev->irq,
-                      print_mac(mac, ndev->dev_addr), mac_src);
-       }
+                      ndev->dev_addr, mac_src);
        return 0;
 
 out:
@@ -1377,7 +1410,7 @@ dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)
        board_info_t *db;
 
        if (ndev) {
-               db = (board_info_t *) ndev->priv;
+               db = netdev_priv(ndev);
                db->in_suspend = 1;
 
                if (netif_running(ndev)) {
@@ -1392,7 +1425,7 @@ static int
 dm9000_drv_resume(struct platform_device *dev)
 {
        struct net_device *ndev = platform_get_drvdata(dev);
-       board_info_t *db = (board_info_t *) ndev->priv;
+       board_info_t *db = netdev_priv(ndev);
 
        if (ndev) {
 
@@ -1416,7 +1449,7 @@ dm9000_drv_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        unregister_netdev(ndev);
-       dm9000_release_board(pdev, (board_info_t *) ndev->priv);
+       dm9000_release_board(pdev, (board_info_t *) netdev_priv(ndev));
        free_netdev(ndev);              /* free device structure */
 
        dev_dbg(&pdev->dev, "released and freed device\n");