Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git] / drivers / net / sky2.c
index ebe7e25..4103e30 100644 (file)
@@ -23,6 +23,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/config.h>
 #include <linux/crc32.h>
 #include <linux/kernel.h>
 #include <linux/version.h>
@@ -50,7 +51,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.5"
+#define DRV_VERSION            "1.6.1"
 #define PFX                    DRV_NAME " "
 
 /*
@@ -65,7 +66,6 @@
 #define RX_MAX_PENDING         (RX_LE_SIZE/2 - 2)
 #define RX_DEF_PENDING         RX_MAX_PENDING
 #define RX_SKB_ALIGN           8
-#define RX_BUF_WRITE           16
 
 #define TX_RING_SIZE           512
 #define TX_DEF_PENDING         (TX_RING_SIZE - 1)
@@ -106,7 +106,6 @@ static const struct pci_device_id sky2_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
        { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },    /* DGE-560T */
-       { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) },    /* DGE-550SX */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
@@ -118,17 +117,10 @@ static const struct pci_device_id sky2_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) },
-       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) },
        { 0 }
 };
 
@@ -245,6 +237,7 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
                udelay(100);
 
                if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+                       sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON);
                        sky2_pci_write32(hw, PCI_DEV_REG3, 0);
                        reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
                        reg1 &= P_ASPM_CONTROL_MSK;
@@ -263,7 +256,6 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
                else
                        reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
                sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
-               udelay(100);
 
                if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
                        sky2_write8(hw, B2_Y2_CLK_GATE, 0);
@@ -329,7 +321,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
        }
 
        ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
-       if (hw->copper) {
+       if (sky2_is_copper(hw)) {
                if (hw->chip_id == CHIP_ID_YUKON_FE) {
                        /* enable automatic crossover */
                        ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
@@ -346,25 +338,37 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
                                ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
                        }
                }
-               gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
        } else {
                /* workaround for deviation #4.88 (CRC errors) */
                /* disable Automatic Crossover */
 
                ctrl &= ~PHY_M_PC_MDIX_MSK;
-               gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+       }
 
-               if (hw->chip_id == CHIP_ID_YUKON_XL) {
-                       /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
-                       gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
-                       ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
-                       ctrl &= ~PHY_M_MAC_MD_MSK;
-                       ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX);
-                       gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+       gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+       /* special setup for PHY 88E1112 Fiber */
+       if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) {
+               pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+               /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
+               gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
+               ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+               ctrl &= ~PHY_M_MAC_MD_MSK;
+               ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX);
+               gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
 
+               if (hw->pmd_type  == 'P') {
                        /* select page 1 to access Fiber registers */
                        gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1);
+
+                       /* for SFP-module set SIGDET polarity to low */
+                       ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+                       ctrl |= PHY_M_FIB_SIGD_POL;
+                       gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
                }
+
+               gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
        }
 
        ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
@@ -381,7 +385,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
        adv = PHY_AN_CSMA;
 
        if (sky2->autoneg == AUTONEG_ENABLE) {
-               if (hw->copper) {
+               if (sky2_is_copper(hw)) {
                        if (sky2->advertising & ADVERTISED_1000baseT_Full)
                                ct1000 |= PHY_M_1000C_AFD;
                        if (sky2->advertising & ADVERTISED_1000baseT_Half)
@@ -394,8 +398,12 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
                                adv |= PHY_M_AN_10_FD;
                        if (sky2->advertising & ADVERTISED_10baseT_Half)
                                adv |= PHY_M_AN_10_HD;
-               } else          /* special defines for FIBER (88E1011S only) */
-                       adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
+               } else {        /* special defines for FIBER (88E1040S only) */
+                       if (sky2->advertising & ADVERTISED_1000baseT_Full)
+                               adv |= PHY_M_AN_1000X_AFD;
+                       if (sky2->advertising & ADVERTISED_1000baseT_Half)
+                               adv |= PHY_M_AN_1000X_AHD;
+               }
 
                /* Set Flow-control capabilities */
                if (sky2->tx_pause && sky2->rx_pause)
@@ -678,7 +686,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
        sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
 
        if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
-               sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 512/8);
+               sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
                sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
                if (hw->dev[port]->mtu > ETH_DATA_LEN) {
                        /* set Tx GMAC FIFO Almost Empty Threshold */
@@ -690,10 +698,16 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
 
 }
 
