Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80116529 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull networking tree from David Miller:

1) ptp_pch driver build broke during this merge window due to missing
   slab.h header, fix from Geery Uytterhoeven.

2) If ipset passes in a bogus hash table size we crash because the size
   is not validated properly.  Compounding this, gcc-4.7 can miscompile
   ipset such that even when the user specifies legitimate parameters
   the tool passes in an out-of-range size to the kernel.

   Fix from Jozsef Kadlecsik.

3) Users have reported that the netdev watchdog can trigger with pch_gbe
   devices, and it turns out this is happening because of races in the
   TX path of the driver leading to the transmitter hanging.  Fix from
   Eric Dumazet, reported and tested by Andy Cress.

4) Novatel USB551L devices match the generic class entries for the cdc
   ethernet USB driver, but they don't work because they have generic
   descriptors and thus need FLAG_WWAN to function properly.

   Add the necessary ID table entry to fix this, from Dan Williams.

5) A recursive locking fix in the USBNET driver added a new problem, in
   that packet list traversal is now racy and we can thus access
   unlinked SKBs and crash.

   Avoid this situation by adding some extra state tracking, from Ming
   Lei.

6) The rtlwifi conversion to asynchronous firmware loading is racy, fix
   by reordering the probe procedure.  From Larry Finger.

   Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=43187

7) Fix regressions with bluetooth keyboards by notifying userland
   properly when the security level changes, from Gustavo Padovan.

8) Bluetooth needs to make sure device connected events are emitted
   before other kinds of events, otherwise userspace will think there is
   no baseband link yet and therefore abort the sockets associated with
   that connection.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  netfilter: ipset: fix hash size checking in kernel
  ptp_pch: Add missing #include <linux/slab.h>
  pch_gbe: fix transmit races
  cdc_ether: add Novatel USB551L device IDs for FLAG_WWAN
  usbnet: fix skb traversing races during unlink(v2)
  Bluetooth: mgmt: Fix device_connected sending order
  Bluetooth: notify userspace of security level change
  rtlwifi: fix for race condition when firmware is cached
parents 568b4455 26a5d3cc
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -584,7 +584,6 @@ struct pch_gbe_hw_stats {
/**
 * struct pch_gbe_adapter - board specific private data structure
 * @stats_lock:	Spinlock structure for status
 * @tx_queue_lock:	Spinlock structure for transmit
 * @ethtool_lock:	Spinlock structure for ethtool
 * @irq_sem:		Semaphore for interrupt
 * @netdev:		Pointer of network device structure
@@ -609,7 +608,6 @@ struct pch_gbe_hw_stats {

struct pch_gbe_adapter {
	spinlock_t stats_lock;
	spinlock_t tx_queue_lock;
	spinlock_t ethtool_lock;
	atomic_t irq_sem;
	struct net_device *netdev;
+11 −14
Original line number Diff line number Diff line
@@ -640,14 +640,11 @@ static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw)
 */
static int pch_gbe_alloc_queues(struct pch_gbe_adapter *adapter)
{
	int size;

	size = (int)sizeof(struct pch_gbe_tx_ring);
	adapter->tx_ring = kzalloc(size, GFP_KERNEL);
	adapter->tx_ring = kzalloc(sizeof(*adapter->tx_ring), GFP_KERNEL);
	if (!adapter->tx_ring)
		return -ENOMEM;
	size = (int)sizeof(struct pch_gbe_rx_ring);
	adapter->rx_ring = kzalloc(size, GFP_KERNEL);

	adapter->rx_ring = kzalloc(sizeof(*adapter->rx_ring), GFP_KERNEL);
	if (!adapter->rx_ring) {
		kfree(adapter->tx_ring);
		return -ENOMEM;
@@ -1162,7 +1159,6 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
	struct sk_buff *tmp_skb;
	unsigned int frame_ctrl;
	unsigned int ring_num;
	unsigned long flags;

	/*-- Set frame control --*/
	frame_ctrl = 0;
@@ -1211,14 +1207,14 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
			}
		}
	}
	spin_lock_irqsave(&tx_ring->tx_lock, flags);

	ring_num = tx_ring->next_to_use;
	if (unlikely((ring_num + 1) == tx_ring->count))
		tx_ring->next_to_use = 0;
	else
		tx_ring->next_to_use = ring_num + 1;

	spin_unlock_irqrestore(&tx_ring->tx_lock, flags);

	buffer_info = &tx_ring->buffer_info[ring_num];
	tmp_skb = buffer_info->skb;

