From 73d540f282c0d8ce48fafd7fcc844e91f31d4103 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 14 Oct 2009 20:20:42 +0000 Subject: be2net: fix promiscuous and multicast promiscuous modes being enabled always Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 8 ++++---- drivers/net/benet/be_cmds.h | 5 +++-- drivers/net/benet/be_main.c | 19 +++++++++++-------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 89876ade5e33..b57abc0c9f48 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -729,8 +729,8 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, /* Create an rx filtering policy configuration on an i/f * Uses mbox */ -int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac, - bool pmac_invalid, u32 *if_handle, u32 *pmac_id) +int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, + u8 *mac, bool pmac_invalid, u32 *if_handle, u32 *pmac_id) { struct be_mcc_wrb *wrb; struct be_cmd_req_if_create *req; @@ -746,8 +746,8 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac, be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req)); - req->capability_flags = cpu_to_le32(flags); - req->enable_flags = cpu_to_le32(flags); + req->capability_flags = cpu_to_le32(cap_flags); + req->enable_flags = cpu_to_le32(en_flags); req->pmac_invalid = pmac_invalid; if (!pmac_invalid) memcpy(req->mac_addr, mac, ETH_ALEN); diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index a86f917f85f4..49953787e41c 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -720,8 +720,9 @@ extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, u32 if_id, u32 *pmac_id); extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id); -extern int be_cmd_if_create(struct be_adapter *adapter, u32 if_flags, u8 *mac, - bool pmac_invalid, u32 *if_handle, u32 *pmac_id); +extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, + u32 en_flags, u8 *mac, bool pmac_invalid, + u32 *if_handle, u32 *pmac_id); extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle); extern int be_cmd_eq_create(struct be_adapter *adapter, struct be_queue_info *eq, int eq_delay); diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 6d5e81f7046f..36cb94869b01 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1620,19 +1620,22 @@ static int be_open(struct net_device *netdev) static int be_setup(struct be_adapter *adapter) { struct net_device *netdev = adapter->netdev; - u32 if_flags; + u32 cap_flags, en_flags; int status; - if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS | - BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED | - BE_IF_FLAGS_PASS_L3L4_ERRORS; - status = be_cmd_if_create(adapter, if_flags, netdev->dev_addr, - false/* pmac_invalid */, &adapter->if_handle, - &adapter->pmac_id); + cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MCAST_PROMISCUOUS | + BE_IF_FLAGS_PROMISCUOUS | + BE_IF_FLAGS_PASS_L3L4_ERRORS; + en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_PASS_L3L4_ERRORS; + + status = be_cmd_if_create(adapter, cap_flags, en_flags, + netdev->dev_addr, false/* pmac_invalid */, + &adapter->if_handle, &adapter->pmac_id); if (status != 0) goto do_none; - status = be_tx_queues_create(adapter); if (status != 0) goto if_destroy; -- cgit v1.2.3 From 43a04fdc369ce4fb6718b95e1c930ff8661e65c1 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 14 Oct 2009 20:21:17 +0000 Subject: be2net: fix support for PCI hot plug Before issuing any cmds to the FW, the driver must first wait till the fW becomes ready. This is needed for PCI hot plug when the driver can be probed while the card fw is being initialized. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 25 ++++++++++++++++++------- drivers/net/benet/be_main.c | 8 ++++---- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index b57abc0c9f48..28a0eda92680 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -243,15 +243,26 @@ static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage) int be_cmd_POST(struct be_adapter *adapter) { - u16 stage, error; + u16 stage; + int status, timeout = 0; - error = be_POST_stage_get(adapter, &stage); - if (error || stage != POST_STAGE_ARMFW_RDY) { - dev_err(&adapter->pdev->dev, "POST failed.\n"); - return -1; - } + do { + status = be_POST_stage_get(adapter, &stage); + if (status) { + dev_err(&adapter->pdev->dev, "POST error; stage=0x%x\n", + stage); + return -1; + } else if (stage != POST_STAGE_ARMFW_RDY) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(2 * HZ); + timeout += 2; + } else { + return 0; + } + } while (timeout < 20); - return 0; + dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage); + return -1; } static inline void *embedded_payload(struct be_mcc_wrb *wrb) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 36cb94869b01..1f941f027718 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2058,6 +2058,10 @@ static int be_hw_up(struct be_adapter *adapter) if (status) return status; + status = be_cmd_reset_function(adapter); + if (status) + return status; + status = be_cmd_get_fw_ver(adapter, adapter->fw_ver); if (status) return status; @@ -2111,10 +2115,6 @@ static int __devinit be_probe(struct pci_dev *pdev, if (status) goto free_netdev; - status = be_cmd_reset_function(adapter); - if (status) - goto ctrl_clean; - status = be_stats_init(adapter); if (status) goto ctrl_clean; -- cgit v1.2.3 From ed79bab847d8e5a2986d8ff43c49c6fb8ee3265f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 14 Oct 2009 14:36:43 +0000 Subject: virtio_net: use dev_kfree_skb_any() in free_old_xmit_skbs() Because netpoll can call netdevice start_xmit() method with irqs disabled, drivers should not call kfree_skb() from their start_xmit(), but use dev_kfree_skb_any() instead. Oct 8 11:16:52 172.30.1.31 [113074.791813] ------------[ cut here ]------------ Oct 8 11:16:52 172.30.1.31 [113074.791813] WARNING: at net/core/skbuff.c:398 \ skb_release_head_state+0x64/0xc8() Oct 8 11:16:52 172.30.1.31 [113074.791813] Hardware name: Oct 8 11:16:52 172.30.1.31 [113074.791813] Modules linked in: netconsole ocfs2 jbd2 quota_tree \ ocfs2_dlmfs ocfs2_stack_o2cb ocfs2_dlm ocfs2_nodemanager ocfs2_stackglue configfs crc32c drbd cn loop \ serio_raw psmouse snd_pcm snd_timer snd soundcore snd_page_alloc virtio_net pcspkr parport_pc parport \ i2c_piix4 i2c_core button processor evdev ext3 jbd mbcache dm_mirror dm_region_hash dm_log dm_snapshot \ dm_mod ide_cd_mod cdrom ata_generic ata_piix virtio_blk libata scsi_mod piix ide_pci_generic ide_core \ virtio_pci virtio_ring virtio floppy thermal fan thermal_sys [last unloaded: netconsole] Oct 8 11:16:52 172.30.1.31 [113074.791813] Pid: 11132, comm: php5-cgi Tainted: G W \ 2.6.31.2-vserver #1 Oct 8 11:16:52 172.30.1.31 [113074.791813] Call Trace: Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? \ skb_release_head_state+0x64/0xc8 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? skb_release_head_state+0x64/0xc8 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? warn_slowpath_common+0x77/0xa3 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? skb_release_head_state+0x64/0xc8 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? __kfree_skb+0x9/0x7d Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? free_old_xmit_skbs+0x51/0x6e \ [virtio_net] Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? start_xmit+0x26/0xf2 [virtio_net] Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? netpoll_send_skb+0xd2/0x205 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? write_msg+0x90/0xeb [netconsole] Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? __call_console_drivers+0x5e/0x6f Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? kvm_clock_read+0x4d/0x52 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? release_console_sem+0x115/0x1ba Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? vprintk+0x2f2/0x34b Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? vx_update_load+0x18/0x13e Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? printk+0x4e/0x5d Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? kvm_clock_read+0x4d/0x52 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? getnstimeofday+0x55/0xaf Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? ktime_get_ts+0x21/0x49 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? ktime_get+0xc/0x41 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? hrtimer_interrupt+0x9c/0x146 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? smp_apic_timer_interrupt+0x80/0x93 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? apic_timer_interrupt+0x13/0x20 Oct 8 11:16:52 172.30.1.31 [113074.791813] [] ? _spin_unlock_irq+0xd/0x31 Reported-and-tested-by: Massimo Cetra Signed-off-by: Eric Dumazet Bug-Entry: http://bugzilla.kernel.org/show_bug.cgi?id=14378 Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 8d009760277c..54bf0912b737 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -454,7 +454,7 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) vi->dev->stats.tx_bytes += skb->len; vi->dev->stats.tx_packets++; tot_sgs += skb_vnet_hdr(skb)->num_sg; - kfree_skb(skb); + dev_kfree_skb_any(skb); } return tot_sgs; } -- cgit v1.2.3 From f6965582ac9b87d875aac8e23afdb03fe35ee33d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 16 Oct 2009 17:54:34 -0700 Subject: vmxnet3: use dev_dbg, fix build for CONFIG_BLOCK=n vmxnet3 was using dprintk() for debugging output. This was defined in and was the only thing that was used from that header file. This caused compile errors when CONFIG_BLOCK was not enabled due to bio* and BIO* uses in the header file, so change this driver to use dev_dbg() for debugging output. include/linux/dst.h:520: error: dereferencing pointer to incomplete type include/linux/dst.h:520: error: 'BIO_POOL_BITS' undeclared (first use in this function) include/linux/dst.h:521: error: dereferencing pointer to incomplete type include/linux/dst.h:522: error: dereferencing pointer to incomplete type include/linux/dst.h:525: error: dereferencing pointer to incomplete type make[4]: *** [drivers/net/vmxnet3/vmxnet3_drv.o] Error 1 Signed-off-by: Randy Dunlap Signed-off-by: Bhavesh Davda Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_drv.c | 27 ++++++++++++++++++--------- drivers/net/vmxnet3/vmxnet3_int.h | 2 +- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 6a16f76f277e..004353a46af0 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -481,7 +481,8 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx, } rq->uncommitted[ring_idx] += num_allocated; - dprintk(KERN_ERR "alloc_rx_buf: %d allocated, next2fill %u, next2comp " + dev_dbg(&adapter->netdev->dev, + "alloc_rx_buf: %d allocated, next2fill %u, next2comp " "%u, uncommited %u\n", num_allocated, ring->next2fill, ring->next2comp, rq->uncommitted[ring_idx]); @@ -539,7 +540,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, tbi = tq->buf_info + tq->tx_ring.next2fill; tbi->map_type = VMXNET3_MAP_NONE; - dprintk(KERN_ERR "txd[%u]: 0x%Lx 0x%x 0x%x\n", + dev_dbg(&adapter->netdev->dev, + "txd[%u]: 0x%Lx 0x%x 0x%x\n", tq->tx_ring.next2fill, ctx->sop_txd->txd.addr, ctx->sop_txd->dword[2], ctx->sop_txd->dword[3]); vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); @@ -572,7 +574,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, gdesc->dword[2] = dw2 | buf_size; gdesc->dword[3] = 0; - dprintk(KERN_ERR "txd[%u]: 0x%Lx 0x%x 0x%x\n", + dev_dbg(&adapter->netdev->dev, + "txd[%u]: 0x%Lx 0x%x 0x%x\n", tq->tx_ring.next2fill, gdesc->txd.addr, gdesc->dword[2], gdesc->dword[3]); vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); @@ -600,7 +603,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, gdesc->dword[2] = dw2 | frag->size; gdesc->dword[3] = 0; - dprintk(KERN_ERR "txd[%u]: 0x%llu %u %u\n", + dev_dbg(&adapter->netdev->dev, + "txd[%u]: 0x%llu %u %u\n", tq->tx_ring.next2fill, gdesc->txd.addr, gdesc->dword[2], gdesc->dword[3]); vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); @@ -697,7 +701,8 @@ vmxnet3_parse_and_copy_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, tdd = tq->data_ring.base + tq->tx_ring.next2fill; memcpy(tdd->data, skb->data, ctx->copy_size); - dprintk(KERN_ERR "copy %u bytes to dataRing[%u]\n", + dev_dbg(&adapter->netdev->dev, + "copy %u bytes to dataRing[%u]\n", ctx->copy_size, tq->tx_ring.next2fill); return 1; @@ -808,7 +813,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) { tq->stats.tx_ring_full++; - dprintk(KERN_ERR "tx queue stopped on %s, next2comp %u" + dev_dbg(&adapter->netdev->dev, + "tx queue stopped on %s, next2comp %u" " next2fill %u\n", adapter->netdev->name, tq->tx_ring.next2comp, tq->tx_ring.next2fill); @@ -853,7 +859,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, /* finally flips the GEN bit of the SOP desc */ gdesc->dword[2] ^= VMXNET3_TXD_GEN; - dprintk(KERN_ERR "txd[%u]: SOP 0x%Lx 0x%x 0x%x\n", + dev_dbg(&adapter->netdev->dev, + "txd[%u]: SOP 0x%Lx 0x%x 0x%x\n", (u32)((union Vmxnet3_GenericDesc *)ctx.sop_txd - tq->tx_ring.base), gdesc->txd.addr, gdesc->dword[2], gdesc->dword[3]); @@ -990,7 +997,8 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, if (unlikely(rcd->len == 0)) { /* Pretend the rx buffer is skipped. */ BUG_ON(!(rcd->sop && rcd->eop)); - dprintk(KERN_ERR "rxRing[%u][%u] 0 length\n", + dev_dbg(&adapter->netdev->dev, + "rxRing[%u][%u] 0 length\n", ring_idx, idx); goto rcd_done; } @@ -1683,7 +1691,8 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter) int err; u32 ret; - dprintk(KERN_ERR "%s: skb_buf_size %d, rx_buf_per_pkt %d, ring sizes" + dev_dbg(&adapter->netdev->dev, + "%s: skb_buf_size %d, rx_buf_per_pkt %d, ring sizes" " %u %u %u\n", adapter->netdev->name, adapter->skb_buf_size, adapter->rx_buf_per_pkt, adapter->tx_queue.tx_ring.size, adapter->rx_queue.rx_ring[0].size, diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 6bb91576e999..3c0d70d58111 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -59,7 +60,6 @@ #include #include #include -#include #include "vmxnet3_defs.h" -- cgit v1.2.3 From 16dd18b0837dee46f1a6b0c01830c5f2b7187266 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Wed, 7 Oct 2009 14:16:42 +0000 Subject: ethoc: inline regs access Signed-off-by: Thomas Chou Signed-off-by: David S. Miller --- drivers/net/ethoc.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 1d338c6f5314..88a1c5223069 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -222,24 +222,25 @@ struct ethoc_bd { u32 addr; }; -static u32 ethoc_read(struct ethoc *dev, loff_t offset) +static inline u32 ethoc_read(struct ethoc *dev, loff_t offset) { return ioread32(dev->iobase + offset); } -static void ethoc_write(struct ethoc *dev, loff_t offset, u32 data) +static inline void ethoc_write(struct ethoc *dev, loff_t offset, u32 data) { iowrite32(data, dev->iobase + offset); } -static void ethoc_read_bd(struct ethoc *dev, int index, struct ethoc_bd *bd) +static inline void ethoc_read_bd(struct ethoc *dev, int index, + struct ethoc_bd *bd) { loff_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd)); bd->stat = ethoc_read(dev, offset + 0); bd->addr = ethoc_read(dev, offset + 4); } -static void ethoc_write_bd(struct ethoc *dev, int index, +static inline void ethoc_write_bd(struct ethoc *dev, int index, const struct ethoc_bd *bd) { loff_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd)); @@ -247,33 +248,33 @@ static void ethoc_write_bd(struct ethoc *dev, int index, ethoc_write(dev, offset + 4, bd->addr); } -static void ethoc_enable_irq(struct ethoc *dev, u32 mask) +static inline void ethoc_enable_irq(struct ethoc *dev, u32 mask) { u32 imask = ethoc_read(dev, INT_MASK); imask |= mask; ethoc_write(dev, INT_MASK, imask); } -static void ethoc_disable_irq(struct ethoc *dev, u32 mask) +static inline void ethoc_disable_irq(struct ethoc *dev, u32 mask) { u32 imask = ethoc_read(dev, INT_MASK); imask &= ~mask; ethoc_write(dev, INT_MASK, imask); } -static void ethoc_ack_irq(struct ethoc *dev, u32 mask) +static inline void ethoc_ack_irq(struct ethoc *dev, u32 mask) { ethoc_write(dev, INT_SOURCE, mask); } -static void ethoc_enable_rx_and_tx(struct ethoc *dev) +static inline void ethoc_enable_rx_and_tx(struct ethoc *dev) { u32 mode = ethoc_read(dev, MODER); mode |= MODER_RXEN | MODER_TXEN; ethoc_write(dev, MODER, mode); } -static void ethoc_disable_rx_and_tx(struct ethoc *dev) +static inline void ethoc_disable_rx_and_tx(struct ethoc *dev) { u32 mode = ethoc_read(dev, MODER); mode &= ~(MODER_RXEN | MODER_TXEN); -- cgit v1.2.3 From 50c54a57dfbd392e17f1473717b8e125afcb01a3 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Wed, 7 Oct 2009 14:16:43 +0000 Subject: ethoc: clear only pending irqs This patch fixed the problem of dropped packets due to lost of interrupt requests. We should only clear what was pending at the moment we read the irq source reg. Signed-off-by: Thomas Chou Signed-off-by: David S. Miller --- drivers/net/ethoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 88a1c5223069..590473afb3dc 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -508,7 +508,7 @@ static irqreturn_t ethoc_interrupt(int irq, void *dev_id) return IRQ_NONE; } - ethoc_ack_irq(priv, INT_MASK_ALL); + ethoc_ack_irq(priv, pending); if (pending & INT_MASK_BUSY) { dev_err(&dev->dev, "packet dropped\n"); -- cgit v1.2.3 From 77238f2b942b38ab4e7f3aced44084493e4a8675 Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Sun, 18 Oct 2009 23:17:37 -0700 Subject: AF_UNIX: Fix deadlock on connecting to shutdown socket I found a deadlock bug in UNIX domain socket, which makes able to DoS attack against the local machine by non-root users. How to reproduce: 1. Make a listening AF_UNIX/SOCK_STREAM socket with an abstruct namespace(*), and shutdown(2) it. 2. Repeat connect(2)ing to the listening socket from the other sockets until the connection backlog is full-filled. 3. connect(2) takes the CPU forever. If every core is taken, the system hangs. PoC code: (Run as many times as cores on SMP machines.) int main(void) { int ret; int csd; int lsd; struct sockaddr_un sun; /* make an abstruct name address (*) */ memset(&sun, 0, sizeof(sun)); sun.sun_family = PF_UNIX; sprintf(&sun.sun_path[1], "%d", getpid()); /* create the listening socket and shutdown */ lsd = socket(AF_UNIX, SOCK_STREAM, 0); bind(lsd, (struct sockaddr *)&sun, sizeof(sun)); listen(lsd, 1); shutdown(lsd, SHUT_RDWR); /* connect loop */ alarm(15); /* forcely exit the loop after 15 sec */ for (;;) { csd = socket(AF_UNIX, SOCK_STREAM, 0); ret = connect(csd, (struct sockaddr *)&sun, sizeof(sun)); if (-1 == ret) { perror("connect()"); break; } puts("Connection OK"); } return 0; } (*) Make sun_path[0] = 0 to use the abstruct namespace. If a file-based socket is used, the system doesn't deadlock because of context switches in the file system layer. Why this happens: Error checks between unix_socket_connect() and unix_wait_for_peer() are inconsistent. The former calls the latter to wait until the backlog is processed. Despite the latter returns without doing anything when the socket is shutdown, the former doesn't check the shutdown state and just retries calling the latter forever. Patch: The patch below adds shutdown check into unix_socket_connect(), so connect(2) to the shutdown socket will return -ECONREFUSED. Signed-off-by: Tomoki Sekiyama Signed-off-by: Masanori Yoshida Signed-off-by: David S. Miller --- net/unix/af_unix.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 51ab497115eb..fc820cd75453 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1074,6 +1074,8 @@ restart: err = -ECONNREFUSED; if (other->sk_state != TCP_LISTEN) goto out_unlock; + if (other->sk_shutdown & RCV_SHUTDOWN) + goto out_unlock; if (unix_recvq_full(other)) { err = -EAGAIN; -- cgit v1.2.3 From a1a2ad9151c26d92e5c733a33d52108f5d3a5b57 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 19 Oct 2009 19:12:36 -0700 Subject: Revert "tcp: fix tcp_defer_accept to consider the timeout" This reverts commit 6d01a026b7d3009a418326bdcf313503a314f1ea. Julian Anastasov, Willy Tarreau and Eric Dumazet have come up with a more correct way to deal with this. Signed-off-by: David S. Miller --- net/ipv4/tcp_minisocks.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index e320afea07fc..624c3c9b3c2b 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -644,7 +644,6 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */ if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { - inet_csk(sk)->icsk_accept_queue.rskq_defer_accept--; inet_rsk(req)->acked = 1; return NULL; } -- cgit v1.2.3 From d1b99ba41d6c5aa1ed2fc634323449dd656899e9 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 19 Oct 2009 10:01:56 +0000 Subject: tcp: accept socket after TCP_DEFER_ACCEPT period Willy Tarreau and many other folks in recent years were concerned what happens when the TCP_DEFER_ACCEPT period expires for clients which sent ACK packet. They prefer clients that actively resend ACK on our SYN-ACK retransmissions to be converted from open requests to sockets and queued to the listener for accepting after the deferring period is finished. Then application server can decide to wait longer for data or to properly terminate the connection with FIN if read() returns EAGAIN which is an indication for accepting after the deferring period. This change still can have side effects for applications that expect always to see data on the accepted socket. Others can be prepared to work in both modes (with or without TCP_DEFER_ACCEPT period) and their data processing can ignore the read=EAGAIN notification and to allocate resources for clients which proved to have no data to send during the deferring period. OTOH, servers that use TCP_DEFER_ACCEPT=1 as flag (not as a timeout) to wait for data will notice clients that didn't send data for 3 seconds but that still resend ACKs. Thanks to Willy Tarreau for the initial idea and to Eric Dumazet for the review and testing the change. Signed-off-by: Julian Anastasov Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_minisocks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 624c3c9b3c2b..4c03598ed924 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -641,8 +641,8 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, if (!(flg & TCP_FLAG_ACK)) return NULL; - /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */ - if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && + /* While TCP_DEFER_ACCEPT is active, drop bare ACK. */ + if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { inet_rsk(req)->acked = 1; return NULL; -- cgit v1.2.3 From 0c3d79bce48034018e840468ac5a642894a521a3 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 19 Oct 2009 10:03:58 +0000 Subject: tcp: reduce SYN-ACK retrans for TCP_DEFER_ACCEPT Change SYN-ACK retransmitting code for the TCP_DEFER_ACCEPT users to not retransmit SYN-ACKs during the deferring period if ACK from client was received. The goal is to reduce traffic during the deferring period. When the period is finished we continue with sending SYN-ACKs (at least one) but this time any traffic from client will change the request to established socket allowing application to terminate it properly. Also, do not drop acked request if sending of SYN-ACK fails. Signed-off-by: Julian Anastasov Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 4351ca2cf0b8..537731b3bcb3 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -446,6 +446,28 @@ extern int sysctl_tcp_synack_retries; EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_hash_add); +/* Decide when to expire the request and when to resend SYN-ACK */ +static inline void syn_ack_recalc(struct request_sock *req, const int thresh, + const int max_retries, + const u8 rskq_defer_accept, + int *expire, int *resend) +{ + if (!rskq_defer_accept) { + *expire = req->retrans >= thresh; + *resend = 1; + return; + } + *expire = req->retrans >= thresh && + (!inet_rsk(req)->acked || req->retrans >= max_retries); + /* + * Do not resend while waiting for data after ACK, + * start to resend on end of deferring period to give + * last chance for data or ACK to create established socket. + */ + *resend = !inet_rsk(req)->acked || + req->retrans >= rskq_defer_accept - 1; +} + void inet_csk_reqsk_queue_prune(struct sock *parent, const unsigned long interval, const unsigned long timeout, @@ -501,9 +523,15 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, reqp=&lopt->syn_table[i]; while ((req = *reqp) != NULL) { if (time_after_eq(now, req->expires)) { - if ((req->retrans < thresh || - (inet_rsk(req)->acked && req->retrans < max_retries)) - && !req->rsk_ops->rtx_syn_ack(parent, req)) { + int expire = 0, resend = 0; + + syn_ack_recalc(req, thresh, max_retries, + queue->rskq_defer_accept, + &expire, &resend); + if (!expire && + (!resend || + !req->rsk_ops->rtx_syn_ack(parent, req) || + inet_rsk(req)->acked)) { unsigned long timeo; if (req->retrans++ == 0) -- cgit v1.2.3 From b103cf34382f26ff48a87931b83f13b177b47c1a Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 19 Oct 2009 10:10:40 +0000 Subject: tcp: fix TCP_DEFER_ACCEPT retrans calculation Fix TCP_DEFER_ACCEPT conversion between seconds and retransmission to match the TCP SYN-ACK retransmission periods because the time is converted to such retransmissions. The old algorithm selects one more retransmission in some cases. Allow up to 255 retransmissions. Signed-off-by: Julian Anastasov Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 55 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 64d0af675823..9b2756fbdf9b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -326,6 +326,43 @@ void tcp_enter_memory_pressure(struct sock *sk) EXPORT_SYMBOL(tcp_enter_memory_pressure); +/* Convert seconds to retransmits based on initial and max timeout */ +static u8 secs_to_retrans(int seconds, int timeout, int rto_max) +{ + u8 res = 0; + + if (seconds > 0) { + int period = timeout; + + res = 1; + while (seconds > period && res < 255) { + res++; + timeout <<= 1; + if (timeout > rto_max) + timeout = rto_max; + period += timeout; + } + } + return res; +} + +/* Convert retransmits to seconds based on initial and max timeout */ +static int retrans_to_secs(u8 retrans, int timeout, int rto_max) +{ + int period = 0; + + if (retrans > 0) { + period = timeout; + while (--retrans) { + timeout <<= 1; + if (timeout > rto_max) + timeout = rto_max; + period += timeout; + } + } + return period; +} + /* * Wait for a TCP event. * @@ -2163,16 +2200,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level, break; case TCP_DEFER_ACCEPT: - icsk->icsk_accept_queue.rskq_defer_accept = 0; - if (val > 0) { - /* Translate value in seconds to number of - * retransmits */ - while (icsk->icsk_accept_queue.rskq_defer_accept < 32 && - val > ((TCP_TIMEOUT_INIT / HZ) << - icsk->icsk_accept_queue.rskq_defer_accept)) - icsk->icsk_accept_queue.rskq_defer_accept++; - icsk->icsk_accept_queue.rskq_defer_accept++; - } + /* Translate value in seconds to number of retransmits */ + icsk->icsk_accept_queue.rskq_defer_accept = + secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ, + TCP_RTO_MAX / HZ); break; case TCP_WINDOW_CLAMP: @@ -2353,8 +2384,8 @@ static int do_tcp_getsockopt(struct sock *sk, int level, val = (val ? : sysctl_tcp_fin_timeout) / HZ; break; case TCP_DEFER_ACCEPT: - val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 : - ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1)); + val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept, + TCP_TIMEOUT_INIT / HZ, TCP_RTO_MAX / HZ); break; case TCP_WINDOW_CLAMP: val = tp->window_clamp; -- cgit v1.2.3 From f74c77cb1124a11acf69c98d10c0fdc22f322664 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Sun, 18 Oct 2009 20:24:41 +0000 Subject: bluetooth: scheduling while atomic bug fix Due to driver core changes dev_set_drvdata will call kzalloc which should be in might_sleep context, but hci_conn_add will be called in atomic context Like dev_set_name move dev_set_drvdata to work queue function. oops as following: Oct 2 17:41:59 darkstar kernel: [ 438.001341] BUG: sleeping function called from invalid context at mm/slqb.c:1546 Oct 2 17:41:59 darkstar kernel: [ 438.001345] in_atomic(): 1, irqs_disabled(): 0, pid: 2133, name: sdptool Oct 2 17:41:59 darkstar kernel: [ 438.001348] 2 locks held by sdptool/2133: Oct 2 17:41:59 darkstar kernel: [ 438.001350] #0: (sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP){+.+.+.}, at: [] lock_sock+0xa/0xc [l2cap] Oct 2 17:41:59 darkstar kernel: [ 438.001360] #1: (&hdev->lock){+.-.+.}, at: [] l2cap_sock_connect+0x103/0x26b [l2cap] Oct 2 17:41:59 darkstar kernel: [ 438.001371] Pid: 2133, comm: sdptool Not tainted 2.6.31-mm1 #2 Oct 2 17:41:59 darkstar kernel: [ 438.001373] Call Trace: Oct 2 17:41:59 darkstar kernel: [ 438.001381] [] __might_sleep+0xde/0xe5 Oct 2 17:41:59 darkstar kernel: [ 438.001386] [] __kmalloc+0x4a/0x15a Oct 2 17:41:59 darkstar kernel: [ 438.001392] [] ? kzalloc+0xb/0xd Oct 2 17:41:59 darkstar kernel: [ 438.001396] [] kzalloc+0xb/0xd Oct 2 17:41:59 darkstar kernel: [ 438.001400] [] device_private_init+0x15/0x3d Oct 2 17:41:59 darkstar kernel: [ 438.001405] [] dev_set_drvdata+0x18/0x26 Oct 2 17:41:59 darkstar kernel: [ 438.001414] [] hci_conn_init_sysfs+0x40/0xd9 [bluetooth] Oct 2 17:41:59 darkstar kernel: [ 438.001422] [] ? hci_conn_add+0x128/0x186 [bluetooth] Oct 2 17:41:59 darkstar kernel: [ 438.001429] [] hci_conn_add+0x177/0x186 [bluetooth] Oct 2 17:41:59 darkstar kernel: [ 438.001437] [] hci_connect+0x3c/0xfb [bluetooth] Oct 2 17:41:59 darkstar kernel: [ 438.001442] [] l2cap_sock_connect+0x174/0x26b [l2cap] Oct 2 17:41:59 darkstar kernel: [ 438.001448] [] sys_connect+0x60/0x7a Oct 2 17:41:59 darkstar kernel: [ 438.001453] [] ? lock_release_non_nested+0x84/0x1de Oct 2 17:41:59 darkstar kernel: [ 438.001458] [] ? might_fault+0x47/0x81 Oct 2 17:41:59 darkstar kernel: [ 438.001462] [] ? might_fault+0x47/0x81 Oct 2 17:41:59 darkstar kernel: [ 438.001468] [] ? __copy_from_user_ll+0x11/0xce Oct 2 17:41:59 darkstar kernel: [ 438.001472] [] sys_socketcall+0x82/0x17b Oct 2 17:41:59 darkstar kernel: [ 438.001477] [] syscall_call+0x7/0xb Signed-off-by: Dave Young Signed-off-by: David S. Miller --- net/bluetooth/hci_sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 7f939ce29801..2bc6f6a8de68 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -92,6 +92,8 @@ static void add_conn(struct work_struct *work) dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); + dev_set_drvdata(&conn->dev, conn); + if (device_add(&conn->dev) < 0) { BT_ERR("Failed to register connection device"); return; @@ -144,8 +146,6 @@ void hci_conn_init_sysfs(struct hci_conn *conn) conn->dev.class = bt_class; conn->dev.parent = &hdev->dev; - dev_set_drvdata(&conn->dev, conn); - device_initialize(&conn->dev); INIT_WORK(&conn->work_add, add_conn); -- cgit v1.2.3 From 45054dc1bf2367ccb0e7c0486037907cd9395f8b Mon Sep 17 00:00:00 2001 From: Dave Young Date: Sun, 18 Oct 2009 20:28:30 +0000 Subject: bluetooth: static lock key fix When shutdown ppp connection, lockdep waring about non-static key will happen, it is caused by the lock is not initialized properly at that time. Fix with tuning the lock/skb_queue_head init order [ 94.339261] INFO: trying to register non-static key. [ 94.342509] the code is fine but needs lockdep annotation. [ 94.342509] turning off the locking correctness validator. [ 94.342509] Pid: 0, comm: swapper Not tainted 2.6.31-mm1 #2 [ 94.342509] Call Trace: [ 94.342509] [] register_lock_class+0x58/0x241 [ 94.342509] [] ? __lock_acquire+0xb57/0xb73 [ 94.342509] [] __lock_acquire+0xac/0xb73 [ 94.342509] [] ? lock_release_non_nested+0x17b/0x1de [ 94.342509] [] lock_acquire+0x67/0x84 [ 94.342509] [] ? skb_dequeue+0x15/0x41 [ 94.342509] [] _spin_lock_irqsave+0x2f/0x3f [ 94.342509] [] ? skb_dequeue+0x15/0x41 [ 94.342509] [] skb_dequeue+0x15/0x41 [ 94.342509] [] ? _read_unlock+0x1d/0x20 [ 94.342509] [] skb_queue_purge+0x14/0x1b [ 94.342509] [] l2cap_recv_frame+0xea1/0x115a [l2cap] [ 94.342509] [] ? __lock_acquire+0xb57/0xb73 [ 94.342509] [] ? mark_lock+0x1e/0x1c7 [ 94.342509] [] ? hci_rx_task+0xd2/0x1bc [bluetooth] [ 94.342509] [] l2cap_recv_acldata+0xb1/0x1c6 [l2cap] [ 94.342509] [] hci_rx_task+0x106/0x1bc [bluetooth] [ 94.342509] [] ? l2cap_recv_acldata+0x0/0x1c6 [l2cap] [ 94.342509] [] tasklet_action+0x69/0xc1 [ 94.342509] [] __do_softirq+0x94/0x11e [ 94.342509] [] do_softirq+0x36/0x5a [ 94.342509] [] irq_exit+0x35/0x68 [ 94.342509] [] do_IRQ+0x72/0x89 [ 94.342509] [] common_interrupt+0x2e/0x34 [ 94.342509] [] ? pm_qos_add_requirement+0x63/0x9d [ 94.342509] [] ? acpi_idle_enter_bm+0x209/0x238 [ 94.342509] [] cpuidle_idle_call+0x5c/0x94 [ 94.342509] [] cpu_idle+0x4e/0x6f [ 94.342509] [] rest_init+0x53/0x55 [ 94.342509] [] start_kernel+0x2f0/0x2f5 [ 94.342509] [] i386_start_kernel+0x91/0x96 Reported-by: Oliver Hartkopp Signed-off-by: Dave Young Tested-by: Oliver Hartkopp Signed-off-by: David S. Miller --- net/bluetooth/l2cap.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 555d9da1869b..77e9fb130adb 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -555,12 +555,12 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) conn->feat_mask = 0; - setup_timer(&conn->info_timer, l2cap_info_timeout, - (unsigned long) conn); - spin_lock_init(&conn->lock); rwlock_init(&conn->chan_list.lock); + setup_timer(&conn->info_timer, l2cap_info_timeout, + (unsigned long) conn); + conn->disc_reason = 0x13; return conn; @@ -783,6 +783,9 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) /* Default config options */ pi->conf_len = 0; pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; + skb_queue_head_init(TX_QUEUE(sk)); + skb_queue_head_init(SREJ_QUEUE(sk)); + INIT_LIST_HEAD(SREJ_LIST(sk)); } static struct proto l2cap_proto = { -- cgit v1.2.3 From 55b8050353c4a212c94d7156e2bd5885225b869b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 19 Oct 2009 06:41:58 +0000 Subject: net: Fix IP_MULTICAST_IF ipv4/ipv6 setsockopt(IP_MULTICAST_IF) have dubious __dev_get_by_index() calls. This function should be called only with RTNL or dev_base_lock held, or reader could see a corrupt hash chain and eventually enter an endless loop. Fix is to call dev_get_by_index()/dev_put(). If this happens to be performance critical, we could define a new dev_exist_by_index() function to avoid touching dev refcount. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ip_sockglue.c | 7 +++---- net/ipv6/ipv6_sockglue.c | 6 +++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 0c0b6e363a20..e982b5c1ee17 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -634,17 +634,16 @@ static int do_ip_setsockopt(struct sock *sk, int level, break; } dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr); - if (dev) { + if (dev) mreq.imr_ifindex = dev->ifindex; - dev_put(dev); - } } else - dev = __dev_get_by_index(sock_net(sk), mreq.imr_ifindex); + dev = dev_get_by_index(sock_net(sk), mreq.imr_ifindex); err = -EADDRNOTAVAIL; if (!dev) break; + dev_put(dev); err = -EINVAL; if (sk->sk_bound_dev_if && diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 14f54eb5a7fc..4f7aaf6996a3 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -496,13 +496,17 @@ done: goto e_inval; if (val) { + struct net_device *dev; + if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) goto e_inval; - if (__dev_get_by_index(net, val) == NULL) { + dev = dev_get_by_index(net, val); + if (!dev) { retv = -ENODEV; break; } + dev_put(dev); } np->mcast_oif = val; retv = 0; -- cgit v1.2.3 From b6b39e8f3fbbb31001b836afec87bcaf4811a7bf Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 19 Oct 2009 19:41:06 +0000 Subject: tcp: Try to catch MSG_PEEK bug This patch tries to print out more information when we hit the MSG_PEEK bug in tcp_recvmsg. It's been around since at least 2005 and it's about time that we finally fix it. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 9b2756fbdf9b..90b2e0649bfb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1442,7 +1442,9 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto found_ok_skb; if (tcp_hdr(skb)->fin) goto found_fin_ok; - WARN_ON(!(flags & MSG_PEEK)); + if (WARN_ON(!(flags & MSG_PEEK))) + printk(KERN_INFO "recvmsg bug 2: copied %X " + "seq %X\n", *seq, TCP_SKB_CB(skb)->seq); } /* Well, if we have backlog, try to process it now yet. */ -- cgit v1.2.3 From abf90cca9725bd05362fb3443ad55071a69a12d9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 18 Oct 2009 22:48:51 +0000 Subject: net: Fix struct inet_timewait_sock bitfield annotation commit 9e337b0f (net: annotate inet_timewait_sock bitfields) added 4/8 bytes in struct inet_timewait_sock. Fix this by declaring tw_ipv6_offset in the 'flags' bitfield The 14 bits hole is named tw_pad to make it cleary apparent. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/inet_timewait_sock.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index b63b80fac567..f93ad90a601b 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -130,11 +130,11 @@ struct inet_timewait_sock { __u16 tw_num; kmemcheck_bitfield_begin(flags); /* And these are ours. */ - __u8 tw_ipv6only:1, - tw_transparent:1; - /* 14 bits hole, try to pack */ + unsigned int tw_ipv6only : 1, + tw_transparent : 1, + tw_pad : 14, /* 14 bits hole */ + tw_ipv6_offset : 16; kmemcheck_bitfield_end(flags); - __u16 tw_ipv6_offset; unsigned long tw_ttd; struct inet_bind_bucket *tw_tb; struct hlist_node tw_death_node; -- cgit v1.2.3 From 78abcb13dd573f80d76d12007b36200a86f1e494 Mon Sep 17 00:00:00 2001 From: Steven King Date: Tue, 20 Oct 2009 18:51:37 -0700 Subject: net: fix section mismatch in fec.c fec_enet_init is called by both fec_probe and fec_resume, so it shouldn't be marked as __init. Signed-off-by: Steven King Signed-off-by: David S. Miller --- drivers/net/fec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 29234380e6c6..16a1d58419d9 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1654,7 +1654,7 @@ static const struct net_device_ops fec_netdev_ops = { * * index is only used in legacy code */ -int __init fec_enet_init(struct net_device *dev, int index) +static int fec_enet_init(struct net_device *dev, int index) { struct fec_enet_private *fep = netdev_priv(dev); struct bufdesc *cbd_base; -- cgit v1.2.3 From 57dada6819160eb08f2945fb847045f173d3218d Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 19 Oct 2009 23:49:03 +0000 Subject: KS8851: Add soft reset at probe time Issue a full soft reset at probe time. This was reported by Doong Ping of Micrel, but no explanation of why this is necessary or what bug it is fixing. Add it as it does not seem to hurt the current driver and ensures that the device is in a known state when we start setting it up. Signed-off-by: Ben Dooks Signed-off-by: David S. Miller --- drivers/net/ks8851.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 237835864357..18b17a1deb11 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -1239,6 +1239,9 @@ static int __devinit ks8851_probe(struct spi_device *spi) ndev->netdev_ops = &ks8851_netdev_ops; ndev->irq = spi->irq; + /* issue a global soft reset to reset the device. */ + ks8851_soft_reset(ks, GRR_GSR); + /* simple check for a valid chip being connected to the bus */ if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) { -- cgit v1.2.3 From 160d0fadaf7ce20e5bad26c8a955504b93c6a5ba Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 19 Oct 2009 23:49:04 +0000 Subject: KS8851: Fix MAC address write order The MAC address register was being written in the wrong order, so add a new address macro to convert mac-address byte to register address and a ks8851_wrreg8() function to write each byte without having to worry about any difficult byte swapping. Fixes a bug reported by Doong, Ping of Micrel. Signed-off-by: Ben Dooks Signed-off-by: David S. Miller --- drivers/net/ks8851.c | 37 +++++++++++++++++++++++++++++++++---- drivers/net/ks8851.h | 1 + 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 18b17a1deb11..29fa19a076bd 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -170,6 +170,36 @@ static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val) ks_err(ks, "spi_sync() failed\n"); } +/** + * ks8851_wrreg8 - write 8bit register value to chip + * @ks: The chip state + * @reg: The register address + * @val: The value to write + * + * Issue a write to put the value @val into the register specified in @reg. + */ +static void ks8851_wrreg8(struct ks8851_net *ks, unsigned reg, unsigned val) +{ + struct spi_transfer *xfer = &ks->spi_xfer1; + struct spi_message *msg = &ks->spi_msg1; + __le16 txb[2]; + int ret; + int bit; + + bit = 1 << (reg & 3); + + txb[0] = cpu_to_le16(MK_OP(bit, reg) | KS_SPIOP_WR); + txb[1] = val; + + xfer->tx_buf = txb; + xfer->rx_buf = NULL; + xfer->len = 3; + + ret = spi_sync(ks->spidev, msg); + if (ret < 0) + ks_err(ks, "spi_sync() failed\n"); +} + /** * ks8851_rx_1msg - select whether to use one or two messages for spi read * @ks: The device structure @@ -322,13 +352,12 @@ static void ks8851_soft_reset(struct ks8851_net *ks, unsigned op) static int ks8851_write_mac_addr(struct net_device *dev) { struct ks8851_net *ks = netdev_priv(dev); - u16 *mcp = (u16 *)dev->dev_addr; + int i; mutex_lock(&ks->lock); - ks8851_wrreg16(ks, KS_MARL, mcp[0]); - ks8851_wrreg16(ks, KS_MARM, mcp[1]); - ks8851_wrreg16(ks, KS_MARH, mcp[2]); + for (i = 0; i < ETH_ALEN; i++) + ks8851_wrreg8(ks, KS_MAR(i), dev->dev_addr[i]); mutex_unlock(&ks->lock); diff --git a/drivers/net/ks8851.h b/drivers/net/ks8851.h index 85abe147afbf..f52c312cc356 100644 --- a/drivers/net/ks8851.h +++ b/drivers/net/ks8851.h @@ -16,6 +16,7 @@ #define CCR_32PIN (1 << 0) /* MAC address registers */ +#define KS_MAR(_m) 0x15 - (_m) #define KS_MARL 0x10 #define KS_MARM 0x12 #define KS_MARH 0x14 -- cgit v1.2.3 From b6a71bfa00eb110c8a2e38f85572ed361f8bf3a5 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 19 Oct 2009 23:49:05 +0000 Subject: KS8851: Fix ks8851_set_rx_mode() for IFF_MULTICAST In ks8851_set_rx_mode() the case handling IFF_MULTICAST was also setting the RXCR1_AE bit by accident. This meant that all unicast frames where being accepted by the device. Remove RXCR1_AE from this case. Note, RXCR1_AE was also masking a problem with setting the MAC address properly, so needs to be applied after fixing the MAC write order. Fixes a bug reported by Doong, Ping of Micrel. This version of the patch avoids setting RXCR1_ME for all cases. Signed-off-by: Ben Dooks Signed-off-by: David S. Miller --- drivers/net/ks8851.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 29fa19a076bd..a23f739d222f 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -980,7 +980,7 @@ static void ks8851_set_rx_mode(struct net_device *dev) mcptr = mcptr->next; } - rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA; + rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXPAFMA; } else { /* just accept broadcast / unicast */ rxctrl.rxcr1 = RXCR1_RXPAFMA; -- cgit v1.2.3 From 845de8afa66550331dca164ab77fa49de930b699 Mon Sep 17 00:00:00 2001 From: Joyce Yu Date: Wed, 21 Oct 2009 17:21:10 -0700 Subject: niu: VLAN_ETH_HLEN should be used to make sure that the whole MAC header was copied to the head buffer in the Vlan packets case Signed-off-by: Joyce Yu Signed-off-by: David S. Miller --- drivers/net/niu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index f9364d0678f2..d6c7ac68f6ea 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -3545,7 +3545,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, rp->rcr_index = index; skb_reserve(skb, NET_IP_ALIGN); - __pskb_pull_tail(skb, min(len, NIU_RXPULL_MAX)); + __pskb_pull_tail(skb, min(len, VLAN_ETH_HLEN)); rp->rx_packets++; rp->rx_bytes += skb->len; -- cgit v1.2.3