-/* Assign Ram Buffer allocation in units of 64bit (8 bytes) */
-static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end)
+/* Assign Ram Buffer allocation.
+ * start and end are in units of 4k bytes
+ * ram registers are in units of 64bit words
+ */
+static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk)
 {
-       pr_debug(PFX "q %d %#x %#x\n", q, start, end);
+       u32 start, end;
+
+       start = startk * 4096/8;
+       end = (endk * 4096/8) - 1;
 
        sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
        sky2_write32(hw, RB_ADDR(q, RB_START), start);
@@ -702,7 +716,7 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end)
        sky2_write32(hw, RB_ADDR(q, RB_RP), start);
 
        if (q == Q_R1 || q == Q_R2) {
-               u32 space = end - start + 1;
+               u32 space = (endk - startk) * 4096/8;
                u32 tp = space - space/4;
 
                /* On receive queue's set the thresholds
@@ -951,14 +965,14 @@ static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 /*
  * It appears the hardware has a bug in the FIFO logic that
  * cause it to hang if the FIFO gets overrun and the receive buffer
- * is not aligned. ALso alloc_skb() won't align properly if slab
+ * is not aligned. Also dev_alloc_skb() won't align properly if slab
  * debugging is enabled.
  */
 static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask)
 {
        struct sk_buff *skb;
 
-       skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
+       skb = __dev_alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
        if (likely(skb)) {
                unsigned long p = (unsigned long) skb->data;
                skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p);
@@ -1084,16 +1098,19 @@ static int sky2_up(struct net_device *dev)
 
        sky2_mac_init(hw, port);
 
-       /* Determine available ram buffer space in qwords.  */
-       ramsize = sky2_read8(hw, B2_E_0) * 4096/8;
-
-       if (ramsize > 6*1024/8)
-               rxspace = ramsize - (ramsize + 2) / 3;
+       /* Determine available ram buffer space (in 4K blocks).
+        * Note: not sure about the FE setting below yet
+        */
+       if (hw->chip_id == CHIP_ID_YUKON_FE)
+               ramsize = 4;
        else
-               rxspace = ramsize / 2;
+               ramsize = sky2_read8(hw, B2_E_0);
+
+       /* Give transmitter one third (rounded up) */
+       rxspace = ramsize - (ramsize + 2) / 3;
 
-       sky2_ramset(hw, rxqaddr[port], 0, rxspace-1);
-       sky2_ramset(hw, txqaddr[port], rxspace, ramsize-1);
+       sky2_ramset(hw, rxqaddr[port], 0, rxspace);
+       sky2_ramset(hw, txqaddr[port], rxspace, ramsize);
 
        /* Make sure SyncQ is disabled */
        sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
@@ -1389,7 +1406,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
        }
 
        sky2->tx_cons = put;
-       if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
+       if (tx_avail(sky2) > MAX_SKB_TX_LE)
                netif_wake_queue(dev);
 }
 
@@ -1420,11 +1437,6 @@ static int sky2_down(struct net_device *dev)
        /* Stop more packets from being queued */
        netif_stop_queue(dev);
 
-       /* Disable port IRQ */
-       imask = sky2_read32(hw, B0_IMSK);
-       imask &= ~portirq_msk[port];
-       sky2_write32(hw, B0_IMSK, imask);
-
        sky2_phy_reset(hw, port);
 
        /* Stop transmitter */
