diff options
| author | David S. Miller <davem@davemloft.net> | 2008-06-28 01:19:40 -0700 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-06-28 01:19:40 -0700 | 
| commit | 1b63ba8a86c85524a8d7e5953b314ce71ebcb9c9 (patch) | |
| tree | fe3dc41cbb47ae12b7c3faf6a88b097349e50d5a | |
| parent | e35c3269edba151e1c703d87068a28ce2cd65bb0 (diff) | |
| parent | d420895efb259a78dda50f95289571faa6e10e41 (diff) | |
| download | olio-linux-3.10-1b63ba8a86c85524a8d7e5953b314ce71ebcb9c9.tar.xz olio-linux-3.10-1b63ba8a86c85524a8d7e5953b314ce71ebcb9c9.zip  | |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
	drivers/net/wireless/iwlwifi/iwl4965-base.c
58 files changed, 362 insertions, 216 deletions
diff --git a/Documentation/networking/s2io.txt b/Documentation/networking/s2io.txt index 4bde53e85f3..1e28e2ddb90 100644 --- a/Documentation/networking/s2io.txt +++ b/Documentation/networking/s2io.txt @@ -83,9 +83,9 @@ Valid range: Limited by memory on system  Default: 30   e. intr_type -Specifies interrupt type. Possible values 1(INTA), 2(MSI), 3(MSI-X) -Valid range: 1-3 -Default: 1  +Specifies interrupt type. Possible values 0(INTA), 2(MSI-X) +Valid values: 0, 2 +Default: 2  5.  Performance suggestions  General: diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 85e2ba7fcfb..bf4830082a1 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -27,6 +27,8 @@  #include <linux/moduleparam.h>  #include <linux/connector.h>  #include <linux/mutex.h> +#include <linux/proc_fs.h> +#include <linux/spinlock.h>  #include <net/sock.h> @@ -403,6 +405,40 @@ static void cn_callback(void *data)  	mutex_unlock(¬ify_lock);  } +static int cn_proc_show(struct seq_file *m, void *v) +{ +	struct cn_queue_dev *dev = cdev.cbdev; +	struct cn_callback_entry *cbq; + +	seq_printf(m, "Name            ID\n"); + +	spin_lock_bh(&dev->queue_lock); + +	list_for_each_entry(cbq, &dev->queue_list, callback_entry) { +		seq_printf(m, "%-15s %u:%u\n", +			   cbq->id.name, +			   cbq->id.id.idx, +			   cbq->id.id.val); +	} + +	spin_unlock_bh(&dev->queue_lock); + +	return 0; +} + +static int cn_proc_open(struct inode *inode, struct file *file) +{ +	return single_open(file, cn_proc_show, NULL); +} + +static const struct file_operations cn_file_ops = { +	.owner   = THIS_MODULE, +	.open    = cn_proc_open, +	.read    = seq_read, +	.llseek  = seq_lseek, +	.release = single_release +}; +  static int __devinit cn_init(void)  {  	struct cn_dev *dev = &cdev; @@ -434,6 +470,8 @@ static int __devinit cn_init(void)  		return -EINVAL;  	} +	proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops); +  	return 0;  } @@ -443,6 +481,8 @@ static void __devexit cn_fini(void)  	cn_already_initialized = 0; +	proc_net_remove(&init_net, "connector"); +  	cn_del_callback(&dev->id);  	cn_queue_free_dev(dev->cbdev);  	netlink_kernel_release(dev->nls); diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 2edda8cc7f9..aabad8ce745 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1768,9 +1768,10 @@ vortex_timer(unsigned long data)  	case XCVR_MII: case XCVR_NWAY:  		{  			ok = 1; -			spin_lock_bh(&vp->lock); +			/* Interrupts are already disabled */ +			spin_lock(&vp->lock);  			vortex_check_media(dev, 0); -			spin_unlock_bh(&vp->lock); +			spin_unlock(&vp->lock);  		}  		break;  	  default:					/* Other media types handled by Tx timeouts. */ diff --git a/drivers/net/e100.c b/drivers/net/e100.c index f3cba5e24ec..1037b133231 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1803,6 +1803,8 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)  	if (rx->prev->skb) {  		struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;  		put_unaligned_le32(rx->dma_addr, &prev_rfd->link); +		pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, +			sizeof(struct rfd), PCI_DMA_TODEVICE);  	}  	return 0; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 701531e72e7..a3f6a9c72ec 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -347,7 +347,7 @@ e1000_set_tso(struct net_device *netdev, u32 data)  	else  		netdev->features &= ~NETIF_F_TSO; -	if (data) +	if (data && (adapter->hw.mac_type > e1000_82547_rev_2))  		netdev->features |= NETIF_F_TSO6;  	else  		netdev->features &= ~NETIF_F_TSO6; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index ccb8ca2cbb2..0320925a42a 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2535,7 +2535,8 @@ void e1000e_down(struct e1000_adapter *adapter)  	adapter->link_speed = 0;  	adapter->link_duplex = 0; -	e1000e_reset(adapter); +	if (!pci_channel_offline(adapter->pdev)) +		e1000e_reset(adapter);  	e1000_clean_tx_ring(adapter);  	e1000_clean_rx_ring(adapter); diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index 0b94833e23f..e8cfadefa4b 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -1077,8 +1077,6 @@ static inline void rx_off(struct scc_priv *priv)  static void start_timer(struct scc_priv *priv, int t, int r15)  { -	unsigned long flags; -  	outb(priv->tmr_mode, priv->tmr_ctrl);  	if (t == 0) {  		tm_isr(priv); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 7b6b780dc8a..6f1ad5368ae 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -718,7 +718,8 @@ void igb_down(struct igb_adapter *adapter)  	adapter->link_speed = 0;  	adapter->link_duplex = 0; -	igb_reset(adapter); +	if (!pci_channel_offline(adapter->pdev)) +		igb_reset(adapter);  	igb_clean_all_tx_rings(adapter);  	igb_clean_all_rx_rings(adapter);  } diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 679a0826780..2c03f4e2ccc 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -1271,7 +1271,7 @@ static void ipg_nic_rx_with_end(struct net_device *dev,  			framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN; -			endframeLen = framelen - jumbo->current_size; +			endframelen = framelen - jumbo->current_size;  			/*  			if (framelen > IPG_RXFRAG_SIZE)  				framelen=IPG_RXFRAG_SIZE; @@ -1279,8 +1279,8 @@ static void ipg_nic_rx_with_end(struct net_device *dev,  			if (framelen > IPG_RXSUPPORT_SIZE)  				dev_kfree_skb_irq(jumbo->skb);  			else { -				memcpy(skb_put(jumbo->skb, endframeLen), -				       skb->data, endframeLen); +				memcpy(skb_put(jumbo->skb, endframelen), +				       skb->data, endframelen);  				jumbo->skb->protocol =  				    eth_type_trans(jumbo->skb, dev); @@ -1352,16 +1352,16 @@ static int ipg_nic_rx(struct net_device *dev)  		switch (ipg_nic_rx_check_frame_type(dev)) {  		case FRAME_WITH_START_WITH_END: -			ipg_nic_rx_with_start_and_end(dev, tp, rxfd, entry); +			ipg_nic_rx_with_start_and_end(dev, sp, rxfd, entry);  			break;  		case FRAME_WITH_START: -			ipg_nic_rx_with_start(dev, tp, rxfd, entry); +			ipg_nic_rx_with_start(dev, sp, rxfd, entry);  			break;  		case FRAME_WITH_END: -			ipg_nic_rx_with_end(dev, tp, rxfd, entry); +			ipg_nic_rx_with_end(dev, sp, rxfd, entry);  			break;  		case FRAME_NO_START_NO_END: -			ipg_nic_rx_no_start_no_end(dev, tp, rxfd, entry); +			ipg_nic_rx_no_start_no_end(dev, sp, rxfd, entry);  			break;  		}  	} @@ -1808,7 +1808,7 @@ static int ipg_nic_open(struct net_device *dev)  	/* initialize JUMBO Frame control variable */  	sp->jumbo.found_start = 0;  	sp->jumbo.current_size = 0; -	sp->jumbo.skb = 0; +	sp->jumbo.skb = NULL;  	dev->mtu = IPG_TXFRAG_SIZE;  #endif diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 0d37c9025be..1674b6a5b90 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1969,7 +1969,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)  	netif_carrier_off(netdev);  	netif_stop_queue(netdev); -	ixgbe_reset(adapter); +	if (!pci_channel_offline(adapter->pdev)) +		ixgbe_reset(adapter);  	ixgbe_clean_all_tx_rings(adapter);  	ixgbe_clean_all_rx_rings(adapter); diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 6797ed069f1..63cd67b931e 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -71,14 +71,18 @@ static irqreturn_t netxen_intr(int irq, void *data);  static irqreturn_t netxen_msi_intr(int irq, void *data);  /*  PCI Device ID Table  */ +#define ENTRY(device) \ +	{PCI_DEVICE(0x4040, (device)), \ +	.class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} +  static struct pci_device_id netxen_pci_tbl[] __devinitdata = { -	{PCI_DEVICE(0x4040, 0x0001), PCI_DEVICE_CLASS(0x020000, ~0)}, -	{PCI_DEVICE(0x4040, 0x0002), PCI_DEVICE_CLASS(0x020000, ~0)}, -	{PCI_DEVICE(0x4040, 0x0003), PCI_DEVICE_CLASS(0x020000, ~0)}, -	{PCI_DEVICE(0x4040, 0x0004), PCI_DEVICE_CLASS(0x020000, ~0)}, -	{PCI_DEVICE(0x4040, 0x0005), PCI_DEVICE_CLASS(0x020000, ~0)}, -	{PCI_DEVICE(0x4040, 0x0024), PCI_DEVICE_CLASS(0x020000, ~0)}, -	{PCI_DEVICE(0x4040, 0x0025), PCI_DEVICE_CLASS(0x020000, ~0)}, +	ENTRY(0x0001), +	ENTRY(0x0002), +	ENTRY(0x0003), +	ENTRY(0x0004), +	ENTRY(0x0005), +	ENTRY(0x0024), +	ENTRY(0x0025),  	{0,}  }; diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index d7018ff9e17..3f682d49a4e 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -525,12 +525,14 @@ static int axnet_open(struct net_device *dev)      int ret;      axnet_dev_t *info = PRIV(dev);      struct pcmcia_device *link = info->p_dev; +    unsigned int nic_base = dev->base_addr;      DEBUG(2, "axnet_open('%s')\n", dev->name);      if (!pcmcia_dev_present(link))  	return -ENODEV; +    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */      ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);      if (ret)  	    return ret; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index fd8158a86f6..2d4c4ad89b8 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -969,6 +969,7 @@ static int pcnet_open(struct net_device *dev)      int ret;      pcnet_dev_t *info = PRIV(dev);      struct pcmcia_device *link = info->p_dev; +    unsigned int nic_base = dev->base_addr;      DEBUG(2, "pcnet_open('%s')\n", dev->name); @@ -976,6 +977,8 @@ static int pcnet_open(struct net_device *dev)  	return -ENODEV;      set_misc_reg(dev); + +    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */      ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);      if (ret)  	    return ret; diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index bafb69b6f7c..fc6f4b8c64b 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -942,7 +942,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,  	m->msg_namelen = 0;  	if (skb) { -		total_len = min(total_len, skb->len); +		total_len = min_t(size_t, total_len, skb->len);  		error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);  		if (error == 0)  			error = total_len; diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 5f608780c3e..e7d48a352be 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -3701,7 +3701,9 @@ static int ql_cycle_adapter(struct ql3_adapter *qdev, int reset)  		printk(KERN_ERR PFX  				"%s: Driver up/down cycle failed, "  				"closing device\n",qdev->ndev->name); +		rtnl_lock();  		dev_close(qdev->ndev); +		rtnl_unlock();  		return -1;  	}  	return 0; diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 858b191517b..504a48ff73c 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -273,7 +273,7 @@ static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring,  	dma_addr_t mapping = desc_dma;  	while (size-- > 0) { -		mapping += sizeof(sizeof(*desc)); +		mapping += sizeof(*desc);  		desc->ndesc = cpu_to_le32(mapping);  		desc->vndescp = desc + 1;  		desc++; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 5694e894fc7..e7a3dbec674 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -2625,9 +2625,7 @@ static int fill_rx_buffers(struct ring_info *ring)  			rxdp1->Buffer0_ptr = pci_map_single  			    (ring->pdev, skb->data, size - NET_IP_ALIGN,  				PCI_DMA_FROMDEVICE); -			if( (rxdp1->Buffer0_ptr == 0) || -				(rxdp1->Buffer0_ptr == -				DMA_ERROR_CODE)) +			if(pci_dma_mapping_error(rxdp1->Buffer0_ptr))  				goto pci_map_failed;  			rxdp->Control_2 = @@ -2657,6 +2655,7 @@ static int fill_rx_buffers(struct ring_info *ring)  			skb->data = (void *) (unsigned long)tmp;  			skb_reset_tail_pointer(skb); +			/* AK: check is wrong. 0 can be valid dma address */  			if (!(rxdp3->Buffer0_ptr))  				rxdp3->Buffer0_ptr =  				   pci_map_single(ring->pdev, ba->ba_0, @@ -2665,8 +2664,7 @@ static int fill_rx_buffers(struct ring_info *ring)  				pci_dma_sync_single_for_device(ring->pdev,  				(dma_addr_t) rxdp3->Buffer0_ptr,  				    BUF0_LEN, PCI_DMA_FROMDEVICE); -			if( (rxdp3->Buffer0_ptr == 0) || -				(rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) +			if (pci_dma_mapping_error(rxdp3->Buffer0_ptr))  				goto pci_map_failed;  			rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); @@ -2681,18 +2679,17 @@ static int fill_rx_buffers(struct ring_info *ring)  				(ring->pdev, skb->data, ring->mtu + 4,  						PCI_DMA_FROMDEVICE); -				if( (rxdp3->Buffer2_ptr == 0) || -					(rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) +				if (pci_dma_mapping_error(rxdp3->Buffer2_ptr))  					goto pci_map_failed; +				/* AK: check is wrong */  				if (!rxdp3->Buffer1_ptr)  					rxdp3->Buffer1_ptr =  						pci_map_single(ring->pdev,  						ba->ba_1, BUF1_LEN,  						PCI_DMA_FROMDEVICE); -				if( (rxdp3->Buffer1_ptr == 0) || -					(rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { +				if (pci_dma_mapping_error(rxdp3->Buffer1_ptr)) {  					pci_unmap_single  						(ring->pdev,  						(dma_addr_t)(unsigned long) @@ -4264,16 +4261,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)  		txdp->Buffer_Pointer = pci_map_single(sp->pdev,  					fifo->ufo_in_band_v,  					sizeof(u64), PCI_DMA_TODEVICE); -		if((txdp->Buffer_Pointer == 0) || -			(txdp->Buffer_Pointer == DMA_ERROR_CODE)) +		if (pci_dma_mapping_error(txdp->Buffer_Pointer))  			goto pci_map_failed;  		txdp++;  	}  	txdp->Buffer_Pointer = pci_map_single  	    (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); -	if((txdp->Buffer_Pointer == 0) || -		(txdp->Buffer_Pointer == DMA_ERROR_CODE)) +	if (pci_dma_mapping_error(txdp->Buffer_Pointer))  		goto pci_map_failed;  	txdp->Host_Control = (unsigned long) skb; @@ -6884,10 +6879,8 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,  				pci_map_single( sp->pdev, (*skb)->data,  					size - NET_IP_ALIGN,  					PCI_DMA_FROMDEVICE); -			if( (rxdp1->Buffer0_ptr == 0) || -				(rxdp1->Buffer0_ptr == DMA_ERROR_CODE)) { +			if (pci_dma_mapping_error(rxdp1->Buffer0_ptr))  				goto memalloc_failed; -			}  			rxdp->Host_Control = (unsigned long) (*skb);  		}  	} else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) { @@ -6913,15 +6906,12 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,  				pci_map_single(sp->pdev, (*skb)->data,  					       dev->mtu + 4,  					       PCI_DMA_FROMDEVICE); -			if( (rxdp3->Buffer2_ptr == 0) || -				(rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) { +			if (pci_dma_mapping_error(rxdp3->Buffer2_ptr))  				goto memalloc_failed; -			}  			rxdp3->Buffer0_ptr = *temp0 =  				pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN,  						PCI_DMA_FROMDEVICE); -			if( (rxdp3->Buffer0_ptr == 0) || -				(rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) { +			if (pci_dma_mapping_error(rxdp3->Buffer0_ptr)) {  				pci_unmap_single (sp->pdev,  					(dma_addr_t)rxdp3->Buffer2_ptr,  					dev->mtu + 4, PCI_DMA_FROMDEVICE); @@ -6933,8 +6923,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,  			rxdp3->Buffer1_ptr = *temp1 =  				pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN,  						PCI_DMA_FROMDEVICE); -			if( (rxdp3->Buffer1_ptr == 0) || -				(rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { +			if (pci_dma_mapping_error(rxdp3->Buffer1_ptr)) {  				pci_unmap_single (sp->pdev,  					(dma_addr_t)rxdp3->Buffer0_ptr,  					BUF0_LEN, PCI_DMA_FROMDEVICE); diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index d0a84ba887a..483b17c34ae 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -75,10 +75,6 @@ static int debug_level = ERR_DBG;  /* DEBUG message print. */  #define DBG_PRINT(dbg_level, args...)  if(!(debug_level<dbg_level)) printk(args) -#ifndef DMA_ERROR_CODE -#define DMA_ERROR_CODE          (~(dma_addr_t)0x0) -#endif -  /* Protocol assist features of the NIC */  #define L3_CKSUM_OK 0xFFFF  #define L4_CKSUM_OK 0xFFFF diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 10e4e85da3f..b07b8cbadea 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1394,6 +1394,7 @@ tc35815_open(struct net_device *dev)  	tc35815_chip_init(dev);  	spin_unlock_irq(&lp->lock); +	netif_carrier_off(dev);  	/* schedule a link state check */  	phy_start(lp->phy_dev); @@ -1735,7 +1736,6 @@ tc35815_rx(struct net_device *dev)  			skb = lp->rx_skbs[cur_bd].skb;  			prefetch(skb->data);  			lp->rx_skbs[cur_bd].skb = NULL; -			lp->fbl_count--;  			pci_unmap_single(lp->pci_dev,  					 lp->rx_skbs[cur_bd].skb_dma,  					 RX_BUF_SIZE, PCI_DMA_FROMDEVICE); @@ -1791,6 +1791,7 @@ tc35815_rx(struct net_device *dev)  #ifdef TC35815_USE_PACKEDBUFFER  			while (lp->fbl_curid != id)  #else +			lp->fbl_count--;  			while (lp->fbl_count < RX_BUF_NUM)  #endif  			{ @@ -2453,6 +2454,7 @@ static int tc35815_resume(struct pci_dev *pdev)  		return 0;  	pci_set_power_state(pdev, PCI_D0);  	tc35815_restart(dev); +	netif_carrier_off(dev);  	if (lp->phy_dev)  		phy_start(lp->phy_dev);  	netif_device_attach(dev); diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 249e18053d5..069f8bb0a99 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -32,6 +32,7 @@  #include <linux/x25.h>  #include <linux/lapb.h>  #include <linux/init.h> +#include <linux/rtnetlink.h>  #include "x25_asy.h"  #include <net/x25device.h> @@ -601,8 +602,10 @@ static void x25_asy_close_tty(struct tty_struct *tty)  	if (!sl || sl->magic != X25_ASY_MAGIC)  		return; +	rtnl_lock();  	if (sl->dev->flags & IFF_UP)  		dev_close(sl->dev); +	rtnl_unlock();  	tty->disc_data = NULL;  	sl->tty = NULL; diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index 36a9c42df83..76f4c7bad8b 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c @@ -72,6 +72,9 @@ static void b43_led_brightness_set(struct led_classdev *led_dev,  	struct b43_wldev *dev = led->dev;  	bool radio_enabled; +	if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) +		return; +  	/* Checking the radio-enabled status here is slightly racy,  	 * but we want to avoid the locking overhead and we don't care  	 * whether the LED has the wrong state for a second. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7bca8e98151..704dd3551ff 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2976,12 +2976,11 @@ static int b43_op_tx(struct ieee80211_hw *hw,  	if (unlikely(skb->len < 2 + 2 + 6)) {  		/* Too short, this can't be a valid frame. */ -		dev_kfree_skb_any(skb); -		return NETDEV_TX_OK; +		goto drop_packet;  	}  	B43_WARN_ON(skb_shinfo(skb)->nr_frags);  	if (unlikely(!dev)) -		return NETDEV_TX_BUSY; +		goto drop_packet;  	/* Transmissions on seperate queues can run concurrently. */  	read_lock_irqsave(&wl->tx_lock, flags); @@ -2997,7 +2996,12 @@ static int b43_op_tx(struct ieee80211_hw *hw,  	read_unlock_irqrestore(&wl->tx_lock, flags);  	if (unlikely(err)) -		return NETDEV_TX_BUSY; +		goto drop_packet; +	return NETDEV_TX_OK; + +drop_packet: +	/* We can not transmit this packet. Drop it. */ +	dev_kfree_skb_any(skb);  	return NETDEV_TX_OK;  } diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 33cc256c5ba..203b0f42ac5 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -876,6 +876,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,  	if (!ring)  		goto out;  	ring->type = type; +	ring->dev = dev;  	nr_slots = B43legacy_RXRING_SLOTS;  	if (for_tx) @@ -922,7 +923,6 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,  				 DMA_TO_DEVICE);  	} -	ring->dev = dev;  	ring->nr_slots = nr_slots;  	ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index);  	ring->index = controller_index; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 5f533b93ad5..069157eea05 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2377,8 +2377,10 @@ static int b43legacy_op_tx(struct ieee80211_hw *hw,  	} else  		err = b43legacy_dma_tx(dev, skb);  out: -	if (unlikely(err)) -		return NETDEV_TX_BUSY; +	if (unlikely(err)) { +		/* Drop the packet. */ +		dev_kfree_skb_any(skb); +	}  	return NETDEV_TX_OK;  } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5ca181f7125..5b420b43af5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -276,13 +276,18 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,  	cancel_delayed_work(&priv->scan_check);  	IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", -		       (priv->scan_bands == 2) ? "2.4" : "5.2", +		       (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? +						"2.4" : "5.2",  		       jiffies_to_msecs(elapsed_jiffies  					(priv->scan_pass_start, jiffies))); -	/* Remove this scanned band from the list -	 * of pending bands to scan */ -	priv->scan_bands--; +	/* Remove this scanned band from the list of pending +	 * bands to scan, band G precedes A in order of scanning +	 * as seen in iwl_bg_request_scan */ +	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) +		priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); +	else if (priv->scan_bands &  BIT(IEEE80211_BAND_5GHZ)) +		priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);  	/* If a request to abort was given, or the scan did not succeed  	 * then we reset the scan state machine and terminate, @@ -292,7 +297,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,  		clear_bit(STATUS_SCAN_ABORTING, &priv->status);  	} else {  		/* If there are more bands on this scan pass reschedule */ -		if (priv->scan_bands > 0) +		if (priv->scan_bands)  			goto reschedule;  	} @@ -389,7 +394,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,  		ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);  		if (!is_channel_valid(ch_info)) { -			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", +			IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n",  				       scan_ch->channel);  			continue;  		} @@ -465,7 +470,10 @@ int iwl_scan_initiate(struct iwl_priv *priv)  	}  	IWL_DEBUG_INFO("Starting scan...\n"); -	priv->scan_bands = 2; +	if (priv->cfg->sku & IWL_SKU_G) +		priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); +	if (priv->cfg->sku & IWL_SKU_A) +		priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);  	set_bit(STATUS_SCANNING, &priv->status);  	priv->scan_start = jiffies;  	priv->scan_pass_start = priv->scan_start; @@ -803,8 +811,7 @@ static void iwl_bg_request_scan(struct work_struct *data)  	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; -	switch (priv->scan_bands) { -	case 2: +	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {  		band = IEEE80211_BAND_2GHZ;  		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;  		tx_ant = iwl_scan_tx_ant(priv, band); @@ -818,9 +825,7 @@ static void iwl_bg_request_scan(struct work_struct *data)  							tx_ant |  							RATE_MCS_CCK_MSK);  		scan->good_CRC_th = 0; -		break; - -	case 1: +	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {  		band = IEEE80211_BAND_5GHZ;  		tx_ant = iwl_scan_tx_ant(priv, band);  		scan->tx_cmd.rate_n_flags = @@ -833,9 +838,7 @@ static void iwl_bg_request_scan(struct work_struct *data)  		 * MIMO is not used here, but value is required */  		if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)  			rx_chain = 0x6; - -		break; -	default: +	} else {  		IWL_WARNING("Invalid scan band count\n");  		goto done;  	} diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 47cf4b997f5..92d1b2e312d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2217,7 +2217,10 @@ static int iwl3945_scan_initiate(struct iwl3945_priv *priv)  	}  	IWL_DEBUG_INFO("Starting scan...\n"); -	priv->scan_bands = 2; +	if (priv->cfg->sku & IWL_SKU_G) +		priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); +	if (priv->cfg->sku & IWL_SKU_A) +		priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);  	set_bit(STATUS_SCANNING, &priv->status);  	priv->scan_start = jiffies;  	priv->scan_pass_start = priv->scan_start; @@ -3342,13 +3345,18 @@ static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv,  	cancel_delayed_work(&priv->scan_check);  	IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", -		       (priv->scan_bands == 2) ? "2.4" : "5.2", +		       (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? +							"2.4" : "5.2",  		       jiffies_to_msecs(elapsed_jiffies  					(priv->scan_pass_start, jiffies))); -	/* Remove this scanned band from the list -	 * of pending bands to scan */ -	priv->scan_bands--; +	/* Remove this scanned band from the list of pending +	 * bands to scan, band G precedes A in order of scanning +	 * as seen in iwl3945_bg_request_scan */ +	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) +		priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); +	else if (priv->scan_bands &  BIT(IEEE80211_BAND_5GHZ)) +		priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);  	/* If a request to abort was given, or the scan did not succeed  	 * then we reset the scan state machine and terminate, @@ -4961,7 +4969,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,  		ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel);  		if (!is_channel_valid(ch_info)) { -			IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", +			IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n",  				       scan_ch->channel);  			continue;  		} @@ -6316,21 +6324,16 @@ static void iwl3945_bg_request_scan(struct work_struct *data)  	/* flags + rate selection */ -	switch (priv->scan_bands) { -	case 2: +	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {  		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;  		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;  		scan->good_CRC_th = 0;  		band = IEEE80211_BAND_2GHZ; -		break; - -	case 1: +	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {  		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;  		scan->good_CRC_th = IWL_GOOD_CRC_TH;  		band = IEEE80211_BAND_5GHZ; -		break; - -	default: +	} else {  		IWL_WARNING("Invalid scan band count\n");  		goto done;  	} @@ -6770,7 +6773,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co  	ch_info = iwl3945_get_channel_info(priv, conf->channel->band,  					   conf->channel->hw_value);  	if (!is_channel_valid(ch_info)) { -		IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n", +		IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this band.\n",  			       conf->channel->hw_value, conf->channel->band);  		IWL_DEBUG_MAC80211("leave - invalid channel\n");  		spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 762e85bef55..e43bae97ed8 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -290,7 +290,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb)  		avs->version = cpu_to_be32(P80211CAPTURE_VERSION);  		avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header)); -		avs->mactime = cpu_to_be64(le64_to_cpu(clock)); +		avs->mactime = cpu_to_be64(clock);  		avs->hosttime = cpu_to_be64(jiffies);  		avs->phytype = cpu_to_be32(6);	/*OFDM: 6 for (g), 8 for (a) */  		avs->channel = cpu_to_be32(channel_of_freq(freq)); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9851cefaabf..0462d6d35b8 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -138,11 +138,8 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,  	 * Wait until the BBP becomes ready.  	 */  	reg = rt2500usb_bbp_check(rt2x00dev); -	if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { -		ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); -		mutex_unlock(&rt2x00dev->usb_cache_mutex); -		return; -	} +	if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) +		goto exit_fail;  	/*  	 * Write the data into the BBP. @@ -155,6 +152,13 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,  	rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);  	mutex_unlock(&rt2x00dev->usb_cache_mutex); + +	return; + +exit_fail: +	mutex_unlock(&rt2x00dev->usb_cache_mutex); + +	ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");  }  static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -168,10 +172,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,  	 * Wait until the BBP becomes ready.  	 */  	reg = rt2500usb_bbp_check(rt2x00dev); -	if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { -		ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); -		return; -	} +	if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) +		goto exit_fail;  	/*  	 * Write the request into the BBP. @@ -186,17 +188,21 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,  	 * Wait until the BBP becomes ready.  	 */  	reg = rt2500usb_bbp_check(rt2x00dev); -	if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { -		ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); -		*value = 0xff; -		mutex_unlock(&rt2x00dev->usb_cache_mutex); -		return; -	} +	if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) +		goto exit_fail;  	rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®);  	*value = rt2x00_get_field16(reg, PHY_CSR7_DATA);  	mutex_unlock(&rt2x00dev->usb_cache_mutex); + +	return; + +exit_fail: +	mutex_unlock(&rt2x00dev->usb_cache_mutex); + +	ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); +	*value = 0xff;  }  static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 0da8f972a1b..52d8e968821 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -818,6 +818,7 @@ struct rt2x00_dev {  	/*  	 * Scheduled work.  	 */ +	struct workqueue_struct *workqueue;  	struct work_struct intf_work;  	struct work_struct filter_work; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 9ea677320da..cc4fee105ed 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -74,7 +74,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev)  	rt2x00lib_reset_link_tuner(rt2x00dev); -	queue_delayed_work(rt2x00dev->hw->workqueue, +	queue_delayed_work(rt2x00dev->workqueue,  			   &rt2x00dev->link.work, LINK_TUNE_INTERVAL);  } @@ -138,14 +138,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)  		return;  	/* -	 * Stop all scheduled work. -	 */ -	if (work_pending(&rt2x00dev->intf_work)) -		cancel_work_sync(&rt2x00dev->intf_work); -	if (work_pending(&rt2x00dev->filter_work)) -		cancel_work_sync(&rt2x00dev->filter_work); - -	/*  	 * Stop the TX queues.  	 */  	ieee80211_stop_queues(rt2x00dev->hw); @@ -400,8 +392,8 @@ static void rt2x00lib_link_tuner(struct work_struct *work)  	 * Increase tuner counter, and reschedule the next link tuner run.  	 */  	rt2x00dev->link.count++; -	queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, -			   LINK_TUNE_INTERVAL); +	queue_delayed_work(rt2x00dev->workqueue, +			   &rt2x00dev->link.work, LINK_TUNE_INTERVAL);  }  static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) @@ -434,6 +426,15 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,  	spin_unlock(&intf->lock); +	/* +	 * It is possible the radio was disabled while the work had been +	 * scheduled. If that happens we should return here immediately, +	 * note that in the spinlock protected area above the delayed_flags +	 * have been cleared correctly. +	 */ +	if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) +		return; +  	if (delayed_flags & DELAYED_UPDATE_BEACON) {  		skb = ieee80211_beacon_get(rt2x00dev->hw, vif);  		if (skb && @@ -442,7 +443,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,  	}  	if (delayed_flags & DELAYED_CONFIG_ERP) -		rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf); +		rt2x00lib_config_erp(rt2x00dev, intf, &conf);  	if (delayed_flags & DELAYED_LED_ASSOC)  		rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); @@ -488,7 +489,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)  						   rt2x00lib_beacondone_iter,  						   rt2x00dev); -	queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); +	queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work);  }  EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -1003,6 +1004,10 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)  	/*  	 * Initialize configuration work.  	 */ +	rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib"); +	if (!rt2x00dev->workqueue) +		goto exit; +  	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);  	INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);  	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); @@ -1063,6 +1068,13 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)  	rt2x00leds_unregister(rt2x00dev);  	/* +	 * Stop all queued work. Note that most tasks will already be halted +	 * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize(). +	 */ +	flush_workqueue(rt2x00dev->workqueue); +	destroy_workqueue(rt2x00dev->workqueue); + +	/*  	 * Free ieee80211_hw memory.  	 */  	rt2x00lib_remove_hw(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c90992f613f..1253da89295 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -431,7 +431,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,  	if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))  		rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);  	else -		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); +		queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work);  }  EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); @@ -512,7 +512,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,  	memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));  	if (delayed) {  		intf->delayed_flags |= delayed; -		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); +		queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work);  	}  	spin_unlock(&intf->lock);  } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index fceefd730ab..675ff7900ee 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -134,11 +134,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,  	 * Wait until the BBP becomes ready.  	 */  	reg = rt73usb_bbp_check(rt2x00dev); -	if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { -		ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); -		mutex_unlock(&rt2x00dev->usb_cache_mutex); -		return; -	} +	if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) +		goto exit_fail;  	/*  	 * Write the data into the BBP. @@ -151,6 +148,13 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,  	rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);  	mutex_unlock(&rt2x00dev->usb_cache_mutex); + +	return; + +exit_fail: +	mutex_unlock(&rt2x00dev->usb_cache_mutex); + +	ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");  }  static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -164,11 +168,8 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,  	 * Wait until the BBP becomes ready.  	 */  	reg = rt73usb_bbp_check(rt2x00dev); -	if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { -		ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); -		mutex_unlock(&rt2x00dev->usb_cache_mutex); -		return; -	} +	if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) +		goto exit_fail;  	/*  	 * Write the request into the BBP. @@ -184,14 +185,19 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,  	 * Wait until the BBP becomes ready.  	 */  	reg = rt73usb_bbp_check(rt2x00dev); -	if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { -		ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); -		*value = 0xff; -		return; -	} +	if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) +		goto exit_fail;  	*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);  	mutex_unlock(&rt2x00dev->usb_cache_mutex); + +	return; + +exit_fail: +	mutex_unlock(&rt2x00dev->usb_cache_mutex); + +	ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); +	*value = 0xff;  }  static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, diff --git a/include/linux/inet_lro.h b/include/linux/inet_lro.h index 80335b7d77c..c4335faebb6 100644 --- a/include/linux/inet_lro.h +++ b/include/linux/inet_lro.h @@ -84,7 +84,11 @@ struct net_lro_mgr {  				    from received packets and eth protocol  				    is still ETH_P_8021Q */ -	u32 ip_summed;      /* Set in non generated SKBs in page mode */ +	/* +	 * Set for generated SKBs that are not added to +	 * the frag list in fragmented mode +	 */ +	u32 ip_summed;  	u32 ip_summed_aggr; /* Set in aggregated SKBs: CHECKSUM_UNNECESSARY  			     * or CHECKSUM_NONE */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1304ad2d710..56dadb528f6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -88,6 +88,8 @@ struct wireless_dev;  #define NETDEV_TX_BUSY 1	/* driver tx path was busy*/  #define NETDEV_TX_LOCKED -1	/* driver tx lock was already taken */ +#ifdef  __KERNEL__ +  /*   *	Compute the worst case header length according to the protocols   *	used. @@ -114,6 +116,8 @@ struct wireless_dev;  #define MAX_HEADER (LL_MAX_HEADER + 48)  #endif +#endif  /*  __KERNEL__  */ +  struct net_device_subqueue  {  	/* Give a control state for each queue.  This struct may contain diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 7f7db8d5793..c2222ee74d6 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -365,6 +365,12 @@ static inline int ipv6_addr_any(const struct in6_addr *a)  		 a->s6_addr32[2] | a->s6_addr32[3] ) == 0);   } +static inline int ipv6_addr_loopback(const struct in6_addr *a) +{ +	return ((a->s6_addr32[0] | a->s6_addr32[1] | +		 a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0); +} +  static inline int ipv6_addr_v4mapped(const struct in6_addr *a)  {  	return ((a->s6_addr32[0] | a->s6_addr32[1] | diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 8df751b3be5..f90443045c7 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -95,6 +95,11 @@ extern struct list_head net_namespace_list;  #ifdef CONFIG_NET_NS  extern void __put_net(struct net *net); +static inline int net_alive(struct net *net) +{ +	return net && atomic_read(&net->count); +} +  static inline struct net *get_net(struct net *net)  {  	atomic_inc(&net->count); @@ -125,6 +130,12 @@ int net_eq(const struct net *net1, const struct net *net2)  	return net1 == net2;  }  #else + +static inline int net_alive(struct net *net) +{ +	return 1; +} +  static inline struct net *get_net(struct net *net)  {  	return net; diff --git a/net/core/dev.c b/net/core/dev.c index f6944ecd5b2..472676dd550 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2107,6 +2107,10 @@ int netif_receive_skb(struct sk_buff *skb)  	rcu_read_lock(); +	/* Don't receive packets in an exiting network namespace */ +	if (!net_alive(dev_net(skb->dev))) +		goto out; +  #ifdef CONFIG_NET_CLS_ACT  	if (skb->tc_verd & TC_NCLS) {  		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); @@ -3034,7 +3038,7 @@ EXPORT_SYMBOL(dev_unicast_delete);  /**   *	dev_unicast_add		- add a secondary unicast address   *	@dev: device - *	@addr: address to delete + *	@addr: address to add   *	@alen: length of @addr   *   *	Add a secondary unicast address to the device or increase diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 72b4c184dd8..7c52fe277b6 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -140,6 +140,9 @@ static void cleanup_net(struct work_struct *work)  	struct pernet_operations *ops;  	struct net *net; +	/* Be very certain incoming network packets will not find us */ +	rcu_barrier(); +  	net = container_of(work, struct net, work);  	mutex_lock(&net_mutex); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2df012be973..7c571560e9d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1290,12 +1290,14 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,  {  	unsigned int nr_pages = spd->nr_pages;  	unsigned int poff, plen, len, toff, tlen; -	int headlen, seg; +	int headlen, seg, error = 0;  	toff = *offset;  	tlen = *total_len; -	if (!tlen) +	if (!tlen) { +		error = 1;  		goto err; +	}  	/*  	 * if the offset is greater than the linear part, go directly to @@ -1337,7 +1339,8 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,  		 * just jump directly to update and return, no point  		 * in going over fragments when the output is full.  		 */ -		if (spd_fill_page(spd, virt_to_page(p), plen, poff, skb)) +		error = spd_fill_page(spd, virt_to_page(p), plen, poff, skb); +		if (error)  			goto done;  		tlen -= plen; @@ -1367,7 +1370,8 @@ map_frag:  		if (!plen)  			break; -		if (spd_fill_page(spd, f->page, plen, poff, skb)) +		error = spd_fill_page(spd, f->page, plen, poff, skb); +		if (error)  			break;  		tlen -= plen; @@ -1380,7 +1384,10 @@ done:  		return 0;  	}  err: -	return 1; +	/* update the offset to reflect the linear part skip, if any */ +	if (!error) +		*offset = toff; +	return error;  }  /* diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 4ed429bd595..0546a0bc97e 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -192,14 +192,21 @@ EXPORT_SYMBOL(inet_frag_evictor);  static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,  		struct inet_frag_queue *qp_in, struct inet_frags *f, -		unsigned int hash, void *arg) +		void *arg)  {  	struct inet_frag_queue *qp;  #ifdef CONFIG_SMP  	struct hlist_node *n;  #endif +	unsigned int hash;  	write_lock(&f->lock); +	/* +	 * While we stayed w/o the lock other CPU could update +	 * the rnd seed, so we need to re-calculate the hash +	 * chain. Fortunatelly the qp_in can be used to get one. +	 */ +	hash = f->hashfn(qp_in);  #ifdef CONFIG_SMP  	/* With SMP race we have to recheck hash table, because  	 * such entry could be created on other cpu, while we @@ -247,7 +254,7 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,  }  static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, -		struct inet_frags *f, void *arg, unsigned int hash) +		struct inet_frags *f, void *arg)  {  	struct inet_frag_queue *q; @@ -255,7 +262,7 @@ static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf,  	if (q == NULL)  		return NULL; -	return inet_frag_intern(nf, q, f, hash, arg); +	return inet_frag_intern(nf, q, f, arg);  }  struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, @@ -264,7 +271,6 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,  	struct inet_frag_queue *q;  	struct hlist_node *n; -	read_lock(&f->lock);  	hlist_for_each_entry(q, n, &f->hash[hash], list) {  		if (q->net == nf && f->match(q, key)) {  			atomic_inc(&q->refcnt); @@ -274,6 +280,6 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,  	}  	read_unlock(&f->lock); -	return inet_frag_create(nf, f, key, hash); +	return inet_frag_create(nf, f, key);  }  EXPORT_SYMBOL(inet_frag_find); diff --git a/net/ipv4/inet_lro.c b/net/ipv4/inet_lro.c index 4a4d49fca1f..cfd034a2b96 100644 --- a/net/ipv4/inet_lro.c +++ b/net/ipv4/inet_lro.c @@ -383,8 +383,7 @@ static int __lro_proc_skb(struct net_lro_mgr *lro_mgr, struct sk_buff *skb,  out2: /* send aggregated SKBs to stack */  	lro_flush(lro_mgr, lro_desc); -out:  /* Original SKB has to be posted to stack */ -	skb->ip_summed = lro_mgr->ip_summed; +out:  	return 1;  } diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 91e32140731..fbd5804b5d8 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -227,6 +227,8 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)  	arg.iph = iph;  	arg.user = user; + +	read_lock(&ip4_frags.lock);  	hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);  	q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index cf0850c068f..c66ac83316e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -258,6 +258,8 @@  #include <linux/socket.h>  #include <linux/random.h>  #include <linux/bootmem.h> +#include <linux/highmem.h> +#include <linux/swap.h>  #include <linux/cache.h>  #include <linux/err.h>  #include <linux/crypto.h> @@ -2688,7 +2690,7 @@ __setup("thash_entries=", set_thash_entries);  void __init tcp_init(void)  {  	struct sk_buff *skb = NULL; -	unsigned long limit; +	unsigned long nr_pages, limit;  	int order, i, max_share;  	BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); @@ -2757,8 +2759,9 @@ void __init tcp_init(void)  	 * is up to 1/2 at 256 MB, decreasing toward zero with the amount of  	 * memory, with a floor of 128 pages.  	 */ -	limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); -	limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); +	nr_pages = totalram_pages - totalhigh_pages; +	limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); +	limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);  	limit = max(limit, 128UL);  	sysctl_tcp_mem[0] = limit / 4 * 3;  	sysctl_tcp_mem[1] = limit; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0db9b75c1fa..4300bcf2cea 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2189,7 +2189,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)  	}  	seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " -			"%08X %5d %8d %lu %d %p %u %u %u %u %d%n", +			"%08X %5d %8d %lu %d %p %lu %lu %u %u %d%n",  		i, src, srcp, dest, destp, sk->sk_state,  		tp->write_seq - tp->snd_una,  		sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog : @@ -2201,8 +2201,8 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)  		icsk->icsk_probes_out,  		sock_i_ino(sk),  		atomic_read(&sk->sk_refcnt), sk, -		icsk->icsk_rto, -		icsk->icsk_ack.ato, +		jiffies_to_clock_t(icsk->icsk_rto), +		jiffies_to_clock_t(icsk->icsk_ack.ato),  		(icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,  		tp->snd_cwnd,  		tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh, diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index f77a6011c30..34e5a96623a 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -100,6 +100,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt  	if (hdr->version != 6)  		goto err; +	/* +	 * RFC4291 2.5.3 +	 * A packet received on an interface with a destination address +	 * of loopback must be dropped. +	 */ +	if (!(dev->flags & IFF_LOOPBACK) && +	    ipv6_addr_loopback(&hdr->daddr)) +		goto err; +  	skb->transport_header = skb->network_header + sizeof(*hdr);  	IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index a9988841172..030c0c956f9 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -343,18 +343,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,  	case IPV6_DSTOPTS:  	{  		struct ipv6_txoptions *opt; + +		/* remove any sticky options header with a zero option +		 * length, per RFC3542. +		 */  		if (optlen == 0)  			optval = NULL; +		else if (optlen < sizeof(struct ipv6_opt_hdr) || +			 optlen & 0x7 || optlen > 8 * 255) +			goto e_inval;  		/* hop-by-hop / destination options are privileged option */  		retv = -EPERM;  		if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))  			break; -		if (optlen < sizeof(struct ipv6_opt_hdr) || -		    optlen & 0x7 || optlen > 8 * 255) -			goto e_inval; -  		opt = ipv6_renew_options(sk, np->opt, optname,  					 (struct ipv6_opt_hdr __user *)optval,  					 optlen); diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 27a5e8b48d9..f405cea21a8 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -129,7 +129,7 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = {  		.priority	= NF_IP6_PRI_MANGLE,  	},  	{ -		.hook		= ip6t_local_hook, +		.hook		= ip6t_route_hook,  		.owner		= THIS_MODULE,  		.pf		= PF_INET6,  		.hooknum	= NF_INET_LOCAL_IN, diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index e65e26e210e..cf20bc4fd60 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -207,9 +207,10 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst)  	arg.id = id;  	arg.src = src;  	arg.dst = dst; + +	read_lock_bh(&nf_frags.lock);  	hash = ip6qhashfn(id, src, dst); -	local_bh_disable();  	q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash);  	local_bh_enable();  	if (q == NULL) diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 13509f906d8..6ab957ec2dd 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -245,6 +245,8 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst,  	arg.id = id;  	arg.src = src;  	arg.dst = dst; + +	read_lock(&ip6_frags.lock);  	hash = ip6qhashfn(id, src, dst);  	q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index efe036aa3dd..751e98f9b8b 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -238,7 +238,7 @@ static inline int rt6_need_strict(struct in6_addr *daddr)  static inline struct rt6_info *rt6_device_match(struct net *net,  						    struct rt6_info *rt,  						    int oif, -						    int strict) +						    int flags)  {  	struct rt6_info *local = NULL;  	struct rt6_info *sprt; @@ -251,7 +251,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net,  			if (dev->flags & IFF_LOOPBACK) {  				if (sprt->rt6i_idev == NULL ||  				    sprt->rt6i_idev->dev->ifindex != oif) { -					if (strict && oif) +					if (flags & RT6_LOOKUP_F_IFACE && oif)  						continue;  					if (local && (!oif ||  						      local->rt6i_idev->dev->ifindex == oif)) @@ -264,7 +264,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net,  		if (local)  			return local; -		if (strict) +		if (flags & RT6_LOOKUP_F_IFACE)  			return net->ipv6.ip6_null_entry;  	}  	return rt; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 09be09cc1aa..30dbab7cc3c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1946,7 +1946,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)  	seq_printf(seq,  		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " -		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n", +		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %lu %lu %u %u %d\n",  		   i,  		   src->s6_addr32[0], src->s6_addr32[1],  		   src->s6_addr32[2], src->s6_addr32[3], srcp, @@ -1962,8 +1962,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)  		   icsk->icsk_probes_out,  		   sock_i_ino(sp),  		   atomic_read(&sp->sk_refcnt), sp, -		   icsk->icsk_rto, -		   icsk->icsk_ack.ato, +		   jiffies_to_clock_t(icsk->icsk_rto), +		   jiffies_to_clock_t(icsk->icsk_ack.ato),  		   (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,  		   tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh  		   ); diff --git a/net/mac80211/key.c b/net/mac80211/key.c index d4893bd1775..6597c779e35 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -387,6 +387,15 @@ void ieee80211_key_free(struct ieee80211_key *key)  	if (!key)  		return; +	if (!key->sdata) { +		/* The key has not been linked yet, simply free it +		 * and don't Oops */ +		if (key->conf.alg == ALG_CCMP) +			ieee80211_aes_key_free(key->u.ccmp.tfm); +		kfree(key); +		return; +	} +  	spin_lock_irqsave(&key->sdata->local->key_lock, flags);  	__ieee80211_key_free(key);  	spin_unlock_irqrestore(&key->sdata->local->key_lock, flags); diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 0099da5b259..52b2611a6eb 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1534,7 +1534,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,  		}  	}  	list_for_each_entry_rcu(addr6, &iface->addr6_list, list) { -		if (addr6->valid || iter_addr6++ < skip_addr6) +		if (!addr6->valid || iter_addr6++ < skip_addr6)  			continue;  		if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,  					   iface, diff --git a/net/netlink/attr.c b/net/netlink/attr.c index 47bbf45ae5d..2d106cfe1d2 100644 --- a/net/netlink/attr.c +++ b/net/netlink/attr.c @@ -132,6 +132,7 @@ errout:   * @maxtype: maximum attribute type to be expected   * @head: head of attribute stream   * @len: length of attribute stream + * @policy: validation policy   *   * Parses a stream of attributes and stores a pointer to each attribute in   * the tb array accessable via the attribute type. Attributes with a type @@ -194,7 +195,7 @@ struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)  /**   * nla_strlcpy - Copy string attribute payload into a sized buffer   * @dst: where to copy the string to - * @src: attribute to copy the string from + * @nla: attribute to copy the string from   * @dstsize: size of destination buffer   *   * Copies at most dstsize - 1 bytes into the destination buffer. @@ -340,9 +341,9 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)  }  /** - * nla_reserve - reserve room for attribute without header + * nla_reserve_nohdr - reserve room for attribute without header   * @skb: socket buffer to reserve room on - * @len: length of attribute payload + * @attrlen: length of attribute payload   *   * Reserves room for attribute payload without a header.   * diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 82adfe6447d..9437b27ff84 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -106,17 +106,6 @@ config NET_SCH_PRIO  	  To compile this code as a module, choose M here: the  	  module will be called sch_prio. -config NET_SCH_RR -	tristate "Multi Band Round Robin Queuing (RR)" -	select NET_SCH_PRIO -	---help--- -	  Say Y here if you want to use an n-band round robin packet -	  scheduler. - -	  The module uses sch_prio for its framework and is aliased as -	  sch_rr, so it will load sch_prio, although it is referred -	  to using sch_rr. -  config NET_SCH_RED  	tristate "Random Early Detection (RED)"  	---help--- diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index d355e5e47fe..13afa721439 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -468,7 +468,7 @@ struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops)  	return sch;  errout: -	return ERR_PTR(-err); +	return ERR_PTR(err);  }  struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops, diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f98650cc48d..43460a1cb6d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4512,7 +4512,9 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,  	if (copy_from_user(&getaddrs, optval, len))  		return -EFAULT; -	if (getaddrs.addr_num <= 0) return -EINVAL; +	if (getaddrs.addr_num <= 0 || +	    getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr))) +		return -EINVAL;  	/*  	 *  For UDP-style sockets, id specifies the association to query.  	 *  If the id field is set to the value '0' then the locally bound diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index b4280490cf6..70ceb1604ad 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -485,8 +485,8 @@ static int unix_socketpair(struct socket *, struct socket *);  static int unix_accept(struct socket *, struct socket *, int);  static int unix_getname(struct socket *, struct sockaddr *, int *, int);  static unsigned int unix_poll(struct file *, struct socket *, poll_table *); -static unsigned int unix_datagram_poll(struct file *, struct socket *, -				       poll_table *); +static unsigned int unix_dgram_poll(struct file *, struct socket *, +				    poll_table *);  static int unix_ioctl(struct socket *, unsigned int, unsigned long);  static int unix_shutdown(struct socket *, int);  static int unix_stream_sendmsg(struct kiocb *, struct socket *, @@ -532,7 +532,7 @@ static const struct proto_ops unix_dgram_ops = {  	.socketpair =	unix_socketpair,  	.accept =	sock_no_accept,  	.getname =	unix_getname, -	.poll =		unix_datagram_poll, +	.poll =		unix_dgram_poll,  	.ioctl =	unix_ioctl,  	.listen =	sock_no_listen,  	.shutdown =	unix_shutdown, @@ -553,7 +553,7 @@ static const struct proto_ops unix_seqpacket_ops = {  	.socketpair =	unix_socketpair,  	.accept =	unix_accept,  	.getname =	unix_getname, -	.poll =		unix_datagram_poll, +	.poll =		unix_dgram_poll,  	.ioctl =	unix_ioctl,  	.listen =	unix_listen,  	.shutdown =	unix_shutdown, @@ -1992,29 +1992,13 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl  	return mask;  } -static unsigned int unix_datagram_poll(struct file *file, struct socket *sock, -				       poll_table *wait) +static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, +				    poll_table *wait)  { -	struct sock *sk = sock->sk, *peer; -	unsigned int mask; +	struct sock *sk = sock->sk, *other; +	unsigned int mask, writable;  	poll_wait(file, sk->sk_sleep, wait); - -	peer = unix_peer_get(sk); -	if (peer) { -		if (peer != sk) { -			/* -			 * Writability of a connected socket additionally -			 * depends on the state of the receive queue of the -			 * peer. -			 */ -			poll_wait(file, &unix_sk(peer)->peer_wait, wait); -		} else { -			sock_put(peer); -			peer = NULL; -		} -	} -  	mask = 0;  	/* exceptional events? */ @@ -2040,14 +2024,26 @@ static unsigned int unix_datagram_poll(struct file *file, struct socket *sock,  	}  	/* writable? */ -	if (unix_writable(sk) && !(peer && unix_recvq_full(peer))) +	writable = unix_writable(sk); +	if (writable) { +		other = unix_peer_get(sk); +		if (other) { +			if (unix_peer(other) != sk) { +				poll_wait(file, &unix_sk(other)->peer_wait, +					  wait); +				if (unix_recvq_full(other)) +					writable = 0; +			} + +			sock_put(other); +		} +	} + +	if (writable)  		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;  	else  		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); -	if (peer) -		sock_put(peer); -  	return mask;  }  |