From 5e46882e2ecacd2ebd1bfba3caaa4a25ffbcb94d Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 28 Jan 2009 09:38:30 -0800 Subject: iwlwifi: clean key table in iwl_clear_stations_table Cleans uCode key table bit map iwl_clear_stations_table since all stations are cleared also the key table must be. Since the keys are not removed properly on suspend by mac80211 this may result in exhausting key table on resume leading to memory corruption during removal Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 412f66bac1a..70a8b21ca39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -480,6 +480,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv) priv->num_stations = 0; memset(priv->stations, 0, sizeof(priv->stations)); + /* clean ucode key table bit map */ + priv->ucode_key_table = 0; + spin_unlock_irqrestore(&priv->sta_lock, flags); } EXPORT_SYMBOL(iwl_clear_stations_table); -- cgit v1.2.3 From c4e061ace75513aee227090486cc46dec7810c00 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 3 Feb 2009 10:20:03 -0800 Subject: iwlwifi: save PCI state before suspend, restore after resume This is the right thing to do and fixes the following warning: [ 115.012278] ------------[ cut here ]------------ [ 115.012281] WARNING: at drivers/pci/pci-driver.c:370 pci_legacy_suspend+0x85/0xc2() [ 115.012285] Hardware name: Latitude D630 [ 115.012301] PCI PM: Device state not saved by iwl3945_pci_suspend+0x0/0x4c [iwl3945] [ 115.012304] Modules linked in: fuse nfsd lockd nfs_acl auth_rpcgss exportfs sunrpc ipv6 acpi_cpufreq kvm_intel kvm snd_hda_codec_idt snd_hda_intel snd_hda_codec snd_hwdep arc4 snd_seq_device snd_pcm_oss snd_mixer_oss ecb snd_pcm cryptomgr aead snd_timer crypto_blkcipher snd snd_page_alloc ohci1394 crypto_hash crypto_algapi ch341 ieee1394 usbserial thermal iwl3945 mac80211 led_class lib80211 tg3 processor i2c_i801 i2c_core sg cfg80211 libphy usbhid battery ac button sr_mod cdrom evdev dcdbas ata_generic ata_piix libata sd_mod scsi_mod ext3 jbd mbcache uhci_hcd ohci_hcd ehci_hcd usbcore [last unloaded: microcode] [ 115.012374] Pid: 4163, comm: pm-suspend Not tainted 2.6.29-rc3-00227-gf1dd849-dirty #67 [ 115.012377] Call Trace: [ 115.012382] [] warn_slowpath+0xb1/0xed [ 115.012387] [] ? _spin_unlock_irqrestore+0x5c/0x78 [ 115.012390] [] ? up+0x34/0x39 [ 115.012394] [] ? acpi_ut_release_mutex+0x5d/0x61 [ 115.012397] [] ? acpi_get_data+0x5e/0x70 [ 115.012400] [] ? acpi_bus_get_device+0x25/0x39 [ 115.012403] [] ? acpi_bus_power_manageable+0x11/0x29 [ 115.012406] [] ? acpi_pci_power_manageable+0x17/0x19 [ 115.012410] [] ? pci_set_power_state+0xcc/0x101 [ 115.012418] [] ? iwl3945_pci_suspend+0x0/0x4c [iwl3945] [ 115.012422] [] pci_legacy_suspend+0x85/0xc2 [ 115.012425] [] pci_pm_suspend+0x34/0x86 [ 115.012429] [] pm_op+0x52/0xe5 [ 115.012432] [] device_suspend+0x32a/0x451 [ 115.012436] [] suspend_devices_and_enter+0x3e/0x13a [ 115.012439] [] enter_state+0x110/0x164 [ 115.012442] [] state_store+0xb7/0xd7 [ 115.012446] [] kobj_attr_store+0x17/0x19 [ 115.012449] [] sysfs_write_file+0xe4/0x119 [ 115.012453] [] vfs_write+0xae/0x137 [ 115.012456] [] sys_write+0x47/0x70 [ 115.012459] [] system_call_fastpath+0x16/0x1b [ 115.012467] ---[ end trace 829828966f6f24dc ]--- Signed-off-by: Reinette Chatre Tested-by: Ming Lei Cc: Rafael J. Wysocki Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b35c8813bef..c01ea48da5f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4042,6 +4042,7 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) priv->is_open = 1; } + pci_save_state(pdev); pci_set_power_state(pdev, PCI_D3hot); return 0; @@ -4052,6 +4053,7 @@ static int iwl_pci_resume(struct pci_dev *pdev) struct iwl_priv *priv = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); if (priv->is_open) iwl_mac_start(priv->hw); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 95d01984c80..5b44d322b99 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -8143,6 +8143,7 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state) priv->is_open = 1; } + pci_save_state(pdev); pci_set_power_state(pdev, PCI_D3hot); return 0; @@ -8153,6 +8154,7 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) struct iwl3945_priv *priv = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); if (priv->is_open) iwl3945_mac_start(priv->hw); -- cgit v1.2.3 From 65ab8385b67854792e89267907f9fcb27e779f95 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Wed, 4 Feb 2009 16:31:39 -0800 Subject: cxgb3: Fix lro switch The LRO switch is always set to 1 in the rx processing loop. It breaks the accelerated iSCSI receive traffic. Fix its computation. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/sge.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 379a1324db4..d31791f6029 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2276,8 +2276,7 @@ no_mem: } else if ((len = ntohl(r->len_cq)) != 0) { struct sge_fl *fl; - if (eth) - lro = qs->lro_enabled && is_eth_tcp(rss_hi); + lro &= eth && is_eth_tcp(rss_hi); fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; if (fl->use_pages) { -- cgit v1.2.3 From 1fbe49328f7442090439addddf441fb5b3186e71 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 4 Feb 2009 16:37:40 -0800 Subject: gianfar: Fix BD_LENGTH_MASK definition BD_LENGTH_MASK is supposed to catch the low 16-bits of the status field, not the low byte. The old way, we would never be able to clean up tx packets with sizes divisible by 256. Signed-off-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/gianfar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index b1a83344acc..eaa86897f5c 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -312,7 +312,7 @@ extern const char gfar_driver_version[]; #define ATTRELI_EI(x) (x) #define BD_LFLAG(flags) ((flags) << 16) -#define BD_LENGTH_MASK 0x00ff +#define BD_LENGTH_MASK 0x0000ffff /* TxBD status field bits */ #define TXBD_READY 0x8000 -- cgit v1.2.3 From b98ac702f49042ab0c382b839465b95a2bd0cd65 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 4 Feb 2009 16:38:05 -0800 Subject: gianfar: Fix potential soft reset race SOFT_RESET must be asserted for at least 3 TX clocks in order for it to work properly. The syncs in the gfar_write() commands have been hiding this, but we need to guarantee it. Signed-off-by: Andy Fleming Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 3f7eab42aef..acae2d8cd68 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -351,6 +351,9 @@ static int gfar_probe(struct of_device *ofdev, /* Reset MAC layer */ gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); + /* We need to delay at least 3 TX clocks */ + udelay(2); + tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); gfar_write(&priv->regs->maccfg1, tempval); -- cgit v1.2.3 From 7b5e56f9d635643ad54f2f42e69ad16b80a2cff1 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Thu, 5 Feb 2009 15:05:45 -0800 Subject: udp: Fix UDP short packet false positive The UDP header pointer assignment must happen after calling pskb_may_pull(). As pskb_may_pull() can potentially alter the SKB buffer. This was exposted by running multicast traffic through the NIU driver, as it won't prepull the protocol headers into the linear area on receive. Signed-off-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- net/ipv4/udp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 1ab180bad72..cc3a0a06c00 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1231,7 +1231,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, int proto) { struct sock *sk; - struct udphdr *uh = udp_hdr(skb); + struct udphdr *uh; unsigned short ulen; struct rtable *rt = (struct rtable*)skb->dst; __be32 saddr = ip_hdr(skb)->saddr; @@ -1244,6 +1244,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (!pskb_may_pull(skb, sizeof(struct udphdr))) goto drop; /* No space for header. */ + uh = udp_hdr(skb); ulen = ntohs(uh->len); if (ulen > skb->len) goto short_packet; -- cgit v1.2.3 From 0178b695fd6b40a62a215cbeb03dd51ada3bb5e0 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 5 Feb 2009 15:15:50 -0800 Subject: ipv6: Copy cork options in ip6_append_data As the options passed to ip6_append_data may be ephemeral, we need to duplicate it for corking. This patch applies the simplest fix which is to memdup all the relevant bits. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 67 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4b15938bef4..9fb49c3b518 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1105,6 +1105,18 @@ static inline int ip6_ufo_append_data(struct sock *sk, return err; } +static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, + gfp_t gfp) +{ + return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; +} + +static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, + gfp_t gfp) +{ + return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; +} + int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, @@ -1130,17 +1142,37 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, * setup for corking */ if (opt) { - if (np->cork.opt == NULL) { - np->cork.opt = kmalloc(opt->tot_len, - sk->sk_allocation); - if (unlikely(np->cork.opt == NULL)) - return -ENOBUFS; - } else if (np->cork.opt->tot_len < opt->tot_len) { - printk(KERN_DEBUG "ip6_append_data: invalid option length\n"); + if (WARN_ON(np->cork.opt)) return -EINVAL; - } - memcpy(np->cork.opt, opt, opt->tot_len); - inet->cork.flags |= IPCORK_OPT; + + np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation); + if (unlikely(np->cork.opt == NULL)) + return -ENOBUFS; + + np->cork.opt->tot_len = opt->tot_len; + np->cork.opt->opt_flen = opt->opt_flen; + np->cork.opt->opt_nflen = opt->opt_nflen; + + np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt, + sk->sk_allocation); + if (opt->dst0opt && !np->cork.opt->dst0opt) + return -ENOBUFS; + + np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt, + sk->sk_allocation); + if (opt->dst1opt && !np->cork.opt->dst1opt) + return -ENOBUFS; + + np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt, + sk->sk_allocation); + if (opt->hopopt && !np->cork.opt->hopopt) + return -ENOBUFS; + + np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt, + sk->sk_allocation); + if (opt->srcrt && !np->cork.opt->srcrt) + return -ENOBUFS; + /* need source address above miyazawa*/ } dst_hold(&rt->u.dst); @@ -1167,8 +1199,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, } else { rt = (struct rt6_info *)inet->cork.dst; fl = &inet->cork.fl; - if (inet->cork.flags & IPCORK_OPT) - opt = np->cork.opt; + opt = np->cork.opt; transhdrlen = 0; exthdrlen = 0; mtu = inet->cork.fragsize; @@ -1407,9 +1438,15 @@ error: static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) { - inet->cork.flags &= ~IPCORK_OPT; - kfree(np->cork.opt); - np->cork.opt = NULL; + if (np->cork.opt) { + kfree(np->cork.opt->dst0opt); + kfree(np->cork.opt->dst1opt); + kfree(np->cork.opt->hopopt); + kfree(np->cork.opt->srcrt); + kfree(np->cork.opt); + np->cork.opt = NULL; + } + if (inet->cork.dst) { dst_release(inet->cork.dst); inet->cork.dst = NULL; -- cgit v1.2.3 From a23f4bbd8d27ac8ddc5d71ace1f91bb503f0469a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 5 Feb 2009 15:38:31 -0800 Subject: Revert "tcp: Always set urgent pointer if it's beyond snd_nxt" This reverts commit 64ff3b938ec6782e6585a83d5459b98b0c3f6eb8. Jeff Chua reports that it breaks rlogin for him. Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 557fe16cbfb..dda42f0bd7a 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -663,14 +663,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, th->urg_ptr = 0; /* The urg_mode check is necessary during a below snd_una win probe */ - if (unlikely(tcp_urg_mode(tp))) { - if (between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF)) { - th->urg_ptr = htons(tp->snd_up - tcb->seq); - th->urg = 1; - } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { - th->urg_ptr = 0xFFFF; - th->urg = 1; - } + if (unlikely(tcp_urg_mode(tp) && + between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF))) { + th->urg_ptr = htons(tp->snd_up - tcb->seq); + th->urg = 1; } tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); -- cgit v1.2.3