@@ -1468,6 +1480,11 @@ static int sky2_down(struct net_device *dev)
        sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
        sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
 
+       /* Disable port IRQ */
+       imask = sky2_read32(hw, B0_IMSK);
+       imask &= ~portirq_msk[port];
+       sky2_write32(hw, B0_IMSK, imask);
+
        /* turn off LED's */
        sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
 
@@ -1496,7 +1513,7 @@ static int sky2_down(struct net_device *dev)
 
 static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
 {
-       if (!hw->copper)
+       if (!sky2_is_copper(hw))
                return SPEED_1000;
 
        if (hw->chip_id == CHIP_ID_YUKON_FE)
@@ -1678,13 +1695,13 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
        struct sky2_port *sky2 = netdev_priv(dev);
        u16 istatus, phystat;
 
-       if (!netif_running(dev))
-               return;
-
        spin_lock(&sky2->phy_lock);
        istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT);
        phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
 
+       if (!netif_running(dev))
+               goto out;
+
        if (netif_msg_intr(sky2))
                printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n",
                       sky2->netdev->name, istatus, phystat);
@@ -1854,7 +1871,7 @@ static struct sk_buff *sky2_receive(struct sky2_port *sky2,
                goto oversize;
 
        if (length < copybreak) {
-               skb = alloc_skb(length + 2, GFP_ATOMIC);
+               skb = dev_alloc_skb(length + 2);
                if (!skb)
                        goto resubmit;
 
@@ -1888,6 +1905,9 @@ resubmit:
        re->skb->ip_summed = CHECKSUM_NONE;
        sky2_rx_add(sky2, re->mapaddr);
 
+       /* Tell receiver about new buffers. */
+       sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put);
+
        return skb;
 
 oversize:
@@ -1934,9 +1954,7 @@ static inline int sky2_more_work(const struct sky2_hw *hw)
 /* Process status response ring */
 static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 {
-       struct sky2_port *sky2;
        int work_done = 0;
-       unsigned buf_write[2] = { 0, 0 };
        u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
 
        rmb();
@@ -1944,6 +1962,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
        while (hw->st_idx != hwidx) {
                struct sky2_status_le *le  = hw->st_le + hw->st_idx;
                struct net_device *dev;
+               struct sky2_port *sky2;
                struct sk_buff *skb;
                u32 status;
                u16 length;
@@ -1976,14 +1995,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 #endif
                                netif_receive_skb(skb);
 
-                       /* Update receiver after 16 frames */
-                       if (++buf_write[le->link] == RX_BUF_WRITE) {
-                               sky2_put_idx(hw, rxqaddr[le->link],
-                                            sky2->rx_put);
-                               buf_write[le->link] = 0;
-                       }
-
-                       /* Stop after net poll weight */
                        if (++work_done >= to_do)
                                goto exit_loop;
                        break;
@@ -2021,17 +2032,10 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
                }
        }
 
-exit_loop:
-       if (buf_write[0]) {
-               sky2 = netdev_priv(hw->dev[0]);
-               sky2_put_idx(hw, Q_R1, sky2->rx_put);
-       }
-
-       if (buf_write[1]) {
-               sky2 = netdev_priv(hw->dev[1]);
-               sky2_put_idx(hw, Q_R2, sky2->rx_put);
-       }
+       /* Fully processed status ring so clear irq */
+       sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
 
+exit_loop:
        return work_done;
 }
 
@@ -2233,9 +2237,6 @@ static int sky2_poll(struct net_device *dev0, int *budget)
        *budget -= work_done;
        dev0->quota -= work_done;
 
-       if (status & Y2_IS_STAT_BMU)
-               sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-
        if (sky2_more_work(hw))
                return 1;
 
@@ -2299,10 +2300,10 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
 }
 
 
