]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/skge.c
Merge branch 'master'
[linux-2.6-omap-h63xx.git] / drivers / net / skge.c
index a1cfead5827bcc7bd781655c5259cdb627d063c7..8b6e2a11e28d58a893c24761e18d3d9ac112c7cf 100644 (file)
@@ -43,7 +43,7 @@
 #include "skge.h"
 
 #define DRV_NAME               "skge"
-#define DRV_VERSION            "1.1"
+#define DRV_VERSION            "1.2"
 #define PFX                    DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE   128
@@ -130,7 +130,7 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
                      regs->len - B3_RI_WTO_R1);
 }
 
-/* Wake on Lan only supported on Yukon chps with rev 1 or above */
+/* Wake on Lan only supported on Yukon chips with rev 1 or above */
 static int wol_supported(const struct skge_hw *hw)
 {
        return !((hw->chip_id == CHIP_ID_GENESIS ||
@@ -170,8 +170,8 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        return 0;
 }
 
-/* Determine supported/adverised modes based on hardware.
- * Note: ethtoool ADVERTISED_xxx == SUPPORTED_xxx
+/* Determine supported/advertised modes based on hardware.
+ * Note: ethtool ADVERTISED_xxx == SUPPORTED_xxx
  */
 static u32 skge_supported_modes(const struct skge_hw *hw)
 {
@@ -532,13 +532,13 @@ static inline u32 hwkhz(const struct skge_hw *hw)
                return 78215; /* or:  78.125 MHz */
 }
 
-/* Chip hz to microseconds */
+/* Chip HZ to microseconds */
 static inline u32 skge_clk2usec(const struct skge_hw *hw, u32 ticks)
 {
        return (ticks * 1000) / hwkhz(hw);
 }
 
-/* Microseconds to chip hz */
+/* Microseconds to chip HZ */
 static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec)
 {
        return hwkhz(hw) * usec / 1000;
@@ -1163,7 +1163,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
        xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ext);
        xm_phy_write(hw, port, PHY_BCOM_CTRL, ctl);
 
-       /* Use link status change interrrupt */
+       /* Use link status change interrupt */
        xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
 
        bcom_check_link(hw, port);
@@ -1203,7 +1203,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
        skge_write32(hw, B2_GP_IO, r);
        skge_read32(hw, B2_GP_IO);
 
-       /* Enable GMII interfac */
+       /* Enable GMII interface */
        xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
 
        bcom_phy_init(skge, jumbo);
@@ -1254,7 +1254,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
         * that jumbo frames larger than 8192 bytes will be
         * truncated. Disabling all bad frame filtering causes
         * the RX FIFO to operate in streaming mode, in which
-        * case the XMAC will start transfering frames out of the
+        * case the XMAC will start transferring frames out of the
         * RX FIFO as soon as the FIFO threshold is reached.
         */
        xm_write32(hw, port, XM_MODE, XM_DEF_MODE);
@@ -1321,7 +1321,7 @@ static void genesis_stop(struct skge_port *skge)
                     port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
 
        /*
-        * If the transfer stucks at the MAC the STOP command will not
+        * If the transfer sticks at the MAC the STOP command will not
         * terminate if we don't flush the XMAC's transmit FIFO !
         */
        xm_write32(hw, port, XM_MODE,
@@ -1559,7 +1559,7 @@ static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg)
        return v;
 }
 
-/* Marvell Phy Initailization */
+/* Marvell Phy Initialization */
 static void yukon_init(struct skge_hw *hw, int port)
 {
        struct skge_port *skge = netdev_priv(hw->dev[port]);
@@ -1804,6 +1804,25 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
        skge_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
 }
 
+/* Go into power down mode */
+static void yukon_suspend(struct skge_hw *hw, int port)
+{
+       u16 ctrl;
+
+       ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+       ctrl |= PHY_M_PC_POL_R_DIS;
+       gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+       ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
+       ctrl |= PHY_CT_RESET;
+       gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+       /* switch IEEE compatible power down mode on */
+       ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
+       ctrl |= PHY_CT_PDOWN;
+       gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+}
+
 static void yukon_stop(struct skge_port *skge)
 {
        struct skge_hw *hw = skge->hw;
@@ -1817,14 +1836,7 @@ static void yukon_stop(struct skge_port *skge)
                         & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
        gma_read16(hw, port, GM_GP_CTRL);
 
-       if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-           hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
-               u32 io = skge_read32(hw, B2_GP_IO);
-
-               io |= GP_DIR_9 | GP_IO_9;
-               skge_write32(hw, B2_GP_IO, io);
-               skge_read32(hw, B2_GP_IO);
-       }
+       yukon_suspend(hw, port);
 
        /* set GPHY Control reset */
        skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
@@ -2144,7 +2156,7 @@ static int skge_up(struct net_device *dev)
        hw->intr_mask |= portirqmask[port];
        skge_write32(hw, B0_IMSK, hw->intr_mask);
 
