]> err.no Git - linux-2.6/blobdiff - drivers/net/spider_net.c
Modified ipw_config and STATUS_INIT setting to correct race condition
[linux-2.6] / drivers / net / spider_net.c
index 692a0437fef717834962615032b85612d396aa0d..c796f41b4a52f3f8c0d91de463bc2dd6cda0cff2 100644 (file)
@@ -108,6 +108,23 @@ spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 value)
        writel(value, card->regs + reg);
 }
 
+/**
+ * spider_net_write_reg_sync - writes to an SMMIO register of a card
+ * @card: device structure
+ * @reg: register to write to
+ * @value: value to write into the specified SMMIO register
+ *
+ * Unlike spider_net_write_reg, this will also make sure the
+ * data arrives on the card by reading the reg again.
+ */
+static void
+spider_net_write_reg_sync(struct spider_net_card *card, u32 reg, u32 value)
+{
+       value = cpu_to_le32(value);
+       writel(value, card->regs + reg);
+       (void)readl(card->regs + reg);
+}
+
 /**
  * spider_net_rx_irq_off - switch off rx irq on this spider card
  * @card: device structure
@@ -123,7 +140,7 @@ spider_net_rx_irq_off(struct spider_net_card *card)
        spin_lock_irqsave(&card->intmask_lock, flags);
        regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
        regvalue &= ~SPIDER_NET_RXINT;
-       spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
+       spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
        spin_unlock_irqrestore(&card->intmask_lock, flags);
 }
 
@@ -196,7 +213,7 @@ spider_net_rx_irq_on(struct spider_net_card *card)
        spin_lock_irqsave(&card->intmask_lock, flags);
        regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
        regvalue |= SPIDER_NET_RXINT;
-       spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
+       spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
        spin_unlock_irqrestore(&card->intmask_lock, flags);
 }
 
@@ -215,7 +232,7 @@ spider_net_tx_irq_off(struct spider_net_card *card)
        spin_lock_irqsave(&card->intmask_lock, flags);
        regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
        regvalue &= ~SPIDER_NET_TXINT;
-       spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
+       spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
        spin_unlock_irqrestore(&card->intmask_lock, flags);
 }
 
@@ -234,7 +251,7 @@ spider_net_tx_irq_on(struct spider_net_card *card)
        spin_lock_irqsave(&card->intmask_lock, flags);
        regvalue = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
        regvalue |= SPIDER_NET_TXINT;
-       spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
+       spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
        spin_unlock_irqrestore(&card->intmask_lock, flags);
 }
 
@@ -813,6 +830,9 @@ spider_net_stop(struct net_device *netdev)
        spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
        spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
 
+       /* free_irq(netdev->irq, netdev);*/
+       free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
+
        spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
                             SPIDER_NET_DMA_TX_FEND_VALUE);
 
@@ -822,10 +842,6 @@ spider_net_stop(struct net_device *netdev)
        /* release chains */
        spider_net_release_tx_chain(card, 1);
 
-       /* switch off card */
-       spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
-                            SPIDER_NET_CKRCTRL_STOP_VALUE);
-
        spider_net_free_chain(card, &card->tx_chain);
        spider_net_free_chain(card, &card->rx_chain);
 
@@ -1276,23 +1292,29 @@ static int
 spider_net_set_mac(struct net_device *netdev, void *p)
 {
        struct spider_net_card *card = netdev_priv(netdev);
-       u32 macl, macu;
+       u32 macl, macu, regvalue;
        struct sockaddr *addr = p;
 
-       /* GMACTPE and GMACRPE must be off, so we only allow this, if
-        * the device is down */
-       if (netdev->flags & IFF_UP)
-               return -EBUSY;
-
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
+       /* switch off GMACTPE and GMACRPE */
+       regvalue = spider_net_read_reg(card, SPIDER_NET_GMACOPEMD);
+       regvalue &= ~((1 << 5) | (1 << 6));
+       spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, regvalue);
+
+       /* write mac */
        macu = (addr->sa_data[0]<<24) + (addr->sa_data[1]<<16) +
                (addr->sa_data[2]<<8) + (addr->sa_data[3]);
        macl = (addr->sa_data[4]<<8) + (addr->sa_data[5]);
        spider_net_write_reg(card, SPIDER_NET_GMACUNIMACU, macu);
        spider_net_write_reg(card, SPIDER_NET_GMACUNIMACL, macl);
 
+       /* switch GMACTPE and GMACRPE back on */
+       regvalue = spider_net_read_reg(card, SPIDER_NET_GMACOPEMD);
+       regvalue |= ((1 << 5) | (1 << 6));
+       spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, regvalue);
+
        spider_net_set_promisc(card);
 
        /* look up, whether we have been successful */
@@ -1745,6 +1767,10 @@ spider_net_open(struct net_device *netdev)
 
        spider_net_enable_card(card);
 
+       netif_start_queue(netdev);
+       netif_carrier_on(netdev);
+       netif_poll_enable(netdev);
+
        return 0;
 
 register_int_failed:
@@ -1791,6 +1817,10 @@ spider_net_setup_phy(struct spider_net_card *card)
        /* LEDs active in both modes, autosense prio = fiber */
        spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f);
 
+       /* switch off fibre autoneg */
+       spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01);
+       spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004);
+
        phy->def->ops->read_link(phy);
        pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
                phy->speed, phy->duplex==1 ? "Full" : "Half");
@@ -2045,7 +2075,12 @@ spider_net_setup_netdev(struct spider_net_card *card)
        netdev->irq = card->pdev->irq;
 
        dn = pci_device_to_OF_node(card->pdev);
+       if (!dn)
+               return -EIO;
+
        mac = (u8 *)get_property(dn, "local-mac-address", NULL);
+       if (!mac)
+               return -EIO;
        memcpy(addr.sa_data, mac, ETH_ALEN);
 
        result = spider_net_set_mac(netdev, &addr);
@@ -2243,10 +2278,15 @@ spider_net_remove(struct pci_dev *pdev)
                   atomic_read(&card->tx_timeout_task_counter) == 0);
 
        unregister_netdev(netdev);
+
+       /* switch off card */
+       spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+                            SPIDER_NET_CKRCTRL_STOP_VALUE);
+       spider_net_write_reg(card, SPIDER_NET_CKRCTRL,
+                            SPIDER_NET_CKRCTRL_RUN_VALUE);
+
        spider_net_undo_pci_setup(card);
        free_netdev(netdev);
-
-       free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
 }
 
 static struct pci_driver spider_net_driver = {