2.6.22.2 -stable review
Subsystems (45)
cover 2.6.22.2 -stable review
So sorry for the delay in getting the .22.y release out, my appologies. I think I've gotten all the patches that people have sent us, _and_ are already in Linus's tree. If you have sent us stuff that I have missed, please resend. If you have sent us patches that are not in Linus's tree yet, please be sure to notify us when they do go into his tree in order for us to be able to add them to the next review cycle.
This is the start of the stable review cycle for the 2.6.22.2 release. There are 84 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let us know. If anyone is a maintainer of the proper subsystem, and wants to add a Signed-off-by: line to the patch, please respond with it.
These patches are sent out with a number of different people on the Cc:
line. If you wish to be a reviewer, please email [email protected] to add your name to the list. If you want to be off the reviewer list, also email us.
Responses should be made by August 9, 2007 19:00:00 UTC. Anything received after that time might be too late.
thanks,
greg k-h
PATCH 1/84 USB: cdc-acm: fix sysfs attribute registration bug
From: Alan Stern <[email protected]>
This patch (as950) fixes a bug in the cdc-acm driver. It doesn't keep track of which interface (control or data) the sysfs attributes get registered for, and as a result, during disconnect it will sometimes attempt to remove the attributes from the wrong interface. The left-over attributes can cause a crash later on, particularly if the driver module has been unloaded.
--- drivers/usb/class/cdc-acm.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/usb/class/cdc-acm.c +9 -3
@@ -919,6 +919,10 @@ skip_normal_probe:return -EINVAL ; } } + +/* Accept probe requests only for the control interface */ +if (intf != control_interface) +return -ENODEV ;if (usb_interface_claimed (data_interface)) {/* valid in this context */ dev_dbg (&intf->dev,"The data interface isn't available" );
@@ -1107,10 +1111,12 @@ static void acm_disconnect(struct usb_inreturn ; }if (acm->country_codes){ -device_remove_file (&intf->dev, &dev_attr_wCountryCodes); -device_remove_file (&intf->dev, &dev_attr_iCountryCodeRelDate); +device_remove_file (&acm->control->dev, + &dev_attr_wCountryCodes); +device_remove_file (&acm->control->dev, + &dev_attr_iCountryCodeRelDate); } -device_remove_file (&intf->dev, &dev_attr_bmCapabilities); +device_remove_file (&acm->control->dev, &dev_attr_bmCapabilities); acm->dev =NULL ;usb_set_intfdata (acm->control,NULL );usb_set_intfdata (acm->data,NULL );
PATCH 2/84 TCP FRTO retransmit bug fix
In reply to Greg KHFrom: Ilpo J�rvinen <[email protected]>
[TCP]: Verify the presence of RETRANS bit when leaving FRTO
For yet unknown reason, something cleared SACKED_RETRANS bit underneath FRTO.
--- net/ipv4/tcp_input.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/ipv4/tcp_input.c +3 -1
@@ -1398,7 +1398,9 @@ static void tcp_enter_frto_loss(struct s* waiting for the first ACK and did not get it)... */ if ((tp->frto_counter ==1 ) && !(flag&FLAG_DATA_ACKED )) { - tp->retrans_out +=tcp_skb_pcount (skb); +/* For some reason this R-bit might get cleared? */ +if (TCP_SKB_CB (skb)->sacked &TCPCB_SACKED_RETRANS ) + tp->retrans_out +=tcp_skb_pcount (skb);/* ...enter this if branch just for the first segment */ flag |=FLAG_DATA_ACKED ; }else {
PATCH 3/84 Fix TC deadlock.
In reply to Greg KHFrom: Patrick McHardy <[email protected]>
[NET_SCHED]: Revert "avoid transmit softirq on watchdog wakeup" optimization
As noticed by Ranko Zivojnovic <[email protected]>, calling qdisc_run from the timer handler can result in deadlock:
Quoted 14 lines
CPU#0
qdisc_watchdog()fires and getsdev->queue_lockqdisc_run()...qdisc_restart()...
-> releasesdev->queue_lockand entersdev_hard_start_xmit()CPU#1
tc del qdisc dev ... qdisc_graft()...dev_graft_qdisc()...dev_deactivate()... -> grabs
dev->queue_lock...qdisc_reset()...{cbq,hfsc,htb,netem,tbf}_reset()...qdisc_watchdog_cancel()... ->
hrtimer_cancel()- waiting for theqdisc_watchdog()to exit, while still
Quoted 8 lines
holding dev->queue_lockCPU#0
dev_hard_start_xmit()returns ...
-> wants to getdev->queue_lock(!)DEADLOCK!
The entire optimization is a bit questionable IMO, it moves potentially large parts of NET_TX_SOFTIRQ work to TIMER_SOFTIRQ/HRTIMER_SOFTIRQ, which kind of defeats the separation of them.
--- net/sched/sch_api.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
net/sched/sch_api.c +1 -5
@@ -290,11 +290,7 @@ static enum hrtimer_restart qdisc_watchd wd->qdisc->flags &= ~TCQ_F_THROTTLED ;smp_wmb (); -if (spin_trylock (&dev->queue_lock)) { -qdisc_run (dev); -spin_unlock (&dev->queue_lock); - }else -netif_schedule (dev); +netif_schedule (dev);return HRTIMER_NORESTART ; }
PATCH 4/84 Fix IPCOMP crashes.
In reply to Greg KHFrom: Patrick McHardy <[email protected]>
[XFRM]: Fix crash introduced by struct dst_entry reordering
XFRM expects xfrm_dst->u.next to be same pointer as dst->next, which was broken by the dst_entry reordering in commit 1e19e02c~, causing an oops in xfrm_bundle_ok when walking the bundle upwards.
Kill xfrm_dst->u.next and change the only user to use dst->next instead.
--- include/net/xfrm.h | 1 - net/xfrm/xfrm_policy.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-)
include/net/xfrm.h +0 -1
@@ -577,7 +577,6 @@ static inline int xfrm_sec_ctx_match(strstruct xfrm_dst {union { -struct xfrm_dst *next;struct dst_entry dst;struct rtable rt;struct rt6_info rt6;
net/xfrm/xfrm_policy.c +1 -1
@@ -2141,7 +2141,7 @@ int xfrm_bundle_ok(struct xfrm_policy *pif (last == first)break ; - last = last->u.next; + last = (struct xfrm_dst *)last->u.dst.next; last->child_mtu_cached = mtu; }
PATCH 5/84 Fix deadlocks in sparc serial console.
In reply to Greg KHFrom: David S. Miller <[email protected]>
Subject: [2.6.22.2 review 05/84] [PATCH] [SERIAL]: Fix console write locking in sparc drivers.
Mirror the logic in 8250 for proper console write locking when SYSRQ is triggered or an OOPS is in progress.
--- drivers/serial/sunhv.c | 30 ++++++++++++++++++++++++++---- drivers/serial/sunsab.c | 19 ++++++++++++++----- drivers/serial/sunsu.c | 14 ++++++++++++++ drivers/serial/sunzilog.c | 17 ++++++++++++++--- 4 files changed, 68 insertions(+), 12 deletions(-)
drivers/serial/sunhv.c +26 -4
@@ -440,8 +440,16 @@ static void sunhv_console_write_paged(st {struct uart_port *port = sunhv_port;unsigned long flags; +int locked =1 ; + +local_irq_save (flags); +if (port->sysrq) { + locked =0 ; + }else if (oops_in_progress) { + locked =spin_trylock (&port->lock); + }else +spin_lock (&port->lock); -spin_lock_irqsave (&port->lock, flags);while (n >0 ) {unsigned long ra =__pa (con_write_page);unsigned long page_bytes;
@@ -469,7 +477,10 @@ static void sunhv_console_write_paged(st ra += written; } } -spin_unlock_irqrestore (&port->lock, flags); + +if (locked) +spin_unlock (&port->lock); +local_irq_restore (flags); }static inline void sunhv_console_putchar (struct uart_port *port,char c)
@@ -488,7 +499,15 @@ static void sunhv_console_write_bychar(s {struct uart_port *port = sunhv_port;unsigned long flags; -int i; +int i, locked =1 ; + +local_irq_save (flags); +if (port->sysrq) { + locked =0 ; + }else if (oops_in_progress) { + locked =spin_trylock (&port->lock); + }else +spin_lock (&port->lock);spin_lock_irqsave (&port->lock, flags);for (i =0 ; i < n; i++) {
@@ -496,7 +515,10 @@ static void sunhv_console_write_bychar(ssunhv_console_putchar (port,'\r' );sunhv_console_putchar (port, *s++); } -spin_unlock_irqrestore (&port->lock, flags); + +if (locked) +spin_unlock (&port->lock); +local_irq_restore (flags); }static struct console sunhv_console = {
drivers/serial/sunsab.c +14 -5
@@ -860,22 +860,31 @@ static int num_channels;static void sunsab_console_putchar (struct uart_port *port,int c) {struct uart_sunsab_port *up = (struct uart_sunsab_port *)port; -unsigned long flags; - -spin_lock_irqsave (&up->port.lock, flags);sunsab_tec_wait (up);writeb (c, &up->regs->w.tic); - -spin_unlock_irqrestore (&up->port.lock, flags); }static void sunsab_console_write (struct console *con,const char *s,unsigned n) {struct uart_sunsab_port *up = &sunsab_ports[con->index]; +unsigned long flags; +int locked =1 ; + +local_irq_save (flags); +if (up->port.sysrq) { + locked =0 ; + }else if (oops_in_progress) { + locked =spin_trylock (&up->port.lock); + }else +spin_lock (&up->port.lock);uart_console_write (&up->port, s, n, sunsab_console_putchar);sunsab_tec_wait (up); + +if (locked) +spin_unlock (&up->port.lock); +local_irq_restore (flags); }static int sunsab_console_setup (struct console *con,char *options)
drivers/serial/sunsu.c +14 -0
@@ -1288,7 +1288,17 @@ static void sunsu_console_write(struct c unsigned int count) {struct uart_sunsu_port *up = &sunsu_ports[co->index]; +unsigned long flags;unsigned int ier; +int locked =1 ; + +local_irq_save (flags); +if (up->port.sysrq) { + locked =0 ; + }else if (oops_in_progress) { + locked =spin_trylock (&up->port.lock); + }else +spin_lock (&up->port.lock);/* * First save the UER then disable the interrupts
@@ -1304,6 +1314,10 @@ static void sunsu_console_write(struct c*/ wait_for_xmitr (up);serial_out (up,UART_IER , ier); + +if (locked) +spin_unlock (&up->port.lock); +local_irq_restore (flags); }/*
drivers/serial/sunzilog.c +14 -3
@@ -9,7 +9,7 @@* C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their * work there. * -* Copyright (C) 2002, 2006 David S. Miller ([email protected]) +* Copyright (C) 2002, 2006, 2007 David S. Miller ([email protected]) */ #include <linux/module.h>
@@ -1151,11 +1151,22 @@ sunzilog_console_write(struct console *c {struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];unsigned long flags; +int locked =1 ; + +local_irq_save (flags); +if (up->port.sysrq) { + locked =0 ; + }else if (oops_in_progress) { + locked =spin_trylock (&up->port.lock); + }else +spin_lock (&up->port.lock); -spin_lock_irqsave (&up->port.lock, flags);uart_console_write (&up->port, s, count, sunzilog_putchar);udelay (2 ); -spin_unlock_irqrestore (&up->port.lock, flags); + +if (locked) +spin_unlock (&up->port.lock); +local_irq_restore (flags); }static int __init sunzilog_console_setup (struct console *con,char *options)
PATCH 6/84 Add a PCI ID for santa rosas PATA controller.
In reply to Greg KHFrom: Christian Lamparter <[email protected]>
This is commit c1e6f28cc5de37dcd113b9668a185c0b9334ba8a which is merged during 23-rc1 window. Considering the popularity of these chips, I think including it in -stable release would be good idea.
--- drivers/ata/ata_piix.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/ata/ata_piix.c +2 -0
@@ -200,6 +200,8 @@ static const struct pci_device_id piix_p/* ICH7/7-R (i945, i975) UDMA 100*/ { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, +/* ICH8 Mobile PATA Controller */ + { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },/* NOTE: The following PCI ids must be kept in sync with the * list in drivers/pci/quirks.c.
Re: [2.6.22.2 review 06/84] Add a PCI ID for santa rosas PATA controller.
Quoted 11 lines · Greg KH
From: Christian Lamparter <[email protected]>
This is commit
c1e6f28cc5de37dcd113b9668a185c0b9334ba8awhich is merged during 23-rc1 window. Considering the popularity of these chips, I think including it in -stable release would be good idea.Signed-off-by Christian Lamparter <[email protected]>Signed-off-by Jeff Garzik <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>
I did not receive any complains. I guess it's stable enough for -stable ;-) ...
---
Not OT:
There is another outstanding issue with ata_piix.c.
Intel has never officially supported anything faster than PATA 100MB/s.
But, the ata_piix.c driver "define" the ICH5 & ICH7 as UDMA6 (aka 133MB/s) capable. [ Well, no one has probably noticed it before, because there is bug in do_pata_set_dmamode... Just look at libata_atapiix_enable_real_udma133.patch and you'll see what wrong with it. ]
Here are Intel's datasheets for the affected chipsets:
ICH5 Datasheet: http://www.intel.com/design/chipsets/datashts/252516.htm
(See note on page 183: "... the ICH5 supports reads at the maximum rate of 100MB/s.")
ICH7 Datasheet: http://www.intel.com/design/chipsets/datashts/307013.htm
(See first note on page 190: "... the ICH7 supports reads at the maximum rate of 100MB/s.")
-
They are two different ways to deal with it:
- Either -
1. replace all ich_pata_133 with ich_pata_100. (libata_atapiix_disable_udma6.diff - diff from 2.6.22 )
- Or -
2. keep all ich_pata_133 and fix the bug in "do_pata_set_dmamode". (libata_atapiix_enable_real_udma133.patch - diff from 2.6.22)
If there are any concerns about the safety of the patch patch:
http://lkml.org/lkml/2007/7/6/292 (It was already tested by an Intel employee, but I guess a bit more user input is necessary here... )
Both ways have their pros and cons. Unfortunately, I don't have the time to follow this discussion right now, so here's a:
(Just in case, if one of the patches really gets merged!)
Thanks,
Chr.
drivers/ata/ata_piix.c +4 -4
@@ -122,7 +122,7 @@ enum { ich_pata_33 =1 ,/* ICH up to UDMA 33 only */ ich_pata_66 =2 ,/* ICH up to 66 Mhz */ ich_pata_100 =3 ,/* ICH up to UDMA 100 */ - ich_pata_133 =4 ,/* ICH up to UDMA 133 */ +/* ICH up to UDMA 133 is not supported */ ich5_sata =5 , ich6_sata =6 , ich6_sata_ahci = 7,
@@ -190,7 +190,7 @@ static const struct pci_device_id piix_p { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },/* Intel ICH5 */ - { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, + { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },/* C-ICH (i810E2) */ { 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* ESB (855GME/875P + 6300ESB) UDMA 100 */
@@ -198,7 +198,7 @@ static const struct pci_device_id piix_p/* ICH6 (and 6) (i915) UDMA 100 */ { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },/* ICH7/7-R (i945, i975) UDMA 100*/ - { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, + { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },/* NOTE: The following PCI ids must be kept in sync with the
@@ -479,7 +479,7 @@ static struct ata_port_info piix_port_in .port_ops = &ich_pata_ops, }, -/* ich_pata_133: 4 ICH with full UDMA6 */ +/* ich_pata_133: 4 - Not supported - */ { .sht = &piix_sht, .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
drivers/ata/ata_piix.c +2 -2
@@ -765,8 +765,8 @@ static void do_pata_set_dmamode (struct* except UDMA0 which is 00 */ u_speed =min (2 - (udma &1 ), udma); -if (udma ==5 ) - u_clock =0x1000 ;/* 100Mhz */ +if (udma >=5 ) + u_clock =0x1000 ;/* 133Mhz */ else if (udma >2 ) u_clock =1 ;/* 66Mhz */ else
Andrew Morton
maintainerRe: [2.6.22.2 review 06/84] Add a PCI ID for santa rosas PATA controller.
Quoted 50 lines · On Wed, 8 Aug 2007 01:39:12 +0200 Chr <[email protected]> wrote:
Quoted 11 lines · Greg KH
From: Christian Lamparter <[email protected]>
This is commit
c1e6f28cc5de37dcd113b9668a185c0b9334ba8awhich is merged during 23-rc1 window. Considering the popularity of these chips, I think including it in -stable release would be good idea.Signed-off-by Christian Lamparter <[email protected]>Signed-off-by Jeff Garzik <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>I did not receive any complains. I guess it's stable enough for -stable ;-) ...
---
Not OT:
There is another outstanding issue with
ata_piix.c.
Intel has never officially supported anything faster than PATA 100MB/s.But, the
ata_piix.cdriver "define" the ICH5 & ICH7 as UDMA6 (aka 133MB/s) capable. [ Well, no one has probably noticed it before, because there is bug indo_pata_set_dmamode... Just look at libata_atapiix_enable_real_udma133.patch and you'll see what wrong with it. ]Here are Intel's datasheets for the affected chipsets:
ICH5 Datasheet: http://www.intel.com/design/chipsets/datashts/252516.htm
(See note on page 183: "... the ICH5 supports reads at the maximum rate of 100MB/s.")ICH7 Datasheet: http://www.intel.com/design/chipsets/datashts/307013.htm
(See first note on page 190: "... the ICH7 supports reads at the maximum rate of 100MB/s.")-
They are two different ways to deal with it:
- Either -
1. replace all
ich_pata_133withich_pata_100. (libata_atapiix_disable_udma6.diff - diff from 2.6.22 )- Or -
2. keep all
ich_pata_133and fix the bug in "do_pata_set_dmamode". (libata_atapiix_enable_real_udma133.patch - diff from 2.6.22)
If there are any concerns about the safety of the patch patch:
http://lkml.org/lkml/2007/7/6/292 (It was already tested by an Intel employee, but I guess a bit more user input is necessary here... )
Quoted 6 lines
Both ways have their pros and cons. Unfortunately, I don't have the time to follow this discussion right now, so here's a:
Signed-off-by Christian Lamparter <[email protected]>(Just in case, if one of the patches really gets merged!)
You kinda hid these patches rather well.
I chose option 1.
PATCH 7/84 Missing header include in ipt_iprange.h
In reply to Greg KHFrom: Adrian Bunk <[email protected]>
[NETFILTER]: ipt_iprange.h must #include <linux/types.h>
ipt_iprange.h must #include <linux/types.h> since it uses __be32.
This patch fixes kernel Bugzilla #7604.
--- include/linux/netfilter_ipv4/ipt_iprange.h | 2 ++ 1 file changed, 2 insertions(+)
include/linux/netfilter_ipv4/ipt_iprange.h +2 -0
@@ -1,6 +1,8 @@#ifndef _IPT_IPRANGE_H#define _IPT_IPRANGE_H +#include <linux/types.h> +#define IPRANGE_SRC 0x01/* Match source IP address */ #define IPRANGE_DST 0x02/* Match destination IP address */ #define IPRANGE_SRC_INV 0x10/* Negate the condition */
PATCH 8/84 SCTP scope_id handling fix
In reply to Greg KHFrom: Vlad Yasevich <[email protected]>
SCTP: Add scope_id validation for link-local binds
SCTP currently permits users to bind to link-local addresses, but doesn't verify that the scope id specified at bind matches the interface that the address is configured on. It was report that this can hang a system.
--- net/sctp/ipv6.c | 4 ++++ 1 file changed, 4 insertions(+)
net/sctp/ipv6.c +4 -0
@@ -875,6 +875,10 @@ static int sctp_inet6_send_verify(struct dev =dev_get_by_index (addr->v6.sin6_scope_id);if (!dev)return 0 ; +if (!ipv6_chk_addr (&addr->v6.sin6_addr, dev,0 )) { +dev_put (dev); +return 0 ; + }dev_put (dev); } af = opt->pf->af;
PATCH 9/84 Fix rfkill IRQ flags.
In reply to Greg KHFrom: Ingo Molnar <[email protected]>
[RFKILL]: fix net/rfkill/rfkill-input.c bug on 64-bit systems
Subject: [2.6.22.2 review 09/84] [patch] net/input: fix net/rfkill/rfkill-input.c bug on 64-bit systems
this recent commit:
commit cf4328cd949c2086091c62c5685f1580fe9b55e4
Author: Ivo van Doorn <[email protected]>
Date: Mon May 7 00:34:20 2007 -0700
[NET]: rfkill: add support for input key to control wireless radio
added this 64-bit bug:
.... unsigned int flags;
spin_lock_irqsave(&task->lock, flags);
....irq 'flags' must be unsigned long, not unsigned int. The -rt tree has strict checks about this on 64-bit so this triggered a build failure.
--- net/rfkill/rfkill-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/rfkill/rfkill-input.c +1 -1
@@ -55,7 +55,7 @@ static void rfkill_task_handler(struct wstatic void rfkill_schedule_toggle (struct rfkill_task *task) { -unsigned int flags; +unsigned long flags;spin_lock_irqsave (&task->lock, flags);
Re: [2.6.22.2 review 09/84] Fix rfkill IRQ flags.
Quoted 11 lines · Greg KH
added this 64-bit bug:
.... unsigned int flags; spin_lock_irqsave(&task->lock, flags); ....irq 'flags' must be unsigned long, not unsigned int. The -rt tree has strict checks about this on 64-bit so this triggered a build failure.
Since the check is a compile-time one, would not it be good to add it to the regular linux tree too?
Jan
Re: [2.6.22.2 review 09/84] Fix rfkill IRQ flags.
Quoted 8 lines · Jan Engelhardt
Quoted 6 lines · Greg KH
added this 64-bit bug:
.... unsigned int flags;
Quoted 8 lines
Quoted 5 lines
spin_lock_irqsave(&task->lock, flags); ....irq 'flags' must be unsigned long, not unsigned int. The -rt tree has strict checks about this on 64-bit so this triggered a build failure.
Since the check is a compile-time one, would not it be good to add it to the regular linux tree too?
BUILD_BUG_ON was tried, but due to amazingly wrong moment of merging survived only for a day or so. There will be a second try, though.
PATCH 10/84 gen estimator timer unload race
In reply to Greg KHFrom: Patrick McHardy <[email protected]>
[NET]: Fix gen_estimator timer removal race
As noticed by Jarek Poplawski <[email protected]>, the timer removal in gen_kill_estimator races with the timer function rearming the timer.
Check whether the timer list is empty before rearming the timer in the timer function to fix this.
--- net/core/gen_estimator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/core/gen_estimator.c +2 -1
@@ -128,7 +128,8 @@ static void est_timer(unsigned long arg)spin_unlock (e->stats_lock); } -mod_timer (&elist[idx].timer, jiffies + ((HZ <<idx)/4 )); +if (elist[idx].list !=NULL ) +mod_timer (&elist[idx].timer, jiffies + ((HZ <<idx)/4 ));read_unlock (&est_lock); }
PATCH 11/84 gen estimator deadlock fix
In reply to Greg KHFrom: Ranko Zivojnovic <[email protected]>
[NET]: gen_estimator deadlock fix
-Fixes ABBA deadlock noted by Patrick McHardy <[email protected]>:
Quoted 7 lines
There is at least one ABBA deadlock,
est_timer()does:read_lock(&est_lock)spin_lock(e->stats_lock)(which isdev->queue_lock)and
qdisc_destroycallshtb_destroyunderdev->queue_lock, which callshtb_destroy_class, thengen_kill_estimatorand thiswrite_locksest_lock.
To fix the ABBA deadlock the rate estimators are now kept on an rcu list.
-The est_lock changes the use from protecting the list to protecting the update to the 'bstat' pointer in order to avoid NULL dereferencing.
-The 'interval' member of the gen_estimator structure removed as it is not needed.
--- net/core/gen_estimator.c | 81 ++++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 32 deletions(-)
net/core/gen_estimator.c +49 -32
@@ -79,27 +79,27 @@struct gen_estimator { -struct gen_estimator *next; +struct list_head list;struct gnet_stats_basic *bstats;struct gnet_stats_rate_est *rate_est;spinlock_t *stats_lock; -unsigned interval;int ewma_log;u64 last_bytes;u32 last_packets;u32 avpps;u32 avbps; +struct rcu_head e_rcu; };struct gen_estimator_head {struct timer_list timer; -struct gen_estimator *list; +struct list_head list; };static struct gen_estimator_head elist[EST_MAX_INTERVAL +1 ]; -/* Estimator array lock */ +/* Protects against NULL dereference */ static DEFINE_RWLOCK (est_lock);static void est_timer (unsigned long arg)
@@ -107,13 +107,17 @@ static void est_timer(unsigned long arg)int idx = (int )arg;struct gen_estimator *e; -read_lock (&est_lock); -for (e = elist[idx].list; e; e = e->next) { +rcu_read_lock (); +list_for_each_entry_rcu (e, &elist[idx].list, list) {u64 nbytes;u32 npackets;u32 rate;spin_lock (e->stats_lock); +read_lock (&est_lock); +if (e->bstats ==NULL ) + goto skip; + nbytes = e->bstats->bytes; npackets = e->bstats->packets; rate = (nbytes - e->last_bytes)<<(7 - idx);
@@ -125,12 +129,14 @@ static void est_timer(unsigned long arg) e->last_packets = npackets; e->avpps += ((long )rate - (long )e->avpps) >> e->ewma_log; e->rate_est->pps = (e->avpps+0x1FF )>>10 ; +skip: +read_unlock (&est_lock);spin_unlock (e->stats_lock); } -if (elist[idx].list !=NULL ) +if (!list_empty (&elist[idx].list))mod_timer (&elist[idx].timer, jiffies + ((HZ <<idx)/4 )); -read_unlock (&est_lock); +rcu_read_unlock (); }/**
@@ -147,12 +153,17 @@ static void est_timer(unsigned long arg)* &rate_est with the statistics lock grabed during this period. * * Returns 0 on success or a negative error code. +* +* NOTE: Called under rtnl_mutex */ int gen_new_estimator (struct gnet_stats_basic *bstats, -struct gnet_stats_rate_est *rate_est,spinlock_t *stats_lock,struct rtattr *opt) +struct gnet_stats_rate_est *rate_est, +spinlock_t *stats_lock, +struct rtattr *opt) {struct gen_estimator *est;struct gnet_estimator *parm =RTA_DATA (opt); +int idx;if (RTA_PAYLOAD (opt) <sizeof (*parm))return -EINVAL ;
@@ -164,7 +175,7 @@ int gen_new_estimator(struct gnet_stats_if (est ==NULL )return -ENOBUFS ; - est->interval = parm->interval +2 ; + idx = parm->interval +2 ; est->bstats = bstats; est->rate_est = rate_est; est->stats_lock = stats_lock;
@@ -174,20 +185,25 @@ int gen_new_estimator(struct gnet_stats_ est->last_packets = bstats->packets; est->avpps = rate_est->pps<<10 ; - est->next = elist[est->interval].list; -if (est->next ==NULL ) { -init_timer (&elist[est->interval].timer); - elist[est->interval].timer.data = est->interval; - elist[est->interval].timer.expires = jiffies + ((HZ <<est->interval)/4 ); - elist[est->interval].timer.function = est_timer; -add_timer (&elist[est->interval].timer); +if (!elist[idx].timer.function) { +INIT_LIST_HEAD (&elist[idx].list); +setup_timer (&elist[idx].timer, est_timer, idx); } -write_lock_bh (&est_lock); - elist[est->interval].list = est; -write_unlock_bh (&est_lock); + +if (list_empty (&elist[idx].list)) +mod_timer (&elist[idx].timer, jiffies + ((HZ <<idx)/4 )); + +list_add_rcu (&est->list, &elist[idx].list);return 0 ; } +static void __gen_kill_estimator (struct rcu_head *head) +{ +struct gen_estimator *e =container_of (head, + struct gen_estimator, e_rcu); +kfree (e); +} +/** * gen_kill_estimator - remove a rate estimator * @bstats: basic statistics
@@ -195,31 +211,32 @@ int gen_new_estimator(struct gnet_stats_* * Removes the rate estimator specified by &bstats and &rate_est * and deletes the timer. +* +* NOTE: Called under rtnl_mutex */ void gen_kill_estimator (struct gnet_stats_basic *bstats,struct gnet_stats_rate_est *rate_est) {int idx; -struct gen_estimator *est, **pest; +struct gen_estimator *e, *n;for (idx=0 ; idx <=EST_MAX_INTERVAL ; idx++) { -int killed =0 ; - pest = &elist[idx].list; -while ((est=*pest) !=NULL ) { -if (est->rate_est != rate_est || est->bstats != bstats) { - pest = &est->next; + +/* Skip non initialized indexes */ +if (!elist[idx].timer.function) +continue ; + +list_for_each_entry_safe (e, n, &elist[idx].list, list) { +if (e->rate_est != rate_est || e->bstats != bstats)continue ; - }write_lock_bh (&est_lock); - *pest = est->next; + e->bstats =NULL ;write_unlock_bh (&est_lock); -kfree (est); - killed++; +list_del_rcu (&e->list); +call_rcu (&e->e_rcu, __gen_kill_estimator); } -if (killed && elist[idx].list ==NULL ) -del_timer (&elist[idx].timer); } }
PATCH 12/84 Fix error queue socket lookup in ipv6
In reply to Greg KHFrom: Dmitry Butskoy <[email protected]>
[IPV6]: MSG_ERRQUEUE messages do not pass to connected raw sockets
From: Dmitry Butskoy <[email protected]>
Taken from http://bugzilla.kernel.org/show_bug.cgi?id=8747
Problem Description:
It is related to the possibility to obtain MSG_ERRQUEUE messages from the udp and raw sockets, both connected and unconnected.
There is a little typo in net/ipv6/icmp.c code, which prevents such messages to be delivered to the errqueue of the correspond raw socket, when the socket is CONNECTED. The typo is due to swap of local/remote addresses.
Consider __raw_v6_lookup() function from net/ipv6/raw.c. When a raw socket is looked up usual way, it is something like:
sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
where "daddr" is a destination address of the incoming packet (IOW our local address), "saddr" is a source address of the incoming packet (the remote end).
But when the raw socket is looked up for some icmp error report, in net/ipv6/icmp.c:icmpv6_notify() , daddr/saddr are obtained from the echoed fragment of the "bad" packet, i.e. "daddr" is the original destination address of that packet, "saddr" is our local address. Hence, for icmpv6_notify() must use "saddr, daddr" in its arguments, not "daddr, saddr"
...
Steps to reproduce:
Create some raw socket, connect it to an address, and cause some error
situation: f.e. set ttl=1 where the remote address is more than 1 hop to reach. Set IPV6_RECVERR .
Then send something and wait for the error (f.e. poll() with POLLERR|POLLIN). You should receive "time exceeded" icmp message (because of "ttl=1"), but the socket do not receive it.
If you do not connect your raw socket, you will receive MSG_ERRQUEUE successfully. (The reason is that for unconnected socket there are no actual checks for local/remote addresses).
--- net/ipv6/icmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/icmp.c +1 -1
@@ -604,7 +604,7 @@ static void icmpv6_notify(struct sk_buffread_lock (&raw_v6_lock);if ((sk =sk_head (&raw_v6_htable[hash])) !=NULL ) { -while ((sk =__raw_v6_lookup (sk, nexthdr, daddr, saddr, +while ((sk =__raw_v6_lookup (sk, nexthdr, saddr, daddr,IP6CB (skb)->iif))) {rawv6_err (sk, skb,NULL , type, code, inner_offset, info); sk =sk_next (sk);
PATCH 13/84 Fix ipv6 link down handling.
In reply to Greg KHFrom: Vlad Yasevich <[email protected]>
[IPV6]: Call inet6addr_chain notifiers on link down
Currently if the link is brought down via ip link or ifconfig down, the inet6addr_chain notifiers are not called even though all the addresses are removed from the interface. This caused SCTP to add duplicate addresses to it's list.
--- net/ipv6/addrconf.c | 1 + 1 file changed, 1 insertion(+)
net/ipv6/addrconf.c +1 -0
@@ -2472,6 +2472,7 @@ static int addrconf_ifdown(struct net_dewrite_unlock_bh (&idev->lock);__ipv6_ifa_notify (RTM_DELADDR , ifa); +atomic_notifier_call_chain (&inet6addr_chain,NETDEV_DOWN , ifa);in6_ifa_put (ifa);write_lock_bh (&idev->lock);
PATCH 14/84 Netpoll leak
In reply to Greg KHFrom: Satyam Sharma <[email protected]>
[NETPOLL]: Fix a leak-n-bug in netpoll_cleanup()
93ec2c723e3f8a216dde2899aeb85c648672bc6b applied excessive duct tape to the netpoll beast's netpoll_cleanup(), thus substituting one leak with another, and opening up a little buglet :-)
net_device->npinfo (netpoll_info) is a shared and refcounted object and cannot simply be set NULL the first time netpoll_cleanup() is called. Otherwise, further netpoll_cleanup()'s see np->dev->npinfo == NULL and become no-ops, thus leaking. And it's a bug too: the first call to netpoll_cleanup() would thus (annoyingly) "disable" other (still alive) netpolls too. Maybe nobody noticed this because netconsole (only user of netpoll) never supported multiple netpoll objects earlier.
This is a trivial and obvious one-line fixlet.
--- net/core/netpoll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/netpoll.c +1 -1
@@ -781,7 +781,6 @@ void netpoll_cleanup(struct netpoll *np)spin_unlock_irqrestore (&npinfo->rx_lock, flags); } - np->dev->npinfo =NULL ;if (atomic_dec_and_test (&npinfo->refcnt)) {skb_queue_purge (&npinfo->arp_tx);skb_queue_purge (&npinfo->txq);
@@ -794,6 +793,7 @@ void netpoll_cleanup(struct netpoll *np)kfree_skb (skb); }kfree (npinfo); + np->dev->npinfo =NULL ; } }
PATCH 15/84 Sparc64 bootup assembler bug
In reply to Greg KHFrom: David S. Miller <[email protected]>
[SPARC64]: Fix two year old bug in early bootup asm.
We try to fetch the CIF entry pointer from %o4, but that can get clobbered by the early OBP calls. It is saved in %l7 already, so actually this "mov %o4, %l7" can just be completely removed with no other changes.
--- arch/sparc64/kernel/head.S | 1 - 1 file changed, 1 deletion(-)
arch/sparc64/kernel/head.S +0 -1
@@ -458,7 +458,6 @@ tlb_fixup_done: or %g6, %lo(init_thread_union), %g6 ldx [%g6 + TI_TASK], %g4 mov %sp, %l6 - mov %o4, %l7 wr %g0, ASI_P, %asi mov 1, %g1
PATCH 16/84 Fix ipv6 tunnel endianness bug.
In reply to Greg KHFrom: Al Viro <[email protected]>
[IPV6]: endianness bug in ip6_tunnel
--- net/ipv6/ip6_tunnel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/ipv6/ip6_tunnel.c +2 -2
@@ -962,8 +962,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, str dsfield =ipv4_get_dsfield (iph);if ((t->parms.flags &IP6_TNL_F_USE_ORIG_TCLASS )) - fl.fl6_flowlabel |=ntohl (((__u32 )iph->tos <<IPV6_TCLASS_SHIFT ) - &IPV6_TCLASS_MASK ); + fl.fl6_flowlabel |=htonl ((__u32 )iph->tos <<IPV6_TCLASS_SHIFT ) + &IPV6_TCLASS_MASK ; err =ip6_tnl_xmit2 (skb, dev, dsfield, &fl, encap_limit, &mtu);if (err !=0 ) {
PATCH 17/84 Fix sparc32 memset()
In reply to Greg KHFrom: Alexander Shmelev <[email protected]>
[SPARC32]: Fix bug in sparc optimized memset.
Sparc optimized memset (arch/sparc/lib/memset.S) does not fill last byte of the memory area, if area size is less than 8 bytes and start address is not word (4-bytes) aligned.
Here is code chunk where bug located:
/* %o0 - memory address, %o1 - size, %g3 - value */ 8:
add %o0, 1, %o0
subcc %o1, 1, %o1
bne,a 8b
stb %g3, [%o0 - 1]This code should write byte every loop iteration, but last time delay instruction stb is not executed because branch instruction sets "annul" bit.
Patch replaces bne,a by bne instruction.
Error can be reproduced by simple kernel module:
--------------------
#include <linux/module.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <string.h>
static void do_memset(void **p, int size)
{
memset(p, 0x00, size);
}static int __init memset_test_init(void)
{
char fooc[8];
int *fooi;
memset(fooc, 0xba, sizeof(fooc));
do_memset((void**)(fooc + 3), 1);
fooi = (int*) fooc;
printk("%08X %08X\n", fooi[0], fooi[1]);
return -1;
}static void __exit memset_test_cleanup(void)
{
return;
}module_init(memset_test_init);module_exit(memset_test_cleanup);
MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;
------------------------
--- arch/sparc/lib/memset.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/sparc/lib/memset.S +1 -1
@@ -162,7 +162,7 @@ __bzero: 8: add %o0, 1, %o0 subcc %o1, 1, %o1 - bne,a 8b + bne 8b EX(stb %g3, [%o0 - 1], add %o1, 1) 0: retl
PATCH 18/84 Fix sparc32 udelay() rounding errors.
In reply to Greg KHFrom: Mark Fortescue <[email protected]>
[SPARC32]: Fix rounding errors in ndelay/udelay implementation.
__ndelay and __udelay have not been delayung >= specified time. The problem with __ndelay has been tacked down to the rounding of the multiplier constant. By changing this, delays > app 18us are correctly calculated.
The problem with __udelay has also been tracked down to rounding issues. Changing the multiplier constant (to match that used in sparc64) corrects for large delays and adding in a rounding constant corrects for trunctaion errors in the claculations.
Many short delays will return without looping. This is not an error as there is the fixed delay of doing all the maths to calculate the loop count.
--- arch/sparc/kernel/entry.S | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
arch/sparc/kernel/entry.S +10 -4
@@ -1749,8 +1749,8 @@ fpload: __ndelay: save %sp, -STACKFRAME_SZ, %sp mov %i0, %o0 - call .umul - mov 0x1ad, %o1 ! 2**32 / (1 000 000 000 / HZ) + call .umul ! round multiplier up so large ns ok + mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ) call .umul mov %i1, %o1 ! udelay_val ba delay_continue
@@ -1760,11 +1760,17 @@ __ndelay: __udelay: save %sp, -STACKFRAME_SZ, %sp mov %i0, %o0 - sethi %hi(0x10c6), %o1 + sethi %hi(0x10c7), %o1 ! round multiplier up so large us ok call .umul - or %o1, %lo(0x10c6), %o1 ! 2**32 / 1 000 000 + or %o1, %lo(0x10c7), %o1 ! 2**32 / 1 000 000 call .umul mov %i1, %o1 ! udelay_val + sethi %hi(0x028f4b62), %l0 ! Add in rounding constant * 2**32, + or %g0, %lo(0x028f4b62), %l0 + addcc %o0, %l0, %o0 ! 2**32 * 0.009 999 + bcs,a 3f + add %o1, 0x01, %o1 +3: call .umul mov HZ, %o0 ! >>32 earlier for wider range
Re: [2.6.22.2 review 18/84] Fix sparc32 udelay() rounding errors.
arch/sparc/kernel/entry.S fpload: · line 1753
Quoted 10 lines · Greg KH
arch/sparc/kernel/entry.S +0
-0@@ -1749,8 +1749,8 @@ fpload:
__ndelay:save %sp, -STACKFRAME_SZ, %sp mov %i0, %o0arch/sparc/kernel/entry.S +2
-2- call .umul - mov 0x1ad, %o1 ! 2**32 / (1 000 000 000 / HZ) + call .umul ! round multiplier up so large ns ok + mov 0x1ae, %o1 ! 2**32 / (1 000 000 000 / HZ)
If noone noticed - spacing seems odd :)
Jan
PATCH 19/84 Fix TCP IPV6 MD5 bug.
In reply to Greg KHFrom: YOSHIFUJI Hideaki <[email protected]>
[TCPv6] MD5SIG: Ensure to reset allocation count to avoid panic.
After clearing all passwords for IPv6 peers, we need to set allocation count to zero as well as we free the storage. Otherwise, we panic when a user trys to (re)add a password.
Discovered and fixed by MIYAJIMA Mitsuharu <[email protected]>.
--- net/ipv6/tcp_ipv6.c | 1 + 1 file changed, 1 insertion(+)
net/ipv6/tcp_ipv6.c +1 -0
@@ -644,6 +644,7 @@ static int tcp_v6_md5_do_del(struct sockif (tp->md5sig_info->entries6 ==0 ) {kfree (tp->md5sig_info->keys6); tp->md5sig_info->keys6 =NULL ; + tp->md5sig_info->alloced6 =0 ;tcp_free_md5sig_pool ();
PATCH 20/84 KVM: SVM: Reliably detect if SVM was disabled by BIOS
In reply to Greg KHFrom: Joerg Roedel <[email protected]>
This patch adds an implementation to the svm is_disabled function to detect reliably if the BIOS disabled the SVM feature in the CPU. This fixes the issues with kernel panics when loading the kvm-amd module on machines where SVM is available but disabled.
--- drivers/kvm/svm.c | 6 ++++++ drivers/kvm/svm.h | 3 +++ 2 files changed, 9 insertions(+)
drivers/kvm/svm.c +6 -0
@@ -1727,6 +1727,12 @@ static void svm_inject_page_fault(structstatic int is_disabled (void ) { +u64 vm_cr; + +rdmsrl (MSR_VM_CR , vm_cr); +if (vm_cr & (1 <<SVM_VM_CR_SVM_DISABLE )) +return 1 ; +return 0 ; }
drivers/kvm/svm.h +3 -0
@@ -175,8 +175,11 @@ struct __attribute__ ((__packed__)) vmcb#define SVM_CPUID_FUNC 0x8000000a#define MSR_EFER_SVME_MASK (1ULL << 12) +#define MSR_VM_CR 0xc0010114#define MSR_VM_HSAVE_PA 0xc0010117ULL +#define SVM_VM_CR_SVM_DISABLE 4 +#define SVM_SELECTOR_S_SHIFT 4#define SVM_SELECTOR_DPL_SHIFT 5#define SVM_SELECTOR_P_SHIFT 7
PATCH 21/84 USB: fix warning caused by autosuspend counter going negative
In reply to Greg KHFrom: Alan Stern <[email protected]>
This patch (as937) fixes a minor bug in the autosuspend usage-counting code. Each hub's usage counter keeps track of the number of unsuspended children. However the current driver increments the counter after registering a new child, by which time the child may already have been suspended and caused the counter to go negative. The obvious solution is to increment the counter before registering the child.
--- drivers/usb/core/hub.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/usb/core/hub.c +6 -4
@@ -1388,6 +1388,10 @@ int usb_new_device(struct usb_device *ud udev->dev.devt =MKDEV (USB_DEVICE_MAJOR , (((udev->bus->busnum-1 ) *128 ) + (udev->devnum-1 ))); +/* Increment the parent's count of unsuspended children */ +if (udev->parent) +usb_autoresume_device (udev->parent); +/* Register the device. The device driver is responsible * for adding the device files to sysfs and for configuring * the device.
@@ -1395,13 +1399,11 @@ int usb_new_device(struct usb_device *ud err =device_add (&udev->dev);if (err) {dev_err (&udev->dev,"can't device_add, error %d\n" , err); +if (udev->parent) +usb_autosuspend_device (udev->parent); goto fail; } -/* Increment the parent's count of unsuspended children */ -if (udev->parent) -usb_autoresume_device (udev->parent); - exit:return err;
PATCH 22/84 usb-serial: Fix edgeport regression on non-EPiC devices
In reply to Greg KHFrom: Adam Kropelin <[email protected]>
Fix serious regression on non-EPiC edgeport usb-serial devices. Baud rate and MCR/LCR registers are not being written on these models due to apparent copy-n-paste errors introduced with EPiC support.
Failure reported by Nick Pasich <[email protected]>.
--- drivers/usb/serial/io_edgeport.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
drivers/usb/serial/io_edgeport.c +8 -11
@@ -2366,9 +2366,8 @@ static int send_cmd_write_baud_rate (strint status;unsigned char number = edge_port->port->number - edge_port->port->serial->minor; -if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate))) { +if (edge_serial->is_epic && + !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) {dbg ("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d" , edge_port->port->number, baudRate);return 0 ;
@@ -2461,18 +2460,16 @@ static int send_cmd_write_uart_registerdbg ("%s - write to %s register 0x%02x" , (regNum ==MCR ) ?"MCR" :"LCR" , __FUNCTION__, regValue); -if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) && - (regNum ==MCR ))) { +if (edge_serial->is_epic && + !edge_serial->epic_descriptor.Supports.IOSPWriteMCR && + regNum ==MCR ) {dbg ("SendCmdWriteUartReg - Not writing to MCR Register" );return 0 ; } -if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) && - (regNum ==LCR ))) { +if (edge_serial->is_epic && + !edge_serial->epic_descriptor.Supports.IOSPWriteLCR && + regNum ==LCR ) {dbg ("SendCmdWriteUartReg - Not writing to LCR Register" );return 0 ; }
PATCH 23/84 Fix reported task file values in sense data
In reply to Greg KHFrom: Petr Vandrovec <[email protected]>
ata_tf_read was setting HOB bit when lba48 command was submitted, but was not clearing it before reading "normal" data. As it is only place which sets HOB bit in control register, and register reads should not be affected by other bits, let's just clear it when we are done with reading upper bytes so non-48bit commands do not have to touch ctl at all.
pata_scc suffered from same problem...
--- drivers/ata/libata-sff.c | 2 ++ drivers/ata/pata_scc.c | 2 ++ 2 files changed, 4 insertions(+)
drivers/ata/libata-sff.c +2 -0
@@ -211,6 +211,8 @@ void ata_tf_read(struct ata_port *ap, st tf->hob_lbal =ioread8 (ioaddr->lbal_addr); tf->hob_lbam =ioread8 (ioaddr->lbam_addr); tf->hob_lbah =ioread8 (ioaddr->lbah_addr); +iowrite8 (tf->ctl, ioaddr->ctl_addr); + ap->last_ctl = tf->ctl; } }
drivers/ata/pata_scc.c +2 -0
@@ -352,6 +352,8 @@ static void scc_tf_read (struct ata_port tf->hob_lbal =in_be32 (ioaddr->lbal_addr); tf->hob_lbam =in_be32 (ioaddr->lbam_addr); tf->hob_lbah =in_be32 (ioaddr->lbah_addr); +out_be32 (ioaddr->ctl_addr, tf->ctl); + ap->last_ctl = tf->ctl; } }
PATCH 24/84 aacraid: fix security hole
In reply to Greg KHFrom: Alan Cox <[email protected]>
On the SCSI layer ioctl path there is no implicit permissions check for ioctls (and indeed other drivers implement unprivileged ioctls). aacraid however allows all sorts of very admin only things to be done so should check.
--- drivers/scsi/aacraid/linit.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/scsi/aacraid/linit.c +4 -0
@@ -597,6 +597,8 @@ static int aac_cfg_open(struct inode *instatic int aac_cfg_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg) { +if (!capable (CAP_SYS_ADMIN )) +return -EPERM ;return aac_do_ioctl (file->private_data, cmd, (void __user *)arg); }
@@ -650,6 +652,8 @@ static int aac_compat_ioctl(struct scsi_static long aac_compat_cfg_ioctl (struct file *file,unsigned cmd,unsigned long arg) { +if (!capable (CAP_SYS_ADMIN )) +return -EPERM ;return aac_compat_do_ioctl ((struct aac_dev *)file->private_data, cmd, arg); }#endif
PATCH 25/84 firewire: fw-sbp2: set correct maximum payload (fixes CardBus adapters)
In reply to Greg KHFrom: Stefan Richter <[email protected]>
As far as I know, all CardBus FireWire 400 adapters have a maximum payload of 1024 bytes which is less than the speed-dependent limit of 2048 bytes. Fw-sbp2 has to take the host adapter's limit into account.
This apparently fixes Juju's incompatibility with my CardBus cards, a NEC based card and a VIA based card.
Backport of commit 25659f7183376c6b37661da6141d5eaa21479061.
--- drivers/firewire/fw-sbp2.c | 5 ++++- drivers/firewire/fw-transaction.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-)
drivers/firewire/fw-sbp2.c +4 -1
@@ -985,6 +985,7 @@ static int sbp2_scsi_queuecommand(structstruct fw_unit *unit = sd->unit;struct fw_device *device =fw_device (unit->device.parent);struct sbp2_command_orb *orb; +unsigned max_payload;/* * Bidirectional commands are not yet implemented, and unknown
@@ -1023,8 +1024,10 @@ static int sbp2_scsi_queuecommand(struct* specifies the max payload size as 2 ^ (max_payload + 2), so * if we set this to max_speed + 7, we get the right value. */ + max_payload = device->node->max_speed +7 ; + max_payload =min (max_payload, device->card->max_receive -1 ); orb->request.misc = -COMMAND_ORB_MAX_PAYLOAD (device->node->max_speed +7 ) | +COMMAND_ORB_MAX_PAYLOAD (max_payload) |COMMAND_ORB_SPEED (device->node->max_speed) |COMMAND_ORB_NOTIFY ;
drivers/firewire/fw-transaction.h +1 -1
@@ -228,7 +228,7 @@ struct fw_card {unsigned long reset_jiffies;unsigned long long guid; -int max_receive; +unsigned max_receive;int link_speed;int config_rom_generation;
PATCH 26/84 make timerfd return a u64 and fix the __put_user
In reply to Greg KHFrom: Davide Libenzi <[email protected]>
Davi fixed a missing cast in the __put_user(), that was making timerfd return a single byte instead of the full value.
Talking with Michael about the timerfd man page, we think it'd be better to use a u64 for the returned value, to align it with the eventfd implementation.
This is an ABI change. The timerfd code is new in 2.6.22 and if we merge this into 2.6.23 then we should also merge it into 2.6.22.x. That will leave a few early 2.6.22 kernels out in the wild which might misbehave when a future timerfd-enabled glibc is run on them.
mtk says:
The difference would be that read() will only return 4 bytes, while the application will expect 8. If the application is checking the size of returned value, as it should, then it will be able to detect the problem (it could even be sophisticated enough to know that if this is a 4-byte return, then it is running on an old 2.6.22 kernel). If the application is not checking the return from read(), then its 8-byte buffer will not be filled -- the contents of the last 4 bytes will be undefined, so the u64 value as a whole will be junk.
When I wrote up that description above, I forgot a crucial detail. The above description described the difference between the new behavior implemented by the patch, and the current (i.e., 2.6.22) *intended* behavior. However, as I originally remarked to Davide, the 2.6.22 read() behavior is broken: it should return 4 bytes on a read(), but as originally implemented, only the least significant byte contained valid information. (In other words, the top 3 bytes of overrun information were simply being discarded.)
So the patch both fixes a bug in the originally intended behavior, and changes the intended behavior (to return 8 bytes from a read() instead of 4).
--- fs/timerfd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/timerfd.c +3 -3
@@ -95,7 +95,7 @@ static ssize_t timerfd_read(struct file {struct timerfd_ctx *ctx = file->private_data;ssize_t res; -u32 ticks =0 ; +u64 ticks =0 ;DECLARE_WAITQUEUE (wait, current);if (count <sizeof (ticks))
@@ -130,7 +130,7 @@ static ssize_t timerfd_read(struct file* callback to avoid DoS attacks specifying a very * short timer period. */ - ticks = (u32 ) + ticks = (u64 )hrtimer_forward (&ctx->tmr,hrtimer_cb_get_time (&ctx->tmr), ctx->tintv);
@@ -140,7 +140,7 @@ static ssize_t timerfd_read(struct file }spin_unlock_irq (&ctx->wqh.lock);if (ticks) - res =put_user (ticks, buf) ? -EFAULT :sizeof (ticks); + res =put_user (ticks, (u64 __user *) buf) ? -EFAULT :sizeof (ticks);return res; }
Re: [2.6.22.2 review 26/84] make timerfd return a u64 and fix the __put_user
Quoted 12 lines · Greg KH
fs/timerfd.c +1
-1@@ -95,7 +95,7 @@ static ssize_t timerfd_read(struct file {struct timerfd_ctx *ctx = file->private_data;ssize_t res; -u32 ticks =0 ; +u64 ticks =0 ;DECLARE_WAITQUEUE (wait, current);if (count <sizeof (ticks))
fs/timerfd.c static ssize_t timerfd_read(struct file · line 136
Quoted 8 lines
fs/timerfd.c +1
-1@@ -130,7 +130,7 @@ static ssize_t timerfd_read(struct file* callback to avoid DoS attacks specifying a very * short timer period. */ - ticks = (u32 ) + ticks = (u64 )hrtimer_forward (&ctx->tmr,hrtimer_cb_get_time (&ctx->tmr), ctx->tintv);
[ Minor: Cast is not strictly required; hrtimer_forward()s result is autopromoted/demoted to the type of @ticks. ]
Jan
PATCH 27/84 V4L: Add check for valid control ID to v4l2_ctrl_next
In reply to Greg KHFrom: Hans Verkuil <[email protected]>
If v4l2_ctrl_next is called without the V4L2_CTRL_FLAG_NEXT_CTRL then it should check whether the passed control ID is valid and return 0 if it isn't. Otherwise a for-loop over the control IDs will never end.
(cherry picked from commit a46c5fbc6912c4e34cb7ded314249b639dc244a6)
--- drivers/media/video/v4l2-common.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
drivers/media/video/v4l2-common.c +14 -5
@@ -939,16 +939,25 @@ int v4l2_ctrl_query_menu(struct v4l2_queWhen no more controls are available 0 is returned. */ u32 v4l2_ctrl_next (const u32 *const * ctrl_classes,u32 id) { -u32 ctrl_class; +u32 ctrl_class =V4L2_CTRL_ID2CLASS (id);const u32 *pctrl; -/* if no query is desired, then just return the control ID */ -if ((id &V4L2_CTRL_FLAG_NEXT_CTRL ) ==0 ) -return id;if (ctrl_classes ==NULL )return 0 ; + +/* if no query is desired, then check if the ID is part of ctrl_classes */ +if ((id &V4L2_CTRL_FLAG_NEXT_CTRL ) ==0 ) { +/* find class */ +while (*ctrl_classes &&V4L2_CTRL_ID2CLASS (**ctrl_classes) != ctrl_class) + ctrl_classes++; +if (*ctrl_classes ==NULL ) +return 0 ; + pctrl = *ctrl_classes; +/* find control ID */ +while (*pctrl && *pctrl != id) pctrl++; +return *pctrl ? id :0 ; + } id &=V4L2_CTRL_ID_MASK ; - ctrl_class =V4L2_CTRL_ID2CLASS (id); id++;/* select next control */ /* find first class that matches (or is greater than) the class of the ID */
PATCH 28/84 V4L: ivtv: fix broken VBI output support
In reply to Greg KHFrom: Hans Verkuil <[email protected]>
The old service_set_out setting was still tested, even though it no longer was ever set and was in fact obsolete. This meant that everything that was written to /dev/vbi16 was ignored. Removed the service_set_out variable altogether and now it works again.
(cherry picked from commit 47fd3ba9fc62d23a985f4969719c3091438d21c5)
--- drivers/media/video/ivtv/ivtv-driver.h | 1 - drivers/media/video/ivtv/ivtv-vbi.c | 31 +++++++++++-------------------- 2 files changed, 11 insertions(+), 21 deletions(-)
drivers/media/video/ivtv/ivtv-driver.h +0 -1
@@ -650,7 +650,6 @@ struct vbi_info {/* convenience pointer to sliced struct in vbi_in union */ struct v4l2_sliced_vbi_format *sliced_in;u32 service_set_in; -u32 service_set_out;int insert_mpeg;/* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
drivers/media/video/ivtv/ivtv-vbi.c +11 -20
@@ -219,31 +219,23 @@ ssize_t ivtv_write_vbi(struct ivtv *itv,int found_cc =0 ;int cc_pos = itv->vbi.cc_pos; -if (itv->vbi.service_set_out ==0 ) -return -EPERM ; -while (count >=sizeof (struct v4l2_sliced_vbi_data )) {switch (p->id) {case V4L2_SLICED_CAPTION_525 : -if (p->id ==V4L2_SLICED_CAPTION_525 && - p->line ==21 && - (itv->vbi.service_set_out & -V4L2_SLICED_CAPTION_525 ) ==0 ) { -break ; - } - found_cc =1 ; -if (p->field) { - cc[2 ] = p->data[0 ]; - cc[3 ] = p->data[1 ]; - }else { - cc[0 ] = p->data[0 ]; - cc[1 ] = p->data[1 ]; +if (p->line ==21 ) { + found_cc =1 ; +if (p->field) { + cc[2 ] = p->data[0 ]; + cc[3 ] = p->data[1 ]; + }else { + cc[0 ] = p->data[0 ]; + cc[1 ] = p->data[1 ]; + } }break ;case V4L2_SLICED_VPS : -if (p->line ==16 && p->field ==0 && - (itv->vbi.service_set_out &V4L2_SLICED_VPS )) { +if (p->line ==16 && p->field ==0 ) { itv->vbi.vps[0 ] = p->data[2 ]; itv->vbi.vps[1 ] = p->data[8 ]; itv->vbi.vps[2 ] = p->data[9 ];
@@ -255,8 +247,7 @@ ssize_t ivtv_write_vbi(struct ivtv *itv,break ;case V4L2_SLICED_WSS_625 : -if (p->line ==23 && p->field ==0 && - (itv->vbi.service_set_out &V4L2_SLICED_WSS_625 )) { +if (p->line ==23 && p->field ==0 ) {/* No lock needed for WSS */ itv->vbi.wss = p->data[0 ] | (p->data[1 ] <<8 ); itv->vbi.wss_found =1 ;
PATCH 29/84 V4L: ivtv: fix DMA timeout when capturing VBI + another stream
In reply to Greg KHFrom: Hans Verkuil <[email protected]>
The VBI DMA is handled in a special way and is marked with a bit. However, that bit was set at the wrong time and could be cleared by mistake if a PCM (or other) DMA request would arrive before the VBI DMA was completed. So on completion of the VBI DMA the driver no longer knew that that DMA transfer was for VBI data. And this in turn caused havoc with the card's DMA engine.
(cherry picked from commit dd1e729d63f74a0b6290ca417bafd3fd8665db50)
--- drivers/media/video/ivtv/ivtv-irq.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/media/video/ivtv/ivtv-irq.c +5 -2
@@ -403,6 +403,11 @@ static void ivtv_dma_enc_start(struct iv/* Mark last buffer size for Interrupt flag */ s->SGarray[s->SG_length -1 ].size |=cpu_to_le32 (0x80000000 ); +if (s->type ==IVTV_ENC_STREAM_TYPE_VBI ) +set_bit (IVTV_F_I_ENC_VBI , &itv->i_flags); +else +clear_bit (IVTV_F_I_ENC_VBI , &itv->i_flags); +if (ivtv_use_pio (s)) {for (i =0 ; i < s->SG_length; i++) { s->PIOarray[i].src =le32_to_cpu (s->SGarray[i].src);
@@ -597,7 +602,6 @@ static void ivtv_irq_enc_start_cap(struc data[0], data[1], data[2]);return ; } -clear_bit (IVTV_F_I_ENC_VBI , &itv->i_flags); s = &itv->streams[ivtv_stream_map[data[0 ]]];if (!stream_enc_dma_append (s, data)) {set_bit (ivtv_use_pio (s) ?IVTV_F_S_PIO_PENDING :IVTV_F_S_DMA_PENDING , &s->s_flags);
@@ -634,7 +638,6 @@ static void ivtv_irq_enc_vbi_cap(structthen start a DMA request for just the VBI data. */ if (!stream_enc_dma_append (s, data) && !test_bit (IVTV_F_S_STREAMING , &s_mpg->s_flags)) { -set_bit (IVTV_F_I_ENC_VBI , &itv->i_flags);set_bit (ivtv_use_pio (s) ?IVTV_F_S_PIO_PENDING :IVTV_F_S_DMA_PENDING , &s->s_flags); } }
PATCH 30/84 V4L: ivtv: Add locking to ensure stream setup is atomic
In reply to Greg KHFrom: Hans Verkuil <[email protected]>
Starting an MPEG and VBI capture simultaneously caused errors in the VBI setup: this setup was done twice when it should be done only for the first stream that is opened.
Added a mutex to prevent this from happening.
(cherry picked from commit f885969196da6ae905162c0d1c5f0553de12cb40)
--- drivers/media/video/ivtv/ivtv-driver.c | 1 + drivers/media/video/ivtv/ivtv-driver.h | 1 + drivers/media/video/ivtv/ivtv-streams.c | 30 +++++++++++++++++++----------- 3 files changed, 21 insertions(+), 11 deletions(-)
drivers/media/video/ivtv/ivtv-driver.c +1 -0
@@ -622,6 +622,7 @@ static int __devinit ivtv_init_struct1(s itv->enc_mbox.max_mbox =2 ;/* the encoder has 3 mailboxes (0-2) */ itv->dec_mbox.max_mbox =1 ;/* the decoder has 2 mailboxes (0-1) */ +mutex_init (&itv->serialize_lock);mutex_init (&itv->i2c_bus_lock);mutex_init (&itv->udma.lock);
drivers/media/video/ivtv/ivtv-driver.h +1 -0
@@ -722,6 +722,7 @@ struct ivtv {int search_pack_header;spinlock_t dma_reg_lock;/* lock access to DMA engine registers */ +struct mutex serialize_lock;/* lock used to serialize starting streams */ /* User based DMA for OSD */ struct ivtv_user_dma udma;
drivers/media/video/ivtv/ivtv-streams.c +19 -11
@@ -446,6 +446,9 @@ int ivtv_start_v4l2_encode_stream(structif (s->v4l2dev ==NULL )return -EINVAL ; +/* Big serialization lock to ensure no two streams are started +simultaneously: that can give all sorts of weird results. */ +mutex_lock (&itv->serialize_lock);IVTV_DEBUG_INFO ("Start encoder stream %s\n" , s->name);switch (s->type) {
@@ -487,6 +490,7 @@ int ivtv_start_v4l2_encode_stream(struct 0, sizeof(itv->vbi.sliced_mpeg_size));break ;default : +mutex_unlock (&itv->serialize_lock);return -EINVAL ; } s->subtype = subtype;
@@ -568,6 +572,7 @@ int ivtv_start_v4l2_encode_stream(structif (ivtv_vapi (itv,CX2341X_ENC_START_CAPTURE ,2 , captype, subtype)) {IVTV_DEBUG_WARN ("Error starting capture!\n" ); +mutex_unlock (&itv->serialize_lock);return -EINVAL ; }
@@ -583,6 +588,7 @@ int ivtv_start_v4l2_encode_stream(struct/* you're live! sit back and await interrupts :) */ atomic_inc (&itv->capturing); +mutex_unlock (&itv->serialize_lock);return 0 ; }
@@ -762,17 +768,6 @@ int ivtv_stop_v4l2_encode_stream(struct/* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ ivtv_vapi (itv,CX2341X_ENC_STOP_CAPTURE ,3 , stopmode, cap_type, s->subtype); -/* only run these if we're shutting down the last cap */ -if (atomic_read (&itv->capturing) -1 ==0 ) { -/* event notification (off) */ -if (test_and_clear_bit (IVTV_F_I_DIG_RST , &itv->i_flags)) { -/* type: 0 = refresh */ -/* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ -ivtv_vapi (itv,CX2341X_ENC_SET_EVENT_NOTIFICATION ,4 ,0 ,0 ,IVTV_IRQ_ENC_VIM_RST ,-1 ); -ivtv_set_irq_mask (itv,IVTV_IRQ_ENC_VIM_RST ); - } - } - then = jiffies;if (!test_bit (IVTV_F_S_PASSTHROUGH , &s->s_flags)) {
@@ -840,17 +835,30 @@ int ivtv_stop_v4l2_encode_stream(struct/* Clear capture and no-read bits */ clear_bit (IVTV_F_S_STREAMING , &s->s_flags); +/* ensure these global cleanup actions are done only once */ +mutex_lock (&itv->serialize_lock); +if (s->type ==IVTV_ENC_STREAM_TYPE_VBI )ivtv_set_irq_mask (itv,IVTV_IRQ_ENC_VBI_CAP );if (atomic_read (&itv->capturing) >0 ) { +mutex_unlock (&itv->serialize_lock);return 0 ; }/* Set the following Interrupt mask bits for capture */ ivtv_set_irq_mask (itv,IVTV_IRQ_MASK_CAPTURE ); +/* event notification (off) */ +if (test_and_clear_bit (IVTV_F_I_DIG_RST , &itv->i_flags)) { +/* type: 0 = refresh */ +/* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ +ivtv_vapi (itv,CX2341X_ENC_SET_EVENT_NOTIFICATION ,4 ,0 ,0 ,IVTV_IRQ_ENC_VIM_RST ,-1 ); +ivtv_set_irq_mask (itv,IVTV_IRQ_ENC_VIM_RST ); + } +wake_up (&s->waitq); +mutex_unlock (&itv->serialize_lock);return 0 ; }
PATCH 31/84 V4L: wm8775/wm8739: Fix memory leak when unloading module
In reply to Greg KHFrom: Hans Verkuil <[email protected]>
State struct was never freed.
(cherry picked from commit 1b2232ab879993fcf5b9391c3febf6ab5d78201e)
--- drivers/media/video/wm8739.c | 2 ++ drivers/media/video/wm8775.c | 2 ++ 2 files changed, 4 insertions(+)
drivers/media/video/wm8739.c +2 -0
@@ -321,12 +321,14 @@ static int wm8739_probe(struct i2c_adaptstatic int wm8739_detach (struct i2c_client *client) { +struct wm8739_state *state =i2c_get_clientdata (client);int err; err =i2c_detach_client (client);if (err)return err; +kfree (state);kfree (client);return 0 ; }
drivers/media/video/wm8775.c +2 -0
@@ -222,12 +222,14 @@ static int wm8775_probe(struct i2c_adaptstatic int wm8775_detach (struct i2c_client *client) { +struct wm8775_state *state =i2c_get_clientdata (client);int err; err =i2c_detach_client (client);if (err) {return err; } +kfree (state);kfree (client);return 0 ;
PATCH 32/84 Input: lifebook - fix an oops on Panasonic CF-18
In reply to Greg KHFrom: Dmitry Torokhov <[email protected]>
Input: lifebook - fix an oops on Panasonic CF-18
--- drivers/input/mouse/lifebook.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/mouse/lifebook.c +1 -1
@@ -109,7 +109,7 @@ static psmouse_ret_t lifebook_process_by {struct lifebook_data *priv = psmouse->private;struct input_dev *dev1 = psmouse->dev; -struct input_dev *dev2 = priv->dev2; +struct input_dev *dev2 = priv ? priv->dev2 :NULL ;unsigned char *packet = psmouse->packet;int relative_packet = packet[0 ] &0x08 ;
PATCH 33/84 splice: fix double page unlock
In reply to Greg KHFrom: Jens Axboe <[email protected]>
If add_to_page_cache_lru() fails, the page will not be locked. But splice jumps to an error path that does a page release and unlock, causing a BUG() in unlock_page().
Fix this by adding one more label that just releases the page. This bug was actually triggered on EL5 by gurudas pai <[email protected]> using fio.
--- fs/splice.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/splice.c +3 -2
@@ -601,7 +601,7 @@ find_page: ret =add_to_page_cache_lru (page, mapping, index,GFP_KERNEL );if (unlikely (ret)) - goto out; + goto out_release; } ret = mapping->a_ops->prepare_write (file, page, offset, offset+this_len);
@@ -657,8 +657,9 @@ find_page:*/ mark_page_accessed (page); out: -page_cache_release (page);unlock_page (page); +out_release: +page_cache_release (page); out_ret:return ret; }
PATCH 34/84 drm/i915: Fix i965 secured batchbuffer usage (CVE-2007-3851)
In reply to Greg KHFrom: Dave Airlie <[email protected]>
This 965G and above chipsets moved the batch buffer non-secure bits to another place. This means that previous drm's allowed in-secure batchbuffers to be submitted to the hardware from non-privileged users who are logged into X and and have access to direct rendering.
--- drivers/char/drm/i915_dma.c | 14 +++++++++++--- drivers/char/drm/i915_drv.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-)
drivers/char/drm/i915_dma.c +11 -3
@@ -184,6 +184,8 @@ static int i915_initialize(drm_device_t* private backbuffer/depthbuffer usage. */ dev_priv->use_mi_batchbuffer_start =0 ; +if (IS_I965G (dev))/* 965 doesn't support older method */ + dev_priv->use_mi_batchbuffer_start =1 ;/* Allow hardware batchbuffers unless told otherwise. */
@@ -517,8 +519,13 @@ static int i915_dispatch_batchbuffer(drmif (dev_priv->use_mi_batchbuffer_start) {BEGIN_LP_RING (2 ); -OUT_RING (MI_BATCH_BUFFER_START | (2 <<6 )); -OUT_RING (batch->start |MI_BATCH_NON_SECURE ); +if (IS_I965G (dev)) { +OUT_RING (MI_BATCH_BUFFER_START | (2 <<6 ) |MI_BATCH_NON_SECURE_I965 ); +OUT_RING (batch->start); + }else { +OUT_RING (MI_BATCH_BUFFER_START | (2 <<6 )); +OUT_RING (batch->start |MI_BATCH_NON_SECURE ); + }ADVANCE_LP_RING (); }else {BEGIN_LP_RING (4 );
@@ -735,7 +742,8 @@ static int i915_setparam(DRM_IOCTL_ARGS)switch (param.param) {case I915_SETPARAM_USE_MI_BATCHBUFFER_START : - dev_priv->use_mi_batchbuffer_start = param.value; +if (!IS_I965G (dev)) + dev_priv->use_mi_batchbuffer_start = param.value;break ;case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY : dev_priv->tex_lru_log_granularity = param.value;
drivers/char/drm/i915_drv.h +1 -0
@@ -282,6 +282,7 @@ extern int i915_wait_ring(drm_device_t *#define MI_BATCH_BUFFER_START (0x31<<23)#define MI_BATCH_BUFFER_END (0xA<<23)#define MI_BATCH_NON_SECURE (1) +#define MI_BATCH_NON_SECURE_I965 (1<<8)#define MI_WAIT_FOR_EVENT ((0x3<<23))#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
PATCH 35/84 Fix leak on /proc/lockdep_stats
In reply to Greg KHFrom: Alexey Dobriyan <[email protected]>
--- kernel/lockdep_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/lockdep_proc.c +1 -1
@@ -339,7 +339,7 @@ static const struct file_operations proc .open = lockdep_stats_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, };static int __init lockdep_proc_init (void )
PATCH 35/84 Fix leak on /proc/lockdep_stats
In reply to Greg KHFrom: Alexey Dobriyan <[email protected]>
--- kernel/lockdep_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/lockdep_proc.c +1 -1
@@ -339,7 +339,7 @@ static const struct file_operations proc .open = lockdep_stats_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, };static int __init lockdep_proc_init (void )
PATCH 36/84 CPU online file permission
In reply to Greg KHFrom: Ulrich Drepper <[email protected]>
Is there a reason why the "online" file in the subdirectories for the CPUs in /sys/devices/system isn't world-readable? I cannot imagine it to be security relevant especially now that a getcpu() syscall can be used to determine what CPUa thread runs on.
The file is useful to correctly implement the sysconf() function to return the number of online CPUs. In the presence of hotplug we currently cannot provide this information. The patch below should to it.
--- drivers/base/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/cpu.c +1 -1
@@ -53,7 +53,7 @@ static ssize_t store_online(struct sys_d ret = count;return ret; } -static SYSDEV_ATTR(online, 0600, show_online, store_online); +static SYSDEV_ATTR(online, 0644, show_online, store_online);static void __devinit register_cpu_control (struct cpu *cpu) {
PATCH 37/84 Fix user struct leakage with locked IPC shem segment
In reply to Greg KHFrom: Pavel Emelianov <[email protected]>
When user locks an ipc shmem segmant with SHM_LOCK ctl and the segment is already locked the shmem_lock() function returns 0. After this the subsequent code leaks the existing user struct:
== ipc/shm.c: sys_shmctl() ==
...
err = shmem_lock(shp->shm_file, 1, user);
if (!err) {
shp->shm_perm.mode |= SHM_LOCKED;
shp->mlock_user = user;
}
...==
Other results of this are:
1. the new shp->mlock_user is not get-ed and will point to freed memory when the task dies.
2. the RLIMIT_MEMLOCK is screwed on both user structs.
The exploit looks like this:
==
id = shmget(...);
setresuid(uid, 0, 0);
shmctl(id, SHM_LOCK, NULL);
setresuid(uid + 1, 0, 0);
shmctl(id, SHM_LOCK, NULL);==
My solution is to return 0 to the userspace and do not change the segment's user.
--- ipc/shm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
ipc/shm.c +1 -1
@@ -716,7 +716,7 @@ asmlinkage long sys_shmctl (int shmid, istruct user_struct * user = current->user;if (!is_file_hugepages (shp->shm_file)) { err =shmem_lock (shp->shm_file,1 , user); -if (!err) { +if (!err && !(shp->shm_perm.mode &SHM_LOCKED )){ shp->shm_perm.mode |=SHM_LOCKED ; shp->mlock_user = user; }
PATCH 38/84 md: handle writes to broken raid10 arrays gracefully
In reply to Greg KHFrom: Arne Redlich <[email protected]>
When writing to a broken array, raid10 currently happily emits empty bio lists. IOW, the master bio will never be completed, sending writers to UNINTERRUPTIBLE_SLEEP forever.
--- drivers/md/raid10.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/md/raid10.c +7 -0
@@ -917,6 +917,13 @@ static int make_request(request_queue_tbio_list_add (&bl, mbio); } +if (unlikely (!atomic_read (&r10_bio->remaining))) { +/* the array is dead */ +md_write_end (mddev); +raid_end_bio_io (r10_bio); +return 0 ; + } +bitmap_startwrite (mddev->bitmap, bio->bi_sector, r10_bio->sectors,0 );spin_lock_irqsave (&conf->device_lock, flags);bio_list_merge (&conf->pending_bio_list, &bl);
PATCH 39/84 md: raid10: fix use-after-free of bio
In reply to Greg KHFrom: Maik Hampel <[email protected]>
In case of read errors raid10d tries to print a nice error message, unfortunately using data from an already put bio.
--- drivers/md/raid10.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/md/raid10.c +2 -1
@@ -1565,7 +1565,6 @@ static void raid10d(mddev_t *mddev) bio = r10_bio->devs[r10_bio->read_slot].bio; r10_bio->devs[r10_bio->read_slot].bio = mddev->ro ?IO_BLOCKED :NULL ; -bio_put (bio); mirror =read_balance (conf, r10_bio);if (mirror ==-1 ) { printk(KERN_ALERT "raid10: %s: unrecoverable I/O"
@@ -1573,8 +1572,10 @@ static void raid10d(mddev_t *mddev)bdevname (bio->bi_bdev,b), (unsigned long long)r10_bio->sector);raid_end_bio_io (r10_bio); +bio_put (bio); }else {const int do_sync =bio_sync (r10_bio->master_bio); +bio_put (bio); rdev = conf->mirrors[mirror].rdev;if (printk_ratelimit ()) printk(KERN_ERR "raid10: %s: redirecting sector %llu to"
PATCH 40/84 pcmcia: give socket time to power down
In reply to Greg KHFrom: Daniel Ritz <[email protected]>
Give sockets up to 100ms of additional time to power down. otherwise we might generate false warnings with KERN_ERR priority (like in bug #8262).
--- drivers/pcmcia/cs.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/pcmcia/cs.c +3 -0
@@ -409,6 +409,9 @@ static void socket_shutdown(struct pcmci#endif s->functions =0 ; +/* give socket some time to power down */ +msleep (100 ); + s->ops->get_status (s, &status);if (status &SS_POWERON ) {printk (KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n" , s);
PATCH 41/84 Fix leaks on /proc/{*/sched, sched_debug, timer_list, timer_stats}
In reply to Greg KHFrom: Alexey Dobriyan <[email protected]>
On every open/close one struct seq_operations leaks. Kudos to /proc/slab_allocators.
--- kernel/time/timer_list.c | 2 +- kernel/time/timer_stats.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
kernel/time/timer_list.c +1 -1
@@ -267,7 +267,7 @@ static struct file_operations timer_list .open = timer_list_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, };static int __init init_timer_list_procfs (void )
kernel/time/timer_stats.c +1 -1
@@ -391,7 +391,7 @@ static struct file_operations tstats_fop .read = seq_read, .write = tstats_write, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, };void __init init_timer_stats (void )
PATCH 42/84 futex: pass nr_wake2 to futex_wake_op
In reply to Greg KHFrom: Andreas Schwab <[email protected]>
The fourth argument of sys_futex is ignored when op == FUTEX_WAKE_OP, but futex_wake_op expects it as its nr_wake2 parameter.
The only user of this operation in glibc is always passing 1, so this bug had no consequences so far.
--- kernel/futex.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/futex.c +3 -1
@@ -2061,8 +2061,10 @@ asmlinkage long sys_futex(u32 __user *ua }/* * requeue parameter in 'utime' if cmd == FUTEX_REQUEUE. +* number of waiters to wake in 'utime' if cmd == FUTEX_WAKE_OP. */ -if (cmd ==FUTEX_REQUEUE || cmd ==FUTEX_CMP_REQUEUE ) +if (cmd ==FUTEX_REQUEUE || cmd ==FUTEX_CMP_REQUEUE || + cmd ==FUTEX_WAKE_OP ) val2 = (u32 ) (unsigned long ) utime;return do_futex (uaddr, op, val, tp, uaddr2, val2, val3);
PATCH 43/84 "ext4_ext_put_in_cache" uses __u32 to receive physical block number
In reply to Greg KHFrom: Mingming Cao <[email protected]>
Quoted 4 lines · Yan Zheng
I think I found a bug in
ext4/extents.c, "ext4_ext_put_in_cache" uses "__u32" to receive physical block number. "ext4_ext_put_in_cache" is used in "ext4_ext_get_blocks", it sets ext4 inode's extent cache according most recently tree lookup (higher 16 bits of saved physical
Quoted 9 lines
block number are always zero). when serving a mapping request, "
ext4_ext_get_blocks" first check whether the logical block is in inode's extent cache. if the logical block is in the cache and the cached region isn't a gap, "ext4_ext_get_blocks" gets physical block number by using cached region's physical block number and offset in the cached region. as described above, "ext4_ext_get_blocks" may return wrong result when there are physical block numbers bigger than0xffffffff.
You are right. Thanks for reporting this!
--- fs/ext4/extents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ext4/extents.c +1 -1
@@ -1445,7 +1445,7 @@ int ext4_ext_walk_space(struct inode *instatic void ext4_ext_put_in_cache (struct inode *inode,__u32 block, -__u32 len,__u32 start,int type) +__u32 len,ext4_fsblk_t start,int type) {struct ext4_ext_cache *cex;BUG_ON (len ==0 );
PATCH 44/84 Include serial_reg.h with userspace headers
In reply to Greg KHFrom: Herton Ronaldo Krzesinski <[email protected]>
As reported by Gustavo de Nardin <[email protected]>, while trying to compile xosview (http://xosview.sourceforge.net/) with upstream kernel headers being used you get the following errors:
serialmeter.cc:48:30: error: linux/serial_reg.h: No such file or directory serialmeter.cc: In member function 'virtual void SerialMeter::checkResources()':
serialmeter.cc:71: error: 'UART_LSR' was not declared in this scope serialmeter.cc:71: error: 'UART_MSR' was not declared in this scope
...
--- include/linux/Kbuild | 1 + 1 file changed, 1 insertion(+)
include/linux/Kbuild +1 -0
@@ -137,6 +137,7 @@ header-y += radeonfb.h header-y += raw.h header-y += resource.h header-y += rose.h +header-y += serial_reg.h header-y += smbno.h header-y += snmp.h header-y += sockios.h
PATCH 45/84 dm io: fix panic on large request
In reply to Greg KHFrom: Milan Broz <[email protected]>
Flush workqueue before releasing bioset and mopools in dm-crypt. There can be finished but not yet released request.
Call chain causing oops:
run workqueue
dec_pending
bio_endio(...);
<remove device request - remove mempool>
mempool_free(io, cc->io_pool);This usually happens when cryptsetup create temporary luks mapping in the beggining of crypt device activation.
When dm-core calls destructor crypt_dtr, no new request are possible.
--- drivers/md/dm-crypt.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/md/dm-crypt.c +2 -0
@@ -920,6 +920,8 @@ static void crypt_dtr(struct dm_target * {struct crypt_config *cc = (struct crypt_config *) ti->private; +flush_workqueue (_kcryptd_workqueue); +bioset_free (cc->bs);mempool_destroy (cc->page_pool);mempool_destroy (cc->io_pool);
PATCH 46/84 i386: HPET, check if the counter works
In reply to Greg KHFrom: Thomas Gleixner <[email protected]>
Some systems have a HPET which is not incrementing, which leads to a complete hang. Detect it during HPET setup.
--- arch/i386/kernel/hpet.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
arch/i386/kernel/hpet.c +23 -1
@@ -226,7 +226,8 @@ int __init hpet_enable(void) {unsigned long id;uint64_t hpet_freq; -u64 tmp; +u64 tmp, start, now; +cycle_t t1;if (!is_hpet_capable ())return 0 ;
@@ -273,6 +274,27 @@ int __init hpet_enable(void)/* Start the counter */ hpet_start_counter (); +/* Verify whether hpet counter works */ + t1 =read_hpet (); +rdtscll (start); + +/* +* We don't know the TSC frequency yet, but waiting for +* 200000 TSC cycles is safe: +* 4 GHz == 50us +* 1 GHz == 200us +*/ +do { +rep_nop (); +rdtscll (now); + }while ((now - start) <200000UL ); + +if (t1 ==read_hpet ()) { +printk (KERN_WARNING +"HPET counter not counting. HPET disabled\n" ); + goto out_nohpet; + } +/* Initialize and register HPET clocksource * * hpet period is in femto seconds per cycle
PATCH 47/84 fw-ohci: fix "scheduling while atomic"
In reply to Greg KHFrom: Stefan Richter <[email protected]>
context_stop is called by bus_reset_tasklet, among else.
Fixes http://bugzilla.kernel.org/show_bug.cgi?id=8735.
Same as commit b980f5a224f3df6c884dbf5ae48797ce352ba139.
--- drivers/firewire/fw-ohci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firewire/fw-ohci.c +1 -1
@@ -586,7 +586,7 @@ static void context_stop(struct contextbreak ;fw_notify ("context_stop: still active (0x%08x)\n" , reg); -msleep (1 ); +mdelay (1 ); } }
PATCH 48/84 firewire: fix memory leak of fw_request instances
In reply to Greg KHFrom: Stefan Richter <[email protected]>
Found and debugged by Jay Fenlason <[email protected]>. The bug was especially noticeable with direct I/O over fw-sbp2.
Same as commit 9c9bdf4d50730fd04b06077e22d7a83b585f26b5.
--- drivers/firewire/fw-transaction.c | 4 +++- drivers/firewire/fw-transaction.h | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-)
drivers/firewire/fw-transaction.c +3 -1
@@ -605,8 +605,10 @@ fw_send_response(struct fw_card *card, s* check is sufficient to ensure we don't send response to * broadcast packets or posted writes. */ -if (request->ack !=ACK_PENDING ) +if (request->ack !=ACK_PENDING ) { +kfree (request);return ; + }if (rcode ==RCODE_COMPLETE ) fw_fill_response(&request->response, request->request_header,
drivers/firewire/fw-transaction.h +4 -0
@@ -124,6 +124,10 @@ typedef void (*fw_transaction_callback_tsize_t length, void *callback_data); +/* +* Important note: The callback must guarantee that either fw_send_response() +* or kfree() is called on the @request. +*/ typedef void (*fw_address_callback_t)(struct fw_card *card, struct fw_request *request, int tcode, int destination, int source,
PATCH 49/84 softmac: Fix ESSID problem
In reply to Greg KHFrom: Jean Tourrilhes <[email protected]>
Victor Porton reported that the SoftMAC layer had random problem when setting the ESSID :
http://bugzilla.kernel.org/show_bug.cgi?id=8686 After investigation, it turned out to be worse, the SoftMAC layer is left in an inconsistent state. The fix is pretty trivial.
--- net/ieee80211/softmac/ieee80211softmac_assoc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/ieee80211/softmac/ieee80211softmac_assoc.c +4 -1
@@ -271,8 +271,11 @@ ieee80211softmac_assoc_work(struct work_*/ dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");ieee80211softmac_notify (mac->dev,IEEE80211SOFTMAC_EVENT_SCAN_FINISHED , ieee80211softmac_assoc_notify_scan,NULL ); -if (ieee80211softmac_start_scan (mac)) +if (ieee80211softmac_start_scan (mac)) { dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); + mac->associnfo.associating =0 ; + mac->associnfo.associated =0 ; + } goto out; }else { mac->associnfo.associating =0 ;
PATCH 50/84 eCryptfs: ecryptfs_setattr() bugfix
In reply to Greg KHFrom: Michael Halcrow <[email protected]>
There is another bug recently introduced into the ecryptfs_setattr() function in 2.6.22. eCryptfs will attempt to treat special files like regular eCryptfs files on chmod, chown, and so forth. This leads to a NULL pointer dereference. This patch validates that the file is a regular file before proceeding with operations related to the inode's crypt_stat.
Thanks to Ryusuke Konishi for finding this bug and suggesting the fix.
--- fs/ecryptfs/inode.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/ecryptfs/inode.c +3 -2
@@ -902,8 +902,9 @@ static int ecryptfs_setattr(struct dentrmutex_lock (&crypt_stat->cs_mutex);if (S_ISDIR (dentry->d_inode->i_mode)) crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED ); -else if (!(crypt_stat->flags &ECRYPTFS_POLICY_APPLIED ) - || !(crypt_stat->flags &ECRYPTFS_KEY_VALID )) { +else if (S_ISREG (dentry->d_inode->i_mode) + && (!(crypt_stat->flags &ECRYPTFS_POLICY_APPLIED ) + || !(crypt_stat->flags &ECRYPTFS_KEY_VALID ))) {struct vfsmount *lower_mnt;struct file *lower_file =NULL ;struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
PATCH 51/84 nfsd: fix possible read-ahead cache and export table corruption
In reply to Greg KHFrom: J. Bruce Fields <[email protected]>
The value of nperbucket calculated here is too small--we should be rounding up instead of down--with the result that the index j in the following loop can overflow the raparm_hash array. At least in my case, the next thing in memory turns out to be export_table, so the symptoms I see are crashes caused by the appearance of four zeroed-out export entries in the first bucket of the hash table of exports (which were actually entries in the readahead cache, a pointer to which had been written to the export table in this initialization code).
It looks like the bug was probably introduced with commit fce1456a19f5c08b688c29f00ef90fdfa074c79b ("knfsd: make the readahead params cache SMP-friendly").
--- fs/nfsd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/vfs.c +1 -1
@@ -1890,7 +1890,7 @@ nfsd_racache_init(int cache_size) raparm_hash[i].pb_head =NULL ;spin_lock_init (&raparm_hash[i].pb_lock); } - nperbucket = cache_size >>RAPARM_HASH_BITS ; + nperbucket =DIV_ROUND_UP (cache_size,RAPARM_HASH_SIZE );for (i =0 ; i < cache_size -1 ; i++) {if (i % nperbucket ==0 ) raparm_hash[j++].pb_head = raparml + i;
PATCH 52/84 readahead: MIN_RA_PAGES/MAX_RA_PAGES macros
In reply to Greg KHFrom: Fengguang Wu <[email protected]>
Define two convenient macros for read-ahead:
- MAX_RA_PAGES: rounded down counterpart of VM_MAX_READAHEAD
- MIN_RA_PAGES: rounded _up_ counterpart of VM_MIN_READAHEAD
Note that the rounded up MIN_RA_PAGES will work flawlessly with _large_ page sizes like 64k.
--- mm/readahead.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
mm/readahead.c +10 -2
@@ -21,8 +21,16 @@ void default_unplug_io_fn(struct backing }EXPORT_SYMBOL (default_unplug_io_fn); +/* +* Convienent macros for min/max read-ahead pages. +* Note that MAX_RA_PAGES is rounded down, while MIN_RA_PAGES is rounded up. +* The latter is necessary for systems with large page size(i.e. 64k). +*/ +#define MAX_RA_PAGES (VM_MAX_READAHEAD*1024 / PAGE_CACHE_SIZE) +#define MIN_RA_PAGES DIV_ROUND_UP(VM_MIN_READAHEAD*1024, PAGE_CACHE_SIZE) +struct backing_dev_info default_backing_dev_info = { - .ra_pages = (VM_MAX_READAHEAD *1024 ) /PAGE_CACHE_SIZE , + .ra_pages =MAX_RA_PAGES , .state =0 , .capabilities =BDI_CAP_MAP_COPY , .unplug_io_fn = default_unplug_io_fn,
@@ -51,7 +59,7 @@ static inline unsigned long get_max_readstatic inline unsigned long get_min_readahead (struct file_ra_state *ra) { -return (VM_MIN_READAHEAD *1024 ) /PAGE_CACHE_SIZE ; +return MIN_RA_PAGES ; }static inline void reset_ahead_window (struct file_ra_state *ra)
PATCH 53/84 fs: 9p/conv.c error path fix
In reply to Greg KHFrom: Mariusz Kozlowski <[email protected]>
When buf_check_overflow() returns != 0 we will hit kfree(ERR_PTR(err)) and it will not be happy about it.
--- fs/9p/conv.c | 1 + 1 file changed, 1 insertion(+)
fs/9p/conv.c +1 -0
@@ -742,6 +742,7 @@ struct v9fs_fcall *v9fs_create_twrite(u3if (err) {kfree (fc); fc =ERR_PTR (err); + goto error; }if (buf_check_overflow (bufp)) {
PATCH 54/84 forcedeth bug fix: cicada phy
In reply to Greg KHFrom: Ayaz Abdulla <[email protected]>
This patch contains errata fixes for the cicada phy. It only renamed the defines to be phy specific.
--- drivers/net/forcedeth.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
drivers/net/forcedeth.c +10 -10
@@ -557,12 +557,12 @@ union ring_type {#define PHYID2_MODEL_MASK 0x03f0#define PHY_MODEL_MARVELL_E3016 0x220#define PHY_MARVELL_E3016_INITMASK 0x0300 -#define PHY_INIT1 0x0f000 -#define PHY_INIT2 0x0e00 -#define PHY_INIT3 0x01000 -#define PHY_INIT4 0x0200 -#define PHY_INIT5 0x0004 -#define PHY_INIT6 0x02000 +#define PHY_CICADA_INIT1 0x0f000 +#define PHY_CICADA_INIT2 0x0e00 +#define PHY_CICADA_INIT3 0x01000 +#define PHY_CICADA_INIT4 0x0200 +#define PHY_CICADA_INIT5 0x0004 +#define PHY_CICADA_INIT6 0x02000#define PHY_GIGABIT 0x0100#define PHY_TIMEOUT 0x1
@@ -1141,14 +1141,14 @@ static int phy_init(struct net_device *d/* phy vendor specific configuration */ if ((np->phy_oui ==PHY_OUI_CICADA ) && (phyinterface &PHY_RGMII ) ) { phy_reserved =mii_rw (dev, np->phyaddr,MII_RESV1 ,MII_READ ); - phy_reserved &= ~(PHY_INIT1 |PHY_INIT2 ); - phy_reserved |= (PHY_INIT3 |PHY_INIT4 ); + phy_reserved &= ~(PHY_CICADA_INIT1 |PHY_CICADA_INIT2 ); + phy_reserved |= (PHY_CICADA_INIT3 |PHY_CICADA_INIT4 );if (mii_rw (dev, np->phyaddr,MII_RESV1 , phy_reserved)) {printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev));return PHY_ERROR ; } phy_reserved =mii_rw (dev, np->phyaddr,MII_NCONFIG ,MII_READ ); - phy_reserved |=PHY_INIT5 ; + phy_reserved |=PHY_CICADA_INIT5 ;if (mii_rw (dev, np->phyaddr,MII_NCONFIG , phy_reserved)) {printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev));return PHY_ERROR ;
@@ -1156,7 +1156,7 @@ static int phy_init(struct net_device *d }if (np->phy_oui ==PHY_OUI_CICADA ) { phy_reserved =mii_rw (dev, np->phyaddr,MII_SREVISION ,MII_READ ); - phy_reserved |=PHY_INIT6 ; + phy_reserved |=PHY_CICADA_INIT6 ;if (mii_rw (dev, np->phyaddr,MII_SREVISION , phy_reserved)) {printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev));return PHY_ERROR ;
PATCH 55/84 forcedeth bug fix: vitesse phy
In reply to Greg KHFrom: Ayaz Abdulla <[email protected]>
This patch contains errata fixes for the vitesse phy. It only renamed the defines to be phy specific.
--- drivers/net/forcedeth.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)
drivers/net/forcedeth.c +88 -0
@@ -550,6 +550,7 @@ union ring_type {/* PHY defines */ #define PHY_OUI_MARVELL 0x5043#define PHY_OUI_CICADA 0x03f1 +#define PHY_OUI_VITESSE 0x01c1#define PHYID1_OUI_MASK 0x03ff#define PHYID1_OUI_SHFT 6#define PHYID2_OUI_MASK 0xfc00
@@ -563,6 +564,23 @@ union ring_type {#define PHY_CICADA_INIT4 0x0200#define PHY_CICADA_INIT5 0x0004#define PHY_CICADA_INIT6 0x02000 +#define PHY_VITESSE_INIT_REG1 0x1f +#define PHY_VITESSE_INIT_REG2 0x10 +#define PHY_VITESSE_INIT_REG3 0x11 +#define PHY_VITESSE_INIT_REG4 0x12 +#define PHY_VITESSE_INIT_MSK1 0xc +#define PHY_VITESSE_INIT_MSK2 0x0180 +#define PHY_VITESSE_INIT1 0x52b5 +#define PHY_VITESSE_INIT2 0xaf8a +#define PHY_VITESSE_INIT3 0x8 +#define PHY_VITESSE_INIT4 0x8f8a +#define PHY_VITESSE_INIT5 0xaf86 +#define PHY_VITESSE_INIT6 0x8f86 +#define PHY_VITESSE_INIT7 0xaf82 +#define PHY_VITESSE_INIT8 0x0100 +#define PHY_VITESSE_INIT9 0x8f82 +#define PHY_VITESSE_INIT10 0x0 +#define PHY_GIGABIT 0x0100#define PHY_TIMEOUT 0x1
@@ -1162,6 +1180,76 @@ static int phy_init(struct net_device *dreturn PHY_ERROR ; } } +if (np->phy_oui ==PHY_OUI_VITESSE ) { +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG1 ,PHY_VITESSE_INIT1 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG2 ,PHY_VITESSE_INIT2 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } + phy_reserved =mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG4 ,MII_READ ); +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG4 , phy_reserved)) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } + phy_reserved =mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG3 ,MII_READ ); + phy_reserved &= ~PHY_VITESSE_INIT_MSK1 ; + phy_reserved |=PHY_VITESSE_INIT3 ; +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG3 , phy_reserved)) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG2 ,PHY_VITESSE_INIT4 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG2 ,PHY_VITESSE_INIT5 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } + phy_reserved =mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG4 ,MII_READ ); + phy_reserved &= ~PHY_VITESSE_INIT_MSK1 ; + phy_reserved |=PHY_VITESSE_INIT3 ; +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG4 , phy_reserved)) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } + phy_reserved =mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG3 ,MII_READ ); +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG3 , phy_reserved)) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG2 ,PHY_VITESSE_INIT6 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG2 ,PHY_VITESSE_INIT7 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } + phy_reserved =mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG4 ,MII_READ ); +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG4 , phy_reserved)) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } + phy_reserved =mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG3 ,MII_READ ); + phy_reserved &= ~PHY_VITESSE_INIT_MSK2 ; + phy_reserved |=PHY_VITESSE_INIT8 ; +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG3 , phy_reserved)) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG2 ,PHY_VITESSE_INIT9 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_VITESSE_INIT_REG1 ,PHY_VITESSE_INIT10 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } + }/* some phys clear out pause advertisment on reset, set it back */ mii_rw (dev, np->phyaddr,MII_ADVERTISE , reg);
PATCH 56/84 forcedeth bug fix: realtek phy
In reply to Greg KHFrom: Ayaz Abdulla <[email protected]>
This patch contains errata fixes for the realtek phy. It only renamed the defines to be phy specific.
--- drivers/net/forcedeth.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
drivers/net/forcedeth.c +54 -0
@@ -551,6 +551,7 @@ union ring_type {#define PHY_OUI_MARVELL 0x5043#define PHY_OUI_CICADA 0x03f1#define PHY_OUI_VITESSE 0x01c1 +#define PHY_OUI_REALTEK 0x01c1#define PHYID1_OUI_MASK 0x03ff#define PHYID1_OUI_SHFT 6#define PHYID2_OUI_MASK 0xfc00
@@ -580,6 +581,13 @@ union ring_type {#define PHY_VITESSE_INIT8 0x0100#define PHY_VITESSE_INIT9 0x8f82#define PHY_VITESSE_INIT10 0x0 +#define PHY_REALTEK_INIT_REG1 0x1f +#define PHY_REALTEK_INIT_REG2 0x19 +#define PHY_REALTEK_INIT_REG3 0x13 +#define PHY_REALTEK_INIT1 0x0000 +#define PHY_REALTEK_INIT2 0x8e00 +#define PHY_REALTEK_INIT3 0x0001 +#define PHY_REALTEK_INIT4 0xad17#define PHY_GIGABIT 0x0100
@@ -1114,6 +1122,28 @@ static int phy_init(struct net_device *dreturn PHY_ERROR ; } } +if (np->phy_oui ==PHY_OUI_REALTEK ) { +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG1 ,PHY_REALTEK_INIT1 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG2 ,PHY_REALTEK_INIT2 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG1 ,PHY_REALTEK_INIT3 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG3 ,PHY_REALTEK_INIT4 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG1 ,PHY_REALTEK_INIT1 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } + }/* set advertise register */ reg =mii_rw (dev, np->phyaddr,MII_ADVERTISE ,MII_READ );
@@ -1250,6 +1280,30 @@ static int phy_init(struct net_device *dreturn PHY_ERROR ; } } +if (np->phy_oui ==PHY_OUI_REALTEK ) { +/* reset could have cleared these out, set them back */ +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG1 ,PHY_REALTEK_INIT1 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG2 ,PHY_REALTEK_INIT2 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG1 ,PHY_REALTEK_INIT3 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG3 ,PHY_REALTEK_INIT4 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } +if (mii_rw (dev, np->phyaddr,PHY_REALTEK_INIT_REG1 ,PHY_REALTEK_INIT1 )) { +printk (KERN_INFO "%s: phy init failed.\n" ,pci_name (np->pci_dev)); +return PHY_ERROR ; + } + } +/* some phys clear out pause advertisment on reset, set it back */ mii_rw (dev, np->phyaddr,MII_ADVERTISE , reg);
PATCH 57/84 acpi-cpufreq: Proper ReadModifyWrite of PERF_CTL MSR
In reply to Greg KHFrom: Venki Pallipadi <[email protected]>
[CPUFREQ] acpi-cpufreq: Proper ReadModifyWrite of PERF_CTL MSR
During recent acpi-cpufreq changes, writing to PERF_CTL msr changed from RMW of entire 64 bit to RMW of low 32 bit and clearing of upper 32 bit. Fix it back to do a proper RMW of the MSR.
--- arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +5 -8
@@ -167,11 +167,13 @@ static void do_drv_read(struct drv_cmd *static void do_drv_write (struct drv_cmd *cmd) { -u32 h =0 ; +u32 lo, hi;switch (cmd->type) {case SYSTEM_INTEL_MSR_CAPABLE : -wrmsr (cmd->addr.msr.reg, cmd->val, h); +rdmsr (cmd->addr.msr.reg, lo, hi); + lo = (lo & ~INTEL_MSR_RANGE ) | (cmd->val &INTEL_MSR_RANGE ); +wrmsr (cmd->addr.msr.reg, lo, hi);break ;case SYSTEM_IO_CAPABLE : acpi_os_write_port((acpi_io_address)cmd->addr.io.port,
@@ -372,7 +374,6 @@ static int acpi_cpufreq_target(struct cpstruct cpufreq_freqs freqs;cpumask_t online_policy_cpus;struct drv_cmd cmd; -unsigned int msr;unsigned int next_state =0 ;/* Index into freq_table */ unsigned int next_perf_state =0 ;/* Index into perf table */ unsigned int i;
@@ -417,11 +418,7 @@ static int acpi_cpufreq_target(struct cpcase SYSTEM_INTEL_MSR_CAPABLE : cmd.type =SYSTEM_INTEL_MSR_CAPABLE ; cmd.addr.msr.reg =MSR_IA32_PERF_CTL ; - msr = - (u32 ) perf->states[next_perf_state]. - control &INTEL_MSR_RANGE ; - cmd.val =get_cur_val (online_policy_cpus); - cmd.val = (cmd.val & ~INTEL_MSR_RANGE ) | msr; + cmd.val = (u32 ) perf->states[next_perf_state].control;break ;case SYSTEM_IO_CAPABLE : cmd.type =SYSTEM_IO_CAPABLE ;
PATCH 58/84 jbd commit: fix transaction dropping
In reply to Greg KHFrom: Jan Kara <[email protected]>
We have to check that also the second checkpoint list is non-empty before dropping the transaction.
--- fs/jbd/commit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/jbd/commit.c +2 -1
@@ -887,7 +887,8 @@ restart_loop: journal->j_committing_transaction =NULL ;spin_unlock (&journal->j_state_lock); -if (commit_transaction->t_checkpoint_list ==NULL ) { +if (commit_transaction->t_checkpoint_list ==NULL && + commit_transaction->t_checkpoint_io_list ==NULL ) {__journal_drop_transaction (journal, commit_transaction); }else {if (journal->j_checkpoint_transactions ==NULL ) {
PATCH 59/84 jbd2 commit: fix transaction dropping
In reply to Greg KHFrom: Jan Kara <[email protected]>
We have to check that also the second checkpoint list is non-empty before dropping the transaction.
--- fs/jbd2/commit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/jbd2/commit.c +2 -1
@@ -896,7 +896,8 @@ restart_loop: journal->j_committing_transaction =NULL ;spin_unlock (&journal->j_state_lock); -if (commit_transaction->t_checkpoint_list ==NULL ) { +if (commit_transaction->t_checkpoint_list ==NULL && + commit_transaction->t_checkpoint_io_list ==NULL ) {__jbd2_journal_drop_transaction (journal, commit_transaction); }else {if (journal->j_checkpoint_transactions ==NULL ) {
PATCH 60/84 hugetlb: fix race in alloc_fresh_huge_page()
In reply to Greg KHFrom: Joe Jin <[email protected]>
That static `nid' index needs locking. Without it we can end up calling alloc_pages_node() with an illegal node ID and the kernel crashes.
--- mm/hugetlb.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
mm/hugetlb.c +11 -4
@@ -101,13 +101,20 @@ static void free_huge_page(struct page *static int alloc_fresh_huge_page (void ) { -static int nid =0 ; +static int prev_nid;struct page *page; - page =alloc_pages_node (nid,GFP_HIGHUSER |__GFP_COMP|__GFP_NOWARN, -HUGETLB_PAGE_ORDER ); - nid =next_node (nid, node_online_map); +static DEFINE_SPINLOCK (nid_lock); +int nid; + +spin_lock (&nid_lock); + nid =next_node (prev_nid, node_online_map);if (nid ==MAX_NUMNODES ) nid =first_node (node_online_map); + prev_nid = nid; +spin_unlock (&nid_lock); + + page =alloc_pages_node (nid,GFP_HIGHUSER |__GFP_COMP|__GFP_NOWARN, +HUGETLB_PAGE_ORDER );if (page) {set_compound_page_dtor (page, free_huge_page);spin_lock (&hugetlb_lock);
PATCH 61/84 do not limit locked memory when RLIMIT_MEMLOCK is RLIM_INFINITY
In reply to Greg KHFrom: Herbert van den Bergh <[email protected]>
Fix a bug in mm/mlock.c on 32-bit architectures that prevents a user from locking more than 4GB of shared memory, or allocating more than 4GB of shared memory in hugepages, when rlim[RLIMIT_MEMLOCK] is set to RLIM_INFINITY.
--- mm/mlock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
mm/mlock.c +4 -1
@@ -244,9 +244,12 @@ int user_shm_lock(size_t size, struct us locked = (size +PAGE_SIZE -1 ) >>PAGE_SHIFT ; lock_limit = current->signal->rlim[RLIMIT_MEMLOCK ].rlim_cur; +if (lock_limit ==RLIM_INFINITY ) + allowed =1 ; lock_limit >>=PAGE_SHIFT ;spin_lock (&shmlock_user_lock); -if (locked + user->locked_shm > lock_limit && !capable (CAP_IPC_LOCK )) +if (!allowed && + locked + user->locked_shm > lock_limit && !capable (CAP_IPC_LOCK )) goto out;get_uid (user); user->locked_shm += locked;
PATCH 62/84 uml: limit request size on COWed devices
In reply to Greg KHFrom: Jeff Dike <[email protected]>
COWed devices can't handle more than 32 (64 on x86_64) sectors in one request due to the size of the bitmap being carried around in the io_thread_req.
Enforce that by telling the block layer not to put too many sectors in requests to COWed devices.
--- arch/um/drivers/ubd_kern.c | 2 ++ 1 file changed, 2 insertions(+)
arch/um/drivers/ubd_kern.c +2 -0
@@ -712,6 +712,8 @@ static int ubd_add(int n, char **error_o ubd_dev->queue->queuedata = ubd_dev;blk_queue_max_hw_segments (ubd_dev->queue,MAX_SG ); +if (ubd_dev->cow.file !=NULL ) +blk_queue_max_sectors (ubd_dev->queue,8 *sizeof (long )); err =ubd_disk_register (MAJOR_NR , ubd_dev->size, n, &ubd_gendisk[n]);if (err){ *error_out ="Failed to register device" ;
PATCH 63/84 sony-laptop: fix bug in event handling
In reply to Greg KHFrom: Mattia Dongili <[email protected]>
The rewritten event reading code from sonypi was absolutely wrong, this patche makes things functional for type2 and type1 models.
--- drivers/misc/sony-laptop.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-)
drivers/misc/sony-laptop.c +22 -8
@@ -908,7 +908,9 @@ static struct acpi_driver sony_nc_driver#define SONYPI_DEVICE_TYPE2 0x00000002#define SONYPI_DEVICE_TYPE3 0x00000004 -#define SONY_PIC_EV_MASK 0xff +#define SONYPI_TYPE1_OFFSET 0x04 +#define SONYPI_TYPE2_OFFSET 0x12 +#define SONYPI_TYPE3_OFFSET 0x12struct sony_pic_ioport {struct acpi_resource_io io;
@@ -922,6 +924,7 @@ struct sony_pic_irq {struct sony_pic_dev {int model; +u16 evport_offset;u8 camera_power;u8 bluetooth_power;u8 wwan_power;
@@ -1998,20 +2001,17 @@ end:static irqreturn_t sony_pic_irq (int irq,void *dev_id) {int i, j; -u32 port_val =0 ;u8 ev =0 ;u8 data_mask =0 ;u8 device_event =0 ;struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; -acpi_os_read_port (dev->cur_ioport->io.minimum, &port_val, - dev->cur_ioport->io.address_length); - ev = port_val &SONY_PIC_EV_MASK ; - data_mask =0xff & (port_val >> (dev->cur_ioport->io.address_length -8 )); + ev =inb_p (dev->cur_ioport->io.minimum); + data_mask =inb_p (dev->cur_ioport->io.minimum + dev->evport_offset); -dprintk ("event (0x%.8x [%.2x] [%.2x]) at port 0x%.4x\n" , - port_val, ev, data_mask, dev->cur_ioport->io.minimum); +dprintk ("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n" , + ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset);if (ev ==0x00 || ev ==0xff )return IRQ_HANDLED ;
@@ -2102,6 +2102,20 @@ static int sony_pic_add(struct acpi_devi spic_dev.model =sony_pic_detect_device_type ();mutex_init (&spic_dev.lock); +/* model specific characteristics */ +switch (spic_dev.model) { +case SONYPI_DEVICE_TYPE1 : + spic_dev.evport_offset =SONYPI_TYPE1_OFFSET ; +break ; +case SONYPI_DEVICE_TYPE3 : + spic_dev.evport_offset =SONYPI_TYPE3_OFFSET ; +break ; +case SONYPI_DEVICE_TYPE2 : +default : + spic_dev.evport_offset =SONYPI_TYPE2_OFFSET ; +break ; + } +/* read _PRS resources */ result =sony_pic_possible_resources (device);if (result) {
PATCH 64/84 destroy_workqueue() can livelock
In reply to Greg KHFrom: Oleg Nesterov <[email protected]>
Pointed out by Michal Schmidt <[email protected]>.
The bug was introduced in 2.6.22 by me.
cleanup_workqueue_thread() does flush_cpu_workqueue(cwq) in a loop until ->worklist becomes empty. This is live-lockable, a re-niced caller can get CPU after wake_up() and insert a new barrier before the lower-priority cwq->thread has a chance to clear ->current_work.
Change cleanup_workqueue_thread() to do flush_cpu_workqueue(cwq) only once.
We can rely on the fact that run_workqueue() won't return until it flushes
all works. So it is safe to call kthread_stop() after that, the "should stop" request won't be noticed until run_workqueue() returns.
--- kernel/workqueue.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
kernel/workqueue.c +5 -6
@@ -739,18 +739,17 @@ static void cleanup_workqueue_thread(strif (cwq->thread ==NULL )return ; +flush_cpu_workqueue (cwq);/* -* If the caller is CPU_DEAD the single flush_cpu_workqueue() -* is not enough, a concurrent flush_workqueue() can insert a -* barrier after us. +* If the caller is CPU_DEAD and cwq->worklist was not empty, +* a concurrent flush_workqueue() can insert a barrier after us. +* However, in that case run_workqueue() won't return and check +* kthread_should_stop() until it flushes all work_struct's. * When ->worklist becomes empty it is safe to exit because no * more work_structs can be queued on this cwq: flush_workqueue * checks list_empty(), and a "normal" queue_work() can't use * a dead CPU. */ -while (flush_cpu_workqueue (cwq)) - ; -kthread_stop (cwq->thread); cwq->thread =NULL ; }
PATCH 65/84 drivers/video/macmodes.c:mac_find_mode() mustnt be __devinit
In reply to Greg KHFrom: Adrian Bunk <[email protected]>
If it's EXPORT_SYMBOL'ed it can't be __devinit.
Reported by Mikael Pettersson.
--- drivers/video/macmodes.c | 5 ++--- drivers/video/macmodes.h | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-)
drivers/video/macmodes.c +2 -3
@@ -369,9 +369,8 @@ EXPORT_SYMBOL(mac_map_monitor_sense);* */ -int __devinit mac_find_mode (struct fb_var_screeninfo *var, -struct fb_info *info,const char *mode_option, -unsigned int default_bpp) +int mac_find_mode (struct fb_var_screeninfo *var,struct fb_info *info, +const char *mode_option,unsigned int default_bpp) {const struct fb_videomode *db =NULL ;unsigned int dbsize =0 ;
drivers/video/macmodes.h +4 -4
@@ -55,10 +55,10 @@ extern int mac_vmode_to_var(int vmode, iextern int mac_var_to_vmode (const struct fb_var_screeninfo *var,int *vmode,int *cmode);extern int mac_map_monitor_sense (int sense); -extern int __devinit mac_find_mode (struct fb_var_screeninfo *var, -struct fb_info *info, -const char *mode_option, -unsigned int default_bpp); +extern int mac_find_mode (struct fb_var_screeninfo *var, +struct fb_info *info, +const char *mode_option, +unsigned int default_bpp);/*
PATCH 66/84 cfq-iosched: fix async queue behaviour
In reply to Greg KHFrom: Jens Axboe <[email protected]>
With the cfq_queue hash removal, we inadvertently got rid of the async queue sharing. This was not intentional, in fact CFQ purposely shares the async queue per priority level to get good merging for async writes.
So put some logic in cfq_get_queue() to track the shared queues.
--- block/cfq-iosched.c | 39 ++++++++++++++++++++++++++++++++++++--- include/linux/ioprio.h | 6 ++++-- 2 files changed, 40 insertions(+), 5 deletions(-)
block/cfq-iosched.c +36 -3
@@ -92,6 +92,8 @@ struct cfq_data {struct cfq_queue *active_queue;struct cfq_io_context *active_cic; +struct cfq_queue *async_cfqq[IOPRIO_BE_NR ]; +struct timer_list idle_class_timer;sector_t last_position;
@@ -1351,8 +1353,8 @@ static void cfq_ioc_set_ioprio(struct io }static struct cfq_queue * -cfq_get_queue (struct cfq_data *cfqd,int is_sync,struct task_struct *tsk, -gfp_t gfp_mask) +cfq_find_alloc_queue (struct cfq_data *cfqd,int is_sync, +struct task_struct *tsk,gfp_t gfp_mask) {struct cfq_queue *cfqq, *new_cfqq =NULL ;struct cfq_io_context *cic;
@@ -1405,12 +1407,35 @@ retry:if (new_cfqq)kmem_cache_free (cfq_pool, new_cfqq); -atomic_inc (&cfqq->ref); out:WARN_ON ((gfp_mask & __GFP_WAIT) && !cfqq);return cfqq; } +static struct cfq_queue * +cfq_get_queue (struct cfq_data *cfqd,int is_sync,struct task_struct *tsk, +gfp_t gfp_mask) +{ +const int ioprio =task_ioprio (tsk); +struct cfq_queue *cfqq =NULL ; + +if (!is_sync) + cfqq = cfqd->async_cfqq[ioprio]; +if (!cfqq) + cfqq =cfq_find_alloc_queue (cfqd, is_sync, tsk, gfp_mask); + +/* +* pin the queue now that it's allocated, scheduler exit will prune it +*/ +if (!is_sync && !cfqd->async_cfqq[ioprio]) { +atomic_inc (&cfqq->ref); + cfqd->async_cfqq[ioprio] = cfqq; + } + +atomic_inc (&cfqq->ref); +return cfqq; +} +/* * We drop cfq io contexts lazily, so we may find a dead one. */
@@ -2019,6 +2044,7 @@ static void cfq_exit_queue(elevator_t *e {struct cfq_data *cfqd = e->elevator_data;request_queue_t *q = cfqd->queue; +int i;cfq_shutdown_timer_wq (cfqd);
@@ -2035,6 +2061,13 @@ static void cfq_exit_queue(elevator_t *e__cfq_exit_single_io_context (cfqd, cic); } +/* +* Put the async queues +*/ +for (i =0 ; i <IOPRIO_BE_NR ; i++) +if (cfqd->async_cfqq[i]) +cfq_put_queue (cfqd->async_cfqq[i]); +spin_unlock_irq (q->queue_lock);cfq_shutdown_timer_wq (cfqd);
include/linux/ioprio.h +4 -2
@@ -47,8 +47,10 @@ enum {#define IOPRIO_NORM (4)static inline int task_ioprio (struct task_struct *task) { -WARN_ON (!ioprio_valid (task->ioprio)); -return IOPRIO_PRIO_DATA (task->ioprio); +if (ioprio_valid (task->ioprio)) +return IOPRIO_PRIO_DATA (task->ioprio); + +return IOPRIO_NORM ; }static inline int task_nice_ioprio (struct task_struct *task)
PATCH 67/84 libata: add FUJITSU MHV2080BH to NCQ blacklist
In reply to Greg KHFrom: Tejun Heo <[email protected]>
Please warmly welcome the first member from FUJITSU to the prestigious NCQ spurious completion club.
This is reported by Serge Van Thillo in bugzilla bug 8730.
http://bugzilla.kernel.org/show_bug.cgi?id=8730
--- drivers/ata/libata-core.c | 1 + 1 file changed, 1 insertion(+)
drivers/ata/libata-core.c +1 -0
@@ -3800,6 +3800,7 @@ static const struct ata_blacklist_entry { "HTS541612J9SA00", "SBDIC7JP", ATA_HORKAGE_NONCQ, }, { "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, }, { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, }, + { "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, },/* Devices with NCQ limits */
PATCH 68/84 ieee1394: revert "sbp2: enforce 32bit DMA mapping"
In reply to Greg KHFrom: Stefan Richter <[email protected]>
Revert commit 0555659d63c285ceb7ead3115532e1b71b0f27a7 from 2.6.22-rc1. The dma_set_mask call somehow failed on a PowerMac G5, PPC64:
http://lkml.org/lkml/2007/8/1/344
Should there ever occur a DMA mapping beyond the physical DMA range, a proper SBP-2 firmware will report transport errors. So let's leave it at that.
Same as commit a9c2f18800753c82c45fc13b27bdc148849bdbb2.
--- drivers/ieee1394/sbp2.c | 5 ----- 1 file changed, 5 deletions(-)
drivers/ieee1394/sbp2.c +0 -5
@@ -774,11 +774,6 @@ static struct sbp2_lu *sbp2_alloc_deviceSBP2_ERR ("failed to register lower 4GB address range" ); goto failed_alloc; } -#else -if (dma_set_mask (hi->host->device.parent,DMA_32BIT_MASK )) { -SBP2_ERR ("failed to set 4GB DMA mask" ); - goto failed_alloc; - }#endif }
PATCH 69/84 nfsd: fix possible oops on re-insertion of rpcsec_gss modules
In reply to Greg KHFrom: J. Bruce Fields <[email protected]>
The handling of the re-registration case is wrong here; the "test" that was returned from auth_domain_lookup will not be used again, so that reference should be put. And auth_domain_lookup never did anything with "new" in this case, so we should just clean it up ourself.
Thanks to Akinobu Mita for bug report, analysis, and testing.
--- net/sunrpc/auth_gss/svcauth_gss.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
net/sunrpc/auth_gss/svcauth_gss.c +5 -4
@@ -760,11 +760,12 @@ svcauth_gss_register_pseudoflavor(u32 ps new->h.flavour = &svcauthops_gss; new->pseudoflavor = pseudoflavor; + stat =0 ; test =auth_domain_lookup (name, &new->h); -if (test != &new->h) {/* XXX Duplicate registration? */ -auth_domain_put (&new->h); -/* dangling ref-count... */ - goto out; +if (test != &new->h) {/* Duplicate registration */ +auth_domain_put (test); +kfree (new->h.name); + goto out_free_dom; }return 0 ;
PATCH 70/84 dm raid1: fix status
In reply to Greg KHFrom: Milan Broz <[email protected]>
Fix mirror status line broken in dm-log-report-fault-status.patch:
- space missing between two words
- placeholder ("0") required for compatibility with a subsequent patch
- incorrect offset parameter
--- drivers/md/dm-raid1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/dm-raid1.c +2 -2
@@ -1288,12 +1288,12 @@ static int mirror_status(struct dm_targefor (m =0 ; m < ms->nr_mirrors; m++)DMEMIT ("%s " , ms->mirror[m].dev->name); -DMEMIT ("%llu/%llu" , +DMEMIT ("%llu/%llu 0 " , (unsigned long long )ms->rh.log->type->get_sync_count (ms->rh.log), (unsigned long long )ms->nr_regions); - sz = ms->rh.log->type->status (ms->rh.log, type, result, maxlen); + sz += ms->rh.log->type->status (ms->rh.log, type, result+sz, maxlen-sz);break ;
PATCH 71/84 dm io: fix another panic on large request
In reply to Greg KHFrom: "Jun'ichi Nomura" <[email protected]>
bio_alloc_bioset() will return NULL if 'num_vecs' is too large. Use bio_get_nr_vecs() to get estimation of maximum number.
--- drivers/md/dm-io.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/md/dm-io.c +4 -1
@@ -293,7 +293,10 @@ static void do_region(int rw, unsigned i* bvec for bio_get/set_region() and decrement bi_max_vecs * to hide it from bio_add_page(). */ - num_bvecs = (remaining / (PAGE_SIZE >>SECTOR_SHIFT )) +2 ; + num_bvecs =dm_sector_div_up (remaining, + (PAGE_SIZE >>SECTOR_SHIFT )); + num_bvecs =1 +min_t (int,bio_get_nr_vecs (where->bdev), + num_bvecs); bio =bio_alloc_bioset (GFP_NOIO , num_bvecs, io->client->bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev;
PATCH 72/84 dm snapshot: permit invalid activation
In reply to Greg KHFrom: Milan Broz <[email protected]>
Allow invalid snapshots to be activated instead of failing.
This allows userspace to reinstate any given snapshot state - for example after an unscheduled reboot - and clean up the invalid snapshot at its leisure.
--- drivers/md/dm-exception-store.c | 11 ++++++----- drivers/md/dm-snap.c | 5 ++++- 2 files changed, 10 insertions(+), 6 deletions(-)
drivers/md/dm-exception-store.c +6 -5
@@ -457,11 +457,6 @@ static int persistent_read_metadata(stru/* * Sanity checks. */ -if (!ps->valid) { -DMWARN ("snapshot is marked invalid" ); -return -EINVAL ; - } -if (ps->version !=SNAPSHOT_DISK_VERSION ) {DMWARN ("unable to handle snapshot disk version %d" , ps->version);
@@ -469,6 +464,12 @@ static int persistent_read_metadata(stru }/* +* Metadata are valid, but snapshot is invalidated +*/ +if (!ps->valid) +return 1 ; + +/* * Read the metadata. */ r =read_exceptions (ps);
drivers/md/dm-snap.c +4 -1
@@ -522,9 +522,12 @@ static int snapshot_ctr(struct dm_target/* Metadata must only be loaded into one table at once */ r = s->store.read_metadata (&s->store); -if (r) { +if (r <0 ) { ti->error ="Failed to read snapshot metadata" ; goto bad6; + }else if (r >0 ) { + s->valid =0 ; +DMWARN ("Snapshot is marked invalid." ); }bio_list_init (&s->queued_bios);
PATCH 73/84 dm: disable barriers
In reply to Greg KHFrom: Stefan Bader <[email protected]>
This patch causes device-mapper to reject any barrier requests. This is done since most of the targets won't handle this correctly anyway. So until the situation improves it is better to reject these requests at the first place. Since barrier requests won't get to the targets, the checks there can be removed.
--- drivers/md/dm-crypt.c | 3 --- drivers/md/dm-mpath.c | 3 --- drivers/md/dm-snap.c | 6 ------ drivers/md/dm.c | 9 +++++++++ 4 files changed, 9 insertions(+), 12 deletions(-)
drivers/md/dm-crypt.c +0 -3
@@ -943,9 +943,6 @@ static int crypt_map(struct dm_target *tstruct crypt_config *cc = ti->private;struct crypt_io *io; -if (bio_barrier (bio)) -return -EOPNOTSUPP ; - io =mempool_alloc (cc->io_pool,GFP_NOIO ); io->target = ti; io->base_bio = bio;
drivers/md/dm-mpath.c +0 -3
@@ -798,9 +798,6 @@ static int multipath_map(struct dm_targestruct mpath_io *mpio;struct multipath *m = (struct multipath *) ti->private; -if (bio_barrier (bio)) -return -EOPNOTSUPP ; - mpio =mempool_alloc (m->mpio_pool,GFP_NOIO );dm_bio_record (&mpio->details, bio);
drivers/md/dm-snap.c +0 -6
@@ -887,9 +887,6 @@ static int snapshot_map(struct dm_targetif (!s->valid)return -EIO ; -if (unlikely (bio_barrier (bio))) -return -EOPNOTSUPP ; -/* FIXME: should only take write lock if we need * to copy an exception */ down_write (&s->lock);
@@ -1160,9 +1157,6 @@ static int origin_map(struct dm_target *struct dm_dev *dev = (struct dm_dev *) ti->private; bio->bi_bdev = dev->bdev; -if (unlikely (bio_barrier (bio))) -return -EOPNOTSUPP ; -/* Only tell snapshots if this is a write */ return (bio_rw (bio) ==WRITE ) ?do_origin (dev, bio) :DM_MAPIO_REMAPPED ; }
drivers/md/dm.c +9 -0
@@ -802,6 +802,15 @@ static int dm_request(request_queue_t *qint rw =bio_data_dir (bio);struct mapped_device *md = q->queuedata; +/* +* There is no use in forwarding any barrier request since we can't +* guarantee it is (or can be) handled by the targets correctly. +*/ +if (unlikely (bio_barrier (bio))) { +bio_endio (bio, bio->bi_size, -EOPNOTSUPP ); +return 0 ; + } +down_read (&md->io_lock);disk_stat_inc (dm_disk (md), ios[rw]);
PATCH 74/84 cr_backlight_probe() allocates too little storage for struct cr_panel
In reply to Greg KHFrom: Jesper Juhl <[email protected]>
The Coverity checker noticed that we allocate too little storage for "struct cr_panel *crp" in cr_backlight_probe().
--- drivers/video/backlight/cr_bllcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/video/backlight/cr_bllcd.c +1 -1
@@ -174,7 +174,7 @@ static int cr_backlight_probe(struct plastruct cr_panel *crp;u8 dev_en; - crp =kzalloc (sizeof (crp),GFP_KERNEL ); + crp =kzalloc (sizeof (*crp),GFP_KERNEL );if (crp ==NULL )return -ENOMEM ;
PATCH 75/84 ACPI: dock: fix opps after dock driver fails to initialize
In reply to Greg KHFrom: Chuck Ebbert <[email protected]>
ACPI: dock: fix opps after dock driver fails to initialize
The driver tests the dock_station pointer for nonnull to check whether it has initialized properly. But in some cases dock_station will be non-null after being freed when driver init fails. Fix by zeroing the pointer after freeing.
--- drivers/acpi/dock.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/acpi/dock.c +7 -0
@@ -716,6 +716,7 @@ static int dock_add(acpi_handle handle)if (ret) { printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret);kfree (dock_station); + dock_station =NULL ;return ret; } ret =device_create_file (&dock_device.dev, &dev_attr_docked);
@@ -723,6 +724,7 @@ static int dock_add(acpi_handle handle)printk ("Error %d adding sysfs file\n" , ret);platform_device_unregister (&dock_device);kfree (dock_station); + dock_station =NULL ;return ret; } ret =device_create_file (&dock_device.dev, &dev_attr_undock);
@@ -731,6 +733,7 @@ static int dock_add(acpi_handle handle)device_remove_file (&dock_device.dev, &dev_attr_docked);platform_device_unregister (&dock_device);kfree (dock_station); + dock_station =NULL ;return ret; } ret =device_create_file (&dock_device.dev, &dev_attr_uid);
@@ -738,6 +741,7 @@ static int dock_add(acpi_handle handle)printk ("Error %d adding sysfs file\n" , ret);platform_device_unregister (&dock_device);kfree (dock_station); + dock_station =NULL ;return ret; }
@@ -750,6 +754,7 @@ static int dock_add(acpi_handle handle) dd =alloc_dock_dependent_device (handle);if (!dd) {kfree (dock_station); + dock_station =NULL ; ret = -ENOMEM ; goto dock_add_err_unregister; }
@@ -777,6 +782,7 @@ dock_add_err_unregister:device_remove_file (&dock_device.dev, &dev_attr_undock);platform_device_unregister (&dock_device);kfree (dock_station); + dock_station =NULL ;return ret; }
@@ -810,6 +816,7 @@ static int dock_remove(void)/* free dock station memory */ kfree (dock_station); + dock_station =NULL ;return 0 ; }
PATCH 76/84 Hangup TTY before releasing rfcomm_dev
In reply to Greg KHFrom: Mikko Rapeli <[email protected]>
The core problem is that RFCOMM socket layer ioctl can release rfcomm_dev struct while RFCOMM TTY layer is still actively using it. Calling tty_vhangup() is needed for a synchronous hangup before rfcomm_dev is freed.
Addresses the oops at http://bugzilla.kernel.org/show_bug.cgi?id=7509
--- net/bluetooth/rfcomm/tty.c | 4 ++++ 1 file changed, 4 insertions(+)
net/bluetooth/rfcomm/tty.c +4 -0
@@ -383,6 +383,10 @@ static int rfcomm_release_dev(void __useif (req.flags & (1 <<RFCOMM_HANGUP_NOW ))rfcomm_dlc_close (dev->dlc,0 ); +/* Shut down TTY synchronously before freeing rfcomm_dev */ +if (dev->tty) +tty_vhangup (dev->tty); +rfcomm_dev_del (dev);rfcomm_dev_put (dev);return 0 ;
PATCH 77/84 Keep rfcomm_dev on the list until it is freed
In reply to Greg KHFrom: Ville Tervo <[email protected]>
This patch changes the RFCOMM TTY release process so that the TTY is kept on the list until it is really freed. A new device flag is used to keep track of released TTYs.
--- include/net/bluetooth/rfcomm.h | 1 + net/bluetooth/rfcomm/tty.c | 30 ++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-)
include/net/bluetooth/rfcomm.h +1 -0
@@ -323,6 +323,7 @@ int rfcomm_connect_ind(struct rfcomm_se#define RFCOMM_RELEASE_ONHUP 1#define RFCOMM_HANGUP_NOW 2#define RFCOMM_TTY_ATTACHED 3 +#define RFCOMM_TTY_RELEASED 4struct rfcomm_dev_req {s16 dev_id;
net/bluetooth/rfcomm/tty.c +22 -8
@@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct rBT_DBG ("dev %p dlc %p" , dev, dlc); +write_lock_bh (&rfcomm_dev_lock); +list_del_init (&dev->list); +write_unlock_bh (&rfcomm_dev_lock); +rfcomm_dlc_lock (dlc);/* Detach DLC if it's owned by this dev */ if (dlc->owner == dev)
@@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_read_lock (&rfcomm_dev_lock); dev =__rfcomm_dev_get (id); -if (dev) -rfcomm_dev_hold (dev); + +if (dev) { +if (test_bit (RFCOMM_TTY_RELEASED , &dev->flags)) + dev =NULL ; +else +rfcomm_dev_hold (dev); + }read_unlock (&rfcomm_dev_lock);
@@ -265,6 +274,12 @@ out: dev->tty_dev =tty_register_device (rfcomm_tty_driver, dev->id,NULL ); +if (IS_ERR (dev->tty_dev)) { +list_del (&dev->list); +kfree (dev); +return PTR_ERR (dev->tty_dev); + } +return dev->id; }
@@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm {BT_DBG ("dev %p" , dev); -write_lock_bh (&rfcomm_dev_lock); -list_del_init (&dev->list); -write_unlock_bh (&rfcomm_dev_lock); - +set_bit (RFCOMM_TTY_RELEASED , &dev->flags);rfcomm_dev_put (dev); }
@@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sockif (copy_from_user (&req, arg,sizeof (req)))return -EFAULT ; -BT_DBG ("sk %p dev_id %id flags 0x%x" , sk, req.dev_id, req.flags); +BT_DBG ("sk %p dev_id %d flags 0x%x" , sk, req.dev_id, req.flags);if (req.flags !=NOCAP_FLAGS && !capable (CAP_NET_ADMIN ))return -EPERM ;
@@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __useif (copy_from_user (&req, arg,sizeof (req)))return -EFAULT ; -BT_DBG ("dev_id %id flags 0x%x" , req.dev_id, req.flags); +BT_DBG ("dev_id %d flags 0x%x" , req.dev_id, req.flags);if (!(dev =rfcomm_dev_get (req.dev_id)))return -ENODEV ;
@@ -419,6 +431,8 @@ static int rfcomm_get_dev_list(void __uslist_for_each (p, &rfcomm_dev_list) { struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); +if (test_bit (RFCOMM_TTY_RELEASED , &dev->flags)) +continue ; (di + n)->id = dev->id; (di + n)->flags = dev->flags; (di + n)->state = dev->dlc->state;
PATCH 78/84 nf_conntrack: dont track locally generated special ICMP error
In reply to Greg KHFrom: Yasuyuki Kozakai <[email protected]>
[NETFILTER]: nf_conntrack: don't track locally generated special ICMP error
The conntrack assigned to locally generated ICMP error is usually the one assigned to the original packet which has caused the error. But if the original packet is handled as invalid by nf_conntrack, no conntrack is assigned to the original packet. Then nf_ct_attach() cannot assign any conntrack to the ICMP error packet. In that case the current nf_conntrack_icmp assigns appropriate conntrack to it. But the current code mistakes the direction of the packet. As a result, NAT code mistakes the address to be mangled.
To fix the bug, this changes nf_conntrack_icmp not to assign conntrack to such ICMP error. Actually no address is necessary to be mangled in this case.
Spotted by Jordan Russell.
Upstream commit ID: 130e7a83d7ec8c5c673225e0fa8ea37b1ed507a5
--- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-)
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +5 -17
@@ -189,25 +189,13 @@ icmp_error_message(struct sk_buff *skb, h =nf_conntrack_find_get (&innertuple,NULL );if (!h) { -/* Locally generated ICMPs will match inverted if they -haven't been SNAT'ed yet */ -/* FIXME: NAT code has to handle half-done double NAT --RR */ -if (hooknum ==NF_IP_LOCAL_OUT ) - h =nf_conntrack_find_get (&origtuple,NULL ); - -if (!h) { -DEBUGP ("icmp_error_message: no match\n" ); -return -NF_ACCEPT ; - } - -/* Reverse direction from that found */ -if (NF_CT_DIRECTION (h) ==IP_CT_DIR_REPLY ) - *ctinfo +=IP_CT_IS_REPLY ; - }else { -if (NF_CT_DIRECTION (h) ==IP_CT_DIR_REPLY ) - *ctinfo +=IP_CT_IS_REPLY ; +DEBUGP ("icmp_error_message: no match\n" ); +return -NF_ACCEPT ; } +if (NF_CT_DIRECTION (h) ==IP_CT_DIR_REPLY ) + *ctinfo +=IP_CT_IS_REPLY ; +/* Update skb to refer to this connection */ skb->nfct = &nf_ct_tuplehash_to_ctrack (h)->ct_general; skb->nfctinfo = *ctinfo;
PATCH 79/84 IPV6: /proc/net/anycast6 unbalanced inet6_dev refcnt
In reply to Greg KHFrom: David Stevens <[email protected]>
Reading /proc/net/anycast6 when there is no anycast address on an interface results in an ever-increasing inet6_dev reference count, as well as a reference to the netdevice you can't get rid of.
--- net/ipv6/anycast.c | 1 + 1 file changed, 1 insertion(+)
net/ipv6/anycast.c +1 -0
@@ -66,6 +66,7 @@ ip6_onlink(struct in6_addr *addr, structbreak ; }read_unlock_bh (&idev->lock); +in6_dev_put (idev); }rcu_read_unlock ();return onlink;
PATCH 80/84 sysfs: release mutex when kmalloc() failed in sysfs_open_file().
In reply to Greg KHFrom: YOSHIFUJI Hideaki <[email protected]>
--- fs/sysfs/file.c | 1 + 1 file changed, 1 insertion(+)
fs/sysfs/file.c +1 -0
@@ -283,6 +283,7 @@ static int sysfs_open_file(struct inodemutex_lock (&inode->i_mutex);if (!(set = inode->i_private)) {if (!(set = inode->i_private =kmalloc (sizeof (struct sysfs_buffer_collection ),GFP_KERNEL ))) { +mutex_unlock (&inode->i_mutex); error = -ENOMEM ; goto Done; }else {
PATCH 81/84 Netfilter: Fix logging regression
In reply to Greg KHFrom: Patrick McHardy <[email protected]>
[NETFILTER]: Fix logging regression
Loading one of the LOG target fails if a different target has already registered itself as backend for the same family. This can affect the ipt_LOG and ipt_ULOG modules when both are loaded.
Reported and tested by: <[email protected]>
Upstream-commit: 7e2acc7e
--- net/bridge/netfilter/ebt_log.c | 6 ++---- net/bridge/netfilter/ebt_ulog.c | 8 ++------ net/ipv4/netfilter/ipt_LOG.c | 6 ++---- net/ipv6/netfilter/ip6t_LOG.c | 6 ++---- 4 files changed, 8 insertions(+), 18 deletions(-)
net/bridge/netfilter/ebt_log.c +2 -4
@@ -196,10 +196,8 @@ static int __init ebt_log_init(void) ret =ebt_register_watcher (&log);if (ret <0 )return ret; - ret =nf_log_register (PF_BRIDGE , &ebt_log_logger); -if (ret <0 && ret != -EEXIST ) -ebt_unregister_watcher (&log); -return ret; +nf_log_register (PF_BRIDGE , &ebt_log_logger); +return 0 ; } static void __exit ebt_log_fini(void)
net/bridge/netfilter/ebt_ulog.c +2 -6
@@ -308,12 +308,8 @@ static int __init ebt_ulog_init(void)else if ((ret =ebt_register_watcher (&ulog)))sock_release (ebtulognl->sk_socket); -if (nf_log_register (PF_BRIDGE , &ebt_ulog_logger) <0 ) { -printk (KERN_WARNING "ebt_ulog: not logging via ulog " -"since somebody else already registered for PF_BRIDGE\n" ); -/* we cannot make module load fail here, since otherwise -* ebtables userspace would abort */ - } +if (ret ==0 ) +nf_log_register (PF_BRIDGE , &ebt_ulog_logger);return ret; }
net/ipv4/netfilter/ipt_LOG.c +2 -4
@@ -477,10 +477,8 @@ static int __init ipt_log_init(void) ret =xt_register_target (&ipt_log_reg);if (ret <0 )return ret; - ret =nf_log_register (PF_INET , &ipt_log_logger); -if (ret <0 && ret != -EEXIST ) -xt_unregister_target (&ipt_log_reg); -return ret; +nf_log_register (PF_INET , &ipt_log_logger); +return 0 ; } static void __exit ipt_log_fini(void)
net/ipv6/netfilter/ip6t_LOG.c +2 -4
@@ -490,10 +490,8 @@ static int __init ip6t_log_init(void) ret =xt_register_target (&ip6t_log_reg);if (ret <0 )return ret; - ret =nf_log_register (PF_INET6 , &ip6t_logger); -if (ret <0 && ret != -EEXIST ) -xt_unregister_target (&ip6t_log_reg); -return ret; +nf_log_register (PF_INET6 , &ip6t_logger); +return 0 ; } static void __exit ip6t_log_fini(void)
PATCH 82/84 USB: fix for ftdi_sio quirk handling
In reply to Greg KHFrom: Oliver Neukum <[email protected]>
this one fixes an oops with quirky ftdi_sio devices. As it fixes a regression, I propose that it be included in 2.6.22
--- drivers/usb/serial/ftdi_sio.c | 104 +++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 60 deletions(-)
drivers/usb/serial/ftdi_sio.c +44 -60
@@ -271,26 +271,58 @@ static int debug;static __u16 vendor =FTDI_VID ;static __u16 product; +struct ftdi_private { +ftdi_chip_type_t chip_type; +/* type of the device, either SIO or FT8U232AM */ +int baud_base;/* baud base clock for divisor setting */ +int custom_divisor;/* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ +__u16 last_set_data_urb_value ; +/* the last data state set - needed for doing a break */ +int write_offset;/* This is the offset in the usb data block to write the serial data - +* it is different between devices +*/ +int flags;/* some ASYNC_xxxx flags are supported */ +unsigned long last_dtr_rts;/* saved modem control outputs */ +wait_queue_head_t delta_msr_wait;/* Used for TIOCMIWAIT */ +char prev_status, diff_status;/* Used for TIOCMIWAIT */ +__u8 rx_flags;/* receive state flags (throttling) */ +spinlock_t rx_lock;/* spinlock for receive state */ +struct delayed_work rx_work; +struct usb_serial_port *port; +int rx_processed; +unsigned long rx_bytes; + +__u16 interface;/* FT2232C port interface (0 for FT232/245) */ + +int force_baud;/* if non-zero, force the baud rate to this value */ +int force_rtscts;/* if non-zero, force RTS-CTS to always be enabled */ + +spinlock_t tx_lock;/* spinlock for transmit state */ +unsigned long tx_bytes; +unsigned long tx_outstanding_bytes; +unsigned long tx_outstanding_urbs; +}; +/* struct ftdi_sio_quirk is used by devices requiring special attention. */ struct ftdi_sio_quirk {int (*probe)(struct usb_serial *); -void (*setup)(struct usb_serial *);/* Special settings during startup. */ +void (*port_probe)(struct ftdi_private *);/* Special settings for probed ports. */ };static int ftdi_olimex_probe (struct usb_serial *serial); -static void ftdi_USB_UIRT_setup (struct usb_serial *serial); -static void ftdi_HE_TIRA1_setup (struct usb_serial *serial); +static void ftdi_USB_UIRT_setup (struct ftdi_private *priv); +static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv);static struct ftdi_sio_quirk ftdi_olimex_quirk = { .probe = ftdi_olimex_probe, };static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { - .setup = ftdi_USB_UIRT_setup, + .port_probe = ftdi_USB_UIRT_setup, };static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { - .setup = ftdi_HE_TIRA1_setup, + .port_probe = ftdi_HE_TIRA1_setup, };/*
@@ -567,38 +599,6 @@ static const char *ftdi_chip_name[] = {#define THROTTLED 0x01#define ACTUALLY_THROTTLED 0x02 -struct ftdi_private { -ftdi_chip_type_t chip_type; -/* type of the device, either SIO or FT8U232AM */ -int baud_base;/* baud base clock for divisor setting */ -int custom_divisor;/* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ -__u16 last_set_data_urb_value ; -/* the last data state set - needed for doing a break */ -int write_offset;/* This is the offset in the usb data block to write the serial data - -* it is different between devices -*/ -int flags;/* some ASYNC_xxxx flags are supported */ -unsigned long last_dtr_rts;/* saved modem control outputs */ -wait_queue_head_t delta_msr_wait;/* Used for TIOCMIWAIT */ -char prev_status, diff_status;/* Used for TIOCMIWAIT */ -__u8 rx_flags;/* receive state flags (throttling) */ -spinlock_t rx_lock;/* spinlock for receive state */ -struct delayed_work rx_work; -struct usb_serial_port *port; -int rx_processed; -unsigned long rx_bytes; - -__u16 interface;/* FT2232C port interface (0 for FT232/245) */ - -int force_baud;/* if non-zero, force the baud rate to this value */ -int force_rtscts;/* if non-zero, force RTS-CTS to always be enabled */ - -spinlock_t tx_lock;/* spinlock for transmit state */ -unsigned long tx_bytes; -unsigned long tx_outstanding_bytes; -unsigned long tx_outstanding_urbs; -}; -/* Used for TIOCMIWAIT */ #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)#define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
@@ -609,7 +609,6 @@ struct ftdi_private {/* function prototypes for a FTDI serial converter */ static int ftdi_sio_probe (struct usb_serial *serial,const struct usb_device_id *id); -static int ftdi_sio_attach (struct usb_serial *serial);static void ftdi_shutdown (struct usb_serial *serial);static int ftdi_sio_port_probe (struct usb_serial_port *port);static int ftdi_sio_port_remove (struct usb_serial_port *port);
@@ -663,7 +662,6 @@ static struct usb_serial_driver ftdi_sio .ioctl = ftdi_ioctl, .set_termios = ftdi_set_termios, .break_ctl = ftdi_break_ctl, - .attach = ftdi_sio_attach, .shutdown = ftdi_shutdown, };
@@ -1198,6 +1196,8 @@ static int ftdi_sio_probe (struct usb_sestatic int ftdi_sio_port_probe (struct usb_serial_port *port) {struct ftdi_private *priv; +struct ftdi_sio_quirk *quirk =usb_get_serial_data (port->serial); +dbg ("%s" ,__FUNCTION__);
@@ -1214,6 +1214,9 @@ static int ftdi_sio_port_probe(struct usthan queue a task to deliver them */ priv->flags =ASYNC_LOW_LATENCY ; +if (quirk && quirk->port_probe) + quirk->port_probe (priv); +/* Increase the size of read buffers */ kfree (port->bulk_in_buffer); port->bulk_in_buffer =kmalloc (BUFSZ ,GFP_KERNEL );
@@ -1244,29 +1247,13 @@ static int ftdi_sio_port_probe(struct usreturn 0 ; } -/* attach subroutine */ -static int ftdi_sio_attach (struct usb_serial *serial) -{ -/* Check for device requiring special set up. */ -struct ftdi_sio_quirk *quirk =usb_get_serial_data (serial); - -if (quirk && quirk->setup) - quirk->setup (serial); - -return 0 ; -}/* ftdi_sio_attach */ - -/* Setup for the USB-UIRT device, which requires hardwired * baudrate (38400 gets mapped to 312500) */ /* Called from usbserial:serial_probe */ -static void ftdi_USB_UIRT_setup (struct usb_serial *serial) +static void ftdi_USB_UIRT_setup (struct ftdi_private *priv) { -struct ftdi_private *priv; -dbg ("%s" ,__FUNCTION__); - priv =usb_get_serial_port_data (serial->port[0 ]); priv->flags |=ASYNC_SPD_CUST ; priv->custom_divisor =77 ; priv->force_baud =B38400 ;
@@ -1274,13 +1261,10 @@ static void ftdi_USB_UIRT_setup (struct/* Setup for the HE-TIRA1 device, which requires hardwired * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ -static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) +static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv) { -struct ftdi_private *priv; -dbg ("%s" ,__FUNCTION__); - priv =usb_get_serial_port_data (serial->port[0 ]); priv->flags |=ASYNC_SPD_CUST ; priv->custom_divisor =240 ; priv->force_baud =B38400 ;
PATCH 83/84 sx: switch subven and subid values
In reply to Greg KHFrom: Jiri Slaby <[email protected]>
sx.c is failing to locate Graham's card.
--- drivers/char/sx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/char/sx.c +2 -2
@@ -2721,9 +2721,9 @@ static void __devexit sx_pci_remove(struits because the standard requires it. So check for SUBVENDOR_ID. */ static struct pci_device_id sx_pci_tbl[] = { {PCI_VENDOR_ID_SPECIALIX ,PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 , - .subvendor =0x0200 ,.subdevice =PCI_ANY_ID }, + .subvendor =PCI_ANY_ID , .subdevice =0x0200 }, {PCI_VENDOR_ID_SPECIALIX ,PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 , - .subvendor =0x0300 ,.subdevice =PCI_ANY_ID }, + .subvendor =PCI_ANY_ID , .subdevice =0x0300 }, {0 } };
PATCH 84/84 UML: exports for hostfs
In reply to Greg KHFrom: Jeff Dike <[email protected]>
Add some exports for hostfs that are required after Alberto Bertogli's fixes for accessing unlinked host files.
Also did some style cleanups while I was here.
--- arch/um/os-Linux/user_syms.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-)
arch/um/os-Linux/user_syms.c +8 -12
@@ -5,7 +5,8 @@* so I *must* declare good prototypes for them and then EXPORT them. * The kernel code uses the macro defined by include/linux/string.h, * so I undef macros; the userspace code does not include that and I -* add an EXPORT for the glibc one.*/ +* add an EXPORT for the glibc one. +*/ #undef strlen#undef strstr
@@ -61,12 +62,18 @@ EXPORT_SYMBOL_PROTO(dup2);EXPORT_SYMBOL_PROTO (__xstat);EXPORT_SYMBOL_PROTO (__lxstat);EXPORT_SYMBOL_PROTO (__lxstat64); +EXPORT_SYMBOL_PROTO (__fxstat64);EXPORT_SYMBOL_PROTO (lseek);EXPORT_SYMBOL_PROTO (lseek64);EXPORT_SYMBOL_PROTO (chown); +EXPORT_SYMBOL_PROTO (fchown);EXPORT_SYMBOL_PROTO (truncate); +EXPORT_SYMBOL_PROTO (ftruncate64);EXPORT_SYMBOL_PROTO (utime); +EXPORT_SYMBOL_PROTO (utimes); +EXPORT_SYMBOL_PROTO (futimes);EXPORT_SYMBOL_PROTO (chmod); +EXPORT_SYMBOL_PROTO (fchmod);EXPORT_SYMBOL_PROTO (rename);EXPORT_SYMBOL_PROTO (__xmknod);
@@ -102,14 +109,3 @@ EXPORT_SYMBOL(__stack_smash_handler); extern long __guard __attribute__((weak));EXPORT_SYMBOL (__guard ); - -/* -* Overrides for Emacs so that we follow Linus's tabbing style. -* Emacs will notice this stuff at the end of the file and automatically -* adjust the settings for this buffer only. This must remain at the end -* of the file. -* --------------------------------------------------------------------------- -* Local variables: -* c-file-style: "linux" -* End: -*/
Signature · 9 lines
------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ User-mode-linux-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
Quoted 5 lines · Greg KH
This is the start of the stable review cycle for the 2.6.22.2 release. There are 84 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let us know. If anyone is a maintainer of the proper subsystem, and wants to add a Signed-off-by: line to the patch, please respond with it.
Rolled up patch can be found at:
kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.22.2-rc1.gz
thanks,
greg k-h