Merge branch 'pstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux
[pandora-kernel.git] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_main.c
index 501e16b..0bd1638 100644 (file)
@@ -2135,13 +2135,13 @@ qlcnic_map_tx_skb(struct pci_dev *pdev,
                frag = &skb_shinfo(skb)->frags[i];
                nf = &pbuf->frag_array[i+1];
 
-               map = skb_frag_dma_map(&pdev->dev, frag, 0, frag->size,
-                                      PCI_DMA_TODEVICE);
-               if (pci_dma_mapping_error(pdev, map))
+               map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
+                                      DMA_TO_DEVICE);
+               if (dma_mapping_error(&pdev->dev, map))
                        goto unwind;
 
                nf->dma = map;
-               nf->length = frag->size;
+               nf->length = skb_frag_size(frag);
        }
 
        return 0;
@@ -2221,7 +2221,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
 
                for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
-                       delta += skb_shinfo(skb)->frags[i].size;
+                       delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
 
                if (!__pskb_pull_tail(skb, delta))
                        goto drop_packet;
@@ -2840,8 +2840,15 @@ qlcnic_fwinit_work(struct work_struct *work)
                goto wait_npar;
        }
 
+       if (dev_state == QLCNIC_DEV_INITIALIZING ||
+           dev_state == QLCNIC_DEV_READY) {
+               dev_info(&adapter->pdev->dev, "Detected state change from "
+                               "DEV_NEED_RESET, skipping ack check\n");
+               goto skip_ack_check;
+       }
+
        if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) {
-               dev_err(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
+               dev_info(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n",
                                        adapter->reset_ack_timeo);
                goto skip_ack_check;
        }
@@ -3087,7 +3094,7 @@ static int
 qlcnic_check_health(struct qlcnic_adapter *adapter)
 {
        u32 state = 0, heartbeat;
-       struct net_device *netdev = adapter->netdev;
+       u32 peg_status;
 
        if (qlcnic_check_temp(adapter))
                goto detach;
@@ -3127,8 +3134,8 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
        if (auto_fw_reset)
                clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
 
-       dev_info(&netdev->dev, "firmware hang detected\n");
-       dev_info(&adapter->pdev->dev, "Dumping hw/fw registers\n"
+       dev_err(&adapter->pdev->dev, "firmware hang detected\n");
+       dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n"
                        "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"
                        "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"
                        "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"
@@ -3140,6 +3147,11 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
                        QLCRD32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c),
                        QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c),
                        QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c));
+       peg_status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
+       if (LSW(MSB(peg_status)) == 0x67)
+               dev_err(&adapter->pdev->dev,
+                       "Firmware aborted with error code 0x00006700. "
+                               "Device is being reset.\n");
 detach:
        adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
                QLCNIC_DEV_NEED_RESET;
@@ -3492,11 +3504,16 @@ qlcnic_store_beacon(struct device *dev,
 {
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        int max_sds_rings = adapter->max_sds_rings;
-       int dev_down = 0;
        u16 beacon;
        u8 b_state, b_rate;
        int err;
 
+       if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+               dev_warn(dev, "LED test not supported for non "
+                               "privilege function\n");
+               return -EOPNOTSUPP;
+       }
+
        if (len != sizeof(u16))
                return QL_STATUS_INVALID_PARAM;
 
@@ -3508,36 +3525,40 @@ qlcnic_store_beacon(struct device *dev,
        if (adapter->ahw->beacon_state == b_state)
                return len;
 
+       rtnl_lock();
+
        if (!adapter->ahw->beacon_state)
-               if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
+               if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
+                       rtnl_unlock();
                        return -EBUSY;
+               }
+
+       if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
+               err = -EIO;
+               goto out;
+       }
 
        if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
-               if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
-                       return -EIO;
                err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
-               if (err) {
-                       clear_bit(__QLCNIC_RESETTING, &adapter->state);
-                       clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
-                       return err;
-               }
-               dev_down = 1;
+               if (err)
+                       goto out;
+               set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
        }
 
        err = qlcnic_config_led(adapter, b_state, b_rate);
 
        if (!err) {
-               adapter->ahw->beacon_state = b_state;
                err = len;
+               adapter->ahw->beacon_state = b_state;
        }
 
-       if (dev_down) {
+       if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
                qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
-               clear_bit(__QLCNIC_RESETTING, &adapter->state);
-       }
 
-       if (!b_state)
+ out:
+       if (!adapter->ahw->beacon_state)
                clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
+       rtnl_unlock();
 
        return err;
 }