*/
char e1000_driver_name[] = "e1000";
-char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
+static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#ifndef CONFIG_E1000_NAPI
#define DRIVERNAPI
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
+#define DRV_VERSION "6.3.9-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
-char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table
*
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-int e1000_setup_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *txdr);
-int e1000_setup_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rxdr);
-void e1000_free_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring);
-void e1000_free_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *txdr);
+static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rxdr);
+static void e1000_free_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring);
+static void e1000_free_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring);
void e1000_update_stats(struct e1000_adapter *adapter);
/* Local Function Prototypes */
E1000_WRITE_FLUSH(&adapter->hw);
}
}
-void
+
+static void
e1000_update_mng_vlan(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
}
if((adapter->hw.mac_type != e1000_82573) &&
- (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) {
+ (adapter->netdev->mtu > E1000_RXBUFFER_8192)) {
pba -= 8; /* allocate more FIFO for Tx */
/* send an XOFF when there is enough space in the
* Rx FIFO to hold one extra full size Rx packet
break;
case e1000_82546:
case e1000_82546_rev_3:
+ case e1000_82571:
if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
&& (adapter->hw.media_type == e1000_media_type_copper)) {
e1000_read_eeprom(&adapter->hw,
* Return 0 on success, negative on failure
**/
-int
+static int
e1000_setup_tx_resources(struct e1000_adapter *adapter,
struct e1000_tx_ring *txdr)
{
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
- memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
/* round up to nearest 4K */
* Returns 0 on success, negative on failure
**/
-int
+static int
e1000_setup_rx_resources(struct e1000_adapter *adapter,
struct e1000_rx_ring *rxdr)
{
* Free all transmit software resources
**/
-void
+static void
e1000_free_tx_resources(struct e1000_adapter *adapter,
struct e1000_tx_ring *tx_ring)
{
/* Free all the Tx ring sk_buffs */
- if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
- e1000_unmap_and_free_tx_resource(adapter,
- &tx_ring->previous_buffer_info);
- }
-
for(i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
+ tx_ring->last_tx_tso = 0;
writel(0, adapter->hw.hw_addr + tx_ring->tdh);
writel(0, adapter->hw.hw_addr + tx_ring->tdt);
* Free all receive software resources
**/
-void
+static void
e1000_free_rx_resources(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring)
{
e1000_watchdog_task(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
+ struct e1000_tx_ring *txdr = adapter->tx_ring;
uint32_t link;
e1000_check_for_link(&adapter->hw);
{
#ifdef NETIF_F_TSO
struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
unsigned int i;
uint32_t cmd_length = 0;
uint16_t ipcse = 0, tucse, mss;
i = tx_ring->next_to_use;
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+ buffer_info = &tx_ring->buffer_info[i];
context_desc->lower_setup.ip_fields.ipcss = ipcss;
context_desc->lower_setup.ip_fields.ipcso = ipcso;
context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
context_desc->cmd_and_length = cpu_to_le32(cmd_length);
+ buffer_info->time_stamp = jiffies;
+
if (++i == tx_ring->count) i = 0;
tx_ring->next_to_use = i;
struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
unsigned int i;
uint8_t css;
css = skb->h.raw - skb->data;
i = tx_ring->next_to_use;
+ buffer_info = &tx_ring->buffer_info[i];
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
context_desc->upper_setup.tcp_fields.tucss = css;
context_desc->tcp_seg_setup.data = 0;
context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
+ buffer_info->time_stamp = jiffies;
+
if (unlikely(++i == tx_ring->count)) i = 0;
tx_ring->next_to_use = i;
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
#ifdef NETIF_F_TSO
+ /* Workaround for Controller erratum --
+ * descriptor for non-tso packet in a linear SKB that follows a
+ * tso gets written back prematurely before the data is fully
+ * DMAd to the controller */
+ if (!skb->data_len && tx_ring->last_tx_tso &&
+ !skb_shinfo(skb)->tso_size) {
+ tx_ring->last_tx_tso = 0;
+ size -= 4;
+ }
+
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
if(unlikely(mss && !nr_frags && size == len && size > 8))
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
return 0;
}
- if(htons(ETH_P_IP) == skb->protocol) {
- const struct iphdr *ip = skb->nh.iph;
- if(IPPROTO_UDP == ip->protocol) {
- struct udphdr *udp = (struct udphdr *)(skb->h.uh);
- if(ntohs(udp->dest) == 67) {
- offset = (uint8_t *)udp + 8 - skb->data;
- length = skb->len - offset;
-
- return e1000_mng_write_dhcp_info(hw,
- (uint8_t *)udp + 8, length);
- }
- }
- } else if((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
+ if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
struct ethhdr *eth = (struct ethhdr *) skb->data;
if((htons(ETH_P_IP) == eth->h_proto)) {
const struct iphdr *ip =
* overrun the FIFO, adjust the max buffer len if mss
* drops. */
if(mss) {
+ uint8_t hdr_len;
max_per_txd = min(mss << 2, max_per_txd);
max_txd_pwr = fls(max_per_txd) - 1;
+
+ /* TSO Workaround for 82571/2 Controllers -- if skb->data
+ * points to just header, pull a few bytes of payload from
+ * frags into skb->data */
+ hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+ if (skb->data_len && (hdr_len == (skb->len - skb->data_len)) &&
+ (adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572)) {
+ len = skb->len - skb->data_len;
+ }
}
if((mss) || (skb->ip_summed == CHECKSUM_HW))
+ /* reserve a descriptor for the offload context */
count++;
count++;
#else
if(skb->ip_summed == CHECKSUM_HW)
count++;
#endif
+
+#ifdef NETIF_F_TSO
+ /* Controller Erratum workaround */
+ if (!skb->data_len && tx_ring->last_tx_tso &&
+ !skb_shinfo(skb)->tso_size)
+ count++;
+#endif
+
count += TXD_USE_COUNT(len, max_txd_pwr);
if(adapter->pcix_82544)
if(adapter->pcix_82544)
count += nr_frags;
-#ifdef NETIF_F_TSO
- /* TSO Workaround for 82571/2 Controllers -- if skb->data
- * points to just header, pull a few bytes of payload from
- * frags into skb->data */
- if (skb_shinfo(skb)->tso_size) {
- uint8_t hdr_len;
- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
- if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) &&
- (adapter->hw.mac_type == e1000_82571 ||
- adapter->hw.mac_type == e1000_82572)) {
- unsigned int pull_size;
- pull_size = min((unsigned int)4, skb->data_len);
- if (!__pskb_pull_tail(skb, pull_size)) {
- printk(KERN_ERR "__pskb_pull_tail failed.\n");
- dev_kfree_skb_any(skb);
- return -EFAULT;
- }
+ unsigned int pull_size;
+ pull_size = min((unsigned int)4, skb->data_len);
+ if (!__pskb_pull_tail(skb, pull_size)) {
+ printk(KERN_ERR "__pskb_pull_tail failed.\n");
+ dev_kfree_skb_any(skb);
+ return -EFAULT;
}
- }
-#endif
if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
e1000_transfer_dhcp_info(adapter, skb);
return NETDEV_TX_OK;
}
- if (likely(tso))
+ if (likely(tso)) {
+ tx_ring->last_tx_tso = 1;
tx_flags |= E1000_TX_FLAGS_TSO;
- else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
+ } else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
tx_flags |= E1000_TX_FLAGS_CSUM;
/* Old method was to assume IPv4 packet by default if TSO was enabled.
eop_desc = E1000_TX_DESC(*tx_ring, eop);
while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
- /* Premature writeback of Tx descriptors clear (free buffers
- * and unmap pci_mapping) previous_buffer_info */
- if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
- e1000_unmap_and_free_tx_resource(adapter,
- &tx_ring->previous_buffer_info);
- }
-
for(cleaned = FALSE; !cleaned; ) {
tx_desc = E1000_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
cleaned = (i == eop);
-#ifdef NETIF_F_TSO
- if (!(netdev->features & NETIF_F_TSO)) {
-#endif
- e1000_unmap_and_free_tx_resource(adapter,
- buffer_info);
-#ifdef NETIF_F_TSO
- } else {
- if (cleaned) {
- memcpy(&tx_ring->previous_buffer_info,
- buffer_info,
- sizeof(struct e1000_buffer));
- memset(buffer_info, 0,
- sizeof(struct e1000_buffer));
- } else {
- e1000_unmap_and_free_tx_resource(
- adapter, buffer_info);
- }
- }
-#endif
+ e1000_unmap_and_free_tx_resource(adapter, buffer_info);
tx_desc->buffer_addr = 0;
tx_desc->lower.data = 0;
if(unlikely(++i == tx_ring->count)) i = 0;
}
- tx_ring->pkt++;
-
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
}
netif_stop_queue(netdev);
}
}
-#ifdef NETIF_F_TSO
- if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
- time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
- e1000_unmap_and_free_tx_resource(
- adapter, &tx_ring->previous_buffer_info);
-#endif
return cleaned;
}
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
next_desc:
rx_desc->status = 0;
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
next_desc:
rx_desc->wb.middle.status_error &= ~0xFF;