From cd2e18fe785082b132d960063df83a02acc9a4f2 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Fri, 1 Jan 2010 17:43:08 +0100 Subject: pcmcia: remove remaining unused IRQ_FIRST_SHARED parameter Komuro pointed out correctly that I missed one IRQ_FIRST_SHARED parameter in smc91c92_cs.c, and that another line could be writter more beautifully. CC: netdev@vger.kernel.org CC: Komuro Tested-by: Wolfram Sang Signed-off-by: Dominik Brodowski --- drivers/net/pcmcia/smc91c92_cs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 6dd486d2977..aa57cfd1e3f 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -453,8 +453,7 @@ static int mhz_mfc_config(struct pcmcia_device *link) link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; - link->irq.Attributes = - IRQ_TYPE_DYNAMIC_SHARING; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->io.IOAddrLines = 16; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts2 = 8; @@ -652,8 +651,7 @@ static int osi_config(struct pcmcia_device *link) link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; - link->irq.Attributes = - IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->io.NumPorts1 = 64; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts2 = 8; -- cgit v1.2.3 From b6c3f5be7c6ac3375f44de4545c1ffe216b34022 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 2 Feb 2010 10:08:19 -0600 Subject: b43: Fix throughput regression Commit c7ab5ef9bcd281135c21b4732c9be779585181be entitled "b43: implement short slot and basic rate handling" reduced the transmit throughput for my BCM4311 device from 18 Mb/s to 0.7 Mb/s. The basic rate handling portion is OK, the problem is in the short slot handling. Prior to this change, the short slot enable/disable routines were never called. Experimentation showed that the critical part was changing the value at offset 0x0010 in the shared memory. This is supposed to contain the 802.11 Slot Time in usec, but if it is changed from its initial value of zero, performance is destroyed. On the other hand, changing the value in the MMIO register corresponding to the Interframe Slot Time increased performance from 18 to 22 Mb/s. A BCM4306/3 also shows dramatic improvement of the transmit rate from 5.3 to 19.0 Mb/s. Other changes in the patch include removal of the magic number for the MMIO register, and allowing the slot time to be set for any PHY operating in the 2.4 GHz band. Previously, the routine was executed only for G PHYs. Signed-off-by: Larry Finger Cc: Stable [Any stable version back through 2.6.28] Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/main.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index fe3bf949199..c484cc25389 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -115,6 +115,7 @@ #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ #define B43_MMIO_RNG 0x65A +#define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */ #define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ #define B43_MMIO_IFSCTL_USE_EDCF 0x0004 #define B43_MMIO_POWERUP_DELAY 0x6A8 diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 19b4eae47b5..fcbf0e27d9f 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -628,10 +628,17 @@ static void b43_upload_card_macaddress(struct b43_wldev *dev) static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time) { /* slot_time is in usec. */ - if (dev->phy.type != B43_PHYTYPE_G) + /* This test used to exit for all but a G PHY. */ + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) return; - b43_write16(dev, 0x684, 510 + slot_time); - b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time); + b43_write16(dev, B43_MMIO_IFSSLOT, 510 + slot_time); + /* Shared memory location 0x0010 is the slot time and should be + * set to slot_time; however, this register is initially 0 and changing + * the value adversely affects the transmit rate for BCM4311 + * devices. Until this behavior is unterstood, delete this step + * + * b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time); + */ } static void b43_short_slot_timing_enable(struct b43_wldev *dev) -- cgit v1.2.3 From 098dfded5b1b09927995e89c6d689f85a0f53384 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 5 Feb 2010 11:40:00 -0800 Subject: iwlwifi: Fix to set correct ht configuration iwl_set_rxon_ht() only get called in iwl_post_associate(); which cause possible incorrect ht configuration. Adding the call in iwl_mac_config() if IEEE80211_CONF_CHANGE_CHANNEL flag is set to re-configure and send rxon command. Fixes http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2146 Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre CC: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5461f105bd2..d10bea64fce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2744,6 +2744,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) priv->staging_rxon.flags = 0; + iwl_set_rxon_ht(priv, ht_conf); iwl_set_rxon_channel(priv, conf->channel); iwl_set_flags_for_band(priv, conf->channel->band); -- cgit v1.2.3 From 71a157e8edca55198e808f8561dd49017a54ee34 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 1 Feb 2010 21:34:14 -0700 Subject: of: add 'of_' prefix to machine_is_compatible() machine is compatible is an OF-specific call. It should have the of_ prefix to protect the global namespace. Signed-off-by: Grant Likely Acked-by: Michal Simek --- drivers/net/mace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/mace.c b/drivers/net/mace.c index d9fbad38638..43aea91e336 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -206,7 +206,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i mp->port_aaui = port_aaui; else { /* Apple Network Server uses the AAUI port */ - if (machine_is_compatible("AAPL,ShinerESB")) + if (of_machine_is_compatible("AAPL,ShinerESB")) mp->port_aaui = 1; else { #ifdef CONFIG_MACE_AAUI_PORT -- cgit v1.2.3 From 6c8afef551fef87a3bf24f8a74c69a7f2f72fc82 Mon Sep 17 00:00:00 2001 From: Sujith Date: Tue, 9 Feb 2010 10:07:00 +0530 Subject: ath9k: Fix sequence numbers for PAE frames Currently, PAE frames are not assigned proper sequence numbers. Since sending PAE frames as part of aggregates breaks crupto with several APs, they are sent as normal MPDUs. Fix the seqeuence number issue by updating the frame with the internal sequence number. Tested-by: Felix Fietkau Signed-off-by: Sujith Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index fa12b9060b0..29bf33692f7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1615,7 +1615,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_frmlen -= padsize; } - if (conf_is_ht(&hw->conf) && !is_pae(skb)) + if (conf_is_ht(&hw->conf)) bf->bf_state.bf_type |= BUF_HT; bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); @@ -1701,7 +1701,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, goto tx_done; } - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && !is_pae(skb)) { /* * Try aggregation if it's a unicast data frame * and the destination is HT capable. -- cgit v1.2.3 From 33a5d083e786f0c3fb4efedb59b0e8e3de39963b Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 9 Feb 2010 12:07:41 +0100 Subject: iwmc3200wifi: Test of wrong pointer after kzalloc in iwm_mlme_update_bss_table() The wrong pointer was tested. Signed-off-by: Roel Kluin Acked-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 3db3d8b0749..64d16fe37f9 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -794,7 +794,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, } bss->bss = kzalloc(bss_len, GFP_KERNEL); - if (!bss) { + if (!bss->bss) { kfree(bss); IWM_ERR(iwm, "Couldn't allocate bss\n"); return -ENOMEM; -- cgit v1.2.3 From 174b24963eaf96dc5e093502ee09639aed13eb2f Mon Sep 17 00:00:00 2001 From: Jelle Martijn Kok Date: Wed, 10 Feb 2010 09:34:09 -0600 Subject: rtl8187: Add new device ID Add new RTL8187B device. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index bc5726dd5fe..7ba3052b070 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -65,6 +65,7 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { /* Sitecom */ {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, + {USB_DEVICE(0x0df6, 0x0029), .driver_info = DEVICE_RTL8187B}, /* Sphairon Access Systems GmbH */ {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, /* Dick Smith Electronics */ -- cgit v1.2.3 From d6cade0f7f40834ff3b48f2469d00b1be0ea0db6 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Tue, 9 Feb 2010 23:37:54 +0000 Subject: via-velocity: Remove unused IRQ status parameter from rx_srv and tx_srv Signed-off-by: Simon Kagstrom Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index c93f58f5c6f..133069738ba 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1877,13 +1877,12 @@ static void velocity_error(struct velocity_info *vptr, int status) /** * tx_srv - transmit interrupt service * @vptr; Velocity - * @status: * * Scan the queues looking for transmitted packets that * we can complete and clean up. Update any statistics as * necessary/ */ -static int velocity_tx_srv(struct velocity_info *vptr, u32 status) +static int velocity_tx_srv(struct velocity_info *vptr) { struct tx_desc *td; int qnum; @@ -2090,14 +2089,12 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) /** * velocity_rx_srv - service RX interrupt * @vptr: velocity - * @status: adapter status (unused) * * Walk the receive ring of the velocity adapter and remove * any received packets from the receive queue. Hand the ring * slots back to the adapter for reuse. */ -static int velocity_rx_srv(struct velocity_info *vptr, int status, - int budget_left) +static int velocity_rx_srv(struct velocity_info *vptr, int budget_left) { struct net_device_stats *stats = &vptr->dev->stats; int rd_curr = vptr->rx.curr; @@ -2165,10 +2162,10 @@ static int velocity_poll(struct napi_struct *napi, int budget) * Do rx and tx twice for performance (taken from the VIA * out-of-tree driver). */ - rx_done = velocity_rx_srv(vptr, isr_status, budget / 2); - velocity_tx_srv(vptr, isr_status); - rx_done += velocity_rx_srv(vptr, isr_status, budget - rx_done); - velocity_tx_srv(vptr, isr_status); + rx_done = velocity_rx_srv(vptr, budget / 2); + velocity_tx_srv(vptr); + rx_done += velocity_rx_srv(vptr, budget - rx_done); + velocity_tx_srv(vptr); spin_unlock(&vptr->lock); @@ -3100,7 +3097,7 @@ static int velocity_resume(struct pci_dev *pdev) velocity_init_registers(vptr, VELOCITY_INIT_WOL); mac_disable_int(vptr->mac_regs); - velocity_tx_srv(vptr, 0); + velocity_tx_srv(vptr); for (i = 0; i < vptr->tx.numq; i++) { if (vptr->tx.used[i]) -- cgit v1.2.3 From 39c2ff43ea3830ccc693f965abdace96e514b1c5 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Tue, 9 Feb 2010 23:38:07 +0000 Subject: via-velocity: Take spinlock on set coalesce velocity_set_coalesce touches ISR and some other sensitive registers not covered by the rtnl lock, so take the velocity spinlock. Signed-off-by: Simon Kagstrom Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 133069738ba..54bafdab1f9 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -3341,6 +3341,7 @@ static int velocity_set_coalesce(struct net_device *dev, { struct velocity_info *vptr = netdev_priv(dev); int max_us = 0x3f * 64; + unsigned long flags; /* 6 bits of */ if (ecmd->tx_coalesce_usecs > max_us) @@ -3362,6 +3363,7 @@ static int velocity_set_coalesce(struct net_device *dev, ecmd->tx_coalesce_usecs); /* Setup the interrupt suppression and queue timers */ + spin_lock_irqsave(&vptr->lock, flags); mac_disable_int(vptr->mac_regs); setup_adaptive_interrupts(vptr); setup_queue_timers(vptr); @@ -3369,6 +3371,7 @@ static int velocity_set_coalesce(struct net_device *dev, mac_write_int_mask(vptr->int_mask, vptr->mac_regs); mac_clear_isr(vptr->mac_regs); mac_enable_int(vptr->mac_regs); + spin_unlock_irqrestore(&vptr->lock, flags); return 0; } -- cgit v1.2.3 From 3f2e8d9f13246382fbda6f03178eef867a9bfbe2 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Tue, 9 Feb 2010 23:38:25 +0000 Subject: via-velocity: Fix races on shared interrupts This patch fixes two potential races in the velocity driver: * Move the ACK and error handler to the interrupt handler. This fixes a potential race with shared interrupts when the other device interrupts before the NAPI poll handler has finished. As the velocity driver hasn't acked it's own interrupt, it will then steal the interrupt from the other device. * Use spin_lock_irqsave in velocity_poll. In the current code, the interrupt handler will deadlock if e.g., the NAPI poll handler is executing when an interrupt (for another device) comes in since it tries to take the already held lock. Also unlock the spinlock only after enabling the interrupt in velocity_poll. The error path is moved to the interrupt handler since this is where the ISR is checked now. Signed-off-by: Simon Kagstrom Signed-off-by: Anders Grafstrom Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 54bafdab1f9..317aa34b21c 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -2148,16 +2148,9 @@ static int velocity_poll(struct napi_struct *napi, int budget) struct velocity_info *vptr = container_of(napi, struct velocity_info, napi); unsigned int rx_done; - u32 isr_status; - - spin_lock(&vptr->lock); - isr_status = mac_read_isr(vptr->mac_regs); - - /* Ack the interrupt */ - mac_write_isr(vptr->mac_regs, isr_status); - if (isr_status & (~(ISR_PRXI | ISR_PPRXI | ISR_PTXI | ISR_PPTXI))) - velocity_error(vptr, isr_status); + unsigned long flags; + spin_lock_irqsave(&vptr->lock, flags); /* * Do rx and tx twice for performance (taken from the VIA * out-of-tree driver). @@ -2167,13 +2160,12 @@ static int velocity_poll(struct napi_struct *napi, int budget) rx_done += velocity_rx_srv(vptr, budget - rx_done); velocity_tx_srv(vptr); - spin_unlock(&vptr->lock); - /* If budget not fully consumed, exit the polling mode */ if (rx_done < budget) { napi_complete(napi); mac_enable_int(vptr->mac_regs); } + spin_unlock_irqrestore(&vptr->lock, flags); return rx_done; } @@ -2203,10 +2195,17 @@ static irqreturn_t velocity_intr(int irq, void *dev_instance) return IRQ_NONE; } + /* Ack the interrupt */ + mac_write_isr(vptr->mac_regs, isr_status); + if (likely(napi_schedule_prep(&vptr->napi))) { mac_disable_int(vptr->mac_regs); __napi_schedule(&vptr->napi); } + + if (isr_status & (~(ISR_PRXI | ISR_PPRXI | ISR_PTXI | ISR_PPTXI))) + velocity_error(vptr, isr_status); + spin_unlock(&vptr->lock); return IRQ_HANDLED; -- cgit v1.2.3 From fafaf31bf9f965d91462ee115e27ef6c262b74ea Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Thu, 11 Feb 2010 10:42:22 -0800 Subject: iwlwifi: fix AMSDU Rx after paged Rx patch Previous patch "use paged Rx" broke AMSDU Rx functionality. If an AP sends out A-MSDU packets the station will crash. Fix it by linearizing skbuff for AMSDU packet before handing it to mac80211 since mac80211 doesn't support paged skbuff. This fixes http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2155 Reported-by: Norbert Preining Signed-off-by: Shanyu Zhao Acked-by: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-rx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 6f36b6e79f5..2dbce85404a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -928,7 +928,10 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, if (ieee80211_is_mgmt(fc) || ieee80211_has_protected(fc) || ieee80211_has_morefrags(fc) || - le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) + le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG || + (ieee80211_is_data_qos(fc) && + *ieee80211_get_qos_ctl(hdr) & + IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)) ret = skb_linearize(skb); else ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? -- cgit v1.2.3 From 5e2a911cecc7e0fd89b1d2d001b7b89d47057ad6 Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Fri, 12 Feb 2010 12:32:27 -0800 Subject: sfc: Fix SFE4002 initialisation From: Steve Hodgson Commit 357d46a17e54c9a87e0e6ef3930ff4ab2d232b81 "sfc: QT202x: Remove unreliable MMD check at initialisation" broke initialisation of the SFE4002. efx_mdio_reset_mmd() returns a positive value rather than 0 on success. The above commit causes this value to be propagated up by qt202x_reset_phy(), which is treated as a failure by its callers. Change qt202x_reset_phy() to return 0 if successful. The PCI layer treats >0 as "fail, but please call remove() anyway", which means that unloading the driver would cause a crash. Add a WARN_ON() on the failure path of efx_pci_probe() to provide early warning if there are any other cases where we do this. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/efx.c | 1 + drivers/net/sfc/qt202x_phy.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 103e8b0e2a0..46997e177ee 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -2284,6 +2284,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, fail2: efx_fini_struct(efx); fail1: + WARN_ON(rc > 0); EFX_LOG(efx, "initialisation failed. rc=%d\n", rc); free_netdev(net_dev); return rc; diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index e0d13a45101..67eec7a6e48 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c @@ -320,7 +320,7 @@ static int qt202x_reset_phy(struct efx_nic *efx) falcon_board(efx)->type->init_phy(efx); - return rc; + return 0; fail: EFX_ERR(efx, "PHY reset timed out\n"); -- cgit v1.2.3 From a626e8478b18de4fdee0e6d13975cea2b23efea5 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 11 Feb 2010 04:13:49 +0000 Subject: ixgbe: Fix - Do not allow Rx FC on 82598 at 1G due to errata The 82598 has an erratum that receipt of pause frames at 1G could lead to a Tx Hang. To avoid this this patch disables Rx FC while at 1G speed for all 82598 parts. Signed-off-by: Don Skidmore Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82598.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 3103f416531..35a06b47587 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -357,12 +357,34 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num) u32 fctrl_reg; u32 rmcs_reg; u32 reg; + u32 link_speed = 0; + bool link_up; #ifdef CONFIG_DCB if (hw->fc.requested_mode == ixgbe_fc_pfc) goto out; #endif /* CONFIG_DCB */ + /* + * On 82598 having Rx FC on causes resets while doing 1G + * so if it's on turn it off once we know link_speed. For + * more details see 82598 Specification update. + */ + hw->mac.ops.check_link(hw, &link_speed, &link_up, false); + if (link_up && link_speed == IXGBE_LINK_SPEED_1GB_FULL) { + switch (hw->fc.requested_mode) { + case ixgbe_fc_full: + hw->fc.requested_mode = ixgbe_fc_tx_pause; + break; + case ixgbe_fc_rx_pause: + hw->fc.requested_mode = ixgbe_fc_none; + break; + default: + /* no change */ + break; + } + } + /* Negotiate the fc mode to use */ ret_val = ixgbe_fc_autoneg(hw); if (ret_val) -- cgit v1.2.3 From e86bff0edaa514a63ecd80e1ed2b3472b2507880 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Thu, 11 Feb 2010 04:14:08 +0000 Subject: ixgbe: fix WOL register setup for 82599 We need to have the WUS register set to all 1's in order for the hardware to be capable of ever waking up. Set it here in the ixgbe_probe(). Signed-off-by: Don Skidmore Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7b7c8486c0b..951b73cf5ca 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5763,6 +5763,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, if (err) goto err_sw_init; + /* Make it possible the adapter to be woken up via WOL */ + if (adapter->hw.mac.type == ixgbe_mac_82599EB) + IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); + /* * If there is a fan on this device and it has failed log the * failure. -- cgit v1.2.3 From 07793d33b4fba00f5bd1dac78fa038bb0e23fa5c Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 16 Feb 2010 00:18:46 +0000 Subject: be2net: set proper value to version field in req hdr Before sending a command to the ASIC, set version properly. This is necessary for the ARM firmware to send correct data to the driver. This also fixes a bug in certain skews of the ASIC where the statistics are misreported. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index fee6eee7ae5..006cb2efcd2 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -296,6 +296,7 @@ static void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, req_hdr->opcode = opcode; req_hdr->subsystem = subsystem; req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); + req_hdr->version = 0; } static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, -- cgit v1.2.3 From 5e2f75b8993a0d83d469388b50716dd5551f2eb4 Mon Sep 17 00:00:00 2001 From: Dan Halperin Date: Thu, 18 Feb 2010 22:01:39 -0800 Subject: iwlwifi: set HT flags after channel in rxon The HT extension channel settings require priv->staging_rxon.channel to be accurate. However, iwl_set_rxon_ht was being called before iwl_set_rxon_channel and thus HT40 could be broken unless another call to iwl_mac_config came in. This problem was recently introduced by "iwlwifi: Fix to set correct ht configuration" The particular setting in which I noticed this was monitor mode: iwconfig wlan0 mode monitor ifconfig wlan0 up ./iw wlan0 set channel 64 HT40- #./iw wlan0 set channel 64 HT40- tcpdump -i wlan0 -y IEEE802_11_RADIO would only catch HT40 packets if I issued the IW command twice. From visual inspection, iwl_set_rxon_channel does not depend on iwl_set_rxon_ht, so simply swapping them should be safe and fixes this problem. Signed-off-by: Daniel Halperin Acked-by: Wey-Yi Guy Signed-off-by: Reinette Chatre CC: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d10bea64fce..f36f804804f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2744,8 +2744,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) priv->staging_rxon.flags = 0; - iwl_set_rxon_ht(priv, ht_conf); iwl_set_rxon_channel(priv, conf->channel); + iwl_set_rxon_ht(priv, ht_conf); iwl_set_flags_for_band(priv, conf->channel->band); spin_unlock_irqrestore(&priv->lock, flags); -- cgit v1.2.3 From e0bf54c93a15c365a37cfc4fe0137f5bc012d1b9 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 19 Feb 2010 13:29:27 +0000 Subject: sfc: Fix sign of efx_mcdi_poll_reboot() error in efx_mcdi_poll() efx_mcdi_poll() uses positive error numbers, matching the MCDI protocol. It must negate the result of efx_mcdi_poll_reboot() which returns the usual negative error numbers. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/mcdi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index 9f035b9f035..f66b3da6ddf 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c @@ -127,7 +127,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) efx_dword_t reg; /* Check for a reboot atomically with respect to efx_mcdi_copyout() */ - rc = efx_mcdi_poll_reboot(efx); + rc = -efx_mcdi_poll_reboot(efx); if (rc) goto out; -- cgit v1.2.3 From 242cc0547f3bcecc0b02ca6f3e9512760185727e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 19 Feb 2010 13:34:03 +0000 Subject: sfc: SFE4002/SFN4112F: Widen temperature and voltage tolerances The temperature and voltage limits currently set on these boards are too conservative and will cause the driver to stop the net device erroneously in some systems. Based on a review of the chip datasheets and advice from the designer of these boards: - Raise the maximum board temperatures to the specified maximum ambient temperatures for their PHYs plus the expected temperature bias of the board - Raise the maximum controller temperature to 90 degrees - Lower the minimum temperatures to 0 degrees - Widen the voltage tolerances to at least +/- 10% Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon_boards.c | 45 ++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c index bf0b96af533..5712fddd72f 100644 --- a/drivers/net/sfc/falcon_boards.c +++ b/drivers/net/sfc/falcon_boards.c @@ -29,6 +29,15 @@ #define FALCON_BOARD_SFN4111T 0x51 #define FALCON_BOARD_SFN4112F 0x52 +/* Board temperature is about 15°C above ambient when air flow is + * limited. */ +#define FALCON_BOARD_TEMP_BIAS 15 + +/* SFC4000 datasheet says: 'The maximum permitted junction temperature + * is 125°C; the thermal design of the environment for the SFC4000 + * should aim to keep this well below 100°C.' */ +#define FALCON_JUNC_TEMP_MAX 90 + /***************************************************************************** * Support for LM87 sensor chip used on several boards */ @@ -548,16 +557,16 @@ fail_hwmon: static u8 sfe4002_lm87_channel = 0x03; /* use AIN not FAN inputs */ static const u8 sfe4002_lm87_regs[] = { - LM87_IN_LIMITS(0, 0x83, 0x91), /* 2.5V: 1.8V +/- 5% */ - LM87_IN_LIMITS(1, 0x51, 0x5a), /* Vccp1: 1.2V +/- 5% */ - LM87_IN_LIMITS(2, 0xb6, 0xca), /* 3.3V: 3.3V +/- 5% */ - LM87_IN_LIMITS(3, 0xb0, 0xc9), /* 5V: 4.6-5.2V */ - LM87_IN_LIMITS(4, 0xb0, 0xe0), /* 12V: 11-14V */ - LM87_IN_LIMITS(5, 0x44, 0x4b), /* Vccp2: 1.0V +/- 5% */ - LM87_AIN_LIMITS(0, 0xa0, 0xb2), /* AIN1: 1.66V +/- 5% */ - LM87_AIN_LIMITS(1, 0x91, 0xa1), /* AIN2: 1.5V +/- 5% */ - LM87_TEMP_INT_LIMITS(10, 60), /* board */ - LM87_TEMP_EXT1_LIMITS(10, 70), /* Falcon */ + LM87_IN_LIMITS(0, 0x7c, 0x99), /* 2.5V: 1.8V +/- 10% */ + LM87_IN_LIMITS(1, 0x4c, 0x5e), /* Vccp1: 1.2V +/- 10% */ + LM87_IN_LIMITS(2, 0xac, 0xd4), /* 3.3V: 3.3V +/- 10% */ + LM87_IN_LIMITS(3, 0xac, 0xd4), /* 5V: 5.0V +/- 10% */ + LM87_IN_LIMITS(4, 0xac, 0xe0), /* 12V: 10.8-14V */ + LM87_IN_LIMITS(5, 0x3f, 0x4f), /* Vccp2: 1.0V +/- 10% */ + LM87_AIN_LIMITS(0, 0x98, 0xbb), /* AIN1: 1.66V +/- 10% */ + LM87_AIN_LIMITS(1, 0x8a, 0xa9), /* AIN2: 1.5V +/- 10% */ + LM87_TEMP_INT_LIMITS(0, 80 + FALCON_BOARD_TEMP_BIAS), + LM87_TEMP_EXT1_LIMITS(0, FALCON_JUNC_TEMP_MAX), 0 }; @@ -619,14 +628,14 @@ static int sfe4002_init(struct efx_nic *efx) static u8 sfn4112f_lm87_channel = 0x03; /* use AIN not FAN inputs */ static const u8 sfn4112f_lm87_regs[] = { - LM87_IN_LIMITS(0, 0x83, 0x91), /* 2.5V: 1.8V +/- 5% */ - LM87_IN_LIMITS(1, 0x51, 0x5a), /* Vccp1: 1.2V +/- 5% */ - LM87_IN_LIMITS(2, 0xb6, 0xca), /* 3.3V: 3.3V +/- 5% */ - LM87_IN_LIMITS(4, 0xb0, 0xe0), /* 12V: 11-14V */ - LM87_IN_LIMITS(5, 0x44, 0x4b), /* Vccp2: 1.0V +/- 5% */ - LM87_AIN_LIMITS(1, 0x91, 0xa1), /* AIN2: 1.5V +/- 5% */ - LM87_TEMP_INT_LIMITS(10, 60), /* board */ - LM87_TEMP_EXT1_LIMITS(10, 70), /* Falcon */ + LM87_IN_LIMITS(0, 0x7c, 0x99), /* 2.5V: 1.8V +/- 10% */ + LM87_IN_LIMITS(1, 0x4c, 0x5e), /* Vccp1: 1.2V +/- 10% */ + LM87_IN_LIMITS(2, 0xac, 0xd4), /* 3.3V: 3.3V +/- 10% */ + LM87_IN_LIMITS(4, 0xac, 0xe0), /* 12V: 10.8-14V */ + LM87_IN_LIMITS(5, 0x3f, 0x4f), /* Vccp2: 1.0V +/- 10% */ + LM87_AIN_LIMITS(1, 0x8a, 0xa9), /* AIN2: 1.5V +/- 10% */ + LM87_TEMP_INT_LIMITS(0, 60 + FALCON_BOARD_TEMP_BIAS), + LM87_TEMP_EXT1_LIMITS(0, FALCON_JUNC_TEMP_MAX), 0 }; -- cgit v1.2.3 From a239a8b47cc0e5e6d7416a89f340beac06d5edaa Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 19 Feb 2010 15:47:32 -0800 Subject: iwlwifi: error checking for number of tfds in queue When receive reply_tx and ready to decrement the count for number of tfds in queue, do error checking to prevent error condition and tfds_in_queue become negative number. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre CC: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-tx.c | 16 +++++++++++++++- 4 files changed, 20 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9b4b8b5c757..31462813bac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2008,7 +2008,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " "%d index %d\n", scd_ssn , index); freed = iwl_tx_queue_reclaim(priv, txq_id, index); - priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark) && diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index de45f308b74..f27c514886a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1125,7 +1125,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, scd_ssn , index, txq_id, txq->swq_id); freed = iwl_tx_queue_reclaim(priv, txq_id, index); - priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark) && @@ -1154,7 +1154,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, freed = iwl_tx_queue_reclaim(priv, txq_id, index); if (ieee80211_is_data_qos(tx_resp->frame_ctrl)) - priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark)) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 675b7df632f..fe37d6a6bf9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -446,6 +446,8 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv); int iwl_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq); int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); +void iwl_free_tfds_in_queue(struct iwl_priv *priv, + int sta_id, int tid, int freed); int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id); void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 87ce2bd292c..72136c8f51d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -120,6 +120,20 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) EXPORT_SYMBOL(iwl_txq_update_write_ptr); +void iwl_free_tfds_in_queue(struct iwl_priv *priv, + int sta_id, int tid, int freed) +{ + if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + else { + IWL_ERR(priv, "free more than tfds_in_queue (%u:%d)\n", + priv->stations[sta_id].tid[tid].tfds_in_queue, + freed); + priv->stations[sta_id].tid[tid].tfds_in_queue = 0; + } +} +EXPORT_SYMBOL(iwl_free_tfds_in_queue); + /** * iwl_tx_queue_free - Deallocate DMA queue. * @txq: Transmit queue to deallocate. @@ -1559,7 +1573,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { /* calculate mac80211 ampdu sw queue to wake */ int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); - priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && priv->mac80211_registered && -- cgit v1.2.3 From a120e912eb51e347f36c71b60a1d13af74d30e83 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 19 Feb 2010 15:47:33 -0800 Subject: iwlwifi: sanity check before counting number of tfds can be free Check the frame control for ieee80211_is_data_qos() is true before counting the number of tfds can be free, the tfds_in_queue only increment when ieee80211_is_data_qos() is true before transmit; so it should only decrement if the type match. Remove ieee80211_is_data_qos check for frame_ctrl in tx_resp to avoid invalid information pass from uCode. Signed-off-by: Stanislaw Gruszka Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre CC: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 6 ++---- drivers/net/wireless/iwlwifi/iwl-tx.c | 6 +++++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f27c514886a..cffaae772d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1153,16 +1153,14 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, tx_resp->failure_frame); freed = iwl_tx_queue_reclaim(priv, txq_id, index); - if (ieee80211_is_data_qos(tx_resp->frame_ctrl)) - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); if (priv->mac80211_registered && (iwl_queue_space(&txq->q) > txq->q.low_mark)) iwl_wake_queue(priv, txq_id); } - if (ieee80211_is_data_qos(tx_resp->frame_ctrl)) - iwl_txq_check_empty(priv, sta_id, tid, txq_id); + iwl_txq_check_empty(priv, sta_id, tid, txq_id); if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 72136c8f51d..8f407156285 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1145,6 +1145,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) struct iwl_queue *q = &txq->q; struct iwl_tx_info *tx_info; int nfreed = 0; + struct ieee80211_hdr *hdr; if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " @@ -1159,13 +1160,16 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) tx_info = &txq->txb[txq->q.read_ptr]; iwl_tx_status(priv, tx_info->skb[0]); + + hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; + if (hdr && ieee80211_is_data_qos(hdr->frame_control)) + nfreed++; tx_info->skb[0] = NULL; if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); priv->cfg->ops->lib->txq_free_tfd(priv, txq); - nfreed++; } return nfreed; } -- cgit v1.2.3 From b5abb028e214cca68f4231d4f3bc0847ddbc986e Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 19 Feb 2010 17:54:53 +0000 Subject: e1000: Fix DMA mapping error handling on RX Check for error return from pci_map_single/pci_map_page and clean up. With this and the previous patch the driver was able to handle a significant percentage of errors (I set the fault injection rate to 10% and could still download large files at a reasonable speed). Signed-off-by: Anton Blanchard Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index d29bb532ecc..765543663a4 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -4006,11 +4006,21 @@ check_page: } } - if (!buffer_info->dma) + if (!buffer_info->dma) { buffer_info->dma = pci_map_page(pdev, buffer_info->page, 0, buffer_info->length, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, buffer_info->dma)) { + put_page(buffer_info->page); + dev_kfree_skb(skb); + buffer_info->page = NULL; + buffer_info->skb = NULL; + buffer_info->dma = 0; + adapter->alloc_rx_buff_failed++; + break; /* while !buffer_info->skb */ + } + } rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); @@ -4101,6 +4111,13 @@ map_skb: skb->data, buffer_info->length, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, buffer_info->dma)) { + dev_kfree_skb(skb); + buffer_info->skb = NULL; + buffer_info->dma = 0; + adapter->alloc_rx_buff_failed++; + break; /* while !buffer_info->skb */ + } /* * XXX if it was allocated cleanly it will never map to a -- cgit v1.2.3 From cac43a1b7b091b17113502e4128dcb0ff7e3503d Mon Sep 17 00:00:00 2001 From: Torgny Johansson Date: Fri, 19 Feb 2010 01:59:15 +0000 Subject: cdc_ether: new PID for Ericsson C3607w to the whitelist (resubmit) This patch adds a new vid/pid to the cdc_ether whitelist. Device added: - Ericsson Mobile Broadband variant C3607w Signed-off-by: Torgny Johansson -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ether.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 4f27f022fbf..5f3b9eaeb04 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -583,6 +583,11 @@ static const struct usb_device_id products [] = { USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1049, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &mbm_info, +}, { + /* Ericsson C3607w ver 2 */ + USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x190b, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &mbm_info, }, { /* Toshiba F3507g */ USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130b, USB_CLASS_COMM, -- cgit v1.2.3 From 662a96bd6f020782dfbdc0d0bd177c7dbb556687 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Fri, 19 Feb 2010 05:13:58 +0000 Subject: tc35815: Remove a wrong netif_wake_queue() call which triggers BUG_ON The netif_wake_queue() is called correctly (i.e. only on !txfull condition) from txdone routine. So Unconditional call to the netif_wake_queue() here is wrong. This might cause calling of start_xmit routine on txfull state and trigger BUG_ON. This bug does not happen when NAPI disabled. After txdone there must be at least one free tx slot. But with NAPI, this is not true anymore and the BUG_ON can hits on heavy load. In this driver NAPI was enabled on 2.6.33-rc1 so this is regression from 2.6.32 kernel. Reported-by: Ralf Roesch Signed-off-by: Atsushi Nemoto Signed-off-by: David S. Miller --- drivers/net/tc35815.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 75a669d48e5..d71c1976072 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1437,7 +1437,6 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status, int limit) /* Transmit complete. */ lp->lstats.tx_ints++; tc35815_txdone(dev); - netif_wake_queue(dev); if (ret < 0) ret = 0; } -- cgit v1.2.3 From 9bdcf336d0c061e77f4c45c7b2bc32e3ed6b57e3 Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Sun, 4 Oct 2009 14:55:24 +0200 Subject: MIPS: Alchemy: devboard register abstraction All Alchemy development boards have external CPLDs with a few registers in them. They all share an identical register layout with only a few minor differences (except the PB1000) in bit functions and base addresses. This patch - adds a primitive facility to initialize and use these external registers, - replaces all occurrences of bcsr->xxx accesses with calls to the new functions (the pb1200 cascade irq handling code is special). - collects BCSR register information scattered throughout the board headers in a central place. Signed-off-by: Manuel Lauss Signed-off-by: Ralf Baechle --- drivers/net/irda/au1k_ir.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c index 9b2eebdbb25..b5cbd39d068 100644 --- a/drivers/net/irda/au1k_ir.c +++ b/drivers/net/irda/au1k_ir.c @@ -36,6 +36,7 @@ #include #elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) #include +#include #else #error au1k_ir: unsupported board #endif @@ -66,10 +67,6 @@ static char version[] __devinitdata = #define RUN_AT(x) (jiffies + (x)) -#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) -static BCSR * const bcsr = (BCSR *)0xAE000000; -#endif - static DEFINE_SPINLOCK(ir_lock); /* @@ -282,9 +279,8 @@ static int au1k_irda_net_init(struct net_device *dev) #if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) /* power on */ - bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK; - bcsr->resets |= BCSR_RESETS_IRDA_MODE_FULL; - au_sync(); + bcsr_mod(BCSR_RESETS, BCSR_RESETS_IRDA_MODE_MASK, + BCSR_RESETS_IRDA_MODE_FULL); #endif return 0; @@ -720,14 +716,14 @@ au1k_irda_set_speed(struct net_device *dev, int speed) if (speed == 4000000) { #if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) - bcsr->resets |= BCSR_RESETS_FIR_SEL; + bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_FIR_SEL); #else /* Pb1000 and Pb1100 */ writel(1<<13, CPLD_AUX1); #endif } else { #if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) - bcsr->resets &= ~BCSR_RESETS_FIR_SEL; + bcsr_mod(BCSR_RESETS, BCSR_RESETS_FIR_SEL, 0); #else /* Pb1000 and Pb1100 */ writel(readl(CPLD_AUX1) & ~(1<<13), CPLD_AUX1); #endif -- cgit v1.2.3 From bd2302c220566cffd0756e1ac5f65705f9e3d8e7 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 10 Nov 2009 01:13:38 +0100 Subject: NET: au1000-eth: Convert to platform_driver model This patch converts the au1000-eth driver to become a full platform-driver as it ought to be. We now pass PHY-speficic configurations through platform_data but for compatibility the driver still assumes the default settings (search for PHY1 on MAC0) when no platform_data is passed. Tested on my MTX-1 board. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: netdev@vger.kernel.org Acked-by: David S. Miller Patchwork: http://patchwork.linux-mips.org/patch/619/ Patchwork: http://patchwork.linux-mips.org/patch/963/ Signed-off-by: Ralf Baechle --- drivers/net/au1000_eth.c | 441 ++++++++++++++++++++++++----------------------- drivers/net/au1000_eth.h | 9 + 2 files changed, 232 insertions(+), 218 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 6bac04603a8..6e5a68ecde0 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,7 @@ #include #include +#include #include #include "au1000_eth.h" @@ -112,15 +114,15 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; * * PHY detection algorithm * - * If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is + * If phy_static_config is undefined, the PHY setup is * autodetected: * * mii_probe() first searches the current MAC's MII bus for a PHY, - * selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is + * selecting the first (or last, if phy_search_highest_addr is * defined) PHY address not already claimed by another netdev. * * If nothing was found that way when searching for the 2nd ethernet - * controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then + * controller's PHY and phy1_search_mac0 is defined, then * the first MII bus is searched as well for an unclaimed PHY; this is * needed in case of a dual-PHY accessible only through the MAC0's MII * bus. @@ -129,9 +131,7 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; * controller is not registered to the network subsystem. */ -/* autodetection defaults */ -#undef AU1XXX_PHY_SEARCH_HIGHEST_ADDR -#define AU1XXX_PHY1_SEARCH_ON_MAC0 +/* autodetection defaults: phy1_search_mac0 */ /* static PHY setup * @@ -148,29 +148,6 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES]; * specific irq-map */ -#if defined(CONFIG_MIPS_BOSPORUS) -/* - * Micrel/Kendin 5 port switch attached to MAC0, - * MAC0 is associated with PHY address 5 (== WAN port) - * MAC1 is not associated with any PHY, since it's connected directly - * to the switch. - * no interrupts are used - */ -# define AU1XXX_PHY_STATIC_CONFIG - -# define AU1XXX_PHY0_ADDR 5 -# define AU1XXX_PHY0_BUSID 0 -# undef AU1XXX_PHY0_IRQ - -# undef AU1XXX_PHY1_ADDR -# undef AU1XXX_PHY1_BUSID -# undef AU1XXX_PHY1_IRQ -#endif - -#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0) -# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet -#endif - static void enable_mac(struct net_device *dev, int force_reset) { unsigned long flags; @@ -390,67 +367,55 @@ static int mii_probe (struct net_device *dev) struct au1000_private *const aup = netdev_priv(dev); struct phy_device *phydev = NULL; -#if defined(AU1XXX_PHY_STATIC_CONFIG) - BUG_ON(aup->mac_id < 0 || aup->mac_id > 1); + if (aup->phy_static_config) { + BUG_ON(aup->mac_id < 0 || aup->mac_id > 1); - if(aup->mac_id == 0) { /* get PHY0 */ -# if defined(AU1XXX_PHY0_ADDR) - phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus->phy_map[AU1XXX_PHY0_ADDR]; -# else - printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n", - dev->name); - return 0; -# endif /* defined(AU1XXX_PHY0_ADDR) */ - } else if (aup->mac_id == 1) { /* get PHY1 */ -# if defined(AU1XXX_PHY1_ADDR) - phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus->phy_map[AU1XXX_PHY1_ADDR]; -# else - printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n", - dev->name); + if (aup->phy_addr) + phydev = aup->mii_bus->phy_map[aup->phy_addr]; + else + printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n", + dev->name); return 0; -# endif /* defined(AU1XXX_PHY1_ADDR) */ - } - -#else /* defined(AU1XXX_PHY_STATIC_CONFIG) */ - int phy_addr; - - /* find the first (lowest address) PHY on the current MAC's MII bus */ - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) - if (aup->mii_bus->phy_map[phy_addr]) { - phydev = aup->mii_bus->phy_map[phy_addr]; -# if !defined(AU1XXX_PHY_SEARCH_HIGHEST_ADDR) - break; /* break out with first one found */ -# endif - } + } else { + int phy_addr; + + /* find the first (lowest address) PHY on the current MAC's MII bus */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) + if (aup->mii_bus->phy_map[phy_addr]) { + phydev = aup->mii_bus->phy_map[phy_addr]; + if (!aup->phy_search_highest_addr) + break; /* break out with first one found */ + } -# if defined(AU1XXX_PHY1_SEARCH_ON_MAC0) - /* try harder to find a PHY */ - if (!phydev && (aup->mac_id == 1)) { - /* no PHY found, maybe we have a dual PHY? */ - printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, " - "let's see if it's attached to MAC0...\n"); + if (aup->phy1_search_mac0) { + /* try harder to find a PHY */ + if (!phydev && (aup->mac_id == 1)) { + /* no PHY found, maybe we have a dual PHY? */ + printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, " + "let's see if it's attached to MAC0...\n"); - BUG_ON(!au_macs[0]); + /* find the first (lowest address) non-attached PHY on + * the MAC0 MII bus */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { + struct phy_device *const tmp_phydev = + aup->mii_bus->phy_map[phy_addr]; - /* find the first (lowest address) non-attached PHY on - * the MAC0 MII bus */ - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - struct phy_device *const tmp_phydev = - au_macs[0]->mii_bus->phy_map[phy_addr]; + if (aup->mac_id == 1) + break; - if (!tmp_phydev) - continue; /* no PHY here... */ + if (!tmp_phydev) + continue; /* no PHY here... */ - if (tmp_phydev->attached_dev) - continue; /* already claimed by MAC0 */ + if (tmp_phydev->attached_dev) + continue; /* already claimed by MAC0 */ - phydev = tmp_phydev; - break; /* found it */ + phydev = tmp_phydev; + break; /* found it */ + } + } } } -# endif /* defined(AU1XXX_PHY1_SEARCH_OTHER_BUS) */ -#endif /* defined(AU1XXX_PHY_STATIC_CONFIG) */ if (!phydev) { printk (KERN_ERR DRV_NAME ":%s: no PHY found\n", dev->name); return -1; @@ -578,31 +543,6 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base) } } -static struct { - u32 base_addr; - u32 macen_addr; - int irq; - struct net_device *dev; -} iflist[2] = { -#ifdef CONFIG_SOC_AU1000 - {AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT}, - {AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT} -#endif -#ifdef CONFIG_SOC_AU1100 - {AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT} -#endif -#ifdef CONFIG_SOC_AU1500 - {AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT}, - {AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT} -#endif -#ifdef CONFIG_SOC_AU1550 - {AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT}, - {AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT} -#endif -}; - -static int num_ifs; - /* * ethtool operations */ @@ -711,7 +651,6 @@ static int au1000_init(struct net_device *dev) static inline void update_rx_stats(struct net_device *dev, u32 status) { - struct au1000_private *aup = netdev_priv(dev); struct net_device_stats *ps = &dev->stats; ps->rx_packets++; @@ -969,7 +908,7 @@ static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev) } pDB = aup->tx_db_inuse[aup->tx_head]; - skb_copy_from_linear_data(skb, pDB->vaddr, skb->len); + skb_copy_from_linear_data(skb, (void *)pDB->vaddr, skb->len); if (skb->len < ETH_ZLEN) { for (i=skb->len; ivaddr)[i] = 0; @@ -1058,53 +997,59 @@ static const struct net_device_ops au1000_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; -static struct net_device * au1000_probe(int port_num) +static int __devinit au1000_probe(struct platform_device *pdev) { static unsigned version_printed = 0; struct au1000_private *aup = NULL; + struct au1000_eth_platform_data *pd; struct net_device *dev = NULL; db_dest_t *pDB, *pDBfree; + int irq, i, err = 0; + struct resource *base, *macen; char ethaddr[6]; - int irq, i, err; - u32 base, macen; - if (port_num >= NUM_ETH_INTERFACES) - return NULL; + base = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!base) { + printk(KERN_ERR DRV_NAME ": failed to retrieve base register\n"); + err = -ENODEV; + goto out; + } - base = CPHYSADDR(iflist[port_num].base_addr ); - macen = CPHYSADDR(iflist[port_num].macen_addr); - irq = iflist[port_num].irq; + macen = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!macen) { + printk(KERN_ERR DRV_NAME ": failed to retrieve MAC Enable register\n"); + err = -ENODEV; + goto out; + } - if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") || - !request_mem_region(macen, 4, "Au1x00 ENET")) - return NULL; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + printk(KERN_ERR DRV_NAME ": failed to retrieve IRQ\n"); + err = -ENODEV; + goto out; + } - if (version_printed++ == 0) - printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR); + if (!request_mem_region(base->start, resource_size(base), pdev->name)) { + printk(KERN_ERR DRV_NAME ": failed to request memory region for base registers\n"); + err = -ENXIO; + goto out; + } + + if (!request_mem_region(macen->start, resource_size(macen), pdev->name)) { + printk(KERN_ERR DRV_NAME ": failed to request memory region for MAC enable register\n"); + err = -ENXIO; + goto err_request; + } dev = alloc_etherdev(sizeof(struct au1000_private)); if (!dev) { printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME); - return NULL; + err = -ENOMEM; + goto err_alloc; } - dev->base_addr = base; - dev->irq = irq; - dev->netdev_ops = &au1000_netdev_ops; - SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops); - dev->watchdog_timeo = ETH_TX_TIMEOUT; - - err = register_netdev(dev); - if (err != 0) { - printk(KERN_ERR "%s: Cannot register net device, error %d\n", - DRV_NAME, err); - free_netdev(dev); - return NULL; - } - - printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n", - dev->name, base, irq); - + SET_NETDEV_DEV(dev, &pdev->dev); + platform_set_drvdata(pdev, dev); aup = netdev_priv(dev); spin_lock_init(&aup->lock); @@ -1115,21 +1060,29 @@ static struct net_device * au1000_probe(int port_num) (NUM_TX_BUFFS + NUM_RX_BUFFS), &aup->dma_addr, 0); if (!aup->vaddr) { - free_netdev(dev); - release_mem_region( base, MAC_IOSIZE); - release_mem_region(macen, 4); - return NULL; + printk(KERN_ERR DRV_NAME ": failed to allocate data buffers\n"); + err = -ENOMEM; + goto err_vaddr; } /* aup->mac is the base address of the MAC's registers */ - aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr; + aup->mac = (volatile mac_reg_t *)ioremap_nocache(base->start, resource_size(base)); + if (!aup->mac) { + printk(KERN_ERR DRV_NAME ": failed to ioremap MAC registers\n"); + err = -ENXIO; + goto err_remap1; + } - /* Setup some variables for quick register address access */ - aup->enable = (volatile u32 *)iflist[port_num].macen_addr; - aup->mac_id = port_num; - au_macs[port_num] = aup; + /* Setup some variables for quick register address access */ + aup->enable = (volatile u32 *)ioremap_nocache(macen->start, resource_size(macen)); + if (!aup->enable) { + printk(KERN_ERR DRV_NAME ": failed to ioremap MAC enable register\n"); + err = -ENXIO; + goto err_remap2; + } + aup->mac_id = pdev->id; - if (port_num == 0) { + if (pdev->id == 0) { if (prom_get_ethernet_addr(ethaddr) == 0) memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); else { @@ -1139,7 +1092,7 @@ static struct net_device * au1000_probe(int port_num) } setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); - } else if (port_num == 1) + } else if (pdev->id == 1) setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR); /* @@ -1147,14 +1100,37 @@ static struct net_device * au1000_probe(int port_num) * to match those that are printed on their stickers */ memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); - dev->dev_addr[5] += port_num; + dev->dev_addr[5] += pdev->id; *aup->enable = 0; aup->mac_enabled = 0; + pd = pdev->dev.platform_data; + if (!pd) { + printk(KERN_INFO DRV_NAME ": no platform_data passed, PHY search on MAC0\n"); + aup->phy1_search_mac0 = 1; + } else { + aup->phy_static_config = pd->phy_static_config; + aup->phy_search_highest_addr = pd->phy_search_highest_addr; + aup->phy1_search_mac0 = pd->phy1_search_mac0; + aup->phy_addr = pd->phy_addr; + aup->phy_busid = pd->phy_busid; + aup->phy_irq = pd->phy_irq; + } + + if (aup->phy_busid && aup->phy_busid > 0) { + printk(KERN_ERR DRV_NAME ": MAC0-associated PHY attached 2nd MACs MII" + "bus not supported yet\n"); + err = -ENODEV; + goto err_mdiobus_alloc; + } + aup->mii_bus = mdiobus_alloc(); - if (aup->mii_bus == NULL) - goto err_out; + if (aup->mii_bus == NULL) { + printk(KERN_ERR DRV_NAME ": failed to allocate mdiobus structure\n"); + err = -ENOMEM; + goto err_mdiobus_alloc; + } aup->mii_bus->priv = dev; aup->mii_bus->read = au1000_mdiobus_read; @@ -1168,23 +1144,19 @@ static struct net_device * au1000_probe(int port_num) for(i = 0; i < PHY_MAX_ADDR; ++i) aup->mii_bus->irq[i] = PHY_POLL; - /* if known, set corresponding PHY IRQs */ -#if defined(AU1XXX_PHY_STATIC_CONFIG) -# if defined(AU1XXX_PHY0_IRQ) - if (AU1XXX_PHY0_BUSID == aup->mac_id) - aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ; -# endif -# if defined(AU1XXX_PHY1_IRQ) - if (AU1XXX_PHY1_BUSID == aup->mac_id) - aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ; -# endif -#endif - mdiobus_register(aup->mii_bus); + if (aup->phy_static_config) + if (aup->phy_irq && aup->phy_busid == aup->mac_id) + aup->mii_bus->irq[aup->phy_addr] = aup->phy_irq; + + err = mdiobus_register(aup->mii_bus); + if (err) { + printk(KERN_ERR DRV_NAME " failed to register MDIO bus\n"); + goto err_mdiobus_reg; + } - if (mii_probe(dev) != 0) { + if (mii_probe(dev) != 0) goto err_out; - } pDBfree = NULL; /* setup the data buffer descriptors and attach a buffer to each one */ @@ -1216,19 +1188,35 @@ static struct net_device * au1000_probe(int port_num) aup->tx_db_inuse[i] = pDB; } + dev->base_addr = base->start; + dev->irq = irq; + dev->netdev_ops = &au1000_netdev_ops; + SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops); + dev->watchdog_timeo = ETH_TX_TIMEOUT; + /* * The boot code uses the ethernet controller, so reset it to start * fresh. au1000_init() expects that the device is in reset state. */ reset_mac(dev); - return dev; + err = register_netdev(dev); + if (err) { + printk(KERN_ERR DRV_NAME "%s: Cannot register net device, aborting.\n", + dev->name); + goto err_out; + } + + printk("%s: Au1xx0 Ethernet found at 0x%lx, irq %d\n", + dev->name, (unsigned long)base->start, irq); + if (version_printed++ == 0) + printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR); + + return 0; err_out: - if (aup->mii_bus != NULL) { + if (aup->mii_bus != NULL) mdiobus_unregister(aup->mii_bus); - mdiobus_free(aup->mii_bus); - } /* here we should have a valid dev plus aup-> register addresses * so we can reset the mac properly.*/ @@ -1242,67 +1230,84 @@ err_out: if (aup->tx_db_inuse[i]) ReleaseDB(aup, aup->tx_db_inuse[i]); } +err_mdiobus_reg: + mdiobus_free(aup->mii_bus); +err_mdiobus_alloc: + iounmap(aup->enable); +err_remap2: + iounmap(aup->mac); +err_remap1: dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), (void *)aup->vaddr, aup->dma_addr); - unregister_netdev(dev); +err_vaddr: free_netdev(dev); - release_mem_region( base, MAC_IOSIZE); - release_mem_region(macen, 4); - return NULL; +err_alloc: + release_mem_region(macen->start, resource_size(macen)); +err_request: + release_mem_region(base->start, resource_size(base)); +out: + return err; } -/* - * Setup the base address and interrupt of the Au1xxx ethernet macs - * based on cpu type and whether the interface is enabled in sys_pinfunc - * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0. - */ -static int __init au1000_init_module(void) +static int __devexit au1000_remove(struct platform_device *pdev) { - int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4); - struct net_device *dev; - int i, found_one = 0; + struct net_device *dev = platform_get_drvdata(pdev); + struct au1000_private *aup = netdev_priv(dev); + int i; + struct resource *base, *macen; - num_ifs = NUM_ETH_INTERFACES - ni; + platform_set_drvdata(pdev, NULL); + + unregister_netdev(dev); + mdiobus_unregister(aup->mii_bus); + mdiobus_free(aup->mii_bus); + + for (i = 0; i < NUM_RX_DMA; i++) + if (aup->rx_db_inuse[i]) + ReleaseDB(aup, aup->rx_db_inuse[i]); + + for (i = 0; i < NUM_TX_DMA; i++) + if (aup->tx_db_inuse[i]) + ReleaseDB(aup, aup->tx_db_inuse[i]); + + dma_free_noncoherent(NULL, MAX_BUF_SIZE * + (NUM_TX_BUFFS + NUM_RX_BUFFS), + (void *)aup->vaddr, aup->dma_addr); + + iounmap(aup->mac); + iounmap(aup->enable); + + base = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(base->start, resource_size(base)); + + macen = platform_get_resource(pdev, IORESOURCE_MEM, 1); + release_mem_region(macen->start, resource_size(macen)); + + free_netdev(dev); - for(i = 0; i < num_ifs; i++) { - dev = au1000_probe(i); - iflist[i].dev = dev; - if (dev) - found_one++; - } - if (!found_one) - return -ENODEV; return 0; } -static void __exit au1000_cleanup_module(void) +static struct platform_driver au1000_eth_driver = { + .probe = au1000_probe, + .remove = __devexit_p(au1000_remove), + .driver = { + .name = "au1000-eth", + .owner = THIS_MODULE, + }, +}; +MODULE_ALIAS("platform:au1000-eth"); + + +static int __init au1000_init_module(void) +{ + return platform_driver_register(&au1000_eth_driver); +} + +static void __exit au1000_exit_module(void) { - int i, j; - struct net_device *dev; - struct au1000_private *aup; - - for (i = 0; i < num_ifs; i++) { - dev = iflist[i].dev; - if (dev) { - aup = netdev_priv(dev); - unregister_netdev(dev); - mdiobus_unregister(aup->mii_bus); - mdiobus_free(aup->mii_bus); - for (j = 0; j < NUM_RX_DMA; j++) - if (aup->rx_db_inuse[j]) - ReleaseDB(aup, aup->rx_db_inuse[j]); - for (j = 0; j < NUM_TX_DMA; j++) - if (aup->tx_db_inuse[j]) - ReleaseDB(aup, aup->tx_db_inuse[j]); - dma_free_noncoherent(NULL, MAX_BUF_SIZE * - (NUM_TX_BUFFS + NUM_RX_BUFFS), - (void *)aup->vaddr, aup->dma_addr); - release_mem_region(dev->base_addr, MAC_IOSIZE); - release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4); - free_netdev(dev); - } - } + platform_driver_unregister(&au1000_eth_driver); } module_init(au1000_init_module); -module_exit(au1000_cleanup_module); +module_exit(au1000_exit_module); diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h index 824ecd5ff3a..f9d29a29b8f 100644 --- a/drivers/net/au1000_eth.h +++ b/drivers/net/au1000_eth.h @@ -108,6 +108,15 @@ struct au1000_private { struct phy_device *phy_dev; struct mii_bus *mii_bus; + /* PHY configuration */ + int phy_static_config; + int phy_search_highest_addr; + int phy1_search_mac0; + + int phy_addr; + int phy_busid; + int phy_irq; + /* These variables are just for quick access to certain regs addresses. */ volatile mac_reg_t *mac; /* mac registers */ volatile u32 *enable; /* address of MAC Enable Register */ -- cgit v1.2.3 From 780019ddf02f214ad61e641b57b8ac30c837e2a7 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Jan 2010 09:10:06 +0100 Subject: MIPS: AR7: Implement clock API This patch makes the ar7 clock code implement the Linux clk API. Drivers using the various clocks available in the SoC are updated accordingly. Signed-off-by: Florian Fainelli Acked-by: Wim Van Sebroeck To: linux-mips@linux-mips.org Cc: Wim Van Sebroeck Cc: netdev@vger.kernel.org Cc: David Miller Patchwork: http://patchwork.linux-mips.org/patch/881/ Signed-off-by: Ralf Baechle --- drivers/net/cpmac.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 8d0be26f94e..bf2072e5420 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -294,9 +295,16 @@ static int cpmac_mdio_write(struct mii_bus *bus, int phy_id, static int cpmac_mdio_reset(struct mii_bus *bus) { + struct clk *cpmac_clk; + + cpmac_clk = clk_get(&bus->dev, "cpmac"); + if (IS_ERR(cpmac_clk)) { + printk(KERN_ERR "unable to get cpmac clock\n"); + return -1; + } ar7_device_reset(AR7_RESET_BIT_MDIO); cpmac_write(bus->priv, CPMAC_MDIO_CONTROL, MDIOC_ENABLE | - MDIOC_CLKDIV(ar7_cpmac_freq() / 2200000 - 1)); + MDIOC_CLKDIV(clk_get_rate(cpmac_clk) / 2200000 - 1)); return 0; } -- cgit v1.2.3 From eeb9c182a6ad8bc130377adb0a4cd7b95dd15f49 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 4 Nov 2009 00:42:02 +1100 Subject: mac68k: move macsonic and macmace platform devices Move platform device code from the drivers to the platform init function. Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/net/macmace.c | 33 ++++----------------------------- drivers/net/macsonic.c | 33 ++++----------------------------- 2 files changed, 8 insertions(+), 58 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index 44f3c2896f2..79408c37787 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -39,7 +39,6 @@ #include "mace.h" static char mac_mace_string[] = "macmace"; -static struct platform_device *mac_mace_device; #define N_TX_BUFF_ORDER 0 #define N_TX_RING (1 << N_TX_BUFF_ORDER) @@ -752,6 +751,7 @@ static irqreturn_t mace_dma_intr(int irq, void *dev_id) MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Macintosh MACE ethernet driver"); +MODULE_ALIAS("platform:macmace"); static int __devexit mac_mace_device_remove (struct platform_device *pdev) { @@ -777,47 +777,22 @@ static struct platform_driver mac_mace_driver = { .probe = mace_probe, .remove = __devexit_p(mac_mace_device_remove), .driver = { - .name = mac_mace_string, + .name = mac_mace_string, + .owner = THIS_MODULE, }, }; static int __init mac_mace_init_module(void) { - int err; - if (!MACH_IS_MAC) return -ENODEV; - if ((err = platform_driver_register(&mac_mace_driver))) { - printk(KERN_ERR "Driver registration failed\n"); - return err; - } - - mac_mace_device = platform_device_alloc(mac_mace_string, 0); - if (!mac_mace_device) - goto out_unregister; - - if (platform_device_add(mac_mace_device)) { - platform_device_put(mac_mace_device); - mac_mace_device = NULL; - } - - return 0; - -out_unregister: - platform_driver_unregister(&mac_mace_driver); - - return -ENOMEM; + return platform_driver_register(&mac_mace_driver); } static void __exit mac_mace_cleanup_module(void) { platform_driver_unregister(&mac_mace_driver); - - if (mac_mace_device) { - platform_device_unregister(mac_mace_device); - mac_mace_device = NULL; - } } module_init(mac_mace_init_module); diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index 875d361fb79..24109c28810 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -62,7 +62,6 @@ #include static char mac_sonic_string[] = "macsonic"; -static struct platform_device *mac_sonic_device; #include "sonic.h" @@ -607,6 +606,7 @@ out: MODULE_DESCRIPTION("Macintosh SONIC ethernet driver"); module_param(sonic_debug, int, 0); MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)"); +MODULE_ALIAS("platform:macsonic"); #include "sonic.c" @@ -627,44 +627,19 @@ static struct platform_driver mac_sonic_driver = { .probe = mac_sonic_probe, .remove = __devexit_p(mac_sonic_device_remove), .driver = { - .name = mac_sonic_string, + .name = mac_sonic_string, + .owner = THIS_MODULE, }, }; static int __init mac_sonic_init_module(void) { - int err; - - if ((err = platform_driver_register(&mac_sonic_driver))) { - printk(KERN_ERR "Driver registration failed\n"); - return err; - } - - mac_sonic_device = platform_device_alloc(mac_sonic_string, 0); - if (!mac_sonic_device) - goto out_unregister; - - if (platform_device_add(mac_sonic_device)) { - platform_device_put(mac_sonic_device); - mac_sonic_device = NULL; - } - - return 0; - -out_unregister: - platform_driver_unregister(&mac_sonic_driver); - - return -ENOMEM; + return platform_driver_register(&mac_sonic_driver); } static void __exit mac_sonic_cleanup_module(void) { platform_driver_unregister(&mac_sonic_driver); - - if (mac_sonic_device) { - platform_device_unregister(mac_sonic_device); - mac_sonic_device = NULL; - } } module_init(mac_sonic_init_module); -- cgit v1.2.3