aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/bnx2.c6
-rw-r--r--drivers/net/bonding/bond_alb.c12
-rw-r--r--drivers/net/bonding/bond_main.c30
-rw-r--r--drivers/net/e1000/e1000_main.c4
-rw-r--r--drivers/net/e1000e/netdev.c2
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c31
-rw-r--r--drivers/net/igb/igb.h2
-rw-r--r--drivers/net/igb/igb_ethtool.c8
-rw-r--r--drivers/net/igb/igb_main.c26
-rw-r--r--drivers/net/igbvf/ethtool.c36
-rw-r--r--drivers/net/igbvf/igbvf.h6
-rw-r--r--drivers/net/igbvf/netdev.c17
-rw-r--r--drivers/net/ixgb/ixgb_main.c2
-rw-r--r--drivers/net/ixgbe/ixgbe.h7
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_nl.c16
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c369
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h1
-rw-r--r--drivers/net/lasi_82596.c6
-rw-r--r--drivers/net/mv643xx_eth.c87
-rw-r--r--drivers/net/netxen/netxen_nic.h12
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c156
-rw-r--r--drivers/net/netxen/netxen_nic_hw.h10
-rw-r--r--drivers/net/netxen/netxen_nic_init.c15
-rw-r--r--drivers/net/netxen/netxen_nic_main.c55
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c154
-rw-r--r--drivers/net/r6040.c12
-rw-r--r--drivers/net/smsc911x.c48
-rw-r--r--drivers/net/usb/Kconfig14
-rw-r--r--drivers/net/usb/Makefile1
-rw-r--r--drivers/net/usb/cdc_eem.c381
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c1
-rw-r--r--drivers/pci/quirks.c2
35 files changed, 992 insertions, 562 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index d47839184a0..b0cb29d4cc0 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -54,8 +54,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "2.0.0"
-#define DRV_MODULE_RELDATE "April 2, 2009"
+#define DRV_MODULE_VERSION "2.0.1"
+#define DRV_MODULE_RELDATE "May 6, 2009"
#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-4.6.16.fw"
#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-4.6.16.fw"
#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-4.6.17.fw"
@@ -2600,6 +2600,7 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi)
/* Tell compiler that status block fields can change. */
barrier();
cons = *bnapi->hw_tx_cons_ptr;
+ barrier();
if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT))
cons++;
return cons;
@@ -2879,6 +2880,7 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
/* Tell compiler that status block fields can change. */
barrier();
cons = *bnapi->hw_rx_cons_ptr;
+ barrier();
if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT))
cons++;
return cons;
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 553a8991977..46d312bedfb 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1706,10 +1706,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
* Called with RTNL
*/
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
- __releases(&bond->curr_slave_lock)
- __releases(&bond->lock)
__acquires(&bond->lock)
- __acquires(&bond->curr_slave_lock)
+ __releases(&bond->lock)
{
struct bonding *bond = netdev_priv(bond_dev);
struct sockaddr *sa = addr;
@@ -1745,9 +1743,6 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
}
}
- write_unlock_bh(&bond->curr_slave_lock);
- read_unlock(&bond->lock);
-
if (swap_slave) {
alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
@@ -1755,16 +1750,15 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
bond->alb_info.rlb_enabled);
+ read_lock(&bond->lock);
alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
if (bond->alb_info.rlb_enabled) {
/* inform clients mac address has changed */
rlb_req_update_slave_clients(bond, bond->curr_active_slave);
}
+ read_unlock(&bond->lock);
}
- read_lock(&bond->lock);
- write_lock_bh(&bond->curr_slave_lock);
-
return 0;
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index e3af662b055..815191dd03c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3459,8 +3459,28 @@ static void bond_destroy_proc_dir(void)
bond_proc_dir = NULL;
}
}
+
+#else /* !CONFIG_PROC_FS */
+
+static int bond_create_proc_entry(struct bonding *bond)
+{
+}
+
+static void bond_remove_proc_entry(struct bonding *bond)
+{
+}
+
+static void bond_create_proc_dir(void)
+{
+}
+
+static void bond_destroy_proc_dir(void)
+{
+}
+
#endif /* CONFIG_PROC_FS */
+
/*-------------------------- netdev event handling --------------------------*/
/*
@@ -3468,10 +3488,8 @@ static void bond_destroy_proc_dir(void)
*/
static int bond_event_changename(struct bonding *bond)
{
-#ifdef CONFIG_PROC_FS
bond_remove_proc_entry(bond);
bond_create_proc_entry(bond);
-#endif
down_write(&(bonding_rwsem));
bond_destroy_sysfs_entry(bond);
bond_create_sysfs_entry(bond);
@@ -4637,9 +4655,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER);
-#ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond);
-#endif
list_add_tail(&bond->bond_list, &bond_dev_list);
return 0;
@@ -4677,9 +4693,7 @@ static void bond_deinit(struct net_device *bond_dev)
bond_work_cancel_all(bond);
-#ifdef CONFIG_PROC_FS
bond_remove_proc_entry(bond);
-#endif
}
/* Unregister and free all bond devices.
@@ -4698,9 +4712,7 @@ static void bond_free_all(void)
bond_destroy(bond);
}
-#ifdef CONFIG_PROC_FS
bond_destroy_proc_dir();
-#endif
}
/*------------------------- Module initialization ---------------------------*/
@@ -5196,9 +5208,7 @@ static int __init bonding_init(void)
goto out;
}
-#ifdef CONFIG_PROC_FS
bond_create_proc_dir();
-#endif
init_rwsem(&bonding_rwsem);
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 71d4fe15976..9a32d0c73cb 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2646,6 +2646,8 @@ static void e1000_watchdog(unsigned long data)
* (Do the reset outside of interrupt context). */
adapter->tx_timeout_count++;
schedule_work(&adapter->reset_task);
+ /* return immediately since reset is imminent */
+ return;
}
}
@@ -3739,7 +3741,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
struct e1000_hw *hw = &adapter->hw;
u32 rctl, icr = er32(ICR);
- if (unlikely((!icr) || test_bit(__E1000_RESETTING, &adapter->flags)))
+ if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags)))
return IRQ_NONE; /* Not our interrupt */
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index da6b37e05be..ccaaee0951c 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -3651,6 +3651,8 @@ link_up:
*/
adapter->tx_timeout_count++;
schedule_work(&adapter->reset_task);
+ /* return immediately since reset is imminent */
+ return;
}
}
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 6e317caf429..16a41389575 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0100"
+#define DRV_VERSION "EHEA_0101"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 37a190d85fc..147c4b088fb 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -545,14 +545,17 @@ static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
x &= (arr_len - 1);
pref = skb_array[x];
- prefetchw(pref);
- prefetchw(pref + EHEA_CACHE_LINE);
-
- pref = (skb_array[x]->data);
- prefetch(pref);
- prefetch(pref + EHEA_CACHE_LINE);
- prefetch(pref + EHEA_CACHE_LINE * 2);
- prefetch(pref + EHEA_CACHE_LINE * 3);
+ if (pref) {
+ prefetchw(pref);
+ prefetchw(pref + EHEA_CACHE_LINE);
+
+ pref = (skb_array[x]->data);
+ prefetch(pref);
+ prefetch(pref + EHEA_CACHE_LINE);
+ prefetch(pref + EHEA_CACHE_LINE * 2);
+ prefetch(pref + EHEA_CACHE_LINE * 3);
+ }
+
skb = skb_array[skb_index];
skb_array[skb_index] = NULL;
return skb;
@@ -569,12 +572,14 @@ static inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array,
x &= (arr_len - 1);
pref = skb_array[x];
- prefetchw(pref);
- prefetchw(pref + EHEA_CACHE_LINE);
+ if (pref) {
+ prefetchw(pref);
+ prefetchw(pref + EHEA_CACHE_LINE);
- pref = (skb_array[x]->data);
- prefetchw(pref);
- prefetchw(pref + EHEA_CACHE_LINE);
+ pref = (skb_array[x]->data);
+ prefetchw(pref);
+ prefetchw(pref + EHEA_CACHE_LINE);
+ }
skb = skb_array[wqe_index];
skb_array[wqe_index] = NULL;
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 4e8464b9df2..154c5acc6fc 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -238,7 +238,6 @@ struct igb_adapter {
u64 hw_csum_err;
u64 hw_csum_good;
u32 alloc_rx_buff_failed;
- bool rx_csum;
u32 gorc;
u64 gorc_old;
u16 rx_ps_hdr_size;
@@ -286,6 +285,7 @@ struct igb_adapter {
#define IGB_FLAG_DCA_ENABLED (1 << 1)
#define IGB_FLAG_QUAD_PORT_A (1 << 2)
#define IGB_FLAG_NEED_CTX_IDX (1 << 3)
+#define IGB_FLAG_RX_CSUM_DISABLED (1 << 4)
enum e1000_state_t {
__IGB_TESTING,
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index b1367ce6586..b8551a57dd3 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -275,13 +275,17 @@ static int igb_set_pauseparam(struct net_device *netdev,
static u32 igb_get_rx_csum(struct net_device *netdev)
{
struct igb_adapter *adapter = netdev_priv(netdev);
- return adapter->rx_csum;
+ return !(adapter->flags & IGB_FLAG_RX_CSUM_DISABLED);
}
static int igb_set_rx_csum(struct net_device *netdev, u32 data)
{
struct igb_adapter *adapter = netdev_priv(netdev);
- adapter->rx_csum = data;
+
+ if (data)
+ adapter->flags &= ~IGB_FLAG_RX_CSUM_DISABLED;
+ else
+ adapter->flags |= IGB_FLAG_RX_CSUM_DISABLED;
return 0;
}
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index bca7e9f76be..ffd73153999 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1395,8 +1395,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
igb_validate_mdi_setting(hw);
- adapter->rx_csum = 1;
-
/* Initial Wake on LAN setting If APM wake is enabled in the EEPROM,
* enable the ACPI Magic Packet filter
*/
@@ -2012,7 +2010,7 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 rctl;
u32 srrctl = 0;
- int i, j;
+ int i;
rctl = rd32(E1000_RCTL);
@@ -2077,8 +2075,6 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
if (adapter->vfs_allocated_count) {
u32 vmolr;
- j = adapter->rx_ring[0].reg_idx;
-
/* set all queue drop enable bits */
wr32(E1000_QDE, ALL_QUEUES);
srrctl |= E1000_SRRCTL_DROP_EN;
@@ -2086,16 +2082,16 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
/* disable queue 0 to prevent tail write w/o re-config */
wr32(E1000_RXDCTL(0), 0);
- vmolr = rd32(E1000_VMOLR(j));
+ vmolr = rd32(E1000_VMOLR(adapter->vfs_allocated_count));
if (rctl & E1000_RCTL_LPE)
vmolr |= E1000_VMOLR_LPE;
- if (adapter->num_rx_queues > 0)
+ if (adapter->num_rx_queues > 1)
vmolr |= E1000_VMOLR_RSSE;
- wr32(E1000_VMOLR(j), vmolr);
+ wr32(E1000_VMOLR(adapter->vfs_allocated_count), vmolr);
}
for (i = 0; i < adapter->num_rx_queues; i++) {
- j = adapter->rx_ring[i].reg_idx;
+ int j = adapter->rx_ring[i].reg_idx;
wr32(E1000_SRRCTL(j), srrctl);
}
@@ -2249,13 +2245,12 @@ static void igb_configure_rx(struct igb_adapter *adapter)
rxcsum = rd32(E1000_RXCSUM);
/* Disable raw packet checksumming */
rxcsum |= E1000_RXCSUM_PCSD;
- /* Don't need to set TUOFL or IPOFL, they default to 1 */
- if (!adapter->rx_csum)
- rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL);
- else if (adapter->hw.mac.type == e1000_82576)
+
+ if (adapter->hw.mac.type == e1000_82576)
/* Enable Receive Checksum Offload for SCTP */
rxcsum |= E1000_RXCSUM_CRCOFL;
+ /* Don't need to set TUOFL or IPOFL, they default to 1 */
wr32(E1000_RXCSUM, rxcsum);
/* Set the default pool for the PF's first queue */
@@ -2714,6 +2709,8 @@ link_up:
* (Do the reset outside of interrupt context). */
adapter->tx_timeout_count++;
schedule_work(&adapter->reset_task);
+ /* return immediately since reset is imminent */
+ return;
}
}
@@ -4455,7 +4452,8 @@ static inline void igb_rx_checksum_adv(struct igb_adapter *adapter,
skb->ip_summed = CHECKSUM_NONE;
/* Ignore Checksum bit is set or checksum is disabled through ethtool */
- if ((status_err & E1000_RXD_STAT_IXSM) || !adapter->rx_csum)
+ if ((status_err & E1000_RXD_STAT_IXSM) ||
+ (adapter->flags & IGB_FLAG_RX_CSUM_DISABLED))
return;
/* TCP/UDP checksum error bit is set */
if (status_err &
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c
index 1dcaa690531..ee17a097d1c 100644
--- a/drivers/net/igbvf/ethtool.c
+++ b/drivers/net/igbvf/ethtool.c
@@ -133,6 +133,24 @@ static int igbvf_set_pauseparam(struct net_device *netdev,
return -EOPNOTSUPP;
}
+static u32 igbvf_get_rx_csum(struct net_device *netdev)
+{
+ struct igbvf_adapter *adapter = netdev_priv(netdev);
+ return !(adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED);
+}
+
+static int igbvf_set_rx_csum(struct net_device *netdev, u32 data)
+{
+ struct igbvf_adapter *adapter = netdev_priv(netdev);
+
+ if (data)
+ adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
+ else
+ adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
+
+ return 0;
+}
+
static u32 igbvf_get_tx_csum(struct net_device *netdev)
{
return ((netdev->features & NETIF_F_IP_CSUM) != 0);
@@ -150,8 +168,6 @@ static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
static int igbvf_set_tso(struct net_device *netdev, u32 data)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
- int i;
- struct net_device *v_netdev;
if (data) {
netdev->features |= NETIF_F_TSO;
@@ -159,24 +175,10 @@ static int igbvf_set_tso(struct net_device *netdev, u32 data)
} else {
netdev->features &= ~NETIF_F_TSO;
netdev->features &= ~NETIF_F_TSO6;
- /* disable TSO on all VLANs if they're present */
- if (!adapter->vlgrp)
- goto tso_out;
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
- v_netdev = vlan_group_get_device(adapter->vlgrp, i);
- if (!v_netdev)
- continue;
-
- v_netdev->features &= ~NETIF_F_TSO;
- v_netdev->features &= ~NETIF_F_TSO6;
- vlan_group_set_device(adapter->vlgrp, i, v_netdev);
- }
}
-tso_out:
dev_info(&adapter->pdev->dev, "TSO is %s\n",
data ? "Enabled" : "Disabled");
- adapter->flags |= FLAG_TSO_FORCE;
return 0;
}
@@ -517,6 +519,8 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
.set_ringparam = igbvf_set_ringparam,
.get_pauseparam = igbvf_get_pauseparam,
.set_pauseparam = igbvf_set_pauseparam,
+ .get_rx_csum = igbvf_get_rx_csum,
+ .set_rx_csum = igbvf_set_rx_csum,
.get_tx_csum = igbvf_get_tx_csum,
.set_tx_csum = igbvf_set_tx_csum,
.get_sg = ethtool_op_get_sg,
diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h
index 4bff35e4687..2ad6cd75653 100644
--- a/drivers/net/igbvf/igbvf.h
+++ b/drivers/net/igbvf/igbvf.h
@@ -286,11 +286,7 @@ struct igbvf_info {
};
/* hardware capability, feature, and workaround flags */
-#define FLAG_HAS_HW_VLAN_FILTER (1 << 0)
-#define FLAG_HAS_JUMBO_FRAMES (1 << 1)
-#define FLAG_MSI_ENABLED (1 << 2)
-#define FLAG_RX_CSUM_ENABLED (1 << 3)
-#define FLAG_TSO_FORCE (1 << 4)
+#define IGBVF_FLAG_RX_CSUM_DISABLED (1 << 0)
#define IGBVF_RX_DESC_ADV(R, i) \
(&((((R).desc))[i].rx_desc))
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index b774666ad3c..44a8eef03a7 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -58,8 +58,7 @@ static void igbvf_reset_interrupt_capability(struct igbvf_adapter *);
static struct igbvf_info igbvf_vf_info = {
.mac = e1000_vfadapt,
- .flags = FLAG_HAS_JUMBO_FRAMES
- | FLAG_RX_CSUM_ENABLED,
+ .flags = 0,
.pba = 10,
.init_ops = e1000_init_function_pointers_vf,
};
@@ -107,8 +106,10 @@ static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
skb->ip_summed = CHECKSUM_NONE;
/* Ignore Checksum bit is set or checksum is disabled through ethtool */
- if ((status_err & E1000_RXD_STAT_IXSM))
+ if ((status_err & E1000_RXD_STAT_IXSM) ||
+ (adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED))
return;
+
/* TCP/UDP checksum error bit is set */
if (status_err &
(E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) {
@@ -116,6 +117,7 @@ static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
adapter->hw_csum_err++;
return;
}
+
/* It must be a TCP or UDP packet with a valid checksum */
if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -2351,15 +2353,6 @@ static int igbvf_change_mtu(struct net_device *netdev, int new_mtu)
return -EINVAL;
}
- /* Jumbo frame size limits */
- if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) {
- if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
- dev_err(&adapter->pdev->dev,
- "Jumbo Frames not supported.\n");
- return -EINVAL;
- }
- }
-
#define MAX_STD_JUMBO_FRAME_SIZE 9234
if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n");
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index cb9ecc48f6d..04cb81a739c 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1140,6 +1140,8 @@ ixgb_watchdog(unsigned long data)
* to get done, so reset controller to flush Tx.
* (Do the reset outside of interrupt context). */
schedule_work(&adapter->tx_timeout_task);
+ /* return immediately since reset is imminent */
+ return;
}
}
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 4b44a8efac8..d743d0ed5c2 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -187,6 +187,7 @@ struct ixgbe_q_vector {
u8 tx_itr;
u8 rx_itr;
u32 eitr;
+ u32 v_idx; /* vector index in list */
};
/* Helper macros to switch between ints/sec and what the register uses.
@@ -230,7 +231,7 @@ struct ixgbe_adapter {
struct vlan_group *vlgrp;
u16 bd_number;
struct work_struct reset_task;
- struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS];
+ struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
char name[MAX_MSIX_COUNT][IFNAMSIZ + 9];
struct ixgbe_dcb_config dcb_cfg;
struct ixgbe_dcb_config temp_dcb_cfg;
@@ -367,10 +368,8 @@ extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *)
extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
-extern void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter);
extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
-void ixgbe_napi_add_all(struct ixgbe_adapter *adapter);
-void ixgbe_napi_del_all(struct ixgbe_adapter *adapter);
+extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
extern void ixgbe_write_eitr(struct ixgbe_adapter *, int, u32);
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
index bd0a0c27695..99e0c106e67 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -124,13 +124,7 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
if (netif_running(netdev))
netdev->netdev_ops->ndo_stop(netdev);
- ixgbe_reset_interrupt_capability(adapter);
- ixgbe_napi_del_all(adapter);
- INIT_LIST_HEAD(&netdev->napi_list);
- kfree(adapter->tx_ring);
- kfree(adapter->rx_ring);
- adapter->tx_ring = NULL;
- adapter->rx_ring = NULL;
+ ixgbe_clear_interrupt_scheme(adapter);
adapter->hw.fc.requested_mode = ixgbe_fc_pfc;
adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
@@ -144,13 +138,7 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
adapter->hw.fc.requested_mode = ixgbe_fc_default;
if (netif_running(netdev))
netdev->netdev_ops->ndo_stop(netdev);
- ixgbe_reset_interrupt_capability(adapter);
- ixgbe_napi_del_all(adapter);
- INIT_LIST_HEAD(&netdev->napi_list);
- kfree(adapter->tx_ring);
- kfree(adapter->rx_ring);
- adapter->tx_ring = NULL;
- adapter->rx_ring = NULL;
+ ixgbe_clear_interrupt_scheme(adapter);
adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index d822c92058c..c0167d617b1 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -1114,7 +1114,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
}
for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
- struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
+ struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
if (q_vector->txr_count && !q_vector->rxr_count)
/* tx vector gets half the rate */
q_vector->eitr = (adapter->eitr_param >> 1);
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index be5eabce9e3..efb175b1e43 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -461,6 +461,7 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
**/
static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
struct sk_buff *skb, u8 status,
+ struct ixgbe_ring *ring,
union ixgbe_adv_rx_desc *rx_desc)
{
struct ixgbe_adapter *adapter = q_vector->adapter;
@@ -468,7 +469,7 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
bool is_vlan = (status & IXGBE_RXD_STAT_VP);
u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
- skb_record_rx_queue(skb, q_vector - &adapter->q_vector[0]);
+ skb_record_rx_queue(skb, ring->queue_index);
if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
if (adapter->vlgrp && is_vlan && (tag != 0))
vlan_gro_receive(napi, adapter->vlgrp, tag, skb);
@@ -782,7 +783,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
total_rx_packets++;
skb->protocol = eth_type_trans(skb, adapter->netdev);
- ixgbe_receive_skb(q_vector, skb, staterr, rx_desc);
+ ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc);
next_desc:
rx_desc->wb.upper.status_error = 0;
@@ -835,7 +836,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
* corresponding register.
*/
for (v_idx = 0; v_idx < q_vectors; v_idx++) {
- q_vector = &adapter->q_vector[v_idx];
+ q_vector = adapter->q_vector[v_idx];
/* XXX for_each_bit(...) */
r_idx = find_first_bit(q_vector->rxr_idx,
adapter->num_rx_queues);
@@ -984,8 +985,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
struct ixgbe_adapter *adapter = q_vector->adapter;
u32 new_itr;
u8 current_itr, ret_itr;
- int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) /
- sizeof(struct ixgbe_q_vector);
+ int i, r_idx, v_idx = q_vector->v_idx;
struct ixgbe_ring *rx_ring, *tx_ring;
r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
@@ -1303,19 +1303,21 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget)
static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
int r_idx)
{
- a->q_vector[v_idx].adapter = a;
- set_bit(r_idx, a->q_vector[v_idx].rxr_idx);
- a->q_vector[v_idx].rxr_count++;
- a->rx_ring[r_idx].v_idx = 1 << v_idx;
+ struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
+
+ set_bit(r_idx, q_vector->rxr_idx);
+ q_vector->rxr_count++;
+ a->rx_ring[r_idx].v_idx = (u64)1 << v_idx;
}
static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
- int r_idx)
+ int t_idx)
{
- a->q_vector[v_idx].adapter = a;
- set_bit(r_idx, a->q_vector[v_idx].txr_idx);
- a->q_vector[v_idx].txr_count++;
- a->tx_ring[r_idx].v_idx = 1 << v_idx;
+ struct ixgbe_q_vector *q_vector = a->q_vector[v_idx];
+
+ set_bit(t_idx, q_vector->txr_idx);
+ q_vector->txr_count++;
+ a->tx_ring[t_idx].v_idx = (u64)1 << v_idx;
}
/**
@@ -1411,7 +1413,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
(!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
&ixgbe_msix_clean_many)
for (vector = 0; vector < q_vectors; vector++) {
- handler = SET_HANDLER(&adapter->q_vector[vector]);
+ handler = SET_HANDLER(adapter->q_vector[vector]);
if(handler == &ixgbe_msix_clean_rx) {
sprintf(adapter->name[vector], "%s-%s-%d",
@@ -1427,7 +1429,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
err = request_irq(adapter->msix_entries[vector].vector,
handler, 0, adapter->name[vector],
- &(adapter->q_vector[vector]));
+ adapter->q_vector[vector]);
if (err) {
DPRINTK(PROBE, ERR,
"request_irq failed for MSIX interrupt "
@@ -1450,7 +1452,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
free_queue_irqs:
for (i = vector - 1; i >= 0; i--)
free_irq(adapter->msix_entries[--vector].vector,
- &(adapter->q_vector[i]));
+ adapter->q_vector[i]);
adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries);
@@ -1461,7 +1463,7 @@ out:
static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
{
- struct ixgbe_q_vector *q_vector = adapter->q_vector;
+ struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
u8 current_itr;
u32 new_itr = q_vector->eitr;
struct ixgbe_ring *rx_ring = &adapter->rx_ring[0];
@@ -1539,6 +1541,7 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
struct net_device *netdev = data;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
u32 eicr;
/*
@@ -1566,13 +1569,13 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
ixgbe_check_fan_failure(adapter, eicr);
- if (napi_schedule_prep(&adapter->q_vector[0].napi)) {
+ if (napi_schedule_prep(&(q_vector->napi))) {
adapter->tx_ring[0].total_packets = 0;
adapter->tx_ring[0].total_bytes = 0;
adapter->rx_ring[0].total_packets = 0;
adapter->rx_ring[0].total_bytes = 0;
/* would disable interrupts here but EIAM disabled it */
- __napi_schedule(&adapter->q_vector[0].napi);
+ __napi_schedule(&(q_vector->napi));
}
return IRQ_HANDLED;
@@ -1583,7 +1586,7 @@ static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter)
int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
for (i = 0; i < q_vectors; i++) {
- struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
+ struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES);
bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES);
q_vector->rxr_count = 0;
@@ -1634,7 +1637,7 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
i--;
for (; i >= 0; i--) {
free_irq(adapter->msix_entries[i].vector,
- &(adapter->q_vector[i]));
+ adapter->q_vector[i]);
}
ixgbe_reset_q_vectors(adapter);
@@ -1737,7 +1740,18 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index)
unsigned long mask;
if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
- queue0 = index;
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
+ if (dcb_i == 8)
+ queue0 = index >> 4;
+ else if (dcb_i == 4)
+ queue0 = index >> 5;
+ else
+ dev_err(&adapter->pdev->dev, "Invalid DCB "
+ "configuration\n");
+ } else {
+ queue0 = index;
+ }
} else {
mask = (unsigned long) adapter->ring_feature[RING_F_RSS].mask;
queue0 = index & mask;
@@ -1751,28 +1765,20 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index)
srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
+ srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
+ IXGBE_SRRCTL_BSIZEHDR_MASK;
+
if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
- u16 bufsz = IXGBE_RXBUFFER_2048;
- /* grow the amount we can receive on large page machines */
- if (bufsz < (PAGE_SIZE / 2))
- bufsz = (PAGE_SIZE / 2);
- /* cap the bufsz at our largest descriptor size */
- bufsz = min((u16)IXGBE_MAX_RXBUFFER, bufsz);
-
- srrctl |= bufsz >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+#if (PAGE_SIZE / 2) > IXGBE_MAX_RXBUFFER
+ srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+#else
+ srrctl |= (PAGE_SIZE / 2) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+#endif
srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
- srrctl |= ((IXGBE_RX_HDR_SIZE <<
- IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
- IXGBE_SRRCTL_BSIZEHDR_MASK);
} else {
+ srrctl |= ALIGN(rx_ring->rx_buf_len, 1024) >>
+ IXGBE_SRRCTL_BSIZEPKT_SHIFT;
srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
-
- if (rx_ring->rx_buf_len == MAXIMUM_ETHERNET_VLAN_SIZE)
- srrctl |= IXGBE_RXBUFFER_2048 >>
- IXGBE_SRRCTL_BSIZEPKT_SHIFT;
- else
- srrctl |= rx_ring->rx_buf_len >>
- IXGBE_SRRCTL_BSIZEPKT_SHIFT;
}
IXGBE_WRITE_REG(&adapter->hw, IXGBE_SRRCTL(index), srrctl);
@@ -1812,7 +1818,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
IXGBE_PSRTYPE_UDPHDR |
IXGBE_PSRTYPE_IPV4HDR |
- IXGBE_PSRTYPE_IPV6HDR;
+ IXGBE_PSRTYPE_IPV6HDR |
+ IXGBE_PSRTYPE_L2HDR;
IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
}
} else {
@@ -2135,7 +2142,7 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
for (q_idx = 0; q_idx < q_vectors; q_idx++) {
struct napi_struct *napi;
- q_vector = &adapter->q_vector[q_idx];
+ q_vector = adapter->q_vector[q_idx];
if (!q_vector->rxr_count)
continue;
napi = &q_vector->napi;
@@ -2158,7 +2165,7 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
q_vectors = 1;
for (q_idx = 0; q_idx < q_vectors; q_idx++) {
- q_vector = &adapter->q_vector[q_idx];
+ q_vector = adapter->q_vector[q_idx];
if (!q_vector->rxr_count)
continue;
napi_disable(&q_vector->napi);
@@ -2451,6 +2458,17 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
ixgbe_irq_enable(adapter);
/*
+ * If this adapter has a fan, check to see if we had a failure
+ * before we enabled the interrupt.
+ */
+ if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
+ u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+ if (esdp & IXGBE_ESDP_SDP1)
+ DPRINTK(DRV, CRIT,
+ "Fan has stopped, replace the adapter\n");
+ }
+
+ /*
* For hot-pluggable SFP+ devices, a new SFP+ module may have
* arrived before interrupts were enabled. We need to kick off
* the SFP+ module setup first, then try to bring up link.
@@ -2498,8 +2516,6 @@ int ixgbe_up(struct ixgbe_adapter *adapter)
/* hardware has been reset, we need to reload some things */
ixgbe_configure(adapter);
- ixgbe_napi_add_all(adapter);
-
return ixgbe_up_complete(adapter);
}
@@ -2877,9 +2893,6 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
- adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
- adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
- ixgbe_set_num_queues(adapter);
} else {
adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */
/*
@@ -3103,31 +3116,20 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
* mean we disable MSI-X capabilities of the adapter. */
adapter->msix_entries = kcalloc(v_budget,
sizeof(struct msix_entry), GFP_KERNEL);
- if (!adapter->msix_entries) {
- adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
- adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
- ixgbe_set_num_queues(adapter);
- kfree(adapter->tx_ring);
- kfree(adapter->rx_ring);
- err = ixgbe_alloc_queues(adapter);
- if (err) {
- DPRINTK(PROBE, ERR, "Unable to allocate memory "
- "for queues\n");
- goto out;
- }
-
- goto try_msi;
- }
+ if (adapter->msix_entries) {
+ for (vector = 0; vector < v_budget; vector++)
+ adapter->msix_entries[vector].entry = vector;
- for (vector = 0; vector < v_budget; vector++)
- adapter->msix_entries[vector].entry = vector;
+ ixgbe_acquire_msix_vectors(adapter, v_budget);
- ixgbe_acquire_msix_vectors(adapter, v_budget);
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+ goto out;
+ }
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
- goto out;
+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
+ adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+ ixgbe_set_num_queues(adapter);
-try_msi:
err = pci_enable_msi(adapter->pdev);
if (!err) {
adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
@@ -3142,6 +3144,87 @@ out:
return err;
}
+/**
+ * ixgbe_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * We allocate one q_vector per queue interrupt. If allocation fails we
+ * return -ENOMEM.
+ **/
+static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
+{
+ int q_idx, num_q_vectors;
+ struct ixgbe_q_vector *q_vector;
+ int napi_vectors;
+ int (*poll)(struct napi_struct *, int);
+
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ napi_vectors = adapter->num_rx_queues;
+ poll = &ixgbe_clean_rxonly;
+ } else {
+ num_q_vectors = 1;
+ napi_vectors = 1;
+ poll = &ixgbe_poll;
+ }
+
+ for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
+ q_vector = kzalloc(sizeof(struct ixgbe_q_vector), GFP_KERNEL);
+ if (!q_vector)
+ goto err_out;
+ q_vector->adapter = adapter;
+ q_vector->v_idx = q_idx;
+ q_vector->eitr = adapter->eitr_param;
+ if (q_idx < napi_vectors)
+ netif_napi_add(adapter->netdev, &q_vector->napi,
+ (*poll), 64);
+ adapter->q_vector[q_idx] = q_vector;
+ }
+
+ return 0;
+
+err_out:
+ while (q_idx) {
+ q_idx--;
+ q_vector = adapter->q_vector[q_idx];
+ netif_napi_del(&q_vector->napi);
+ kfree(q_vector);
+ adapter->q_vector[q_idx] = NULL;
+ }
+ return -ENOMEM;
+}
+
+/**
+ * ixgbe_free_q_vectors - Free memory allocated for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * This function frees the memory allocated to the q_vectors. In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter)
+{
+ int q_idx, num_q_vectors;
+ int napi_vectors;
+
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+ napi_vectors = adapter->num_rx_queues;
+ } else {
+ num_q_vectors = 1;
+ napi_vectors = 1;
+ }
+
+ for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
+ struct ixgbe_q_vector *q_vector = adapter->q_vector[q_idx];
+
+ adapter->q_vector[q_idx] = NULL;
+ if (q_idx < napi_vectors)
+ netif_napi_del(&q_vector->napi);
+ kfree(q_vector);
+ }
+}
+
void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
{
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
@@ -3173,18 +3256,25 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
/* Number of supported queues */
ixgbe_set_num_queues(adapter);
- err = ixgbe_alloc_queues(adapter);
- if (err) {
- DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
- goto err_alloc_queues;
- }
-
err = ixgbe_set_interrupt_capability(adapter);
if (err) {
DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n");
goto err_set_interrupt;
}
+ err = ixgbe_alloc_q_vectors(adapter);
+ if (err) {
+ DPRINTK(PROBE, ERR, "Unable to allocate memory for queue "
+ "vectors\n");
+ goto err_alloc_q_vectors;
+ }
+
+ err = ixgbe_alloc_queues(adapter);
+ if (err) {
+ DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
+ goto err_alloc_queues;
+ }
+
DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, "
"Tx Queue count = %u\n",
(adapter->num_rx_queues > 1) ? "Enabled" :
@@ -3194,11 +3284,30 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
return 0;
+err_alloc_queues:
+ ixgbe_free_q_vectors(adapter);
+err_alloc_q_vectors:
+ ixgbe_reset_interrupt_capability(adapter);
err_set_interrupt:
+ return err;
+}
+
+/**
+ * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings
+ * @adapter: board private structure to clear interrupt scheme on
+ *
+ * We go through and clear interrupt specific resources and reset the structure
+ * to pre-load conditions
+ **/
+void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
+{
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
-err_alloc_queues:
- return err;
+ adapter->tx_ring = NULL;
+ adapter->rx_ring = NULL;
+
+ ixgbe_free_q_vectors(adapter);
+ ixgbe_reset_interrupt_capability(adapter);
}
/**
@@ -3284,9 +3393,11 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->ring_feature[RING_F_RSS].indices = rss;
adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES;
- if (hw->mac.type == ixgbe_mac_82598EB)
+ if (hw->mac.type == ixgbe_mac_82598EB) {
+ if (hw->device_id == IXGBE_DEV_ID_82598AT)
+ adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598;
- else if (hw->mac.type == ixgbe_mac_82599EB) {
+ } else if (hw->mac.type == ixgbe_mac_82599EB) {
adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599;
adapter->flags |= IXGBE_FLAG_RSC_CAPABLE;
adapter->flags |= IXGBE_FLAG_RSC_ENABLED;
@@ -3619,8 +3730,6 @@ static int ixgbe_open(struct net_device *netdev)
ixgbe_configure(adapter);
- ixgbe_napi_add_all(adapter);
-
err = ixgbe_request_irq(adapter);
if (err)
goto err_req_irq;
@@ -3672,55 +3781,6 @@ static int ixgbe_close(struct net_device *netdev)
return 0;
}
-/**
- * ixgbe_napi_add_all - prep napi structs for use
- * @adapter: private struct
- *
- * helper function to napi_add each possible q_vector->napi
- */
-void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
-{
- int q_idx, q_vectors;
- struct net_device *netdev = adapter->netdev;
- int (*poll)(struct napi_struct *, int);
-
- /* check if we already have our netdev->napi_list populated */
- if (&netdev->napi_list != netdev->napi_list.next)
- return;
-
- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
- poll = &ixgbe_clean_rxonly;
- /* Only enable as many vectors as we have rx queues. */
- q_vectors = adapter->num_rx_queues;
- } else {
- poll = &ixgbe_poll;
- /* only one q_vector for legacy modes */
- q_vectors = 1;
- }
-
- for (q_idx = 0; q_idx < q_vectors; q_idx++) {
- struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx];
- netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
- }
-}
-
-void ixgbe_napi_del_all(struct ixgbe_adapter *adapter)
-{
- int q_idx;
- int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
-
- /* legacy and MSI only use one vector */
- if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
- q_vectors = 1;
-
- for (q_idx = 0; q_idx < q_vectors; q_idx++) {
- struct ixgbe_q_vector *q_vector = &adapter->q_vector[q_idx];
- if (!q_vector->rxr_count)
- continue;
- netif_napi_del(&q_vector->napi);
- }
-}
-
#ifdef CONFIG_PM
static int ixgbe_resume(struct pci_dev *pdev)
{
@@ -3730,7 +3790,8 @@ static int ixgbe_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- err = pci_enable_device(pdev);
+
+ err = pci_enable_device_mem(pdev);
if (err) {
printk(KERN_ERR "ixgbe: Cannot enable PCI device from "
"suspend\n");
@@ -3782,11 +3843,7 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
ixgbe_free_all_tx_resources(adapter);
ixgbe_free_all_rx_resources(adapter);
}
- ixgbe_reset_interrupt_capability(adapter);
- ixgbe_napi_del_all(adapter);
- INIT_LIST_HEAD(&netdev->napi_list);
- kfree(adapter->tx_ring);
- kfree(adapter->rx_ring);
+ ixgbe_clear_interrupt_scheme(adapter);
#ifdef CONFIG_PM
retval = pci_save_state(pdev);
@@ -4000,7 +4057,7 @@ static void ixgbe_watchdog(unsigned long data)
int i;
for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++)
- eics |= (1 << i);
+ eics |= ((u64)1 << i);
/* Cause software interrupt to ensure rx rings are cleaned */
switch (hw->mac.type) {
@@ -4739,7 +4796,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
int i, err, pci_using_dac;
u32 part_num, eec;
- err = pci_enable_device(pdev);
+ err = pci_enable_device_mem(pdev);
if (err)
return err;
@@ -4759,9 +4816,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
pci_using_dac = 0;
}
- err = pci_request_regions(pdev, ixgbe_driver_name);
+ err = pci_request_selected_regions(pdev, pci_select_bars(pdev,
+ IORESOURCE_MEM), ixgbe_driver_name);
if (err) {
- dev_err(&pdev->dev, "pci_request_regions failed 0x%x\n", err);
+ dev_err(&pdev->dev,
+ "pci_request_selected_regions failed 0x%x\n", err);
goto err_pci_reg;
}
@@ -4869,6 +4928,17 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
if (err)
goto err_sw_init;
+ /*
+ * If there is a fan on this device and it has failed log the
+ * failure.
+ */
+ if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
+ u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+ if (esdp & IXGBE_ESDP_SDP1)
+ DPRINTK(PROBE, CRIT,
+ "Fan has stopped, replace the adapter\n");
+ }
+
/* reset_hw fills in the perm_addr as well */
err = hw->mac.ops.reset_hw(hw);
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
@@ -5012,8 +5082,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
err_register:
ixgbe_release_hw_control(adapter);
err_hw_init:
+ ixgbe_clear_interrupt_scheme(adapter);
err_sw_init:
- ixgbe_reset_interrupt_capability(adapter);
err_eeprom:
clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
del_timer_sync(&adapter->sfp_timer);
@@ -5024,7 +5094,8 @@ err_eeprom:
err_ioremap:
free_netdev(netdev);
err_alloc_etherdev:
- pci_release_regions(pdev);
+ pci_release_selected_regions(pdev, pci_select_bars(pdev,
+ IORESOURCE_MEM));
err_pci_reg:
err_dma:
pci_disable_device(pdev);
@@ -5071,16 +5142,15 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdev(netdev);
- ixgbe_reset_interrupt_capability(adapter);
+ ixgbe_clear_interrupt_scheme(adapter);
ixgbe_release_hw_control(adapter);
iounmap(adapter->hw.hw_addr);
- pci_release_regions(pdev);
+ pci_release_selected_regions(pdev, pci_select_bars(pdev,
+ IORESOURCE_MEM));
DPRINTK(PROBE, INFO, "complete\n");
- kfree(adapter->tx_ring);
- kfree(adapter->rx_ring);
free_netdev(netdev);
@@ -5108,6 +5178,9 @@ static pci_ers_result_t ixgbe_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))
ixgbe_down(adapter);
pci_disable_device(pdev);
@@ -5129,7 +5202,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
pci_ers_result_t result;
int err;
- if (pci_enable_device(pdev)) {
+ if (pci_enable_device_mem(pdev)) {
DPRINTK(PROBE, ERR,
"Cannot re-enable PCI device after reset.\n");
result = PCI_ERS_RESULT_DISCONNECT;
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index e49e8af59ed..9fd79a05ff0 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -1604,6 +1604,7 @@
#define IXGBE_PSRTYPE_UDPHDR 0x00000020
#define IXGBE_PSRTYPE_IPV4HDR 0x00000100
#define IXGBE_PSRTYPE_IPV6HDR 0x00000200
+#define IXGBE_PSRTYPE_L2HDR 0x00001000
/* SRRCTL bit definitions */
#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index efbae4b8398..a0c578585a5 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -161,12 +161,12 @@ lan_init_chip(struct parisc_device *dev)
if (!dev->irq) {
printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
- __FILE__, dev->hpa.start);
+ __FILE__, (unsigned long)dev->hpa.start);
return -ENODEV;
}
- printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
- dev->irq);
+ printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n",
+ (unsigned long)dev->hpa.start, dev->irq);
netdevice = alloc_etherdev(sizeof(struct i596_private));
if (!netdevice)
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index a400d7115f7..d5838528791 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -88,7 +88,24 @@ static char mv643xx_eth_driver_version[] = "1.4";
#define MAC_ADDR_LOW 0x0014
#define MAC_ADDR_HIGH 0x0018
#define SDMA_CONFIG 0x001c
+#define TX_BURST_SIZE_16_64BIT 0x01000000
+#define TX_BURST_SIZE_4_64BIT 0x00800000
+#define BLM_TX_NO_SWAP 0x00000020
+#define BLM_RX_NO_SWAP 0x00000010
+#define RX_BURST_SIZE_16_64BIT 0x00000008
+#define RX_BURST_SIZE_4_64BIT 0x00000004
#define PORT_SERIAL_CONTROL 0x003c
+#define SET_MII_SPEED_TO_100 0x01000000
+#define SET_GMII_SPEED_TO_1000 0x00800000
+#define SET_FULL_DUPLEX_MODE 0x00200000
+#define MAX_RX_PACKET_9700BYTE 0x000a0000
+#define DISABLE_AUTO_NEG_SPEED_GMII 0x00002000
+#define DO_NOT_FORCE_LINK_FAIL 0x00000400
+#define SERIAL_PORT_CONTROL_RESERVED 0x00000200
+#define DISABLE_AUTO_NEG_FOR_FLOW_CTRL 0x00000008
+#define DISABLE_AUTO_NEG_FOR_DUPLEX 0x00000004
+#define FORCE_LINK_PASS 0x00000002
+#define SERIAL_PORT_ENABLE 0x00000001
#define PORT_STATUS 0x0044
#define TX_FIFO_EMPTY 0x00000400
#define TX_IN_PROGRESS 0x00000080
@@ -106,7 +123,9 @@ static char mv643xx_eth_driver_version[] = "1.4";
#define TX_BW_BURST 0x005c
#define INT_CAUSE 0x0060
#define INT_TX_END 0x07f80000
+#define INT_TX_END_0 0x00080000
#define INT_RX 0x000003fc
+#define INT_RX_0 0x00000004
#define INT_EXT 0x00000002
#define INT_CAUSE_EXT 0x0064
#define INT_EXT_LINK_PHY 0x00110000
@@ -135,15 +154,8 @@ static char mv643xx_eth_driver_version[] = "1.4";
/*
- * SDMA configuration register.
+ * SDMA configuration register default value.
*/
-#define RX_BURST_SIZE_4_64BIT (2 << 1)
-#define RX_BURST_SIZE_16_64BIT (4 << 1)
-#define BLM_RX_NO_SWAP (1 << 4)
-#define BLM_TX_NO_SWAP (1 << 5)
-#define TX_BURST_SIZE_4_64BIT (2 << 22)
-#define TX_BURST_SIZE_16_64BIT (4 << 22)
-
#if defined(__BIG_ENDIAN)
#define PORT_SDMA_CONFIG_DEFAULT_VALUE \
(RX_BURST_SIZE_4_64BIT | \
@@ -160,22 +172,11 @@ static char mv643xx_eth_driver_version[] = "1.4";
/*
- * Port serial control register.
+ * Misc definitions.
*/
-#define SET_MII_SPEED_TO_100 (1 << 24)
-#define SET_GMII_SPEED_TO_1000 (1 << 23)
-#define SET_FULL_DUPLEX_MODE (1 << 21)
-#define MAX_RX_PACKET_9700BYTE (5 << 17)
-#define DISABLE_AUTO_NEG_SPEED_GMII (1 << 13)
-#define DO_NOT_FORCE_LINK_FAIL (1 << 10)
-#define SERIAL_PORT_CONTROL_RESERVED (1 << 9)
-#define DISABLE_AUTO_NEG_FOR_FLOW_CTRL (1 << 3)
-#define DISABLE_AUTO_NEG_FOR_DUPLEX (1 << 2)
-#define FORCE_LINK_PASS (1 << 1)
-#define SERIAL_PORT_ENABLE (1 << 0)
-
-#define DEFAULT_RX_QUEUE_SIZE 128
-#define DEFAULT_TX_QUEUE_SIZE 256
+#define DEFAULT_RX_QUEUE_SIZE 128
+#define DEFAULT_TX_QUEUE_SIZE 256
+#define SKB_DMA_REALIGN ((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES)
/*
@@ -393,6 +394,7 @@ struct mv643xx_eth_private {
struct work_struct tx_timeout_task;
struct napi_struct napi;
+ u32 int_mask;
u8 oom;
u8 work_link;
u8 work_tx;
@@ -651,23 +653,20 @@ static int rxq_refill(struct rx_queue *rxq, int budget)
refilled = 0;
while (refilled < budget && rxq->rx_desc_count < rxq->rx_ring_size) {
struct sk_buff *skb;
- int unaligned;
int rx;
struct rx_desc *rx_desc;
skb = __skb_dequeue(&mp->rx_recycle);
if (skb == NULL)
- skb = dev_alloc_skb(mp->skb_size +
- dma_get_cache_alignment() - 1);
+ skb = dev_alloc_skb(mp->skb_size);
if (skb == NULL) {
mp->oom = 1;
goto oom;
}
- unaligned = (u32)skb->data & (dma_get_cache_alignment() - 1);
- if (unaligned)
- skb_reserve(skb, dma_get_cache_alignment() - unaligned);
+ if (SKB_DMA_REALIGN)
+ skb_reserve(skb, SKB_DMA_REALIGN);
refilled++;
rxq->rx_desc_count++;
@@ -966,8 +965,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
if (skb != NULL) {
if (skb_queue_len(&mp->rx_recycle) <
mp->rx_ring_size &&
- skb_recycle_check(skb, mp->skb_size +
- dma_get_cache_alignment() - 1))
+ skb_recycle_check(skb, mp->skb_size))
__skb_queue_head(&mp->rx_recycle, skb);
else
dev_kfree_skb(skb);
@@ -1807,7 +1805,6 @@ static void mv643xx_eth_program_multicast_filter(struct net_device *dev)
if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
int port_num;
u32 accept;
- int i;
oom:
port_num = mp->port_num;
@@ -2064,15 +2061,16 @@ static int mv643xx_eth_collect_events(struct mv643xx_eth_private *mp)
u32 int_cause;
u32 int_cause_ext;
- int_cause = rdlp(mp, INT_CAUSE) & (INT_TX_END | INT_RX | INT_EXT);
+ int_cause = rdlp(mp, INT_CAUSE) & mp->int_mask;
if (int_cause == 0)
return 0;
int_cause_ext = 0;
- if (int_cause & INT_EXT)
+ if (int_cause & INT_EXT) {
+ int_cause &= ~INT_EXT;
int_cause_ext = rdlp(mp, INT_CAUSE_EXT);
+ }
- int_cause &= INT_TX_END | INT_RX;
if (int_cause) {
wrlp(mp, INT_CAUSE, ~int_cause);
mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) &
@@ -2179,6 +2177,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
if (mp->work_link) {
mp->work_link = 0;
handle_link_event(mp);
+ work_done++;
continue;
}
@@ -2217,7 +2216,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
if (mp->oom)
mod_timer(&mp->rx_oom, jiffies + (HZ / 10));
napi_complete(napi);
- wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
+ wrlp(mp, INT_MASK, mp->int_mask);
}
return work_done;
@@ -2338,6 +2337,14 @@ static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp)
* size field are ignored by the hardware.
*/
mp->skb_size = (skb_size + 7) & ~7;
+
+ /*
+ * If NET_SKB_PAD is smaller than a cache line,
+ * netdev_alloc_skb() will cause skb->data to be misaligned
+ * to a cache line boundary. If this is the case, include
+ * some extra space to allow re-aligning the data area.
+ */
+ mp->skb_size += SKB_DMA_REALIGN;
}
static int mv643xx_eth_open(struct net_device *dev)
@@ -2363,6 +2370,8 @@ static int mv643xx_eth_open(struct net_device *dev)
skb_queue_head_init(&mp->rx_recycle);
+ mp->int_mask = INT_EXT;
+
for (i = 0; i < mp->rxq_count; i++) {
err = rxq_init(mp, i);
if (err) {
@@ -2372,6 +2381,7 @@ static int mv643xx_eth_open(struct net_device *dev)
}
rxq_refill(mp->rxq + i, INT_MAX);
+ mp->int_mask |= INT_RX_0 << i;
}
if (mp->oom) {
@@ -2386,12 +2396,13 @@ static int mv643xx_eth_open(struct net_device *dev)
txq_deinit(mp->txq + i);
goto out_free;
}
+ mp->int_mask |= INT_TX_END_0 << i;
}
port_start(mp);
wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX);
- wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
+ wrlp(mp, INT_MASK, mp->int_mask);
return 0;
@@ -2535,7 +2546,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev)
mv643xx_eth_irq(dev->irq, dev);
- wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
+ wrlp(mp, INT_MASK, mp->int_mask);
}
#endif
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 8dacfbb003e..9350c8663fd 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -1019,8 +1019,8 @@ typedef struct {
#define NETXEN_MAC_DEL 2
typedef struct nx_mac_list_s {
- struct nx_mac_list_s *next;
- uint8_t mac_addr[MAX_ADDR_LEN];
+ struct list_head list;
+ uint8_t mac_addr[ETH_ALEN+2];
} nx_mac_list_t;
/*
@@ -1213,7 +1213,7 @@ struct netxen_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
- nx_mac_list_t *mac_list;
+ struct list_head mac_list;
u32 curr_window;
u32 crb_win;
@@ -1264,9 +1264,10 @@ struct netxen_adapter {
int (*enable_phy_interrupts) (struct netxen_adapter *);
int (*disable_phy_interrupts) (struct netxen_adapter *);
- int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t);
+ int (*macaddr_set) (struct netxen_adapter *, u8 *);
int (*set_mtu) (struct netxen_adapter *, int);
int (*set_promisc) (struct netxen_adapter *, u32);
+ void (*set_multi) (struct net_device *);
int (*phy_read) (struct netxen_adapter *, long reg, u32 *);
int (*phy_write) (struct netxen_adapter *, long reg, u32 val);
int (*init_port) (struct netxen_adapter *, int);
@@ -1331,6 +1332,9 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
+int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
+int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
+
#define NXRD32(adapter, off) \
(adapter->hw_read_wx(adapter, off))
#define NXWR32(adapter, off, val) \
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 9f5ced3eaf9..86c9e78ec39 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -321,27 +321,6 @@ static unsigned crb_hub_agt[64] =
#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
-int netxen_nic_set_mac(struct net_device *netdev, void *p)
-{
- struct netxen_adapter *adapter = netdev_priv(netdev);
- struct sockaddr *addr = p;
-
- if (netif_running(netdev))
- return -EBUSY;
-
- if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
-
- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-
- /* For P3, MAC addr is not set in NIU */
- if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter, addr->sa_data);
-
- return 0;
-}
-
#define NETXEN_UNICAST_ADDR(port, index) \
(NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
#define NETXEN_MCAST_ADDR(port, index) \
@@ -470,45 +449,6 @@ void netxen_p2_nic_set_multi(struct net_device *netdev)
netxen_nic_set_mcast_addr(adapter, index, null_addr);
}
-static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
- u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
-{
- nx_mac_list_t *cur, *prev;
-
- /* if in del_list, move it to adapter->mac_list */
- for (cur = *del_list, prev = NULL; cur;) {
- if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
- if (prev == NULL)
- *del_list = cur->next;
- else
- prev->next = cur->next;
- cur->next = adapter->mac_list;
- adapter->mac_list = cur;
- return 0;
- }
- prev = cur;
- cur = cur->next;
- }
-
- /* make sure to add each mac address only once */
- for (cur = adapter->mac_list; cur; cur = cur->next) {
- if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
- return 0;
- }
- /* not in del_list, create new entry and add to add_list */
- cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
- if (cur == NULL) {
- printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
- "not work properly from now.\n", __func__);
- return -1;
- }
-
- memcpy(cur->mac_addr, addr, ETH_ALEN);
- cur->next = *add_list;
- *add_list = cur;
- return 0;
-}
-
static int
netxen_send_cmd_descs(struct netxen_adapter *adapter,
struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
@@ -526,7 +466,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
producer = tx_ring->producer;
consumer = tx_ring->sw_consumer;
- if (nr_desc > find_diff_among(producer, consumer, tx_ring->num_desc)) {
+ if (nr_desc >= find_diff_among(producer, consumer, tx_ring->num_desc)) {
netif_tx_unlock_bh(adapter->netdev);
return -EBUSY;
}
@@ -555,14 +495,12 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
return 0;
}
-static int nx_p3_sre_macaddr_change(struct net_device *dev,
- u8 *addr, unsigned op)
+static int
+nx_p3_sre_macaddr_change(struct netxen_adapter *adapter, u8 *addr, unsigned op)
{
- struct netxen_adapter *adapter = netdev_priv(dev);
nx_nic_req_t req;
nx_mac_req_t *mac_req;
u64 word;
- int rv;
memset(&req, 0, sizeof(nx_nic_req_t));
req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
@@ -574,28 +512,51 @@ static int nx_p3_sre_macaddr_change(struct net_device *dev,
mac_req->op = op;
memcpy(mac_req->mac_addr, addr, 6);
- rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
- if (rv != 0) {
- printk(KERN_ERR "ERROR. Could not send mac update\n");
- return rv;
+ return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+}
+
+static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
+ u8 *addr, struct list_head *del_list)
+{
+ struct list_head *head;
+ nx_mac_list_t *cur;
+
+ /* look up if already exists */
+ list_for_each(head, del_list) {
+ cur = list_entry(head, nx_mac_list_t, list);
+
+ if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+ list_move_tail(head, &adapter->mac_list);
+ return 0;
+ }
}
- return 0;
+ cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC);
+ if (cur == NULL) {
+ printk(KERN_ERR "%s: failed to add mac address filter\n",
+ adapter->netdev->name);
+ return -ENOMEM;
+ }
+ memcpy(cur->mac_addr, addr, ETH_ALEN);
+ list_add_tail(&cur->list, &adapter->mac_list);
+ return nx_p3_sre_macaddr_change(adapter,
+ cur->mac_addr, NETXEN_MAC_ADD);
}
void netxen_p3_nic_set_multi(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
- nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
struct dev_mc_list *mc_ptr;
u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
u32 mode = VPORT_MISS_MODE_DROP;
+ LIST_HEAD(del_list);
+ struct list_head *head;
+ nx_mac_list_t *cur;
- del_list = adapter->mac_list;
- adapter->mac_list = NULL;
+ list_splice_tail_init(&adapter->mac_list, &del_list);
- nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
- nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
+ nx_p3_nic_add_mac(adapter, netdev->dev_addr, &del_list);
+ nx_p3_nic_add_mac(adapter, bcast_addr, &del_list);
if (netdev->flags & IFF_PROMISC) {
mode = VPORT_MISS_MODE_ACCEPT_ALL;
@@ -611,25 +572,20 @@ void netxen_p3_nic_set_multi(struct net_device *netdev)
if (netdev->mc_count > 0) {
for (mc_ptr = netdev->mc_list; mc_ptr;
mc_ptr = mc_ptr->next) {
- nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
- &add_list, &del_list);
+ nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list);
}
}
send_fw_cmd:
adapter->set_promisc(adapter, mode);
- for (cur = del_list; cur;) {
- nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
- next = cur->next;
+ head = &del_list;
+ while (!list_empty(head)) {
+ cur = list_entry(head->next, nx_mac_list_t, list);
+
+ nx_p3_sre_macaddr_change(adapter,
+ cur->mac_addr, NETXEN_MAC_DEL);
+ list_del(&cur->list);
kfree(cur);
- cur = next;
- }
- for (cur = add_list; cur;) {
- nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
- next = cur->next;
- cur->next = adapter->mac_list;
- adapter->mac_list = cur;
- cur = next;
}
}
@@ -654,17 +610,25 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
void netxen_p3_free_mac_list(struct netxen_adapter *adapter)
{
- nx_mac_list_t *cur, *next;
-
- cur = adapter->mac_list;
-
- while (cur) {
- next = cur->next;
+ nx_mac_list_t *cur;
+ struct list_head *head = &adapter->mac_list;
+
+ while (!list_empty(head)) {
+ cur = list_entry(head->next, nx_mac_list_t, list);
+ nx_p3_sre_macaddr_change(adapter,
+ cur->mac_addr, NETXEN_MAC_DEL);
+ list_del(&cur->list);
kfree(cur);
- cur = next;
}
}
+int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+{
+ /* assuming caller has already copied new addr to netdev */
+ netxen_p3_nic_set_multi(adapter->netdev);
+ return 0;
+}
+
#define NETXEN_CONFIG_INTR_COALESCE 3
/*
@@ -752,7 +716,7 @@ int netxen_linkevent_request(struct netxen_adapter *adapter, int enable)
word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
req.req_hdr = cpu_to_le64(word);
- req.words[0] = cpu_to_le64(enable);
+ req.words[0] = cpu_to_le64(enable | (enable << 8));
rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0) {
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
index f20c96591a8..d4e83333978 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -42,8 +42,6 @@ struct netxen_adapter;
void netxen_nic_set_link_parameters(struct netxen_adapter *adapter);
-typedef u8 netxen_ethernet_macaddr_t[6];
-
/* Nibble or Byte mode for phy interface (GbE mode only) */
#define _netxen_crb_get_bit(var, bit) ((var >> bit) & 0x1)
@@ -395,14 +393,6 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
u32 mode);
-/* set the MAC address for a given MAC */
-int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
- netxen_ethernet_macaddr_t addr);
-
-/* XG version */
-int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
- netxen_ethernet_macaddr_t addr);
-
/* Generic enable for GbE ports. Will detect the speed of the link. */
int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port);
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index d18216779a0..4a51c31330d 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -319,13 +319,15 @@ err_out:
void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
{
+ adapter->macaddr_set = netxen_p2_nic_set_mac_addr;
+ adapter->set_multi = netxen_p2_nic_set_multi;
+
switch (adapter->ahw.port_type) {
case NETXEN_NIC_GBE:
adapter->enable_phy_interrupts =
netxen_niu_gbe_enable_phy_interrupts;
adapter->disable_phy_interrupts =
netxen_niu_gbe_disable_phy_interrupts;
- adapter->macaddr_set = netxen_niu_macaddr_set;
adapter->set_mtu = netxen_nic_set_mtu_gb;
adapter->set_promisc = netxen_niu_set_promiscuous_mode;
adapter->phy_read = netxen_niu_gbe_phy_read;
@@ -339,7 +341,6 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
netxen_niu_xgbe_enable_phy_interrupts;
adapter->disable_phy_interrupts =
netxen_niu_xgbe_disable_phy_interrupts;
- adapter->macaddr_set = netxen_niu_xg_macaddr_set;
adapter->set_mtu = netxen_nic_set_mtu_xgb;
adapter->init_port = netxen_niu_xg_init_port;
adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
@@ -353,6 +354,8 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
adapter->set_mtu = nx_fw_cmd_set_mtu;
adapter->set_promisc = netxen_p3_nic_set_promisc;
+ adapter->macaddr_set = netxen_p3_nic_set_mac_addr;
+ adapter->set_multi = netxen_p3_nic_set_multi;
}
}
@@ -1319,10 +1322,11 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
break;
}
- if (count) {
- tx_ring->sw_consumer = sw_consumer;
+ tx_ring->sw_consumer = sw_consumer;
+
+ if (count && netif_running(netdev)) {
smp_mb();
- if (netif_queue_stopped(netdev) && netif_running(netdev)) {
+ if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
netif_tx_lock(netdev);
netif_wake_queue(netdev);
smp_mb();
@@ -1450,7 +1454,6 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
rds_ring->producer = producer;
NXWR32(adapter, rds_ring->crb_rcv_producer,
(producer - 1) & (rds_ring->num_desc - 1));
- wmb();
}
spin_unlock(&rds_ring->lock);
}
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 5d79c19a6ec..83dadfd78c3 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -442,20 +442,38 @@ netxen_read_mac_addr(struct netxen_adapter *adapter)
if (!is_valid_ether_addr(netdev->perm_addr))
dev_warn(&pdev->dev, "Bad MAC address %pM.\n", netdev->dev_addr);
- else
- adapter->macaddr_set(adapter, netdev->dev_addr);
return 0;
}
+int netxen_nic_set_mac(struct net_device *netdev, void *p)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EINVAL;
+
+ if (netif_running(netdev)) {
+ netif_device_detach(netdev);
+ netxen_napi_disable(adapter);
+ }
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ adapter->macaddr_set(adapter, addr->sa_data);
+
+ if (netif_running(netdev)) {
+ netif_device_attach(netdev);
+ netxen_napi_enable(adapter);
+ }
+ return 0;
+}
+
static void netxen_set_multicast_list(struct net_device *dev)
{
struct netxen_adapter *adapter = netdev_priv(dev);
- if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
- netxen_p3_nic_set_multi(dev);
- else
- netxen_p2_nic_set_multi(dev);
+ adapter->set_multi(dev);
}
static const struct net_device_ops netxen_netdev_ops = {
@@ -782,16 +800,13 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
netxen_nic_driver_name, adapter->portnum);
return err;
}
- adapter->macaddr_set(adapter, netdev->dev_addr);
-
- netxen_nic_set_link_parameters(adapter);
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ adapter->macaddr_set(adapter, netdev->dev_addr);
- netxen_set_multicast_list(netdev);
- if (adapter->set_mtu)
- adapter->set_mtu(adapter, netdev->mtu);
+ adapter->set_multi(netdev);
+ adapter->set_mtu(adapter, netdev->mtu);
adapter->ahw.linkup = 0;
- mod_timer(&adapter->watchdog_timer, jiffies);
netxen_napi_enable(adapter);
@@ -800,6 +815,10 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)
netxen_linkevent_request(adapter, 1);
+ else
+ netxen_nic_set_link_parameters(adapter);
+
+ mod_timer(&adapter->watchdog_timer, jiffies);
return 0;
}
@@ -809,11 +828,15 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
{
netif_carrier_off(netdev);
netif_stop_queue(netdev);
+ smp_mb();
netxen_napi_disable(adapter);
if (adapter->stop_port)
adapter->stop_port(adapter);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_p3_free_mac_list(adapter);
+
netxen_release_tx_buffers(adapter);
FLUSH_SCHEDULED_WORK();
@@ -960,6 +983,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
rwlock_init(&adapter->adapter_lock);
spin_lock_init(&adapter->tx_clean_lock);
+ INIT_LIST_HEAD(&adapter->mac_list);
err = netxen_setup_pci_map(adapter);
if (err)
@@ -1113,9 +1137,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
netxen_nic_detach(adapter);
-
- if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
- netxen_p3_free_mac_list(adapter);
}
if (adapter->portnum == 0)
@@ -1340,7 +1361,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
producer = tx_ring->producer;
smp_mb();
consumer = tx_ring->sw_consumer;
- if ((no_of_desc+2) > find_diff_among(producer, consumer, num_txd)) {
+ if ((no_of_desc+2) >= find_diff_among(producer, consumer, num_txd)) {
netif_stop_queue(netdev);
smp_mb();
return NETDEV_TX_BUSY;
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 5e2698bf575..5941c79be72 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -402,76 +402,6 @@ int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
return 0;
}
-/*
- * Return the current station MAC address.
- * Note that the passed-in value must already be in network byte order.
- */
-static int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
- netxen_ethernet_macaddr_t * addr)
-{
- u32 stationhigh;
- u32 stationlow;
- int phy = adapter->physical_port;
- u8 val[8];
-
- if (addr == NULL)
- return -EINVAL;
- if ((phy < 0) || (phy > 3))
- return -EINVAL;
-
- stationhigh = NXRD32(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy));
- stationlow = NXRD32(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy));
- ((__le32 *)val)[1] = cpu_to_le32(stationhigh);
- ((__le32 *)val)[0] = cpu_to_le32(stationlow);
-
- memcpy(addr, val + 2, 6);
-
- return 0;
-}
-
-/*
- * Set the station MAC address.
- * Note that the passed-in value must already be in network byte order.
- */
-int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
- netxen_ethernet_macaddr_t addr)
-{
- u8 temp[4];
- u32 val;
- int phy = adapter->physical_port;
- unsigned char mac_addr[6];
- int i;
-
- if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
- return 0;
-
- for (i = 0; i < 10; i++) {
- temp[0] = temp[1] = 0;
- memcpy(temp + 2, addr, 2);
- val = le32_to_cpu(*(__le32 *)temp);
- if (NXWR32(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), val))
- return -EIO;
-
- memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
- val = le32_to_cpu(*(__le32 *)temp);
- if (NXWR32(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), val))
- return -2;
-
- netxen_niu_macaddr_get(adapter,
- (netxen_ethernet_macaddr_t *) mac_addr);
- if (memcmp(mac_addr, addr, 6) == 0)
- break;
- }
-
- if (i == 10) {
- printk(KERN_ERR "%s: cannot set Mac addr for %s\n",
- netxen_nic_driver_name, adapter->netdev->name);
- printk(KERN_ERR "MAC address set: %pM.\n", addr);
- printk(KERN_ERR "MAC address get: %pM.\n", mac_addr);
- }
- return 0;
-}
-
/* Disable a GbE interface */
int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
{
@@ -561,57 +491,6 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
return 0;
}
-/*
- * Set the MAC address for an XG port
- * Note that the passed-in value must already be in network byte order.
- */
-int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
- netxen_ethernet_macaddr_t addr)
-{
- int phy = adapter->physical_port;
- u8 temp[4];
- u32 val;
-
- if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
- return 0;
-
- if ((phy < 0) || (phy > NETXEN_NIU_MAX_XG_PORTS))
- return -EIO;
-
- temp[0] = temp[1] = 0;
- switch (phy) {
- case 0:
- memcpy(temp + 2, addr, 2);
- val = le32_to_cpu(*(__le32 *)temp);
- if (NXWR32(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1, val))
- return -EIO;
-
- memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
- val = le32_to_cpu(*(__le32 *)temp);
- if (NXWR32(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI, val))
- return -EIO;
- break;
-
- case 1:
- memcpy(temp + 2, addr, 2);
- val = le32_to_cpu(*(__le32 *)temp);
- if (NXWR32(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1, val))
- return -EIO;
-
- memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
- val = le32_to_cpu(*(__le32 *)temp);
- if (NXWR32(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI, val))
- return -EIO;
- break;
-
- default:
- printk(KERN_ERR "Unknown port %d\n", phy);
- break;
- }
-
- return 0;
-}
-
int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
u32 mode)
{
@@ -636,3 +515,36 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
return 0;
}
+
+int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+{
+ u32 mac_hi, mac_lo;
+ u32 reg_hi, reg_lo;
+
+ u8 phy = adapter->physical_port;
+ u8 phy_count = (adapter->ahw.port_type == NETXEN_NIC_XGBE) ?
+ NETXEN_NIU_MAX_XG_PORTS : NETXEN_NIU_MAX_GBE_PORTS;
+
+ if (phy >= phy_count)
+ return -EINVAL;
+
+ mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24);
+ mac_hi = addr[2] | ((u32)addr[3] << 8) |
+ ((u32)addr[4] << 16) | ((u32)addr[5] << 24);
+
+ if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
+ reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy);
+ reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy);
+ } else {
+ reg_lo = NETXEN_NIU_GB_STATION_ADDR_1(phy);
+ reg_hi = NETXEN_NIU_GB_STATION_ADDR_0(phy);
+ }
+
+ /* write twice to flush */
+ if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
+ return -EIO;
+ if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
+ return -EIO;
+
+ return 0;
+}
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 6f97b47d74a..1508b124e3d 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -49,8 +49,8 @@
#include <asm/processor.h>
#define DRV_NAME "r6040"
-#define DRV_VERSION "0.22"
-#define DRV_RELDATE "25Mar2009"
+#define DRV_VERSION "0.23"
+#define DRV_RELDATE "05May2009"
/* PHY CHIP Address */
#define PHY1_ADDR 1 /* For MAC1 */
@@ -742,6 +742,14 @@ static int r6040_up(struct net_device *dev)
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
int ret;
+ u16 val;
+
+ /* Check presence of a second PHY */
+ val = r6040_phy_read(ioaddr, lp->phy_addr, 2);
+ if (val == 0xFFFF) {
+ printk(KERN_ERR DRV_NAME " no second PHY attached\n");
+ return -EIO;
+ }
/* Initialise and alloc RX/TX buffers */
r6040_init_txbufs(dev);
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index 5113b26fc2d..3cff84078a9 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -1976,7 +1976,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
retval = -ENODEV;
goto out_0;
}
- res_size = res->end - res->start;
+ res_size = res->end - res->start + 1;
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq_res) {
@@ -2109,12 +2109,58 @@ out_0:
return retval;
}
+#ifdef CONFIG_PM
+/* This implementation assumes the devices remains powered on its VDDVARIO
+ * pins during suspend. */
+
+static int smsc911x_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct smsc911x_data *pdata = netdev_priv(dev);
+
+ /* enable wake on LAN, energy detection and the external PME
+ * signal. */
+ smsc911x_reg_write(pdata, PMT_CTRL,
+ PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ |
+ PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_);
+
+ return 0;
+}
+
+static int smsc911x_resume(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ unsigned int to = 100;
+
+ /* Note 3.11 from the datasheet:
+ * "When the LAN9220 is in a power saving state, a write of any
+ * data to the BYTE_TEST register will wake-up the device."
+ */
+ smsc911x_reg_write(pdata, BYTE_TEST, 0);
+
+ /* poll the READY bit in PMT_CTRL. Any other access to the device is
+ * forbidden while this bit isn't set. Try for 100ms and return -EIO
+ * if it failed. */
+ while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+ udelay(1000);
+
+ return (to == 0) ? -EIO : 0;
+}
+
+#else
+#define smsc911x_suspend NULL
+#define smsc911x_resume NULL
+#endif
+
static struct platform_driver smsc911x_driver = {
.probe = smsc911x_drv_probe,
.remove = smsc911x_drv_remove,
.driver = {
.name = SMSC_CHIPNAME,
},
+ .suspend = smsc911x_suspend,
+ .resume = smsc911x_resume,
};
/* Entry point for loading the module */
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index e00b5b1f674..3717569828b 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -180,6 +180,20 @@ config USB_NET_CDCETHER
IEEE 802 "local assignment" bit is set in the address, a "usbX"
name is used instead.
+config USB_NET_CDC_EEM
+ tristate "CDC EEM support"
+ depends on USB_USBNET && EXPERIMENTAL
+ help
+ This option supports devices conforming to the Communication Device
+ Class (CDC) Ethernet Emulation Model, a specification that's easy to
+ implement in device firmware. The CDC EEM specifications are available
+ from <http://www.usb.org/>.
+
+ This driver creates an interface named "ethX", where X depends on
+ what other networking devices you have in use. However, if the
+ IEEE 802 "local assignment" bit is set in the address, a "usbX"
+ name is used instead.
+
config USB_NET_DM9601
tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
depends on USB_USBNET
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
index f4402a06e52..b870b0b1cbe 100644
--- a/drivers/net/usb/Makefile
+++ b/drivers/net/usb/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_USB_RTL8150) += rtl8150.o
obj-$(CONFIG_USB_HSO) += hso.o
obj-$(CONFIG_USB_NET_AX8817X) += asix.o
obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
+obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o
obj-$(CONFIG_USB_NET_DM9601) += dm9601.o
obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o
obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c
new file mode 100644
index 00000000000..80e01778dd3
--- /dev/null
+++ b/drivers/net/usb/cdc_eem.c
@@ -0,0 +1,381 @@
+/*
+ * USB CDC EEM network interface driver
+ * Copyright (C) 2009 Oberthur Technologies
+ * by Omar Laazimani, Olivier Condemine
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ctype.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+
+
+/*
+ * This driver is an implementation of the CDC "Ethernet Emulation
+ * Model" (EEM) specification, which encapsulates Ethernet frames
+ * for transport over USB using a simpler USB device model than the
+ * previous CDC "Ethernet Control Model" (ECM, or "CDC Ethernet").
+ *
+ * For details, see www.usb.org/developers/devclass_docs/CDC_EEM10.pdf
+ *
+ * This version has been tested with GIGAntIC WuaoW SIM Smart Card on 2.6.24,
+ * 2.6.27 and 2.6.30rc2 kernel.
+ * It has also been validated on Openmoko Om 2008.12 (based on 2.6.24 kernel).
+ * build on 23-April-2009
+ */
+
+#define EEM_HEAD 2 /* 2 byte header */
+
+/*-------------------------------------------------------------------------*/
+
+static void eem_linkcmd_complete(struct urb *urb)
+{
+ dev_kfree_skb(urb->context);
+ usb_free_urb(urb);
+}
+
+static void eem_linkcmd(struct usbnet *dev, struct sk_buff *skb)
+{
+ struct urb *urb;
+ int status;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ goto fail;
+
+ usb_fill_bulk_urb(urb, dev->udev, dev->out,
+ skb->data, skb->len, eem_linkcmd_complete, skb);
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ usb_free_urb(urb);
+fail:
+ dev_kfree_skb(skb);
+ devwarn(dev, "link cmd failure\n");
+ return;
+ }
+}
+
+static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int status = 0;
+
+ status = usbnet_get_endpoints(dev, intf);
+ if (status < 0) {
+ usb_set_intfdata(intf, NULL);
+ usb_driver_release_interface(driver_of(intf), intf);
+ return status;
+ }
+
+ /* no jumbogram (16K) support for now */
+
+ dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+
+ return 0;
+}
+
+/*
+ * EEM permits packing multiple Ethernet frames into USB transfers
+ * (a "bundle"), but for TX we don't try to do that.
+ */
+static struct sk_buff *eem_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+ gfp_t flags)
+{
+ struct sk_buff *skb2 = NULL;
+ u16 len = skb->len;
+ u32 crc = 0;
+ int padlen = 0;
+
+ /* When ((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket) is
+ * zero, stick two bytes of zero length EEM packet on the end.
+ * Else the framework would add invalid single byte padding,
+ * since it can't know whether ZLPs will be handled right by
+ * all the relevant hardware and software.
+ */
+ if (!((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket))
+ padlen += 2;
+
+ if (!skb_cloned(skb)) {
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+
+ if ((tailroom >= ETH_FCS_LEN + padlen)
+ && (headroom >= EEM_HEAD))
+ goto done;
+
+ if ((headroom + tailroom)
+ > (EEM_HEAD + ETH_FCS_LEN + padlen)) {
+ skb->data = memmove(skb->head +
+ EEM_HEAD,
+ skb->data,
+ skb->len);
+ skb_set_tail_pointer(skb, len);
+ goto done;
+ }
+ }
+
+ skb2 = skb_copy_expand(skb, EEM_HEAD, ETH_FCS_LEN + padlen, flags);
+ if (!skb2)
+ return NULL;
+
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+
+done:
+ /* we don't use the "no Ethernet CRC" option */
+ crc = crc32_le(~0, skb->data, skb->len);
+ crc = ~crc;
+
+ put_unaligned_le32(crc, skb_put(skb, 4));
+
+ /* EEM packet header format:
+ * b0..13: length of ethernet frame
+ * b14: bmCRC (1 == valid Ethernet CRC)
+ * b15: bmType (0 == data)
+ */
+ len = skb->len;
+ put_unaligned_le16(BIT(14) | len, skb_push(skb, 2));
+
+ /* Bundle a zero length EEM packet if needed */
+ if (padlen)
+ put_unaligned_le16(0, skb_put(skb, 2));
+
+ return skb;
+}
+
+static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ /*
+ * Our task here is to strip off framing, leaving skb with one
+ * data frame for the usbnet framework code to process. But we
+ * may have received multiple EEM payloads, or command payloads.
+ * So we must process _everything_ as if it's a header, except
+ * maybe the last data payload
+ *
+ * REVISIT the framework needs updating so that when we consume
+ * all payloads (the last or only message was a command, or a
+ * zero length EEM packet) that is not accounted as an rx_error.
+ */
+ do {
+ struct sk_buff *skb2 = NULL;
+ u16 header;
+ u16 len = 0;
+
+ /* incomplete EEM header? */
+ if (skb->len < EEM_HEAD)
+ return 0;
+
+ /*
+ * EEM packet header format:
+ * b0..14: EEM type dependant (Data or Command)
+ * b15: bmType
+ */
+ header = get_unaligned_le16(skb->data);
+ skb_pull(skb, EEM_HEAD);
+
+ /*
+ * The bmType bit helps to denote when EEM
+ * packet is data or command :
+ * bmType = 0 : EEM data payload
+ * bmType = 1 : EEM (link) command
+ */
+ if (header & BIT(15)) {
+ u16 bmEEMCmd;
+
+ /*
+ * EEM (link) command packet:
+ * b0..10: bmEEMCmdParam
+ * b11..13: bmEEMCmd
+ * b14: bmReserved (must be 0)
+ * b15: 1 (EEM command)
+ */
+ if (header & BIT(14)) {
+ devdbg(dev, "reserved command %04x\n", header);
+ continue;
+ }
+
+ bmEEMCmd = (header >> 11) & 0x7;
+ switch (bmEEMCmd) {
+
+ /* Responding to echo requests is mandatory. */
+ case 0: /* Echo command */
+ len = header & 0x7FF;
+
+ /* bogus command? */
+ if (skb->len < len)
+ return 0;
+
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (unlikely(!skb2))
+ goto next;
+ skb_trim(skb2, len);
+ put_unaligned_le16(BIT(15) | (1 << 11) | len,
+ skb_push(skb2, 2));
+ eem_linkcmd(dev, skb2);
+ break;
+
+ /*
+ * Host may choose to ignore hints.
+ * - suspend: peripheral ready to suspend
+ * - response: suggest N millisec polling
+ * - response complete: suggest N sec polling
+ */
+ case 2: /* Suspend hint */
+ case 3: /* Response hint */
+ case 4: /* Response complete hint */
+ continue;
+
+ /*
+ * Hosts should never receive host-to-peripheral
+ * or reserved command codes; or responses to an
+ * echo command we didn't send.
+ */
+ case 1: /* Echo response */
+ case 5: /* Tickle */
+ default: /* reserved */
+ devwarn(dev, "unexpected link command %d\n",
+ bmEEMCmd);
+ continue;
+ }
+
+ } else {
+ u32 crc, crc2;
+ int is_last;
+
+ /* zero length EEM packet? */
+ if (header == 0)
+ continue;
+
+ /*
+ * EEM data packet header :
+ * b0..13: length of ethernet frame
+ * b14: bmCRC
+ * b15: 0 (EEM data)
+ */
+ len = header & 0x3FFF;
+
+ /* bogus EEM payload? */
+ if (skb->len < len)
+ return 0;
+
+ /* bogus ethernet frame? */
+ if (len < (ETH_HLEN + ETH_FCS_LEN))
+ goto next;
+
+ /*
+ * Treat the last payload differently: framework
+ * code expects our "fixup" to have stripped off
+ * headers, so "skb" is a data packet (or error).
+ * Else if it's not the last payload, keep "skb"
+ * for further processing.
+ */
+ is_last = (len == skb->len);
+ if (is_last)
+ skb2 = skb;
+ else {
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (unlikely(!skb2))
+ return 0;
+ }
+
+ crc = get_unaligned_le32(skb2->data
+ + len - ETH_FCS_LEN);
+ skb_trim(skb2, len - ETH_FCS_LEN);
+
+ /*
+ * The bmCRC helps to denote when the CRC field in
+ * the Ethernet frame contains a calculated CRC:
+ * bmCRC = 1 : CRC is calculated
+ * bmCRC = 0 : CRC = 0xDEADBEEF
+ */
+ if (header & BIT(14))
+ crc2 = ~crc32_le(~0, skb2->data, len);
+ else
+ crc2 = 0xdeadbeef;
+
+ if (is_last)
+ return crc == crc2;
+
+ if (unlikely(crc != crc2)) {
+ dev->stats.rx_errors++;
+ dev_kfree_skb_any(skb2);
+ } else
+ usbnet_skb_return(dev, skb2);
+ }
+
+next:
+ skb_pull(skb, len);
+ } while (skb->len);
+
+ return 1;
+}
+
+static const struct driver_info eem_info = {
+ .description = "CDC EEM Device",
+ .flags = FLAG_ETHER,
+ .bind = eem_bind,
+ .rx_fixup = eem_rx_fixup,
+ .tx_fixup = eem_tx_fixup,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static const struct usb_device_id products[] = {
+{
+ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_EEM,
+ USB_CDC_PROTO_EEM),
+ .driver_info = (unsigned long) &eem_info,
+},
+{
+ /* EMPTY == end of list */
+},
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver eem_driver = {
+ .name = "cdc_eem",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+
+static int __init eem_init(void)
+{
+ return usb_register(&eem_driver);
+}
+module_init(eem_init);
+
+static void __exit eem_exit(void)
+{
+ usb_deregister(&eem_driver);
+}
+module_exit(eem_exit);
+
+MODULE_AUTHOR("Omar Laazimani <omar.oberthur@gmail.com>");
+MODULE_DESCRIPTION("USB CDC EEM");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 28dd225269a..0eb939c40ac 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -719,6 +719,14 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
{
unsigned long flags;
int ret = 0;
+ __le16 key_flags = 0;
+
+ key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+ key_flags &= ~STA_KEY_FLG_INVALID;
+
+ if (sta_id == priv->hw_params.bcast_sta_id)
+ key_flags |= STA_KEY_MULTICAST_MSK;
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
@@ -738,6 +746,9 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
"no space for a new key");
+ priv->stations[sta_id].sta.key.key_flags = key_flags;
+
+
/* This copy is acutally not needed: we get the key with each TX */
memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
@@ -754,9 +765,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
{
u8 sta_id = IWL_INVALID_STATION;
unsigned long flags;
- __le16 key_flags = 0;
int i;
- DECLARE_MAC_BUF(mac);
sta_id = priv->cfg->ops->smgmt->find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
@@ -771,16 +780,8 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
return;
}
- key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
- key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- key_flags &= ~STA_KEY_FLG_INVALID;
-
- if (sta_id == priv->hw_params.bcast_sta_id)
- key_flags |= STA_KEY_MULTICAST_MSK;
-
spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.key.key_flags = key_flags;
priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
for (i = 0; i < 5; i++)
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 9f5191a84a1..f6c1489a0c4 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1460,7 +1460,6 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
rxq->bd = NULL;
rxq->rb_stts = NULL;
}
-EXPORT_SYMBOL(iwl3945_rx_queue_free);
/* Convert linear signal-to-noise ratio into dB */
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 0254741bece..c01c1196d45 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2460,6 +2460,8 @@ static void __devinit quirk_i82576_sriov(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov);
#endif /* CONFIG_PCI_IOV */