Skip to contentSkip to conversation

2.6.22-stable review

PATCH In review Greg KH 1 participant 29 messages Oct 31, 2007

Subsystems (19)
lore
Share & tools
lore

Greg KH

author
#0 lore raw

cover 2.6.22-stable review

This is the start of the stable review cycle for the 2.6.22.11 release. There are 26 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 Nov 2, 2007 16:00:00 UTC. Anything received after that time might be too late.

This is probably going to be the last 2.6.22-stable release, unless I have missed some major issues somewhere. If I have, please let the stable team know.

thanks,

the -stable release team

author
#1 lore raw

PATCH 1/26 ACPI: disable lower idle C-states across suspend/resume

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Thomas Gleixner <[email protected]>

changeset b04e7bdb984e3b7f62fb7f44146a529f88cc7639 from mainline.

device_suspend() calls ACPI suspend functions, which seems to have undesired side effects on lower idle C-states. It took me some time to realize that especially the VAIO BIOSes (both Andrews jinxed UP and my elfstruck SMP one) show this effect. I'm quite sure that other bug reports against suspend/resume about turning the system into a brick have the same root cause.

After fishing in the dark for quite some time, I realized that removing the ACPI processor module before suspend (this removes the lower C-state functionality) made the problem disappear. Interestingly enough the propability of having a bricked box is influenced by various factors (interrupts, size of the ram image, ...). Even adding a bunch of printks in the wrong places made the problem go away. The previous periodic tick implementation simply pampered over the problem, which explains why the dyntick / clockevents changes made this more prominent.

We avoid complex functionality during the boot process and we have to do the same during suspend/resume. It is a similar scenario and equaly fragile.

Add suspend / resume functions to the ACPI processor code and disable the lower idle C-states across suspend/resume. Fall back to the default idle implementation (halt) instead.

---
 drivers/acpi/processor_core.c |    2 ++
 drivers/acpi/processor_idle.c |   19 ++++++++++++++++++-
 include/acpi/processor.h      |    2 ++
 3 files changed, 22 insertions(+), 1 deletion(-)
drivers/acpi/processor_core.c +2 -0
@@ -93,6 +93,8 @@ static struct acpi_driver acpi_processor
 		.add = acpi_processor_add,
 		.remove = acpi_processor_remove,
 		.start = acpi_processor_start,
+		.suspend = acpi_processor_suspend,
+		.resume = acpi_processor_resume,
 		},
 };
 