-       /* Initialze MAC */
+       /* Initialize MAC */
        spin_lock_bh(&hw->phy_lock);
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_mac_init(hw, port);
@@ -2268,11 +2280,13 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        }
 
        if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) {
-               netif_stop_queue(dev);
-               spin_unlock_irqrestore(&skge->tx_lock, flags);
+               if (!netif_stopped(dev)) {
+                       netif_stop_queue(dev);
 
-               printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
-                      dev->name);
+                       printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
+                              dev->name);
+               }
+               spin_unlock_irqrestore(&skge->tx_lock, flags);
                return NETDEV_TX_BUSY;
        }
 
@@ -2288,14 +2302,12 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        td->dma_hi = map >> 32;
 
        if (skb->ip_summed == CHECKSUM_HW) {
-               const struct iphdr *ip
-                       = (const struct iphdr *) (skb->data + ETH_HLEN);
                int offset = skb->h.raw - skb->data;
 
                /* This seems backwards, but it is what the sk98lin
                 * does.  Looks like hardware is wrong?
                 */
-               if (ip->protocol == IPPROTO_UDP
+               if (skb->h.ipiph->protocol == IPPROTO_UDP
                    && hw->chip_rev == 0 && hw->chip_id == CHIP_ID_YUKON)
                        control = BMU_TCP_CHECK;
                else
@@ -2464,7 +2476,7 @@ static void yukon_set_multicast(struct net_device *dev)
        reg = gma_read16(hw, port, GM_RX_CTRL);
        reg |= GM_RXCR_UCF_ENA;
 
-       if (dev->flags & IFF_PROMISC)           /* promiscious */
+       if (dev->flags & IFF_PROMISC)           /* promiscuous */
                reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
        else if (dev->flags & IFF_ALLMULTI)     /* all multicast */
                memset(filter, 0xff, sizeof(filter));
@@ -2615,7 +2627,7 @@ static int skge_poll(struct net_device *dev, int *budget)
        unsigned int to_do = min(dev->quota, *budget);
        unsigned int work_done = 0;
 
-       for (e = ring->to_clean; work_done < to_do; e = e->next) {
+       for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) {
                struct skge_rx_desc *rd = e->desc;
                struct sk_buff *skb;
                u32 control;
@@ -2648,11 +2660,11 @@ static int skge_poll(struct net_device *dev, int *budget)
        if (work_done >=  to_do)
                return 1; /* not done */
 
-       local_irq_disable();
-       __netif_rx_complete(dev);
+       netif_rx_complete(dev);
        hw->intr_mask |= portirqmask[skge->port];
        skge_write32(hw, B0_IMSK, hw->intr_mask);
-       local_irq_enable();
+       skge_read32(hw, B0_IMSK);
+
        return 0;
 }
 
@@ -2664,7 +2676,7 @@ static inline void skge_tx_intr(struct net_device *dev)
        struct skge_element *e;
 
        spin_lock(&skge->tx_lock);
-       for (e = ring->to_clean; e != ring->to_use; e = e->next) {
+       for (e = ring->to_clean; prefetch(e->next), e != ring->to_use; e = e->next) {
                struct skge_tx_desc *td = e->desc;
                u32 control;
 
@@ -2787,7 +2799,7 @@ static void skge_error_irq(struct skge_hw *hw)
 }
 
 /*
- * Interrrupt from PHY are handled in tasklet (soft irq)
+ * Interrupt from PHY are handled in tasklet (soft irq)
  * because accessing phy registers requires spin wait which might
  * cause excess interrupt latency.
  */
@@ -2817,6 +2829,14 @@ static void skge_extirq(unsigned long data)
        local_irq_enable();
 }
 
+static inline void skge_wakeup(struct net_device *dev)
+{
+       struct skge_port *skge = netdev_priv(dev);
+
+       prefetch(skge->rx_ring.to_clean);
+       netif_rx_schedule(dev);
+}
+
 static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct skge_hw *hw = dev_id;
@@ -2828,12 +2848,12 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
        status &= hw->intr_mask;
        if (status & IS_R1_F) {
                hw->intr_mask &= ~IS_R1_F;
-               netif_rx_schedule(hw->dev[0]);
+               skge_wakeup(hw->dev[0]);
        }
 
        if (status & IS_R2_F) {
                hw->intr_mask &= ~IS_R2_F;
-               netif_rx_schedule(hw->dev[1]);
+               skge_wakeup(hw->dev[1]);
        }
 
        if (status & IS_XA1_F)
@@ -3213,7 +3233,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
        }
 
 #ifdef __BIG_ENDIAN
-       /* byte swap decriptors in hardware */
+       /* byte swap descriptors in hardware */
        {
                u32 reg;
 
@@ -3253,7 +3273,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
        if (err)
                goto err_out_free_irq;
 
-       printk(KERN_INFO PFX "addr 0x%lx irq %d chip %s rev %d\n",
+       printk(KERN_INFO PFX DRV_VERSION " addr 0x%lx irq %d chip %s rev %d\n",
               pci_resource_start(pdev, 0), pdev->irq,
               skge_board_name(hw), hw->chip_rev);