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; |