@@ -1518,7 +1514,7 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter,
						&rx_ring->rx_buff_pool_logic,
						GFP_KERNEL);
	if (!rx_ring->rx_buff_pool) {
		pr_err("Unable to allocate memory for the receive poll buffer\n");
		pr_err("Unable to allocate memory for the receive pool buffer\n");
		return -ENOMEM;
	}
	memset(rx_ring->rx_buff_pool, 0, size);
@@ -1637,15 +1633,17 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter,
	pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n",
		 cleaned_count);
	/* Recover from running out of Tx resources in xmit_frame */
	spin_lock(&tx_ring->tx_lock);
	if (unlikely(cleaned && (netif_queue_stopped(adapter->netdev)))) {
		netif_wake_queue(adapter->netdev);
		adapter->stats.tx_restart_count++;
		pr_debug("Tx wake queue\n");
	}
	spin_lock(&adapter->tx_queue_lock);

	tx_ring->next_to_clean = i;
	spin_unlock(&adapter->tx_queue_lock);

	pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean);
	spin_unlock(&tx_ring->tx_lock);
	return cleaned;
}

@@ -2037,7 +2035,6 @@ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter)
		return -ENOMEM;
	}
	spin_lock_init(&adapter->hw.miim_lock);
	spin_lock_init(&adapter->tx_queue_lock);
	spin_lock_init(&adapter->stats_lock);
	spin_lock_init(&adapter->ethtool_lock);
	atomic_set(&adapter->irq_sem, 0);
@@ -2142,10 +2139,10 @@ static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
			 tx_ring->next_to_use, tx_ring->next_to_clean);
		return NETDEV_TX_BUSY;
	}
	spin_unlock_irqrestore(&tx_ring->tx_lock, flags);

	/* CRC,ITAG no support */
	pch_gbe_tx_queue(adapter, tx_ring, skb);
	spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
	return NETDEV_TX_OK;
}

+16 −0
Original line number Diff line number Diff line
@@ -485,6 +485,7 @@ static const struct driver_info wwan_info = {
/*-------------------------------------------------------------------------*/

#define HUAWEI_VENDOR_ID	0x12D1
#define NOVATEL_VENDOR_ID	0x1410

static const struct usb_device_id	products [] = {
/*
@@ -602,6 +603,21 @@ static const struct usb_device_id products [] = {
 * because of bugs/quirks in a given product (like Zaurus, above).
 */
{
	/* Novatel USB551L */
	/* This match must come *before* the generic CDC-ETHER match so that
	 * we get FLAG_WWAN set on the device, since it's descriptors are
	 * generic CDC-ETHER.
	 */
	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
		 | USB_DEVICE_ID_MATCH_PRODUCT
		 | USB_DEVICE_ID_MATCH_INT_INFO,
	.idVendor               = NOVATEL_VENDOR_ID,
	.idProduct		= 0xB001,
	.bInterfaceClass	= USB_CLASS_COMM,
	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET,
	.bInterfaceProtocol	= USB_CDC_PROTO_NONE,
	.driver_info = (unsigned long)&wwan_info,
}, {
	USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
			USB_CDC_PROTO_NONE),
	.driver_info = (unsigned long) &cdc_info,
+38 −16
Original line number Diff line number Diff line
@@ -282,17 +282,32 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
}
EXPORT_SYMBOL_GPL(usbnet_change_mtu);

/* The caller must hold list->lock */
static void __usbnet_queue_skb(struct sk_buff_head *list,
			struct sk_buff *newsk, enum skb_state state)
{
	struct skb_data *entry = (struct skb_data *) newsk->cb;

	__skb_queue_tail(list, newsk);
	entry->state = state;
}

/*-------------------------------------------------------------------------*/

/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
 * completion callbacks.  2.5 should have fixed those bugs...
 */

static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list)
static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
		struct sk_buff_head *list, enum skb_state state)
{
	unsigned long		flags;
	enum skb_state 		old_state;
	struct skb_data *entry = (struct skb_data *) skb->cb;

	spin_lock_irqsave(&list->lock, flags);
	old_state = entry->state;
	entry->state = state;
	__skb_unlink(skb, list);
	spin_unlock(&list->lock);
	spin_lock(&dev->done.lock);
@@ -300,6 +315,7 @@ static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_hea
	if (dev->done.qlen == 1)
		tasklet_schedule(&dev->bh);
	spin_unlock_irqrestore(&dev->done.lock, flags);
	return old_state;
}

