From: Stefan Assmann <sassmann@redhat.com> Date: Fri, 27 Aug 2010 10:47:28 -0400 Subject: [net] igbvf: update to latest upstream for RHEL5.6 Message-id: <4C7797C0.2090008@redhat.com> Patchwork-id: 27839 O-Subject: [RHEL 5.6 PATCH v2] igbvf: update igbvf driver to latest upstream Bugzilla: 566028 RH-Acked-by: Andy Gospodarek <gospo@redhat.com> RH-Acked-by: David S. Miller <davem@redhat.com> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=566028 Description: Driver update for igbvf to latest upstream. The following commits or parts of them have been backported for RHEL5.6. v2: - A bit closer to the upstream code. Upstream Status: from net-next-2.6 042a53a9e437feaf2230dd2cadcecfae9c7bfe05 net: skb_shared_info optimization 98a1708de1bfa5fe1c490febba850d6043d3c7fa trivial: fix typos s/paramter/parameter/ and s/excute/execute/ in documentation and source comments. 8e20ce94ce378334dea83a83ab26253b851100a2 convert some DMA_nnBIT_MASK() callers 92d947b77436437f4fe6f9b7b7cd35f1a294fa9d igbvf: resolve "frees DMA memory with different size" warnings c06c430dedf71a0e9180d673191b9c9368aeaa65 igbvf: return PCI_ERS_RESULT_DISCONNECT on permanent failure 3b29a56d31d585d39bf9ffe9ef1f10bd637ee0f1 intel: convert drivers to netdev_tx_t 451f14439847db302e5104c44458b2dbb4b1829d drivers: Kill now superfluous ->last_rx stores 39305965f31e080d6ed96e0ff51ed11e7639d52e igbvf: fix memory leak when ring size changed while interface down a0607fd3a25ba1848a63a0d925e36d914735ab47 drivers/net: request_irq - Remove unnecessary leading & from second arg a7d5ca40ff56e2cd4e30bbe91f2d0deab6bfc006 igbvf: remove skb_dma_map/unmap call from drivers 8e95a2026f3b43f7c3d676adaccd2de9532e8dcc drivers/net: Move && and || to end of previous line 7227909340477c1e5225bb2df76cdcc95b5e1da1 igbvf: avoid reset storms due to mailbox issues 1242b6f31e1d0688f1eb1dc78036dbd975bd6140 igbvf: Make igbvf error message more informative c1fa347f20f17f14a4a1575727fa24340e8a9117 e1000/e1000e/igb/igbvf/ixgb/ixgbe: Fix tests of unsigned in *_tx_map() 8581145f39c39b00cd1b6a2dcb4ce5bf7d8d6070 igb/igbvf: cleanup exception handling in tx_map_adv 8e1e8a4779cb23c1d9f51e9223795e07ec54d77a net: Fix IPv6 GSO type checks in Intel ethernet drivers ac26d7d6aca9621f75f6954c159d2727c9c9cbd0 igbvf: fix issue w/ mapped_as_page being left set after unmap Brew Build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=2714505 Test Status: Changes to igbvf have been tested by myself in the host and with XEN. Stefan diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c index 5b77380..47e8480 100644 --- a/drivers/net/igbvf/ethtool.c +++ b/drivers/net/igbvf/ethtool.c @@ -279,7 +279,7 @@ static int igbvf_set_ringparam(struct net_device *netdev, { struct igbvf_adapter *adapter = netdev_priv(netdev); struct igbvf_ring *temp_ring; - int err; + int err = 0; u32 new_rx_count, new_tx_count; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) @@ -299,15 +299,22 @@ static int igbvf_set_ringparam(struct net_device *netdev, return 0; } - temp_ring = vmalloc(sizeof(struct igbvf_ring)); - if (!temp_ring) - return -ENOMEM; - while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state)) msleep(1); - if (netif_running(adapter->netdev)) - igbvf_down(adapter); + if (!netif_running(adapter->netdev)) { + adapter->tx_ring->count = new_tx_count; + adapter->rx_ring->count = new_rx_count; + goto clear_reset; + } + + temp_ring = vmalloc(sizeof(struct igbvf_ring)); + if (!temp_ring) { + err = -ENOMEM; + goto clear_reset; + } + + igbvf_down(adapter); /* * We can't just free everything and then setup again, @@ -339,14 +346,11 @@ static int igbvf_set_ringparam(struct net_device *netdev, memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring)); } - - err = 0; err_setup: - if (netif_running(adapter->netdev)) - igbvf_up(adapter); - - clear_bit(__IGBVF_RESETTING, &adapter->state); + igbvf_up(adapter); vfree(temp_ring); +clear_reset: + clear_bit(__IGBVF_RESETTING, &adapter->state); return err; } diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h index cf30f3e..6ab7980 100644 --- a/drivers/net/igbvf/igbvf.h +++ b/drivers/net/igbvf/igbvf.h @@ -45,7 +45,7 @@ struct igbvf_adapter; /* Interrupt defines */ #define IGBVF_START_ITR 648 /* ~6000 ints/sec */ -/* Interrupt modes, as used by the IntMode paramter */ +/* Interrupt modes, as used by the IntMode parameter */ #define IGBVF_INT_MODE_LEGACY 0 #define IGBVF_INT_MODE_MSI 1 #define IGBVF_INT_MODE_MSIX 2 @@ -117,6 +117,7 @@ struct igbvf_buffer { unsigned long time_stamp; u16 length; u16 next_to_watch; + u16 mapped_as_page; }; /* Rx */ struct { @@ -274,6 +275,7 @@ struct igbvf_adapter { unsigned long led_status; unsigned int flags; + unsigned long last_reset; }; struct igbvf_info { diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 669d49f..6571fb8 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -95,8 +95,6 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter, E1000_RXD_SPC_VLAN_MASK); else netif_receive_skb(skb); - - netdev->last_rx = jiffies; } static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter, @@ -148,7 +146,6 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring, bufsz = adapter->rx_ps_hdr_size; else bufsz = adapter->rx_buffer_len; - bufsz += NET_IP_ALIGN; while (cleaned_count--) { rx_desc = IGBVF_RX_DESC_ADV(*rx_ring, i); @@ -172,7 +169,7 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring, } if (!buffer_info->skb) { - skb = netdev_alloc_skb(netdev, bufsz); + skb = netdev_alloc_skb(netdev, bufsz + NET_IP_ALIGN); if (!skb) { adapter->alloc_rx_buff_failed++; goto no_buffers; @@ -285,7 +282,7 @@ static bool igbvf_clean_rx_irq(struct igbvf_adapter *adapter, if (!skb_shinfo(skb)->nr_frags) { pci_unmap_single(pdev, buffer_info->dma, - adapter->rx_ps_hdr_size + NET_IP_ALIGN, + adapter->rx_ps_hdr_size, PCI_DMA_FROMDEVICE); skb_put(skb, hlen); } @@ -342,8 +339,6 @@ send_up: igbvf_receive_skb(adapter, netdev, skb, staterr, rx_desc->wb.upper.vlan); - netdev->last_rx = jiffies; - next_desc: rx_desc->wb.upper.status_error = 0; @@ -376,11 +371,17 @@ next_desc: static void igbvf_put_txbuf(struct igbvf_adapter *adapter, struct igbvf_buffer *buffer_info) { - if (buffer_info->skb) { - pci_unmap_page(adapter->pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_TODEVICE); + if (buffer_info->dma) { + if (buffer_info->mapped_as_page) + pci_unmap_page(adapter->pdev, + buffer_info->dma, + buffer_info->length, + PCI_DMA_TODEVICE); + else + pci_unmap_single(adapter->pdev, + buffer_info->dma, + buffer_info->length, + PCI_DMA_TODEVICE); buffer_info->dma = 0; } if (buffer_info->skb) { @@ -832,8 +833,8 @@ static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring) adapter->detect_tx_hung = false; if (tx_ring->buffer_info[i].time_stamp && time_after(jiffies, tx_ring->buffer_info[i].time_stamp + - (adapter->tx_timeout_factor * HZ)) - && !(er32(STATUS) & E1000_STATUS_TXOFF)) { + (adapter->tx_timeout_factor * HZ)) && + !(er32(STATUS) & E1000_STATUS_TXOFF)) { tx_desc = IGBVF_TX_DESC_ADV(*tx_ring, i); /* detected Tx unit hang */ @@ -1058,7 +1059,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter) } err = request_irq(adapter->msix_entries[vector].vector, - &igbvf_intr_msix_tx, 0, adapter->tx_ring->name, + igbvf_intr_msix_tx, 0, adapter->tx_ring->name, netdev); if (err) goto out; @@ -1068,7 +1069,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter) vector++; err = request_irq(adapter->msix_entries[vector].vector, - &igbvf_intr_msix_rx, 0, adapter->rx_ring->name, + igbvf_intr_msix_rx, 0, adapter->rx_ring->name, netdev); if (err) goto out; @@ -1078,7 +1079,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter) vector++; err = request_irq(adapter->msix_entries[vector].vector, - &igbvf_msix_other, 0, netdev->name, netdev); + igbvf_msix_other, 0, netdev->name, netdev); if (err) goto out; @@ -1290,7 +1291,7 @@ static void igbvf_configure_tx(struct igbvf_adapter *adapter) /* Setup the HW Tx Head and Tail descriptor pointers */ ew32(TDLEN(0), tx_ring->count * sizeof(union e1000_adv_tx_desc)); tdba = tx_ring->dma; - ew32(TDBAL(0), (tdba & DMA_32BIT_MASK)); + ew32(TDBAL(0), (tdba & DMA_BIT_MASK(32))); ew32(TDBAH(0), (tdba >> 32)); ew32(TDH(0), 0); ew32(TDT(0), 0); @@ -1376,7 +1377,7 @@ static void igbvf_configure_rx(struct igbvf_adapter *adapter) * the Base and Length of the Rx Descriptor Ring */ rdba = rx_ring->dma; - ew32(RDBAL(0), (rdba & DMA_32BIT_MASK)); + ew32(RDBAL(0), (rdba & DMA_BIT_MASK(32))); ew32(RDBAH(0), (rdba >> 32)); ew32(RDLEN(0), rx_ring->count * sizeof(union e1000_adv_rx_desc)); rx_ring->head = E1000_RDH(0); @@ -1479,6 +1480,8 @@ static void igbvf_reset(struct igbvf_adapter *adapter) memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len); } + + adapter->last_reset = jiffies; } int igbvf_up(struct igbvf_adapter *adapter) @@ -1822,11 +1825,15 @@ static bool igbvf_has_link(struct igbvf_adapter *adapter) s32 ret_val = E1000_SUCCESS; bool link_active; + /* If interface is down, stay link down */ + if (test_bit(__IGBVF_DOWN, &adapter->state)) + return false; + ret_val = hw->mac.ops.check_for_link(hw); link_active = !hw->mac.get_link_status; /* if check for link returns error we will need to reset */ - if (ret_val) + if (ret_val && time_after(jiffies, adapter->last_reset + (10 * HZ))) schedule_work(&adapter->reset_task); return link_active; @@ -1964,7 +1971,7 @@ static int igbvf_tso(struct igbvf_adapter *adapter, iph->daddr, 0, IPPROTO_TCP, 0); - } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + } else if (skb_is_gso_v6(skb)) { ipv6_hdr(skb)->payload_len = 0; tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, @@ -2105,6 +2112,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, unsigned int first) { struct igbvf_buffer *buffer_info; + struct pci_dev *pdev = adapter->pdev; unsigned int len = skb_headlen(skb); unsigned int count = 0, i; unsigned int f; @@ -2117,13 +2125,17 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, /* set time_stamp *before* dma to help avoid a possible race */ buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; - buffer_info->dma = pci_map_single(adapter->pdev, skb->data, len, + buffer_info->mapped_as_page = false; + buffer_info->dma = pci_map_single(pdev, skb->data, len, PCI_DMA_TODEVICE); - count++; + if (pci_dma_mapping_error(buffer_info->dma)) + goto dma_error; + for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { struct skb_frag_struct *frag; + count++; i++; if (i == tx_ring->count) i = 0; @@ -2136,19 +2148,43 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, buffer_info->length = len; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; - buffer_info->dma = pci_map_page(adapter->pdev, + buffer_info->mapped_as_page = true; + buffer_info->dma = pci_map_page(pdev, frag->page, frag->page_offset, len, PCI_DMA_TODEVICE); - - count++; + if (pci_dma_mapping_error(buffer_info->dma)) + goto dma_error; } tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; - return count; + return ++count; + +dma_error: + dev_err(&pdev->dev, "TX DMA map failed\n"); + + /* clear timestamp and dma mappings for failed buffer_info mapping */ + buffer_info->dma = 0; + buffer_info->time_stamp = 0; + buffer_info->length = 0; + buffer_info->next_to_watch = 0; + buffer_info->mapped_as_page = false; + if (count) + count--; + + /* clear timestamp and dma mappings for remaining portion of packet */ + while (count--) { + if (i==0) + i += tx_ring->count; + i--; + buffer_info = &tx_ring->buffer_info[i]; + igbvf_put_txbuf(adapter, buffer_info); + } + + return 0; } static inline void igbvf_tx_queue_adv(struct igbvf_adapter *adapter, @@ -2211,8 +2247,8 @@ static inline void igbvf_tx_queue_adv(struct igbvf_adapter *adapter, } static int igbvf_xmit_frame_ring_adv(struct sk_buff *skb, - struct net_device *netdev, - struct igbvf_ring *tx_ring) + struct net_device *netdev, + struct igbvf_ring *tx_ring) { struct igbvf_adapter *adapter = netdev_priv(netdev); unsigned int first, tx_flags = 0; @@ -2286,11 +2322,11 @@ static int igbvf_xmit_frame_ring_adv(struct sk_buff *skb, return NETDEV_TX_OK; } -static int igbvf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +static int igbvf_xmit_frame(struct sk_buff *skb, + struct net_device *netdev) { struct igbvf_adapter *adapter = netdev_priv(netdev); struct igbvf_ring *tx_ring; - int retval; if (test_bit(__IGBVF_DOWN, &adapter->state)) { dev_kfree_skb_any(skb); @@ -2299,9 +2335,7 @@ static int igbvf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) tx_ring = &adapter->tx_ring[0]; - retval = igbvf_xmit_frame_ring_adv(skb, netdev, tx_ring); - - return retval; + return igbvf_xmit_frame_ring_adv(skb, netdev, tx_ring); } /** @@ -2515,6 +2549,9 @@ static pci_ers_result_t igbvf_io_error_detected(struct pci_dev *pdev, netif_device_detach(netdev); + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + if (netif_running(netdev)) igbvf_down(adapter); pci_disable_device(pdev); @@ -2613,15 +2650,16 @@ static int __devinit igbvf_probe(struct pci_dev *pdev, return err; pci_using_dac = 0; - err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); if (!err) { - err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); if (!err) pci_using_dac = 1; } else { - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, + DMA_BIT_MASK(32)); if (err) { dev_err(&pdev->dev, "No usable DMA " "configuration, aborting\n"); @@ -2721,7 +2759,8 @@ static int __devinit igbvf_probe(struct pci_dev *pdev, err = hw->mac.ops.reset_hw(hw); if (err) { dev_info(&pdev->dev, - "PF still in reset state, assigning new address\n"); + "PF still in reset state, assigning new address." + " Is the PF interface up?\n"); random_ether_addr(hw->mac.addr); } else { err = hw->mac.ops.read_mac_addr(hw);