From: Greg Kroah-Hartman Date: Wed, 11 Apr 2007 18:42:39 +0000 (-0700) Subject: start up another queue X-Git-Tag: v2.6.20.7~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=027ece83671ead95e898f1e57ce4597a7b382012;p=thirdparty%2Fkernel%2Fstable-queue.git start up another queue --- diff --git a/queue-2.6.20/dvb-pluto2-fix-incorrect-tscr-register-setting.patch b/queue-2.6.20/dvb-pluto2-fix-incorrect-tscr-register-setting.patch new file mode 100644 index 00000000000..230f4a1eda0 --- /dev/null +++ b/queue-2.6.20/dvb-pluto2-fix-incorrect-tscr-register-setting.patch @@ -0,0 +1,100 @@ +From stable-bounces@linux.kernel.org Sun Apr 8 07:57:54 2007 +From: Andreas Oberritter +Date: Sun, 08 Apr 2007 10:56:40 -0400 +Subject: DVB: pluto2: fix incorrect TSCR register setting +To: stable@kernel.org +Message-ID: <461902A8.7070309@linuxtv.org> + +From: Andreas Oberritter + +DVB: pluto2: fix incorrect TSCR register setting + +The ADEF bits in the TSCR register have different meanings in read +and write mode. For this reason ADEF has to be reset on every +read-modify-write operation. + +This patch introduces a special write function for this register, which +takes care of it. + +Thanks to Holger Magnussen for pointing my nose at this problem. + +(cherry picked from commit 1489f90a49f0603a393e1800d729050f6e332bec) + +Signed-off-by: Andreas Oberritter +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Michael Krufky +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/dvb/pluto2/pluto2.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +--- a/drivers/media/dvb/pluto2/pluto2.c ++++ b/drivers/media/dvb/pluto2/pluto2.c +@@ -149,6 +149,15 @@ static inline void pluto_rw(struct pluto + writel(val, &pluto->io_mem[reg]); + } + ++static void pluto_write_tscr(struct pluto *pluto, u32 val) ++{ ++ /* set the number of packets */ ++ val &= ~TSCR_ADEF; ++ val |= TS_DMA_PACKETS / 2; ++ ++ pluto_writereg(pluto, REG_TSCR, val); ++} ++ + static void pluto_setsda(void *data, int state) + { + struct pluto *pluto = data; +@@ -213,11 +222,11 @@ static void pluto_reset_ts(struct pluto + + if (val & TSCR_RSTN) { + val &= ~TSCR_RSTN; +- pluto_writereg(pluto, REG_TSCR, val); ++ pluto_write_tscr(pluto, val); + } + if (reenable) { + val |= TSCR_RSTN; +- pluto_writereg(pluto, REG_TSCR, val); ++ pluto_write_tscr(pluto, val); + } + } + +@@ -339,7 +348,7 @@ static irqreturn_t pluto_irq(int irq, vo + } + + /* ACK the interrupt */ +- pluto_writereg(pluto, REG_TSCR, tscr | TSCR_IACK); ++ pluto_write_tscr(pluto, tscr | TSCR_IACK); + + return IRQ_HANDLED; + } +@@ -348,9 +357,6 @@ static void __devinit pluto_enable_irqs( + { + u32 val = pluto_readreg(pluto, REG_TSCR); + +- /* set the number of packets */ +- val &= ~TSCR_ADEF; +- val |= TS_DMA_PACKETS / 2; + /* disable AFUL and LOCK interrupts */ + val |= (TSCR_MSKA | TSCR_MSKL); + /* enable DMA and OVERFLOW interrupts */ +@@ -358,7 +364,7 @@ static void __devinit pluto_enable_irqs( + /* clear pending interrupts */ + val |= TSCR_IACK; + +- pluto_writereg(pluto, REG_TSCR, val); ++ pluto_write_tscr(pluto, val); + } + + static void pluto_disable_irqs(struct pluto *pluto) +@@ -370,7 +376,7 @@ static void pluto_disable_irqs(struct pl + /* clear pending interrupts */ + val |= TSCR_IACK; + +- pluto_writereg(pluto, REG_TSCR, val); ++ pluto_write_tscr(pluto, val); + } + + static int __devinit pluto_hw_init(struct pluto *pluto) diff --git a/queue-2.6.20/dvb-tda10086-fix-diseqc-message-length.patch b/queue-2.6.20/dvb-tda10086-fix-diseqc-message-length.patch new file mode 100644 index 00000000000..04fee367327 --- /dev/null +++ b/queue-2.6.20/dvb-tda10086-fix-diseqc-message-length.patch @@ -0,0 +1,36 @@ +From stable-bounces@linux.kernel.org Sun Apr 8 07:55:51 2007 +From: Andreas Oberritter +Date: Sun, 08 Apr 2007 10:54:27 -0400 +Subject: DVB: tda10086: fix DiSEqC message length +To: stable@kernel.org +Message-ID: <46190223.1020501@linuxtv.org> + +From: Andreas Oberritter + +DVB: tda10086: fix DiSEqC message length + +Setting the message length to zero means to send one byte, so you need a +subtraction instead of an addition. + +(cherry picked from commit d420cb44693b8370cbf06c3e31b4b5dec66c9f86) + +Signed-off-by: Andreas Oberritter +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Michael Krufky +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/dvb/frontends/tda10086.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/dvb/frontends/tda10086.c ++++ b/drivers/media/dvb/frontends/tda10086.c +@@ -212,7 +212,7 @@ static int tda10086_send_master_cmd (str + for(i=0; i< cmd->msg_len; i++) { + tda10086_write_byte(state, 0x48+i, cmd->msg[i]); + } +- tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len + 1) << 4)); ++ tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len - 1) << 4)); + + tda10086_diseqc_wait(state); + diff --git a/queue-2.6.20/fix-calculation-for-size-of-filemap_attr-array-in-md-bitmap.patch b/queue-2.6.20/fix-calculation-for-size-of-filemap_attr-array-in-md-bitmap.patch new file mode 100644 index 00000000000..91f012e6145 --- /dev/null +++ b/queue-2.6.20/fix-calculation-for-size-of-filemap_attr-array-in-md-bitmap.patch @@ -0,0 +1,35 @@ +From stable-bounces@linux.kernel.org Tue Apr 10 20:32:35 2007 +From: Neil Brown +Date: Wed, 11 Apr 2007 13:31:07 +1000 +Subject: Fix calculation for size of filemap_attr array in md/bitmap. +To: Reuben Farrelly +Cc: linux-raid@vger.kernel.org, Andrew Morton , stable@kernel.org, linux-kernel@vger.kernel.org +Message-ID: <17948.22139.163549.68639@notabene.brown> + +From: Neil Brown + +If 'num_pages' were ever 1 more than a multiple of 8 (32bit platforms) +for of 16 (64 bit platforms). filemap_attr would be allocated one +'unsigned long' shorter than required. We need a round-up in there. + + +Signed-off-by: Neil Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/bitmap.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/md/bitmap.c ++++ b/drivers/md/bitmap.c +@@ -863,9 +863,7 @@ static int bitmap_init_from_disk(struct + + /* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */ + bitmap->filemap_attr = kzalloc( +- (((num_pages*4/8)+sizeof(unsigned long)-1) +- /sizeof(unsigned long)) +- *sizeof(unsigned long), ++ roundup( DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)), + GFP_KERNEL); + if (!bitmap->filemap_attr) + goto out; diff --git a/queue-2.6.20/hid-do-not-discard-truncated-input-reports.patch b/queue-2.6.20/hid-do-not-discard-truncated-input-reports.patch new file mode 100644 index 00000000000..5029c528f58 --- /dev/null +++ b/queue-2.6.20/hid-do-not-discard-truncated-input-reports.patch @@ -0,0 +1,42 @@ +From stable-bounces@linux.kernel.org Wed Apr 11 02:09:00 2007 +From: Adam Kropelin +Date: Wed, 11 Apr 2007 11:13:13 +0200 (CEST) +Subject: HID: Do not discard truncated input reports +To: stable@kernel.org +Cc: Adam Kropelin +Message-ID: + +From: Adam Kropelin + +HID: Do not discard truncated input reports + +Truncated reports should not be discarded since it prevents buggy +devices from communicating with userspace. + +Prior to the regession introduced in 2.6.20, a shorter-than-expected +report in hid_input_report() was passed thru after having the missing +bytes cleared. This behavior was established over a few patches in the +2.6.early-teens days, including commit +cd6104572bca9e4afe0dcdb8ecd65ef90b01297b. + +This patch restores the previous behavior and fixes the regression. + +Signed-off-by: Adam Kropelin +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -975,7 +975,7 @@ int hid_input_report(struct hid_device * + + if (size < rsize) { + dbg("report %d is too short, (%d < %d)", report->id, size, rsize); +- return -1; ++ memset(data + size, 0, rsize - size); + } + + if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) diff --git a/queue-2.6.20/i386-fix-file_read_actor-and-pipe_read-for-original-i386-systems.patch b/queue-2.6.20/i386-fix-file_read_actor-and-pipe_read-for-original-i386-systems.patch new file mode 100644 index 00000000000..d6cdd912777 --- /dev/null +++ b/queue-2.6.20/i386-fix-file_read_actor-and-pipe_read-for-original-i386-systems.patch @@ -0,0 +1,60 @@ +From stable-bounces@linux.kernel.org Mon Apr 2 05:26:55 2007 +From: Thomas Gleixner +Date: Mon, 02 Apr 2007 14:25:31 +0200 +Subject: i386: fix file_read_actor() and pipe_read() for original i386 systems +To: Linus Torvalds +Cc: Manfred Spraul , Adrian Bunk , Ingo Molnar , Andrew Morton +Message-ID: <1175516731.28263.129.camel@localhost.localdomain> + +From: Thomas Gleixner + +The __copy_to_user_inatomic() calls in file_read_actor() and pipe_read() +are broken on original i386 machines, where WP-works-ok == false, as +__copy_to_user_inatomic() on such systems calls functions which might +sleep and/or contain cond_resched() calls inside of a kmap_atomic() +region. + +The original check for WP-works-ok was in access_ok(), but got moved +during the 2.5 series to fix a race vs. swap. + +Return the number of bytes to copy in the case where we are in an atomic +region, so the non atomic code pathes in file_read_actor() and +pipe_read() are taken. + +This could be optimized to avoid the kmap_atomic by moving the check for +WP-works-ok into fault_in_pages_writeable(), but this is more intrusive +and can be done later. + +Signed-off-by: Thomas Gleixner +Acked-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + arch/i386/lib/usercopy.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/arch/i386/lib/usercopy.c ++++ b/arch/i386/lib/usercopy.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -719,6 +720,14 @@ unsigned long __copy_to_user_ll(void __u + #ifndef CONFIG_X86_WP_WORKS_OK + if (unlikely(boot_cpu_data.wp_works_ok == 0) && + ((unsigned long )to) < TASK_SIZE) { ++ /* ++ * When we are in an atomic section (see ++ * mm/filemap.c:file_read_actor), return the full ++ * length to take the slow path. ++ */ ++ if (in_atomic()) ++ return n; ++ + /* + * CPU does not honor the WP bit when writing + * from supervisory mode, and due to preemption or SMP, diff --git a/queue-2.6.20/kbuild-fix-dependency-generation.patch b/queue-2.6.20/kbuild-fix-dependency-generation.patch new file mode 100644 index 00000000000..61133c95423 --- /dev/null +++ b/queue-2.6.20/kbuild-fix-dependency-generation.patch @@ -0,0 +1,63 @@ +From stable-bounces@linux.kernel.org Sun Apr 1 11:41:56 2007 +From: Jan Beulich +Date: Sun, 1 Apr 2007 20:41:26 +0200 +Subject: kbuild: fix dependency generation +To: Oleg Verych +Cc: Andrew Morton , Linus Torvalds , stable@kernel.org, Jan Beulich +Message-ID: <20070401184126.GA10113@uranus.ravnborg.org> +Content-Disposition: inline + +From: Jan Beulich + +Commit 2e3646e51b2d6415549b310655df63e7e0d7a080 changed the way +the split config tree is built, but failed to also adjust fixdep +accordingly - if changing a config option from or to m, files +referencing the respective CONFIG_..._MODULE (but not the +corresponding CONFIG_...) didn't get rebuilt. + +The problem is that trisate symbol are represent with three +different symbols: +SYMBOL=n => no symbol defined +SYMBOL=y => CONFIG_SYMBOL defined to '1' +SYMBOL=m => CONFIG_SYMBOL_MODULE defined to '1' + +But conf_split_config do not distingush between the =y and =m case, +so only the =y case is honoured. +This is fixed in fixdep so when a CONFIG symbol with +_MODULE is found we skip that part and only look +for the CONFIG_SYMBOL version. + +Signed-off-by: Jan Beulich +Signed-off-by: Sam Ravnborg +Signed-off-by: Greg Kroah-Hartman + +--- + scripts/basic/fixdep.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/scripts/basic/fixdep.c ++++ b/scripts/basic/fixdep.c +@@ -28,9 +28,11 @@ + * the dependency on linux/autoconf.h by a dependency on every config + * option which is mentioned in any of the listed prequisites. + * +- * To be exact, split-include populates a tree in include/config/, +- * e.g. include/config/his/driver.h, which contains the #define/#undef +- * for the CONFIG_HIS_DRIVER option. ++ * kconfig populates a tree in include/config/ with an empty file ++ * for each config symbol and when the configuration is updated ++ * the files representing changed config options are touched ++ * which then let make pick up the changes and the files that use ++ * the config symbols are rebuilt. + * + * So if the user changes his CONFIG_HIS_DRIVER option, only the objects + * which depend on "include/linux/config/his/driver.h" will be rebuilt, +@@ -245,6 +247,8 @@ void parse_config_file(char *map, size_t + continue; + + found: ++ if (!memcmp(q - 7, "_MODULE", 7)) ++ q -= 7; + use_config(p+7, q-p-7); + } + } diff --git a/queue-2.6.20/series b/queue-2.6.20/series new file mode 100644 index 00000000000..38409c9b12e --- /dev/null +++ b/queue-2.6.20/series @@ -0,0 +1,11 @@ +kbuild-fix-dependency-generation.patch +i386-fix-file_read_actor-and-pipe_read-for-original-i386-systems.patch +sky2-reliable-recovery.patch +skge-carrier.patch +sky2-carrier.patch +sky2-ec-clocks-resume.patch +sky2-ec-u-a1.patch +dvb-tda10086-fix-diseqc-message-length.patch +dvb-pluto2-fix-incorrect-tscr-register-setting.patch +hid-do-not-discard-truncated-input-reports.patch +fix-calculation-for-size-of-filemap_attr-array-in-md-bitmap.patch diff --git a/queue-2.6.20/skge-carrier.patch b/queue-2.6.20/skge-carrier.patch new file mode 100644 index 00000000000..e0029246142 --- /dev/null +++ b/queue-2.6.20/skge-carrier.patch @@ -0,0 +1,31 @@ +From stable-bounces@linux.kernel.org Sat Apr 7 16:45:03 2007 +From: Stephen Hemminger +Date: Sat, 07 Apr 2007 16:42:06 -0700 +Subject: skge: turn carrier off when down +Cc: netdev@vger.kernel.org, stable@kernel.org +Message-ID: <20070407234235.566060329@linux-foundation.org> +Content-Disposition: inline; filename=skge-carrier.patch + +From: Stephen Hemminger + +Driver needs to turn off carrier when down, otherwise it can +confuse bonding and bridging and looks like carrier is on immediately +when it is brought back up. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/skge.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/skge.c ++++ b/drivers/net/skge.c +@@ -2462,6 +2462,7 @@ static int skge_down(struct net_device * + printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); + + netif_stop_queue(dev); ++ netif_carrier_off(dev); + if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) + cancel_rearming_delayed_work(&skge->link_thread); + diff --git a/queue-2.6.20/sky2-carrier.patch b/queue-2.6.20/sky2-carrier.patch new file mode 100644 index 00000000000..af6df1e1961 --- /dev/null +++ b/queue-2.6.20/sky2-carrier.patch @@ -0,0 +1,29 @@ +From stable-bounces@linux.kernel.org Sat Apr 7 16:44:38 2007 +From: Stephen Hemminger +Date: Sat, 07 Apr 2007 16:42:07 -0700 +Subject: sky2: turn carrier off when down +Cc: netdev@vger.kernel.org, stable@kernel.org +Message-ID: <20070407234235.799379023@linux-foundation.org> +Content-Disposition: inline; filename=sky2-carrier.patch + +From: Stephen Hemminger + +Driver needs to turn off carrier when down. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/sky2.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -1506,6 +1506,7 @@ static int sky2_down(struct net_device * + + /* Stop more packets from being queued */ + netif_stop_queue(dev); ++ netif_carrier_off(dev); + + /* Disable port IRQ */ + imask = sky2_read32(hw, B0_IMSK); diff --git a/queue-2.6.20/sky2-ec-clocks-resume.patch b/queue-2.6.20/sky2-ec-clocks-resume.patch new file mode 100644 index 00000000000..6396cdcade9 --- /dev/null +++ b/queue-2.6.20/sky2-ec-clocks-resume.patch @@ -0,0 +1,44 @@ +From stable-bounces@linux.kernel.org Sat Apr 7 16:44:47 2007 +From: Stephen Hemminger +Date: Sat, 07 Apr 2007 16:42:08 -0700 +Subject: sky2: turn on clocks when doing resume +Cc: netdev@vger.kernel.org, stable@kernel.org +Message-ID: <20070407234236.129627887@linux-foundation.org> +Content-Disposition: inline; filename=sky2-ec-clocks-resume.patch + +From: Stephen Hemminger + +Some of these chips are disabled until clock is enabled. +This fixes: + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=404107 + +Signed-off-by: Stephen Hemminger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/sky2.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -2421,6 +2421,10 @@ static int sky2_reset(struct sky2_hw *hw + return -EOPNOTSUPP; + } + ++ /* Make sure and enable all clocks */ ++ if (hw->chip_id == CHIP_ID_YUKON_EC_U) ++ sky2_pci_write32(hw, PCI_DEV_REG3, 0); ++ + hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; + + /* This rev is really old, and requires untested workarounds */ +@@ -3639,6 +3643,9 @@ static int sky2_resume(struct pci_dev *p + + pci_restore_state(pdev); + pci_enable_wake(pdev, PCI_D0, 0); ++ ++ if (hw->chip_id == CHIP_ID_YUKON_EC_U) ++ sky2_pci_write32(hw, PCI_DEV_REG3, 0); + sky2_set_power_state(hw, PCI_D0); + + err = sky2_reset(hw); diff --git a/queue-2.6.20/sky2-ec-u-a1.patch b/queue-2.6.20/sky2-ec-u-a1.patch new file mode 100644 index 00000000000..e55249e3334 --- /dev/null +++ b/queue-2.6.20/sky2-ec-u-a1.patch @@ -0,0 +1,44 @@ +From stable-bounces@linux.kernel.org Sat Apr 7 16:45:12 2007 +From: Stephen Hemminger +Date: Sat, 07 Apr 2007 16:42:09 -0700 +Subject: sky2: phy workarounds for Yukon EC-U A1 +Cc: netdev@vger.kernel.org, stable@kernel.org +Message-ID: <20070407234236.256434192@linux-foundation.org> +Content-Disposition: inline; filename=sky2-ec-u-a1.patch + +From: Stephen Hemminger + +The workaround Yukon EC-U wasn't comparing with correct +version and wasn't doing correct setup. Without it, 88e8056 +throws all sorts of errors. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/sky2.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -524,9 +524,9 @@ static void sky2_phy_init(struct sky2_hw + ledover &= ~PHY_M_LED_MO_RX; + } + +- if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) { ++ if (hw->chip_id == CHIP_ID_YUKON_EC_U && ++ hw->chip_rev == CHIP_REV_YU_EC_U_A1) { + /* apply fixes in PHY AFE */ +- pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255); + + /* increase differential signal amplitude in 10BASE-T */ +@@ -538,7 +538,7 @@ static void sky2_phy_init(struct sky2_hw + gm_phy_write(hw, port, 0x17, 0x2002); + + /* set page register to 0 */ +- gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); ++ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); + } else { + gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); + diff --git a/queue-2.6.20/sky2-reliable-recovery.patch b/queue-2.6.20/sky2-reliable-recovery.patch new file mode 100644 index 00000000000..1e3974d8204 --- /dev/null +++ b/queue-2.6.20/sky2-reliable-recovery.patch @@ -0,0 +1,143 @@ +From stable-bounces@linux.kernel.org Wed Apr 4 11:12:04 2007 +From: Stephen Hemminger +Date: Wed, 4 Apr 2007 11:10:43 -0700 +Subject: sky2: reliable recovery +To: stable@kernel.org +Cc: +Message-ID: <20070404111043.28ecce69@freekitty> + +From: Stephen Hemminger + +This adds working recovery from transmit timeouts. Previous code +didn't do enough to truly reset chip. + +It is a backport of the 2.6.21 code. + +Signed-off-by: Stephen Hemminger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/sky2.c | 81 +++++++++++++++++++++++++++++++++++------------------ + drivers/net/sky2.h | 1 + 2 files changed, 56 insertions(+), 26 deletions(-) + +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -1802,38 +1802,22 @@ static void sky2_tx_timeout(struct net_d + { + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; +- unsigned txq = txqaddr[sky2->port]; +- u16 report, done; ++ unsigned port = sky2->port; + + if (netif_msg_timer(sky2)) + printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); + +- report = sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX); +- done = sky2_read16(hw, Q_ADDR(txq, Q_DONE)); +- +- printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", +- dev->name, +- sky2->tx_cons, sky2->tx_prod, report, done); +- +- if (report != done) { +- printk(KERN_INFO PFX "status burst pending (irq moderation?)\n"); ++ /* Get information for bug report :-) */ ++ printk(KERN_INFO PFX "%s: transmit ring %u .. %u report=%u done=%u\n", ++ dev->name, sky2->tx_cons, sky2->tx_prod, ++ sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), ++ sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE))); + +- sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); +- sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); +- } else if (report != sky2->tx_cons) { +- printk(KERN_INFO PFX "status report lost?\n"); +- sky2_tx_complete(sky2, report); +- } else { +- printk(KERN_INFO PFX "hardware hung? flushing\n"); ++ printk(KERN_INFO PFX "gmac control %#x status %#x\n", ++ gma_read16(hw, port, GM_GP_CTRL), gma_read16(hw, port, GM_GP_STAT)); + +- sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); +- sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); +- +- sky2_tx_complete(sky2, sky2->tx_prod); +- +- sky2_qset(hw, txq); +- sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); +- } ++ /* can't restart safely under softirq */ ++ schedule_work(&hw->restart_work); + } + + static int sky2_change_mtu(struct net_device *dev, int new_mtu) +@@ -2565,6 +2549,49 @@ static int sky2_reset(struct sky2_hw *hw + return 0; + } + ++static void sky2_restart(struct work_struct *work) ++{ ++ struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work); ++ struct net_device *dev; ++ int i, err; ++ ++ dev_dbg(&hw->pdev->dev, "restarting\n"); ++ ++ del_timer_sync(&hw->idle_timer); ++ ++ rtnl_lock(); ++ sky2_write32(hw, B0_IMSK, 0); ++ sky2_read32(hw, B0_IMSK); ++ ++ netif_poll_disable(hw->dev[0]); ++ ++ for (i = 0; i < hw->ports; i++) { ++ dev = hw->dev[i]; ++ if (netif_running(dev)) ++ sky2_down(dev); ++ } ++ ++ sky2_reset(hw); ++ sky2_write32(hw, B0_IMSK, Y2_IS_BASE); ++ netif_poll_enable(hw->dev[0]); ++ ++ for (i = 0; i < hw->ports; i++) { ++ dev = hw->dev[i]; ++ if (netif_running(dev)) { ++ err = sky2_up(dev); ++ if (err) { ++ printk(KERN_INFO PFX "%s: could not restart %d\n", ++ dev->name, err); ++ dev_close(dev); ++ } ++ } ++ } ++ ++ sky2_idle_start(hw); ++ ++ rtnl_unlock(); ++} ++ + static u32 sky2_supported_modes(const struct sky2_hw *hw) + { + if (sky2_is_copper(hw)) { +@@ -3508,6 +3535,8 @@ static int __devinit sky2_probe(struct p + } + + setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); ++ INIT_WORK(&hw->restart_work, sky2_restart); ++ + sky2_idle_start(hw); + + pci_set_drvdata(pdev, hw); +--- a/drivers/net/sky2.h ++++ b/drivers/net/sky2.h +@@ -1898,6 +1898,7 @@ struct sky2_hw { + dma_addr_t st_dma; + + struct timer_list idle_timer; ++ struct work_struct restart_work; + int msi; + wait_queue_head_t msi_wait; + };