Commit 80116529 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

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
...@@ -584,7 +584,6 @@ struct pch_gbe_hw_stats { ...@@ -584,7 +584,6 @@ struct pch_gbe_hw_stats {
/** /**
* struct pch_gbe_adapter - board specific private data structure * struct pch_gbe_adapter - board specific private data structure
* @stats_lock: Spinlock structure for status * @stats_lock: Spinlock structure for status
* @tx_queue_lock: Spinlock structure for transmit
* @ethtool_lock: Spinlock structure for ethtool * @ethtool_lock: Spinlock structure for ethtool
* @irq_sem: Semaphore for interrupt * @irq_sem: Semaphore for interrupt
* @netdev: Pointer of network device structure * @netdev: Pointer of network device structure
...@@ -609,7 +608,6 @@ struct pch_gbe_hw_stats { ...@@ -609,7 +608,6 @@ struct pch_gbe_hw_stats {
struct pch_gbe_adapter { struct pch_gbe_adapter {
spinlock_t stats_lock; spinlock_t stats_lock;
spinlock_t tx_queue_lock;
spinlock_t ethtool_lock; spinlock_t ethtool_lock;
atomic_t irq_sem; atomic_t irq_sem;
struct net_device *netdev; struct net_device *netdev;
......
...@@ -640,14 +640,11 @@ static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw) ...@@ -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) static int pch_gbe_alloc_queues(struct pch_gbe_adapter *adapter)
{ {
int size; adapter->tx_ring = kzalloc(sizeof(*adapter->tx_ring), GFP_KERNEL);
size = (int)sizeof(struct pch_gbe_tx_ring);
adapter->tx_ring = kzalloc(size, GFP_KERNEL);
if (!adapter->tx_ring) if (!adapter->tx_ring)
return -ENOMEM; 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) { if (!adapter->rx_ring) {
kfree(adapter->tx_ring); kfree(adapter->tx_ring);
return -ENOMEM; return -ENOMEM;
...@@ -1162,7 +1159,6 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, ...@@ -1162,7 +1159,6 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
struct sk_buff *tmp_skb; struct sk_buff *tmp_skb;
unsigned int frame_ctrl; unsigned int frame_ctrl;
unsigned int ring_num; unsigned int ring_num;
unsigned long flags;
/*-- Set frame control --*/ /*-- Set frame control --*/
frame_ctrl = 0; frame_ctrl = 0;
...@@ -1211,14 +1207,14 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, ...@@ -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; ring_num = tx_ring->next_to_use;
if (unlikely((ring_num + 1) == tx_ring->count)) if (unlikely((ring_num + 1) == tx_ring->count))
tx_ring->next_to_use = 0; tx_ring->next_to_use = 0;
else else
tx_ring->next_to_use = ring_num + 1; tx_ring->next_to_use = ring_num + 1;
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
buffer_info = &tx_ring->buffer_info[ring_num]; buffer_info = &tx_ring->buffer_info[ring_num];
tmp_skb = buffer_info->skb; tmp_skb = buffer_info->skb;
...@@ -1518,7 +1514,7 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter, ...@@ -1518,7 +1514,7 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter,
&rx_ring->rx_buff_pool_logic, &rx_ring->rx_buff_pool_logic,
GFP_KERNEL); GFP_KERNEL);
if (!rx_ring->rx_buff_pool) { 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; return -ENOMEM;
} }
memset(rx_ring->rx_buff_pool, 0, size); memset(rx_ring->rx_buff_pool, 0, size);
...@@ -1637,15 +1633,17 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, ...@@ -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", pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n",
cleaned_count); cleaned_count);
/* Recover from running out of Tx resources in xmit_frame */ /* Recover from running out of Tx resources in xmit_frame */
spin_lock(&tx_ring->tx_lock);
if (unlikely(cleaned && (netif_queue_stopped(adapter->netdev)))) { if (unlikely(cleaned && (netif_queue_stopped(adapter->netdev)))) {
netif_wake_queue(adapter->netdev); netif_wake_queue(adapter->netdev);
adapter->stats.tx_restart_count++; adapter->stats.tx_restart_count++;
pr_debug("Tx wake queue\n"); pr_debug("Tx wake queue\n");
} }
spin_lock(&adapter->tx_queue_lock);
tx_ring->next_to_clean = i; tx_ring->next_to_clean = i;
spin_unlock(&adapter->tx_queue_lock);
pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean); pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean);
spin_unlock(&tx_ring->tx_lock);
return cleaned; return cleaned;
} }
...@@ -2037,7 +2035,6 @@ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter) ...@@ -2037,7 +2035,6 @@ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter)
return -ENOMEM; return -ENOMEM;
} }
spin_lock_init(&adapter->hw.miim_lock); spin_lock_init(&adapter->hw.miim_lock);
spin_lock_init(&adapter->tx_queue_lock);
spin_lock_init(&adapter->stats_lock); spin_lock_init(&adapter->stats_lock);
spin_lock_init(&adapter->ethtool_lock); spin_lock_init(&adapter->ethtool_lock);
atomic_set(&adapter->irq_sem, 0); atomic_set(&adapter->irq_sem, 0);
...@@ -2142,10 +2139,10 @@ static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -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); tx_ring->next_to_use, tx_ring->next_to_clean);
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
/* CRC,ITAG no support */ /* CRC,ITAG no support */
pch_gbe_tx_queue(adapter, tx_ring, skb); pch_gbe_tx_queue(adapter, tx_ring, skb);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
......
...@@ -485,6 +485,7 @@ static const struct driver_info wwan_info = { ...@@ -485,6 +485,7 @@ static const struct driver_info wwan_info = {
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#define HUAWEI_VENDOR_ID 0x12D1 #define HUAWEI_VENDOR_ID 0x12D1
#define NOVATEL_VENDOR_ID 0x1410
static const struct usb_device_id products [] = { static const struct usb_device_id products [] = {
/* /*
...@@ -602,6 +603,21 @@ 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). * 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_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
USB_CDC_PROTO_NONE), USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info, .driver_info = (unsigned long) &cdc_info,
......
...@@ -282,17 +282,32 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu) ...@@ -282,17 +282,32 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
} }
EXPORT_SYMBOL_GPL(usbnet_change_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 /* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
* completion callbacks. 2.5 should have fixed those bugs... * 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; unsigned long flags;
enum skb_state old_state;
struct skb_data *entry = (struct skb_data *) skb->cb;
spin_lock_irqsave(&list->lock, flags); spin_lock_irqsave(&list->lock, flags);
old_state = entry->state;
entry->state = state;
__skb_unlink(skb, list); __skb_unlink(skb, list);
spin_unlock(&list->lock); spin_unlock(&list->lock);
spin_lock(&dev->done.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 ...@@ -300,6 +315,7 @@ static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_hea
if (dev->done.qlen == 1) if (dev->done.qlen == 1)
tasklet_schedule(&dev->bh); tasklet_schedule(&dev->bh);
spin_unlock_irqrestore(&dev->done.lock, flags); spin_unlock_irqrestore(&dev->done.lock, flags);
return old_state;
} }
/* some work can't be done in tasklets, so we use keventd /* 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) ...@@ -340,7 +356,6 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
entry = (struct skb_data *) skb->cb; entry = (struct skb_data *) skb->cb;
entry->urb = urb; entry->urb = urb;
entry->dev = dev; entry->dev = dev;
entry->state = rx_start;
entry->length = 0; entry->length = 0;
usb_fill_bulk_urb (urb, dev->udev, dev->in, 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) ...@@ -372,7 +387,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
tasklet_schedule (&dev->bh); tasklet_schedule (&dev->bh);
break; break;
case 0: case 0:
__skb_queue_tail (&dev->rxq, skb); __usbnet_queue_skb(&dev->rxq, skb, rx_start);
} }
} else { } else {
netif_dbg(dev, ifdown, dev->net, "rx: stopped\n"); netif_dbg(dev, ifdown, dev->net, "rx: stopped\n");
...@@ -423,16 +438,17 @@ static void rx_complete (struct urb *urb) ...@@ -423,16 +438,17 @@ static void rx_complete (struct urb *urb)
struct skb_data *entry = (struct skb_data *) skb->cb; struct skb_data *entry = (struct skb_data *) skb->cb;
struct usbnet *dev = entry->dev; struct usbnet *dev = entry->dev;
int urb_status = urb->status; int urb_status = urb->status;
enum skb_state state;
skb_put (skb, urb->actual_length); skb_put (skb, urb->actual_length);
entry->state = rx_done; state = rx_done;
entry->urb = NULL; entry->urb = NULL;
switch (urb_status) { switch (urb_status) {
/* success */ /* success */
case 0: case 0:
if (skb->len < dev->net->hard_header_len) { if (skb->len < dev->net->hard_header_len) {
entry->state = rx_cleanup; state = rx_cleanup;
dev->net->stats.rx_errors++; dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++; dev->net->stats.rx_length_errors++;
netif_dbg(dev, rx_err, dev->net, netif_dbg(dev, rx_err, dev->net,
...@@ -471,7 +487,7 @@ static void rx_complete (struct urb *urb) ...@@ -471,7 +487,7 @@ static void rx_complete (struct urb *urb)
"rx throttle %d\n", urb_status); "rx throttle %d\n", urb_status);
} }
block: block:
entry->state = rx_cleanup; state = rx_cleanup;
entry->urb = urb; entry->urb = urb;
urb = NULL; urb = NULL;
break; break;
...@@ -482,17 +498,18 @@ static void rx_complete (struct urb *urb) ...@@ -482,17 +498,18 @@ static void rx_complete (struct urb *urb)
// FALLTHROUGH // FALLTHROUGH
default: default:
entry->state = rx_cleanup; state = rx_cleanup;
dev->net->stats.rx_errors++; dev->net->stats.rx_errors++;
netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status); netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status);
break; break;
} }
defer_bh(dev, skb, &dev->rxq); state = defer_bh(dev, skb, &dev->rxq, state);
if (urb) { if (urb) {
if (netif_running (dev->net) && 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); rx_submit (dev, urb, GFP_ATOMIC);
usb_mark_last_busy(dev->udev); usb_mark_last_busy(dev->udev);
return; return;
...@@ -579,16 +596,23 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq); ...@@ -579,16 +596,23 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq);
static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
{ {
unsigned long flags; unsigned long flags;
struct sk_buff *skb, *skbnext; struct sk_buff *skb;
int count = 0; int count = 0;
spin_lock_irqsave (&q->lock, flags); spin_lock_irqsave (&q->lock, flags);
skb_queue_walk_safe(q, skb, skbnext) { while (!skb_queue_empty(q)) {
struct skb_data *entry; struct skb_data *entry;
struct urb *urb; struct urb *urb;
int retval; int retval;
entry = (struct skb_data *) skb->cb; 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; urb = entry->urb;
/* /*
...@@ -1039,8 +1063,7 @@ static void tx_complete (struct urb *urb) ...@@ -1039,8 +1063,7 @@ static void tx_complete (struct urb *urb)
} }
usb_autopm_put_interface_async(dev->intf); usb_autopm_put_interface_async(dev->intf);
entry->state = tx_done; (void) defer_bh(dev, skb, &dev->txq, tx_done);
defer_bh(dev, skb, &dev->txq);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -1096,7 +1119,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, ...@@ -1096,7 +1119,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
entry = (struct skb_data *) skb->cb; entry = (struct skb_data *) skb->cb;
entry->urb = urb; entry->urb = urb;
entry->dev = dev; entry->dev = dev;
entry->state = tx_start;
entry->length = length; entry->length = length;
usb_fill_bulk_urb (urb, dev->udev, dev->out, usb_fill_bulk_urb (urb, dev->udev, dev->out,
...@@ -1155,7 +1177,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, ...@@ -1155,7 +1177,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
break; break;
case 0: case 0:
net->trans_start = jiffies; 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)) if (dev->txq.qlen >= TX_QLEN (dev))
netif_stop_queue (net); netif_stop_queue (net);
} }
......
...@@ -1851,14 +1851,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, ...@@ -1851,14 +1851,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
/*like read eeprom and so on */ /*like read eeprom and so on */
rtlpriv->cfg->ops->read_eeprom_info(hw); 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 */ /*aspm */
rtl_pci_init_aspm(hw); rtl_pci_init_aspm(hw);
...@@ -1877,6 +1869,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, ...@@ -1877,6 +1869,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
goto fail3; 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); err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group);
if (err) { if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
......
...@@ -971,11 +971,6 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, ...@@ -971,11 +971,6 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
rtlpriv->cfg->ops->read_chip_version(hw); rtlpriv->cfg->ops->read_chip_version(hw);
/*like read eeprom and so on */ /*like read eeprom and so on */
rtlpriv->cfg->ops->read_eeprom_info(hw); 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");
goto error_out;
}
rtlpriv->cfg->ops->init_sw_leds(hw);
err = _rtl_usb_init(hw); err = _rtl_usb_init(hw);
if (err) if (err)
goto error_out; goto error_out;
...@@ -987,6 +982,11 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, ...@@ -987,6 +982,11 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
"Can't allocate sw for mac80211\n"); "Can't allocate sw for mac80211\n");
goto error_out; goto error_out;
} }
if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
goto error_out;
}
rtlpriv->cfg->ops->init_sw_leds(hw);
return 0; return 0;
error_out: error_out:
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/ptp_clock_kernel.h> #include <linux/ptp_clock_kernel.h>
#include <linux/slab.h>
#define STATION_ADDR_LEN 20 #define STATION_ADDR_LEN 20
#define PCI_DEVICE_ID_PCH_1588 0x8819 #define PCI_DEVICE_ID_PCH_1588 0x8819
......
...@@ -99,6 +99,22 @@ struct ip_set_hash { ...@@ -99,6 +99,22 @@ struct ip_set_hash {
#endif #endif
}; };
static size_t
htable_size(u8 hbits)
{
size_t hsize;
/* We must fit both into u32 in jhash and size_t */
if (hbits > 31)
return 0;
hsize = jhash_size(hbits);
if ((((size_t)-1) - sizeof(struct htable))/sizeof(struct hbucket)
< hsize)
return 0;
return hsize * sizeof(struct hbucket) + sizeof(struct htable);
}
/* Compute htable_bits from the user input parameter hashsize */ /* Compute htable_bits from the user input parameter hashsize */
static u8 static u8
htable_bits(u32 hashsize) htable_bits(u32 hashsize)
......
...@@ -191,7 +191,8 @@ extern void usbnet_cdc_status(struct usbnet *, struct urb *); ...@@ -191,7 +191,8 @@ extern void usbnet_cdc_status(struct usbnet *, struct urb *);
enum skb_state { enum skb_state {
illegal = 0, illegal = 0,
tx_start, tx_done, tx_start, tx_done,
rx_start, rx_done, rx_cleanup rx_start, rx_done, rx_cleanup,
unlink_start
}; };
struct skb_data { /* skb->cb is one of these */ struct skb_data { /* skb->cb is one of these */
......
...@@ -191,6 +191,7 @@ struct bt_sock { ...@@ -191,6 +191,7 @@ struct bt_sock {
struct list_head accept_q; struct list_head accept_q;
struct sock *parent; struct sock *parent;
u32 defer_setup; u32 defer_setup;
bool suspended;
}; };
struct bt_sock_list { struct bt_sock_list {
......
...@@ -450,7 +450,7 @@ unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wa ...@@ -450,7 +450,7 @@ unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wa
sk->sk_state == BT_CONFIG) sk->sk_state == BT_CONFIG)
return mask; return mask;
if (sock_writeable(sk)) if (!bt_sk(sk)->suspended && sock_writeable(sk))
mask |= POLLOUT | POLLWRNORM | POLLWRBAND; mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
else else
set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
......
...@@ -2784,6 +2784,14 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2784,6 +2784,14 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
if (conn) { if (conn) {
hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
mgmt_device_connected(hdev, &conn->dst, conn->type,
conn->dst_type, 0, NULL, 0,
conn->dev_class);
hci_dev_unlock(hdev);
/* Send to upper protocol */ /* Send to upper protocol */
l2cap_recv_acldata(conn, skb, flags); l2cap_recv_acldata(conn, skb, flags);
return; return;
......
...@@ -2039,6 +2039,12 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff * ...@@ -2039,6 +2039,12 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
if (ev->status && conn->state == BT_CONNECTED) {
hci_acl_disconn(conn, 0x13);
hci_conn_put(conn);
goto unlock;
}
if (conn->state == BT_CONFIG) { if (conn->state == BT_CONFIG) {
if (!ev->status) if (!ev->status)
conn->state = BT_CONNECTED; conn->state = BT_CONNECTED;
...@@ -2049,6 +2055,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff * ...@@ -2049,6 +2055,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
hci_encrypt_cfm(conn, ev->status, ev->encrypt); hci_encrypt_cfm(conn, ev->status, ev->encrypt);
} }
unlock:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
...@@ -2102,7 +2109,7 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff ...@@ -2102,7 +2109,7 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
goto unlock; goto unlock;
} }
if (!ev->status) { if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
struct hci_cp_remote_name_req cp; struct hci_cp_remote_name_req cp;
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst); bacpy(&cp.bdaddr, &conn->dst);
...@@ -2871,7 +2878,7 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b ...@@ -2871,7 +2878,7 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
if (conn->state != BT_CONFIG) if (conn->state != BT_CONFIG)
goto unlock; goto unlock;
if (!ev->status) { if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
struct hci_cp_remote_name_req cp; struct hci_cp_remote_name_req cp;
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst); bacpy(&cp.bdaddr, &conn->dst);
......
...@@ -4589,6 +4589,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) ...@@ -4589,6 +4589,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (!status && (chan->state == BT_CONNECTED || if (!status && (chan->state == BT_CONNECTED ||
chan->state == BT_CONFIG)) { chan->state == BT_CONFIG)) {
struct sock *sk = chan->sk;
bt_sk(sk)->suspended = false;
sk->sk_state_change(sk);
l2cap_check_encryption(chan, encrypt); l2cap_check_encryption(chan, encrypt);
l2cap_chan_unlock(chan); l2cap_chan_unlock(chan);
continue; continue;
......
...@@ -592,10 +592,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch ...@@ -592,10 +592,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
sk->sk_state = BT_CONFIG; sk->sk_state = BT_CONFIG;
chan->state = BT_CONFIG; chan->state = BT_CONFIG;
/* or for ACL link, under defer_setup time */ /* or for ACL link */
} else if (sk->sk_state == BT_CONNECT2 && } else if ((sk->sk_state == BT_CONNECT2 &&
bt_sk(sk)->defer_setup) { bt_sk(sk)->defer_setup) ||
err = l2cap_chan_check_security(chan); sk->sk_state == BT_CONNECTED) {
if (!l2cap_chan_check_security(chan))
bt_sk(sk)->suspended = true;
else
sk->sk_state_change(sk);
} else { } else {
err = -EINVAL; err = -EINVAL;
} }
......
...@@ -364,6 +364,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -364,6 +364,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
{ {
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
u8 netmask, hbits; u8 netmask, hbits;
size_t hsize;
struct ip_set_hash *h; struct ip_set_hash *h;
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
...@@ -405,9 +406,12 @@ hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -405,9 +406,12 @@ hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->timeout = IPSET_NO_TIMEOUT; h->timeout = IPSET_NO_TIMEOUT;
hbits = htable_bits(hashsize); hbits = htable_bits(hashsize);
h->table = ip_set_alloc( hsize = htable_size(hbits);
sizeof(struct htable) if (hsize == 0) {
+ jhash_size(hbits) * sizeof(struct hbucket)); kfree(h);
return -ENOMEM;
}
h->table = ip_set_alloc(hsize);
if (!h->table) { if (!h->table) {
kfree(h); kfree(h);
return -ENOMEM; return -ENOMEM;
......
...@@ -449,6 +449,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -449,6 +449,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
struct ip_set_hash *h; struct ip_set_hash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
u8 hbits; u8 hbits;
size_t hsize;
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
return -IPSET_ERR_INVALID_FAMILY; return -IPSET_ERR_INVALID_FAMILY;
...@@ -476,9 +477,12 @@ hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -476,9 +477,12 @@ hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->timeout = IPSET_NO_TIMEOUT; h->timeout = IPSET_NO_TIMEOUT;
hbits = htable_bits(hashsize); hbits = htable_bits(hashsize);
h->table = ip_set_alloc( hsize = htable_size(hbits);
sizeof(struct htable) if (hsize == 0) {
+ jhash_size(hbits) * sizeof(struct hbucket)); kfree(h);
return -ENOMEM;
}
h->table = ip_set_alloc(hsize);
if (!h->table) { if (!h->table) {
kfree(h); kfree(h);
return -ENOMEM; return -ENOMEM;
......
...@@ -467,6 +467,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -467,6 +467,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
struct ip_set_hash *h; struct ip_set_hash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
u8 hbits; u8 hbits;
size_t hsize;
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
return -IPSET_ERR_INVALID_FAMILY; return -IPSET_ERR_INVALID_FAMILY;
...@@ -494,9 +495,12 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -494,9 +495,12 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->timeout = IPSET_NO_TIMEOUT; h->timeout = IPSET_NO_TIMEOUT;
hbits = htable_bits(hashsize); hbits = htable_bits(hashsize);
h->table = ip_set_alloc( hsize = htable_size(hbits);
sizeof(struct htable) if (hsize == 0) {
+ jhash_size(hbits) * sizeof(struct hbucket)); kfree(h);
return -ENOMEM;
}
h->table = ip_set_alloc(hsize);
if (!h->table) { if (!h->table) {
kfree(h); kfree(h);
return -ENOMEM; return -ENOMEM;
......
...@@ -616,6 +616,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -616,6 +616,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
struct ip_set_hash *h; struct ip_set_hash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
u8 hbits; u8 hbits;
size_t hsize;
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
return -IPSET_ERR_INVALID_FAMILY; return -IPSET_ERR_INVALID_FAMILY;
...@@ -645,9 +646,12 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -645,9 +646,12 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->timeout = IPSET_NO_TIMEOUT; h->timeout = IPSET_NO_TIMEOUT;
hbits = htable_bits(hashsize); hbits = htable_bits(hashsize);
h->table = ip_set_alloc( hsize = htable_size(hbits);
sizeof(struct htable) if (hsize == 0) {
+ jhash_size(hbits) * sizeof(struct hbucket)); kfree(h);
return -ENOMEM;
}
h->table = ip_set_alloc(hsize);
if (!h->table) { if (!h->table) {
kfree(h); kfree(h);
return -ENOMEM; return -ENOMEM;
......
...@@ -460,6 +460,7 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -460,6 +460,7 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
struct ip_set_hash *h; struct ip_set_hash *h;
u8 hbits; u8 hbits;
size_t hsize;
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
return -IPSET_ERR_INVALID_FAMILY; return -IPSET_ERR_INVALID_FAMILY;
...@@ -489,9 +490,12 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -489,9 +490,12 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->timeout = IPSET_NO_TIMEOUT; h->timeout = IPSET_NO_TIMEOUT;
hbits = htable_bits(hashsize); hbits = htable_bits(hashsize);
h->table = ip_set_alloc( hsize = htable_size(hbits);
sizeof(struct htable) if (hsize == 0) {
+ jhash_size(hbits) * sizeof(struct hbucket)); kfree(h);
return -ENOMEM;
}
h->table = ip_set_alloc(hsize);
if (!h->table) { if (!h->table) {
kfree(h); kfree(h);
return -ENOMEM; return -ENOMEM;
......
...@@ -722,6 +722,7 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -722,6 +722,7 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
struct ip_set_hash *h; struct ip_set_hash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
u8 hbits; u8 hbits;
size_t hsize;
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
return -IPSET_ERR_INVALID_FAMILY; return -IPSET_ERR_INVALID_FAMILY;
...@@ -752,9 +753,12 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -752,9 +753,12 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->ahash_max = AHASH_MAX_SIZE; h->ahash_max = AHASH_MAX_SIZE;
hbits = htable_bits(hashsize); hbits = htable_bits(hashsize);
h->table = ip_set_alloc( hsize = htable_size(hbits);
sizeof(struct htable) if (hsize == 0) {
+ jhash_size(hbits) * sizeof(struct hbucket)); kfree(h);
return -ENOMEM;
}
h->table = ip_set_alloc(hsize);
if (!h->table) { if (!h->table) {
kfree(h); kfree(h);
return -ENOMEM; return -ENOMEM;
......
...@@ -572,6 +572,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -572,6 +572,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
struct ip_set_hash *h; struct ip_set_hash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
u8 hbits; u8 hbits;
size_t hsize;
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
return -IPSET_ERR_INVALID_FAMILY; return -IPSET_ERR_INVALID_FAMILY;
...@@ -601,9 +602,12 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) ...@@ -601,9 +602,12 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->timeout = IPSET_NO_TIMEOUT; h->timeout = IPSET_NO_TIMEOUT;
hbits = htable_bits(hashsize); hbits = htable_bits(hashsize);
h->table = ip_set_alloc( hsize = htable_size(hbits);
sizeof(struct htable) if (hsize == 0) {
+ jhash_size(hbits) * sizeof(struct hbucket)); kfree(h);
return -ENOMEM;
}
h->table = ip_set_alloc(hsize);
if (!h->table) { if (!h->table) {
kfree(h); kfree(h);
return -ENOMEM; return -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment