[S390] Add support for memory hot-remove.
[safe/jmp/linux-2.6] / drivers / net / qla3xxx.c
old mode 100755 (executable)
new mode 100644 (file)
index ed79aa8..e82b37b
@@ -81,7 +81,7 @@ typedef enum {
 } PHY_DEVICE_et;
 
 typedef struct {
-       PHY_DEVICE_et phyDevice; 
+       PHY_DEVICE_et phyDevice;
        u32             phyIdOUI;
        u16             phyIdModel;
        char            *name;
@@ -328,9 +328,9 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
                                             qdev->lrg_buffer_len -
                                             QL_HEADER_SPACE,
                                             PCI_DMA_FROMDEVICE);
-                       err = pci_dma_mapping_error(map);
+                       err = pci_dma_mapping_error(qdev->pdev, map);
                        if(err) {
-                               printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+                               printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
                                       qdev->ndev->name, err);
                                dev_kfree_skb(lrg_buf_cb->skb);
                                lrg_buf_cb->skb = NULL;
@@ -540,20 +540,12 @@ static void eeprom_readword(struct ql3_adapter *qdev,
        fm93c56a_deselect(qdev);
 }
 
-static void ql_swap_mac_addr(u8 * macAddress)
+static void ql_set_mac_addr(struct net_device *ndev, u16 *addr)
 {
-#ifdef __BIG_ENDIAN
-       u8 temp;
-       temp = macAddress[0];
-       macAddress[0] = macAddress[1];
-       macAddress[1] = temp;
-       temp = macAddress[2];
-       macAddress[2] = macAddress[3];
-       macAddress[3] = temp;
-       temp = macAddress[4];
-       macAddress[4] = macAddress[5];
-       macAddress[5] = temp;
-#endif
+       __le16 *p = (__le16 *)ndev->dev_addr;
+       p[0] = cpu_to_le16(addr[0]);
+       p[1] = cpu_to_le16(addr[1]);
+       p[2] = cpu_to_le16(addr[2]);
 }
 
 static int ql_get_nvram_params(struct ql3_adapter *qdev)
@@ -590,18 +582,6 @@ static int ql_get_nvram_params(struct ql3_adapter *qdev)
                return -1;
        }
 
-       /*
-        * We have a problem with endianness for the MAC addresses
-        * and the two 8-bit values version, and numPorts.  We
-        * have to swap them on big endian systems.
-        */
-       ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn0.macAddress);
-       ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn1.macAddress);
-       ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn2.macAddress);
-       ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn3.macAddress);
-       pEEPROMData = (u16 *) & qdev->nvram_data.version;
-       *pEEPROMData = le16_to_cpu(*pEEPROMData);
-
        spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
        return checksum;
 }
@@ -711,7 +691,7 @@ static int ql_mii_write_reg_ex(struct ql3_adapter *qdev,
        if (ql_wait_for_mii_ready(qdev)) {
                if (netif_msg_link(qdev))
                        printk(KERN_WARNING PFX
-                              "%s: Timed out waiting for management port to"
+                              "%s: Timed out waiting for management port to "
                               "get free before issuing command.\n",
                               qdev->ndev->name);
                return -1;
@@ -884,14 +864,14 @@ static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev)
        u16 reg;
 
        /* Enable Auto-negotiation sense */
-       ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, &reg, 
+       ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, &reg,
                           PHYAddr[qdev->mac_index]);
        reg |= PETBI_TBI_AUTO_SENSE;
-       ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg, 
+       ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg,
                            PHYAddr[qdev->mac_index]);
 
        ql_mii_write_reg_ex(qdev, PETBI_NEG_ADVER,
-                           PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX, 
+                           PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX,
                            PHYAddr[qdev->mac_index]);
 
        ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG,
@@ -945,7 +925,7 @@ static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr)
        ql_mii_write_reg_ex(qdev, 0x10, 0x2806, miiAddr);
        /* Write new PHYAD w/bit 5 set */
        ql_mii_write_reg_ex(qdev, 0x11, 0x0020 | (PHYAddr[qdev->mac_index] >> 8), miiAddr);