-static int sky2_reset(struct sky2_hw *hw)
+static int __devinit sky2_reset(struct sky2_hw *hw)
 {
        u16 status;
-       u8 t8, pmd_type;
+       u8 t8;
        int i;
 
        sky2_write8(hw, B0_CTST, CS_RST_CLR);
@@ -2348,9 +2349,7 @@ static int sky2_reset(struct sky2_hw *hw)
                sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL);
 
 
-       pmd_type = sky2_read8(hw, B2_PMD_TYP);
-       hw->copper = !(pmd_type == 'L' || pmd_type == 'S');
-
+       hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
        hw->ports = 1;
        t8 = sky2_read8(hw, B2_Y2_HW_RES);
        if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
@@ -2447,21 +2446,22 @@ static int sky2_reset(struct sky2_hw *hw)
 
 static u32 sky2_supported_modes(const struct sky2_hw *hw)
 {
-       u32 modes;
-       if (hw->copper) {
-               modes = SUPPORTED_10baseT_Half
-                   | SUPPORTED_10baseT_Full
-                   | SUPPORTED_100baseT_Half
-                   | SUPPORTED_100baseT_Full
-                   | SUPPORTED_Autoneg | SUPPORTED_TP;
+       if (sky2_is_copper(hw)) {
+               u32 modes = SUPPORTED_10baseT_Half
+                       | SUPPORTED_10baseT_Full
+                       | SUPPORTED_100baseT_Half
+                       | SUPPORTED_100baseT_Full
+                       | SUPPORTED_Autoneg | SUPPORTED_TP;
 
                if (hw->chip_id != CHIP_ID_YUKON_FE)
                        modes |= SUPPORTED_1000baseT_Half
-                           | SUPPORTED_1000baseT_Full;
+                               | SUPPORTED_1000baseT_Full;
+               return modes;
        } else
-               modes = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE
-                   | SUPPORTED_Autoneg;
-       return modes;
+               return  SUPPORTED_1000baseT_Half
+                       | SUPPORTED_1000baseT_Full
+                       | SUPPORTED_Autoneg
+                       | SUPPORTED_FIBRE;
 }
 
 static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -2472,7 +2472,7 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        ecmd->transceiver = XCVR_INTERNAL;
        ecmd->supported = sky2_supported_modes(hw);
        ecmd->phy_address = PHY_ADDR_MARV;
-       if (hw->copper) {
+       if (sky2_is_copper(hw)) {
                ecmd->supported = SUPPORTED_10baseT_Half
                    | SUPPORTED_10baseT_Full
                    | SUPPORTED_100baseT_Half
@@ -2481,12 +2481,14 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                    | SUPPORTED_1000baseT_Full
                    | SUPPORTED_Autoneg | SUPPORTED_TP;
                ecmd->port = PORT_TP;
-       } else
+               ecmd->speed = sky2->speed;
+       } else {
+               ecmd->speed = SPEED_1000;
                ecmd->port = PORT_FIBRE;
+       }
 
        ecmd->advertising = sky2->advertising;
        ecmd->autoneg = sky2->autoneg;
-       ecmd->speed = sky2->speed;
        ecmd->duplex = sky2->duplex;
        return 0;
 }
@@ -2736,14 +2738,6 @@ static int sky2_set_mac_address(struct net_device *dev, void *p)
        return 0;
 }
 
-static void inline sky2_add_filter(u8 filter[8], const u8 *addr)
-{
-       u32 bit;
-
-       bit = ether_crc(ETH_ALEN, addr) & 63;
-       filter[bit >> 3] |= 1 << (bit & 7);
-}
-
 static void sky2_set_multicast(struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
@@ -2752,7 +2746,6 @@ static void sky2_set_multicast(struct net_device *dev)
        struct dev_mc_list *list = dev->mc_list;
        u16 reg;
        u8 filter[8];
-       static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
 
        memset(filter, 0, sizeof(filter));
 
@@ -2763,17 +2756,16 @@ static void sky2_set_multicast(struct net_device *dev)
                reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
        else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16)     /* all multicast */
                memset(filter, 0xff, sizeof(filter));