/* some work can't be done in tasklets, so we use keventd
@@ -340,7 +356,6 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
	entry = (struct skb_data *) skb->cb;
	entry->urb = urb;
	entry->dev = dev;
	entry->state = rx_start;
	entry->length = 0;

	usb_fill_bulk_urb (urb, dev->udev, dev->in,
@@ -372,7 +387,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
			tasklet_schedule (&dev->bh);
			break;
		case 0:
			__skb_queue_tail (&dev->rxq, skb);
			__usbnet_queue_skb(&dev->rxq, skb, rx_start);
		}
	} else {
		netif_dbg(dev, ifdown, dev->net, "rx: stopped\n");
@@ -423,16 +438,17 @@ static void rx_complete (struct urb *urb)
	struct skb_data		*entry = (struct skb_data *) skb->cb;
	struct usbnet		*dev = entry->dev;
	int			urb_status = urb->status;
	enum skb_state		state;

	skb_put (skb, urb->actual_length);
	entry->state = rx_done;
	state = rx_done;
	entry->urb = NULL;

	switch (urb_status) {
	/* success */
	case 0:
		if (skb->len < dev->net->hard_header_len) {
			entry->state = rx_cleanup;
			state = rx_cleanup;
			dev->net->stats.rx_errors++;
			dev->net->stats.rx_length_errors++;
			netif_dbg(dev, rx_err, dev->net,
@@ -471,7 +487,7 @@ static void rx_complete (struct urb *urb)
				  "rx throttle %d\n", urb_status);
		}
block:
		entry->state = rx_cleanup;
		state = rx_cleanup;
		entry->urb = urb;
		urb = NULL;
		break;
@@ -482,17 +498,18 @@ static void rx_complete (struct urb *urb)
		// FALLTHROUGH

	default:
		entry->state = rx_cleanup;
		state = rx_cleanup;
		dev->net->stats.rx_errors++;
		netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status);
		break;
	}

	defer_bh(dev, skb, &dev->rxq);
	state = defer_bh(dev, skb, &dev->rxq, state);

	if (urb) {
		if (netif_running (dev->net) &&
		    !test_bit (EVENT_RX_HALT, &dev->flags)) {
		    !test_bit (EVENT_RX_HALT, &dev->flags) &&
		    state != unlink_start) {
			rx_submit (dev, urb, GFP_ATOMIC);
			usb_mark_last_busy(dev->udev);
			return;
@@ -579,16 +596,23 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq);
static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
{
	unsigned long		flags;
	struct sk_buff		*skb, *skbnext;
	struct sk_buff		*skb;
	int			count = 0;

	spin_lock_irqsave (&q->lock, flags);
	skb_queue_walk_safe(q, skb, skbnext) {
	while (!skb_queue_empty(q)) {
		struct skb_data		*entry;
		struct urb		*urb;
		int			retval;

		skb_queue_walk(q, skb) {
			entry = (struct skb_data *) skb->cb;
			if (entry->state != unlink_start)
				goto found;
		}
		break;
found:
		entry->state = unlink_start;
		urb = entry->urb;

		/*
@@ -1039,8 +1063,7 @@ static void tx_complete (struct urb *urb)
	}

	usb_autopm_put_interface_async(dev->intf);
	entry->state = tx_done;
	defer_bh(dev, skb, &dev->txq);
	(void) defer_bh(dev, skb, &dev->txq, tx_done);
}

/*-------------------------------------------------------------------------*/
@@ -1096,7 +1119,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
	entry = (struct skb_data *) skb->cb;
	entry->urb = urb;
	entry->dev = dev;
	entry->state = tx_start;
	entry->length = length;

	usb_fill_bulk_urb (urb, dev->udev, dev->out,
@@ -1155,7 +1177,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
		break;
	case 0:
		net->trans_start = jiffies;
		__skb_queue_tail (&dev->txq, skb);
		__usbnet_queue_skb(&dev->txq, skb, tx_start);
		if (dev->txq.qlen >= TX_QLEN (dev))
			netif_stop_queue (net);
	}
+8 −8
Original line number Diff line number Diff line
@@ -1851,14 +1851,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
	/*like read eeprom and so on */
	rtlpriv->cfg->ops->read_eeprom_info(hw);

	if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
		err = -ENODEV;
		goto fail3;
	}

	rtlpriv->cfg->ops->init_sw_leds(hw);

	/*aspm */
	rtl_pci_init_aspm(hw);

@@ -1877,6 +1869,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
		goto fail3;
	}

	if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
		err = -ENODEV;
		goto fail3;
	}

	rtlpriv->cfg->ops->init_sw_leds(hw);

	err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group);
	if (err) {
		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Loading