-       /* 
+       /*
         * Disable diagnostic mode bit 2 = 0
         * Power up device bit 11 = 0
         * Link up (on) and activity (blink)
@@ -955,18 +935,18 @@ static void phyAgereSpecificInit(struct ql3_adapter *qdev, u32 miiAddr)
        ql_mii_write_reg(qdev, 0x1c, 0xfaf0);
 }
 
-static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev, 
+static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev,
                                 u16 phyIdReg0, u16 phyIdReg1)
 {
        PHY_DEVICE_et result = PHY_TYPE_UNKNOWN;
-       u32   oui;     
+       u32   oui;
        u16   model;
-       int i;   
+       int i;
 
        if (phyIdReg0 == 0xffff) {
                return result;
        }
-   
+
        if (phyIdReg1 == 0xffff) {
                return result;
        }
@@ -984,7 +964,7 @@ static PHY_DEVICE_et getPhyType (struct ql3_adapter *qdev,
 
                        printk(KERN_INFO "%s: Phy: %s\n",
                                qdev->ndev->name, PHY_DEVICES[i].name);
-                       
+
                        break;
                }
        }
@@ -1033,7 +1013,7 @@ static int ql_is_full_dup(struct ql3_adapter *qdev)
        {
                if (ql_mii_read_reg(qdev, 0x1A, &reg))
                        return 0;
-                       
+
                return ((reg & 0x0080) && (reg & 0x1000)) != 0;
        }
        case PHY_VITESSE_VSC8211:
@@ -1082,19 +1062,19 @@ static int PHY_Setup(struct ql3_adapter *qdev)
        /*  Check if we have a Agere PHY */
        if ((reg1 == 0xffff) || (reg2 == 0xffff)) {
 
-               /* Determine which MII address we should be using 
+               /* Determine which MII address we should be using
                   determined by the index of the card */
                if (qdev->mac_index == 0) {
                        miiAddr = MII_AGERE_ADDR_1;
                } else {
                        miiAddr = MII_AGERE_ADDR_2;
                }
-      
+
                err =ql_mii_read_reg_ex(qdev, PHY_ID_0_REG, &reg1, miiAddr);
                if(err != 0) {
                        printk(KERN_ERR "%s: Could not read from reg PHY_ID_0_REG after Agere detected\n",
                               qdev->ndev->name);
-                       return err; 
+                       return err;
                }
 
                err = ql_mii_read_reg_ex(qdev, PHY_ID_1_REG, &reg2, miiAddr);
@@ -1103,9 +1083,9 @@ static int PHY_Setup(struct ql3_adapter *qdev)
                               qdev->ndev->name);
                        return err;
                }
-   
+
                /*  We need to remember to initialize the Agere PHY */
-               agereAddrChangeNeeded = true; 
+               agereAddrChangeNeeded = true;
        }
 
        /*  Determine the particular PHY we have on board to apply
@@ -1114,7 +1094,7 @@ static int PHY_Setup(struct ql3_adapter *qdev)
 
        if ((qdev->phyType == PHY_AGERE_ET1011C) && agereAddrChangeNeeded) {
                /* need this here so address gets changed */
-               phyAgereSpecificInit(qdev, miiAddr);  
+               phyAgereSpecificInit(qdev, miiAddr);
        } else if (qdev->phyType == PHY_TYPE_UNKNOWN) {
                printk(KERN_ERR "%s: PHY is unknown\n", qdev->ndev->name);
                return -EIO;
@@ -1427,7 +1407,7 @@ static int ql_this_adapter_controls_port(struct ql3_adapter *qdev)
 
 static void ql_phy_reset_ex(struct ql3_adapter *qdev)
 {
-       ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET, 
+       ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET,
                            PHYAddr[qdev->mac_index]);
 }
 
@@ -1438,7 +1418,7 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
 
        if(qdev->phyType == PHY_AGERE_ET1011C) {
                /* turn off external loopback */
-               ql_mii_write_reg(qdev, 0x13, 0x0000); 
+               ql_mii_write_reg(qdev, 0x13, 0x0000);
        }
 
        if(qdev->mac_index == 0)
@@ -1452,23 +1432,18 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
                portConfiguration = PORT_CONFIG_DEFAULT;
 
        /* Set the 1000 advertisements */
-       ql_mii_read_reg_ex(qdev, PHY_GIG_CONTROL, &reg, 
+       ql_mii_read_reg_ex(qdev, PHY_GIG_CONTROL, &reg,
                           PHYAddr[qdev->mac_index]);
        reg &= ~PHY_GIG_ALL_PARAMS;
 
-       if(portConfiguration & 
-          PORT_CONFIG_FULL_DUPLEX_ENABLED &
-          PORT_CONFIG_1000MB_SPEED) {
-               reg |= PHY_GIG_ADV_1000F;
-       }
-        
-       if(portConfiguration & 
-          PORT_CONFIG_HALF_DUPLEX_ENABLED &
-          PORT_CONFIG_1000MB_SPEED) {
-               reg |= PHY_GIG_ADV_1000H;
+       if(portConfiguration & PORT_CONFIG_1000MB_SPEED) {
+               if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED)
+                       reg |= PHY_GIG_ADV_1000F;
+               else
+                       reg |= PHY_GIG_ADV_1000H;
        }
 
-       ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg, 
+       ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg,
                            PHYAddr[qdev->mac_index]);
 
        /* Set the 10/100 & pause negotiation advertisements */
@@ -1482,7 +1457,7 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
        if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) {
                if(portConfiguration & PORT_CONFIG_100MB_SPEED)
                        reg |= PHY_NEG_ADV_100F;
-               
+
                if(portConfiguration & PORT_CONFIG_10MB_SPEED)
                        reg |= PHY_NEG_ADV_10F;
        }
@@ -1490,22 +1465,22 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev)
        if(portConfiguration & PORT_CONFIG_HALF_DUPLEX_ENABLED) {
                if(portConfiguration & PORT_CONFIG_100MB_SPEED)
                        reg |= PHY_NEG_ADV_100H;
-               
+
                if(portConfiguration & PORT_CONFIG_10MB_SPEED)
                        reg |= PHY_NEG_ADV_10H;
        }
 
        if(portConfiguration &
           PORT_CONFIG_1000MB_SPEED) {
-               reg |= 1;       
+               reg |= 1;
        }
 
-       ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, reg, 
+       ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER, reg,
                            PHYAddr[qdev->mac_index]);
 
        ql_mii_read_reg_ex(qdev, CONTROL_REG, &reg, PHYAddr[qdev->mac_index]);
-       
-       ql_mii_write_reg_ex(qdev, CONTROL_REG, 
+
+       ql_mii_write_reg_ex(qdev, CONTROL_REG,
                            reg | PHY_CTRL_RESTART_NEG | PHY_CTRL_AUTO_NEG,
                            PHYAddr[qdev->mac_index]);
 }
@@ -1645,8 +1620,11 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev)
        return 0;
 }
 
-static void ql_link_state_machine(struct ql3_adapter *qdev)
+static void ql_link_state_machine_work(struct work_struct *work)
 {
+       struct ql3_adapter *qdev =
+               container_of(work, struct ql3_adapter, link_state_work.work);
+
        u32 curr_link_state;
        unsigned long hw_flags;
 
@@ -1660,7 +1638,11 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
                               "%s: Reset in progress, skip processing link "
                               "state.\n", qdev->ndev->name);
 
-               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);               
+               spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+               /* Restart timer on 2 second interval. */
+               mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);\
+
                return;
        }
 
@@ -1705,6 +1687,9 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
                break;
        }
        spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+       /* Restart timer on 2 second interval. */
+       mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
 }
 
 /*
@@ -1752,7 +1737,7 @@ static int ql_mii_setup(struct ql3_adapter *qdev)
                return -1;
 
        if (qdev->device_id == QL3032_DEVICE_ID)
-               ql_write_page0_reg(qdev, 
+               ql_write_page0_reg(qdev,
                        &port_regs->macMIIMgmtControlReg, 0x0f00000);
 
        /* Divide 125MHz clock by 28 to meet PHY timing requirements */
@@ -1865,8 +1850,6 @@ static void ql_get_drvinfo(struct net_device *ndev,
        strncpy(drvinfo->version, ql3xxx_driver_version, 32);
        strncpy(drvinfo->fw_version, "N/A", 32);
        strncpy(drvinfo->bus_info, pci_name(qdev->pdev), 32);
-       drvinfo->n_stats = 0;
-       drvinfo->testinfo_len = 0;
        drvinfo->regdump_len = 0;
        drvinfo->eedump_len = 0;
 }
@@ -1936,9 +1919,9 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
                                                     QL_HEADER_SPACE,
                                                     PCI_DMA_FROMDEVICE);
 
-                               err = pci_dma_mapping_error(map);
+                               err = pci_dma_mapping_error(qdev->pdev, map);
                                if(err) {
-                                       printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+                                       printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
                                               qdev->ndev->name, err);
                                        dev_kfree_skb(lrg_buf_cb->skb);
                                        lrg_buf_cb->skb = NULL;
@@ -2046,7 +2029,7 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
        if(mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
                printk(KERN_WARNING "Frame short but, frame was padded and sent.\n");
        }
-       
+
        tx_cb = &qdev->tx_buf[mac_rsp->transaction_id];
 
        /*  Check the transmit response flags for any errors */
@@ -2110,13 +2093,13 @@ static struct ql_rcv_buf_cb *ql_get_lbuf(struct ql3_adapter *qdev)
 
 /*
  * The difference between 3022 and 3032 for inbound completions:
- * 3022 uses two buffers per completion.  The first buffer contains 
- * (some) header info, the second the remainder of the headers plus 
- * the data.  For this chip we reserve some space at the top of the 
- * receive buffer so that the header info in buffer one can be 
- * prepended to the buffer two.  Buffer two is the sent up while 
+ * 3022 uses two buffers per completion.  The first buffer contains
+ * (some) header info, the second the remainder of the headers plus
+ * the data.  For this chip we reserve some space at the top of the
+ * receive buffer so that the header info in buffer one can be
+ * prepended to the buffer two.  Buffer two is the sent up while
  * buffer one is returned to the hardware to be reused.
- * 3032 receives all of it's data and headers in one buffer for a 
+ * 3032 receives all of it's data and headers in one buffer for a
  * simpler process.  3032 also supports checksum verification as
  * can be seen in ql_process_macip_rx_intr().
  */
@@ -2207,13 +2190,13 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
                                                 skb_push(skb2, size), size);
        } else {
                u16 checksum = le16_to_cpu(ib_ip_rsp_ptr->checksum);
-               if (checksum & 
-                       (IB_IP_IOCB_RSP_3032_ICE | 
-                        IB_IP_IOCB_RSP_3032_CE)) { 
+               if (checksum &
+                       (IB_IP_IOCB_RSP_3032_ICE |
+                        IB_IP_IOCB_RSP_3032_CE)) {
                        printk(KERN_ERR
                               "%s: Bad checksum for this %s packet, checksum = %x.\n",
                               __func__,
-                              ((checksum & 
+                              ((checksum &
                                IB_IP_IOCB_RSP_3032_TCP) ? "TCP" :
                                "UDP"),checksum);
                } else if ((checksum & IB_IP_IOCB_RSP_3032_TCP) ||
@@ -2317,14 +2300,9 @@ static int ql_poll(struct napi_struct *napi, int budget)
        unsigned long hw_flags;
        struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
 
-       if (!netif_carrier_ok(ndev))
-               goto quit_polling;
-
        ql_tx_rx_clean(qdev, &tx_cleaned, &rx_cleaned, budget);
 
-       if (tx_cleaned + rx_cleaned != budget ||
-           !netif_running(ndev)) {
-quit_polling:
+       if (tx_cleaned + rx_cleaned != budget) {
                spin_lock_irqsave(&qdev->hw_lock, hw_flags);
                __netif_rx_complete(ndev, napi);
                ql_update_small_bufq_prod_index(qdev);
@@ -2396,12 +2374,12 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
 }
 
 /*
- * Get the total number of segments needed for the 
+ * Get the total number of segments needed for the
  * given number of fragments.  This is necessary because
  * outbound address lists (OAL) will be used when more than
- * two frags are given.  Each address list has 5 addr/len 
+ * two frags are given.  Each address list has 5 addr/len
  * pairs.  The 5th pair in each AOL is used to  point to
- * the next AOL if more frags are coming.  
+ * the next AOL if more frags are coming.
  * That is why the frags:segment count  ratio is not linear.
  */
 static int ql_get_seg_count(struct ql3_adapter *qdev,
@@ -2476,14 +2454,14 @@ static int ql_send_map(struct ql3_adapter *qdev,
         */
        map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE);
 
-       err = pci_dma_mapping_error(map);
+       err = pci_dma_mapping_error(qdev->pdev, map);
        if(err) {
-               printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+               printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
                       qdev->ndev->name, err);
 
                return NETDEV_TX_BUSY;
        }
-       
+
        oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
        oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
        oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
@@ -2494,8 +2472,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
 
        if (seg_cnt == 1) {
                /* Terminate the last segment. */
-               oal_entry->len =
-                   cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
+               oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
        } else {
                oal = tx_cb->oal;
                for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) {
@@ -2510,10 +2487,10 @@ static int ql_send_map(struct ql3_adapter *qdev,
                                                     sizeof(struct oal),
                                                     PCI_DMA_TODEVICE);
 
-                               err = pci_dma_mapping_error(map);
+                               err = pci_dma_mapping_error(qdev->pdev, map);
                                if(err) {
 
-                                       printk(KERN_ERR "%s: PCI mapping outbound address list with error: %d\n", 
+                                       printk(KERN_ERR "%s: PCI mapping outbound address list with error: %d\n",
                                               qdev->ndev->name, err);
                                        goto map_error;
                                }
@@ -2537,9 +2514,9 @@ static int ql_send_map(struct ql3_adapter *qdev,
                                         frag->page_offset, frag->size,
                                         PCI_DMA_TODEVICE);
 
-                       err = pci_dma_mapping_error(map);
+                       err = pci_dma_mapping_error(qdev->pdev, map);
                        if(err) {
-                               printk(KERN_ERR "%s: PCI mapping frags failed with error: %d\n", 
+                               printk(KERN_ERR "%s: PCI mapping frags failed with error: %d\n",
                                       qdev->ndev->name, err);
                                goto map_error;
                        }
@@ -2552,18 +2529,17 @@ static int ql_send_map(struct ql3_adapter *qdev,
                                          frag->size);
                }
                /* Terminate the last segment. */
-               oal_entry->len =
-                   cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
+               oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
        }
 
        return NETDEV_TX_OK;
 
 map_error:
        /* A PCI mapping failed and now we will need to back out
-        * We need to traverse through the oal's and associated pages which 
+        * We need to traverse through the oal's and associated pages which
         * have been mapped and now we must unmap them to clean up properly
         */
-       
+
        seg = 1;
        oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
        oal = tx_cb->oal;
@@ -2601,11 +2577,11 @@ map_error:
  * The difference between 3022 and 3032 sends:
  * 3022 only supports a simple single segment transmission.
  * 3032 supports checksumming and scatter/gather lists (fragments).
- * The 3032 supports sglists by using the 3 addr/len pairs (ALP) 
- * in the IOCB plus a chain of outbound address lists (OAL) that 
- * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th) 
- * will used to point to an OAL when more ALP entries are required.  
- * The IOCB is always the top of the chain followed by one or more 
+ * The 3032 supports sglists by using the 3 addr/len pairs (ALP)
+ * in the IOCB plus a chain of outbound address lists (OAL) that
+ * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th)
+ * will used to point to an OAL when more ALP entries are required.
+ * The IOCB is always the top of the chain followed by one or more
  * OALs (when necessary).
  */
 static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
@@ -2619,14 +2595,14 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
        if (unlikely(atomic_read(&qdev->tx_count) < 2)) {
                return NETDEV_TX_BUSY;
        }
-       
+
        tx_cb = &qdev->tx_buf[qdev->req_producer_index] ;
        if((tx_cb->seg_count = ql_get_seg_count(qdev,
                                                (skb_shinfo(skb)->nr_frags))) == -1) {
                printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__);
                return NETDEV_TX_OK;
        }
-       
+
        mac_iocb_ptr = tx_cb->queue_entry;
        memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req));
        mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
@@ -2638,12 +2614,12 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
        if (qdev->device_id == QL3032_DEVICE_ID &&
            skb->ip_summed == CHECKSUM_PARTIAL)
                ql_hw_csum_setup(skb, mac_iocb_ptr);
-       
+
        if(ql_send_map(qdev,mac_iocb_ptr,tx_cb,skb) != NETDEV_TX_OK) {
                printk(KERN_ERR PFX"%s: Could not map the segments!\n",__func__);
                return NETDEV_TX_BUSY;
        }
-       
+
        wmb();
        qdev->req_producer_index++;
        if (qdev->req_producer_index == NUM_REQ_Q_ENTRIES)
@@ -2741,7 +2717,7 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
                       "%s: qdev->lrg_buf alloc failed.\n", qdev->ndev->name);
                return -ENOMEM;
        }