-       else if (dev->mc_count == 0 && !sky2->rx_pause)
+       else if (dev->mc_count == 0)    /* no multicast */
                reg &= ~GM_RXCR_MCF_ENA;
        else {
                int i;
                reg |= GM_RXCR_MCF_ENA;
 
-               if (sky2->rx_pause)
-                       sky2_add_filter(filter, pause_mc_addr);
-
-               for (i = 0; list && i < dev->mc_count; i++, list = list->next)
-                       sky2_add_filter(filter, list->dmi_addr);
+               for (i = 0; list && i < dev->mc_count; i++, list = list->next) {
+                       u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
+                       filter[bit / 8] |= 1 << (bit % 8);
+               }
        }
 
        gma_write16(hw, port, GM_MC_ADDR_H1,
@@ -3213,7 +3205,7 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
 
        sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
 
-       err = request_irq(pdev->irq, sky2_test_intr, IRQF_SHARED, DRV_NAME, hw);
+       err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw);
        if (err) {
                printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
                       pci_name(pdev), pdev->irq);
@@ -3227,8 +3219,9 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
 
        if (!hw->msi_detected) {
                /* MSI test failed, go back to INTx mode */
-               printk(KERN_INFO PFX "%s: No interrupt generated using MSI, "
-                      "switching to INTx mode.\n",
+               printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, "
+                      "switching to INTx mode. Please report this failure to "
+                      "the PCI maintainer and include system chipset information.\n",
                       pci_name(pdev));
 
                err = -EOPNOTSUPP;
@@ -3236,7 +3229,6 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
        }
 
        sky2_write32(hw, B0_IMSK, 0);
-       sky2_read32(hw, B0_IMSK);
 
        free_irq(pdev->irq, hw);
 
@@ -3333,9 +3325,9 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        if (err)
                goto err_out_iounmap;
 
-       printk(KERN_INFO PFX "v%s addr 0x%llx irq %d Yukon-%s (0x%x) rev %d\n",
-              DRV_VERSION, (unsigned long long)pci_resource_start(pdev, 0),
-              pdev->irq, yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
+       printk(KERN_INFO PFX "v%s addr 0x%lx irq %d Yukon-%s (0x%x) rev %d\n",
+              DRV_VERSION, pci_resource_start(pdev, 0), pdev->irq,
+              yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
               hw->chip_id, hw->chip_rev);
 
        dev = sky2_init_netdev(hw, 0, using_dac);
@@ -3371,7 +3363,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                        goto err_out_unregister;
        }
 
-       err = request_irq(pdev->irq,  sky2_intr, IRQF_SHARED, DRV_NAME, hw);
+       err = request_irq(pdev->irq,  sky2_intr, SA_SHIRQ, DRV_NAME, hw);
        if (err) {
                printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
                       pci_name(pdev), pdev->irq);
@@ -3460,14 +3452,17 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
                return -EINVAL;
 
        del_timer_sync(&hw->idle_timer);
-       netif_poll_disable(hw->dev[0]);
 
        for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
 
-               if (netif_running(dev)) {
+               if (dev) {
+                       if (!netif_running(dev))
+                               continue;
+
                        sky2_down(dev);
                        netif_device_detach(dev);
+                       netif_poll_disable(dev);
                }
        }
 
@@ -3494,8 +3489,9 @@ static int sky2_resume(struct pci_dev *pdev)
 
        for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
-               if (netif_running(dev)) {
+               if (dev && netif_running(dev)) {
                        netif_device_attach(dev);
+                       netif_poll_enable(dev);
 
                        err = sky2_up(dev);
                        if (err) {
@@ -3507,7 +3503,6 @@ static int sky2_resume(struct pci_dev *pdev)
                }
        }
 
-       netif_poll_enable(hw->dev[0]);
        sky2_idle_start(hw);
 out:
        return err;