From e484c16f6212f7f06407382efa4d3ad214b6c589 Mon Sep 17 00:00:00 2001 From: Martin Decky Date: Thu, 10 Sep 2009 03:44:47 +0200 Subject: hostap: Revert a toxic part of the conversion to net_device_ops As the hostap driver was converted to use net_device_ops, a mistake was made in hostap_main.c (commit 5ae4efbcd2611562a8b93596be034e63495706a5). Originally, the tx_queue_len was set to 0 for every other interface than HOSTAP_INTERFACE_MASTER, but the new fragment of code sets tx_queue_len to 0 only for HOSTAP_INTERFACE_MASTER. The opposite of the previous behavior makes the driver to drop all packets in AP mode. Change the way 0 is assigned to tx_queue_len according to the original logic. Signed-off-by: Martin Decky Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 6fe122f18c0..eb57d1ea361 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -875,15 +875,16 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local, switch(type) { case HOSTAP_INTERFACE_AP: + dev->tx_queue_len = 0; /* use main radio device queue */ dev->netdev_ops = &hostap_mgmt_netdev_ops; dev->type = ARPHRD_IEEE80211; dev->header_ops = &hostap_80211_ops; break; case HOSTAP_INTERFACE_MASTER: - dev->tx_queue_len = 0; /* use main radio device queue */ dev->netdev_ops = &hostap_master_ops; break; default: + dev->tx_queue_len = 0; /* use main radio device queue */ dev->netdev_ops = &hostap_netdev_ops; } -- cgit v1.2.3 From 32f6afd82c1c4e9415db9f8d18e3fd6fc65cfd46 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 10 Sep 2009 20:31:46 +0200 Subject: b43: Force-wake queues on init Force wake the mac80211 queues on init. Under rare circumstances they may be stopped, if a DMA error or something else causes a device reset while a queue was stopped. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7a9a3fa5542..78e9834d4c1 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4287,6 +4287,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev) if (!dev->suspend_in_progress) b43_rng_init(wl); + ieee80211_wake_queues(dev->wl->hw); + b43_set_status(dev, B43_STAT_INITIALIZED); if (!dev->suspend_in_progress) -- cgit v1.2.3 From d37b7da39dbac8197e41a5f9c8162730f6b36d8b Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 11 Sep 2009 08:30:03 +0530 Subject: ath9k: Fix bug in ANI channel handling When processing MIB interrupts, OFDM and CCK error handling routines for low RSSI values have to be invoked only when the channel mode is 11G/11B. Since HT channels will also fall under the bands 2Ghz/5Ghz, check appropriately. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index a7cbb07988c..2b493742ef1 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -327,7 +327,8 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) aniState->firstepLevel + 1); return; } else { - if (conf->channel->band == IEEE80211_BAND_2GHZ) { + if ((conf->channel->band == IEEE80211_BAND_2GHZ) && + !conf_is_ht(conf)) { if (!aniState->ofdmWeakSigDetectOff) ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, @@ -369,7 +370,8 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1); } else { - if (conf->channel->band == IEEE80211_BAND_2GHZ) { + if ((conf->channel->band == IEEE80211_BAND_2GHZ) && + !conf_is_ht(conf)) { if (aniState->firstepLevel > 0) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0); -- cgit v1.2.3 From ff4d572a186c1276ea2118e405528432eb1f747c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 11 Sep 2009 04:43:29 -0400 Subject: wireless: default CONFIG_WLAN to y When this was added no defaults were set and it seems this implies n. Default this to y. Reported-by: Jouni Malinen Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index ad89d23968d..49ea9c92b7e 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -5,6 +5,7 @@ menuconfig WLAN bool "Wireless LAN" depends on !S390 + default y ---help--- This section contains all the pre 802.11 and 802.11 wireless device drivers. For a complete list of drivers and documentation -- cgit v1.2.3 From e175e99646f21602d844ce85a727c83ba644ab87 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 11 Sep 2009 18:31:32 +0200 Subject: b43: Fix resume failure This fixes a resume failure where a signal is pending on resume so the firmware upload fails. This removes the interruptible sleep, because we don't really need it. In the worst case (with broken firmware) the sleep loop will take 1 second. In the common case (working firmware), it will only take a few milliseconds. So we don't really need to be interruptible. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 78e9834d4c1..e789792a36b 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2289,11 +2289,7 @@ static int b43_upload_microcode(struct b43_wldev *dev) err = -ENODEV; goto error; } - msleep_interruptible(50); - if (signal_pending(current)) { - err = -EINTR; - goto error; - } + msleep(50); } b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); /* dummy read */ -- cgit v1.2.3 From 392a0baf31b39b50cc6bf6d4400d542641d466c4 Mon Sep 17 00:00:00 2001 From: Daniel C Halperin Date: Fri, 11 Sep 2009 10:38:08 -0700 Subject: iwlwifi: fix HT operation in 2.4 GHz band When we cleaned up the driver to properly tell mac80211 about HT rates ("iwlwifi: use iwl_hwrate_get_mac80211_idx where appropriate"), we broke internal rate indexing in 2.4 GHz band. Signed-off-by: Daniel C Halperin Tested-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 40b207aa8fe..fd731534df1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -883,6 +883,12 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, mac_index &= RATE_MCS_CODE_MSK; /* Remove # of streams */ if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE)) mac_index++; + /* + * mac80211 HT index is always zero-indexed; we need to move + * HT OFDM rates after CCK rates in 2.4 GHz band + */ + if (priv->band == IEEE80211_BAND_2GHZ) + mac_index += IWL_FIRST_OFDM_RATE; } if ((mac_index < 0) || -- cgit v1.2.3 From 0aae511c0bf9e49165cfa04c51f6a3bf179aef09 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 11 Sep 2009 10:38:12 -0700 Subject: iwlwifi: fix potential rx buffer loss RX handling maintains a few lists that keep track of the RX buffers. Buffers move from one list to the other as they are used, replenished, and again made available for usage. In one such instance, when a buffer is used it enters the "rx_used" list. When buffers are replenished an skb is attached to the buffer and it is moved to the "rx_free" list. The problem here is that the buffer is first removed from the "rx_used" list _before_ the skb is allocated. Thus, if the skb allocation fails this buffer remains removed from the "rx_used" list and is thus lost for future usage. Fix this by first allocating the skb before trying to attach it to a list. We add an additional check to not do this unnecessarily. Reported-by: Rick Farrington Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-rx.c | 24 +++++++++++++++++------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 24 ++++++++++++++++-------- 2 files changed, 33 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 8150c5c3a16..b90adcb73b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -239,26 +239,22 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; + struct sk_buff *skb; unsigned long flags; while (1) { spin_lock_irqsave(&rxq->lock, flags); - if (list_empty(&rxq->rx_used)) { spin_unlock_irqrestore(&rxq->lock, flags); return; } - element = rxq->rx_used.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); - spin_unlock_irqrestore(&rxq->lock, flags); /* Alloc a new receive buffer */ - rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256, + skb = alloc_skb(priv->hw_params.rx_buf_size + 256, priority); - if (!rxb->skb) { + if (!skb) { IWL_CRIT(priv, "Can not allocate SKB buffers\n"); /* We don't reschedule replenish work here -- we will * call the restock method and if it still needs @@ -266,6 +262,20 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) break; } + spin_lock_irqsave(&rxq->lock, flags); + + if (list_empty(&rxq->rx_used)) { + spin_unlock_irqrestore(&rxq->lock, flags); + dev_kfree_skb_any(skb); + return; + } + element = rxq->rx_used.next; + rxb = list_entry(element, struct iwl_rx_mem_buffer, list); + list_del(element); + + spin_unlock_irqrestore(&rxq->lock, flags); + + rxb->skb = skb; /* Get physical address of RB/SKB */ rxb->real_dma_addr = pci_map_single( priv->pci_dev, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 2238c9f2018..090966837f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1134,6 +1134,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; + struct sk_buff *skb; unsigned long flags; while (1) { @@ -1143,17 +1144,11 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) spin_unlock_irqrestore(&rxq->lock, flags); return; } - - element = rxq->rx_used.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); spin_unlock_irqrestore(&rxq->lock, flags); /* Alloc a new receive buffer */ - rxb->skb = - alloc_skb(priv->hw_params.rx_buf_size, - priority); - if (!rxb->skb) { + skb = alloc_skb(priv->hw_params.rx_buf_size, priority); + if (!skb) { if (net_ratelimit()) IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); /* We don't reschedule replenish work here -- we will @@ -1162,6 +1157,19 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) break; } + spin_lock_irqsave(&rxq->lock, flags); + if (list_empty(&rxq->rx_used)) { + spin_unlock_irqrestore(&rxq->lock, flags); + dev_kfree_skb_any(skb); + return; + } + element = rxq->rx_used.next; + rxb = list_entry(element, struct iwl_rx_mem_buffer, list); + list_del(element); + spin_unlock_irqrestore(&rxq->lock, flags); + + rxb->skb = skb; + /* If radiotap head is required, reserve some headroom here. * The physical head count is a variable rx_stats->phy_count. * We reserve 4 bytes here. Plus these extra bytes, the -- cgit v1.2.3 From 2ff6578ba2ac38c0082c1e56babd5f575029faf8 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 11 Sep 2009 10:38:18 -0700 Subject: iwlwifi: find the correct first antenna We can not assume antenna "A" is the first valid anttena for all the NIC. Need to make sure choice the correct antenna based on h/w configuration for transmit to avoid sending frame on invalid antenna Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index fd731534df1..346dc06fa7b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -760,6 +760,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, u16 high_low; u8 switch_to_legacy = 0; u8 is_green = lq_sta->is_green; + struct iwl_priv *priv = lq_sta->drv; /* check if we need to switch from HT to legacy rates. * assumption is that mandatory rates (1Mbps or 6Mbps) @@ -773,7 +774,8 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, tbl->lq_type = LQ_G; if (num_of_ant(tbl->ant_type) > 1) - tbl->ant_type = ANT_A;/*FIXME:RS*/ + tbl->ant_type = + first_antenna(priv->hw_params.valid_tx_ant); tbl->is_ht40 = 0; tbl->is_SGI = 0; -- cgit v1.2.3 From 559a4741b8a5b4551b8c7e8e0de7f3e41a79bb5a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Sep 2009 10:50:37 -0700 Subject: iwlwifi: disable powersave for 4965 There's a bug in 4965 powersave that appears to be related to the way it keeps track of its data during sleep, but we haven't found it yet. Due to that, using powersave may spontaneously cause the device to SYSASSERT when transitioning from sleep to wake. Therefore, disable powersave for 4965, until (if ever, unfortunately) we can identify and fix the problem. Cf. http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=1982 which was closed, but now has re-appeared with IDLE mode, which probably means we never really fixed it. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 9 ++++++--- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-power.c | 5 +++-- 4 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6a13bfbc9d9..ca61d3796ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2346,6 +2346,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .mod_params = &iwl4965_mod_params, .use_isr_legacy = true, .ht_greenfield_support = false, + .broken_powersave = true, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index acfd7b40afb..fd26c0dc9c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1585,9 +1585,12 @@ int iwl_setup_mac(struct iwl_priv *priv) hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + IEEE80211_HW_SPECTRUM_MGMT; + + if (!priv->cfg->broken_powersave) + hw->flags |= IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index c04d2a27081..7ff9ffb2b70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -252,6 +252,7 @@ struct iwl_cfg { const u16 max_ll_items; const bool shadow_ram_support; const bool ht_greenfield_support; + const bool broken_powersave; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 4ec6a8307cc..60be976afff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -292,8 +292,9 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) else dtimper = 1; - /* TT power setting overwrites everything */ - if (tt->state >= IWL_TI_1) + if (priv->cfg->broken_powersave) + iwl_power_sleep_cam_cmd(priv, &cmd); + else if (tt->state >= IWL_TI_1) iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); else if (!enabled) iwl_power_sleep_cam_cmd(priv, &cmd); -- cgit v1.2.3 From e4c57d0f964cdbe278ed6b3bf632138fe575267e Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 14 Sep 2009 08:03:42 +0000 Subject: netdev: smc91x: drop Blackfin cruft Now that all Blackfin boards are using the board resources, we don't need to keep the arch/board specific crap in the driver header. Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Signed-off-by: David S. Miller --- drivers/net/smc91x.h | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 57a159fac99..9c8c6ed4a3c 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -83,34 +83,6 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg) } } -#elif defined(CONFIG_BLACKFIN) - -#define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH -#define RPC_LSA_DEFAULT RPC_LED_100_10 -#define RPC_LSB_DEFAULT RPC_LED_TX_RX - -#define SMC_CAN_USE_8BIT 0 -#define SMC_CAN_USE_16BIT 1 -# if defined(CONFIG_BF561) -#define SMC_CAN_USE_32BIT 1 -# else -#define SMC_CAN_USE_32BIT 0 -# endif -#define SMC_IO_SHIFT 0 -#define SMC_NOWAIT 1 -#define SMC_USE_BFIN_DMA 0 - -#define SMC_inw(a, r) readw((a) + (r)) -#define SMC_outw(v, a, r) writew(v, (a) + (r)) -#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) -#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) -# if SMC_CAN_USE_32BIT -#define SMC_inl(a, r) readl((a) + (r)) -#define SMC_outl(v, a, r) writel(v, (a) + (r)) -#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) -#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) -# endif - #elif defined(CONFIG_REDWOOD_5) || defined(CONFIG_REDWOOD_6) /* We can only do 16-bit reads and writes in the static memory space. */ -- cgit v1.2.3 From 5708e868dc512f055f0ea4a14d01f8252c3ca8a1 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 14 Sep 2009 12:23:23 +0000 Subject: net: constify remaining proto_ops Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/pppol2tp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index e0f9219a0ae..cc394d07375 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -229,7 +229,7 @@ static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel); static atomic_t pppol2tp_tunnel_count; static atomic_t pppol2tp_session_count; static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL }; -static struct proto_ops pppol2tp_ops; +static const struct proto_ops pppol2tp_ops; /* per-net private data for this module */ static int pppol2tp_net_id; @@ -2574,7 +2574,7 @@ static const struct file_operations pppol2tp_proc_fops = { * Init and cleanup *****************************************************************************/ -static struct proto_ops pppol2tp_ops = { +static const struct proto_ops pppol2tp_ops = { .family = AF_PPPOX, .owner = THIS_MODULE, .release = pppol2tp_release, -- cgit v1.2.3 From ce187619e8f39abd60a8d99eeb2c52b4c00adc13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Mon, 14 Sep 2009 03:10:28 +0000 Subject: cdc-phonet: remove noisy debug statement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Rémi Denis-Courmont Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- drivers/net/usb/cdc-phonet.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 97e54d9d03c..33d5c579c5a 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -264,7 +264,6 @@ static int usbpn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) switch (cmd) { case SIOCPNGAUTOCONF: req->ifr_phonet_autoconf.device = PN_DEV_PC; - printk(KERN_CRIT"device is PN_DEV_PC\n"); return 0; } return -ENOIOCTLCMD; -- cgit v1.2.3 From 1b3ff02eac6dcb6d7d03a5be6a642b58ec9cf4bb Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Mon, 14 Sep 2009 07:47:27 +0000 Subject: ixgbe: Properly disable packet split per-ring when globally disabled The packet split feature was recently moved out of the adapter-wide flags feature field and into a per-Rx ring feature field. In the process, packet split isn't properly disabled in the Rx ring if the adapter has it globally disabled, followed by a device reset. This won't impact the driver today, since it's always in packet split mode. However, this will prevent any pitfalls if someone disables packet split on the adapter in the future and doesn't disable it in each ring. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: Don Skidmore Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 45bf8b9716e..b47aaa88133 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2055,6 +2055,8 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) rx_ring->flags |= IXGBE_RING_RX_PS_ENABLED; + else + rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED; #ifdef IXGBE_FCOE if (netdev->features & NETIF_F_FCOE_MTU) { -- cgit v1.2.3 From 8911184fed68d2cdde1a8a920813e07a6d4f997f Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Mon, 14 Sep 2009 07:47:49 +0000 Subject: ixgbe: Add support for 82599-based CX4 adapters This patch adds support for CX4 adapters based on 82599. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: Don Skidmore Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82599.c | 3 +++ drivers/net/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ixgbe/ixgbe_type.h | 1 + 3 files changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 61af47e75aa..c9006bbd2ed 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -337,6 +337,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82599_SFP: media_type = ixgbe_media_type_fiber; break; + case IXGBE_DEV_ID_82599_CX4: + media_type = ixgbe_media_type_fiber; + break; default: media_type = ixgbe_media_type_unknown; break; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b47aaa88133..59ad9590e70 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -97,6 +97,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4), + board_82599 }, /* required last entry */ {0, } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 8ba90eec1dc..37303a15e6d 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -49,6 +49,7 @@ #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1 #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 #define IXGBE_DEV_ID_82599_KX4 0x10F7 +#define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC -- cgit v1.2.3 From 6b1be1990d2f7d1a3b1f25bf3e6444600665764a Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Mon, 14 Sep 2009 07:48:10 +0000 Subject: ixgbe: Create separate media type for CX4 adapters Currently the media type detection for CX4 adapters lumps them into a type of fiber. This causes some strange fallout when firmware verification is done on the NIC, and certain fiber NIC rules get enforced incorrectly. This patch introduces a new media type for CX4, and puts both 82598 and 82599 CX4 adapters into this bucket. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: Don Skidmore Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 6 ++++-- drivers/net/ixgbe/ixgbe_82599.c | 2 +- drivers/net/ixgbe/ixgbe_type.h | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index cb7f0c3c6e1..56b12f3192f 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -322,14 +322,16 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) break; case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: - case IXGBE_DEV_ID_82598EB_CX4: - case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: case IXGBE_DEV_ID_82598_DA_DUAL_PORT: case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: case IXGBE_DEV_ID_82598EB_XF_LR: case IXGBE_DEV_ID_82598EB_SFP_LOM: media_type = ixgbe_media_type_fiber; break; + case IXGBE_DEV_ID_82598EB_CX4: + case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: + media_type = ixgbe_media_type_cx4; + break; case IXGBE_DEV_ID_82598AT: case IXGBE_DEV_ID_82598AT2: media_type = ixgbe_media_type_copper; diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index c9006bbd2ed..2ec58dcdb82 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -338,7 +338,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82599_CX4: - media_type = ixgbe_media_type_fiber; + media_type = ixgbe_media_type_cx4; break; default: media_type = ixgbe_media_type_unknown; diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 37303a15e6d..8761d7899f7 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -2144,6 +2144,7 @@ enum ixgbe_media_type { ixgbe_media_type_fiber, ixgbe_media_type_copper, ixgbe_media_type_backplane, + ixgbe_media_type_cx4, ixgbe_media_type_virtual }; -- cgit v1.2.3 From 2fb02a26bda1cbc3553164a8358c303d936255c5 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 14 Sep 2009 08:22:54 +0000 Subject: igb: reset sgmii phy at start of init Our SGMII phy code was incomplete in that it was not actually placing the phy in SGMII mode and as a result the PHY was not able to establish a link when connected to a non serdes link partner. This patch updates the code to combine the SGMII/serdes PCS init and to add the necessary reset. Signed-off-by: Alexander Duyck Signed-off-by: Don Skidmore Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 198 +++++++++++++++++++--------------------- drivers/net/igb/e1000_82575.h | 2 +- drivers/net/igb/e1000_defines.h | 2 +- drivers/net/igb/igb_main.c | 2 +- 4 files changed, 95 insertions(+), 109 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 6158c0f3b20..f8f5772557c 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -49,11 +49,10 @@ static s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16 *); static s32 igb_reset_hw_82575(struct e1000_hw *); static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *, bool); static s32 igb_setup_copper_link_82575(struct e1000_hw *); -static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *); +static s32 igb_setup_serdes_link_82575(struct e1000_hw *); static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16); static void igb_clear_hw_cntrs_82575(struct e1000_hw *); static s32 igb_acquire_swfw_sync_82575(struct e1000_hw *, u16); -static void igb_configure_pcs_link_82575(struct e1000_hw *); static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *, u16 *, u16 *); static s32 igb_get_phy_id_82575(struct e1000_hw *); @@ -105,16 +104,20 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) dev_spec->sgmii_active = false; ctrl_ext = rd32(E1000_CTRL_EXT); - if ((ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) == - E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES) { - hw->phy.media_type = e1000_media_type_internal_serdes; - ctrl_ext |= E1000_CTRL_I2C_ENA; - } else if (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII) { + switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { + case E1000_CTRL_EXT_LINK_MODE_SGMII: dev_spec->sgmii_active = true; ctrl_ext |= E1000_CTRL_I2C_ENA; - } else { + break; + case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: + hw->phy.media_type = e1000_media_type_internal_serdes; + ctrl_ext |= E1000_CTRL_I2C_ENA; + break; + default: ctrl_ext &= ~E1000_CTRL_I2C_ENA; + break; } + wr32(E1000_CTRL_EXT, ctrl_ext); /* Set mta register count */ @@ -134,7 +137,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) ? igb_setup_copper_link_82575 - : igb_setup_fiber_serdes_link_82575; + : igb_setup_serdes_link_82575; /* NVM initialization */ eecd = rd32(E1000_EECD); @@ -379,6 +382,7 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) struct e1000_phy_info *phy = &hw->phy; s32 ret_val = 0; u16 phy_id; + u32 ctrl_ext; /* * For SGMII PHYs, we try the list of possible addresses until @@ -393,6 +397,12 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) goto out; } + /* Power on sgmii phy if it is disabled */ + ctrl_ext = rd32(E1000_CTRL_EXT); + wr32(E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); + wrfl(); + msleep(300); + /* * The address field in the I2CCMD register is 3 bits and 0 is invalid. * Therefore, we need to test 1-7 @@ -418,9 +428,12 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) phy->addr = 0; ret_val = -E1000_ERR_PHY; goto out; + } else { + ret_val = igb_get_phy_id(hw); } - ret_val = igb_get_phy_id(hw); + /* restore previous sfp cage power state */ + wr32(E1000_CTRL_EXT, ctrl_ext); out: return ret_val; @@ -766,17 +779,18 @@ static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, } /** - * igb_shutdown_fiber_serdes_link_82575 - Remove link during power down + * igb_shutdown_serdes_link_82575 - Remove link during power down * @hw: pointer to the HW structure * * In the case of fiber serdes, shut down optics and PCS on driver unload * when management pass thru is not enabled. **/ -void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw) +void igb_shutdown_serdes_link_82575(struct e1000_hw *hw) { u32 reg; - if (hw->phy.media_type != e1000_media_type_internal_serdes) + if (hw->phy.media_type != e1000_media_type_internal_serdes || + igb_sgmii_active_82575(hw)) return; /* if the management interface is not enabled, then power down */ @@ -788,7 +802,7 @@ void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw) /* shutdown the laser */ reg = rd32(E1000_CTRL_EXT); - reg |= E1000_CTRL_EXT_SDP7_DATA; + reg |= E1000_CTRL_EXT_SDP3_DATA; wr32(E1000_CTRL_EXT, reg); /* flush the write to verify completion */ @@ -927,6 +941,17 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); wr32(E1000_CTRL, ctrl); + ret_val = igb_setup_serdes_link_82575(hw); + if (ret_val) + goto out; + + if (igb_sgmii_active_82575(hw) && !hw->phy.reset_disable) { + ret_val = hw->phy.ops.reset(hw); + if (ret_val) { + hw_dbg("Error resetting the PHY.\n"); + goto out; + } + } switch (hw->phy.type) { case e1000_phy_m88: ret_val = igb_copper_link_setup_m88(hw); @@ -963,8 +988,6 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) } } - igb_configure_pcs_link_82575(hw); - /* * Check link status. Wait up to 100 microseconds for link to become * valid. @@ -987,14 +1010,18 @@ out: } /** - * igb_setup_fiber_serdes_link_82575 - Setup link for fiber/serdes + * igb_setup_serdes_link_82575 - Setup link for fiber/serdes * @hw: pointer to the HW structure * * Configures speed and duplex for fiber and serdes links. **/ -static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw) +static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw) { - u32 reg; + u32 ctrl_reg, reg; + + if ((hw->phy.media_type != e1000_media_type_internal_serdes) && + !igb_sgmii_active_82575(hw)) + return 0; /* * On the 82575, SerDes loopback mode persists until it is @@ -1004,26 +1031,38 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw) */ wr32(E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); - /* Force link up, set 1gb, set both sw defined pins */ - reg = rd32(E1000_CTRL); - reg |= E1000_CTRL_SLU | - E1000_CTRL_SPD_1000 | - E1000_CTRL_FRCSPD | - E1000_CTRL_SWDPIN0 | - E1000_CTRL_SWDPIN1; - wr32(E1000_CTRL, reg); - - /* Power on phy for 82576 fiber adapters */ - if (hw->mac.type == e1000_82576) { - reg = rd32(E1000_CTRL_EXT); - reg &= ~E1000_CTRL_EXT_SDP7_DATA; - wr32(E1000_CTRL_EXT, reg); + /* power on the sfp cage if present */ + reg = rd32(E1000_CTRL_EXT); + reg &= ~E1000_CTRL_EXT_SDP3_DATA; + wr32(E1000_CTRL_EXT, reg); + + ctrl_reg = rd32(E1000_CTRL); + ctrl_reg |= E1000_CTRL_SLU; + + if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) { + /* set both sw defined pins */ + ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; + + /* Set switch control to serdes energy detect */ + reg = rd32(E1000_CONNSW); + reg |= E1000_CONNSW_ENRGSRC; + wr32(E1000_CONNSW, reg); + } + + reg = rd32(E1000_PCS_LCTL); + + if (igb_sgmii_active_82575(hw)) { + /* allow time for SFP cage to power up phy */ + msleep(300); + + /* AN time out should be disabled for SGMII mode */ + reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); + } else { + ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | + E1000_CTRL_FD | E1000_CTRL_FRCDPX; } - /* Set switch control to serdes energy detect */ - reg = rd32(E1000_CONNSW); - reg |= E1000_CONNSW_ENRGSRC; - wr32(E1000_CONNSW, reg); + wr32(E1000_CTRL, ctrl_reg); /* * New SerDes mode allows for forcing speed or autonegotiating speed @@ -1031,12 +1070,21 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw) * mode that will be compatible with older link partners and switches. * However, both are supported by the hardware and some drivers/tools. */ - reg = rd32(E1000_PCS_LCTL); reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); - if (hw->mac.autoneg) { + /* + * We force flow control to prevent the CTRL register values from being + * overwritten by the autonegotiated flow control values + */ + reg |= E1000_PCS_LCTL_FORCE_FCTRL; + + /* + * we always set sgmii to autoneg since it is the phy that will be + * forcing the link and the serdes is just a go-between + */ + if (hw->mac.autoneg || igb_sgmii_active_82575(hw)) { /* Set PCS register for autoneg */ reg |= E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ E1000_PCS_LCTL_FDV_FULL | /* SerDes Full duplex */ @@ -1053,75 +1101,12 @@ static s32 igb_setup_fiber_serdes_link_82575(struct e1000_hw *hw) hw_dbg("Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg); } - if (hw->mac.type == e1000_82576) { - reg |= E1000_PCS_LCTL_FORCE_FCTRL; - igb_force_mac_fc(hw); - } - wr32(E1000_PCS_LCTL, reg); - return 0; -} - -/** - * igb_configure_pcs_link_82575 - Configure PCS link - * @hw: pointer to the HW structure - * - * Configure the physical coding sub-layer (PCS) link. The PCS link is - * only used on copper connections where the serialized gigabit media - * independent interface (sgmii) is being used. Configures the link - * for auto-negotiation or forces speed/duplex. - **/ -static void igb_configure_pcs_link_82575(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 reg = 0; - - if (hw->phy.media_type != e1000_media_type_copper || - !(igb_sgmii_active_82575(hw))) - return; - - /* For SGMII, we need to issue a PCS autoneg restart */ - reg = rd32(E1000_PCS_LCTL); - - /* AN time out should be disabled for SGMII mode */ - reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); - - if (mac->autoneg) { - /* Make sure forced speed and force link are not set */ - reg &= ~(E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); - - /* - * The PHY should be setup prior to calling this function. - * All we need to do is restart autoneg and enable autoneg. - */ - reg |= E1000_PCS_LCTL_AN_RESTART | E1000_PCS_LCTL_AN_ENABLE; - } else { - /* Set PCS register for forced speed */ - - /* Turn off bits for full duplex, speed, and autoneg */ - reg &= ~(E1000_PCS_LCTL_FSV_1000 | - E1000_PCS_LCTL_FSV_100 | - E1000_PCS_LCTL_FDV_FULL | - E1000_PCS_LCTL_AN_ENABLE); - - /* Check for duplex first */ - if (mac->forced_speed_duplex & E1000_ALL_FULL_DUPLEX) - reg |= E1000_PCS_LCTL_FDV_FULL; - - /* Now set speed */ - if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) - reg |= E1000_PCS_LCTL_FSV_100; - - /* Force speed and force link */ - reg |= E1000_PCS_LCTL_FSD | - E1000_PCS_LCTL_FORCE_LINK | - E1000_PCS_LCTL_FLV_LINK_UP; + if (!igb_sgmii_active_82575(hw)) + igb_force_mac_fc(hw); - hw_dbg("Wrote 0x%08X to PCS_LCTL to configure forced link\n", - reg); - } - wr32(E1000_PCS_LCTL, reg); + return 0; } /** @@ -1248,7 +1233,8 @@ static void igb_clear_hw_cntrs_82575(struct e1000_hw *hw) temp = rd32(E1000_LENERRS); /* This register should not be read in copper configurations */ - if (hw->phy.media_type == e1000_media_type_internal_serdes) + if (hw->phy.media_type == e1000_media_type_internal_serdes || + igb_sgmii_active_82575(hw)) temp = rd32(E1000_SCVPC); } diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index 8a1e6597061..ebd146fd4e1 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -28,7 +28,7 @@ #ifndef _E1000_82575_H_ #define _E1000_82575_H_ -extern void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw); +extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw); extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); #define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index c85829355d5..cb916833f30 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -44,7 +44,7 @@ #define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ /* Extended Device Control */ -#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ +#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Defineable Pin 3 */ /* Physical Func Reset Done Indication */ #define E1000_CTRL_EXT_PFRSTD 0x00004000 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 943186b7848..d2639c4a086 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -5320,7 +5320,7 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) *enable_wake = wufc || adapter->en_mng_pt; if (!*enable_wake) - igb_shutdown_fiber_serdes_link_82575(hw); + igb_shutdown_serdes_link_82575(hw); /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ -- cgit v1.2.3 From d314737ad3bad6b4603b243fd6db572385259690 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 14 Sep 2009 08:23:13 +0000 Subject: igb: do not allow phy sw reset code to make calls to null pointers In the case of fiber and serdes adapters we were seeing issues with ethtool -t causing kernel panics due to null function pointers. To prevent this we need to exit out of the phy reset code in the event that we do not have a valid phy. Signed-off-by: Alexander Duyck Signed-off-by: Don Skidmore Signed-off-by: David S. Miller --- drivers/net/igb/e1000_phy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index c1f4da63042..ee460600e74 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -1565,9 +1565,12 @@ out: **/ s32 igb_phy_sw_reset(struct e1000_hw *hw) { - s32 ret_val; + s32 ret_val = 0; u16 phy_ctrl; + if (!(hw->phy.ops.read_reg)) + goto out; + ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) goto out; -- cgit v1.2.3 From 481a8199142c050b72bff8a1956a49fd0a75bbe0 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 15 Sep 2009 01:31:34 -0700 Subject: can: fix NOHZ local_softirq_pending 08 warning When using nanosleep() in an userspace application we get a ratelimit warning NOHZ: local_softirq_pending 08 for 10 times. The echo of CAN frames is done from process context and softirq context only. Therefore the usage of netif_rx() was wrong (for years). This patch replaces netif_rx() with netif_rx_ni() which has to be used from process/softirq context. It also adds a missing comment that can_send() must no be used from hardirq context. Signed-off-by: Oliver Hartkopp Signed-off-by: Urs Thuermann Signed-off-by: David S. Miller --- drivers/net/can/vcan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 6971f6cd37f..80ac5631398 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -80,7 +80,7 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev) skb->dev = dev; skb->ip_summed = CHECKSUM_UNNECESSARY; - netif_rx(skb); + netif_rx_ni(skb); } static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) -- cgit v1.2.3 From 75c78500ddad74b229cd0691496b8549490496a2 Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Tue, 15 Sep 2009 02:37:40 -0700 Subject: bonding: remap muticast addresses without using dev_close() and dev_open() This patch fixes commit e36b9d16c6a6d0f59803b3ef04ff3c22c3844c10. The approach there is to call dev_close()/dev_open() whenever the device type is changed in order to remap the device IP multicast addresses to HW multicast addresses. This approach suffers from 2 drawbacks: *. It assumes tha the device is UP when calling dev_close(), or otherwise dev_close() has no affect. It is worth to mention that initscripts (Redhat) and sysconfig (Suse) doesn't act the same in this matter. *. dev_close() has other side affects, like deleting entries from the routing table, which might be unnecessary. The fix here is to directly remap the IP multicast addresses to HW multicast addresses for a bonding device that changes its type, and nothing else. Reported-by: Jason Gunthorpe Signed-off-by: Moni Shoua Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a7e731f8a0d..6419cf9a4fa 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1211,7 +1211,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); - netdev_bonding_change(bond->dev); + netdev_bonding_change(bond->dev, NETDEV_BONDING_FAILOVER); read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); @@ -1469,14 +1469,17 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) */ if (bond->slave_cnt == 0) { if (bond_dev->type != slave_dev->type) { - dev_close(bond_dev); pr_debug("%s: change device type from %d to %d\n", bond_dev->name, bond_dev->type, slave_dev->type); + + netdev_bonding_change(bond_dev, NETDEV_BONDING_OLDTYPE); + if (slave_dev->type != ARPHRD_ETHER) bond_setup_by_slave(bond_dev, slave_dev); else ether_setup(bond_dev); - dev_open(bond_dev); + + netdev_bonding_change(bond_dev, NETDEV_BONDING_NEWTYPE); } } else if (bond_dev->type != slave_dev->type) { pr_err(DRV_NAME ": %s ether type (%d) is different " -- cgit v1.2.3 From 531afd64d027e3d798c416b2b37b3cfb1de417d9 Mon Sep 17 00:00:00 2001 From: Ken Kawasaki Date: Tue, 15 Sep 2009 02:42:25 -0700 Subject: pcnet_cs: add cis of Linksys multifunction pcmcia card pcnet_cs,serial_cs: add cis of Linksys lan&modem mulitifunction pcmcia card and some modem card(MT5634ZLX, RS-COM-2P). Signed-off-by: Ken Kawasaki Signed-off-by: David S. Miller --- drivers/net/pcmcia/pcnet_cs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 90a94d21583..97db1c73234 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1750,11 +1750,11 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078), /* too generic! */ /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */ - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"), + PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "DP83903.cis"), -- cgit v1.2.3 From 07e316377458484d95f7624f7af7af99d9bd18cb Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 14 Sep 2009 06:12:55 +0000 Subject: sky2: transmit ring accounting Be more accurate about number of transmit list elements required. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 00bc65a0aac..fc380331697 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -65,8 +65,8 @@ #define RX_DEF_PENDING RX_MAX_PENDING /* This is the worst case number of transmit list elements for a single skb: - VLAN + TSO + CKSUM + Data + skb_frags * DMA */ -#define MAX_SKB_TX_LE (4 + (sizeof(dma_addr_t)/sizeof(u32))*MAX_SKB_FRAGS) + VLAN:GSO + CKSUM + Data + skb_frags * DMA */ +#define MAX_SKB_TX_LE (2 + (sizeof(dma_addr_t)/sizeof(u32))*(MAX_SKB_FRAGS+1)) #define TX_MIN_PENDING (MAX_SKB_TX_LE+1) #define TX_MAX_PENDING 4096 #define TX_DEF_PENDING 127 @@ -1567,11 +1567,13 @@ static unsigned tx_le_req(const struct sk_buff *skb) { unsigned count; - count = sizeof(dma_addr_t) / sizeof(u32); - count += skb_shinfo(skb)->nr_frags * count; + count = (skb_shinfo(skb)->nr_frags + 1) + * (sizeof(dma_addr_t) / sizeof(u32)); if (skb_is_gso(skb)) ++count; + else if (sizeof(dma_addr_t) == sizeof(u32)) + ++count; /* possible vlan */ if (skb->ip_summed == CHECKSUM_PARTIAL) ++count; -- cgit v1.2.3 From ca519274d537706b6fb1e3e91238d34a23320584 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 14 Sep 2009 06:22:29 +0000 Subject: sky2: Make sure both ports initialize correctly Sorry Mike, I sent you off the wrong way. The following is simpler and the second port is diffrent enough in setup (because of NAPI), that the following is simpler. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index fc380331697..4bb52e9cd37 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4550,16 +4550,18 @@ static int __devinit sky2_probe(struct pci_dev *pdev, if (hw->ports > 1) { struct net_device *dev1; + err = -ENOMEM; dev1 = sky2_init_netdev(hw, 1, using_dac, wol_default); - if (!dev1) - dev_warn(&pdev->dev, "allocation for second device failed\n"); - else if ((err = register_netdev(dev1))) { + if (dev1 && (err = register_netdev(dev1)) == 0) + sky2_show_addr(dev1); + else { dev_warn(&pdev->dev, "register of second port failed (%d)\n", err); hw->dev[1] = NULL; - free_netdev(dev1); - } else - sky2_show_addr(dev1); + hw->ports = 1; + if (dev1) + free_netdev(dev1); + } } setup_timer(&hw->watchdog_timer, sky2_watchdog, (unsigned long) hw); -- cgit v1.2.3 From 634354d753898f9d9d146bd47628a1ef27f7dc98 Mon Sep 17 00:00:00 2001 From: Vitaliy Gusev Date: Wed, 16 Sep 2009 00:00:21 -0700 Subject: mlx4: Fix access to freed memory catas_reset() uses pointer to mlx4_priv, but mlx4_priv is not valid after call mlx4_restart_one(). Signed-off-by: Vitaliy Gusev Acked-by: Roland Dreier Signed-off-by: David S. Miller --- drivers/net/mlx4/catas.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/mlx4/catas.c b/drivers/net/mlx4/catas.c index aa9674b7f19..f599294fa8a 100644 --- a/drivers/net/mlx4/catas.c +++ b/drivers/net/mlx4/catas.c @@ -96,12 +96,17 @@ static void catas_reset(struct work_struct *work) spin_unlock_irq(&catas_lock); list_for_each_entry_safe(priv, tmppriv, &tlist, catas_err.list) { + struct pci_dev *pdev = priv->dev.pdev; + ret = mlx4_restart_one(priv->dev.pdev); - dev = &priv->dev; + /* 'priv' now is not valid */ if (ret) - mlx4_err(dev, "Reset failed (%d)\n", ret); - else + printk(KERN_ERR "mlx4 %s: Reset failed (%d)\n", + pci_name(pdev), ret); + else { + dev = pci_get_drvdata(pdev); mlx4_dbg(dev, "Reset succeeded\n"); + } } } -- cgit v1.2.3 From f7f71173ea69d4dabf166533beffa9294090b7ef Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 14 Sep 2009 23:08:43 +0200 Subject: p54usb: add Zcomax XG-705A usbid This patch adds a new usbid for Zcomax XG-705A to the device table. Cc: stable@kernel.org Reported-by: Jari Jaakola Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index e44460ff149..17e199546ee 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -67,6 +67,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ + {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */ {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */ {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */ -- cgit v1.2.3 From b9f602533e2f5c32a09a3a75904e5373cb6e6377 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 31 Aug 2009 11:09:38 +0000 Subject: bonding: make ab_arp select active slaves as other modes When I was implementing primary_passive option (formely named primary_lazy) I've run into troubles with ab_arp. This is the only mode which is not using bond_select_active_slave() function to select active slave and instead it selects it itself. This seems to be not the right behaviour and it would be better to do it in bond_select_active_slave() for all cases. This patch makes this happen. Please review. Signed-off-by: Jiri Pirko Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 122 ++++++++++++---------------------------- 1 file changed, 35 insertions(+), 87 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6419cf9a4fa..69c5b15e22d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1093,15 +1093,8 @@ static struct slave *bond_find_best_slave(struct bonding *bond) return NULL; /* still no slave, return NULL */ } - /* - * first try the primary link; if arping, a link must tx/rx - * traffic before it can be considered the curr_active_slave. - * also, we would skip slaves between the curr_active_slave - * and primary_slave that may be up and able to arp - */ if ((bond->primary_slave) && - (!bond->params.arp_interval) && - (IS_UP(bond->primary_slave->dev))) { + bond->primary_slave->link == BOND_LINK_UP) { new_active = bond->primary_slave; } @@ -1109,15 +1102,14 @@ static struct slave *bond_find_best_slave(struct bonding *bond) old_active = new_active; bond_for_each_slave_from(bond, new_active, i, old_active) { - if (IS_UP(new_active->dev)) { - if (new_active->link == BOND_LINK_UP) { - return new_active; - } else if (new_active->link == BOND_LINK_BACK) { - /* link up, but waiting for stabilization */ - if (new_active->delay < mintime) { - mintime = new_active->delay; - bestslave = new_active; - } + if (new_active->link == BOND_LINK_UP) { + return new_active; + } else if (new_active->link == BOND_LINK_BACK && + IS_UP(new_active->dev)) { + /* link up, but waiting for stabilization */ + if (new_active->delay < mintime) { + mintime = new_active->delay; + bestslave = new_active; } } } @@ -2932,18 +2924,6 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) } } - read_lock(&bond->curr_slave_lock); - - /* - * Trigger a commit if the primary option setting has changed. - */ - if (bond->primary_slave && - (bond->primary_slave != bond->curr_active_slave) && - (bond->primary_slave->link == BOND_LINK_UP)) - commit++; - - read_unlock(&bond->curr_slave_lock); - return commit; } @@ -2964,90 +2944,58 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) continue; case BOND_LINK_UP: - write_lock_bh(&bond->curr_slave_lock); - - if (!bond->curr_active_slave && - time_before_eq(jiffies, dev_trans_start(slave->dev) + - delta_in_ticks)) { + if ((!bond->curr_active_slave && + time_before_eq(jiffies, + dev_trans_start(slave->dev) + + delta_in_ticks)) || + bond->curr_active_slave != slave) { slave->link = BOND_LINK_UP; - bond_change_active_slave(bond, slave); bond->current_arp_slave = NULL; pr_info(DRV_NAME - ": %s: %s is up and now the " - "active interface\n", - bond->dev->name, slave->dev->name); - - } else if (bond->curr_active_slave != slave) { - /* this slave has just come up but we - * already have a current slave; this can - * also happen if bond_enslave adds a new - * slave that is up while we are searching - * for a new slave - */ - slave->link = BOND_LINK_UP; - bond_set_slave_inactive_flags(slave); - bond->current_arp_slave = NULL; + ": %s: link status definitely " + "up for interface %s.\n", + bond->dev->name, slave->dev->name); - pr_info(DRV_NAME - ": %s: backup interface %s is now up\n", - bond->dev->name, slave->dev->name); - } + if (!bond->curr_active_slave || + (slave == bond->primary_slave)) + goto do_failover; - write_unlock_bh(&bond->curr_slave_lock); + } - break; + continue; case BOND_LINK_DOWN: if (slave->link_failure_count < UINT_MAX) slave->link_failure_count++; slave->link = BOND_LINK_DOWN; + bond_set_slave_inactive_flags(slave); - if (slave == bond->curr_active_slave) { - pr_info(DRV_NAME - ": %s: link status down for active " - "interface %s, disabling it\n", - bond->dev->name, slave->dev->name); - - bond_set_slave_inactive_flags(slave); - - write_lock_bh(&bond->curr_slave_lock); - - bond_select_active_slave(bond); - if (bond->curr_active_slave) - bond->curr_active_slave->jiffies = - jiffies; - - write_unlock_bh(&bond->curr_slave_lock); + pr_info(DRV_NAME + ": %s: link status definitely down for " + "interface %s, disabling it\n", + bond->dev->name, slave->dev->name); + if (slave == bond->curr_active_slave) { bond->current_arp_slave = NULL; - - } else if (slave->state == BOND_STATE_BACKUP) { - pr_info(DRV_NAME - ": %s: backup interface %s is now down\n", - bond->dev->name, slave->dev->name); - - bond_set_slave_inactive_flags(slave); + goto do_failover; } - break; + + continue; default: pr_err(DRV_NAME ": %s: impossible: new_link %d on slave %s\n", bond->dev->name, slave->new_link, slave->dev->name); + continue; } - } - /* - * No race with changes to primary via sysfs, as we hold rtnl. - */ - if (bond->primary_slave && - (bond->primary_slave != bond->curr_active_slave) && - (bond->primary_slave->link == BOND_LINK_UP)) { +do_failover: + ASSERT_RTNL(); write_lock_bh(&bond->curr_slave_lock); - bond_change_active_slave(bond, bond->primary_slave); + bond_select_active_slave(bond); write_unlock_bh(&bond->curr_slave_lock); } -- cgit v1.2.3 From e99b1f04d922f132ffab8310b470bcc93d3ddf80 Mon Sep 17 00:00:00 2001 From: Dongdong Deng Date: Wed, 16 Sep 2009 16:10:47 +0000 Subject: b44: the poll handler b44_poll must not enable IRQ unconditionally net/core/netpoll.c::netpoll_send_skb() calls the poll handler when it is available. As netconsole can be used from almost any context, IRQ must not be enabled blindly in the NAPI handler of the driver which supports netpoll. Call trace: netpoll_send_skb() { local_irq_save(flags) -> netpoll_poll() -> poll_napi() -> poll_one_napi() -> napi->poll() -> b44_poll() local_irq_restore(flags) } Signed-off-by: Dongdong Deng Signed-off-by: David S. Miller --- drivers/net/b44.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 0189dcd36f3..e046943ef29 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -847,23 +847,22 @@ static int b44_poll(struct napi_struct *napi, int budget) { struct b44 *bp = container_of(napi, struct b44, napi); int work_done; + unsigned long flags; - spin_lock_irq(&bp->lock); + spin_lock_irqsave(&bp->lock, flags); if (bp->istat & (ISTAT_TX | ISTAT_TO)) { /* spin_lock(&bp->tx_lock); */ b44_tx(bp); /* spin_unlock(&bp->tx_lock); */ } - spin_unlock_irq(&bp->lock); + spin_unlock_irqrestore(&bp->lock, flags); work_done = 0; if (bp->istat & ISTAT_RX) work_done += b44_rx(bp, budget); if (bp->istat & ISTAT_ERRORS) { - unsigned long flags; - spin_lock_irqsave(&bp->lock, flags); b44_halt(bp); b44_init_rings(bp); -- cgit v1.2.3 From 0aad191c5fea3627c8efbc453cfebb6d1dca496c Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Wed, 16 Sep 2009 14:07:38 +0000 Subject: wl12xx: switch to %pM to print the mac address Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: John W. Linville Signed-off-by: David S. Miller --- drivers/net/wireless/wl12xx/wl1271_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d9169b47ac4..f6f8895bbc8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -644,11 +644,10 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw, { struct wl1271 *wl = hw->priv; struct sk_buff *beacon; - DECLARE_MAC_BUF(mac); int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %s", - print_mac(mac, conf->bssid)); + printf("%pM", conf->bssid); wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid, conf->ssid_len); -- cgit v1.2.3 From 3264690b04ce4edc517fa5d31fa72496f71a7321 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 17 Sep 2009 10:18:30 -0700 Subject: wl12xx: Fix print_mac() conversion. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: David S. Miller --- drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index f6f8895bbc8..27298b19d5b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -646,8 +646,8 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw, struct sk_buff *beacon; int ret; - wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %s", - printf("%pM", conf->bssid); + wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM", + conf->bssid); wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid, conf->ssid_len); -- cgit v1.2.3 From 03f18991614cba1fa5be5dcd1a79b0e30ac44c50 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 17 Sep 2009 10:27:28 -0700 Subject: atl1e: fix 2.6.31-git4 -- ATL1E 0000:03:00.0: DMA-API: device driver frees DMA use the wrong API when free dma. So when map dma use a flag to demostrate whether it is 'pci_map_single' or 'pci_map_page'. When free the dma, check the flags to select the right APIs('pci_unmap_single' or 'pci_unmap_page'). set the flags type to u16 instead of unsigned long on David's comments. Signed-off-by: Jie Yang Signed-off-by: David S. Miller --- drivers/net/atl1e/atl1e.h | 9 +++++++++ drivers/net/atl1e/atl1e_main.c | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h index ba48220df16..490d3b38e0c 100644 --- a/drivers/net/atl1e/atl1e.h +++ b/drivers/net/atl1e/atl1e.h @@ -377,10 +377,19 @@ struct atl1e_hw { */ struct atl1e_tx_buffer { struct sk_buff *skb; + u16 flags; +#define ATL1E_TX_PCIMAP_SINGLE 0x0001 +#define ATL1E_TX_PCIMAP_PAGE 0x0002 +#define ATL1E_TX_PCIMAP_TYPE_MASK 0x0003 u16 length; dma_addr_t dma; }; +#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do { \ + ((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK; \ + ((tx_buff)->flags) |= (type); \ + } while (0) + struct atl1e_rx_page { dma_addr_t dma; /* receive rage DMA address */ u8 *addr; /* receive rage virtual address */ diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 69b830f4b68..955da733c2a 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -635,7 +635,11 @@ static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter) for (index = 0; index < ring_count; index++) { tx_buffer = &tx_ring->tx_buffer[index]; if (tx_buffer->dma) { - pci_unmap_page(pdev, tx_buffer->dma, + if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE) + pci_unmap_single(pdev, tx_buffer->dma, + tx_buffer->length, PCI_DMA_TODEVICE); + else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE) + pci_unmap_page(pdev, tx_buffer->dma, tx_buffer->length, PCI_DMA_TODEVICE); tx_buffer->dma = 0; } @@ -1220,7 +1224,11 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter) while (next_to_clean != hw_next_to_clean) { tx_buffer = &tx_ring->tx_buffer[next_to_clean]; if (tx_buffer->dma) { - pci_unmap_page(adapter->pdev, tx_buffer->dma, + if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE) + pci_unmap_single(adapter->pdev, tx_buffer->dma, + tx_buffer->length, PCI_DMA_TODEVICE); + else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE) + pci_unmap_page(adapter->pdev, tx_buffer->dma, tx_buffer->length, PCI_DMA_TODEVICE); tx_buffer->dma = 0; } @@ -1741,6 +1749,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, tx_buffer->length = map_len; tx_buffer->dma = pci_map_single(adapter->pdev, skb->data, hdr_len, PCI_DMA_TODEVICE); + ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); mapped_len += map_len; use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | @@ -1766,6 +1775,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, tx_buffer->dma = pci_map_single(adapter->pdev, skb->data + mapped_len, map_len, PCI_DMA_TODEVICE); + ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); mapped_len += map_len; use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | @@ -1801,6 +1811,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, (i * MAX_TX_BUF_LEN), tx_buffer->length, PCI_DMA_TODEVICE); + ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE); use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | ((cpu_to_le32(tx_buffer->length) & -- cgit v1.2.3 From b31c50a7f9e93a61d14740dedcbbf2c376998bc7 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 17 Sep 2009 10:30:13 -0700 Subject: be2net: fix some cmds to use mccq instead of mbox All cmds issued to BE after the creation of mccq must now use the mcc-q (and not mbox) to avoid a hw issue that results in mbox poll timeout. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 1 + drivers/net/benet/be_cmds.c | 412 ++++++++++++++++++++++++++------------------ drivers/net/benet/be_cmds.h | 5 +- drivers/net/benet/be_main.c | 42 ++--- 4 files changed, 271 insertions(+), 189 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 13b72ce870d..684c6fe24c8 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -362,5 +362,6 @@ static inline u8 is_udp_pkt(struct sk_buff *skb) extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped); extern void be_link_status_update(struct be_adapter *adapter, bool link_up); +extern void netdev_stats_update(struct be_adapter *adapter); extern int be_load_fw(struct be_adapter *adapter, u8 *func); #endif /* BE_H */ diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 1db09249830..3dd76c4170b 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -59,15 +59,22 @@ static int be_mcc_compl_process(struct be_adapter *adapter, compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & CQE_STATUS_COMPL_MASK; - if (compl_status != MCC_STATUS_SUCCESS) { + if (compl_status == MCC_STATUS_SUCCESS) { + if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) { + struct be_cmd_resp_get_stats *resp = + adapter->stats.cmd.va; + be_dws_le_to_cpu(&resp->hw_stats, + sizeof(resp->hw_stats)); + netdev_stats_update(adapter); + } + } else if (compl_status != MCC_STATUS_NOT_SUPPORTED) { extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & CQE_STATUS_EXTD_MASK; dev_warn(&adapter->pdev->dev, "Error in cmd completion: status(compl/extd)=%d/%d\n", compl_status, extd_status); - return -1; } - return 0; + return compl_status; } /* Link state evt is a string of bytes; no need for endian swapping */ @@ -97,10 +104,10 @@ static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) return NULL; } -void be_process_mcc(struct be_adapter *adapter) +int be_process_mcc(struct be_adapter *adapter) { struct be_mcc_compl *compl; - int num = 0; + int num = 0, status = 0; spin_lock_bh(&adapter->mcc_cq_lock); while ((compl = be_mcc_compl_get(adapter))) { @@ -111,38 +118,47 @@ void be_process_mcc(struct be_adapter *adapter) /* Interpret compl as a async link evt */ be_async_link_state_process(adapter, (struct be_async_event_link_state *) compl); - } else { - be_mcc_compl_process(adapter, compl); - atomic_dec(&adapter->mcc_obj.q.used); + } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { + status = be_mcc_compl_process(adapter, compl); + atomic_dec(&adapter->mcc_obj.q.used); } be_mcc_compl_use(compl); num++; } + if (num) be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, num); + spin_unlock_bh(&adapter->mcc_cq_lock); + return status; } /* Wait till no more pending mcc requests are present */ -static void be_mcc_wait_compl(struct be_adapter *adapter) +static int be_mcc_wait_compl(struct be_adapter *adapter) { -#define mcc_timeout 50000 /* 5s timeout */ - int i; +#define mcc_timeout 120000 /* 12s timeout */ + int i, status; for (i = 0; i < mcc_timeout; i++) { - be_process_mcc(adapter); + status = be_process_mcc(adapter); + if (status) + return status; + if (atomic_read(&adapter->mcc_obj.q.used) == 0) break; udelay(100); } - if (i == mcc_timeout) + if (i == mcc_timeout) { dev_err(&adapter->pdev->dev, "mccq poll timed out\n"); + return -1; + } + return 0; } /* Notify MCC requests and wait for completion */ -static void be_mcc_notify_wait(struct be_adapter *adapter) +static int be_mcc_notify_wait(struct be_adapter *adapter) { be_mcc_notify(adapter); - be_mcc_wait_compl(adapter); + return be_mcc_wait_compl(adapter); } static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) @@ -173,7 +189,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) * Insert the mailbox address into the doorbell in two steps * Polls on the mbox doorbell till a command completion (or a timeout) occurs */ -static int be_mbox_notify(struct be_adapter *adapter) +static int be_mbox_notify_wait(struct be_adapter *adapter) { int status; u32 val = 0; @@ -182,8 +198,6 @@ static int be_mbox_notify(struct be_adapter *adapter) struct be_mcc_mailbox *mbox = mbox_mem->va; struct be_mcc_compl *compl = &mbox->compl; - memset(compl, 0, sizeof(*compl)); - val |= MPU_MAILBOX_DB_HI_MASK; /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; @@ -310,34 +324,40 @@ static u32 eq_delay_to_mult(u32 usec_delay) return multiplier; } -static inline struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) +static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter) { - return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; + struct be_dma_mem *mbox_mem = &adapter->mbox_mem; + struct be_mcc_wrb *wrb + = &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; + memset(wrb, 0, sizeof(*wrb)); + return wrb; } -static inline struct be_mcc_wrb *wrb_from_mcc(struct be_queue_info *mccq) +static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) { - struct be_mcc_wrb *wrb = NULL; - if (atomic_read(&mccq->used) < mccq->len) { - wrb = queue_head_node(mccq); - queue_head_inc(mccq); - atomic_inc(&mccq->used); - memset(wrb, 0, sizeof(*wrb)); - } + struct be_queue_info *mccq = &adapter->mcc_obj.q; + struct be_mcc_wrb *wrb; + + BUG_ON(atomic_read(&mccq->used) >= mccq->len); + wrb = queue_head_node(mccq); + queue_head_inc(mccq); + atomic_inc(&mccq->used); + memset(wrb, 0, sizeof(*wrb)); return wrb; } int be_cmd_eq_create(struct be_adapter *adapter, struct be_queue_info *eq, int eq_delay) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_eq_create *req = embedded_payload(wrb); - struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_eq_create *req; struct be_dma_mem *q_mem = &eq->dma_mem; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -359,25 +379,29 @@ int be_cmd_eq_create(struct be_adapter *adapter, be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); if (!status) { + struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); eq->id = le16_to_cpu(resp->eq_id); eq->created = true; } + spin_unlock(&adapter->mbox_lock); return status; } +/* Uses mbox */ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, u8 type, bool permanent, u32 if_handle) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_mac_query *req = embedded_payload(wrb); - struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_mac_query *req; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -388,27 +412,32 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, if (permanent) { req->permanent = 1; } else { - req->if_id = cpu_to_le16((u16)if_handle); + req->if_id = cpu_to_le16((u16) if_handle); req->permanent = 0; } - status = be_mbox_notify(adapter); - if (!status) + status = be_mbox_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); memcpy(mac_addr, resp->mac.addr, ETH_ALEN); + } spin_unlock(&adapter->mbox_lock); return status; } +/* Uses synchronous MCCQ */ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, u32 if_id, u32 *pmac_id) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_pmac_add *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_pmac_add *req; int status; - spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -418,24 +447,27 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, req->if_id = cpu_to_le32(if_id); memcpy(req->mac_address, mac_addr, ETH_ALEN); - status = be_mbox_notify(adapter); + status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb); *pmac_id = le32_to_cpu(resp->pmac_id); } - spin_unlock(&adapter->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } +/* Uses synchronous MCCQ */ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_pmac_del *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_pmac_del *req; int status; - spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -445,25 +477,29 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id) req->if_id = cpu_to_le32(if_id); req->pmac_id = cpu_to_le32(pmac_id); - status = be_mbox_notify(adapter); - spin_unlock(&adapter->mbox_lock); + status = be_mcc_notify_wait(adapter); + + spin_unlock_bh(&adapter->mcc_lock); return status; } +/* Uses Mbox */ int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq, struct be_queue_info *eq, bool sol_evts, bool no_delay, int coalesce_wm) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_cq_create *req = embedded_payload(wrb); - struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_cq_create *req; struct be_dma_mem *q_mem = &cq->dma_mem; - void *ctxt = &req->context; + void *ctxt; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + ctxt = &req->context; be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -486,11 +522,13 @@ int be_cmd_cq_create(struct be_adapter *adapter, be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); if (!status) { + struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); cq->id = le16_to_cpu(resp->cq_id); cq->created = true; } + spin_unlock(&adapter->mbox_lock); return status; @@ -508,14 +546,17 @@ int be_cmd_mccq_create(struct be_adapter *adapter, struct be_queue_info *mccq, struct be_queue_info *cq) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_mcc_create *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_mcc_create *req; struct be_dma_mem *q_mem = &mccq->dma_mem; - void *ctxt = &req->context; + void *ctxt; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + ctxt = &req->context; be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -534,7 +575,7 @@ int be_cmd_mccq_create(struct be_adapter *adapter, be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); mccq->id = le16_to_cpu(resp->id); @@ -549,15 +590,17 @@ int be_cmd_txq_create(struct be_adapter *adapter, struct be_queue_info *txq, struct be_queue_info *cq) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_eth_tx_create *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_eth_tx_create *req; struct be_dma_mem *q_mem = &txq->dma_mem; - void *ctxt = &req->context; + void *ctxt; int status; - u32 len_encoded; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + ctxt = &req->context; be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -568,10 +611,8 @@ int be_cmd_txq_create(struct be_adapter *adapter, req->ulp_num = BE_ULP1_NUM; req->type = BE_ETH_TX_RING_TYPE_STANDARD; - len_encoded = fls(txq->len); /* log2(len) + 1 */ - if (len_encoded == 16) - len_encoded = 0; - AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, len_encoded); + AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, + be_encoded_q_len(txq->len)); AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt, be_pci_func(adapter)); AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1); @@ -581,28 +622,32 @@ int be_cmd_txq_create(struct be_adapter *adapter, be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb); txq->id = le16_to_cpu(resp->cid); txq->created = true; } + spin_unlock(&adapter->mbox_lock); return status; } +/* Uses mbox */ int be_cmd_rxq_create(struct be_adapter *adapter, struct be_queue_info *rxq, u16 cq_id, u16 frag_size, u16 max_frame_size, u32 if_id, u32 rss) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_eth_rx_create *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_eth_rx_create *req; struct be_dma_mem *q_mem = &rxq->dma_mem; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -617,29 +662,34 @@ int be_cmd_rxq_create(struct be_adapter *adapter, req->max_frame_size = cpu_to_le16(max_frame_size); req->rss_queue = cpu_to_le32(rss); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); rxq->id = le16_to_cpu(resp->id); rxq->created = true; } + spin_unlock(&adapter->mbox_lock); return status; } -/* Generic destroyer function for all types of queues */ +/* Generic destroyer function for all types of queues + * Uses Mbox + */ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, int queue_type) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_q_destroy *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_q_destroy *req; u8 subsys = 0, opcode = 0; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); switch (queue_type) { @@ -669,23 +719,27 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); req->id = cpu_to_le16(q->id); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); spin_unlock(&adapter->mbox_lock); return status; } -/* Create an rx filtering policy configuration on an i/f */ +/* Create an rx filtering policy configuration on an i/f + * Uses mbox + */ int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac, bool pmac_invalid, u32 *if_handle, u32 *pmac_id) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_if_create *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_if_create *req; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -694,10 +748,11 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac, req->capability_flags = cpu_to_le32(flags); req->enable_flags = cpu_to_le32(flags); + req->pmac_invalid = pmac_invalid; if (!pmac_invalid) memcpy(req->mac_addr, mac, ETH_ALEN); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_if_create *resp = embedded_payload(wrb); *if_handle = le32_to_cpu(resp->interface_id); @@ -709,14 +764,17 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac, return status; } +/* Uses mbox */ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_if_destroy *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_if_destroy *req; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -724,7 +782,8 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id) OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req)); req->interface_id = cpu_to_le32(interface_id); - status = be_mbox_notify(adapter); + + status = be_mbox_notify_wait(adapter); spin_unlock(&adapter->mbox_lock); @@ -733,20 +792,22 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id) /* Get stats is a non embedded command: the request is not embedded inside * WRB but is a separate dma memory block + * Uses asynchronous MCC */ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_get_stats *req = nonemb_cmd->va; - struct be_sge *sge = nonembedded_sgl(wrb); - int status; + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_stats *req; + struct be_sge *sge; - spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); - memset(req, 0, sizeof(*req)); + wrb = wrb_from_mccq(adapter); + req = nonemb_cmd->va; + sge = nonembedded_sgl(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); + wrb->tag0 = OPCODE_ETH_GET_STATISTICS; be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_GET_STATISTICS, sizeof(*req)); @@ -754,59 +815,61 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); sge->len = cpu_to_le32(nonemb_cmd->size); - status = be_mbox_notify(adapter); - if (!status) { - struct be_cmd_resp_get_stats *resp = nonemb_cmd->va; - be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); - } + be_mcc_notify(adapter); - spin_unlock(&adapter->mbox_lock); - return status; + spin_unlock_bh(&adapter->mcc_lock); + return 0; } +/* Uses synchronous mcc */ int be_cmd_link_status_query(struct be_adapter *adapter, bool *link_up) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_link_status *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_link_status *req; int status; - spin_lock(&adapter->mbox_lock); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); *link_up = false; - memset(wrb, 0, sizeof(*wrb)); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req)); - status = be_mbox_notify(adapter); + status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_link_status *resp = embedded_payload(wrb); if (resp->mac_speed != PHY_LINK_SPEED_ZERO) *link_up = true; } - spin_unlock(&adapter->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } +/* Uses Mbox */ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_get_fw_version *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_fw_version *req; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_GET_FW_VERSION, sizeof(*req)); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb); strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN); @@ -816,15 +879,18 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver) return status; } -/* set the EQ delay interval of an EQ to specified value */ +/* set the EQ delay interval of an EQ to specified value + * Uses async mcc + */ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb); - int status; + struct be_mcc_wrb *wrb; + struct be_cmd_req_modify_eq_delay *req; - spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -836,21 +902,24 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd) req->delay[0].phase = 0; req->delay[0].delay_multiplier = cpu_to_le32(eqd); - status = be_mbox_notify(adapter); + be_mcc_notify(adapter); - spin_unlock(&adapter->mbox_lock); - return status; + spin_unlock_bh(&adapter->mcc_lock); + return 0; } +/* Uses sycnhronous mcc */ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, u32 num, bool untagged, bool promiscuous) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_vlan_config *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_vlan_config *req; int status; - spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -866,23 +935,24 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, req->num_vlan * sizeof(vtag_array[0])); } - status = be_mbox_notify(adapter); + status = be_mcc_notify_wait(adapter); - spin_unlock(&adapter->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } -/* Use MCC for this command as it may be called in BH context */ +/* Uses MCC for this command as it may be called in BH context + * Uses synchronous mcc + */ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) { struct be_mcc_wrb *wrb; struct be_cmd_req_promiscuous_config *req; + int status; spin_lock_bh(&adapter->mcc_lock); - wrb = wrb_from_mcc(&adapter->mcc_obj.q); - BUG_ON(!wrb); - + wrb = wrb_from_mccq(adapter); req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -895,14 +965,14 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) else req->port0_promiscuous = en; - be_mcc_notify_wait(adapter); + status = be_mcc_notify_wait(adapter); spin_unlock_bh(&adapter->mcc_lock); - return 0; + return status; } /* - * Use MCC for this command as it may be called in BH context + * Uses MCC for this command as it may be called in BH context * (mc == NULL) => multicast promiscous */ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, @@ -914,9 +984,7 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, spin_lock_bh(&adapter->mcc_lock); - wrb = wrb_from_mcc(&adapter->mcc_obj.q); - BUG_ON(!wrb); - + wrb = wrb_from_mccq(adapter); req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -944,15 +1012,17 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, return 0; } +/* Uses synchrounous mcc */ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_set_flow_control *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_set_flow_control *req; int status; - spin_lock(&adapter->mbox_lock); + spin_lock_bh(&adapter->mcc_lock); - memset(wrb, 0, sizeof(*wrb)); + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -962,28 +1032,30 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) req->tx_flow_control = cpu_to_le16((u16)tx_fc); req->rx_flow_control = cpu_to_le16((u16)rx_fc); - status = be_mbox_notify(adapter); + status = be_mcc_notify_wait(adapter); - spin_unlock(&adapter->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } +/* Uses sycn mcc */ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_get_flow_control *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_flow_control *req; int status; - spin_lock(&adapter->mbox_lock); + spin_lock_bh(&adapter->mcc_lock); - memset(wrb, 0, sizeof(*wrb)); + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req)); - status = be_mbox_notify(adapter); + status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_get_flow_control *resp = embedded_payload(wrb); @@ -991,26 +1063,28 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) *rx_fc = le16_to_cpu(resp->rx_flow_control); } - spin_unlock(&adapter->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } +/* Uses mbox */ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_query_fw_cfg *req; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); if (!status) { struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); *port_num = le32_to_cpu(resp->phys_port); @@ -1020,22 +1094,24 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num) return status; } +/* Uses mbox */ int be_cmd_reset_function(struct be_adapter *adapter) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); - struct be_cmd_req_hdr *req = embedded_payload(wrb); + struct be_mcc_wrb *wrb; + struct be_cmd_req_hdr *req; int status; spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + wrb = wrb_from_mbox(adapter); + req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_FUNCTION_RESET, sizeof(*req)); - status = be_mbox_notify(adapter); + status = be_mbox_notify_wait(adapter); spin_unlock(&adapter->mbox_lock); return status; @@ -1044,13 +1120,17 @@ int be_cmd_reset_function(struct be_adapter *adapter) int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_type, u32 flash_opcode, u32 buf_size) { - struct be_mcc_wrb *wrb = wrb_from_mbox(&adapter->mbox_mem); + struct be_mcc_wrb *wrb; struct be_cmd_write_flashrom *req = cmd->va; - struct be_sge *sge = nonembedded_sgl(wrb); + struct be_sge *sge; int status; - spin_lock(&adapter->mbox_lock); - memset(wrb, 0, sizeof(*wrb)); + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = embedded_payload(wrb); + sge = nonembedded_sgl(wrb); + be_wrb_hdr_prepare(wrb, cmd->size, false, 1); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, @@ -1063,8 +1143,8 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, req->params.op_code = cpu_to_le32(flash_opcode); req->params.data_buf_size = cpu_to_le32(buf_size); - status = be_mbox_notify(adapter); + status = be_mcc_notify_wait(adapter); - spin_unlock(&adapter->mbox_lock); + spin_unlock_bh(&adapter->mcc_lock); return status; } diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index fd7028e5b78..93e432f3d92 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -61,7 +61,8 @@ enum { /* The command is completing because the queue was getting flushed */ MCC_STATUS_QUEUE_FLUSHING = 0x4, /* The command is completing with a DMA error */ - MCC_STATUS_DMA_FAILED = 0x5 + MCC_STATUS_DMA_FAILED = 0x5, + MCC_STATUS_NOT_SUPPORTED = 0x66 }; #define CQE_STATUS_COMPL_MASK 0xFFFF @@ -761,7 +762,7 @@ extern int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc); extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num); extern int be_cmd_reset_function(struct be_adapter *adapter); -extern void be_process_mcc(struct be_adapter *adapter); +extern int be_process_mcc(struct be_adapter *adapter); extern int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_oper, u32 flash_opcode, u32 buf_size); diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index ce11bba2cb6..409cf059590 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -135,7 +135,7 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) return status; } -static void netdev_stats_update(struct be_adapter *adapter) +void netdev_stats_update(struct be_adapter *adapter) { struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va); struct be_rxf_stats *rxf_stats = &hw_stats->rxf; @@ -431,8 +431,7 @@ static int make_tx_wrbs(struct be_adapter *adapter, } static netdev_tx_t be_xmit(struct sk_buff *skb, - struct net_device *netdev) - + struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); struct be_tx_obj *tx_obj = &adapter->tx_obj; @@ -490,11 +489,11 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, * set the BE in promiscuous VLAN mode. */ -static void be_vid_config(struct net_device *netdev) +static int be_vid_config(struct be_adapter *adapter) { - struct be_adapter *adapter = netdev_priv(netdev); u16 vtag[BE_NUM_VLANS_SUPPORTED]; u16 ntags = 0, i; + int status; if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED) { /* Construct VLAN Table to give to HW */ @@ -504,12 +503,13 @@ static void be_vid_config(struct net_device *netdev) ntags++; } } - be_cmd_vlan_config(adapter, adapter->if_handle, - vtag, ntags, 1, 0); + status = be_cmd_vlan_config(adapter, adapter->if_handle, + vtag, ntags, 1, 0); } else { - be_cmd_vlan_config(adapter, adapter->if_handle, - NULL, 0, 1, 1); + status = be_cmd_vlan_config(adapter, adapter->if_handle, + NULL, 0, 1, 1); } + return status; } static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp) @@ -532,7 +532,7 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid) adapter->num_vlans++; adapter->vlan_tag[vid] = 1; - be_vid_config(netdev); + be_vid_config(adapter); } static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) @@ -543,7 +543,7 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) adapter->vlan_tag[vid] = 0; vlan_group_set_device(adapter->vlan_grp, vid, NULL); - be_vid_config(netdev); + be_vid_config(adapter); } static void be_set_multicast_list(struct net_device *netdev) @@ -1444,12 +1444,8 @@ static void be_worker(struct work_struct *work) { struct be_adapter *adapter = container_of(work, struct be_adapter, work.work); - int status; - /* Get Stats */ - status = be_cmd_get_stats(adapter, &adapter->stats.cmd); - if (!status) - netdev_stats_update(adapter); + be_cmd_get_stats(adapter, &adapter->stats.cmd); /* Set EQ delay */ be_rx_eqd_update(adapter); @@ -1622,11 +1618,6 @@ static int be_setup(struct be_adapter *adapter) if (status != 0) goto do_none; - be_vid_config(netdev); - - status = be_cmd_set_flow_control(adapter, true, true); - if (status != 0) - goto if_destroy; status = be_tx_queues_create(adapter); if (status != 0) @@ -1640,8 +1631,17 @@ static int be_setup(struct be_adapter *adapter) if (status != 0) goto rx_qs_destroy; + status = be_vid_config(adapter); + if (status != 0) + goto mccqs_destroy; + + status = be_cmd_set_flow_control(adapter, true, true); + if (status != 0) + goto mccqs_destroy; return 0; +mccqs_destroy: + be_mcc_queues_destroy(adapter); rx_qs_destroy: be_rx_queues_destroy(adapter); tx_qs_destroy: -- cgit v1.2.3