drivers/acpi/processor_idle.c +18 -1
@@ -324,6 +324,23 @@ static void acpi_state_timer_broadcast(s
 
 #endif
 
+/*
+ * Suspend / resume control
+ */
+static int acpi_idle_suspend;
+
+int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
+{
+	acpi_idle_suspend = 1;
+	return 0;
+}
+
+int acpi_processor_resume(struct acpi_device * device)
+{
+	acpi_idle_suspend = 0;
+	return 0;
+}
+
 static void acpi_processor_idle(void)
 {
 	struct acpi_processor *pr = NULL;
@@ -354,7 +371,7 @@ static void acpi_processor_idle(void)
 	}
 
 	cx = pr->power.state;
-	if (!cx) {
+	if (!cx || acpi_idle_suspend) {
 		if (pm_idle_save)
 			pm_idle_save();
 		else
include/acpi/processor.h +2 -0
@@ -279,6 +279,8 @@ int acpi_processor_power_init(struct acp
 int acpi_processor_cst_has_changed(struct acpi_processor *pr);
 int acpi_processor_power_exit(struct acpi_processor *pr,
 			      struct acpi_device *device);
+int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
+int acpi_processor_resume(struct acpi_device * device);
 
 /* in processor_thermal.c */
 int acpi_processor_get_limit_info(struct acpi_processor *pr);
author
#2 lore raw

PATCH 2/26 Fix ESP host instance numbering.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: David Miller <[email protected]>

changeset ff4abd6cfacf0bb23a077f615d3a5cd17359db1b in mainline.

The ESP scsi driver does not initialize the host controller instance early enough, so the messages in the log confuse users.

---
 drivers/scsi/esp_scsi.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/scsi/esp_scsi.c +2 -1
@@ -2318,6 +2318,7 @@ int __devinit scsi_esp_register(struct e
 	esp->host->transportt = esp_transport_template;
 	esp->host->max_lun = ESP_MAX_LUN;
 	esp->host->cmd_per_lun = 2;
+	esp->host->unique_id = instance;
 
 	esp_set_clock_params(esp);
 
@@ -2341,7 +2342,7 @@ int __devinit scsi_esp_register(struct e
 	if (err)
 		return err;
 
-	esp->host->unique_id = instance++;
+	instance++;
 
 	scsi_scan_host(esp->host);
 
author
#3 lore raw

PATCH 3/26 Fix cls_u32 error return handling.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Stephen Hemminger <[email protected]>

changeset bf1b803b01b00c3801e0aa373ba0305f8278e260 from mainline.

---
 net/sched/cls_u32.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/cls_u32.c +1 -1
@@ -518,7 +518,7 @@ static int u32_set_parms(struct tcf_prot
 
 #ifdef CONFIG_NET_CLS_IND
 	if (tb[TCA_U32_INDEV-1]) {
-		int err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]);
+		err = tcf_change_indev(tp, n->indev, tb[TCA_U32_INDEV-1]);
 		if (err < 0)
 			goto errout;
 	}
author
#4 lore raw

PATCH 4/26 Fix ieee80211 handling of bogus hdrlength field

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: John W. Linville <[email protected]>

changeset 04045f98e0457aba7d4e6736f37eed189c48a5f7 from mainline

Reported by Chris Evans <[email protected]>:

Quoted 14 lines

The summary is that an evil 80211 frame can crash out a victim's machine. It only applies to drivers using the 80211 wireless code, and only then to certain drivers (and even then depends on a card's firmware not dropping a dubious packet). I must confess I'm not keeping track of Linux wireless support, and the different protocol stacks etc.

Details are as follows:

ieee80211_rx() does not explicitly check that "skb->len >= hdrlen". There are other skb->len checks, but not enough to prevent a subtle off-by-two error if the frame has the IEEE80211_STYPE_QOS_DATA flag set.

Quoted 6 lines

This leads to integer underflow and crash here:

if (frag != 0)
flen -= hdrlen;

(flen is subsequently used as a memcpy length parameter).

How about this?

---
 net/ieee80211/ieee80211_rx.c |    6 ++++++
 1 file changed, 6 insertions(+)
net/ieee80211/ieee80211_rx.c +6 -0
@@ -366,6 +366,12 @@ int ieee80211_rx(struct ieee80211_device
 	frag = WLAN_GET_SEQ_FRAG(sc);
 	hdrlen = ieee80211_get_hdrlen(fc);
 
+	if (skb->len < hdrlen) {
+		printk(KERN_INFO "%s: invalid SKB length %d\n",
+			dev->name, skb->len);
+		goto rx_dropped;
+	}
+
 	/* Put this code here so that we avoid duplicating it in all
 	 * Rx paths. - Jean II */
 #ifdef CONFIG_WIRELESS_EXT
author
#5 lore raw

PATCH 5/26 Fix some cases of missed IPV6 DAD

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Mitsuru Chinen <[email protected]>

changeset 0fcace22d38ce9216f5ba52f929a99d284aa7e49 from mainline

To judge the timing for DAD, netif_carrier_ok() is used. However, there is a possibility that dev->qdisc stays noop_qdisc even if netif_carrier_ok() returns true. In that case, DAD NS is not sent out. We need to defer the IPv6 device initialization until a valid qdisc is specified.

---
 net/ipv6/addrconf.c |   13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
net/ipv6/addrconf.c +10 -3
@@ -73,6 +73,7 @@
 #include <net/tcp.h>
 #include <net/ip.h>
 #include <net/netlink.h>
+#include <net/pkt_sched.h>
 #include <linux/if_tunnel.h>
 #include <linux/rtnetlink.h>
 
@@ -212,6 +213,12 @@ static struct ipv6_devconf ipv6_devconf_
 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
 
+/* Check if a valid qdisc is available */
+static inline int addrconf_qdisc_ok(struct net_device *dev)
+{
+	return (dev->qdisc != &noop_qdisc);
+}
+
 static void addrconf_del_timer(struct inet6_ifaddr *ifp)
 {
 	if (del_timer(&ifp->timer))
@@ -376,7 +383,7 @@ static struct inet6_dev * ipv6_add_dev(s
 	}
 #endif
 
-	if (netif_running(dev) && netif_carrier_ok(dev))
+	if (netif_running(dev) && addrconf_qdisc_ok(dev))
 		ndev->if_flags |= IF_READY;
 
 	ipv6_mc_init_dev(ndev);
@@ -2269,7 +2276,7 @@ static int addrconf_notify(struct notifi
 	case NETDEV_UP:
 	case NETDEV_CHANGE:
 		if (event == NETDEV_UP) {
-			if (!netif_carrier_ok(dev)) {
+			if (!addrconf_qdisc_ok(dev)) {
 				/* device is not ready yet. */
 				printk(KERN_INFO
 					"ADDRCONF(NETDEV_UP): %s: "
@@ -2281,7 +2288,7 @@ static int addrconf_notify(struct notifi
 			if (idev)
 				idev->if_flags |= IF_READY;
 		} else {
-			if (!netif_carrier_ok(dev)) {
+			if (!addrconf_qdisc_ok(dev)) {
 				/* device is still not ready. */
 				break;
 			}
author
#6 lore raw

PATCH 6/26 Fix ipv6 redirect processing, leads to TAHI failures.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------

From: Brian Haley <[email protected]>

changeset bf0b48dfc368c07c42b5a3a5658c8ee81b4283ac from mainline.

When the ICMPv6 Target address is multicast, Linux processes the redirect instead of dropping it. The problem is in this code in ndisc_redirect_rcv():

         if (ipv6_addr_equal(dest, target)) {
                 on_link = 1;
         } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
                 ND_PRINTK2(KERN_WARNING
                            "ICMPv6 Redirect: target address is not
link-local.\n");
                 return;
         }

This second check will succeed if the Target address is, for example, FF02::1 because it has link-local scope. Instead, it should be checking if it's a unicast link-local address, as stated in RFC 2461/4861 Section 8.1:

- The ICMP Target Address is either a link-local address (when redirected to a router) or the same as the ICMP Destination Address (when redirected to the on-link destination).

I know this doesn't explicitly say unicast link-local address, but it's implied.

This bug is preventing Linux kernels from achieving IPv6 Logo Phase II certification because of a recent error that was found in the TAHI test suite - Neighbor Disovery suite test 206 (v6LC.2.3.6_G) had the multicast address in the Destination field instead of Target field, so we were passing the test. This won't be the case anymore.

The patch below fixes this problem, and also fixes ndisc_send_redirect() to not send an invalid redirect with a multicast address in the Target field. I re-ran the TAHI Neighbor Discovery section to make sure Linux passes all 245 tests now.

---
 net/ipv6/ndisc.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
net/ipv6/ndisc.c +5 -4
@@ -1268,9 +1268,10 @@ static void ndisc_redirect_rcv(struct sk
 
 	if (ipv6_addr_equal(dest, target)) {
 		on_link = 1;
-	} else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
+	} else if (ipv6_addr_type(target) !=
+		   (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
 		ND_PRINTK2(KERN_WARNING
-			   "ICMPv6 Redirect: target address is not link-local.\n");
+			   "ICMPv6 Redirect: target address is not link-local unicast.\n");
 		return;
 	}
 
@@ -1344,9 +1345,9 @@ void ndisc_send_redirect(struct sk_buff 
 	}
 
 	if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) &&
-	    !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
+	    ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
 		ND_PRINTK2(KERN_WARNING
-			"ICMPv6 Redirect: target address is not link-local.\n");
+			"ICMPv6 Redirect: target address is not link-local unicast.\n");
 		return;
 	}
 
author
#7 lore raw

PATCH 7/26 Fix ROSE module unload oops.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Alexey Dobriyan <[email protected]>

changeset 891e6a931255238dddd08a7b306871240961a27f from mainline.

Commit a3d384029aa304f8f3f5355d35f0ae274454f7cd aka "[AX.25]: Fix unchecked rose_add_loopback_neigh uses" transformed rose_loopback_neigh var into statically allocated one. However, on unload it will be kfree's which can't work.

Steps to reproduce:

modprobe rose
rmmod rose

BUG: unable to handle kernel NULL pointer dereference at virtual address 00000008
 printing eip:
c014c664
*pde = 00000000
Oops: 0000 [#1]
PREEMPT DEBUG_PAGEALLOC
Modules linked in: rose ax25 fan ufs loop usbhid rtc snd_intel8x0 snd_ac97_codec ehci_hcd ac97_bus uhci_hcd thermal usbcore button processor evdev sr_mod cdrom
CPU:    0
EIP:    0060:[<c014c664>]    Not tainted VLI
EFLAGS: 00210086   (2.6.23-rc9 #3)

EIP is at kfree+0x48/0xa1
eax: 00000556 ebx: c1734aa0 ecx: f6a5e000 edx: f7082000
esi: 00000000 edi: f9a55d20 ebp: 00200287 esp: f6a5ef28
ds: 007b es: 007b fs: 0000 gs: 0033 ss: 0068
Process rmmod (pid: 1823, ti=f6a5e000 task=f7082000 task.ti=f6a5e000)

Stack: f9a55d20 f9a5200c 00000000 00000000 00000000 f6a5e000 f9a5200c f9a55a00
       00000000 bf818cf0 f9a51f3f f9a55a00 00000000 c0132c60 65736f72 00000000
       f69f9630 f69f9528 c014244a f6a4e900 00200246 f7082000 c01025e6 00000000
Call Trace:
 [<f9a5200c>] rose_rt_free+0x1d/0x49 [rose]
 [<f9a5200c>] rose_rt_free+0x1d/0x49 [rose]
 [<f9a51f3f>] rose_exit+0x4c/0xd5 [rose]
 [<c0132c60>] sys_delete_module+0x15e/0x186
 [<c014244a>] remove_vma+0x40/0x45
 [<c01025e6>] sysenter_past_esp+0x8f/0x99
 [<c012bacf>] trace_hardirqs_on+0x118/0x13b
 [<c01025b6>] sysenter_past_esp+0x5f/0x99
 =======================
Code: 05 03 1d 80 db 5b c0 8b 03 25 00 40 02 00 3d 00 40 02 00 75 03 8b 5b 0c 8b 73 10 8b 44 24 18 89 44 24 04 9c 5d fa e8 77 df fd ff <8b> 56 08 89 f8 e8 84 f4 fd ff e8 bd 32 06 00 3b 5c 86 60 75 0f
EIP: [<c014c664>] kfree+0x48/0xa1 SS:ESP 0068:f6a5ef28
---
 include/net/rose.h       |    2 +-
 net/rose/rose_loopback.c |    4 ++--
 net/rose/rose_route.c    |   15 ++++++++++-----
 3 files changed, 13 insertions(+), 8 deletions(-)
include/net/rose.h +1 -1
@@ -188,7 +188,7 @@ extern void rose_kick(struct sock *);
 extern void rose_enquiry_response(struct sock *);
 
 /* rose_route.c */
-extern struct rose_neigh rose_loopback_neigh;
+extern struct rose_neigh *rose_loopback_neigh;
 extern const struct file_operations rose_neigh_fops;
 extern const struct file_operations rose_nodes_fops;
 extern const struct file_operations rose_routes_fops;
net/rose/rose_loopback.c +2 -2
@@ -79,7 +79,7 @@ static void rose_loopback_timer(unsigned
 
 		skb_reset_transport_header(skb);
 
-		sk = rose_find_socket(lci_o, &rose_loopback_neigh);
+		sk = rose_find_socket(lci_o, rose_loopback_neigh);
 		if (sk) {
 			if (rose_process_rx_frame(sk, skb) == 0)
 				kfree_skb(skb);
@@ -88,7 +88,7 @@ static void rose_loopback_timer(unsigned
 
 		if (frametype == ROSE_CALL_REQUEST) {
 			if ((dev = rose_dev_get(dest)) != NULL) {
-				if (rose_rx_call_request(skb, dev, &rose_loopback_neigh, lci_o) == 0)
+				if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0)
 					kfree_skb(skb);
 			} else {
 				kfree_skb(skb);
net/rose/rose_route.c +10 -5
@@ -45,7 +45,7 @@ static DEFINE_SPINLOCK(rose_neigh_list_l
 static struct rose_route *rose_route_list;
 static DEFINE_SPINLOCK(rose_route_list_lock);
 
-struct rose_neigh rose_loopback_neigh;
+struct rose_neigh *rose_loopback_neigh;
 
 /*
  *	Add a new route to a node, and in the process add the node and the
@@ -362,7 +362,12 @@ out:
  */
 void rose_add_loopback_neigh(void)
 {
-	struct rose_neigh *sn = &rose_loopback_neigh;
+	struct rose_neigh *sn;
+
+	rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_KERNEL);
+	if (!rose_loopback_neigh)
+		return;
+	sn = rose_loopback_neigh;
 
 	sn->callsign  = null_ax25_address;
 	sn->digipeat  = NULL;
@@ -417,13 +422,13 @@ int rose_add_loopback_node(rose_address 
 	rose_node->mask         = 10;
 	rose_node->count        = 1;
 	rose_node->loopback     = 1;
-	rose_node->neighbour[0] = &rose_loopback_neigh;
+	rose_node->neighbour[0] = rose_loopback_neigh;
 
 	/* Insert at the head of list. Address is always mask=10 */
 	rose_node->next = rose_node_list;
 	rose_node_list  = rose_node;
 
-	rose_loopback_neigh.count++;
+	rose_loopback_neigh->count++;
 
 out:
 	spin_unlock_bh(&rose_node_list_lock);
@@ -454,7 +459,7 @@ void rose_del_loopback_node(rose_address
 
 	rose_remove_node(rose_node);
 
-	rose_loopback_neigh.count--;
+	rose_loopback_neigh->count--;
 
 out:
 	spin_unlock_bh(&rose_node_list_lock);
author
#8 lore raw

PATCH 8/26 Fix zero length socket write() semantics.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: David S. Miller <[email protected]>

changeset e79ad711a0108475c1b3a03815527e7237020b08 from mainline.

This fixes kernel bugzilla #5731

It should generate an empty packet for datagram protocols when the socket is connected, for one.

The check is doubly-wrong because all that a write() can be is a sendmsg() call with a NULL msg_control and a single entry iovec. No special semantics should be assigned to it, therefore the zero length check should be removed entirely.

This matches the behavior of BSD and several other systems.

Alan Cox notes that SuSv3 says the behavior of a zero length write on non-files is "unspecified", but that's kind of useless since BSD has defined this behavior for a quarter century and BSD is essentially what application folks code to.

Based upon a patch from Stephen Hemminger.

---
 net/socket.c |    3 ---
 1 file changed, 3 deletions(-)
net/socket.c +0 -3
@@ -778,9 +778,6 @@ static ssize_t sock_aio_write(struct kio
 	if (pos != 0)
 		return -ESPIPE;
 
-	if (iocb->ki_left == 0)	/* Match SYS5 behaviour */
-		return 0;
-
 	x = alloc_sock_iocb(iocb, &siocb);
 	if (!x)
 		return -ENOMEM;
author
#9 lore raw

PATCH 9/26 Fix sys_ipc() SEMCTL on sparc64.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: David S. Miller <[email protected]>

changeset 6536a6b331d3225921c398eb7c6e4ecedb9b05e0 from mainline

Thanks to Tom Callaway for the excellent bug report and test case.

sys_ipc() has several problems, most to due with semaphore call handling:

1) 'err' return should be a 'long'
2) "union semun" is passed in a register on 64-bit compared to 32-bit which provides it on the stack and therefore by reference
3) Second and third arguments to SEMCTL are swapped compared to 32-bit.

---
 arch/sparc64/kernel/sys_sparc.c |   15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)
arch/sparc64/kernel/sys_sparc.c +4 -11
@@ -436,7 +436,7 @@ out:
 asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
 			unsigned long third, void __user *ptr, long fifth)
 {
-	int err;
+	long err;
 
 	/* No need for backward compatibility. We can start fresh... */
 	if (call <= SEMCTL) {
@@ -453,16 +453,9 @@ asmlinkage long sys_ipc(unsigned int cal
 			err = sys_semget(first, (int)second, (int)third);
 			goto out;
 		case SEMCTL: {
-			union semun fourth;
-			err = -EINVAL;
-			if (!ptr)
-				goto out;
-			err = -EFAULT;
-			if (get_user(fourth.__pad,
-				     (void __user * __user *) ptr))
-				goto out;
-			err = sys_semctl(first, (int)second | IPC_64,
-					 (int)third, fourth);
+			err = sys_semctl(first, third,
+					 (int)second | IPC_64,
+					 (union semun) ptr);
 			goto out;
 		}
 		default:
author
#10 lore raw

PATCH 10/26 Fix TCPs ->fastpath_cnt_hit handling.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Ilpo J�rvinen <[email protected]>

changeset 48611c47d09023d9356e78550d1cadb8d61da9c8 in mainline.

When only GSO skb was partially ACKed, no hints are reset, therefore fastpath_cnt_hint must be tweaked too or else it can corrupt fackets_out. The corruption to occur, one must have non-trivial ACK/SACK sequence, so this bug is not very often that harmful. There's a fackets_out state reset in TCP because fackets_out is known to be inaccurate and that fixes the issue eventually anyway.

In case there was also at least one skb that got fully ACKed, the fastpath_skb_hint is set to NULL which causes a recount for fastpath_cnt_hint (the old value won't be accessed anymore), thus it can safely be decremented without additional checking.

Reported by Cedric Le Goater <[email protected]>

---
 net/ipv4/tcp_input.c |    3 +++
 1 file changed, 3 insertions(+)
net/ipv4/tcp_input.c +3 -0
@@ -2403,6 +2403,9 @@ static int tcp_tso_acked(struct sock *sk
 			__u32 dval = min(tp->fackets_out, packets_acked);
 			tp->fackets_out -= dval;
 		}
+		/* hint's skb might be NULL but we don't need to care */
+		tp->fastpath_cnt_hint -= min_t(u32, packets_acked,
+					       tp->fastpath_cnt_hint);
 		tp->packets_out -= packets_acked;
 
 		BUG_ON(tcp_skb_pcount(skb) == 0);
author
#11 lore raw

PATCH 11/26 : Fix TCP MD5 on big-endian.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: David Miller <[email protected]>

changeset f8ab18d2d987a59ccbf0495032b2aef05b730037 in mainline.

Based upon a report and initial patch by Peter Lieven.

tcp4_md5sig_key and tcp6_md5sig_key need to start with the exact same members as tcp_md5sig_key. Because they are both cast to that type by tcp_v{4,6}_md5_do_lookup().

Unfortunately tcp{4,6}_md5sig_key use a u16 for the key length instead of a u8, which is what tcp_md5sig_key uses. This just so happens to work by accident on little-endian, but on big-endian it doesn't.

Instead of casting, just place tcp_md5sig_key as the first member of the address-family specific structures, adjust the access sites, and kill off the ugly casts.

---
 include/net/tcp.h   |    6 ++----
 net/ipv4/tcp_ipv4.c |   19 +++++++++----------
 net/ipv6/tcp_ipv6.c |   18 +++++++++---------
 3 files changed, 20 insertions(+), 23 deletions(-)
include/net/tcp.h +2 -4
@@ -1061,14 +1061,12 @@ struct tcp_md5sig_key {
 };
 
 struct tcp4_md5sig_key {
-	u8			*key;
-	u16			keylen;
+	struct tcp_md5sig_key	base;
 	__be32			addr;
 };
 
 struct tcp6_md5sig_key {
-	u8			*key;
-	u16			keylen;
+	struct tcp_md5sig_key	base;
 #if 0
 	u32			scope_id;	/* XXX */
 #endif
net/ipv4/tcp_ipv4.c +9 -10
@@ -833,8 +833,7 @@ static struct tcp_md5sig_key *
 		return NULL;
 	for (i = 0; i < tp->md5sig_info->entries4; i++) {
 		if (tp->md5sig_info->keys4[i].addr == addr)
-			return (struct tcp_md5sig_key *)
-						&tp->md5sig_info->keys4[i];
+			return &tp->md5sig_info->keys4[i].base;
 	}
 	return NULL;
 }
@@ -865,9 +864,9 @@ int tcp_v4_md5_do_add(struct sock *sk, _
 	key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr);
 	if (key) {
 		/* Pre-existing entry - just update that one. */
-		kfree(key->key);
-		key->key = newkey;
-		key->keylen = newkeylen;
+		kfree(key->base.key);
+		key->base.key = newkey;
+		key->base.keylen = newkeylen;
 	} else {
 		struct tcp_md5sig_info *md5sig;
 
@@ -906,9 +905,9 @@ int tcp_v4_md5_do_add(struct sock *sk, _
 			md5sig->alloced4++;
 		}
 		md5sig->entries4++;
-		md5sig->keys4[md5sig->entries4 - 1].addr   = addr;
-		md5sig->keys4[md5sig->entries4 - 1].key    = newkey;
-		md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen;
+		md5sig->keys4[md5sig->entries4 - 1].addr        = addr;
+		md5sig->keys4[md5sig->entries4 - 1].base.key    = newkey;
+		md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen;
 	}
 	return 0;
 }
@@ -930,7 +929,7 @@ int tcp_v4_md5_do_del(struct sock *sk, _
 	for (i = 0; i < tp->md5sig_info->entries4; i++) {
 		if (tp->md5sig_info->keys4[i].addr == addr) {
 			/* Free the key */
-			kfree(tp->md5sig_info->keys4[i].key);
+			kfree(tp->md5sig_info->keys4[i].base.key);
 			tp->md5sig_info->entries4--;
 
 			if (tp->md5sig_info->entries4 == 0) {
@@ -964,7 +963,7 @@ static void tcp_v4_clear_md5_list(struct
 	if (tp->md5sig_info->entries4) {
 		int i;
 		for (i = 0; i < tp->md5sig_info->entries4; i++)
-			kfree(tp->md5sig_info->keys4[i].key);
+			kfree(tp->md5sig_info->keys4[i].base.key);
 		tp->md5sig_info->entries4 = 0;
 		tcp_free_md5sig_pool();
 	}
net/ipv6/tcp_ipv6.c +9 -9
@@ -551,7 +551,7 @@ static struct tcp_md5sig_key *tcp_v6_md5
 
 	for (i = 0; i < tp->md5sig_info->entries6; i++) {
 		if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0)
-			return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i];
+			return &tp->md5sig_info->keys6[i].base;
 	}
 	return NULL;
 }
@@ -579,9 +579,9 @@ static int tcp_v6_md5_do_add(struct sock
 	key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer);
 	if (key) {
 		/* modify existing entry - just update that one */
-		kfree(key->key);
-		key->key = newkey;
-		key->keylen = newkeylen;
+		kfree(key->base.key);
+		key->base.key = newkey;
+		key->base.keylen = newkeylen;
 	} else {
 		/* reallocate new list if current one is full. */
 		if (!tp->md5sig_info) {
@@ -615,8 +615,8 @@ static int tcp_v6_md5_do_add(struct sock
 
 		ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr,
 			       peer);
-		tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey;
-		tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen;
+		tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey;
+		tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen;
 
 		tp->md5sig_info->entries6++;
 	}
@@ -638,7 +638,7 @@ static int tcp_v6_md5_do_del(struct sock
 	for (i = 0; i < tp->md5sig_info->entries6; i++) {
 		if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) {
 			/* Free the key */
-			kfree(tp->md5sig_info->keys6[i].key);
+			kfree(tp->md5sig_info->keys6[i].base.key);
 			tp->md5sig_info->entries6--;
 
 			if (tp->md5sig_info->entries6 == 0) {
@@ -669,7 +669,7 @@ static void tcp_v6_clear_md5_list (struc
 
 	if (tp->md5sig_info->entries6) {
 		for (i = 0; i < tp->md5sig_info->entries6; i++)
-			kfree(tp->md5sig_info->keys6[i].key);
+			kfree(tp->md5sig_info->keys6[i].base.key);
 		tp->md5sig_info->entries6 = 0;
 		tcp_free_md5sig_pool();
 	}
@@ -680,7 +680,7 @@ static void tcp_v6_clear_md5_list (struc
 
 	if (tp->md5sig_info->entries4) {
 		for (i = 0; i < tp->md5sig_info->entries4; i++)
-			kfree(tp->md5sig_info->keys4[i].key);
+			kfree(tp->md5sig_info->keys4[i].base.key);
 		tp->md5sig_info->entries4 = 0;
 		tcp_free_md5sig_pool();
 	}
author
#12 lore raw

PATCH 12/26 : Fix TCP initial sequence number selection.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Eric Dumazet <[email protected]>

changeset 162f6690a65075b49f242d3c8cdb5caaa959a060 in mainline.

TCP V4 sequence numbers are 32bits, and RFC 793 assumed a 250 KHz clock. In order to follow network speed increase, we can use a faster clock, but we should limit this clock so that the delay between two rollovers is greater than MSL (TCP Maximum Segment Lifetime : 2 minutes)

Choosing a 64 nsec clock should be OK, since the rollovers occur every 274 seconds.

Problem spotted by Denys Fedoryshchenko

[ This bug was introduced by f85958151900f9d30fa5ff941b0ce71eaa45a7de ]

---
 drivers/char/random.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/char/random.c +6 -4
@@ -1550,11 +1550,13 @@ __u32 secure_tcp_sequence_number(__be32 
 	 *	As close as possible to RFC 793, which
 	 *	suggests using a 250 kHz clock.
 	 *	Further reading shows this assumes 2 Mb/s networks.
-	 *	For 10 Gb/s Ethernet, a 1 GHz clock is appropriate.
-	 *	That's funny, Linux has one built in!  Use it!
-	 *	(Networks are faster now - should this be increased?)
+	 *	For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
+	 *	For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
+	 *	we also need to limit the resolution so that the u32 seq
+	 *	overlaps less than one time per MSL (2 minutes).
+	 *	Choosing a clock of 64 ns period is OK. (period of 274 s)
 	 */
-	seq += ktime_get_real().tv64;
+	seq += ktime_get_real().tv64 >> 6;
 #if 0
 	printk("init_seq(%lx, %lx, %d, %d) = %d\n",
 	       saddr, daddr, sport, dport, seq);
author
#13 lore raw

PATCH 13/26 mac80211: filter locally-originated multicast frames

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------

From: John W. Linville <[email protected]>

patch b331615722779b078822988843ddffd4eaec9f83 in mainline.

In STA mode, the AP will echo our traffic. This includes multicast traffic.

Receiving these frames confuses some protocols and applications, notably IPv6 Duplicate Address Detection.

---
 net/mac80211/ieee80211.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
net/mac80211/ieee80211.c +3 -2
@@ -2615,9 +2615,10 @@ ieee80211_rx_h_data(struct ieee80211_txr
 		memcpy(dst, hdr->addr1, ETH_ALEN);
 		memcpy(src, hdr->addr3, ETH_ALEN);
 
-		if (sdata->type != IEEE80211_IF_TYPE_STA) {
+		if (sdata->type != IEEE80211_IF_TYPE_STA ||
+		    (is_multicast_ether_addr(dst) &&
+		     !compare_ether_addr(src, dev->dev_addr)))
 			return TXRX_DROP;
-		}
 		break;
 	case 0:
 		/* DA SA BSSID */
author
#14 lore raw

PATCH 14/26 libertas: fix endianness breakage

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------

From: Al Viro <[email protected]>

patch 5707708111ca6c4e9a1160acffdc98a98d95e462 in mainline.

	wep->keytype[] is u8
---
 drivers/net/wireless/libertas/cmd.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/wireless/libertas/cmd.c +2 -4
@@ -185,14 +185,12 @@ static int wlan_cmd_802_11_set_wep(wlan_
 
 			switch (pkey->len) {
 			case KEY_LEN_WEP_40:
-				wep->keytype[i] =
-					cpu_to_le16(cmd_type_wep_40_bit);
+				wep->keytype[i] = cmd_type_wep_40_bit;
 				memmove(&wep->keymaterial[i], pkey->key,
 				        pkey->len);
 				break;
 			case KEY_LEN_WEP_104:
-				wep->keytype[i] =
-					cpu_to_le16(cmd_type_wep_104_bit);
+				wep->keytype[i] = cmd_type_wep_104_bit;
 				memmove(&wep->keymaterial[i], pkey->key,
 				        pkey->len);
 				break;
author
#15 lore raw

PATCH 15/26 libertas: more endianness breakage

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------

From: Al Viro <[email protected]>

based on patch 8362cd413e8116306fafbaf414f0419db0595142 in mainline.

	domain->header.len is le16 and has just been assigned

cpu_to_le16(arithmetical expression). And all fields of adapter->logmsg are __le32; not a single 16-bit among them...
That's incremental to the previous one

---
 drivers/net/wireless/libertas/11d.c  |    2 +-
 drivers/net/wireless/libertas/wext.c |    8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)
drivers/net/wireless/libertas/11d.c +1 -1
@@ -562,7 +562,7 @@ int libertas_cmd_802_11d_domain_info(wla
 		       nr_subband * sizeof(struct ieeetypes_subbandset));
 
 		cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
-					     domain->header.len +
+					     le16_to_cpu(domain->header.len) +
 					     sizeof(struct mrvlietypesheader) +
 					     S_DS_GEN);
 	} else {
drivers/net/wireless/libertas/wext.c +4 -4
@@ -973,7 +973,7 @@ static struct iw_statistics *wlan_get_wi
 	/* Quality by TX errors */
 	priv->wstats.discard.retries = priv->stats.tx_errors;
 
-	tx_retries = le16_to_cpu(adapter->logmsg.retry);
+	tx_retries = le32_to_cpu(adapter->logmsg.retry);
 
 	if (tx_retries > 75)
 		tx_qual = (90 - tx_retries) * POOR / 15;
@@ -989,10 +989,10 @@ static struct iw_statistics *wlan_get_wi
 		    (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
 	quality = min(quality, tx_qual);
 
-	priv->wstats.discard.code = le16_to_cpu(adapter->logmsg.wepundecryptable);
-	priv->wstats.discard.fragment = le16_to_cpu(adapter->logmsg.rxfrag);
+	priv->wstats.discard.code = le32_to_cpu(adapter->logmsg.wepundecryptable);
+	priv->wstats.discard.fragment = le32_to_cpu(adapter->logmsg.rxfrag);
 	priv->wstats.discard.retries = tx_retries;
-	priv->wstats.discard.misc = le16_to_cpu(adapter->logmsg.ackfailure);
+	priv->wstats.discard.misc = le32_to_cpu(adapter->logmsg.ackfailure);
 
 	/* Calculate quality */
 	priv->wstats.qual.qual = max(quality, (u32)100);
author
#16 lore raw

PATCH 16/26 Add get_unaligned to ieee80211_get_radiotap_len

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------

From: Andy Green <[email protected]>

patch dfe6e81deaa79c85086c0cc8d85b229e444ab97f in mainline.

ieee80211_get_radiotap_len() tries to dereference radiotap length without taking care that it is completely unaligned and get_unaligned() is required.

---
 net/mac80211/ieee80211.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/mac80211/ieee80211.c +2 -1
@@ -24,6 +24,7 @@
 #include <linux/compiler.h>
 #include <linux/bitmap.h>
 #include <net/cfg80211.h>
+#include <asm/unaligned.h>
 
 #include "ieee80211_common.h"
 #include "ieee80211_i.h"
@@ -338,7 +339,7 @@ static int ieee80211_get_radiotap_len(st
 	struct ieee80211_radiotap_header *hdr =
 		(struct ieee80211_radiotap_header *) skb->data;
 
-	return le16_to_cpu(hdr->it_len);
+	return le16_to_cpu(get_unaligned(&hdr->it_len));
 }
 
 #ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP
author
#17 lore raw

PATCH 17/26 firewire: fix unloading of fw-ohci while devices are attached

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Stefan Richter <[email protected]>

Fix panic in run_timer_softirq right after "modprobe -r firewire-ohci" if a FireWire disk was attached and firewire-sbp2 loaded.

Same as commit 8a2d9ed3210464d22fccb9834970629c1c36fa36.

---
 drivers/firewire/fw-card.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/firewire/fw-card.c +4 -2
@@ -507,9 +507,11 @@ fw_core_remove_card(struct fw_card *card
 	/* Set up the dummy driver. */
 	card->driver = &dummy_driver;
 
-	fw_flush_transactions(card);
-
 	fw_destroy_nodes(card);
+	flush_scheduled_work();
+
+	fw_flush_transactions(card);
+	del_timer_sync(&card->flush_timer);
 
 	fw_card_put(card);
 }
author
#18 lore raw

PATCH 18/26 netdrvr: natsemi: Fix device removal bug

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
This episode illustrates how an overused warning can train people to ignore that warning, which winds up hiding bugs.

The warning

drivers/net/natsemi.c: In function ‘natsemi_remove1’:
drivers/net/natsemi.c:3222: warning: ignoring return value of ‘device_create_file’, declared with attribute warn_unused_result

is oft-ignored, even though at close inspection one notices this occurs in the /remove/ function, not normally where creation occurs. A quick s/create/remove/ and we are fixed, with the warning gone.

---
 drivers/net/natsemi.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/natsemi.c +1 -1
@@ -671,7 +671,7 @@ static ssize_t natsemi_show_##_name(stru
 #define NATSEMI_CREATE_FILE(_dev, _name) \
          device_create_file(&_dev->dev, &dev_attr_##_name)
 #define NATSEMI_REMOVE_FILE(_dev, _name) \
-         device_create_file(&_dev->dev, &dev_attr_##_name)
+         device_remove_file(&_dev->dev, &dev_attr_##_name)
 
 NATSEMI_ATTR(dspcfg_workaround);
 
author
#19 lore raw

PATCH 19/26 dm9601: Fix receive MTU

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Peter Korsgaard <[email protected]>

patch f662fe5a0b144efadbfc00e8040e603ec318746e in mainline.

dm9601: Fix receive MTU

dm9601 didn't take the ethernet header into account when calculating RX MTU, causing packets bigger than 1486 to fail.

---
 drivers/net/usb/dm9601.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/usb/dm9601.c +1 -1
@@ -405,7 +405,7 @@ static int dm9601_bind(struct usbnet *de
 	dev->net->ethtool_ops = &dm9601_ethtool_ops;
 	dev->net->hard_header_len += DM_TX_OVERHEAD;
 	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-	dev->rx_urb_size = dev->net->mtu + DM_RX_OVERHEAD;
+	dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD;
 
 	dev->mii.dev = dev->net;
 	dev->mii.mdio_read = dm9601_mdio_read;
author
#20 lore raw

PATCH 20/26 V4L: ivtv: fix udma yuv bug

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------

From: Ian Armstrong <[email protected]>

Based on cb50f548c0ee9b2aac39743fc4021a7188825a98 in mainline

[PATCH] V4L: ivtv: fix udma yuv bug

Using udma yuv causes the driver to become locked into that mode. This prevents use of the mpeg decoder & non-udma yuv output.

This patch clears the operating mode when the device is closed.

---
 drivers/media/video/ivtv/ivtv-fileops.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/media/video/ivtv/ivtv-fileops.c +2 -0
@@ -753,6 +753,8 @@ static void ivtv_stop_decoding(struct iv
 	}
 	if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_YUV)
 	    itv->output_mode = OUT_NONE;
+	else if (s->type == IVTV_DEC_STREAM_TYPE_YUV && itv->output_mode == OUT_UDMA_YUV)
+	    itv->output_mode = OUT_NONE;
 	else if (s->type == IVTV_DEC_STREAM_TYPE_MPG && itv->output_mode == OUT_MPG)
 	    itv->output_mode = OUT_NONE;
 
author
#21 lore raw

PATCH 21/26 hwmon/lm87: Fix a division by zero

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Jean Delvare <[email protected]>

Already in Linus' tree:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=b965d4b7f614522170af6a7e450be0333792ccd2

Missing parentheses in the definition of FAN_FROM_REG cause a division by zero for a specific register value.

---
 drivers/hwmon/lm87.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/lm87.c +1 -1
@@ -129,7 +129,7 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A,
 				 (((val) < 0 ? (val)-500 : (val)+500) / 1000))
 
 #define FAN_FROM_REG(reg,div)	((reg) == 255 || (reg) == 0 ? 0 : \
-				 1350000 + (reg)*(div) / 2) / ((reg)*(div))
+				 (1350000 + (reg)*(div) / 2) / ((reg)*(div)))
 #define FAN_TO_REG(val,div)	((val)*(div) * 255 <= 1350000 ? 255 : \
 				 (1350000 + (val)*(div) / 2) / ((val)*(div)))
 
author
#22 lore raw

PATCH 22/26 hwmon/lm87: Disable VID when it should be

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Jean Delvare <[email protected]>

Already in Linus' tree:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=889af3d5d9586db795a06c619e416b4baee11da8

A stupid bit shifting bug caused the VID value to be always exported even when the hardware is configured for something different.

---
 drivers/hwmon/lm87.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/lm87.c +1 -1
@@ -145,7 +145,7 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A,
 #define CHAN_NO_FAN(nr)		(1 << (nr))
 #define CHAN_TEMP3		(1 << 2)
 #define CHAN_VCC_5V		(1 << 3)
-#define CHAN_NO_VID		(1 << 8)
+#define CHAN_NO_VID		(1 << 7)
 
 /*
  * Functions declaration
author
#23 lore raw

PATCH 23/26 hwmon/w83627hf: Fix setting fan min right after driver load

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Jean Delvare <[email protected]>

Already in Linus' tree:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=c09c5184a26158da32801e89d5849d774605f0dd

We need to read the fan clock dividers at initialization time, otherwise the code in store_fan_min() may use uninitialized values. That's pretty much the same bug and same fix as for the w83627ehf driver last month.

---
 drivers/hwmon/w83627hf.c |   34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)
drivers/hwmon/w83627hf.c +22 -12
@@ -335,6 +335,7 @@ static int w83627hf_remove(struct platfo
 
 static int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
 static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
+static void w83627hf_update_fan_div(struct w83627hf_data *data);
 static struct w83627hf_data *w83627hf_update_device(struct device *dev);
 static void w83627hf_init_device(struct platform_device *pdev);
 
@@ -1127,6 +1128,7 @@ static int __devinit w83627hf_probe(stru
 	data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1));
 	data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2));
 	data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3));
+	w83627hf_update_fan_div(data);
 
 	/* Register common device attributes */
 	if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group)))
@@ -1430,6 +1432,24 @@ static void __devinit w83627hf_init_devi
 			    | 0x01);
 }
 
+static void w83627hf_update_fan_div(struct w83627hf_data *data)
+{
+	int reg;
+
+	reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
+	data->fan_div[0] = (reg >> 4) & 0x03;
+	data->fan_div[1] = (reg >> 6) & 0x03;
+	if (data->type != w83697hf) {
+		data->fan_div[2] = (w83627hf_read_value(data,
+				       W83781D_REG_PIN) >> 6) & 0x03;
+	}
+	reg = w83627hf_read_value(data, W83781D_REG_VBAT);
+	data->fan_div[0] |= (reg >> 3) & 0x04;
+	data->fan_div[1] |= (reg >> 4) & 0x04;
+	if (data->type != w83697hf)
+		data->fan_div[2] |= (reg >> 5) & 0x04;
+}
+
 static struct w83627hf_data *w83627hf_update_device(struct device *dev)
 {
 	struct w83627hf_data *data = dev_get_drvdata(dev);
@@ -1493,18 +1513,8 @@ static struct w83627hf_data *w83627hf_up
 			  w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3));
 		}
 
-		i = w83627hf_read_value(data, W83781D_REG_VID_FANDIV);
-		data->fan_div[0] = (i >> 4) & 0x03;
-		data->fan_div[1] = (i >> 6) & 0x03;
-		if (data->type != w83697hf) {
-			data->fan_div[2] = (w83627hf_read_value(data,
-					       W83781D_REG_PIN) >> 6) & 0x03;
-		}
-		i = w83627hf_read_value(data, W83781D_REG_VBAT);
-		data->fan_div[0] |= (i >> 3) & 0x04;
-		data->fan_div[1] |= (i >> 4) & 0x04;
-		if (data->type != w83697hf)
-			data->fan_div[2] |= (i >> 5) & 0x04;
+		w83627hf_update_fan_div(data);
+
 		data->alarms =
 		    w83627hf_read_value(data, W83781D_REG_ALARM1) |
 		    (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) |
author
#24 lore raw

PATCH 24/26 hwmon/w83627hf: Dont assume bank 0

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Jean Delvare <[email protected]>

Already in Linus' tree:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44

The bank switching code assumes that the bank selector is set to 0 when the driver is loaded. This might not be the case. This is exactly the same bug as was fixed in the w83627ehf driver two months ago:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0956895aa6f8dc6a33210967252fd7787652537d

In practice, this bug was causing the sensor thermal types to be improperly reported for my W83627THF the first time I was loading the w83627hf driver. From the driver history, I'd say that it has been broken since September 2005 (when we stopped resetting the chip by default at driver load.)

---
 drivers/hwmon/w83627hf.c |   44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)
drivers/hwmon/w83627hf.c +22 -22
@@ -1209,6 +1209,24 @@ static int __devexit w83627hf_remove(str
 }
 
 
+/* Registers 0x50-0x5f are banked */
+static inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg)
+{
+	if ((reg & 0x00f0) == 0x50) {
+		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
+		outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET);
+	}
+}
+
+/* Not strictly necessary, but play it safe for now */
+static inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg)
+{
+	if (reg & 0xff00) {
+		outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET);
+		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
+	}
+}
+
 static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
 {
 	int res, word_sized;
@@ -1219,12 +1237,7 @@ static int w83627hf_read_value(struct w8
 		  && (((reg & 0x00ff) == 0x50)
 		   || ((reg & 0x00ff) == 0x53)
 		   || ((reg & 0x00ff) == 0x55));
-	if (reg & 0xff00) {
-		outb_p(W83781D_REG_BANK,
-		       data->addr + W83781D_ADDR_REG_OFFSET);
-		outb_p(reg >> 8,
-		       data->addr + W83781D_DATA_REG_OFFSET);
-	}
+	w83627hf_set_bank(data, reg);
 	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
 	res = inb_p(data->addr + W83781D_DATA_REG_OFFSET);
 	if (word_sized) {
@@ -1234,11 +1247,7 @@ static int w83627hf_read_value(struct w8
 		    (res << 8) + inb_p(data->addr +
 				       W83781D_DATA_REG_OFFSET);
 	}
-	if (reg & 0xff00) {
-		outb_p(W83781D_REG_BANK,
-		       data->addr + W83781D_ADDR_REG_OFFSET);
-		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
-	}
+	w83627hf_reset_bank(data, reg);
 	mutex_unlock(&data->lock);
 	return res;
 }
@@ -1309,12 +1318,7 @@ static int w83627hf_write_value(struct w
 		   || ((reg & 0xff00) == 0x200))
 		  && (((reg & 0x00ff) == 0x53)
 		   || ((reg & 0x00ff) == 0x55));
-	if (reg & 0xff00) {
-		outb_p(W83781D_REG_BANK,
-		       data->addr + W83781D_ADDR_REG_OFFSET);
-		outb_p(reg >> 8,
-		       data->addr + W83781D_DATA_REG_OFFSET);
-	}
+	w83627hf_set_bank(data, reg);
 	outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET);
 	if (word_sized) {
 		outb_p(value >> 8,
@@ -1324,11 +1328,7 @@ static int w83627hf_write_value(struct w
 	}
 	outb_p(value & 0xff,
 	       data->addr + W83781D_DATA_REG_OFFSET);
-	if (reg & 0xff00) {
-		outb_p(W83781D_REG_BANK,
-		       data->addr + W83781D_ADDR_REG_OFFSET);
-		outb_p(0, data->addr + W83781D_DATA_REG_OFFSET);
-	}
+	w83627hf_reset_bank(data, reg);
 	mutex_unlock(&data->lock);
 	return 0;
 }
author
#25 lore raw

PATCH 25/26 i915: fix vbl swap allocation size.

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Dave Airlie <[email protected]>

This is upstream as 54583bf4efda79388fc13163e35c016c8bc5de81

Oops...

---
 drivers/char/drm/i915_irq.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/char/drm/i915_irq.c +1 -1
@@ -541,7 +541,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
 		return DRM_ERR(EBUSY);
 	}
 
-	vbl_swap = drm_calloc(1, sizeof(vbl_swap), DRM_MEM_DRIVER);
+	vbl_swap = drm_calloc(1, sizeof(*vbl_swap), DRM_MEM_DRIVER);
 
 	if (!vbl_swap) {
 		DRM_ERROR("Failed to allocate memory to queue swap\n");
author
#26 lore raw

PATCH 26/26 POWERPC: Fix handling of stfiwx math emulation

In reply to Greg KH

2.6.22-stable review patch. If anyone has any objections, please let us know.

------------------
From: Kumar Gala <[email protected]>

patch ba02946a903015840ef672ccc9dc8620a7e83de6 in mainline

Its legal for the stfiwx instruction to have RA = 0 as part of its effective address calculation. This is illegal for all other XE form instructions.

Add code to compute the proper effective address for stfiwx if RA = 0 rather than treating it as illegal.

---
 arch/powerpc/math-emu/math.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
arch/powerpc/math-emu/math.c +9 -4
@@ -407,11 +407,16 @@ do_mathemu(struct pt_regs *regs)
 
 	case XE:
 		idx = (insn >> 16) & 0x1f;
-		if (!idx)
-			goto illegal;
-
 		op0 = (void *)&current->thread.fpr[(insn >> 21) & 0x1f];
-		op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]);
+		if (!idx) {
+			if (((insn >> 1) & 0x3ff) == STFIWX)
+				op1 = (void *)(regs->gpr[(insn >> 11) & 0x1f]);
+			else
+				goto illegal;
+		} else {
+			op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]);
+		}
+
 		break;
 
 	case XEU:
author
#27 lore raw
In reply to Greg KH
Quoted 5 lines · Greg KH

This is the start of the stable review cycle for the 2.6.22.11 release. There are 26 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.

Full, rolled up patch at:

	kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.22.11-rc1.gz

thanks,

greg k-h

author
#28 lore raw

[patch 27/26] lockdep: fix mismatched lockdep_depth/curr_chain_hash

In reply to Greg KH

[one more patch added to the 2.6.22-stable queue]

From: Gregory Haskins <[email protected]>

patch 3aa416b07f0adf01c090baab26fb70c35ec17623 in mainline.

lockdep: fix mismatched lockdep_depth/curr_chain_hash

It is possible for the current->curr_chain_key to become inconsistent with the current index if the chain fails to validate. The end result is that future lock_acquire() operations may inadvertently fail to find a hit in the cache resulting in a new node being added to the graph for every acquire.

[ peterz: this might explain some of the lockdep is so _slow_ complaints. ] [ mingo: this does not impact the correctness of validation, but may slow
down future operations significantly, if the chain gets very long. ]

kernel/lockdep.c +1 -1
@@ -2166,7 +2166,6 @@ out_calc_hash:
 	}
 #endif
 	chain_key = iterate_chain_key(chain_key, id);
-	curr->curr_chain_key = chain_key;
 
 	/*
 	 * Trylock needs to maintain the stack of held locks, but it
@@ -2215,6 +2214,7 @@ out_calc_hash:
 		if (unlikely(!debug_locks))
 			return 0;
 
+	curr->curr_chain_key = chain_key;
 	curr->lockdep_depth++;
 	check_chain_key(curr);
 #ifdef CONFIG_DEBUG_LOCKDEP

_______________________________________________
stable mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/stable