#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/netdevice.h>
-#include <linux/tcp.h>
#include <linux/ipv6.h>
#include <net/checksum.h>
#include <net/ip6_checksum.h>
adapter->hw.phy.ops.get_phy_info(&adapter->hw);
}
+/**
+ * igb_is_need_ioport - determine if an adapter needs ioport resources or not
+ * @pdev: PCI device information struct
+ *
+ * Returns true if an adapter needs ioport resources
+ **/
+static int igb_is_need_ioport(struct pci_dev *pdev)
+{
+ switch (pdev->device) {
+ /* Currently there are no adapters that need ioport resources */
+ default:
+ return false;
+ }
+}
+
/**
* igb_probe - Device Initialization Routine
* @pdev: PCI device information struct
u16 eeprom_data = 0;
u16 eeprom_apme_mask = IGB_EEPROM_APME;
u32 part_num;
+ int bars, need_ioport;
- err = pci_enable_device(pdev);
+ /* do not allocate ioport bars when not needed */
+ need_ioport = igb_is_need_ioport(pdev);
+ if (need_ioport) {
+ bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
+ err = pci_enable_device(pdev);
+ } else {
+ bars = pci_select_bars(pdev, IORESOURCE_MEM);
+ err = pci_enable_device_mem(pdev);
+ }
if (err)
return err;
}
}
- err = pci_request_regions(pdev, igb_driver_name);
+ err = pci_request_selected_regions(pdev, bars, igb_driver_name);
if (err)
goto err_pci_reg;
pci_set_master(pdev);
+ pci_save_state(pdev);
err = -ENOMEM;
netdev = alloc_etherdev(sizeof(struct igb_adapter));
hw = &adapter->hw;
hw->back = adapter;
adapter->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE;
+ adapter->bars = bars;
+ adapter->need_ioport = need_ioport;
mmio_start = pci_resource_start(pdev, 0);
mmio_len = pci_resource_len(pdev, 0);
NETIF_F_HW_VLAN_FILTER;
netdev->features |= NETIF_F_TSO;
-
netdev->features |= NETIF_F_TSO6;
+
+ netdev->vlan_features |= NETIF_F_TSO;
+ netdev->vlan_features |= NETIF_F_TSO6;
+ netdev->vlan_features |= NETIF_F_HW_CSUM;
+ netdev->vlan_features |= NETIF_F_SG;
+
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
err_ioremap:
free_netdev(netdev);
err_alloc_etherdev:
- pci_release_regions(pdev);
+ pci_release_selected_regions(pdev, bars);
err_pci_reg:
err_dma:
pci_disable_device(pdev);
iounmap(adapter->hw.hw_addr);
if (adapter->hw.flash_address)
iounmap(adapter->hw.flash_address);
- pci_release_regions(pdev);
+ pci_release_selected_regions(pdev, adapter->bars);
free_netdev(netdev);
tu_cmd |= (E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- if (skb->protocol == htons(ETH_P_IP))
+ switch (skb->protocol) {
+ case __constant_htons(ETH_P_IP):
tu_cmd |= E1000_ADVTXD_TUCMD_IPV4;
- if (skb->sk && (skb->sk->sk_protocol == IPPROTO_TCP))
- tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
+ break;
+ case __constant_htons(ETH_P_IPV6):
+ /* XXX what about other V6 headers?? */
+ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
+ tu_cmd |= E1000_ADVTXD_TUCMD_L4T_TCP;
+ break;
+ default:
+ if (unlikely(net_ratelimit()))
+ dev_warn(&adapter->pdev->dev,
+ "partial checksum but proto=%x!\n",
+ skb->protocol);
+ break;
+ }
}
context_desc->type_tucmd_mlhl = cpu_to_le32(tu_cmd);
return 1;
}
+
+static inline u32 get_head(struct igb_ring *tx_ring)
+{
+ void *end = (struct e1000_tx_desc *)tx_ring->desc + tx_ring->count;
+ return le32_to_cpu(*(volatile __le32 *)end);
+}
+
/**
* igb_clean_tx_irq - Reclaim resources after transmit completes
* @adapter: board private structure
unsigned int total_bytes = 0, total_packets = 0;
rmb();
- head = *(volatile u32 *)((struct e1000_tx_desc *)tx_ring->desc
- + tx_ring->count);
- head = le32_to_cpu(head);
+ head = get_head(tx_ring);
i = tx_ring->next_to_clean;
while (1) {
while (i != head) {
}
oldhead = head;
rmb();
- head = *(volatile u32 *)((struct e1000_tx_desc *)tx_ring->desc
- + tx_ring->count);
- head = le32_to_cpu(head);
+ head = get_head(tx_ring);
if (head == oldhead)
goto done_cleaning;
} /* while (1) */
* @vlan: descriptor vlan field as written by hardware (no le/be conversion)
* @skb: pointer to sk_buff to be indicated to stack
**/
-static void igb_receive_skb(struct igb_adapter *adapter, u8 status, u16 vlan,
+static void igb_receive_skb(struct igb_adapter *adapter, u8 status, __le16 vlan,
struct sk_buff *skb)
{
if (adapter->vlgrp && (status & E1000_RXD_STAT_VP))
* that case, it fills the header buffer and spills the rest
* into the page.
*/
- hlen = le16_to_cpu((rx_desc->wb.lower.lo_dword.hdr_info &
- E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT);
+ hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
+ E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
if (hlen > adapter->rx_ps_hdr_size)
hlen = adapter->rx_ps_hdr_size;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- err = pci_enable_device(pdev);
+
+ if (adapter->need_ioport)
+ err = pci_enable_device(pdev);
+ else
+ err = pci_enable_device_mem(pdev);
if (err) {
dev_err(&pdev->dev,
"igb: Cannot enable PCI device from suspend\n");
struct net_device *netdev = pci_get_drvdata(pdev);
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
+ int err;
- if (pci_enable_device(pdev)) {
+ if (adapter->need_ioport)
+ err = pci_enable_device(pdev);
+ else
+ err = pci_enable_device_mem(pdev);
+ if (err) {
dev_err(&pdev->dev,
"Cannot re-enable PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
}
pci_set_master(pdev);
+ pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);