-       
+
        qdev->lrg_buf_q_alloc_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 qdev->lrg_buf_q_alloc_size,
@@ -2940,7 +2916,7 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
                                             QL_HEADER_SPACE,
                                             PCI_DMA_FROMDEVICE);
 
-                       err = pci_dma_mapping_error(map);
+                       err = pci_dma_mapping_error(qdev->pdev, map);
                        if(err) {
                                printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
                                       qdev->ndev->name, err);
@@ -3037,7 +3013,7 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
                    LS_64BITS(qdev->shadow_reg_phy_addr);
 
                qdev->prsp_producer_index =
-                   (u32 *) (((u8 *) qdev->preq_consumer_index) + 8);
+                   (__le32 *) (((u8 *) qdev->preq_consumer_index) + 8);
                qdev->rsp_producer_index_phy_addr_high =
                    qdev->req_consumer_index_phy_addr_high;
                qdev->rsp_producer_index_phy_addr_low =
@@ -3217,7 +3193,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
        ql_write_page1_reg(qdev, &hmem_regs->reqLength, NUM_REQ_Q_ENTRIES);
 
        /* Response Queue Registers */
-       *((u16 *) (qdev->prsp_producer_index)) = 0;
+       *((__le16 *) (qdev->prsp_producer_index)) = 0;
        qdev->rsp_consumer_index = 0;
        qdev->rsp_current = qdev->rsp_q_virt_addr;
 
@@ -3550,7 +3526,7 @@ static void ql_set_mac_info(struct ql3_adapter *qdev)
                       qdev->ndev->name,value);
                break;
        }
-       qdev->numPorts = qdev->nvram_data.numPorts;
+       qdev->numPorts = qdev->nvram_data.version_and_numPorts >> 8;
 }
 
 static void ql_display_dev_info(struct net_device *ndev)
@@ -3725,7 +3701,9 @@ static int ql_cycle_adapter(struct ql3_adapter *qdev, int reset)
                printk(KERN_ERR PFX
                                "%s: Driver up/down cycle failed, "
                                "closing device\n",qdev->ndev->name);
+               rtnl_lock();
                dev_close(qdev->ndev);
+               rtnl_unlock();
                return -1;
        }
        return 0;
@@ -3943,19 +3921,7 @@ static void ql_get_board_info(struct ql3_adapter *qdev)
 static void ql3xxx_timer(unsigned long ptr)
 {
        struct ql3_adapter *qdev = (struct ql3_adapter *)ptr;
-
-       if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) {
-               printk(KERN_DEBUG PFX
-                      "%s: Reset in progress.\n",
-                      qdev->ndev->name);
-               goto end;
-       }
-
-       ql_link_state_machine(qdev);
-
-       /* Restart timer on 2 second interval. */
-end:
-       mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
+       queue_delayed_work(qdev->workqueue, &qdev->link_state_work, 0);
 }
 
 static int __devinit ql3xxx_probe(struct pci_dev *pdev,
@@ -4065,12 +4031,10 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
        /* Validate and set parameters */
        if (qdev->mac_index) {
                ndev->mtu = qdev->nvram_data.macCfg_port1.etherMtu_mac ;
-               memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn2.macAddress,
-                      ETH_ALEN);
+               ql_set_mac_addr(ndev, qdev->nvram_data.funcCfg_fn2.macAddress);
        } else {
                ndev->mtu = qdev->nvram_data.macCfg_port0.etherMtu_mac ;
-               memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn0.macAddress,
-                      ETH_ALEN);
+               ql_set_mac_addr(ndev, qdev->nvram_data.funcCfg_fn0.macAddress);
        }
        memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
 
@@ -4105,6 +4069,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
        qdev->workqueue = create_singlethread_workqueue(ndev->name);
        INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work);
        INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work);
+       INIT_DELAYED_WORK(&qdev->link_state_work, ql_link_state_machine_work);
 
        init_timer(&qdev->adapter_timer);
        qdev->adapter_timer.function = ql3xxx_timer;