From 4b1bfb7d2d125af6653d6c2305356b2677f79dc6 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 10 Aug 2011 15:32:22 +0200 Subject: rt2x00: fix crash in rt2800usb_write_tx_desc Patch should fix this oops: BUG: unable to handle kernel NULL pointer dereference at 000000a0 IP: [] rt2800usb_write_tx_desc+0x18/0xc0 [rt2800usb] *pdpt = 000000002408c001 *pde = 0000000024079067 *pte = 0000000000000000 Oops: 0000 [#1] SMP EIP: 0060:[] EFLAGS: 00010282 CPU: 0 EIP is at rt2800usb_write_tx_desc+0x18/0xc0 [rt2800usb] EAX: 00000035 EBX: ef2bef10 ECX: 00000000 EDX: d40958a0 ESI: ef1865f8 EDI: ef1865f8 EBP: d4095878 ESP: d409585c DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Call Trace: [] rt2x00queue_write_tx_frame+0x155/0x300 [rt2x00lib] [] rt2x00mac_tx+0x7c/0x370 [rt2x00lib] [] ? mark_held_locks+0x62/0x90 [] ? _raw_spin_unlock_irqrestore+0x35/0x60 [] ? trace_hardirqs_on_caller+0x5a/0x170 [] ? trace_hardirqs_on+0xb/0x10 [] __ieee80211_tx+0x5c/0x1e0 [mac80211] [] ieee80211_tx+0xbc/0xe0 [mac80211] [] ? ieee80211_tx+0x23/0xe0 [mac80211] [] ieee80211_xmit+0xc1/0x200 [mac80211] [] ? ieee80211_tx+0xe0/0xe0 [mac80211] [] ? lock_release_holdtime+0x35/0x1b0 [] ? ieee80211_subif_start_xmit+0x446/0x5f0 [mac80211] [] ieee80211_subif_start_xmit+0x29d/0x5f0 [mac80211] [] ? ieee80211_subif_start_xmit+0x3e4/0x5f0 [mac80211] [] ? sock_setsockopt+0x6a8/0x6f0 [] ? sock_setsockopt+0x520/0x6f0 [] dev_hard_start_xmit+0x2ef/0x650 Oops might happen because we perform parallel putting new entries in a queue (rt2x00queue_write_tx_frame()) and removing entries after finishing transmitting (rt2800usb_work_txdone()). There are cases when _txdone may process an entry that was not fully send and nullify entry->skb . To fix check in _txdone if entry has flags that indicate pending transmission and wait until flags get cleared. Reported-by: Justin Piszcz Cc: stable@kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 939563162fb3..2cb25ea13c52 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -464,6 +464,15 @@ static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg) int wcid, ack, pid; int tx_wcid, tx_ack, tx_pid; + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) { + WARNING(entry->queue->rt2x00dev, + "Data pending for entry %u in queue %u\n", + entry->entry_idx, entry->queue->qid); + cond_resched(); + return false; + } + wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); @@ -558,8 +567,10 @@ static void rt2800usb_work_txdone(struct work_struct *work) while (!rt2x00queue_empty(queue)) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) break; + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); else if (rt2x00queue_status_timeout(entry)) -- cgit v1.2.1 From df71c9cfceea801e7e26e2c74241758ef9c042e5 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 10 Aug 2011 15:32:23 +0200 Subject: rt2x00: fix order of entry flags modification In rt2800usb_work_txdone we check flags in order: - ENTRY_OWNER_DEVICE_DATA - ENTRY_DATA_STATUS_PENDING - ENTRY_DATA_IO_FAILED Modify flags in separate order in rt2x00usb_interrupt_txdone, to avoid processing entries in _txdone with wrong flags or skip processing ready entries. Reported-by: Justin Piszcz Cc: stable@kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index b6b4542c2460..7fbb55c9da82 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -262,23 +262,20 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; - - if (rt2x00dev->ops->lib->tx_dma_done) - rt2x00dev->ops->lib->tx_dma_done(entry); - - /* - * Report the frame as DMA done - */ - rt2x00lib_dmadone(entry); - /* * Check if the frame was correctly uploaded */ if (urb->status) set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); + /* + * Report the frame as DMA done + */ + rt2x00lib_dmadone(entry); + if (rt2x00dev->ops->lib->tx_dma_done) + rt2x00dev->ops->lib->tx_dma_done(entry); /* * Schedule the delayed work for reading the TX status * from the device. -- cgit v1.2.1 From 674db1344443204b6ce3293f2df8fd1b7665deea Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 10 Aug 2011 15:32:24 +0200 Subject: rt2x00: fix crash in rt2800usb_get_txwi Patch should fix this oops: BUG: unable to handle kernel NULL pointer dereference at 000000a0 IP: [] rt2800usb_get_txwi+0x19/0x70 [rt2800usb] *pdpt = 0000000000000000 *pde = f000ff53f000ff53 Oops: 0000 [#1] SMP Pid: 198, comm: kworker/u:3 Tainted: G W 3.0.0-wl+ #9 LENOVO 6369CTO/6369CTO EIP: 0060:[] EFLAGS: 00010283 CPU: 1 EIP is at rt2800usb_get_txwi+0x19/0x70 [rt2800usb] EAX: 00000000 EBX: f465e140 ECX: f4494960 EDX: ef24c5f8 ESI: 810f21f5 EDI: f1da9960 EBP: f4581e80 ESP: f4581e70 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Process kworker/u:3 (pid: 198, ti=f4580000 task=f4494960 task.ti=f4580000) Call Trace: [] rt2800_txdone_entry+0x2f/0xf0 [rt2800lib] [] ? warn_slowpath_common+0x7d/0xa0 [] ? rt2800usb_work_txdone+0x288/0x360 [rt2800usb] [] ? rt2800usb_work_txdone+0x288/0x360 [rt2800usb] [] rt2800usb_work_txdone+0x263/0x360 [rt2800usb] [] process_one_work+0x186/0x440 [] ? process_one_work+0x10a/0x440 [] ? rt2800usb_probe_hw+0x120/0x120 [rt2800usb] [] worker_thread+0x133/0x310 [] ? trace_hardirqs_on+0xb/0x10 [] ? manage_workers+0x1e0/0x1e0 [] kthread+0x7c/0x90 [] ? __init_kthread_worker+0x60/0x60 [] kernel_thread_helper+0x6/0x1 Oops might happen because we check rt2x00queue_empty(queue) twice, but this condition can change and we can process entry in rt2800_txdone_entry(), which was already processed by rt2800usb_txdone_entry_check() -> rt2x00lib_txdone_noinfo() and has nullify entry->skb . Reported-by: Justin Piszcz Cc: stable@kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 2cb25ea13c52..dbf501ca317f 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -538,12 +538,11 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev) entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); if (rt2800usb_txdone_entry_check(entry, reg)) break; + entry = NULL; } - if (!entry || rt2x00queue_empty(queue)) - break; - - rt2800_txdone_entry(entry, reg); + if (entry) + rt2800_txdone_entry(entry, reg); } } -- cgit v1.2.1 From f8afdf481f0fef5e170c6c928cec42879d505654 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 12 Aug 2011 13:31:30 -0400 Subject: drivers/net/wireless/wl12xx: add missing kfree In each case, the freed data should be freed in the error handling code as well. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @exists@ local idexpression x; statement S,S1; expression E; identifier fl; expression *ptr != NULL; @@ x = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S <... when != x when != if (...) { <+...kfree(x)...+> } when any when != true x == NULL x->fl ...> ( if (x == NULL) S1 | if (...) { ... when != x when forall ( return \(0\|<+...x...+>\|ptr\); | * return ...; ) } ) // Signed-off-by: Julia Lawall Acked-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/acx.c | 6 +----- drivers/net/wireless/wl12xx/testmode.c | 5 ++++- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 7e33f1f4f3d4..34f6ab53e519 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -77,8 +77,6 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth) auth->sleep_auth = sleep_auth; ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); - if (ret < 0) - return ret; out: kfree(auth); @@ -624,10 +622,8 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl) ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD, detection, sizeof(*detection)); - if (ret < 0) { + if (ret < 0) wl1271_warning("failed to set cca threshold: %d", ret); - return ret; - } out: kfree(detection); diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 5d5e1ef87206..88add68bd9ac 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -139,12 +139,15 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) if (ret < 0) { wl1271_warning("testmode cmd interrogate failed: %d", ret); + kfree(cmd); return ret; } skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd)); - if (!skb) + if (!skb) { + kfree(cmd); return -ENOMEM; + } NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd); -- cgit v1.2.1 From 4eb60d869fdad7acd098b53bfd1863c311d8933d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sat, 13 Aug 2011 09:02:43 -0700 Subject: Revert "iwlagn: sysfs couldn't find the priv pointer" This reverts commit cc1a93e68f6c0d736b771f0746e8e4186f483fdc. This fix introduced a bug: bad pointer in unload. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-pci.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 69d4ec467dca..fb7e436b40c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -134,7 +134,6 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data) { bus->drv_data = drv_data; - pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_data); } static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], @@ -455,6 +454,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); } + pci_set_drvdata(pdev, bus); + bus->dev = &pdev->dev; bus->irq = pdev->irq; bus->ops = &pci_ops; @@ -493,12 +494,11 @@ static void iwl_pci_down(struct iwl_bus *bus) static void __devexit iwl_pci_remove(struct pci_dev *pdev) { - struct iwl_priv *priv = pci_get_drvdata(pdev); - void *bus_specific = priv->bus->bus_specific; + struct iwl_bus *bus = pci_get_drvdata(pdev); - iwl_remove(priv); + iwl_remove(bus->drv_data); - iwl_pci_down(bus_specific); + iwl_pci_down(bus); } #ifdef CONFIG_PM @@ -506,20 +506,20 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) static int iwl_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_priv *priv = pci_get_drvdata(pdev); + struct iwl_bus *bus = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx. */ - return iwl_suspend(priv); + return iwl_suspend(bus->drv_data); } static int iwl_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_priv *priv = pci_get_drvdata(pdev); + struct iwl_bus *bus = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if @@ -532,7 +532,7 @@ static int iwl_pci_resume(struct device *device) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - return iwl_resume(priv); + return iwl_resume(bus->drv_data); } static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); -- cgit v1.2.1 From 16a9d06c753abc44f66f88e03bbecb3f1e45d71b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sat, 13 Aug 2011 09:02:44 -0700 Subject: iwlagn: sysfs couldn't find the priv pointer This bug has been introduced by: d593411084a56124aa9d80aafa15db8463b2d8f7 Author: Emmanuel Grumbach Date: Mon Jul 11 10:48:51 2011 +0300 iwlagn: simplify the bus architecture Revert part of the buggy patch: dev_get_drvdata will now return iwl_priv as it did before the patch. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-pci.c | 39 +++++++++++++++------------------- 1 file changed, 17 insertions(+), 22 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index fb7e436b40c7..2fdbffa079c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -134,6 +134,7 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data) { bus->drv_data = drv_data; + pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_data); } static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], @@ -454,8 +455,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); } - pci_set_drvdata(pdev, bus); - bus->dev = &pdev->dev; bus->irq = pdev->irq; bus->ops = &pci_ops; @@ -479,26 +478,22 @@ out_no_pci: return err; } -static void iwl_pci_down(struct iwl_bus *bus) -{ - struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus->bus_specific; - - pci_disable_msi(pci_bus->pci_dev); - pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base); - pci_release_regions(pci_bus->pci_dev); - pci_disable_device(pci_bus->pci_dev); - pci_set_drvdata(pci_bus->pci_dev, NULL); - - kfree(bus); -} - static void __devexit iwl_pci_remove(struct pci_dev *pdev) { - struct iwl_bus *bus = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); + struct iwl_bus *bus = priv->bus; + struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus); + struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); - iwl_remove(bus->drv_data); + iwl_remove(priv); - iwl_pci_down(bus); + pci_disable_msi(pci_dev); + pci_iounmap(pci_dev, pci_bus->hw_base); + pci_release_regions(pci_dev); + pci_disable_device(pci_dev); + pci_set_drvdata(pci_dev, NULL); + + kfree(bus); } #ifdef CONFIG_PM @@ -506,20 +501,20 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) static int iwl_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_bus *bus = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx. */ - return iwl_suspend(bus->drv_data); + return iwl_suspend(priv); } static int iwl_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_bus *bus = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if @@ -532,7 +527,7 @@ static int iwl_pci_resume(struct device *device) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - return iwl_resume(bus->drv_data); + return iwl_resume(priv); } static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); -- cgit v1.2.1 From 543cc38c8fe86deba4169977c61eb88491036837 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 12 Aug 2011 14:02:04 +0200 Subject: rt2x00: do not drop usb dev reference counter on suspend When hibernating ->resume may not be called by usb core, but disconnect and probe instead, so we do not increase the counter after decreasing it in ->supend. As a result we free memory early, and get crash when unplugging usb dongle. BUG: unable to handle kernel paging request at 6b6b6b9f IP: [] driver_sysfs_remove+0x10/0x30 *pdpt = 0000000034f21001 *pde = 0000000000000000 Pid: 20, comm: khubd Not tainted 3.1.0-rc1-wl+ #20 LENOVO 6369CTO/6369CTO EIP: 0060:[] EFLAGS: 00010202 CPU: 1 EIP is at driver_sysfs_remove+0x10/0x30 EAX: 6b6b6b6b EBX: f52bba34 ECX: 00000000 EDX: 6b6b6b6b ESI: 6b6b6b6b EDI: c0a0ea20 EBP: f61c9e68 ESP: f61c9e64 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Process khubd (pid: 20, ti=f61c8000 task=f6138270 task.ti=f61c8000) Call Trace: [] __device_release_driver+0x1f/0xa0 [] device_release_driver+0x20/0x40 [] bus_remove_device+0x84/0xe0 [] ? device_remove_attrs+0x2a/0x80 [] device_del+0xe7/0x170 [] usb_disconnect+0xd4/0x180 [] hub_thread+0x691/0x1600 [] ? wake_up_bit+0x30/0x30 [] ? complete+0x49/0x60 [] ? hub_disconnect+0xd0/0xd0 [] ? hub_disconnect+0xd0/0xd0 [] kthread+0x74/0x80 [] ? kthread_worker_fn+0x150/0x150 [] kernel_thread_helper+0x6/0x10 Cc: stable@kernel.org Signed-off-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 7fbb55c9da82..1e31050dafc9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -871,18 +871,8 @@ int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state) { struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); struct rt2x00_dev *rt2x00dev = hw->priv; - int retval; - - retval = rt2x00lib_suspend(rt2x00dev, state); - if (retval) - return retval; - /* - * Decrease usbdev refcount. - */ - usb_put_dev(interface_to_usbdev(usb_intf)); - - return 0; + return rt2x00lib_suspend(rt2x00dev, state); } EXPORT_SYMBOL_GPL(rt2x00usb_suspend); @@ -891,8 +881,6 @@ int rt2x00usb_resume(struct usb_interface *usb_intf) struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); struct rt2x00_dev *rt2x00dev = hw->priv; - usb_get_dev(interface_to_usbdev(usb_intf)); - return rt2x00lib_resume(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00usb_resume); -- cgit v1.2.1 From b503c7a273c0a3018ad11ea8c513c639120afbf4 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Fri, 19 Aug 2011 18:43:06 +0530 Subject: ath9k_hw: Fix STA (AR9485) bringup issue due to incorrect MAC address Due to some recent optimization done in the way the mac address bytes are written into the OTP memory, some AR9485 chipsets were forced to use the first byte from the eeprom template and the remaining bytes are read from OTP. AR9485 happens to use generic eeprom template which has 0x1 as the first byte causes issues in bringing up the card. So fixed the eeprom template accordingly to address the issue. Cc: stable@kernel.org Cc: Paul Stewart Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index c34bef1bf2b0..1b9400371eaf 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -69,7 +69,7 @@ static int ar9003_hw_power_interpolate(int32_t x, static const struct ar9300_eeprom ar9300_default = { .eepromVersion = 2, .templateVersion = 2, - .macAddr = {1, 2, 3, 4, 5, 6}, + .macAddr = {0, 2, 3, 4, 5, 6}, .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, .baseEepHeader = { -- cgit v1.2.1 From 80900d0140a7648587982c8f299830e900e49165 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 22 Aug 2011 23:19:48 +0300 Subject: wl12xx: Remove obsolete testmode NVS push command The testmode NVS push command is no longer in use. In addition, it has several implementation issues that prevent it from working correctly: 1. wl1271_tm_cmd_configure relies on wl->chip.id being set. However, since the device was not necessarily booted by the time the function is called, wl->chip.id will be initialized to 0. 2. The NVS file is fetched by calling request_firmware() before it is possible to push an NVS file. 3. The maximum allowed size of nl binary payloads is not sufficient for pushing NVS files. 4. Pushing 128x NVS files will always fail due to a bug in the validation code. 5. In case the pushed NVS file is found invalid, the mutex will be kept locked and the nvs member will become a dangling pointer. Since this feature is not being used, remove it completely instead of fixing it. Signed-off-by: Ido Yariv Acked-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/testmode.c | 45 ---------------------------------- 1 file changed, 45 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 88add68bd9ac..4ae8effaee22 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -36,7 +36,6 @@ enum wl1271_tm_commands { WL1271_TM_CMD_TEST, WL1271_TM_CMD_INTERROGATE, WL1271_TM_CMD_CONFIGURE, - WL1271_TM_CMD_NVS_PUSH, WL1271_TM_CMD_SET_PLT_MODE, WL1271_TM_CMD_RECOVER, @@ -190,48 +189,6 @@ static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[]) return 0; } -static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) -{ - int ret = 0; - size_t len; - void *buf; - - wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push"); - - if (!tb[WL1271_TM_ATTR_DATA]) - return -EINVAL; - - buf = nla_data(tb[WL1271_TM_ATTR_DATA]); - len = nla_len(tb[WL1271_TM_ATTR_DATA]); - - mutex_lock(&wl->mutex); - - kfree(wl->nvs); - - if ((wl->chip.id == CHIP_ID_1283_PG20) && - (len != sizeof(struct wl128x_nvs_file))) - return -EINVAL; - else if (len != sizeof(struct wl1271_nvs_file)) - return -EINVAL; - - wl->nvs = kzalloc(len, GFP_KERNEL); - if (!wl->nvs) { - wl1271_error("could not allocate memory for the nvs file"); - ret = -ENOMEM; - goto out; - } - - memcpy(wl->nvs, buf, len); - wl->nvs_len = len; - - wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs"); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) { u32 val; @@ -288,8 +245,6 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) return wl1271_tm_cmd_interrogate(wl, tb); case WL1271_TM_CMD_CONFIGURE: return wl1271_tm_cmd_configure(wl, tb); - case WL1271_TM_CMD_NVS_PUSH: - return wl1271_tm_cmd_nvs_push(wl, tb); case WL1271_TM_CMD_SET_PLT_MODE: return wl1271_tm_cmd_set_plt_mode(wl, tb); case WL1271_TM_CMD_RECOVER: -- cgit v1.2.1 From a15f1c45f393982196c981a8df8b534cc9f3bb80 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 22 Aug 2011 23:19:49 +0300 Subject: wl12xx: Fix validation of pm_runtime_get_sync return value wl1271_sdio_power_on checks if the return value of pm_runtime_get_sync is non-zero, and if so bails out. However, pm_runtime_get_sync can return a positive number which does not suggest an error has occurred. This is problematic for two reasons: 1. The function will needlessly bail out without decrementing back the runtime PM reference counter. 2. wl1271_power_on only checks if wl1271_power_on return value is negative. This means that wl1271_power_on will continue even if wl1271_sdio_power_on bailed out. As a result, sdio transactions will be initiated without properly enabling the sdio function and claiming the host. This could even lead to a kernel panic. Fix this by only checking that the return value of pm_runtime_get_sync is non-negative. Signed-off-by: Ido Yariv Acked-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 5cf18c2c23f0..fb1fd5af75ea 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -164,7 +164,7 @@ static int wl1271_sdio_power_on(struct wl1271 *wl) /* If enabled, tell runtime PM not to power off the card */ if (pm_runtime_enabled(&func->dev)) { ret = pm_runtime_get_sync(&func->dev); - if (ret) + if (ret < 0) goto out; } else { /* Runtime PM is disabled: power up the card manually */ -- cgit v1.2.1 From 7a5e4877c14de0827dbda8efa5080089757a8733 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 23 Aug 2011 11:42:25 +0300 Subject: wl12xx: add max_sched_scan_ssids value to the hw description After commit 5a865ba, we require a separate value to indicate the number of supported SSIDs in scheduled scans. This patch adds a proper value to the wl12xx driver. This fixes a regression in 3.1-rc3 where scheduled scans were not working properly with the wl12xx driver. Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e58c22d21e39..b70ae40ad660 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -4283,6 +4283,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); wl->hw->wiphy->max_scan_ssids = 1; + wl->hw->wiphy->max_sched_scan_ssids = 1; /* * Maximum length of elements in scanning probe request templates * should be the maximum length possible for a template, without -- cgit v1.2.1 From 66cb54bd24086b2d871a03035de9b0e79b2b725e Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 24 Aug 2011 00:44:32 +0400 Subject: carl9170: Fix mismatch in carl9170_op_set_key mutex lock-unlock If is_main_vif(ar, vif) reports that we have to fall back to software encryption, we goto err_softw; before locking ar->mutex. As a result, we have unprotected call to carl9170_set_operating_mode and unmatched mutex_unlock. The patch fix the issue by adding mutex_lock before goto. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Cc: Acked-By: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/carl9170/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 0122930b14c7..0474e6638d21 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1066,8 +1066,10 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, * the high througput speed in 802.11n networks. */ - if (!is_main_vif(ar, vif)) + if (!is_main_vif(ar, vif)) { + mutex_lock(&ar->mutex); goto err_softw; + } /* * While the hardware supports *catch-all* key, for offloading -- cgit v1.2.1 From 8b2a3827bb12430d932cd479b22d906baf08c212 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 24 Aug 2011 21:38:07 +0530 Subject: ath9k: Fix PS wrappers in ath9k_set_coverage_class this callback is called during suspend/resume and also via iw command. it configures parameters like sifs, slottime, acktimeout in ath9k_hw_init_global_settings where few REG_READ, REG_RMW are also done and hence the need for PS wrappers Cc: stable@kernel.org Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9098aaad97a9..6530694a59ae 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2283,7 +2283,11 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) mutex_lock(&sc->mutex); ah->coverage_class = coverage_class; + + ath9k_ps_wakeup(sc); ath9k_hw_init_global_settings(ah); + ath9k_ps_restore(sc); + mutex_unlock(&sc->mutex); } -- cgit v1.2.1 From c6f59d13e24187ff95427a9f4a5a7e14fb8faf5a Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 24 Aug 2011 17:56:15 -0700 Subject: ibmveth: Fix leak when recycling skb and hypervisor returns error If h_add_logical_lan_buffer returns an error we need to free the skb. Signed-off-by: Anton Blanchard Cc: stable Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index ba99af05bf62..3e6679269400 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -395,7 +395,7 @@ static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *ada } /* recycle the current buffer on the rx queue */ -static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) +static int ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) { u32 q_index = adapter->rx_queue.index; u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator; @@ -403,6 +403,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) unsigned int index = correlator & 0xffffffffUL; union ibmveth_buf_desc desc; unsigned long lpar_rc; + int ret = 1; BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS); BUG_ON(index >= adapter->rx_buff_pool[pool].size); @@ -410,7 +411,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) if (!adapter->rx_buff_pool[pool].active) { ibmveth_rxq_harvest_buffer(adapter); ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]); - return; + goto out; } desc.fields.flags_len = IBMVETH_BUF_VALID | @@ -423,12 +424,16 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed " "during recycle rc=%ld", lpar_rc); ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); + ret = 0; } if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) { adapter->rx_queue.index = 0; adapter->rx_queue.toggle = !adapter->rx_queue.toggle; } + +out: + return ret; } static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter) @@ -1084,8 +1089,9 @@ restart_poll: if (rx_flush) ibmveth_flush_buffer(skb->data, length + offset); + if (!ibmveth_rxq_recycle_buffer(adapter)) + kfree_skb(skb); skb = new_skb; - ibmveth_rxq_recycle_buffer(adapter); } else { ibmveth_rxq_harvest_buffer(adapter); skb_reserve(skb, offset); -- cgit v1.2.1 From 284fb68d00c56e971ed01e0b4bac5ddd4d1b74ab Mon Sep 17 00:00:00 2001 From: Alexandre Bounine Date: Thu, 25 Aug 2011 15:59:13 -0700 Subject: rapidio: fix use of non-compatible registers Replace/remove use of RIO v.1.2 registers/bits that are not forward-compatible with newer versions of RapidIO specification. RapidIO specification v.1.3 removed Write Port CSR, Doorbell CSR, Mailbox CSR and Mailbox and Doorbell bits of the PEF CAR. Use of removed (since RIO v.1.3) register bits affects users of currently available 1.3 and 2.x compliant devices who may use not so recent kernel versions. Removing checks for unsupported bits makes corresponding routines compatible with all versions of RapidIO specification. Therefore, backporting makes stable kernel versions compliant with RIO v.1.3 and later as well. Signed-off-by: Alexandre Bounine Cc: Kumar Gala Cc: Matt Porter Cc: Li Yang Cc: Thomas Moll Cc: Chul Kim Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/rionet.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 86ac38c96bcf..3bb131137033 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -80,13 +80,13 @@ static int rionet_capable = 1; */ static struct rio_dev **rionet_active; -#define is_rionet_capable(pef, src_ops, dst_ops) \ - ((pef & RIO_PEF_INB_MBOX) && \ - (pef & RIO_PEF_INB_DOORBELL) && \ +#define is_rionet_capable(src_ops, dst_ops) \ + ((src_ops & RIO_SRC_OPS_DATA_MSG) && \ + (dst_ops & RIO_DST_OPS_DATA_MSG) && \ (src_ops & RIO_SRC_OPS_DOORBELL) && \ (dst_ops & RIO_DST_OPS_DOORBELL)) #define dev_rionet_capable(dev) \ - is_rionet_capable(dev->pef, dev->src_ops, dev->dst_ops) + is_rionet_capable(dev->src_ops, dev->dst_ops) #define RIONET_MAC_MATCH(x) (*(u32 *)x == 0x00010001) #define RIONET_GET_DESTID(x) (*(u16 *)(x + 4)) @@ -282,7 +282,6 @@ static int rionet_open(struct net_device *ndev) { int i, rc = 0; struct rionet_peer *peer, *tmp; - u32 pwdcsr; struct rionet_private *rnet = netdev_priv(ndev); if (netif_msg_ifup(rnet)) @@ -332,13 +331,8 @@ static int rionet_open(struct net_device *ndev) continue; } - /* - * If device has initialized inbound doorbells, - * send a join message - */ - rio_read_config_32(peer->rdev, RIO_WRITE_PORT_CSR, &pwdcsr); - if (pwdcsr & RIO_DOORBELL_AVAIL) - rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN); + /* Send a join message */ + rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN); } out: @@ -492,7 +486,7 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) { int rc = -ENODEV; - u32 lpef, lsrc_ops, ldst_ops; + u32 lsrc_ops, ldst_ops; struct rionet_peer *peer; struct net_device *ndev = NULL; @@ -515,12 +509,11 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) * on later probes */ if (!rionet_check) { - rio_local_read_config_32(rdev->net->hport, RIO_PEF_CAR, &lpef); rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, &lsrc_ops); rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR, &ldst_ops); - if (!is_rionet_capable(lpef, lsrc_ops, ldst_ops)) { + if (!is_rionet_capable(lsrc_ops, ldst_ops)) { printk(KERN_ERR "%s: local device is not network capable\n", DRV_NAME); -- cgit v1.2.1 From 6e6f400f5381e08dc80e1b5a37ed02a081c179d9 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Mon, 22 Aug 2011 21:07:14 +0000 Subject: net/phy: fix DP83865 phy interrupt handler According to the DP83865 datasheet we need to clear the interrupt status bit by writing a 1 to the corresponding bit in INT_CLEAR (2:0 are reserved). Proposed and tested by Thorsten. Signed-off-by: Thorsten Schubert Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/phy/national.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c index 0620ba963508..04bb8fcc0cb5 100644 --- a/drivers/net/phy/national.c +++ b/drivers/net/phy/national.c @@ -25,8 +25,9 @@ /* DP83865 phy identifier values */ #define DP83865_PHY_ID 0x20005c7a -#define DP83865_INT_MASK_REG 0x15 -#define DP83865_INT_MASK_STATUS 0x14 +#define DP83865_INT_STATUS 0x14 +#define DP83865_INT_MASK 0x15 +#define DP83865_INT_CLEAR 0x17 #define DP83865_INT_REMOTE_FAULT 0x0008 #define DP83865_INT_ANE_COMPLETED 0x0010 @@ -68,21 +69,25 @@ static int ns_config_intr(struct phy_device *phydev) int err; if (phydev->interrupts == PHY_INTERRUPT_ENABLED) - err = phy_write(phydev, DP83865_INT_MASK_REG, + err = phy_write(phydev, DP83865_INT_MASK, DP83865_INT_MASK_DEFAULT); else - err = phy_write(phydev, DP83865_INT_MASK_REG, 0); + err = phy_write(phydev, DP83865_INT_MASK, 0); return err; } static int ns_ack_interrupt(struct phy_device *phydev) { - int ret = phy_read(phydev, DP83865_INT_MASK_STATUS); + int ret = phy_read(phydev, DP83865_INT_STATUS); if (ret < 0) return ret; - return 0; + /* Clear the interrupt status bit by writing a “1” + * to the corresponding bit in INT_CLEAR (2:0 are reserved) */ + ret = phy_write(phydev, DP83865_INT_CLEAR, ret & ~0x7); + + return ret; } static void ns_giga_speed_fallback(struct phy_device *phydev, int mode) -- cgit v1.2.1 From 69558eeeaba7d79364bb9ac4743dc1ad209508b7 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 22 Aug 2011 23:26:33 +0000 Subject: net: sh_eth: fix the compile error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following build error: CC drivers/net/sh_eth.o drivers/net/sh_eth.c:1115: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘sh_eth_interrupt’ drivers/net/sh_eth.c: In function ‘sh_eth_open’: drivers/net/sh_eth.c:1387: error: implicit declaration of function ‘request_irq’ drivers/net/sh_eth.c:1387: error: ‘sh_eth_interrupt’ undeclared (first use in this function) drivers/net/sh_eth.c:1387: error: (Each undeclared identifier is reported only once drivers/net/sh_eth.c:1387: error: for each function it appears in.) drivers/net/sh_eth.c:1391: error: ‘IRQF_SHARED’ undeclared (first use in this function) drivers/net/sh_eth.c:1424: error: implicit declaration of function ‘free_irq’ make[2]: *** [drivers/net/sh_eth.o] Error 1 Signed-off-by: Yoshihiro Shimoda Signed-off-by: David S. Miller --- drivers/net/sh_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 190f619e4215..1c1666e99106 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.1 From 6f288cc52f478e6f58d96158e7cd857fedb6d111 Mon Sep 17 00:00:00 2001 From: Abhilash K V Date: Tue, 23 Aug 2011 03:05:48 +0000 Subject: can: ti_hecc: Fix unintialized variable In ti_hecc_xmit(), local variable "data" is not initialized before being used. This initialization got inadvertently removed in the following patch: can: Unify droping of invalid tx skbs and netdev stats Acked-by: Anant Gole Signed-off-by: Abhilash K V Signed-off-by: David S. Miller --- drivers/net/can/ti_hecc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index f7bbde9eb2cb..0b19a17d8178 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -503,9 +503,9 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) spin_unlock_irqrestore(&priv->mbx_lock, flags); /* Prepare mailbox for transmission */ + data = cf->can_dlc | (get_tx_head_prio(priv) << 8); if (cf->can_id & CAN_RTR_FLAG) /* Remote transmission request */ data |= HECC_CANMCF_RTR; - data |= get_tx_head_prio(priv) << 8; hecc_write_mbx(priv, mbxno, HECC_CANMCF, data); if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */ -- cgit v1.2.1 From 86ad47fff97a9e416aadedfe68909b2d9143dc42 Mon Sep 17 00:00:00 2001 From: Abhilash K V Date: Tue, 23 Aug 2011 03:05:57 +0000 Subject: can: ti_hecc: Fix uninitialized spinlock in probe In ti_hecc_probe(), the spinlock priv->mbx_lock is not inited, causing a spinlock lockup BUG. Acked-by: Anant Gole Signed-off-by: Abhilash K V Signed-off-by: David S. Miller --- drivers/net/can/ti_hecc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 0b19a17d8178..a81249246ece 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -923,6 +923,7 @@ static int ti_hecc_probe(struct platform_device *pdev) priv->can.do_get_state = ti_hecc_get_state; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; + spin_lock_init(&priv->mbx_lock); ndev->irq = irq->start; ndev->flags |= IFF_ECHO; platform_set_drvdata(pdev, ndev); -- cgit v1.2.1 From 3d015565f316584139946a1c450d44209beefeb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fran=C3=A7ois=20romieu?= Date: Thu, 25 Aug 2011 05:02:49 +0000 Subject: cassini: init before use in cas_interruptN. Signed-off-by: Francois Romieu Spotted-by: Thomas Jarosch Signed-off-by: David S. Miller --- drivers/net/cassini.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 646c86bcc545..fdb7a1756409 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2452,14 +2452,13 @@ static irqreturn_t cas_interruptN(int irq, void *dev_id) struct net_device *dev = dev_id; struct cas *cp = netdev_priv(dev); unsigned long flags; - int ring; + int ring = (irq == cp->pci_irq_INTC) ? 2 : 3; u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(ring)); /* check for shared irq */ if (status == 0) return IRQ_NONE; - ring = (irq == cp->pci_irq_INTC) ? 2 : 3; spin_lock_irqsave(&cp->lock, flags); if (status & INTR_RX_DONE_ALT) { /* handle rx separately */ #ifdef USE_NAPI -- cgit v1.2.1 From 1c1bdd324cd50ac55f7ebf95ef249d946c6e4361 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 26 Aug 2011 12:42:11 +0530 Subject: ath9k_hw: Fix init mode register regression The commit 172805ad46b78717a738ca5c7908c68f0326d3a9 overwirtes additional clock settings of AR9330 to all AR9300 chips. Cc: stable@kernel.org Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 1baca8e4715d..fcafec0605f4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -671,7 +671,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites); - if (AR_SREV_9300(ah)) + if (AR_SREV_9330(ah)) REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites); if (AR_SREV_9340(ah) && !ah->is_clk_25mhz) -- cgit v1.2.1 From 7c2510120e9b43b0caf32c3786a6ab831f7d9e87 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 26 Aug 2011 17:24:59 +0200 Subject: iwlegacy: fix BUG_ON(info->control.rates[0].idx < 0) When trying to connect to 5GHz we can provide negative index to mac80211 what trigger BUG_ON. Reason of iwl-3945-rs malfunction on 5GHz is unknown and needs further investigation. For now, to do not trigger a bug, correct value and just print WARNING. Address bug: https://bugzilla.redhat.com/show_bug.cgi?id=730653 Reported-and-tested-by: Jan Teichmann Cc: stable@kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/iwl-3945-rs.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c index 977bd2477c6a..164bcae821f8 100644 --- a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c @@ -822,12 +822,15 @@ static void iwl3945_rs_get_rate(void *priv_r, struct ieee80211_sta *sta, out: - rs_sta->last_txrate_idx = index; - if (sband->band == IEEE80211_BAND_5GHZ) - info->control.rates[0].idx = rs_sta->last_txrate_idx - - IWL_FIRST_OFDM_RATE; - else + if (sband->band == IEEE80211_BAND_5GHZ) { + if (WARN_ON_ONCE(index < IWL_FIRST_OFDM_RATE)) + index = IWL_FIRST_OFDM_RATE; + rs_sta->last_txrate_idx = index; + info->control.rates[0].idx = index - IWL_FIRST_OFDM_RATE; + } else { + rs_sta->last_txrate_idx = index; info->control.rates[0].idx = rs_sta->last_txrate_idx; + } IWL_DEBUG_RATE(priv, "leave: %d\n", index); } -- cgit v1.2.1 From 0e4660cbe51276e86dbdab17228733dbcdb49249 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 29 Aug 2011 10:06:14 +0200 Subject: ath9k_hw: fix calibration on 5 ghz ADC calibrations cannot run on 5 GHz with fast clock enabled. They need to be disabled, otherwise they'll hang and IQ mismatch calibration will not be run either. Signed-off-by: Felix Fietkau Reported-by: Adrian Chadd Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_calib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 2d4c0910295b..2d394af82171 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -41,7 +41,8 @@ static bool ar9002_hw_is_cal_supported(struct ath_hw *ah, case ADC_DC_CAL: /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ if (!IS_CHAN_B(chan) && - !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) + !((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) && + IS_CHAN_HT20(chan))) supported = true; break; } -- cgit v1.2.1 From e2faeec2de9e2c73958e6ea6065dde1e8cd6f3a2 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Tue, 30 Aug 2011 20:58:56 -0400 Subject: e1000: Fix driver to be used on PA RISC C8000 workstations The checksum field in the EEPROM on HPPA is really not a checksum but a signature (0x16d6). So allow 0x16d6 as the matching checksum on HPPA systems. This issue is present on longterm/stable kernels, I have verified that this patch is applicable back to at least 2.6.32.y kernels. v2- changed ifdef to use CONFIG_PARISC instead of __hppa__ CC: Guy Martin CC: Rolf Eike Beer CC: Matt Turner Reported-by: Mikulas Patocka Signed-off-by: Jeff Kirsher Acked-by: Jesse Brandeburg Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_hw.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 8545c7aa93eb..a5a89ecb6f36 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -4026,6 +4026,12 @@ s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw) checksum += eeprom_data; } +#ifdef CONFIG_PARISC + /* This is a signature and not a checksum on HP c8000 */ + if ((hw->subsystem_vendor_id == 0x103C) && (eeprom_data == 0x16d6)) + return E1000_SUCCESS; + +#endif if (checksum == (u16) EEPROM_SUM) return E1000_SUCCESS; else { -- cgit v1.2.1 From 1df726ef0a700587a712a3660b2caa8e533c7de9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 5 Sep 2011 08:58:29 +0100 Subject: NET: am79c961: fix race in link status code The link status code operates from a timer, and writes the index register without first taking a lock. A well-placed interrupt between writing the index register and reading the data register could change the index register on us, which will return wrong data. Add the necessary lock. Signed-off-by: Russell King --- drivers/net/arm/am79c961a.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 52fe21e1e2cd..3b1416e3d217 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -308,8 +308,11 @@ static void am79c961_timer(unsigned long data) struct net_device *dev = (struct net_device *)data; struct dev_priv *priv = netdev_priv(dev); unsigned int lnkstat, carrier; + unsigned long flags; + spin_lock_irqsave(&priv->chip_lock, flags); lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST; + spin_unlock_irqrestore(&priv->chip_lock, flags); carrier = netif_carrier_ok(dev); if (lnkstat && !carrier) { -- cgit v1.2.1 From 3401dc6eba788ebc7c14ce51018d775b1c263399 Mon Sep 17 00:00:00 2001 From: George Date: Sat, 3 Sep 2011 10:58:47 -0500 Subject: rtlwifi: rtl8192su: Fix problem connecting to HT-enabled AP The driver fails to connect to 802.11n-enabled APs. The patch fixes Bug #42262. Signed-off-by: George Signed-off-by: Larry Finger Cc: Stable [2.6.39+] Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 906e7aa55bc3..3e52a5496224 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -549,15 +549,16 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, (tcb_desc->rts_use_shortpreamble ? 1 : 0) : (tcb_desc->rts_use_shortgi ? 1 : 0))); if (mac->bw_40) { - if (tcb_desc->packet_bw) { + if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { SET_TX_DESC_DATA_BW(txdesc, 1); SET_TX_DESC_DATA_SC(txdesc, 3); + } else if(rate_flag & IEEE80211_TX_RC_40_MHZ_WIDTH){ + SET_TX_DESC_DATA_BW(txdesc, 1); + SET_TX_DESC_DATA_SC(txdesc, mac->cur_40_prime_sc); } else { SET_TX_DESC_DATA_BW(txdesc, 0); - if (rate_flag & IEEE80211_TX_RC_DUP_DATA) - SET_TX_DESC_DATA_SC(txdesc, - mac->cur_40_prime_sc); - } + SET_TX_DESC_DATA_SC(txdesc, 0); + } } else { SET_TX_DESC_DATA_BW(txdesc, 0); SET_TX_DESC_DATA_SC(txdesc, 0); -- cgit v1.2.1 From bac2555c6d86387132930af4d14cb47c4dd3f4f7 Mon Sep 17 00:00:00 2001 From: George Date: Sat, 3 Sep 2011 10:58:48 -0500 Subject: rtlwifi: Fix problem when switching connections The driver fails to clear encryption keys making it impossible to switch connections. Signed-off-by: George Signed-off-by: Larry Finger Cc: Stable [2.6.39+] Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/core.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 1bdc1aa305c0..04c4e9eb6ee6 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -610,6 +610,11 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, mac->link_state = MAC80211_NOLINK; memset(mac->bssid, 0, 6); + + /* reset sec info */ + rtl_cam_reset_sec_info(hw); + + rtl_cam_reset_all_entry(hw); mac->vendor = PEER_UNKNOWN; RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, @@ -1063,6 +1068,9 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, *or clear all entry here. */ rtl_cam_delete_one_entry(hw, mac_addr, key_idx); + + rtl_cam_reset_sec_info(hw); + break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, -- cgit v1.2.1 From 6a6b3f3e13decfc4b97263a83ea4e80ac8cc89ae Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 9 Sep 2011 10:41:08 +0530 Subject: ath9k: Fix kernel panic on unplugging the device when the device is yanked out ath_pci_remove starts doing the cleanups, unregistering the hardware etc. so we should bail out immediately when we get drv_flush callback from mac80211 when the card is being unplugged. the panic occurs after we had associated to an AP. EIP: 0060:[] EFLAGS: 00010246 CPU: 0 EIP is at ath_reset+0xa0/0x1c0 [ath9k] EAX: 00000000 EBX: 000697c0 ECX: 00000002 EDX: f3c3ccf0 ESI: 00000000 EDI: 00000000 EBP: f43e7b78 ESP: f43e7b50 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Process kworker/u:2 (pid: 182, ti=f43e6000 task=f3c3c7c0 task.ti=f43e6000) Stack: 0000002a 00000000 00000000 003e7b78 0000000f eaaa8500 ffffffea eaaa97c0 eaaaa000 00000001 f43e7ba8 fb315d23 f99e7721 ecece680 eaaac738 eaaa8500 eaaaa020 000000c8 000000c8 00000000 eaaa8d58 eaaa8500 f43e7bd0 fb080b29 Call Trace: [] ath9k_flush+0x103/0x170 [ath9k] [] __ieee80211_recalc_idle+0x2c9/0x400 [mac80211] [] ieee80211_recalc_idle+0x2e/0x60 [mac80211] [] ieee80211_mgd_deauth+0x173/0x210 [mac80211] [] ieee80211_deauth+0x19/0x20 [mac80211] [] __cfg80211_mlme_deauth+0xf3/0x140 [cfg80211] [] ? __mutex_lock_common+0x1f0/0x380 [] __cfg80211_disconnect+0x18d/0x1f0 [cfg80211] [] cfg80211_netdev_notifier_call+0x159/0x5c0 [cfg80211] [] ? packet_notifier+0x174/0x1f0 [] notifier_call_chain+0x82/0xb0 [] raw_notifier_call_chain+0x1f/0x30 [] call_netdevice_notifiers+0x2c/0x60 [] ? trace_hardirqs_on_caller+0xf4/0x180 [] __dev_close_many+0x4c/0xd0 [] dev_close_many+0x6d/0xc0 [] rollback_registered_many+0x93/0x1c0 [] ? trace_hardirqs_on+0xb/0x10 [] unregister_netdevice_many+0x15/0x50 [] ieee80211_remove_interfaces+0x7b/0xb0 [mac80211] [] ieee80211_unregister_hw+0x4b/0x110 [mac80211] [] ath9k_deinit_device+0x3a/0x60 [ath9k] [] ath_pci_remove+0x46/0x90 [ath9k] [] pci_device_remove+0x44/0x100 [] __device_release_driver+0x64/0xb0 [] device_release_driver+0x27/0x40 [] bus_remove_device+0x7b/0xa0 [] device_del+0xf1/0x180 [] device_unregister+0x10/0x20 [] pci_stop_bus_device+0x6e/0x80 [] pci_remove_bus_device+0x12/0xa0 [] pciehp_unconfigure_device+0x89/0x180 [] ? mark_held_locks+0x64/0x100 [] ? __mutex_unlock_slowpath+0xaf/0x140 [] pciehp_disable_slot+0x64/0x1b0 [] pciehp_power_thread+0xd0/0x100 [] ? process_one_work+0x100/0x4d0 [] process_one_work+0x17c/0x4d0 [] ? process_one_work+0x100/0x4d0 [] ? queue_interrupt_event+0xa0/0xa0 [] worker_thread+0x13b/0x320 [] ? trace_hardirqs_on+0xb/0x10 [] ? manage_workers+0x1e0/0x1e0 [] kthread+0x84/0x90 [] ? __init_kthread_worker+0x60/0x60 [] kernel_thread_helper+0x6/0x10 Cc: Rajkumar Manoharan Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6530694a59ae..722967b86cf1 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2303,6 +2303,12 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) mutex_lock(&sc->mutex); cancel_delayed_work_sync(&sc->tx_complete_work); + if (ah->ah_flags & AH_UNPLUGGED) { + ath_dbg(common, ATH_DBG_ANY, "Device has been unplugged!\n"); + mutex_unlock(&sc->mutex); + return; + } + if (sc->sc_flags & SC_OP_INVALID) { ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); mutex_unlock(&sc->mutex); -- cgit v1.2.1 From 456fc37e4519f3f551830ce01c58ddaa35807204 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 Sep 2011 21:08:25 +0200 Subject: iwlagn: fix stack corruption Alexander reported a strange crash in iwlagn that Meenakshi and Wey couldn't reproduce. I just ran into the same issue and tracked it down to stack corruption. This fixes it. The problem was introduced in commit 4b8b99b6e650d0527f3a123744b7459976581d14 Author: Wey-Yi Guy Date: Fri Jul 8 14:29:48 2011 -0700 iwlagn: radio sensor offset in le16 format Cc: Wey-Yi Guy Cc: Meenakshi Venkataraman Reported-by: Alexander Diewald Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index a895a099d086..56211006a182 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -167,7 +167,7 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); - memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(offset_calib)); + memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib)); if (!(cmd.radio_sensor_offset)) cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; -- cgit v1.2.1 From 282cdb325aea4ebbc42ce753b47cc96145eb54bc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 Sep 2011 12:09:10 -0700 Subject: iwlagn: fix command queue timeout If the command queue is constantly busy, which can happen in P2P, the hangcheck timer will frequently find a command in it and will eventually reset the device because nothing sets the timestamp for this queue when commands are processed. Fix this by setting the timestamp when a command completes. Cc: stable@kernel.org #2.6.39, #3.0.0 #3.1.0 Signed-off-by: Johannes Berg SIgned-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index a6b2b1db0b1d..222d410c586e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -771,6 +771,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; + txq->time_stamp = jiffies; + iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); /* Input error checking is done when commands are added to queue. */ -- cgit v1.2.1 From dfacf1387ceb6d7d6df614b18016fd1f347a1996 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 30 Aug 2011 00:08:39 +0000 Subject: bnx2x: fix BRB thresholds for dropless_fc mode Fix the thresholds according to 5778x HW and increase rx_ring size to suit new thresholds in dropless_fc mode. Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x.h | 84 +++++++++++++++++++++++++++++++++++++----- drivers/net/bnx2x/bnx2x_cmn.c | 10 ++--- drivers/net/bnx2x/bnx2x_main.c | 33 ++++++++++++----- 3 files changed, 102 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index c423504a755f..85297326506c 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -315,6 +315,14 @@ union db_prod { u32 raw; }; +/* dropless fc FW/HW related params */ +#define BRB_SIZE(bp) (CHIP_IS_E3(bp) ? 1024 : 512) +#define MAX_AGG_QS(bp) (CHIP_IS_E1(bp) ? \ + ETH_MAX_AGGREGATION_QUEUES_E1 :\ + ETH_MAX_AGGREGATION_QUEUES_E1H_E2) +#define FW_DROP_LEVEL(bp) (3 + MAX_SPQ_PENDING + MAX_AGG_QS(bp)) +#define FW_PREFETCH_CNT 16 +#define DROPLESS_FC_HEADROOM 100 /* MC hsi */ #define BCM_PAGE_SHIFT 12 @@ -331,15 +339,35 @@ union db_prod { /* SGE ring related macros */ #define NUM_RX_SGE_PAGES 2 #define RX_SGE_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_sge)) -#define MAX_RX_SGE_CNT (RX_SGE_CNT - 2) +#define NEXT_PAGE_SGE_DESC_CNT 2 +#define MAX_RX_SGE_CNT (RX_SGE_CNT - NEXT_PAGE_SGE_DESC_CNT) /* RX_SGE_CNT is promised to be a power of 2 */ #define RX_SGE_MASK (RX_SGE_CNT - 1) #define NUM_RX_SGE (RX_SGE_CNT * NUM_RX_SGE_PAGES) #define MAX_RX_SGE (NUM_RX_SGE - 1) #define NEXT_SGE_IDX(x) ((((x) & RX_SGE_MASK) == \ - (MAX_RX_SGE_CNT - 1)) ? (x) + 3 : (x) + 1) + (MAX_RX_SGE_CNT - 1)) ? \ + (x) + 1 + NEXT_PAGE_SGE_DESC_CNT : \ + (x) + 1) #define RX_SGE(x) ((x) & MAX_RX_SGE) +/* + * Number of required SGEs is the sum of two: + * 1. Number of possible opened aggregations (next packet for + * these aggregations will probably consume SGE immidiatelly) + * 2. Rest of BRB blocks divided by 2 (block will consume new SGE only + * after placement on BD for new TPA aggregation) + * + * Takes into account NEXT_PAGE_SGE_DESC_CNT "next" elements on each page + */ +#define NUM_SGE_REQ (MAX_AGG_QS(bp) + \ + (BRB_SIZE(bp) - MAX_AGG_QS(bp)) / 2) +#define NUM_SGE_PG_REQ ((NUM_SGE_REQ + MAX_RX_SGE_CNT - 1) / \ + MAX_RX_SGE_CNT) +#define SGE_TH_LO(bp) (NUM_SGE_REQ + \ + NUM_SGE_PG_REQ * NEXT_PAGE_SGE_DESC_CNT) +#define SGE_TH_HI(bp) (SGE_TH_LO(bp) + DROPLESS_FC_HEADROOM) + /* Manipulate a bit vector defined as an array of u64 */ /* Number of bits in one sge_mask array element */ @@ -551,24 +579,43 @@ struct bnx2x_fastpath { #define NUM_TX_RINGS 16 #define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(union eth_tx_bd_types)) -#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1) +#define NEXT_PAGE_TX_DESC_CNT 1 +#define MAX_TX_DESC_CNT (TX_DESC_CNT - NEXT_PAGE_TX_DESC_CNT) #define NUM_TX_BD (TX_DESC_CNT * NUM_TX_RINGS) #define MAX_TX_BD (NUM_TX_BD - 1) #define MAX_TX_AVAIL (MAX_TX_DESC_CNT * NUM_TX_RINGS - 2) #define NEXT_TX_IDX(x) ((((x) & MAX_TX_DESC_CNT) == \ - (MAX_TX_DESC_CNT - 1)) ? (x) + 2 : (x) + 1) + (MAX_TX_DESC_CNT - 1)) ? \ + (x) + 1 + NEXT_PAGE_TX_DESC_CNT : \ + (x) + 1) #define TX_BD(x) ((x) & MAX_TX_BD) #define TX_BD_POFF(x) ((x) & MAX_TX_DESC_CNT) /* The RX BD ring is special, each bd is 8 bytes but the last one is 16 */ #define NUM_RX_RINGS 8 #define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd)) -#define MAX_RX_DESC_CNT (RX_DESC_CNT - 2) +#define NEXT_PAGE_RX_DESC_CNT 2 +#define MAX_RX_DESC_CNT (RX_DESC_CNT - NEXT_PAGE_RX_DESC_CNT) #define RX_DESC_MASK (RX_DESC_CNT - 1) #define NUM_RX_BD (RX_DESC_CNT * NUM_RX_RINGS) #define MAX_RX_BD (NUM_RX_BD - 1) #define MAX_RX_AVAIL (MAX_RX_DESC_CNT * NUM_RX_RINGS - 2) -#define MIN_RX_AVAIL 128 + +/* dropless fc calculations for BDs + * + * Number of BDs should as number of buffers in BRB: + * Low threshold takes into account NEXT_PAGE_RX_DESC_CNT + * "next" elements on each page + */ +#define NUM_BD_REQ BRB_SIZE(bp) +#define NUM_BD_PG_REQ ((NUM_BD_REQ + MAX_RX_DESC_CNT - 1) / \ + MAX_RX_DESC_CNT) +#define BD_TH_LO(bp) (NUM_BD_REQ + \ + NUM_BD_PG_REQ * NEXT_PAGE_RX_DESC_CNT + \ + FW_DROP_LEVEL(bp)) +#define BD_TH_HI(bp) (BD_TH_LO(bp) + DROPLESS_FC_HEADROOM) + +#define MIN_RX_AVAIL ((bp)->dropless_fc ? BD_TH_HI(bp) + 128 : 128) #define MIN_RX_SIZE_TPA_HW (CHIP_IS_E1(bp) ? \ ETH_MIN_RX_CQES_WITH_TPA_E1 : \ @@ -579,7 +626,9 @@ struct bnx2x_fastpath { MIN_RX_AVAIL)) #define NEXT_RX_IDX(x) ((((x) & RX_DESC_MASK) == \ - (MAX_RX_DESC_CNT - 1)) ? (x) + 3 : (x) + 1) + (MAX_RX_DESC_CNT - 1)) ? \ + (x) + 1 + NEXT_PAGE_RX_DESC_CNT : \ + (x) + 1) #define RX_BD(x) ((x) & MAX_RX_BD) /* @@ -589,14 +638,31 @@ struct bnx2x_fastpath { #define CQE_BD_REL (sizeof(union eth_rx_cqe) / sizeof(struct eth_rx_bd)) #define NUM_RCQ_RINGS (NUM_RX_RINGS * CQE_BD_REL) #define RCQ_DESC_CNT (BCM_PAGE_SIZE / sizeof(union eth_rx_cqe)) -#define MAX_RCQ_DESC_CNT (RCQ_DESC_CNT - 1) +#define NEXT_PAGE_RCQ_DESC_CNT 1 +#define MAX_RCQ_DESC_CNT (RCQ_DESC_CNT - NEXT_PAGE_RCQ_DESC_CNT) #define NUM_RCQ_BD (RCQ_DESC_CNT * NUM_RCQ_RINGS) #define MAX_RCQ_BD (NUM_RCQ_BD - 1) #define MAX_RCQ_AVAIL (MAX_RCQ_DESC_CNT * NUM_RCQ_RINGS - 2) #define NEXT_RCQ_IDX(x) ((((x) & MAX_RCQ_DESC_CNT) == \ - (MAX_RCQ_DESC_CNT - 1)) ? (x) + 2 : (x) + 1) + (MAX_RCQ_DESC_CNT - 1)) ? \ + (x) + 1 + NEXT_PAGE_RCQ_DESC_CNT : \ + (x) + 1) #define RCQ_BD(x) ((x) & MAX_RCQ_BD) +/* dropless fc calculations for RCQs + * + * Number of RCQs should be as number of buffers in BRB: + * Low threshold takes into account NEXT_PAGE_RCQ_DESC_CNT + * "next" elements on each page + */ +#define NUM_RCQ_REQ BRB_SIZE(bp) +#define NUM_RCQ_PG_REQ ((NUM_BD_REQ + MAX_RCQ_DESC_CNT - 1) / \ + MAX_RCQ_DESC_CNT) +#define RCQ_TH_LO(bp) (NUM_RCQ_REQ + \ + NUM_RCQ_PG_REQ * NEXT_PAGE_RCQ_DESC_CNT + \ + FW_DROP_LEVEL(bp)) +#define RCQ_TH_HI(bp) (RCQ_TH_LO(bp) + DROPLESS_FC_HEADROOM) + /* This is needed for determining of last_max */ #define SUB_S16(a, b) (s16)((s16)(a) - (s16)(b)) diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 37e5790681ad..2a33d2433c31 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -987,8 +987,6 @@ void __bnx2x_link_report(struct bnx2x *bp) void bnx2x_init_rx_rings(struct bnx2x *bp) { int func = BP_FUNC(bp); - int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 : - ETH_MAX_AGGREGATION_QUEUES_E1H_E2; u16 ring_prod; int i, j; @@ -1001,7 +999,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) if (!fp->disable_tpa) { /* Fill the per-aggregtion pool */ - for (i = 0; i < max_agg_queues; i++) { + for (i = 0; i < MAX_AGG_QS(bp); i++) { struct bnx2x_agg_info *tpa_info = &fp->tpa_info[i]; struct sw_rx_bd *first_buf = @@ -1041,7 +1039,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) bnx2x_free_rx_sge_range(bp, fp, ring_prod); bnx2x_free_tpa_pool(bp, fp, - max_agg_queues); + MAX_AGG_QS(bp)); fp->disable_tpa = 1; ring_prod = 0; break; @@ -1137,9 +1135,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp) bnx2x_free_rx_bds(fp); if (!fp->disable_tpa) - bnx2x_free_tpa_pool(bp, fp, CHIP_IS_E1(bp) ? - ETH_MAX_AGGREGATION_QUEUES_E1 : - ETH_MAX_AGGREGATION_QUEUES_E1H_E2); + bnx2x_free_tpa_pool(bp, fp, MAX_AGG_QS(bp)); } } diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index f74582a22c68..3f93e8666104 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -2756,8 +2756,14 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp, u16 tpa_agg_size = 0; if (!fp->disable_tpa) { - pause->sge_th_hi = 250; - pause->sge_th_lo = 150; + pause->sge_th_lo = SGE_TH_LO(bp); + pause->sge_th_hi = SGE_TH_HI(bp); + + /* validate SGE ring has enough to cross high threshold */ + WARN_ON(bp->dropless_fc && + pause->sge_th_hi + FW_PREFETCH_CNT > + MAX_RX_SGE_CNT * NUM_RX_SGE_PAGES); + tpa_agg_size = min_t(u32, (min_t(u32, 8, MAX_SKB_FRAGS) * SGE_PAGE_SIZE * PAGES_PER_SGE), 0xffff); @@ -2771,10 +2777,21 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp, /* pause - not for e1 */ if (!CHIP_IS_E1(bp)) { - pause->bd_th_hi = 350; - pause->bd_th_lo = 250; - pause->rcq_th_hi = 350; - pause->rcq_th_lo = 250; + pause->bd_th_lo = BD_TH_LO(bp); + pause->bd_th_hi = BD_TH_HI(bp); + + pause->rcq_th_lo = RCQ_TH_LO(bp); + pause->rcq_th_hi = RCQ_TH_HI(bp); + /* + * validate that rings have enough entries to cross + * high thresholds + */ + WARN_ON(bp->dropless_fc && + pause->bd_th_hi + FW_PREFETCH_CNT > + bp->rx_ring_size); + WARN_ON(bp->dropless_fc && + pause->rcq_th_hi + FW_PREFETCH_CNT > + NUM_RCQ_RINGS * MAX_RCQ_DESC_CNT); pause->pri_map = 1; } @@ -2802,9 +2819,7 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp, * For PF Clients it should be the maximum avaliable number. * VF driver(s) may want to define it to a smaller value. */ - rxq_init->max_tpa_queues = - (CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 : - ETH_MAX_AGGREGATION_QUEUES_E1H_E2); + rxq_init->max_tpa_queues = MAX_AGG_QS(bp); rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT; rxq_init->fw_sb_id = fp->fw_sb_id; -- cgit v1.2.1 From 5f837363457a2280530373267f86092625d15a4d Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 30 Aug 2011 00:08:40 +0000 Subject: bnx2x: decrease print level to debug It may happen every link toggle. Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_stats.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c index 771f6803b238..f5d9b4213cad 100644 --- a/drivers/net/bnx2x/bnx2x_stats.c +++ b/drivers/net/bnx2x/bnx2x_stats.c @@ -710,7 +710,8 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp) break; case MAC_TYPE_NONE: /* unreached */ - BNX2X_ERR("stats updated by DMAE but no MAC active\n"); + DP(BNX2X_MSG_STATS, + "stats updated by DMAE but no MAC active\n"); return -1; default: /* unreached */ -- cgit v1.2.1 From c2188952fc7d2ca54bb8aca1bc502618a7488baf Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Tue, 30 Aug 2011 00:08:41 +0000 Subject: bnx2x: fix rx ring size report Store the size in bp, read from bp when queried. Signed-off-by: Dmitry Kravkov Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_cmn.c | 17 +++++++++++------ drivers/net/bnx2x/bnx2x_ethtool.c | 5 +---- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 2a33d2433c31..c4cbf9736414 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -3091,15 +3091,20 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) struct bnx2x_fastpath *fp = &bp->fp[index]; int ring_size = 0; u8 cos; + int rx_ring_size = 0; /* if rx_ring_size specified - use it */ - int rx_ring_size = bp->rx_ring_size ? bp->rx_ring_size : - MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp); + if (!bp->rx_ring_size) { - /* allocate at least number of buffers required by FW */ - rx_ring_size = max_t(int, bp->disable_tpa ? MIN_RX_SIZE_NONTPA : - MIN_RX_SIZE_TPA, - rx_ring_size); + rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp); + + /* allocate at least number of buffers required by FW */ + rx_ring_size = max_t(int, bp->disable_tpa ? MIN_RX_SIZE_NONTPA : + MIN_RX_SIZE_TPA, rx_ring_size); + + bp->rx_ring_size = rx_ring_size; + } else + rx_ring_size = bp->rx_ring_size; /* Common */ sb = &bnx2x_fp(bp, index, status_blk); diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index 221863059dae..0ceb6c7b1238 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -1310,10 +1310,7 @@ static void bnx2x_get_ringparam(struct net_device *dev, if (bp->rx_ring_size) ering->rx_pending = bp->rx_ring_size; else - if (bp->state == BNX2X_STATE_OPEN && bp->num_queues) - ering->rx_pending = MAX_RX_AVAIL/bp->num_queues; - else - ering->rx_pending = MAX_RX_AVAIL; + ering->rx_pending = MAX_RX_AVAIL; ering->rx_mini_pending = 0; ering->rx_jumbo_pending = 0; -- cgit v1.2.1 From 3395a033a7c2f1a089fae7e89bf108764b59529c Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 30 Aug 2011 00:08:42 +0000 Subject: bnx2x: fix MF for 4-port devices Number of VNs for 4-port devices is 2 instead of 4 Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x.h | 15 +++++++------- drivers/net/bnx2x/bnx2x_main.c | 43 +++++++++++++++++++++++++---------------- drivers/net/bnx2x/bnx2x_stats.c | 4 ++-- 3 files changed, 36 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 85297326506c..2621a1c56358 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -1166,11 +1166,12 @@ struct bnx2x { #define BP_PORT(bp) (bp->pfid & 1) #define BP_FUNC(bp) (bp->pfid) #define BP_ABS_FUNC(bp) (bp->pf_num) -#define BP_E1HVN(bp) (bp->pfid >> 1) -#define BP_VN(bp) (BP_E1HVN(bp)) /*remove when approved*/ -#define BP_L_ID(bp) (BP_E1HVN(bp) << 2) -#define BP_FW_MB_IDX(bp) (BP_PORT(bp) +\ - BP_VN(bp) * ((CHIP_IS_E1x(bp) || (CHIP_MODE_IS_4_PORT(bp))) ? 2 : 1)) +#define BP_VN(bp) ((bp)->pfid >> 1) +#define BP_MAX_VN_NUM(bp) (CHIP_MODE_IS_4_PORT(bp) ? 2 : 4) +#define BP_L_ID(bp) (BP_VN(bp) << 2) +#define BP_FW_MB_IDX_VN(bp, vn) (BP_PORT(bp) +\ + (vn) * ((CHIP_IS_E1x(bp) || (CHIP_MODE_IS_4_PORT(bp))) ? 2 : 1)) +#define BP_FW_MB_IDX(bp) BP_FW_MB_IDX_VN(bp, BP_VN(bp)) struct net_device *dev; struct pci_dev *pdev; @@ -1833,7 +1834,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, #define MAX_DMAE_C_PER_PORT 8 #define INIT_DMAE_C(bp) (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \ - BP_E1HVN(bp)) + BP_VN(bp)) #define PMF_DMAE_C(bp) (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \ E1HVN_MAX) @@ -1859,7 +1860,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, /* must be used on a CID before placing it on a HW ring */ #define HW_CID(bp, x) ((BP_PORT(bp) << 23) | \ - (BP_E1HVN(bp) << BNX2X_SWCID_SHIFT) | \ + (BP_VN(bp) << BNX2X_SWCID_SHIFT) | \ (x)) #define SP_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_spe)) diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 3f93e8666104..9633e9b6853c 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -407,8 +407,8 @@ u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type, opcode |= (DMAE_CMD_SRC_RESET | DMAE_CMD_DST_RESET); opcode |= (BP_PORT(bp) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0); - opcode |= ((BP_E1HVN(bp) << DMAE_CMD_E1HVN_SHIFT) | - (BP_E1HVN(bp) << DMAE_COMMAND_DST_VN_SHIFT)); + opcode |= ((BP_VN(bp) << DMAE_CMD_E1HVN_SHIFT) | + (BP_VN(bp) << DMAE_COMMAND_DST_VN_SHIFT)); opcode |= (DMAE_COM_SET_ERR << DMAE_COMMAND_ERR_POLICY_SHIFT); #ifdef __BIG_ENDIAN @@ -1419,7 +1419,7 @@ static void bnx2x_hc_int_enable(struct bnx2x *bp) if (!CHIP_IS_E1(bp)) { /* init leading/trailing edge */ if (IS_MF(bp)) { - val = (0xee0f | (1 << (BP_E1HVN(bp) + 4))); + val = (0xee0f | (1 << (BP_VN(bp) + 4))); if (bp->port.pmf) /* enable nig and gpio3 attention */ val |= 0x1100; @@ -1471,7 +1471,7 @@ static void bnx2x_igu_int_enable(struct bnx2x *bp) /* init leading/trailing edge */ if (IS_MF(bp)) { - val = (0xee0f | (1 << (BP_E1HVN(bp) + 4))); + val = (0xee0f | (1 << (BP_VN(bp) + 4))); if (bp->port.pmf) /* enable nig and gpio3 attention */ val |= 0x1100; @@ -2287,7 +2287,7 @@ static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp) int vn; bp->vn_weight_sum = 0; - for (vn = VN_0; vn < E1HVN_MAX; vn++) { + for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) { u32 vn_cfg = bp->mf_config[vn]; u32 vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >> FUNC_MF_CFG_MIN_BW_SHIFT) * 100; @@ -2320,12 +2320,18 @@ static void bnx2x_calc_vn_weight_sum(struct bnx2x *bp) CMNG_FLAGS_PER_PORT_FAIRNESS_VN; } +/* returns func by VN for current port */ +static inline int func_by_vn(struct bnx2x *bp, int vn) +{ + return 2 * vn + BP_PORT(bp); +} + static void bnx2x_init_vn_minmax(struct bnx2x *bp, int vn) { struct rate_shaping_vars_per_vn m_rs_vn; struct fairness_vars_per_vn m_fair_vn; u32 vn_cfg = bp->mf_config[vn]; - int func = 2*vn + BP_PORT(bp); + int func = func_by_vn(bp, vn); u16 vn_min_rate, vn_max_rate; int i; @@ -2422,7 +2428,7 @@ void bnx2x_read_mf_cfg(struct bnx2x *bp) * * and there are 2 functions per port */ - for (vn = VN_0; vn < E1HVN_MAX; vn++) { + for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) { int /*abs*/func = n * (2 * vn + BP_PORT(bp)) + BP_PATH(bp); if (func >= E1H_FUNC_MAX) @@ -2454,7 +2460,7 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type) /* calculate and set min-max rate for each vn */ if (bp->port.pmf) - for (vn = VN_0; vn < E1HVN_MAX; vn++) + for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) bnx2x_init_vn_minmax(bp, vn); /* always enable rate shaping and fairness */ @@ -2473,16 +2479,15 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type) static inline void bnx2x_link_sync_notify(struct bnx2x *bp) { - int port = BP_PORT(bp); int func; int vn; /* Set the attention towards other drivers on the same port */ - for (vn = VN_0; vn < E1HVN_MAX; vn++) { - if (vn == BP_E1HVN(bp)) + for (vn = VN_0; vn < BP_MAX_VN_NUM(bp); vn++) { + if (vn == BP_VN(bp)) continue; - func = ((vn << 1) | port); + func = func_by_vn(bp, vn); REG_WR(bp, MISC_REG_AEU_GENERAL_ATTN_0 + (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func)*4, 1); } @@ -2577,7 +2582,7 @@ static void bnx2x_pmf_update(struct bnx2x *bp) bnx2x_dcbx_pmf_update(bp); /* enable nig attention */ - val = (0xff0f | (1 << (BP_E1HVN(bp) + 4))); + val = (0xff0f | (1 << (BP_VN(bp) + 4))); if (bp->common.int_block == INT_BLOCK_HC) { REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val); REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val); @@ -6686,12 +6691,16 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) if (CHIP_MODE_IS_4_PORT(bp)) dsb_idx = BP_FUNC(bp); else - dsb_idx = BP_E1HVN(bp); + dsb_idx = BP_VN(bp); prod_offset = (CHIP_INT_MODE_IS_BC(bp) ? IGU_BC_BASE_DSB_PROD + dsb_idx : IGU_NORM_BASE_DSB_PROD + dsb_idx); + /* + * igu prods come in chunks of E1HVN_MAX (4) - + * does not matters what is the current chip mode + */ for (i = 0; i < (num_segs * E1HVN_MAX); i += E1HVN_MAX) { addr = IGU_REG_PROD_CONS_MEMORY + @@ -7585,7 +7594,7 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode) u32 val; /* The mac address is written to entries 1-4 to preserve entry 0 which is used by the PMF */ - u8 entry = (BP_E1HVN(bp) + 1)*8; + u8 entry = (BP_VN(bp) + 1)*8; val = (mac_addr[0] << 8) | mac_addr[1]; EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry, val); @@ -8792,13 +8801,13 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp) { int pfid = BP_FUNC(bp); - int vn = BP_E1HVN(bp); int igu_sb_id; u32 val; u8 fid, igu_sb_cnt = 0; bp->igu_base_sb = 0xff; if (CHIP_INT_MODE_IS_BC(bp)) { + int vn = BP_VN(bp); igu_sb_cnt = bp->igu_sb_cnt; bp->igu_base_sb = (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn) * FP_SB_MAX_E1x; @@ -9488,7 +9497,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) bp->mf_ov = 0; bp->mf_mode = 0; - vn = BP_E1HVN(bp); + vn = BP_VN(bp); if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) { BNX2X_DEV_INFO("shmem2base 0x%x, size %d, mfcfg offset %d\n", diff --git a/drivers/net/bnx2x/bnx2x_stats.c b/drivers/net/bnx2x/bnx2x_stats.c index f5d9b4213cad..9908f2bbcf73 100644 --- a/drivers/net/bnx2x/bnx2x_stats.c +++ b/drivers/net/bnx2x/bnx2x_stats.c @@ -1392,7 +1392,7 @@ static void bnx2x_port_stats_base_init(struct bnx2x *bp) static void bnx2x_func_stats_base_init(struct bnx2x *bp) { - int vn, vn_max = IS_MF(bp) ? E1HVN_MAX : E1VN_MAX; + int vn, vn_max = IS_MF(bp) ? BP_MAX_VN_NUM(bp) : E1VN_MAX; u32 func_stx; /* sanity */ @@ -1405,7 +1405,7 @@ static void bnx2x_func_stats_base_init(struct bnx2x *bp) func_stx = bp->func_stx; for (vn = VN_0; vn < vn_max; vn++) { - int mb_idx = CHIP_IS_E1x(bp) ? 2*vn + BP_PORT(bp) : vn; + int mb_idx = BP_FW_MB_IDX_VN(bp, vn); bp->func_stx = SHMEM_RD(bp, func_mb[mb_idx].fw_mb_param); bnx2x_func_stats_init(bp); -- cgit v1.2.1 From 7a06a122322c89544774e789a11aa671423e9362 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 30 Aug 2011 00:08:43 +0000 Subject: bnx2x: don't reset device while reading its configuration. Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_main.c | 24 +++++++++++++++--------- drivers/net/bnx2x/bnx2x_reg.h | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 9633e9b6853c..00dc8f0fc3af 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -5822,7 +5822,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp) * take the UNDI lock to protect undi_unload flow from accessing * registers while we're resetting the chip */ - bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET); bnx2x_reset_common(bp); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff); @@ -5834,7 +5834,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp) } REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, val); - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); bnx2x_init_block(bp, BLOCK_MISC, PHASE_COMMON); @@ -8570,10 +8570,12 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) /* Check if there is any driver already loaded */ val = REG_RD(bp, MISC_REG_UNPREPARED); if (val == 0x1) { - /* Check if it is the UNDI driver + + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET); + /* + * Check if it is the UNDI driver * UNDI driver initializes CID offset for normal bell to 0x7 */ - bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); val = REG_RD(bp, DORQ_REG_NORM_CID_OFST); if (val == 0x7) { u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; @@ -8611,9 +8613,6 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) bnx2x_fw_command(bp, reset_code, 0); } - /* now it's safe to release the lock */ - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); - bnx2x_undi_int_disable(bp); port = BP_PORT(bp); @@ -8663,8 +8662,10 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) bp->fw_seq = (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK); - } else - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); + } + + /* now it's safe to release the lock */ + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); } } @@ -9440,6 +9441,10 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) bp->igu_base_sb = 0; } else { bp->common.int_block = INT_BLOCK_IGU; + + /* do not allow device reset during IGU info preocessing */ + bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET); + val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION); if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) { @@ -9471,6 +9476,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) bnx2x_get_igu_cam_info(bp); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); } /* diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index 40266c14e6dc..dac217d478f2 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h @@ -5766,7 +5766,7 @@ #define HW_LOCK_RESOURCE_RECOVERY_LEADER_0 8 #define HW_LOCK_RESOURCE_RECOVERY_LEADER_1 9 #define HW_LOCK_RESOURCE_SPIO 2 -#define HW_LOCK_RESOURCE_UNDI 5 +#define HW_LOCK_RESOURCE_RESET 5 #define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT (0x1<<4) #define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR (0x1<<5) #define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (0x1<<18) -- cgit v1.2.1 From 0735f2fc8c49f1fbbbb245d038582922984ed3d5 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 30 Aug 2011 00:08:44 +0000 Subject: bnx2x: init fw_seq after undi_unload is done Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 00dc8f0fc3af..94382a78c951 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -9623,13 +9623,6 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) /* port info */ bnx2x_get_port_hwinfo(bp); - if (!BP_NOMCP(bp)) { - bp->fw_seq = - (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & - DRV_MSG_SEQ_NUMBER_MASK); - BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq); - } - /* Get MAC addresses */ bnx2x_get_mac_hwinfo(bp); @@ -9795,6 +9788,14 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) if (!BP_NOMCP(bp)) bnx2x_undi_unload(bp); + /* init fw_seq after undi_unload! */ + if (!BP_NOMCP(bp)) { + bp->fw_seq = + (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & + DRV_MSG_SEQ_NUMBER_MASK); + BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq); + } + if (CHIP_REV_IS_FPGA(bp)) dev_err(&bp->pdev->dev, "FPGA detected\n"); -- cgit v1.2.1 From a5c53dbcde9a156e8303acc6ecb2296bf609fe38 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Tue, 30 Aug 2011 00:08:45 +0000 Subject: bnx2x: don't access removed registers on 57712 and above Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 94382a78c951..0b68d02fe455 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -10290,17 +10290,21 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, /* clean indirect addresses */ pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, PCICFG_VENDOR_ID_OFFSET); - /* Clean the following indirect addresses for all functions since it + /* + * Clean the following indirect addresses for all functions since it * is not used by the driver. */ REG_WR(bp, PXP2_REG_PGL_ADDR_88_F0, 0); REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F0, 0); REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0); REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0, 0); - REG_WR(bp, PXP2_REG_PGL_ADDR_88_F1, 0); - REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F1, 0); - REG_WR(bp, PXP2_REG_PGL_ADDR_90_F1, 0); - REG_WR(bp, PXP2_REG_PGL_ADDR_94_F1, 0); + + if (CHIP_IS_E1x(bp)) { + REG_WR(bp, PXP2_REG_PGL_ADDR_88_F1, 0); + REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F1, 0); + REG_WR(bp, PXP2_REG_PGL_ADDR_90_F1, 0); + REG_WR(bp, PXP2_REG_PGL_ADDR_94_F1, 0); + } /* * Enable internal target-read (in case we are probed after PF FLR). -- cgit v1.2.1 From 150966ad56291776a1f3fed86000a027e0794922 Mon Sep 17 00:00:00 2001 From: Ariel Elior Date: Tue, 30 Aug 2011 00:08:46 +0000 Subject: bnx2x: Fix for a host coalescing bug which impared latency. Seperated Rx and Tx coalescing to different state machines. Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x.h | 25 +++++++++---------------- drivers/net/bnx2x/bnx2x_main.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 2621a1c56358..e46df5331c55 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -751,24 +751,17 @@ struct bnx2x_fastpath { #define FP_CSB_FUNC_OFF \ offsetof(struct cstorm_status_block_c, func) -#define HC_INDEX_TOE_RX_CQ_CONS 0 /* Formerly Ustorm TOE CQ index */ - /* (HC_INDEX_U_TOE_RX_CQ_CONS) */ -#define HC_INDEX_ETH_RX_CQ_CONS 1 /* Formerly Ustorm ETH CQ index */ - /* (HC_INDEX_U_ETH_RX_CQ_CONS) */ -#define HC_INDEX_ETH_RX_BD_CONS 2 /* Formerly Ustorm ETH BD index */ - /* (HC_INDEX_U_ETH_RX_BD_CONS) */ - -#define HC_INDEX_TOE_TX_CQ_CONS 4 /* Formerly Cstorm TOE CQ index */ - /* (HC_INDEX_C_TOE_TX_CQ_CONS) */ -#define HC_INDEX_ETH_TX_CQ_CONS_COS0 5 /* Formerly Cstorm ETH CQ index */ - /* (HC_INDEX_C_ETH_TX_CQ_CONS) */ -#define HC_INDEX_ETH_TX_CQ_CONS_COS1 6 /* Formerly Cstorm ETH CQ index */ - /* (HC_INDEX_C_ETH_TX_CQ_CONS) */ -#define HC_INDEX_ETH_TX_CQ_CONS_COS2 7 /* Formerly Cstorm ETH CQ index */ - /* (HC_INDEX_C_ETH_TX_CQ_CONS) */ +#define HC_INDEX_ETH_RX_CQ_CONS 1 -#define HC_INDEX_ETH_FIRST_TX_CQ_CONS HC_INDEX_ETH_TX_CQ_CONS_COS0 +#define HC_INDEX_OOO_TX_CQ_CONS 4 + +#define HC_INDEX_ETH_TX_CQ_CONS_COS0 5 + +#define HC_INDEX_ETH_TX_CQ_CONS_COS1 6 +#define HC_INDEX_ETH_TX_CQ_CONS_COS2 7 + +#define HC_INDEX_ETH_FIRST_TX_CQ_CONS HC_INDEX_ETH_TX_CQ_CONS_COS0 #define BNX2X_RX_SB_INDEX \ (&fp->sb_index_values[HC_INDEX_ETH_RX_CQ_CONS]) diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 0b68d02fe455..c027e9341a1a 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -4828,6 +4828,37 @@ void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm, hc_sm->time_to_expire = 0xFFFFFFFF; } + +/* allocates state machine ids. */ +static inline +void bnx2x_map_sb_state_machines(struct hc_index_data *index_data) +{ + /* zero out state machine indices */ + /* rx indices */ + index_data[HC_INDEX_ETH_RX_CQ_CONS].flags &= ~HC_INDEX_DATA_SM_ID; + + /* tx indices */ + index_data[HC_INDEX_OOO_TX_CQ_CONS].flags &= ~HC_INDEX_DATA_SM_ID; + index_data[HC_INDEX_ETH_TX_CQ_CONS_COS0].flags &= ~HC_INDEX_DATA_SM_ID; + index_data[HC_INDEX_ETH_TX_CQ_CONS_COS1].flags &= ~HC_INDEX_DATA_SM_ID; + index_data[HC_INDEX_ETH_TX_CQ_CONS_COS2].flags &= ~HC_INDEX_DATA_SM_ID; + + /* map indices */ + /* rx indices */ + index_data[HC_INDEX_ETH_RX_CQ_CONS].flags |= + SM_RX_ID << HC_INDEX_DATA_SM_ID_SHIFT; + + /* tx indices */ + index_data[HC_INDEX_OOO_TX_CQ_CONS].flags |= + SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT; + index_data[HC_INDEX_ETH_TX_CQ_CONS_COS0].flags |= + SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT; + index_data[HC_INDEX_ETH_TX_CQ_CONS_COS1].flags |= + SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT; + index_data[HC_INDEX_ETH_TX_CQ_CONS_COS2].flags |= + SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT; +} + static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, u8 vf_valid, int fw_sb_id, int igu_sb_id) { @@ -4859,6 +4890,7 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, hc_sm_p = sb_data_e2.common.state_machine; sb_data_p = (u32 *)&sb_data_e2; data_size = sizeof(struct hc_status_block_data_e2)/sizeof(u32); + bnx2x_map_sb_state_machines(sb_data_e2.index_data); } else { memset(&sb_data_e1x, 0, sizeof(struct hc_status_block_data_e1x)); @@ -4873,6 +4905,7 @@ static void bnx2x_init_sb(struct bnx2x *bp, dma_addr_t mapping, int vfid, hc_sm_p = sb_data_e1x.common.state_machine; sb_data_p = (u32 *)&sb_data_e1x; data_size = sizeof(struct hc_status_block_data_e1x)/sizeof(u32); + bnx2x_map_sb_state_machines(sb_data_e1x.index_data); } bnx2x_setup_ndsb_state_machine(&hc_sm_p[SM_RX_ID], -- cgit v1.2.1 From 02009afc223aae43b8e18918fc816e4520791537 Mon Sep 17 00:00:00 2001 From: Kavan Smith Date: Wed, 31 Aug 2011 05:12:05 +0000 Subject: ipheth: iPhone 4 Verizon CDMA USB Product ID add Add USB product ID for iPhone 4 CDMA Verizon Tested on at least 2 devices Signed-off-by: Kavan Smith Signed-off-by: David S. Miller --- drivers/net/usb/ipheth.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 15772b1b6a91..13c1f044b40d 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -59,6 +59,7 @@ #define USB_PRODUCT_IPHONE_3G 0x1292 #define USB_PRODUCT_IPHONE_3GS 0x1294 #define USB_PRODUCT_IPHONE_4 0x1297 +#define USB_PRODUCT_IPHONE_4_VZW 0x129c #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -98,6 +99,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); -- cgit v1.2.1 From c482e6c064613b3fd40758ef6c33318462b83789 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 7 Sep 2011 00:47:49 +0000 Subject: bnx2x: Fix ETS bandwidth ETS bandwidth of 0% is not allowed by driver, so provide alternative HW configuration for this case. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_link.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index d45b1555a602..9d381db16516 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -778,9 +778,9 @@ static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp, { u32 nig_reg_adress_crd_weight = 0; u32 pbf_reg_adress_crd_weight = 0; - /* Calculate and set BW for this COS*/ - const u32 cos_bw_nig = (bw * min_w_val_nig) / total_bw; - const u32 cos_bw_pbf = (bw * min_w_val_pbf) / total_bw; + /* Calculate and set BW for this COS - use 1 instead of 0 for BW */ + const u32 cos_bw_nig = ((bw ? bw : 1) * min_w_val_nig) / total_bw; + const u32 cos_bw_pbf = ((bw ? bw : 1) * min_w_val_pbf) / total_bw; switch (cos_entry) { case 0: @@ -852,18 +852,12 @@ static int bnx2x_ets_e3b0_get_total_bw( /* Calculate total BW requested */ for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) { if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) { - - if (0 == ets_params->cos[cos_idx].params.bw_params.bw) { - DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config BW" - "was set to 0\n"); - return -EINVAL; + *total_bw += + ets_params->cos[cos_idx].params.bw_params.bw; } - *total_bw += - ets_params->cos[cos_idx].params.bw_params.bw; - } } - /*Check taotl BW is valid */ + /* Check total BW is valid */ if ((100 != *total_bw) || (0 == *total_bw)) { if (0 == *total_bw) { DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config toatl BW" -- cgit v1.2.1 From 6b1f3900fc0909fbf3bd672242378015f76b3df8 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 7 Sep 2011 00:47:54 +0000 Subject: bnx2x: Enable FEC for 57810-KR Enable FEC(Forward Error Correction) for 57810-KR to reduce link errors. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_link.c | 6 ++++++ drivers/net/bnx2x/bnx2x_reg.h | 3 +++ 2 files changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index 9d381db16516..f7a7ac3e889c 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -3624,6 +3624,12 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16); + /* Advertised and set FEC (Forward Error Correction) */ + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, + MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2, + (MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY | + MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ)); + /* Enable CL37 BAM */ if (REG_RD(bp, params->shmem_base + offsetof(struct shmem_region, dev_info. diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index dac217d478f2..057738623ba4 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h @@ -6853,6 +6853,9 @@ Theotherbitsarereservedandshouldbezero*/ #define MDIO_WC_REG_IEEE0BLK_AUTONEGNP 0x7 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT0 0x10 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1 0x11 +#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2 0x12 +#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY 0x4000 +#define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ 0x8000 #define MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150 0x96 #define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL 0x8000 #define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1 0x800e -- cgit v1.2.1 From 0582242049c67d59c3a95cd1cba8995fa955c858 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 7 Sep 2011 00:47:58 +0000 Subject: bnx2x: Remove fiber remote fault detection Remove remote fault detection as a tactic retreat due to link issues involved with it. Once issue is resolved, this feature will be restored again. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_link.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index f7a7ac3e889c..db5913da5527 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -10638,8 +10638,7 @@ static struct bnx2x_phy phy_warpcore = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, .addr = 0xff, .def_md_devad = 0, - .flags = (FLAGS_HW_LOCK_REQUIRED | - FLAGS_TX_ERROR_CHECK), + .flags = FLAGS_HW_LOCK_REQUIRED, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, @@ -10765,8 +10764,7 @@ static struct bnx2x_phy phy_8706 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706, .addr = 0xff, .def_md_devad = 0, - .flags = (FLAGS_INIT_XGXS_FIRST | - FLAGS_TX_ERROR_CHECK), + .flags = FLAGS_INIT_XGXS_FIRST, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, @@ -10797,8 +10795,7 @@ static struct bnx2x_phy phy_8726 = { .addr = 0xff, .def_md_devad = 0, .flags = (FLAGS_HW_LOCK_REQUIRED | - FLAGS_INIT_XGXS_FIRST | - FLAGS_TX_ERROR_CHECK), + FLAGS_INIT_XGXS_FIRST), .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, @@ -10829,8 +10826,7 @@ static struct bnx2x_phy phy_8727 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727, .addr = 0xff, .def_md_devad = 0, - .flags = (FLAGS_FAN_FAILURE_DET_REQ | - FLAGS_TX_ERROR_CHECK), + .flags = FLAGS_FAN_FAILURE_DET_REQ, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, -- cgit v1.2.1 From 4d7e25d6cc4312b1f949123fea7026fd56441513 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 7 Sep 2011 00:48:03 +0000 Subject: bnx2x: Fix XMAC loopback test Change XMAC loopback type from CORE LOCAL to LINE LOCAL for the BCM578xx due to intermittent problem with the loopback with this configuration. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_link.c | 2 +- drivers/net/bnx2x/bnx2x_reg.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index db5913da5527..342807585c2b 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -1720,7 +1720,7 @@ static int bnx2x_xmac_enable(struct link_params *params, /* Check loopback mode */ if (lb) - val |= XMAC_CTRL_REG_CORE_LOCAL_LPBK; + val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK; REG_WR(bp, xmac_base + XMAC_REG_CTRL, val); bnx2x_set_xumac_nig(params, ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1); diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index 057738623ba4..750e8445dac4 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h @@ -5320,7 +5320,7 @@ #define XCM_REG_XX_OVFL_EVNT_ID 0x20058 #define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS (0x1<<0) #define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS (0x1<<1) -#define XMAC_CTRL_REG_CORE_LOCAL_LPBK (0x1<<3) +#define XMAC_CTRL_REG_LINE_LOCAL_LPBK (0x1<<2) #define XMAC_CTRL_REG_RX_EN (0x1<<1) #define XMAC_CTRL_REG_SOFT_RESET (0x1<<6) #define XMAC_CTRL_REG_TX_EN (0x1<<0) -- cgit v1.2.1 From ab505dec96340946079d1288f49041bea9f259ff Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 7 Sep 2011 00:48:06 +0000 Subject: bnx2x: Fix 578xx link LED Fix 1G link LED for the BCM578xx-SFI/KR. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_link.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index 342807585c2b..ba15bdc5a1a9 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c @@ -5924,7 +5924,7 @@ int bnx2x_set_led(struct link_params *params, (tmp | EMAC_LED_OVERRIDE)); /* * return here without enabling traffic - * LED blink andsetting rate in ON mode. + * LED blink and setting rate in ON mode. * In oper mode, enabling LED blink * and setting rate is needed. */ @@ -5936,7 +5936,11 @@ int bnx2x_set_led(struct link_params *params, * This is a work-around for HW issue found when link * is up in CL73 */ - REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1); + if ((!CHIP_IS_E3(bp)) || + (CHIP_IS_E3(bp) && + mode == LED_MODE_ON)) + REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1); + if (CHIP_IS_E1x(bp) || CHIP_IS_E2(bp) || (mode == LED_MODE_ON)) -- cgit v1.2.1 From 8d661637407963d1990e53c36d53ace123219da3 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 7 Sep 2011 00:48:11 +0000 Subject: bnx2x: Fix ethtool advertisement Enable changing advertisement settings via ethtool. Signed-off-by: Yaniv Rosner Signed-off-by: Eilon Greenstein Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/bnx2x/bnx2x_ethtool.c | 43 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index 0ceb6c7b1238..cf3e47914dd7 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c @@ -363,13 +363,50 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) } /* advertise the requested speed and duplex if supported */ - cmd->advertising &= bp->port.supported[cfg_idx]; + if (cmd->advertising & ~(bp->port.supported[cfg_idx])) { + DP(NETIF_MSG_LINK, "Advertisement parameters " + "are not supported\n"); + return -EINVAL; + } bp->link_params.req_line_speed[cfg_idx] = SPEED_AUTO_NEG; - bp->link_params.req_duplex[cfg_idx] = DUPLEX_FULL; - bp->port.advertising[cfg_idx] |= (ADVERTISED_Autoneg | + bp->link_params.req_duplex[cfg_idx] = cmd->duplex; + bp->port.advertising[cfg_idx] = (ADVERTISED_Autoneg | cmd->advertising); + if (cmd->advertising) { + + bp->link_params.speed_cap_mask[cfg_idx] = 0; + if (cmd->advertising & ADVERTISED_10baseT_Half) { + bp->link_params.speed_cap_mask[cfg_idx] |= + PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF; + } + if (cmd->advertising & ADVERTISED_10baseT_Full) + bp->link_params.speed_cap_mask[cfg_idx] |= + PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL; + if (cmd->advertising & ADVERTISED_100baseT_Full) + bp->link_params.speed_cap_mask[cfg_idx] |= + PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL; + + if (cmd->advertising & ADVERTISED_100baseT_Half) { + bp->link_params.speed_cap_mask[cfg_idx] |= + PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF; + } + if (cmd->advertising & ADVERTISED_1000baseT_Half) { + bp->link_params.speed_cap_mask[cfg_idx] |= + PORT_HW_CFG_SPEED_CAPABILITY_D0_1G; + } + if (cmd->advertising & (ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseKX_Full)) + bp->link_params.speed_cap_mask[cfg_idx] |= + PORT_HW_CFG_SPEED_CAPABILITY_D0_1G; + + if (cmd->advertising & (ADVERTISED_10000baseT_Full | + ADVERTISED_10000baseKX4_Full | + ADVERTISED_10000baseKR_Full)) + bp->link_params.speed_cap_mask[cfg_idx] |= + PORT_HW_CFG_SPEED_CAPABILITY_D0_10G; + } } else { /* forced speed */ /* advertise the requested speed and duplex if supported */ switch (speed) { -- cgit v1.2.1 From 86c432ca5d6da90a26ac8d3e680f2268b502d9c5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 1 Sep 2011 12:09:29 +0000 Subject: Revert "sfc: Use write-combining to reduce TX latency" and follow-ups This reverts commits 65f0b417dee94f779ce9b77102b7d73c93723b39, d88d6b05fee3cc78e5b0273eb58c31201dcc6b76, fcfa060468a4edcf776f0c1211d826d5de1668c1, 747df2258b1b9a2e25929ef496262c339c380009 and 867955f5682f7157fdafe8670804b9f8ea077bc7. Depending on the processor model, write-combining may result in reordering that the NIC will not tolerate. This typically results in a DMA error event and reset by the driver, logged as: sfc 0000:0e:00.0: eth2: TX DMA Q reports TX_EV_PKT_ERR. sfc 0000:0e:00.0: eth2: resetting (ALL) Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/efx.c | 18 ++--------------- drivers/net/sfc/io.h | 15 ++++---------- drivers/net/sfc/mcdi.c | 46 ++++++++++++++++--------------------------- drivers/net/sfc/nic.c | 7 ------- drivers/net/sfc/nic.h | 2 -- drivers/net/sfc/siena.c | 25 ++++------------------- drivers/net/sfc/workarounds.h | 2 -- 7 files changed, 27 insertions(+), 88 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index faca764aa21b..b59abc706d93 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1050,7 +1050,6 @@ static int efx_init_io(struct efx_nic *efx) { struct pci_dev *pci_dev = efx->pci_dev; dma_addr_t dma_mask = efx->type->max_dma_mask; - bool use_wc; int rc; netif_dbg(efx, probe, efx->net_dev, "initialising I/O\n"); @@ -1101,21 +1100,8 @@ static int efx_init_io(struct efx_nic *efx) rc = -EIO; goto fail3; } - - /* bug22643: If SR-IOV is enabled then tx push over a write combined - * mapping is unsafe. We need to disable write combining in this case. - * MSI is unsupported when SR-IOV is enabled, and the firmware will - * have removed the MSI capability. So write combining is safe if - * there is an MSI capability. - */ - use_wc = (!EFX_WORKAROUND_22643(efx) || - pci_find_capability(pci_dev, PCI_CAP_ID_MSI)); - if (use_wc) - efx->membase = ioremap_wc(efx->membase_phys, - efx->type->mem_map_size); - else - efx->membase = ioremap_nocache(efx->membase_phys, - efx->type->mem_map_size); + efx->membase = ioremap_nocache(efx->membase_phys, + efx->type->mem_map_size); if (!efx->membase) { netif_err(efx, probe, efx->net_dev, "could not map memory BAR at %llx+%x\n", diff --git a/drivers/net/sfc/io.h b/drivers/net/sfc/io.h index cc978803d484..dc45110b2456 100644 --- a/drivers/net/sfc/io.h +++ b/drivers/net/sfc/io.h @@ -48,9 +48,9 @@ * replacing the low 96 bits with zero does not affect functionality. * - If the host writes to the last dword address of such a register * (i.e. the high 32 bits) the underlying register will always be - * written. If the collector and the current write together do not - * provide values for all 128 bits of the register, the low 96 bits - * will be written as zero. + * written. If the collector does not hold values for the low 96 + * bits of the register, they will be written as zero. Writing to + * the last qword does not have this effect and must not be done. * - If the host writes to the address of any other part of such a * register while the collector already holds values for some other * register, the write is discarded and the collector maintains its @@ -103,7 +103,6 @@ static inline void efx_writeo(struct efx_nic *efx, efx_oword_t *value, _efx_writed(efx, value->u32[2], reg + 8); _efx_writed(efx, value->u32[3], reg + 12); #endif - wmb(); mmiowb(); spin_unlock_irqrestore(&efx->biu_lock, flags); } @@ -126,7 +125,6 @@ static inline void efx_sram_writeq(struct efx_nic *efx, void __iomem *membase, __raw_writel((__force u32)value->u32[0], membase + addr); __raw_writel((__force u32)value->u32[1], membase + addr + 4); #endif - wmb(); mmiowb(); spin_unlock_irqrestore(&efx->biu_lock, flags); } @@ -141,7 +139,6 @@ static inline void efx_writed(struct efx_nic *efx, efx_dword_t *value, /* No lock required */ _efx_writed(efx, value->u32[0], reg); - wmb(); } /* Read a 128-bit CSR, locking as appropriate. */ @@ -152,7 +149,6 @@ static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value, spin_lock_irqsave(&efx->biu_lock, flags); value->u32[0] = _efx_readd(efx, reg + 0); - rmb(); value->u32[1] = _efx_readd(efx, reg + 4); value->u32[2] = _efx_readd(efx, reg + 8); value->u32[3] = _efx_readd(efx, reg + 12); @@ -175,7 +171,6 @@ static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase, value->u64[0] = (__force __le64)__raw_readq(membase + addr); #else value->u32[0] = (__force __le32)__raw_readl(membase + addr); - rmb(); value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4); #endif spin_unlock_irqrestore(&efx->biu_lock, flags); @@ -242,14 +237,12 @@ static inline void _efx_writeo_page(struct efx_nic *efx, efx_oword_t *value, #ifdef EFX_USE_QWORD_IO _efx_writeq(efx, value->u64[0], reg + 0); - _efx_writeq(efx, value->u64[1], reg + 8); #else _efx_writed(efx, value->u32[0], reg + 0); _efx_writed(efx, value->u32[1], reg + 4); +#endif _efx_writed(efx, value->u32[2], reg + 8); _efx_writed(efx, value->u32[3], reg + 12); -#endif - wmb(); } #define efx_writeo_page(efx, value, reg, page) \ _efx_writeo_page(efx, value, \ diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index 3dd45ed61f0a..81a425397468 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c @@ -50,20 +50,6 @@ static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) return &nic_data->mcdi; } -static inline void -efx_mcdi_readd(struct efx_nic *efx, efx_dword_t *value, unsigned reg) -{ - struct siena_nic_data *nic_data = efx->nic_data; - value->u32[0] = (__force __le32)__raw_readl(nic_data->mcdi_smem + reg); -} - -static inline void -efx_mcdi_writed(struct efx_nic *efx, const efx_dword_t *value, unsigned reg) -{ - struct siena_nic_data *nic_data = efx->nic_data; - __raw_writel((__force u32)value->u32[0], nic_data->mcdi_smem + reg); -} - void efx_mcdi_init(struct efx_nic *efx) { struct efx_mcdi_iface *mcdi; @@ -84,8 +70,8 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd, const u8 *inbuf, size_t inlen) { struct efx_mcdi_iface *mcdi = efx_mcdi(efx); - unsigned pdu = MCDI_PDU(efx); - unsigned doorbell = MCDI_DOORBELL(efx); + unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); + unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx); unsigned int i; efx_dword_t hdr; u32 xflags, seqno; @@ -106,28 +92,29 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd, MCDI_HEADER_SEQ, seqno, MCDI_HEADER_XFLAGS, xflags); - efx_mcdi_writed(efx, &hdr, pdu); + efx_writed(efx, &hdr, pdu); for (i = 0; i < inlen; i += 4) - efx_mcdi_writed(efx, (const efx_dword_t *)(inbuf + i), - pdu + 4 + i); + _efx_writed(efx, *((__le32 *)(inbuf + i)), pdu + 4 + i); + + /* Ensure the payload is written out before the header */ + wmb(); /* ring the doorbell with a distinctive value */ - EFX_POPULATE_DWORD_1(hdr, EFX_DWORD_0, 0x45789abc); - efx_mcdi_writed(efx, &hdr, doorbell); + _efx_writed(efx, (__force __le32) 0x45789abc, doorbell); } static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) { struct efx_mcdi_iface *mcdi = efx_mcdi(efx); - unsigned int pdu = MCDI_PDU(efx); + unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); int i; BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); BUG_ON(outlen & 3 || outlen >= 0x100); for (i = 0; i < outlen; i += 4) - efx_mcdi_readd(efx, (efx_dword_t *)(outbuf + i), pdu + 4 + i); + *((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i); } static int efx_mcdi_poll(struct efx_nic *efx) @@ -135,7 +122,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) struct efx_mcdi_iface *mcdi = efx_mcdi(efx); unsigned int time, finish; unsigned int respseq, respcmd, error; - unsigned int pdu = MCDI_PDU(efx); + unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); unsigned int rc, spins; efx_dword_t reg; @@ -161,7 +148,8 @@ static int efx_mcdi_poll(struct efx_nic *efx) time = get_seconds(); - efx_mcdi_readd(efx, ®, pdu); + rmb(); + efx_readd(efx, ®, pdu); /* All 1's indicates that shared memory is in reset (and is * not a valid header). Wait for it to come out reset before @@ -188,7 +176,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) respseq, mcdi->seqno); rc = EIO; } else if (error) { - efx_mcdi_readd(efx, ®, pdu + 4); + efx_readd(efx, ®, pdu + 4); switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) { #define TRANSLATE_ERROR(name) \ case MC_CMD_ERR_ ## name: \ @@ -222,21 +210,21 @@ out: /* Test and clear MC-rebooted flag for this port/function */ int efx_mcdi_poll_reboot(struct efx_nic *efx) { - unsigned int addr = MCDI_REBOOT_FLAG(efx); + unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_REBOOT_FLAG(efx); efx_dword_t reg; uint32_t value; if (efx_nic_rev(efx) < EFX_REV_SIENA_A0) return false; - efx_mcdi_readd(efx, ®, addr); + efx_readd(efx, ®, addr); value = EFX_DWORD_FIELD(reg, EFX_DWORD_0); if (value == 0) return 0; EFX_ZERO_DWORD(reg); - efx_mcdi_writed(efx, ®, addr); + efx_writed(efx, ®, addr); if (value == MC_STATUS_DWORD_ASSERT) return -EINTR; diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index bafa23a6874c..3edfbaf5f022 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c @@ -1936,13 +1936,6 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf) size = min_t(size_t, table->step, 16); - if (table->offset >= efx->type->mem_map_size) { - /* No longer mapped; return dummy data */ - memcpy(buf, "\xde\xc0\xad\xde", 4); - buf += table->rows * size; - continue; - } - for (i = 0; i < table->rows; i++) { switch (table->step) { case 4: /* 32-bit register or SRAM */ diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h index 4bd1f2839dfe..7443f99c977f 100644 --- a/drivers/net/sfc/nic.h +++ b/drivers/net/sfc/nic.h @@ -143,12 +143,10 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx) /** * struct siena_nic_data - Siena NIC state * @mcdi: Management-Controller-to-Driver Interface - * @mcdi_smem: MCDI shared memory mapping. The mapping is always uncacheable. * @wol_filter_id: Wake-on-LAN packet filter id */ struct siena_nic_data { struct efx_mcdi_iface mcdi; - void __iomem *mcdi_smem; int wol_filter_id; }; diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index 5735e84c69de..2c3bd93fab54 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -250,26 +250,12 @@ static int siena_probe_nic(struct efx_nic *efx) efx_reado(efx, ®, FR_AZ_CS_DEBUG); efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1; - /* Initialise MCDI */ - nic_data->mcdi_smem = ioremap_nocache(efx->membase_phys + - FR_CZ_MC_TREG_SMEM, - FR_CZ_MC_TREG_SMEM_STEP * - FR_CZ_MC_TREG_SMEM_ROWS); - if (!nic_data->mcdi_smem) { - netif_err(efx, probe, efx->net_dev, - "could not map MCDI at %llx+%x\n", - (unsigned long long)efx->membase_phys + - FR_CZ_MC_TREG_SMEM, - FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS); - rc = -ENOMEM; - goto fail1; - } efx_mcdi_init(efx); /* Recover from a failed assertion before probing */ rc = efx_mcdi_handle_assertion(efx); if (rc) - goto fail2; + goto fail1; /* Let the BMC know that the driver is now in charge of link and * filter settings. We must do this before we reset the NIC */ @@ -324,7 +310,6 @@ fail4: fail3: efx_mcdi_drv_attach(efx, false, NULL); fail2: - iounmap(nic_data->mcdi_smem); fail1: kfree(efx->nic_data); return rc; @@ -404,8 +389,6 @@ static int siena_init_nic(struct efx_nic *efx) static void siena_remove_nic(struct efx_nic *efx) { - struct siena_nic_data *nic_data = efx->nic_data; - efx_nic_free_buffer(efx, &efx->irq_status); siena_reset_hw(efx, RESET_TYPE_ALL); @@ -415,8 +398,7 @@ static void siena_remove_nic(struct efx_nic *efx) efx_mcdi_drv_attach(efx, false, NULL); /* Tear down the private nic state */ - iounmap(nic_data->mcdi_smem); - kfree(nic_data); + kfree(efx->nic_data); efx->nic_data = NULL; } @@ -656,7 +638,8 @@ const struct efx_nic_type siena_a0_nic_type = { .default_mac_ops = &efx_mcdi_mac_operations, .revision = EFX_REV_SIENA_A0, - .mem_map_size = FR_CZ_MC_TREG_SMEM, /* MC_TREG_SMEM mapped separately */ + .mem_map_size = (FR_CZ_MC_TREG_SMEM + + FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS), .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, .rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL, .buf_tbl_base = FR_BZ_BUF_FULL_TBL, diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h index 99ff11400cef..e4dd3a7f304b 100644 --- a/drivers/net/sfc/workarounds.h +++ b/drivers/net/sfc/workarounds.h @@ -38,8 +38,6 @@ #define EFX_WORKAROUND_15783 EFX_WORKAROUND_ALWAYS /* Legacy interrupt storm when interrupt fifo fills */ #define EFX_WORKAROUND_17213 EFX_WORKAROUND_SIENA -/* Write combining and sriov=enabled are incompatible */ -#define EFX_WORKAROUND_22643 EFX_WORKAROUND_SIENA /* Spurious parity errors in TSORT buffers */ #define EFX_WORKAROUND_5129 EFX_WORKAROUND_FALCON_A -- cgit v1.2.1 From 483f97f8b2b7f0ab09e14c06fe327d5e346fac28 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 1 Sep 2011 12:09:59 +0000 Subject: sfc: Use 64-bit writes for TX push where possible This was originally done as part of commit 65f0b417dee94f779ce9b77102b7d73c93723b39 ("sfc: Use write-combining to reduce TX latency"), but that had to be reverted. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/io.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/sfc/io.h b/drivers/net/sfc/io.h index dc45110b2456..751d1ec112cc 100644 --- a/drivers/net/sfc/io.h +++ b/drivers/net/sfc/io.h @@ -48,9 +48,9 @@ * replacing the low 96 bits with zero does not affect functionality. * - If the host writes to the last dword address of such a register * (i.e. the high 32 bits) the underlying register will always be - * written. If the collector does not hold values for the low 96 - * bits of the register, they will be written as zero. Writing to - * the last qword does not have this effect and must not be done. + * written. If the collector and the current write together do not + * provide values for all 128 bits of the register, the low 96 bits + * will be written as zero. * - If the host writes to the address of any other part of such a * register while the collector already holds values for some other * register, the write is discarded and the collector maintains its @@ -237,12 +237,13 @@ static inline void _efx_writeo_page(struct efx_nic *efx, efx_oword_t *value, #ifdef EFX_USE_QWORD_IO _efx_writeq(efx, value->u64[0], reg + 0); + _efx_writeq(efx, value->u64[1], reg + 8); #else _efx_writed(efx, value->u32[0], reg + 0); _efx_writed(efx, value->u32[1], reg + 4); -#endif _efx_writed(efx, value->u32[2], reg + 8); _efx_writed(efx, value->u32[3], reg + 12); +#endif } #define efx_writeo_page(efx, value, reg, page) \ _efx_writeo_page(efx, value, \ -- cgit v1.2.1 From 5229d87edcd80a3bceb0708ebd767faff2e589a9 Mon Sep 17 00:00:00 2001 From: Toshiharu Okada Date: Thu, 1 Sep 2011 14:20:07 +0000 Subject: pch_gbe: fixed the issue which receives an unnecessary packet. This patch fixed the issue which receives an unnecessary packet before link When using PHY of GMII, an unnecessary packet is received, And it becomes impossible to receive a packet after link up. Signed-off-by: Toshiharu Okada Signed-off-by: David S. Miller --- drivers/net/pch_gbe/pch_gbe_main.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index eac3c5ca9731..48ff87c455ae 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -717,13 +717,6 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) iowrite32(rdba, &hw->reg->RX_DSC_BASE); iowrite32(rdlen, &hw->reg->RX_DSC_SIZE); iowrite32((rdba + rdlen), &hw->reg->RX_DSC_SW_P); - - /* Enables Receive DMA */ - rxdma = ioread32(&hw->reg->DMA_CTRL); - rxdma |= PCH_GBE_RX_DMA_EN; - iowrite32(rxdma, &hw->reg->DMA_CTRL); - /* Enables Receive */ - iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN); } /** @@ -1097,6 +1090,19 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter) spin_unlock_irqrestore(&adapter->stats_lock, flags); } +static void pch_gbe_start_receive(struct pch_gbe_hw *hw) +{ + u32 rxdma; + + /* Enables Receive DMA */ + rxdma = ioread32(&hw->reg->DMA_CTRL); + rxdma |= PCH_GBE_RX_DMA_EN; + iowrite32(rxdma, &hw->reg->DMA_CTRL); + /* Enables Receive */ + iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN); + return; +} + /** * pch_gbe_intr - Interrupt Handler * @irq: Interrupt number @@ -1717,6 +1723,7 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) pch_gbe_alloc_tx_buffers(adapter, tx_ring); pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count); adapter->tx_queue_len = netdev->tx_queue_len; + pch_gbe_start_receive(&adapter->hw); mod_timer(&adapter->watchdog_timer, jiffies); -- cgit v1.2.1 From 124d770a6459be21b84445f6ebf7dbfb60d43585 Mon Sep 17 00:00:00 2001 From: Toshiharu Okada Date: Thu, 1 Sep 2011 14:20:08 +0000 Subject: pch_gbe: added the process of FIFO over run error This patch added the processing which should be done to hardware, when a FIFO over run error occurred. Signed-off-by: Toshiharu Okada Signed-off-by: David S. Miller --- drivers/net/pch_gbe/pch_gbe.h | 12 +- drivers/net/pch_gbe/pch_gbe_main.c | 271 +++++++++++++++++++++++-------------- 2 files changed, 179 insertions(+), 104 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/pch_gbe/pch_gbe.h b/drivers/net/pch_gbe/pch_gbe.h index 59fac77d0dbb..a09a07197eb5 100644 --- a/drivers/net/pch_gbe/pch_gbe.h +++ b/drivers/net/pch_gbe/pch_gbe.h @@ -127,8 +127,8 @@ struct pch_gbe_regs { /* Reset */ #define PCH_GBE_ALL_RST 0x80000000 /* All reset */ -#define PCH_GBE_TX_RST 0x40000000 /* TX MAC, TX FIFO, TX DMA reset */ -#define PCH_GBE_RX_RST 0x04000000 /* RX MAC, RX FIFO, RX DMA reset */ +#define PCH_GBE_TX_RST 0x00008000 /* TX MAC, TX FIFO, TX DMA reset */ +#define PCH_GBE_RX_RST 0x00004000 /* RX MAC, RX FIFO, RX DMA reset */ /* TCP/IP Accelerator Control */ #define PCH_GBE_EX_LIST_EN 0x00000008 /* External List Enable */ @@ -276,6 +276,9 @@ struct pch_gbe_regs { #define PCH_GBE_RX_DMA_EN 0x00000002 /* Enables Receive DMA */ #define PCH_GBE_TX_DMA_EN 0x00000001 /* Enables Transmission DMA */ +/* RX DMA STATUS */ +#define PCH_GBE_IDLE_CHECK 0xFFFFFFFE + /* Wake On LAN Status */ #define PCH_GBE_WLS_BR 0x00000008 /* Broadcas Address */ #define PCH_GBE_WLS_MLT 0x00000004 /* Multicast Address */ @@ -471,6 +474,7 @@ struct pch_gbe_tx_desc { struct pch_gbe_buffer { struct sk_buff *skb; dma_addr_t dma; + unsigned char *rx_buffer; unsigned long time_stamp; u16 length; bool mapped; @@ -511,6 +515,9 @@ struct pch_gbe_tx_ring { struct pch_gbe_rx_ring { struct pch_gbe_rx_desc *desc; dma_addr_t dma; + unsigned char *rx_buff_pool; + dma_addr_t rx_buff_pool_logic; + unsigned int rx_buff_pool_size; unsigned int size; unsigned int count; unsigned int next_to_use; @@ -622,6 +629,7 @@ struct pch_gbe_adapter { unsigned long rx_buffer_len; unsigned long tx_queue_len; bool have_msi; + bool rx_stop_flag; }; extern const char pch_driver_version[]; diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index 48ff87c455ae..39ce0ee44ad7 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -20,7 +20,6 @@ #include "pch_gbe.h" #include "pch_gbe_api.h" -#include #define DRV_VERSION "1.00" const char pch_driver_version[] = DRV_VERSION; @@ -34,6 +33,7 @@ const char pch_driver_version[] = DRV_VERSION; #define PCH_GBE_WATCHDOG_PERIOD (1 * HZ) /* watchdog time */ #define PCH_GBE_COPYBREAK_DEFAULT 256 #define PCH_GBE_PCI_BAR 1 +#define PCH_GBE_RESERVE_MEMORY 0x200000 /* 2MB */ /* Macros for ML7223 */ #define PCI_VENDOR_ID_ROHM 0x10db @@ -52,6 +52,7 @@ const char pch_driver_version[] = DRV_VERSION; ) /* Ethertype field values */ +#define PCH_GBE_MAX_RX_BUFFER_SIZE 0x2880 #define PCH_GBE_MAX_JUMBO_FRAME_SIZE 10318 #define PCH_GBE_FRAME_SIZE_2048 2048 #define PCH_GBE_FRAME_SIZE_4096 4096 @@ -83,10 +84,12 @@ const char pch_driver_version[] = DRV_VERSION; #define PCH_GBE_INT_ENABLE_MASK ( \ PCH_GBE_INT_RX_DMA_CMPLT | \ PCH_GBE_INT_RX_DSC_EMP | \ + PCH_GBE_INT_RX_FIFO_ERR | \ PCH_GBE_INT_WOL_DET | \ PCH_GBE_INT_TX_CMPLT \ ) +#define PCH_GBE_INT_DISABLE_ALL 0 static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT; @@ -138,6 +141,27 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit) if (!tmp) pr_err("Error: busy bit is not cleared\n"); } + +/** + * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context + * @reg: Pointer of register + * @busy: Busy bit + */ +static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit) +{ + u32 tmp; + int ret = -1; + /* wait busy */ + tmp = 20; + while ((ioread32(reg) & bit) && --tmp) + udelay(5); + if (!tmp) + pr_err("Error: busy bit is not cleared\n"); + else + ret = 0; + return ret; +} + /** * pch_gbe_mac_mar_set - Set MAC address register * @hw: Pointer to the HW structure @@ -189,6 +213,17 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw) return; } +static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw) +{ + /* Read the MAC address. and store to the private data */ + pch_gbe_mac_read_mac_addr(hw); + iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET); + pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST); + /* Setup the MAC address */ + pch_gbe_mac_mar_set(hw, hw->mac.addr, 0); + return; +} + /** * pch_gbe_mac_init_rx_addrs - Initialize receive address's * @hw: Pointer to the HW structure @@ -671,13 +706,8 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter) tcpip = ioread32(&hw->reg->TCPIP_ACC); - if (netdev->features & NETIF_F_RXCSUM) { - tcpip &= ~PCH_GBE_RX_TCPIPACC_OFF; - tcpip |= PCH_GBE_RX_TCPIPACC_EN; - } else { - tcpip |= PCH_GBE_RX_TCPIPACC_OFF; - tcpip &= ~PCH_GBE_RX_TCPIPACC_EN; - } + tcpip |= PCH_GBE_RX_TCPIPACC_OFF; + tcpip &= ~PCH_GBE_RX_TCPIPACC_EN; iowrite32(tcpip, &hw->reg->TCPIP_ACC); return; } @@ -1090,6 +1120,35 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter) spin_unlock_irqrestore(&adapter->stats_lock, flags); } +static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter) +{ + struct pch_gbe_hw *hw = &adapter->hw; + u32 rxdma; + u16 value; + int ret; + + /* Disable Receive DMA */ + rxdma = ioread32(&hw->reg->DMA_CTRL); + rxdma &= ~PCH_GBE_RX_DMA_EN; + iowrite32(rxdma, &hw->reg->DMA_CTRL); + /* Wait Rx DMA BUS is IDLE */ + ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK); + if (ret) { + /* Disable Bus master */ + pci_read_config_word(adapter->pdev, PCI_COMMAND, &value); + value &= ~PCI_COMMAND_MASTER; + pci_write_config_word(adapter->pdev, PCI_COMMAND, value); + /* Stop Receive */ + pch_gbe_mac_reset_rx(hw); + /* Enable Bus master */ + value |= PCI_COMMAND_MASTER; + pci_write_config_word(adapter->pdev, PCI_COMMAND, value); + } else { + /* Stop Receive */ + pch_gbe_mac_reset_rx(hw); + } +} + static void pch_gbe_start_receive(struct pch_gbe_hw *hw) { u32 rxdma; @@ -1129,7 +1188,15 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) if (int_st & PCH_GBE_INT_RX_FRAME_ERR) adapter->stats.intr_rx_frame_err_count++; if (int_st & PCH_GBE_INT_RX_FIFO_ERR) - adapter->stats.intr_rx_fifo_err_count++; + if (!adapter->rx_stop_flag) { + adapter->stats.intr_rx_fifo_err_count++; + pr_debug("Rx fifo over run\n"); + adapter->rx_stop_flag = true; + int_en = ioread32(&hw->reg->INT_EN); + iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR), + &hw->reg->INT_EN); + pch_gbe_stop_receive(adapter); + } if (int_st & PCH_GBE_INT_RX_DMA_ERR) adapter->stats.intr_rx_dma_err_count++; if (int_st & PCH_GBE_INT_TX_FIFO_ERR) @@ -1141,7 +1208,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) /* When Rx descriptor is empty */ if ((int_st & PCH_GBE_INT_RX_DSC_EMP)) { adapter->stats.intr_rx_dsc_empty_count++; - pr_err("Rx descriptor is empty\n"); + pr_debug("Rx descriptor is empty\n"); int_en = ioread32(&hw->reg->INT_EN); iowrite32((int_en & ~PCH_GBE_INT_RX_DSC_EMP), &hw->reg->INT_EN); if (hw->mac.tx_fc_enable) { @@ -1191,29 +1258,23 @@ pch_gbe_alloc_rx_buffers(struct pch_gbe_adapter *adapter, unsigned int i; unsigned int bufsz; - bufsz = adapter->rx_buffer_len + PCH_GBE_DMA_ALIGN; + bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; i = rx_ring->next_to_use; while ((cleaned_count--)) { buffer_info = &rx_ring->buffer_info[i]; - skb = buffer_info->skb; - if (skb) { - skb_trim(skb, 0); - } else { - skb = netdev_alloc_skb(netdev, bufsz); - if (unlikely(!skb)) { - /* Better luck next round */ - adapter->stats.rx_alloc_buff_failed++; - break; - } - /* 64byte align */ - skb_reserve(skb, PCH_GBE_DMA_ALIGN); - - buffer_info->skb = skb; - buffer_info->length = adapter->rx_buffer_len; + skb = netdev_alloc_skb(netdev, bufsz); + if (unlikely(!skb)) { + /* Better luck next round */ + adapter->stats.rx_alloc_buff_failed++; + break; } + /* align */ + skb_reserve(skb, NET_IP_ALIGN); + buffer_info->skb = skb; + buffer_info->dma = dma_map_single(&pdev->dev, - skb->data, + buffer_info->rx_buffer, buffer_info->length, DMA_FROM_DEVICE); if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) { @@ -1246,6 +1307,36 @@ pch_gbe_alloc_rx_buffers(struct pch_gbe_adapter *adapter, return; } +static int +pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter, + struct pch_gbe_rx_ring *rx_ring, int cleaned_count) +{ + struct pci_dev *pdev = adapter->pdev; + struct pch_gbe_buffer *buffer_info; + unsigned int i; + unsigned int bufsz; + unsigned int size; + + bufsz = adapter->rx_buffer_len; + + size = rx_ring->count * bufsz + PCH_GBE_RESERVE_MEMORY; + rx_ring->rx_buff_pool = dma_alloc_coherent(&pdev->dev, size, + &rx_ring->rx_buff_pool_logic, + GFP_KERNEL); + if (!rx_ring->rx_buff_pool) { + pr_err("Unable to allocate memory for the receive poll buffer\n"); + return -ENOMEM; + } + memset(rx_ring->rx_buff_pool, 0, size); + rx_ring->rx_buff_pool_size = size; + for (i = 0; i < rx_ring->count; i++) { + buffer_info = &rx_ring->buffer_info[i]; + buffer_info->rx_buffer = rx_ring->rx_buff_pool + bufsz * i; + buffer_info->length = bufsz; + } + return 0; +} + /** * pch_gbe_alloc_tx_buffers - Allocate transmit buffers * @adapter: Board private structure @@ -1386,7 +1477,7 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, unsigned int i; unsigned int cleaned_count = 0; bool cleaned = false; - struct sk_buff *skb, *new_skb; + struct sk_buff *skb; u8 dma_status; u16 gbec_status; u32 tcp_ip_status; @@ -1407,13 +1498,12 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, rx_desc->gbec_status = DSC_INIT16; buffer_info = &rx_ring->buffer_info[i]; skb = buffer_info->skb; + buffer_info->skb = NULL; /* unmap dma */ dma_unmap_single(&pdev->dev, buffer_info->dma, buffer_info->length, DMA_FROM_DEVICE); buffer_info->mapped = false; - /* Prefetch the packet */ - prefetch(skb->data); pr_debug("RxDecNo = 0x%04x Status[DMA:0x%02x GBE:0x%04x " "TCP:0x%08x] BufInf = 0x%p\n", @@ -1433,70 +1523,16 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, pr_err("Receive CRC Error\n"); } else { /* get receive length */ - /* length convert[-3] */ - length = (rx_desc->rx_words_eob) - 3; - - /* Decide the data conversion method */ - if (!(netdev->features & NETIF_F_RXCSUM)) { - /* [Header:14][payload] */ - if (NET_IP_ALIGN) { - /* Because alignment differs, - * the new_skb is newly allocated, - * and data is copied to new_skb.*/ - new_skb = netdev_alloc_skb(netdev, - length + NET_IP_ALIGN); - if (!new_skb) { - /* dorrop error */ - pr_err("New skb allocation " - "Error\n"); - goto dorrop; - } - skb_reserve(new_skb, NET_IP_ALIGN); - memcpy(new_skb->data, skb->data, - length); - skb = new_skb; - } else { - /* DMA buffer is used as SKB as it is.*/ - buffer_info->skb = NULL; - } - } else { - /* [Header:14][padding:2][payload] */ - /* The length includes padding length */ - length = length - PCH_GBE_DMA_PADDING; - if ((length < copybreak) || - (NET_IP_ALIGN != PCH_GBE_DMA_PADDING)) { - /* Because alignment differs, - * the new_skb is newly allocated, - * and data is copied to new_skb. - * Padding data is deleted - * at the time of a copy.*/ - new_skb = netdev_alloc_skb(netdev, - length + NET_IP_ALIGN); - if (!new_skb) { - /* dorrop error */ - pr_err("New skb allocation " - "Error\n"); - goto dorrop; - } - skb_reserve(new_skb, NET_IP_ALIGN); - memcpy(new_skb->data, skb->data, - ETH_HLEN); - memcpy(&new_skb->data[ETH_HLEN], - &skb->data[ETH_HLEN + - PCH_GBE_DMA_PADDING], - length - ETH_HLEN); - skb = new_skb; - } else { - /* Padding data is deleted - * by moving header data.*/ - memmove(&skb->data[PCH_GBE_DMA_PADDING], - &skb->data[0], ETH_HLEN); - skb_reserve(skb, NET_IP_ALIGN); - buffer_info->skb = NULL; - } - } - /* The length includes FCS length */ - length = length - ETH_FCS_LEN; + /* length convert[-3], length includes FCS length */ + length = (rx_desc->rx_words_eob) - 3 - ETH_FCS_LEN; + if (rx_desc->rx_words_eob & 0x02) + length = length - 4; + /* + * buffer_info->rx_buffer: [Header:14][payload] + * skb->data: [Reserve:2][Header:14][payload] + */ + memcpy(skb->data, buffer_info->rx_buffer, length); + /* update status of driver */ adapter->stats.rx_bytes += length; adapter->stats.rx_packets++; @@ -1515,7 +1551,6 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, pr_debug("Receive skb->ip_summed: %d length: %d\n", skb->ip_summed, length); } -dorrop: /* return some buffers to hardware, one at a time is too slow */ if (unlikely(cleaned_count >= PCH_GBE_RX_BUFFER_WRITE)) { pch_gbe_alloc_rx_buffers(adapter, rx_ring, @@ -1720,6 +1755,11 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) pr_err("Error: can't bring device up\n"); return err; } + err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count); + if (err) { + pr_err("Error: can't bring device up\n"); + return err; + } pch_gbe_alloc_tx_buffers(adapter, tx_ring); pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count); adapter->tx_queue_len = netdev->tx_queue_len; @@ -1741,6 +1781,7 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) void pch_gbe_down(struct pch_gbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; + struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring; /* signal that we're down so the interrupt handler does not * reschedule our watchdog timer */ @@ -1759,6 +1800,12 @@ void pch_gbe_down(struct pch_gbe_adapter *adapter) pch_gbe_reset(adapter); pch_gbe_clean_tx_ring(adapter, adapter->tx_ring); pch_gbe_clean_rx_ring(adapter, adapter->rx_ring); + + pci_free_consistent(adapter->pdev, rx_ring->rx_buff_pool_size, + rx_ring->rx_buff_pool, rx_ring->rx_buff_pool_logic); + rx_ring->rx_buff_pool_logic = 0; + rx_ring->rx_buff_pool_size = 0; + rx_ring->rx_buff_pool = NULL; } /** @@ -2011,6 +2058,8 @@ static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu) { struct pch_gbe_adapter *adapter = netdev_priv(netdev); int max_frame; + unsigned long old_rx_buffer_len = adapter->rx_buffer_len; + int err; max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || @@ -2025,14 +2074,24 @@ static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu) else if (max_frame <= PCH_GBE_FRAME_SIZE_8192) adapter->rx_buffer_len = PCH_GBE_FRAME_SIZE_8192; else - adapter->rx_buffer_len = PCH_GBE_MAX_JUMBO_FRAME_SIZE; - netdev->mtu = new_mtu; - adapter->hw.mac.max_frame_size = max_frame; + adapter->rx_buffer_len = PCH_GBE_MAX_RX_BUFFER_SIZE; - if (netif_running(netdev)) - pch_gbe_reinit_locked(adapter); - else + if (netif_running(netdev)) { + pch_gbe_down(adapter); + err = pch_gbe_up(adapter); + if (err) { + adapter->rx_buffer_len = old_rx_buffer_len; + pch_gbe_up(adapter); + return -ENOMEM; + } else { + netdev->mtu = new_mtu; + adapter->hw.mac.max_frame_size = max_frame; + } + } else { pch_gbe_reset(adapter); + netdev->mtu = new_mtu; + adapter->hw.mac.max_frame_size = max_frame; + } pr_debug("max_frame : %d rx_buffer_len : %d mtu : %d max_frame_size : %d\n", max_frame, (u32) adapter->rx_buffer_len, netdev->mtu, @@ -2110,6 +2169,7 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) int work_done = 0; bool poll_end_flag = false; bool cleaned = false; + u32 int_en; pr_debug("budget : %d\n", budget); @@ -2117,8 +2177,15 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) if (!netif_carrier_ok(netdev)) { poll_end_flag = true; } else { - cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring); pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget); + if (adapter->rx_stop_flag) { + adapter->rx_stop_flag = false; + pch_gbe_start_receive(&adapter->hw); + int_en = ioread32(&adapter->hw.reg->INT_EN); + iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR), + &adapter->hw.reg->INT_EN); + } + cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring); if (cleaned) work_done = budget; -- cgit v1.2.1 From 7756332f5b64c9c1535712b9679792e8bd4f0019 Mon Sep 17 00:00:00 2001 From: Toshiharu Okada Date: Thu, 1 Sep 2011 14:20:09 +0000 Subject: pch_gbe: support ML7831 IOH Support new device OKI SEMICONDUCTOR ML7831 IOH(Input/Output Hub) ML7831 is for general purpose use. ML7831 is companion chip for Intel Atom E6xx series. ML7831 is completely compatible for Intel EG20T PCH. Signed-off-by: Toshiharu Okada Signed-off-by: David S. Miller --- drivers/net/Kconfig | 11 ++++++----- drivers/net/pch_gbe/pch_gbe_main.c | 10 ++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 8d0314dbd946..a44874e24f2a 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2535,7 +2535,7 @@ config S6GMAC source "drivers/net/stmmac/Kconfig" config PCH_GBE - tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE" + tristate "Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE" depends on PCI select MII ---help--- @@ -2548,10 +2548,11 @@ config PCH_GBE This driver enables Gigabit Ethernet function. This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ - Output Hub), ML7223. - ML7223 IOH is for MP(Media Phone) use. - ML7223 is companion chip for Intel Atom E6xx series. - ML7223 is completely compatible for Intel EG20T PCH. + Output Hub), ML7223/ML7831. + ML7223 IOH is for MP(Media Phone) use. ML7831 IOH is for general + purpose use. + ML7223/ML7831 is companion chip for Intel Atom E6xx series. + ML7223/ML7831 is completely compatible for Intel EG20T PCH. config FTGMAC100 tristate "Faraday FTGMAC100 Gigabit Ethernet support" diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index 39ce0ee44ad7..567ff10889be 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -39,6 +39,9 @@ const char pch_driver_version[] = DRV_VERSION; #define PCI_VENDOR_ID_ROHM 0x10db #define PCI_DEVICE_ID_ROHM_ML7223_GBE 0x8013 +/* Macros for ML7831 */ +#define PCI_DEVICE_ID_ROHM_ML7831_GBE 0x8802 + #define PCH_GBE_TX_WEIGHT 64 #define PCH_GBE_RX_WEIGHT 64 #define PCH_GBE_RX_BUFFER_WRITE 16 @@ -2526,6 +2529,13 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = { .class = (PCI_CLASS_NETWORK_ETHERNET << 8), .class_mask = (0xFFFF00) }, + {.vendor = PCI_VENDOR_ID_ROHM, + .device = PCI_DEVICE_ID_ROHM_ML7831_GBE, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .class = (PCI_CLASS_NETWORK_ETHERNET << 8), + .class_mask = (0xFFFF00) + }, /* required last entry */ {0} }; -- cgit v1.2.1 From 33a48ab105a75d37021e422a0a3283241099b142 Mon Sep 17 00:00:00 2001 From: Brian King Date: Wed, 7 Sep 2011 14:41:03 +0000 Subject: ibmveth: Fix DMA unmap error Commit 6e8ab30ec677 (ibmveth: Add scatter-gather support) introduced a DMA mapping API inconsistency resulting in dma_unmap_page getting called on memory mapped via dma_map_single. This was seen when CONFIG_DMA_API_DEBUG was enabled. Fix up this API usage inconsistency. Signed-off-by: Brian King Acked-by: Anton Blanchard Cc: # v2.6.37+ Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 3e6679269400..dcf65d8f10d2 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1026,7 +1026,12 @@ retry_bounce: netdev->stats.tx_bytes += skb->len; } - for (i = 0; i < skb_shinfo(skb)->nr_frags + 1; i++) + dma_unmap_single(&adapter->vdev->dev, + descs[0].fields.address, + descs[0].fields.flags_len & IBMVETH_BUF_LEN_MASK, + DMA_TO_DEVICE); + + for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++) dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address, descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK, DMA_TO_DEVICE); -- cgit v1.2.1 From b93da27f5234198433345e40b39ff59797bc6f6e Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 7 Sep 2011 14:41:04 +0000 Subject: ibmveth: Fix issue with DMA mapping failure descs[].fields.address is 32bit which truncates any dma mapping errors so dma_mapping_error() fails to catch it. Use a dma_addr_t to do the comparison. With this patch I was able to transfer many gigabytes of data with IOMMU fault injection set at 10% probability. Signed-off-by: Anton Blanchard Cc: # v2.6.37+ Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index dcf65d8f10d2..5b8b411d5a80 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -930,6 +930,7 @@ static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb, union ibmveth_buf_desc descs[6]; int last, i; int force_bounce = 0; + dma_addr_t dma_addr; /* * veth handles a maximum of 6 segments including the header, so @@ -994,17 +995,16 @@ retry_bounce: } /* Map the header */ - descs[0].fields.address = dma_map_single(&adapter->vdev->dev, skb->data, - skb_headlen(skb), - DMA_TO_DEVICE); - if (dma_mapping_error(&adapter->vdev->dev, descs[0].fields.address)) + dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); + if (dma_mapping_error(&adapter->vdev->dev, dma_addr)) goto map_failed; descs[0].fields.flags_len = desc_flags | skb_headlen(skb); + descs[0].fields.address = dma_addr; /* Map the frags */ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - unsigned long dma_addr; skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; dma_addr = dma_map_page(&adapter->vdev->dev, frag->page, -- cgit v1.2.1 From 91aae1e5c407d4fc79f6983e6c6ba04756c004cb Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 7 Sep 2011 14:41:05 +0000 Subject: ibmveth: Checksum offload is always disabled Commit b9367bf3ee6d (net: ibmveth: convert to hw_features) reversed a check in ibmveth_set_csum_offload that results in checksum offload never being enabled. Signed-off-by: Anton Blanchard Cc: # 3.0+ Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 5b8b411d5a80..07830f918aed 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -812,7 +812,7 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data) } else adapter->fw_ipv6_csum_support = data; - if (ret != H_SUCCESS || ret6 != H_SUCCESS) + if (ret == H_SUCCESS || ret6 == H_SUCCESS) adapter->rx_csum = data; else rc1 = -EIO; -- cgit v1.2.1 From fb82fd204b6e6c67661bbd37df032edafb2da56e Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 7 Sep 2011 14:41:06 +0000 Subject: ibmveth: Fix checksum offload failure handling Fix a number of issues in ibmveth_set_csum_offload: - set_attr6 and clr_attr6 may be used uninitialised - We store the result of the IPV4 checksum change in ret but overwrite it in a couple of places before checking it again later. Add ret4 to make it obvious what we are doing. - We weren't clearing the NETIF_F_IP_CSUM and NETIF_F_IPV6_CSUM flags if the enable of that hypervisor feature failed. Signed-off-by: Anton Blanchard Signed-off-by: David S. Miller --- drivers/net/ibmveth.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 07830f918aed..8dd5fccef725 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -757,7 +757,7 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data) struct ibmveth_adapter *adapter = netdev_priv(dev); unsigned long set_attr, clr_attr, ret_attr; unsigned long set_attr6, clr_attr6; - long ret, ret6; + long ret, ret4, ret6; int rc1 = 0, rc2 = 0; int restart = 0; @@ -770,6 +770,8 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data) set_attr = 0; clr_attr = 0; + set_attr6 = 0; + clr_attr6 = 0; if (data) { set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM; @@ -784,16 +786,20 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data) if (ret == H_SUCCESS && !(ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK) && !(ret_attr & IBMVETH_ILLAN_TRUNK_PRI_MASK) && (ret_attr & IBMVETH_ILLAN_PADDED_PKT_CSUM)) { - ret = h_illan_attributes(adapter->vdev->unit_address, clr_attr, + ret4 = h_illan_attributes(adapter->vdev->unit_address, clr_attr, set_attr, &ret_attr); - if (ret != H_SUCCESS) { + if (ret4 != H_SUCCESS) { netdev_err(dev, "unable to change IPv4 checksum " "offload settings. %d rc=%ld\n", - data, ret); + data, ret4); + + h_illan_attributes(adapter->vdev->unit_address, + set_attr, clr_attr, &ret_attr); + + if (data == 1) + dev->features &= ~NETIF_F_IP_CSUM; - ret = h_illan_attributes(adapter->vdev->unit_address, - set_attr, clr_attr, &ret_attr); } else { adapter->fw_ipv4_csum_support = data; } @@ -804,15 +810,18 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data) if (ret6 != H_SUCCESS) { netdev_err(dev, "unable to change IPv6 checksum " "offload settings. %d rc=%ld\n", - data, ret); + data, ret6); + + h_illan_attributes(adapter->vdev->unit_address, + set_attr6, clr_attr6, &ret_attr); + + if (data == 1) + dev->features &= ~NETIF_F_IPV6_CSUM; - ret = h_illan_attributes(adapter->vdev->unit_address, - set_attr6, clr_attr6, - &ret_attr); } else adapter->fw_ipv6_csum_support = data; - if (ret == H_SUCCESS || ret6 == H_SUCCESS) + if (ret4 == H_SUCCESS || ret6 == H_SUCCESS) adapter->rx_csum = data; else rc1 = -EIO; -- cgit v1.2.1 From 7cabafcea793c003503a118da58da358b0692930 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 14 Sep 2011 16:47:50 +0200 Subject: ipw2x00: fix rtnl mutex deadlock This fix regression introduced by: commit: ecb4433550f0620f3d1471ae7099037ede30a91e Author: Stanislaw Gruszka Date: Fri Aug 12 14:00:59 2011 +0200 mac80211: fix suspend/resume races with unregister hw Above commit add rtnl_lock() into wiphy_register(), what cause deadlock when initializing ipw2x00 driver, which itself call wiphy_register() from register_netdev() internal callback with rtnl mutex taken. To fix move wiphy_register() outside register_netdev(). This solution have side effect of not creating /sys/class/net/wlanX/phy80211 link, but that's a minor issue we can live with. Bisected-by: Witold Baryluk Bisected-by: Michael Witten Tested-by: Witold Baryluk Tested-by: Michael Witten Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 21 ++++++++++++------ drivers/net/wireless/ipw2x00/ipw2200.c | 39 ++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 3774dd034746..ef9ad79d1bfd 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -1901,17 +1901,19 @@ static void ipw2100_down(struct ipw2100_priv *priv) /* Called by register_netdev() */ static int ipw2100_net_init(struct net_device *dev) +{ + struct ipw2100_priv *priv = libipw_priv(dev); + + return ipw2100_up(priv, 1); +} + +static int ipw2100_wdev_init(struct net_device *dev) { struct ipw2100_priv *priv = libipw_priv(dev); const struct libipw_geo *geo = libipw_get_geo(priv->ieee); struct wireless_dev *wdev = &priv->ieee->wdev; - int ret; int i; - ret = ipw2100_up(priv, 1); - if (ret) - return ret; - memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); /* fill-out priv->ieee->bg_band */ @@ -6350,9 +6352,13 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, "Error calling register_netdev.\n"); goto fail; } + registered = 1; + + err = ipw2100_wdev_init(dev); + if (err) + goto fail; mutex_lock(&priv->action_mutex); - registered = 1; IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev)); @@ -6389,7 +6395,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, fail_unlock: mutex_unlock(&priv->action_mutex); - + wiphy_unregister(priv->ieee->wdev.wiphy); + kfree(priv->ieee->bg_band.channels); fail: if (dev) { if (registered) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 87813c33bdc2..4ffebede5e03 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11424,17 +11424,24 @@ static void ipw_bg_down(struct work_struct *work) /* Called by register_netdev() */ static int ipw_net_init(struct net_device *dev) +{ + int rc = 0; + struct ipw_priv *priv = libipw_priv(dev); + + mutex_lock(&priv->mutex); + if (ipw_up(priv)) + rc = -EIO; + mutex_unlock(&priv->mutex); + + return rc; +} + +static int ipw_wdev_init(struct net_device *dev) { int i, rc = 0; struct ipw_priv *priv = libipw_priv(dev); const struct libipw_geo *geo = libipw_get_geo(priv->ieee); struct wireless_dev *wdev = &priv->ieee->wdev; - mutex_lock(&priv->mutex); - - if (ipw_up(priv)) { - rc = -EIO; - goto out; - } memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); @@ -11519,13 +11526,9 @@ static int ipw_net_init(struct net_device *dev) set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); /* With that information in place, we can now register the wiphy... */ - if (wiphy_register(wdev->wiphy)) { + if (wiphy_register(wdev->wiphy)) rc = -EIO; - goto out; - } - out: - mutex_unlock(&priv->mutex); return rc; } @@ -11832,14 +11835,22 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, goto out_remove_sysfs; } + err = ipw_wdev_init(net_dev); + if (err) { + IPW_ERROR("failed to register wireless device\n"); + goto out_unregister_netdev; + } + #ifdef CONFIG_IPW2200_PROMISCUOUS if (rtap_iface) { err = ipw_prom_alloc(priv); if (err) { IPW_ERROR("Failed to register promiscuous network " "device (error %d).\n", err); - unregister_netdev(priv->net_dev); - goto out_remove_sysfs; + wiphy_unregister(priv->ieee->wdev.wiphy); + kfree(priv->ieee->a_band.channels); + kfree(priv->ieee->bg_band.channels); + goto out_unregister_netdev; } } #endif @@ -11851,6 +11862,8 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, return 0; + out_unregister_netdev: + unregister_netdev(priv->net_dev); out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); out_release_irq: -- cgit v1.2.1 From d331eb51e4d4190b2178c30fcafea54a94a577e8 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 14 Sep 2011 16:50:22 -0500 Subject: rt2800pci: Fix compiler error on PowerPC Using gcc 4.4.5 on a Powerbook G4 with a PPC cpu, a complicated if statement results in incorrect flow, whereas the equivalent switch statement works correctly. Signed-off-by: Larry Finger Cc: stable Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index ef67f6786a84..23568af4941d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3870,19 +3870,23 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) return -ENODEV; } - if (!rt2x00_rf(rt2x00dev, RF2820) && - !rt2x00_rf(rt2x00dev, RF2850) && - !rt2x00_rf(rt2x00dev, RF2720) && - !rt2x00_rf(rt2x00dev, RF2750) && - !rt2x00_rf(rt2x00dev, RF3020) && - !rt2x00_rf(rt2x00dev, RF2020) && - !rt2x00_rf(rt2x00dev, RF3021) && - !rt2x00_rf(rt2x00dev, RF3022) && - !rt2x00_rf(rt2x00dev, RF3052) && - !rt2x00_rf(rt2x00dev, RF3320) && - !rt2x00_rf(rt2x00dev, RF5370) && - !rt2x00_rf(rt2x00dev, RF5390)) { - ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); + switch (rt2x00dev->chip.rf) { + case RF2820: + case RF2850: + case RF2720: + case RF2750: + case RF3020: + case RF2020: + case RF3021: + case RF3022: + case RF3052: + case RF3320: + case RF5370: + case RF5390: + break; + default: + ERROR(rt2x00dev, "Invalid RF chipset 0x%x detected.\n", + rt2x00dev->chip.rf); return -ENODEV; } -- cgit v1.2.1 From daabead1c32f331edcfb255fd973411c667977e8 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 14 Sep 2011 16:50:23 -0500 Subject: rtl2800usb: Fix incorrect storage of MAC address on big-endian platforms The eeprom data is stored in little-endian order in the rt2x00 library. As it was converted to cpu order in the read routines, the data need to be converted to LE on a big-endian platform. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 23568af4941d..0019dfd8fb01 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3697,14 +3697,15 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i) rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, ®); /* Apparently the data is read from end to start */ - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, - (u32 *)&rt2x00dev->eeprom[i]); - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, - (u32 *)&rt2x00dev->eeprom[i + 2]); - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, - (u32 *)&rt2x00dev->eeprom[i + 4]); - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, - (u32 *)&rt2x00dev->eeprom[i + 6]); + rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, ®); + /* The returned value is in CPU order, but eeprom is le */ + rt2x00dev->eeprom[i] = cpu_to_le32(reg); + rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, ®); + *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); + rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, ®); + *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); + rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, ®); + *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg); mutex_unlock(&rt2x00dev->csr_mutex); } -- cgit v1.2.1 From 2249b011432ca3dcce112f0f71e0f531b4bb9347 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Thu, 15 Sep 2011 08:36:22 -0700 Subject: iwlagn: workaround bug crashing some APs This patch reverts commit 9b7688328422b88a7a15dc0dc123ad9ab1a6e22d which was introduced in 2.6.38-rc1. It works around a problem where the iwlagn driver stimulates a bug crashing (requiring power cycle to recover) some APs under heavy traffic. CC: stable@kernel.org #2.6.39, #3.0.0 #3.1.0 Signed-off-by: Don Fry SIgned-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b0ae4de7f083..f9c3cd95d614 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2140,7 +2140,12 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS; + /* + * Including the following line will crash some AP's. This + * workaround removes the stimulus which causes the crash until + * the AP software can be fixed. hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; + */ hw->flags |= IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; -- cgit v1.2.1 From 34b8686d278f00fb16234e74be44c253d6d6b676 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 16 Sep 2011 07:57:43 +0000 Subject: can: ti_hecc: include linux/io.h This fixes a build breakage for OMAP3 boards. Signed-off-by: Daniel Mack Cc: Wolfgang Grandegger Cc: netdev@vger.kernel.org Acked-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- drivers/net/can/ti_hecc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index a81249246ece..2adc294f512a 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include -- cgit v1.2.1 From c2b0c1e7fb69b54e704cb2dae5a80cc78a8cb0b2 Mon Sep 17 00:00:00 2001 From: Hayes Wang Date: Tue, 6 Sep 2011 16:55:16 +0800 Subject: r8169: fix the reset setting for 8111evl rtl8111evl should stop any TLP requirement before resetting by enabling register 0x37 bit 7. Signed-off-by: Hayes Wang --- drivers/net/r8169.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 02339b3352e7..a1c90707a2dd 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3988,6 +3988,7 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) while (RTL_R8(TxPoll) & NPQ) udelay(20); } else if (tp->mac_version == RTL_GIGA_MAC_VER_34) { + RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); while (!(RTL_R32(TxConfig) & TXCFG_EMPTY)) udelay(100); } else { -- cgit v1.2.1 From bbb8af75d0a6a5138ff00fe0b1b95c4824effd55 Mon Sep 17 00:00:00 2001 From: Hayes Wang Date: Tue, 6 Sep 2011 16:55:17 +0800 Subject: r8169: add MODULE_FIRMWARE for the firmware of 8111evl Add MODULE_FIRMWARE for the firmware of RTL8111E-VL Signed-off-by: Hayes Wang --- drivers/net/r8169.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index a1c90707a2dd..b55fba7f3a04 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -710,6 +710,7 @@ MODULE_FIRMWARE(FIRMWARE_8168D_1); MODULE_FIRMWARE(FIRMWARE_8168D_2); MODULE_FIRMWARE(FIRMWARE_8168E_1); MODULE_FIRMWARE(FIRMWARE_8168E_2); +MODULE_FIRMWARE(FIRMWARE_8168E_3); MODULE_FIRMWARE(FIRMWARE_8105E_1); static int rtl8169_open(struct net_device *dev); -- cgit v1.2.1 From 106633897e086e1b47126996aac1a427eb80eb1b Mon Sep 17 00:00:00 2001 From: Hayes Wang Date: Tue, 6 Sep 2011 16:55:14 +0800 Subject: r8169: fix WOL setting for 8105 and 8111evl rtl8105, rtl8111E, and rtl8111evl need enable RxConfig bit 1 ~ 3 for supporting wake on lan. Signed-off-by: Hayes Wang --- drivers/net/r8169.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index b55fba7f3a04..78c1d5832792 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3320,9 +3320,16 @@ static void r810x_phy_power_up(struct rtl8169_private *tp) static void r810x_pll_power_down(struct rtl8169_private *tp) { + void __iomem *ioaddr = tp->mmio_addr; + if (__rtl8169_get_wol(tp) & WAKE_ANY) { rtl_writephy(tp, 0x1f, 0x0000); rtl_writephy(tp, MII_BMCR, 0x0000); + + if (tp->mac_version == RTL_GIGA_MAC_VER_29 || + tp->mac_version == RTL_GIGA_MAC_VER_30) + RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast | + AcceptMulticast | AcceptMyPhys); return; } @@ -3418,7 +3425,8 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) rtl_writephy(tp, MII_BMCR, 0x0000); if (tp->mac_version == RTL_GIGA_MAC_VER_32 || - tp->mac_version == RTL_GIGA_MAC_VER_33) + tp->mac_version == RTL_GIGA_MAC_VER_33 || + tp->mac_version == RTL_GIGA_MAC_VER_34) RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); return; -- cgit v1.2.1 From e03f33af79f0772156e1a1a1e36bdddf8012b2e4 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Thu, 25 Aug 2011 18:47:24 +0200 Subject: r8169: remove erroneous processing of always set bit. When set, RxFOVF (resp. RxBOVF) is always 1 (resp. 0). Signed-off-by: Francois Romieu Cc: Hayes --- drivers/net/r8169.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 78c1d5832792..dff0bf094168 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -407,6 +407,7 @@ enum rtl_register_content { RxOK = 0x0001, /* RxStatusDesc */ + RxBOVF = (1 << 24), RxFOVF = (1 << 23), RxRWT = (1 << 22), RxRES = (1 << 21), @@ -682,6 +683,7 @@ struct rtl8169_private { struct mii_if_info mii; struct rtl8169_counters counters; u32 saved_wolopts; + u32 opts1_mask; struct rtl_fw { const struct firmware *fw; @@ -3786,6 +3788,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->intr_event = cfg->intr_event; tp->napi_event = cfg->napi_event; + tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ? + ~(RxBOVF | RxFOVF) : ~0; + init_timer(&tp->timer); tp->timer.data = (unsigned long) dev; tp->timer.function = rtl8169_phy_timer; @@ -5324,7 +5329,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, u32 status; rmb(); - status = le32_to_cpu(desc->opts1); + status = le32_to_cpu(desc->opts1) & tp->opts1_mask; if (status & DescOwn) break; -- cgit v1.2.1 From 2544bfc0eb2581e0eedbdfea1468b3866223d47e Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Thu, 1 Sep 2011 18:42:09 +0200 Subject: r8169: do not enable the TBI for anything but the original 8169. The TBI bit in PHYStatus is reserved on anything but the oldest 8169. Nobody complained after I disabled it for the 8168 and the 810x (see 66ec5d4fb1ce6f0bd9df4bc4b758f0916d9f37ab). Signed-off-by: Francois Romieu Cc: Hayes Wang --- drivers/net/r8169.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index dff0bf094168..c23667017922 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3080,6 +3080,14 @@ static void rtl8169_phy_reset(struct net_device *dev, netif_err(tp, link, dev, "PHY reset failed\n"); } +static bool rtl_tbi_enabled(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + + return (tp->mac_version == RTL_GIGA_MAC_VER_01) && + (RTL_R8(PHYstatus) & TBI_Enable); +} + static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; @@ -3112,7 +3120,7 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full : 0)); - if (RTL_R8(PHYstatus) & TBI_Enable) + if (rtl_tbi_enabled(tp)) netif_info(tp, link, dev, "TBI auto-negotiating\n"); } @@ -3738,8 +3746,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->features |= rtl_try_msi(pdev, ioaddr, cfg); RTL_W8(Cfg9346, Cfg9346_Lock); - if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && - (RTL_R8(PHYstatus) & TBI_Enable)) { + if (rtl_tbi_enabled(tp)) { tp->set_speed = rtl8169_set_speed_tbi; tp->get_settings = rtl8169_gset_tbi; tp->phy_reset_enable = rtl8169_tbi_reset_enable; -- cgit v1.2.1 From 8c23516fbb209ccf8f8c36268311c721faff29ee Mon Sep 17 00:00:00 2001 From: Manual Munz Date: Sun, 18 Sep 2011 18:24:03 -0500 Subject: b43: Fix beacon problem in ad-hoc mode In ad-hoc mode, driver b43 does not issue beacons. Signed-off-by: Manual Munz Tested-by: Larry Finger Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 26f1ab840cc7..e293a7921bf0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1632,7 +1632,8 @@ static void handle_irq_beacon(struct b43_wldev *dev) u32 cmd, beacon0_valid, beacon1_valid; if (!b43_is_mode(wl, NL80211_IFTYPE_AP) && - !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) + !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) && + !b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) return; /* This is the bottom half of the asynchronous beacon update. */ -- cgit v1.2.1 From 6af29a963cecf426966d56935d60a984bd5594ea Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Thu, 8 Sep 2011 03:14:35 +0000 Subject: GRETH: RX/TX bytes were never increased Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/greth.c | 5 +++++ drivers/net/greth.h | 1 + 2 files changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 16ce45c11934..58ec74a73150 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -428,6 +428,7 @@ greth_start_xmit(struct sk_buff *skb, struct net_device *dev) dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE); status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN); + greth->tx_bufs_length[greth->tx_next] = skb->len & GRETH_BD_LEN; /* Wrap around descriptor ring */ if (greth->tx_next == GRETH_TXBD_NUM_MASK) { @@ -641,6 +642,7 @@ static void greth_clean_tx(struct net_device *dev) dev->stats.tx_fifo_errors++; } dev->stats.tx_packets++; + dev->stats.tx_bytes += greth->tx_bufs_length[greth->tx_last]; greth->tx_last = NEXT_TX(greth->tx_last); greth->tx_free++; } @@ -695,6 +697,7 @@ static void greth_clean_tx_gbit(struct net_device *dev) greth->tx_skbuff[greth->tx_last] = NULL; greth_update_tx_stats(dev, stat); + dev->stats.tx_bytes += skb->len; bdp = greth->tx_bd_base + greth->tx_last; @@ -796,6 +799,7 @@ static int greth_rx(struct net_device *dev, int limit) memcpy(skb_put(skb, pkt_len), phys_to_virt(dma_addr), pkt_len); skb->protocol = eth_type_trans(skb, dev); + dev->stats.rx_bytes += pkt_len; dev->stats.rx_packets++; netif_receive_skb(skb); } @@ -910,6 +914,7 @@ static int greth_rx_gbit(struct net_device *dev, int limit) skb->protocol = eth_type_trans(skb, dev); dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; netif_receive_skb(skb); greth->rx_skbuff[greth->rx_cur] = newskb; diff --git a/drivers/net/greth.h b/drivers/net/greth.h index 9a0040dee4da..232a622a85b7 100644 --- a/drivers/net/greth.h +++ b/drivers/net/greth.h @@ -103,6 +103,7 @@ struct greth_private { unsigned char *tx_bufs[GRETH_TXBD_NUM]; unsigned char *rx_bufs[GRETH_RXBD_NUM]; + u16 tx_bufs_length[GRETH_TXBD_NUM]; u16 tx_next; u16 tx_last; -- cgit v1.2.1 From d706f00f65146822c0097b796b3557ea8980c305 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Fri, 9 Sep 2011 05:17:54 +0000 Subject: GRETH: avoid overwrite IP-stack's IP-frags checksum The GRETH GBIT core does not do checksum offloading for IP segmentation. This patch adds a check in the xmit function to determine if the stack has calculated the checksum for us. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/net/greth.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 58ec74a73150..52a39000c42c 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -491,7 +491,8 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) if (nr_frags != 0) status = GRETH_TXBD_MORE; - status |= GRETH_TXBD_CSALL; + if (skb->ip_summed == CHECKSUM_PARTIAL) + status |= GRETH_TXBD_CSALL; status |= skb_headlen(skb) & GRETH_BD_LEN; if (greth->tx_next == GRETH_TXBD_NUM_MASK) status |= GRETH_BD_WR; @@ -514,7 +515,9 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) greth->tx_skbuff[curr_tx] = NULL; bdp = greth->tx_bd_base + curr_tx; - status = GRETH_TXBD_CSALL | GRETH_BD_EN; + status = GRETH_BD_EN; + if (skb->ip_summed == CHECKSUM_PARTIAL) + status |= GRETH_TXBD_CSALL; status |= frag->size & GRETH_BD_LEN; /* Wrap around descriptor ring */ -- cgit v1.2.1 From 22e83a2926998fe132ae4dd26f1e998c70ae2e38 Mon Sep 17 00:00:00 2001 From: Henry Wong Date: Sun, 18 Sep 2011 13:41:49 +0000 Subject: ppp_generic: fix multilink fragment MTU calculation (again) When using MLPPP, the maximum size of a fragment is incorrectly calculated with an offset of -2. This patch reverses the changes in the patch found here: http://marc.info/?l=linux-netdev&m=123541324010539&w=2 The value of hdrlen includes the size of both the 2-byte PPP protocol field and the 2- or 4-byte multilink header (2+4=6 for long sequence numbers, 2+2=4 for short sequence numbers). Section 2 of RFC1661 says that the MRU that is negotiated (i.e., the MTU of the sending system) includes only the PPP payload but not the protocol field, thus the correct MTU should be the link's MTU minus the multilink header (mtu - (hdrlen-2)). The incorrect calculation causes Linux to fragment packets to a size two bytes smaller than the allowed MTU. While not technically illegal, this behaviour confounds MRU-tuning to avoid PPP-layer fragmentation. Signed-off-by: Henry Wong Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 10e5d985afa3..edfa15d2e795 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1465,7 +1465,12 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) continue; } - mtu = pch->chan->mtu - hdrlen; + /* + * hdrlen includes the 2-byte PPP protocol field, but the + * MTU counts only the payload excluding the protocol field. + * (RFC1661 Section 2) + */ + mtu = pch->chan->mtu - (hdrlen - 2); if (mtu < 4) mtu = 4; if (flen > mtu) -- cgit v1.2.1 From 710778ff878a06654175863db133293007d45aee Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 6 Sep 2011 12:44:25 +0000 Subject: gianfar: Fix overflow check and return value for gfar_get_cls_all() This function may currently fill one entry beyond the end of the array it is given. It also doesn't return an error code in case it does detect overflow. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/gianfar_ethtool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 25a8c2adb001..0caf3c323ec0 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -1669,10 +1669,10 @@ static int gfar_get_cls_all(struct gfar_private *priv, u32 i = 0; list_for_each_entry(comp, &priv->rx_list.list, list) { - if (i <= cmd->rule_cnt) { - rule_locs[i] = comp->fs.location; - i++; - } + if (i == cmd->rule_cnt) + return -EMSGSIZE; + rule_locs[i] = comp->fs.location; + i++; } cmd->data = MAX_FILER_IDX; -- cgit v1.2.1 From 97c7de055713afddf4218f19c896b5185555da15 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Tue, 20 Sep 2011 15:45:07 -0400 Subject: netconsole: switch init_netconsole() to late_initcall Commit 88491d8(drivers/net: Kconfig & Makefile cleanup) causes a regression that netconsole does not work if netconsole and network device driver are build into kernel, because netconsole is linked before network device driver. Andrew Morton suggested to fix this with initcall ordering. Fixes it by switching init_netconsole() to late_initcall. Signed-off-by: Lin Ming Signed-off-by: David S. Miller --- drivers/net/netconsole.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index dfc82720065a..ed2a3977c6e7 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -799,5 +799,11 @@ static void __exit cleanup_netconsole(void) } } -module_init(init_netconsole); +/* + * Use late_initcall to ensure netconsole is + * initialized after network device driver if built-in. + * + * late_initcall() and module_init() are identical if built as module. + */ +late_initcall(init_netconsole); module_exit(cleanup_netconsole); -- cgit v1.2.1 From b7e43381260e56840fd2fa582565c362d2fba1d9 Mon Sep 17 00:00:00 2001 From: Tanmay Upadhyay Date: Mon, 5 Sep 2011 19:32:04 +0000 Subject: net: pxa168: Fix build errors by including interrupt.h Commit a6b7a407865aab9f849dd99a71072b7cd1175116 removed linux/interrupt.h from netdevice.h. This fixes below build failure drivers/net/pxa168_eth.c: In function 'pxa168_eth_collect_events': drivers/net/pxa168_eth.c:866: error: 'IRQ_NONE' undeclared (first use in this function) drivers/net/pxa168_eth.c:866: error: (Each undeclared identifier is reported only once drivers/net/pxa168_eth.c:866: error: for each function it appears in.) drivers/net/pxa168_eth.c: At top level: drivers/net/pxa168_eth.c:913: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'pxa168_eth_int_handler' drivers/net/pxa168_eth.c: In function 'pxa168_eth_open': drivers/net/pxa168_eth.c:1133: error: implicit declaration of function 'request_irq' drivers/net/pxa168_eth.c:1133: error: 'pxa168_eth_int_handler' undeclared (first use in this function) drivers/net/pxa168_eth.c:1134: error: 'IRQF_DISABLED' undeclared (first use in this function) drivers/net/pxa168_eth.c:1160: error: implicit declaration of function 'free_irq' Signed-off-by: Tanmay Upadhyay Signed-off-by: David S. Miller --- drivers/net/pxa168_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c index 1a3033d8e7ed..d17d0624c5e6 100644 --- a/drivers/net/pxa168_eth.c +++ b/drivers/net/pxa168_eth.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.1 From 5c1e688388f629e8d8e88183b5ebc21e209252aa Mon Sep 17 00:00:00 2001 From: Kasper Pedersen Date: Tue, 20 Sep 2011 12:41:17 +0000 Subject: tg3: fix VLAN tagging regression commit 92cd3a17ce9c719abb4c28dee3438e0c641f8de4 tg3: Simplify tx bd assignments broke VLAN tagging on outbound packets. It ifdef'ed BCM_KERNEL_SUPPORTS_8021Q, but this is not set anywhere. So vlan never gets set, and all packets are sent with vlan=0. v2: We can just remove the test. vlan_tx_tag_present is valid regardless of whether the 802.1q module is built. Tested on BCM5721 rev 11. Signed-off-by: Kasper Pedersen Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index dc3fbf61910b..4a1374df6084 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6234,12 +6234,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) } } -#ifdef BCM_KERNEL_SUPPORTS_8021Q if (vlan_tx_tag_present(skb)) { base_flags |= TXD_FLAG_VLAN; vlan = vlan_tx_tag_get(skb); } -#endif if (tg3_flag(tp, USE_JUMBO_BDFLAG) && !mss && skb->len > VLAN_ETH_FRAME_LEN) -- cgit v1.2.1 From b811ce9104a7f7663ddae4f7795a194a103b8f90 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 20 Sep 2011 15:13:03 +0000 Subject: ixgbe: fix possible null buffer error It seems that at least one PPC machine would occasionally give a (valid) 0 as the return value from dma_map, this caused the ixgbe code to not work correctly. A fix is pending in the PPC tree to not return 0 from dma map, but we can also fix the driver to make sure we don't mess up in other arches as well. This patch is applicable to all current stable kernels. Ref: https://bugzilla.redhat.com/show_bug.cgi?id=683611 Reported-by: Neil Horman Signed-off-by: Jesse Brandeburg CC: Alexander Duyck CC: stable@kernel.org Tested-by: Thadeu Lima de Souza Cascardo Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 22790394318a..e1fcc9589278 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1321,8 +1321,8 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, if (ring_is_rsc_enabled(rx_ring)) pkt_is_rsc = ixgbe_get_rsc_state(rx_desc); - /* if this is a skb from previous receive DMA will be 0 */ - if (rx_buffer_info->dma) { + /* linear means we are building an skb from multiple pages */ + if (!skb_is_nonlinear(skb)) { u16 hlen; if (pkt_is_rsc && !(staterr & IXGBE_RXD_STAT_EOP) && -- cgit v1.2.1