summaryrefslogtreecommitdiffstats
path: root/sys/dev/e1000/if_em.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/e1000/if_em.c')
-rw-r--r--sys/dev/e1000/if_em.c176
1 files changed, 88 insertions, 88 deletions
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index f0cd60f..df54a53 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -93,7 +93,7 @@ int em_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char em_driver_version[] = "6.9.6";
+char em_driver_version[] = "6.9.9";
/*********************************************************************
@@ -278,10 +278,8 @@ static void em_set_multi(struct adapter *);
static void em_print_hw_stats(struct adapter *);
static void em_update_link_status(struct adapter *);
static int em_get_buf(struct adapter *, int);
-
static void em_register_vlan(void *, struct ifnet *, u16);
static void em_unregister_vlan(void *, struct ifnet *, u16);
-
static int em_xmit(struct adapter *, struct mbuf **);
static void em_smartspeed(struct adapter *);
static int em_82547_fifo_workaround(struct adapter *, int);
@@ -322,17 +320,19 @@ static void em_irq_fast(void *);
#else
static int em_irq_fast(void *);
#endif
+
/* MSIX handlers */
static void em_msix_tx(void *);
static void em_msix_rx(void *);
static void em_msix_link(void *);
-static void em_add_rx_process_limit(struct adapter *, const char *,
- const char *, int *, int);
-static void em_handle_rxtx(void *context, int pending);
static void em_handle_rx(void *context, int pending);
static void em_handle_tx(void *context, int pending);
+
+static void em_handle_rxtx(void *context, int pending);
static void em_handle_link(void *context, int pending);
-#endif /* EM_LEGACY_IRQ */
+static void em_add_rx_process_limit(struct adapter *, const char *,
+ const char *, int *, int);
+#endif /* ~EM_LEGACY_IRQ */
#ifdef DEVICE_POLLING
static poll_handler_t em_poll;
@@ -514,8 +514,8 @@ em_attach(device_t dev)
** identified
*/
if ((adapter->hw.mac.type == e1000_ich8lan) ||
- (adapter->hw.mac.type == e1000_ich10lan) ||
- (adapter->hw.mac.type == e1000_ich9lan)) {
+ (adapter->hw.mac.type == e1000_ich9lan) ||
+ (adapter->hw.mac.type == e1000_ich10lan)) {
int rid = EM_BAR_TYPE_FLASH;
adapter->flash = bus_alloc_resource_any(dev,
SYS_RES_MEMORY, &rid, RF_ACTIVE);
@@ -644,6 +644,13 @@ em_attach(device_t dev)
adapter->rx_desc_base =
(struct e1000_rx_desc *)adapter->rxdma.dma_vaddr;
+ /*
+ ** Start from a known state, this is
+ ** important in reading the nvm and
+ ** mac from that.
+ */
+ e1000_reset_hw(&adapter->hw);
+
/* Make sure we have a good EEPROM before we read from it */
if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
/*
@@ -659,13 +666,6 @@ em_attach(device_t dev)
}
}
- /* Initialize the hardware */
- if (em_hardware_init(adapter)) {
- device_printf(dev, "Unable to initialize the hardware\n");
- error = EIO;
- goto err_hw_init;
- }
-
/* Copy the permanent MAC address out of the EEPROM */
if (e1000_read_mac_addr(&adapter->hw) < 0) {
device_printf(dev, "EEPROM read error while reading MAC"
@@ -680,6 +680,13 @@ em_attach(device_t dev)
goto err_hw_init;
}
+ /* Initialize the hardware */
+ if (em_hardware_init(adapter)) {
+ device_printf(dev, "Unable to initialize the hardware\n");
+ error = EIO;
+ goto err_hw_init;
+ }
+
/* Allocate transmit descriptors and buffers */
if (em_allocate_transmit_structures(adapter)) {
device_printf(dev, "Could not setup transmit structures\n");
@@ -1463,8 +1470,6 @@ em_init_locked(struct adapter *adapter)
/* Setup VLAN support, basic and offload if available */
E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
- /* New register interface replaces this but
- waiting on kernel support to be added */
if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) &&
((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)) {
u32 ctrl;
@@ -1473,6 +1478,7 @@ em_init_locked(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
}
+
/* Set hardware offload abilities */
ifp->if_hwassist = 0;
if (adapter->hw.mac.type >= e1000_82543) {
@@ -1622,49 +1628,35 @@ em_intr(void *arg)
return;
EM_CORE_LOCK(adapter);
- for (;;) {
- reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
-
- if (adapter->hw.mac.type >= e1000_82571 &&
- (reg_icr & E1000_ICR_INT_ASSERTED) == 0)
- break;
- else if (reg_icr == 0)
- break;
-
- /*
- * XXX: some laptops trigger several spurious interrupts
- * on em(4) when in the resume cycle. The ICR register
- * reports all-ones value in this case. Processing such
- * interrupts would lead to a freeze. I don't know why.
- */
- if (reg_icr == 0xffffffff)
- break;
+ reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
+ if ((reg_icr == 0xffffffff) || (reg_icr == 0)||
+ (adapter->hw.mac.type >= e1000_82571 &&
+ (reg_icr & E1000_ICR_INT_ASSERTED) == 0))
+ goto out;
- EM_CORE_UNLOCK(adapter);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- em_rxeof(adapter, -1);
- EM_TX_LOCK(adapter);
- em_txeof(adapter);
- EM_TX_UNLOCK(adapter);
- }
- EM_CORE_LOCK(adapter);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ goto out;
- /* Link status change */
- if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
- callout_stop(&adapter->timer);
- adapter->hw.mac.get_link_status = 1;
- em_update_link_status(adapter);
- /* Deal with TX cruft when link lost */
- em_tx_purge(adapter);
- callout_reset(&adapter->timer, hz,
- em_local_timer, adapter);
- }
+ EM_TX_LOCK(adapter);
+ em_txeof(adapter);
+ em_rxeof(adapter, -1);
+ em_txeof(adapter);
+ EM_TX_UNLOCK(adapter);
- if (reg_icr & E1000_ICR_RXO)
- adapter->rx_overruns++;
+ if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ callout_stop(&adapter->timer);
+ adapter->hw.mac.get_link_status = 1;
+ em_update_link_status(adapter);
+ /* Deal with TX cruft when link lost */
+ em_tx_purge(adapter);
+ callout_reset(&adapter->timer, hz,
+ em_local_timer, adapter);
}
- EM_CORE_UNLOCK(adapter);
+ if (reg_icr & E1000_ICR_RXO)
+ adapter->rx_overruns++;
+out:
+ EM_CORE_UNLOCK(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
em_start(ifp);
@@ -1713,33 +1705,6 @@ em_handle_rxtx(void *context, int pending)
em_enable_intr(adapter);
}
-static void
-em_handle_rx(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ifnet *ifp = adapter->ifp;
-
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
- (em_rxeof(adapter, adapter->rx_process_limit) != 0))
- taskqueue_enqueue(adapter->tq, &adapter->rx_task);
-
-}
-
-static void
-em_handle_tx(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ifnet *ifp = adapter->ifp;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- EM_TX_LOCK(adapter);
- em_txeof(adapter);
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- em_start_locked(ifp);
- EM_TX_UNLOCK(adapter);
- }
-}
-
/*********************************************************************
*
* Fast Legacy/MSI Combined Interrupt Service routine
@@ -1868,6 +1833,33 @@ em_msix_link(void *arg)
EM_MSIX_LINK | E1000_IMS_LSC);
return;
}
+
+static void
+em_handle_rx(void *context, int pending)
+{
+ struct adapter *adapter = context;
+ struct ifnet *ifp = adapter->ifp;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
+ (em_rxeof(adapter, adapter->rx_process_limit) != 0))
+ taskqueue_enqueue(adapter->tq, &adapter->rx_task);
+
+}
+
+static void
+em_handle_tx(void *context, int pending)
+{
+ struct adapter *adapter = context;
+ struct ifnet *ifp = adapter->ifp;
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ EM_TX_LOCK(adapter);
+ em_txeof(adapter);
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ em_start_locked(ifp);
+ EM_TX_UNLOCK(adapter);
+ }
+}
#endif /* EM_FAST_IRQ */
/*********************************************************************
@@ -2468,7 +2460,7 @@ em_set_multi(struct adapter *adapter)
struct ifnet *ifp = adapter->ifp;
struct ifmultiaddr *ifma;
u32 reg_rctl = 0;
- u8 mta[512]; /* Largest MTS is 4096 bits */
+ u8 *mta; /* Multicast array memory */
int mcnt = 0;
IOCTL_DEBUGOUT("em_set_multi: begin");
@@ -2483,6 +2475,13 @@ em_set_multi(struct adapter *adapter)
msec_delay(5);
}
+ /* Allocate temporary memory to setup array */
+ mta = malloc(sizeof(u8) *
+ (ETH_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (mta == NULL)
+ panic("em_set_multi memory failure\n");
+
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
@@ -2502,8 +2501,7 @@ em_set_multi(struct adapter *adapter)
reg_rctl |= E1000_RCTL_MPE;
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
} else
- e1000_update_mc_addr_list(&adapter->hw, mta,
- mcnt, 1, adapter->hw.mac.rar_entry_count);
+ e1000_update_mc_addr_list(&adapter->hw, mta, mcnt);
if (adapter->hw.mac.type == e1000_82542 &&
adapter->hw.revision_id == E1000_REVISION_2) {
@@ -2514,6 +2512,7 @@ em_set_multi(struct adapter *adapter)
if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
e1000_pci_set_mwi(&adapter->hw);
}
+ free(mta, M_DEVBUF);
}
@@ -2925,6 +2924,7 @@ em_allocate_msix(struct adapter *adapter)
return (0);
}
+
static void
em_free_pci_resources(struct adapter *adapter)
{
@@ -2973,7 +2973,7 @@ em_free_pci_resources(struct adapter *adapter)
}
/*
- * Setup MSI/X
+ * Setup MSI or MSI/X
*/
static int
em_setup_msix(struct adapter *adapter)
OpenPOWER on IntegriCloud