diff options
Diffstat (limited to 'drivers/net/e1000e/netdev.c')
-rw-r--r-- | drivers/net/e1000e/netdev.c | 185 |
1 files changed, 170 insertions, 15 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 05b0b2f9c54b..d266510c8a94 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -510,9 +510,12 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, | |||
510 | netdev_alloc_skb(netdev, length + NET_IP_ALIGN); | 510 | netdev_alloc_skb(netdev, length + NET_IP_ALIGN); |
511 | if (new_skb) { | 511 | if (new_skb) { |
512 | skb_reserve(new_skb, NET_IP_ALIGN); | 512 | skb_reserve(new_skb, NET_IP_ALIGN); |
513 | memcpy(new_skb->data - NET_IP_ALIGN, | 513 | skb_copy_to_linear_data_offset(new_skb, |
514 | skb->data - NET_IP_ALIGN, | 514 | -NET_IP_ALIGN, |
515 | length + NET_IP_ALIGN); | 515 | (skb->data - |
516 | NET_IP_ALIGN), | ||
517 | (length + | ||
518 | NET_IP_ALIGN)); | ||
516 | /* save the skb in buffer_info as good */ | 519 | /* save the skb in buffer_info as good */ |
517 | buffer_info->skb = skb; | 520 | buffer_info->skb = skb; |
518 | skb = new_skb; | 521 | skb = new_skb; |
@@ -1233,26 +1236,36 @@ static irqreturn_t e1000_intr(int irq, void *data) | |||
1233 | return IRQ_HANDLED; | 1236 | return IRQ_HANDLED; |
1234 | } | 1237 | } |
1235 | 1238 | ||
1239 | /** | ||
1240 | * e1000_request_irq - initialize interrupts | ||
1241 | * | ||
1242 | * Attempts to configure interrupts using the best available | ||
1243 | * capabilities of the hardware and kernel. | ||
1244 | **/ | ||
1236 | static int e1000_request_irq(struct e1000_adapter *adapter) | 1245 | static int e1000_request_irq(struct e1000_adapter *adapter) |
1237 | { | 1246 | { |
1238 | struct net_device *netdev = adapter->netdev; | 1247 | struct net_device *netdev = adapter->netdev; |
1239 | irq_handler_t handler = e1000_intr; | ||
1240 | int irq_flags = IRQF_SHARED; | 1248 | int irq_flags = IRQF_SHARED; |
1241 | int err; | 1249 | int err; |
1242 | 1250 | ||
1243 | if (!pci_enable_msi(adapter->pdev)) { | 1251 | if (!(adapter->flags & FLAG_MSI_TEST_FAILED)) { |
1244 | adapter->flags |= FLAG_MSI_ENABLED; | 1252 | err = pci_enable_msi(adapter->pdev); |
1245 | handler = e1000_intr_msi; | 1253 | if (!err) { |
1246 | irq_flags = 0; | 1254 | adapter->flags |= FLAG_MSI_ENABLED; |
1255 | irq_flags = 0; | ||
1256 | } | ||
1247 | } | 1257 | } |
1248 | 1258 | ||
1249 | err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, | 1259 | err = request_irq(adapter->pdev->irq, |
1250 | netdev); | 1260 | ((adapter->flags & FLAG_MSI_ENABLED) ? |
1261 | &e1000_intr_msi : &e1000_intr), | ||
1262 | irq_flags, netdev->name, netdev); | ||
1251 | if (err) { | 1263 | if (err) { |
1252 | e_err("Unable to allocate %s interrupt (return: %d)\n", | 1264 | if (adapter->flags & FLAG_MSI_ENABLED) { |
1253 | adapter->flags & FLAG_MSI_ENABLED ? "MSI":"INTx", err); | ||
1254 | if (adapter->flags & FLAG_MSI_ENABLED) | ||
1255 | pci_disable_msi(adapter->pdev); | 1265 | pci_disable_msi(adapter->pdev); |
1266 | adapter->flags &= ~FLAG_MSI_ENABLED; | ||
1267 | } | ||
1268 | e_err("Unable to allocate interrupt, Error: %d\n", err); | ||
1256 | } | 1269 | } |
1257 | 1270 | ||
1258 | return err; | 1271 | return err; |
@@ -2592,6 +2605,135 @@ err: | |||
2592 | } | 2605 | } |
2593 | 2606 | ||
2594 | /** | 2607 | /** |
2608 | * e1000_intr_msi_test - Interrupt Handler | ||
2609 | * @irq: interrupt number | ||
2610 | * @data: pointer to a network interface device structure | ||
2611 | **/ | ||
2612 | static irqreturn_t e1000_intr_msi_test(int irq, void *data) | ||
2613 | { | ||
2614 | struct net_device *netdev = data; | ||
2615 | struct e1000_adapter *adapter = netdev_priv(netdev); | ||
2616 | struct e1000_hw *hw = &adapter->hw; | ||
2617 | u32 icr = er32(ICR); | ||
2618 | |||
2619 | e_dbg("%s: icr is %08X\n", netdev->name, icr); | ||
2620 | if (icr & E1000_ICR_RXSEQ) { | ||
2621 | adapter->flags &= ~FLAG_MSI_TEST_FAILED; | ||
2622 | wmb(); | ||
2623 | } | ||
2624 | |||
2625 | return IRQ_HANDLED; | ||
2626 | } | ||
2627 | |||
2628 | /** | ||
2629 | * e1000_test_msi_interrupt - Returns 0 for successful test | ||
2630 | * @adapter: board private struct | ||
2631 | * | ||
2632 | * code flow taken from tg3.c | ||
2633 | **/ | ||
2634 | static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) | ||
2635 | { | ||
2636 | struct net_device *netdev = adapter->netdev; | ||
2637 | struct e1000_hw *hw = &adapter->hw; | ||
2638 | int err; | ||
2639 | |||
2640 | /* poll_enable hasn't been called yet, so don't need disable */ | ||
2641 | /* clear any pending events */ | ||
2642 | er32(ICR); | ||
2643 | |||
2644 | /* free the real vector and request a test handler */ | ||
2645 | e1000_free_irq(adapter); | ||
2646 | |||
2647 | /* Assume that the test fails, if it succeeds then the test | ||
2648 | * MSI irq handler will unset this flag */ | ||
2649 | adapter->flags |= FLAG_MSI_TEST_FAILED; | ||
2650 | |||
2651 | err = pci_enable_msi(adapter->pdev); | ||
2652 | if (err) | ||
2653 | goto msi_test_failed; | ||
2654 | |||
2655 | err = request_irq(adapter->pdev->irq, &e1000_intr_msi_test, 0, | ||
2656 | netdev->name, netdev); | ||
2657 | if (err) { | ||
2658 | pci_disable_msi(adapter->pdev); | ||
2659 | goto msi_test_failed; | ||
2660 | } | ||
2661 | |||
2662 | wmb(); | ||
2663 | |||
2664 | e1000_irq_enable(adapter); | ||
2665 | |||
2666 | /* fire an unusual interrupt on the test handler */ | ||
2667 | ew32(ICS, E1000_ICS_RXSEQ); | ||
2668 | e1e_flush(); | ||
2669 | msleep(50); | ||
2670 | |||
2671 | e1000_irq_disable(adapter); | ||
2672 | |||
2673 | rmb(); | ||
2674 | |||
2675 | if (adapter->flags & FLAG_MSI_TEST_FAILED) { | ||
2676 | err = -EIO; | ||
2677 | e_info("MSI interrupt test failed!\n"); | ||
2678 | } | ||
2679 | |||
2680 | free_irq(adapter->pdev->irq, netdev); | ||
2681 | pci_disable_msi(adapter->pdev); | ||
2682 | |||
2683 | if (err == -EIO) | ||
2684 | goto msi_test_failed; | ||
2685 | |||
2686 | /* okay so the test worked, restore settings */ | ||
2687 | e_dbg("%s: MSI interrupt test succeeded!\n", netdev->name); | ||
2688 | msi_test_failed: | ||
2689 | /* restore the original vector, even if it failed */ | ||
2690 | e1000_request_irq(adapter); | ||
2691 | return err; | ||
2692 | } | ||
2693 | |||
2694 | /** | ||
2695 | * e1000_test_msi - Returns 0 if MSI test succeeds or INTx mode is restored | ||
2696 | * @adapter: board private struct | ||
2697 | * | ||
2698 | * code flow taken from tg3.c, called with e1000 interrupts disabled. | ||
2699 | **/ | ||
2700 | static int e1000_test_msi(struct e1000_adapter *adapter) | ||
2701 | { | ||
2702 | int err; | ||
2703 | u16 pci_cmd; | ||
2704 | |||
2705 | if (!(adapter->flags & FLAG_MSI_ENABLED)) | ||
2706 | return 0; | ||
2707 | |||
2708 | /* disable SERR in case the MSI write causes a master abort */ | ||
2709 | pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); | ||
2710 | pci_write_config_word(adapter->pdev, PCI_COMMAND, | ||
2711 | pci_cmd & ~PCI_COMMAND_SERR); | ||
2712 | |||
2713 | err = e1000_test_msi_interrupt(adapter); | ||
2714 | |||
2715 | /* restore previous setting of command word */ | ||
2716 | pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd); | ||
2717 | |||
2718 | /* success ! */ | ||
2719 | if (!err) | ||
2720 | return 0; | ||
2721 | |||
2722 | /* EIO means MSI test failed */ | ||
2723 | if (err != -EIO) | ||
2724 | return err; | ||
2725 | |||
2726 | /* back to INTx mode */ | ||
2727 | e_warn("MSI interrupt test failed, using legacy interrupt.\n"); | ||
2728 | |||
2729 | e1000_free_irq(adapter); | ||
2730 | |||
2731 | err = e1000_request_irq(adapter); | ||
2732 | |||
2733 | return err; | ||
2734 | } | ||
2735 | |||
2736 | /** | ||
2595 | * e1000_open - Called when a network interface is made active | 2737 | * e1000_open - Called when a network interface is made active |
2596 | * @netdev: network interface device structure | 2738 | * @netdev: network interface device structure |
2597 | * | 2739 | * |
@@ -2649,6 +2791,19 @@ static int e1000_open(struct net_device *netdev) | |||
2649 | if (err) | 2791 | if (err) |
2650 | goto err_req_irq; | 2792 | goto err_req_irq; |
2651 | 2793 | ||
2794 | /* | ||
2795 | * Work around PCIe errata with MSI interrupts causing some chipsets to | ||
2796 | * ignore e1000e MSI messages, which means we need to test our MSI | ||
2797 | * interrupt now | ||
2798 | */ | ||
2799 | { | ||
2800 | err = e1000_test_msi(adapter); | ||
2801 | if (err) { | ||
2802 | e_err("Interrupt allocation failed\n"); | ||
2803 | goto err_req_irq; | ||
2804 | } | ||
2805 | } | ||
2806 | |||
2652 | /* From here on the code is the same as e1000e_up() */ | 2807 | /* From here on the code is the same as e1000e_up() */ |
2653 | clear_bit(__E1000_DOWN, &adapter->state); | 2808 | clear_bit(__E1000_DOWN, &adapter->state); |
2654 | 2809 | ||
@@ -3055,7 +3210,7 @@ static void e1000_watchdog_task(struct work_struct *work) | |||
3055 | case SPEED_10: | 3210 | case SPEED_10: |
3056 | txb2b = 0; | 3211 | txb2b = 0; |
3057 | netdev->tx_queue_len = 10; | 3212 | netdev->tx_queue_len = 10; |
3058 | adapter->tx_timeout_factor = 14; | 3213 | adapter->tx_timeout_factor = 16; |
3059 | break; | 3214 | break; |
3060 | case SPEED_100: | 3215 | case SPEED_100: |
3061 | txb2b = 0; | 3216 | txb2b = 0; |
@@ -3721,7 +3876,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) | |||
3721 | struct e1000_adapter *adapter = netdev_priv(netdev); | 3876 | struct e1000_adapter *adapter = netdev_priv(netdev); |
3722 | int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; | 3877 | int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; |
3723 | 3878 | ||
3724 | if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || | 3879 | if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) || |
3725 | (max_frame > MAX_JUMBO_FRAME_SIZE)) { | 3880 | (max_frame > MAX_JUMBO_FRAME_SIZE)) { |
3726 | e_err("Invalid MTU setting\n"); | 3881 | e_err("Invalid MTU setting\n"); |
3727 | return -EINVAL; | 3882 | return -EINVAL; |