ixgbe: remove open-coded skb_cow_head
[linux-2.6-microblaze.git] / drivers / net / ethernet / intel / ixgbe / ixgbe_main.c
index 9e5a366..c4c526b 100644 (file)
@@ -297,7 +297,8 @@ static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
                return;
        hw->hw_addr = NULL;
        e_dev_err("Adapter removed\n");
-       ixgbe_service_event_schedule(adapter);
+       if (test_bit(__IXGBE_SERVICE_INITED, &adapter->state))
+               ixgbe_service_event_schedule(adapter);
 }
 
 void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
@@ -5566,6 +5567,8 @@ static int ixgbe_resume(struct pci_dev *pdev)
                e_dev_err("Cannot enable PCI device from suspend\n");
                return err;
        }
+       smp_mb__before_clear_bit();
+       clear_bit(__IXGBE_DISABLED, &adapter->state);
        pci_set_master(pdev);
 
        pci_wake_from_d3(pdev, false);
@@ -5663,7 +5666,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
 
        ixgbe_release_hw_control(adapter);
 
-       pci_disable_device(pdev);
+       if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
+               pci_disable_device(pdev);
 
        return 0;
 }
@@ -6506,6 +6510,7 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,
        struct sk_buff *skb = first->skb;
        u32 vlan_macip_lens, type_tucmd;
        u32 mss_l4len_idx, l4len;
+       int err;
 
        if (skb->ip_summed != CHECKSUM_PARTIAL)
                return 0;
@@ -6513,11 +6518,9 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,
        if (!skb_is_gso(skb))
                return 0;
 
-       if (skb_header_cloned(skb)) {
-               int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-               if (err)
-                       return err;
-       }
+       err = skb_cow_head(skb, 0);
+       if (err < 0)
+               return err;
 
        /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
        type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP;
@@ -7042,9 +7045,9 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                tx_flags |= IXGBE_TX_FLAGS_SW_VLAN;
        }
 
-       skb_tx_timestamp(skb);
-
-       if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+       if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+                    !test_and_set_bit_lock(__IXGBE_PTP_TX_IN_PROGRESS,
+                                           &adapter->state))) {
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
                tx_flags |= IXGBE_TX_FLAGS_TSTAMP;
 
@@ -7054,6 +7057,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                schedule_work(&adapter->ptp_tx_work);
        }
 
+       skb_tx_timestamp(skb);
+
 #ifdef CONFIG_PCI_IOV
        /*
         * Use the l2switch_enable flag - would be false if the DMA
@@ -7072,8 +7077,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                                        IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT;
                if (tx_flags & IXGBE_TX_FLAGS_SW_VLAN) {
                        struct vlan_ethhdr *vhdr;
-                       if (skb_header_cloned(skb) &&
-                           pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+
+                       if (skb_cow_head(skb, 0))
                                goto out_drop;
                        vhdr = (struct vlan_ethhdr *)skb->data;
                        vhdr->h_vlan_TCI = htons(tx_flags >>
@@ -8018,6 +8023,10 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* EEPROM */
        memcpy(&hw->eeprom.ops, ii->eeprom_ops, sizeof(hw->eeprom.ops));
        eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       if (ixgbe_removed(hw->hw_addr)) {
+               err = -EIO;
+               goto err_ioremap;
+       }
        /* If EEPROM is valid (bit 8 = 1), use default otherwise use bit bang */
        if (!(eec & (1 << 8)))
                hw->eeprom.ops.read = &ixgbe_read_eeprom_bit_bang_generic;
@@ -8180,7 +8189,12 @@ skip_sriov:
        setup_timer(&adapter->service_timer, &ixgbe_service_timer,
                    (unsigned long) adapter);
 
+       if (ixgbe_removed(hw->hw_addr)) {
+               err = -EIO;
+               goto err_sw_init;
+       }
        INIT_WORK(&adapter->service_task, ixgbe_service_task);
+       set_bit(__IXGBE_SERVICE_INITED, &adapter->state);
        clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state);
 
        err = ixgbe_init_interrupt_scheme(adapter);
@@ -8311,7 +8325,8 @@ err_alloc_etherdev:
                                     pci_select_bars(pdev, IORESOURCE_MEM));
 err_pci_reg:
 err_dma:
-       pci_disable_device(pdev);
+       if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
+               pci_disable_device(pdev);
        return err;
 }
 
@@ -8380,7 +8395,8 @@ static void ixgbe_remove(struct pci_dev *pdev)
 
        pci_disable_pcie_error_reporting(pdev);
 
-       pci_disable_device(pdev);
+       if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
+               pci_disable_device(pdev);
 }
 
 /**
@@ -8487,14 +8503,23 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
 
 skip_bad_vf_detection:
 #endif /* CONFIG_PCI_IOV */
+       if (!test_bit(__IXGBE_SERVICE_INITED, &adapter->state))
+               return PCI_ERS_RESULT_DISCONNECT;
+
+       rtnl_lock();
        netif_device_detach(netdev);
 
-       if (state == pci_channel_io_perm_failure)
+       if (state == pci_channel_io_perm_failure) {
+               rtnl_unlock();
                return PCI_ERS_RESULT_DISCONNECT;
+       }
 
        if (netif_running(netdev))
                ixgbe_down(adapter);
-       pci_disable_device(pdev);
+
+       if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
+               pci_disable_device(pdev);
+       rtnl_unlock();
 
        /* Request a slot reset. */
        return PCI_ERS_RESULT_NEED_RESET;
@@ -8516,6 +8541,8 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
                e_err(probe, "Cannot re-enable PCI device after reset.\n");
                result = PCI_ERS_RESULT_DISCONNECT;
        } else {
+               smp_mb__before_clear_bit();
+               clear_bit(__IXGBE_DISABLED, &adapter->state);
                adapter->hw.hw_addr = adapter->io_addr;
                pci_set_master(pdev);
                pci_restore_state(pdev);