Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorDavid S. Miller <davem@davemloft.net>
Fri, 29 Jun 2012 00:37:00 +0000 (17:37 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 29 Jun 2012 00:37:00 +0000 (17:37 -0700)
Conflicts:
drivers/net/caif/caif_hsi.c
drivers/net/usb/qmi_wwan.c

The qmi_wwan merge was trivial.

The caif_hsi.c, on the other hand, was not.  It's a conflict between
1c385f1fdf6f9c66d982802cd74349c040980b50 ("caif-hsi: Replace platform
device with ops structure.") in the net-next tree and commit
39abbaef19cd0a30be93794aa4773c779c3eb1f3 ("caif-hsi: Postpone init of
HIS until open()") in the net tree.

I did my best with that one and will ask Sjur to check it out.

Signed-off-by: David S. Miller <davem@davemloft.net>
19 files changed:
1  2 
MAINTAINERS
drivers/net/caif/caif_hsi.c
drivers/net/can/flexcan.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/usb/qmi_wwan.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/mwifiex/11n_rxreorder.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/staging/gdm72xx/netlink_k.c
net/core/dev.c
net/ipv6/tcp_ipv6.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac802154/tx.c

diff --cc MAINTAINERS
Simple merge
@@@ -678,8 -693,8 +678,6 @@@ static void cfhsi_rx_done(struct cfhsi 
                         */
                        memcpy(rx_buf, (u8 *)piggy_desc,
                                        CFHSI_DESC_SHORT_SZ);
-                       /* Mark no embedded frame here */
-                       piggy_desc->offset = 0;
 -                      if (desc_pld_len == -EPROTO)
 -                              goto out_of_sync;
                }
        }
  
@@@ -1131,7 -1149,43 +1131,51 @@@ static void cfhsi_setup(struct net_devi
        cfhsi->cfdev.use_stx = false;
        cfhsi->cfdev.use_fcs = false;
        cfhsi->ndev = dev;
-       cfhsi->cfg = hsi_default_config;
+ }
+ int cfhsi_probe(struct platform_device *pdev)
+ {
++      struct cfhsi_ops *(*get_ops)(void);
+       struct cfhsi *cfhsi = NULL;
+       struct net_device *ndev;
 -
+       int res;
+       ndev = alloc_netdev(sizeof(struct cfhsi), "cfhsi%d", cfhsi_setup);
+       if (!ndev)
+               return -ENODEV;
+       cfhsi = netdev_priv(ndev);
+       cfhsi->ndev = ndev;
+       cfhsi->pdev = pdev;
++      get_ops = symbol_get(cfhsi_get_ops);
++      if (!get_ops) {
++              pr_err("%s: failed to get the cfhsi_ops\n", __func__);
++              return -ENODEV;
++      }
++
+       /* Assign the HSI device. */
 -      cfhsi->dev = pdev->dev.platform_data;
++      cfhsi->ops = (*get_ops)();
++      if (!cfhsi->ops) {
++              pr_err("%s: failed to get the cfhsi_ops\n", __func__);
++              goto err;
++      }
+       /* Assign the driver to this HSI device. */
 -      cfhsi->dev->drv = &cfhsi->drv;
 -
 -      /* Register network device. */
 -      res = register_netdev(ndev);
++      cfhsi->ops->cb_ops = &cfhsi->cb_ops;
++      res = register_netdevice(ndev);
+       if (res) {
+               dev_err(&ndev->dev, "%s: Registration error: %d.\n",
+                       __func__, res);
+               free_netdev(ndev);
 -              return -ENODEV;
+       }
+       /* Add CAIF HSI device to list. */
 -      spin_lock(&cfhsi_list_lock);
+       list_add_tail(&cfhsi->list, &cfhsi_list);
 -      spin_unlock(&cfhsi_list_lock);
+       return res;
++err:
++      symbol_put(cfhsi_get_ops);
++      return -ENODEV;
  }
  
  static int cfhsi_open(struct net_device *ndev)
@@@ -1314,169 -1374,79 +1358,143 @@@ static const struct net_device_ops cfhs
        .ndo_start_xmit = cfhsi_xmit
  };
  
 -int cfhsi_remove(struct platform_device *pdev)
 +static void cfhsi_netlink_parms(struct nlattr *data[], struct cfhsi *cfhsi)
  {
 -      struct list_head *list_node;
 -      struct list_head *n;
 -      struct cfhsi *cfhsi = NULL;
 -      struct cfhsi_dev *dev;
 +      int i;
  
 -      dev = (struct cfhsi_dev *)pdev->dev.platform_data;
 -      spin_lock(&cfhsi_list_lock);
 -      list_for_each_safe(list_node, n, &cfhsi_list) {
 -              cfhsi = list_entry(list_node, struct cfhsi, list);
 -              /* Find the corresponding device. */
 -              if (cfhsi->dev == dev) {
 -                      /* Remove from list. */
 -                      list_del(list_node);
 -                      spin_unlock(&cfhsi_list_lock);
 -                      return 0;
 -              }
 +      if (!data) {
 +              pr_debug("no params data found\n");
 +              return;
        }
 -      spin_unlock(&cfhsi_list_lock);
 -      return -ENODEV;
 +
 +      i = __IFLA_CAIF_HSI_INACTIVITY_TOUT;
 +      /*
 +       * Inactivity timeout in millisecs. Lowest possible value is 1,
 +       * and highest possible is NEXT_TIMER_MAX_DELTA.
 +       */
 +      if (data[i]) {
 +              u32 inactivity_timeout = nla_get_u32(data[i]);
 +              /* Pre-calculate inactivity timeout. */
 +              cfhsi->cfg.inactivity_timeout = inactivity_timeout * HZ / 1000;
 +              if (cfhsi->cfg.inactivity_timeout == 0)
 +                      cfhsi->cfg.inactivity_timeout = 1;
 +              else if (cfhsi->cfg.inactivity_timeout > NEXT_TIMER_MAX_DELTA)
 +                      cfhsi->cfg.inactivity_timeout = NEXT_TIMER_MAX_DELTA;
 +      }
 +
 +      i = __IFLA_CAIF_HSI_AGGREGATION_TOUT;
 +      if (data[i])
 +              cfhsi->cfg.aggregation_timeout = nla_get_u32(data[i]);
 +
 +      i = __IFLA_CAIF_HSI_HEAD_ALIGN;
 +      if (data[i])
 +              cfhsi->cfg.head_align = nla_get_u32(data[i]);
 +
 +      i = __IFLA_CAIF_HSI_TAIL_ALIGN;
 +      if (data[i])
 +              cfhsi->cfg.tail_align = nla_get_u32(data[i]);
 +
 +      i = __IFLA_CAIF_HSI_QHIGH_WATERMARK;
 +      if (data[i])
 +              cfhsi->cfg.q_high_mark = nla_get_u32(data[i]);
 +
 +      i = __IFLA_CAIF_HSI_QLOW_WATERMARK;
 +      if (data[i])
 +              cfhsi->cfg.q_low_mark = nla_get_u32(data[i]);
 +}
 +
 +static int caif_hsi_changelink(struct net_device *dev, struct nlattr *tb[],
 +                              struct nlattr *data[])
 +{
 +      cfhsi_netlink_parms(data, netdev_priv(dev));
 +      netdev_state_change(dev);
 +      return 0;
  }
  
 -struct platform_driver cfhsi_plat_drv = {
 -      .probe = cfhsi_probe,
 -      .remove = cfhsi_remove,
 -      .driver = {
 -                 .name = "cfhsi",
 -                 .owner = THIS_MODULE,
 -                 },
 +static const struct nla_policy caif_hsi_policy[__IFLA_CAIF_HSI_MAX + 1] = {
 +      [__IFLA_CAIF_HSI_INACTIVITY_TOUT] = { .type = NLA_U32, .len = 4 },
 +      [__IFLA_CAIF_HSI_AGGREGATION_TOUT] = { .type = NLA_U32, .len = 4 },
 +      [__IFLA_CAIF_HSI_HEAD_ALIGN] = { .type = NLA_U32, .len = 4 },
 +      [__IFLA_CAIF_HSI_TAIL_ALIGN] = { .type = NLA_U32, .len = 4 },
 +      [__IFLA_CAIF_HSI_QHIGH_WATERMARK] = { .type = NLA_U32, .len = 4 },
 +      [__IFLA_CAIF_HSI_QLOW_WATERMARK] = { .type = NLA_U32, .len = 4 },
  };
  
 -static void __exit cfhsi_exit_module(void)
 +static size_t caif_hsi_get_size(const struct net_device *dev)
  {
 -      struct list_head *list_node;
 -      struct list_head *n;
 -      struct cfhsi *cfhsi = NULL;
 +      int i;
 +      size_t s = 0;
 +      for (i = __IFLA_CAIF_HSI_UNSPEC + 1; i < __IFLA_CAIF_HSI_MAX; i++)
 +              s += nla_total_size(caif_hsi_policy[i].len);
 +      return s;
 +}
  
 -      spin_lock(&cfhsi_list_lock);
 -      list_for_each_safe(list_node, n, &cfhsi_list) {
 -              cfhsi = list_entry(list_node, struct cfhsi, list);
 +static int caif_hsi_fill_info(struct sk_buff *skb, const struct net_device *dev)
 +{
 +      struct cfhsi *cfhsi = netdev_priv(dev);
  
 -              /* Remove from list. */
 -              list_del(list_node);
 -              spin_unlock(&cfhsi_list_lock);
 +      if (nla_put_u32(skb, __IFLA_CAIF_HSI_INACTIVITY_TOUT,
 +                      cfhsi->cfg.inactivity_timeout) ||
 +          nla_put_u32(skb, __IFLA_CAIF_HSI_AGGREGATION_TOUT,
 +                      cfhsi->cfg.aggregation_timeout) ||
 +          nla_put_u32(skb, __IFLA_CAIF_HSI_HEAD_ALIGN,
 +                      cfhsi->cfg.head_align) ||
 +          nla_put_u32(skb, __IFLA_CAIF_HSI_TAIL_ALIGN,
 +                      cfhsi->cfg.tail_align) ||
 +          nla_put_u32(skb, __IFLA_CAIF_HSI_QHIGH_WATERMARK,
 +                      cfhsi->cfg.q_high_mark) ||
 +          nla_put_u32(skb, __IFLA_CAIF_HSI_QLOW_WATERMARK,
 +                      cfhsi->cfg.q_low_mark))
 +              return -EMSGSIZE;
  
 -              unregister_netdevice(cfhsi->ndev);
 +      return 0;
 +}
  
 -              spin_lock(&cfhsi_list_lock);
 -      }
 -      spin_unlock(&cfhsi_list_lock);
 +static int caif_hsi_newlink(struct net *src_net, struct net_device *dev,
 +                        struct nlattr *tb[], struct nlattr *data[])
 +{
 +      struct cfhsi *cfhsi = NULL;
-       struct cfhsi_ops *(*get_ops)(void);
 +
 +      ASSERT_RTNL();
  
 -      /* Unregister platform driver. */
 -      platform_driver_unregister(&cfhsi_plat_drv);
 +      cfhsi = netdev_priv(dev);
 +      cfhsi_netlink_parms(data, cfhsi);
 +      dev_net_set(cfhsi->ndev, src_net);
 +
-       get_ops = symbol_get(cfhsi_get_ops);
-       if (!get_ops) {
-               pr_err("%s: failed to get the cfhsi_ops\n", __func__);
-               return -ENODEV;
-       }
-       /* Assign the HSI device. */
-       cfhsi->ops = (*get_ops)();
-       if (!cfhsi->ops) {
-               pr_err("%s: failed to get the cfhsi_ops\n", __func__);
-               goto err;
-       }
-       /* Assign the driver to this HSI device. */
-       cfhsi->ops->cb_ops = &cfhsi->cb_ops;
-       if (register_netdevice(dev)) {
-               pr_warn("%s: caif_hsi device registration failed\n", __func__);
-               goto err;
-       }
-       /* Add CAIF HSI device to list. */
-       list_add_tail(&cfhsi->list, &cfhsi_list);
 +      return 0;
- err:
-       symbol_put(cfhsi_get_ops);
-       return -ENODEV;
  }
  
 -static int __init cfhsi_init_module(void)
 +static struct rtnl_link_ops caif_hsi_link_ops __read_mostly = {
 +      .kind           = "cfhsi",
 +      .priv_size      = sizeof(struct cfhsi),
 +      .setup          = cfhsi_setup,
 +      .maxtype        = __IFLA_CAIF_HSI_MAX,
 +      .policy = caif_hsi_policy,
 +      .newlink        = caif_hsi_newlink,
 +      .changelink     = caif_hsi_changelink,
 +      .get_size       = caif_hsi_get_size,
 +      .fill_info      = caif_hsi_fill_info,
 +};
 +
 +static void __exit cfhsi_exit_module(void)
  {
 -      int result;
 +      struct list_head *list_node;
 +      struct list_head *n;
 +      struct cfhsi *cfhsi;
  
 -      /* Initialize spin lock. */
 -      spin_lock_init(&cfhsi_list_lock);
 +      rtnl_link_unregister(&caif_hsi_link_ops);
  
 -      /* Register platform driver. */
 -      result = platform_driver_register(&cfhsi_plat_drv);
 -      if (result) {
 -              printk(KERN_ERR "Could not register platform HSI driver: %d.\n",
 -                      result);
 -              goto err_dev_register;
 +      rtnl_lock();
 +      list_for_each_safe(list_node, n, &cfhsi_list) {
 +              cfhsi = list_entry(list_node, struct cfhsi, list);
 +              unregister_netdev(cfhsi->ndev);
        }
 +      rtnl_unlock();
 +}
  
 - err_dev_register:
 -      return result;
 +static int __init cfhsi_init_module(void)
 +{
 +      return rtnl_link_register(&caif_hsi_link_ops);
  }
  
  module_init(cfhsi_init_module);
Simple merge
   * management protocol is used in place of the standard CDC
   * notifications NOTIFY_NETWORK_CONNECTION and NOTIFY_SPEED_CHANGE
   *
 + * Alternatively, control and data functions can be combined in a
 + * single USB interface.
 + *
   * Handling a protocol like QMI is out of the scope for any driver.
 - * It can be exported as a character device using the cdc-wdm driver,
 - * which will enable userspace applications ("modem managers") to
 - * handle it.  This may be required to use the network interface
 - * provided by the driver.
 + * It is exported as a character device using the cdc-wdm driver as
 + * a subdriver, enabling userspace applications ("modem managers") to
 + * handle it.
   *
   * These devices may alternatively/additionally be configured using AT
 - * commands on any of the serial interfaces driven by the option driver
 - *
 - * This driver binds only to the data ("slave") interface to enable
 - * the cdc-wdm driver to bind to the control interface.  It still
 - * parses the CDC functional descriptors on the control interface to
 - *  a) verify that this is indeed a handled interface (CDC Union
 - *     header lists it as slave)
 - *  b) get MAC address and other ethernet config from the CDC Ethernet
 - *     header
 - *  c) enable user bind requests against the control interface, which
 - *     is the common way to bind to CDC Ethernet Control Model type
 - *     interfaces
 - *  d) provide a hint to the user about which interface is the
 - *     corresponding management interface
 + * commands on a serial interface
   */
  
 +/* driver specific data */
 +struct qmi_wwan_state {
 +      struct usb_driver *subdriver;
 +      atomic_t pmcount;
 +      unsigned long unused;
 +      struct usb_interface *control;
 +      struct usb_interface *data;
 +};
 +
 +/* using a counter to merge subdriver requests with our own into a combined state */
 +static int qmi_wwan_manage_power(struct usbnet *dev, int on)
 +{
 +      struct qmi_wwan_state *info = (void *)&dev->data;
 +      int rv = 0;
 +
 +      dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
 +
 +      if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
 +              /* need autopm_get/put here to ensure the usbcore sees the new value */
 +              rv = usb_autopm_get_interface(dev->intf);
 +              if (rv < 0)
 +                      goto err;
 +              dev->intf->needs_remote_wakeup = on;
 +              usb_autopm_put_interface(dev->intf);
 +      }
 +err:
 +      return rv;
 +}
 +
 +static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on)
 +{
 +      struct usbnet *dev = usb_get_intfdata(intf);
++
++      /* can be called while disconnecting */
++      if (!dev)
++              return 0;
 +      return qmi_wwan_manage_power(dev, on);
 +}
 +
 +/* collect all three endpoints and register subdriver */
 +static int qmi_wwan_register_subdriver(struct usbnet *dev)
 +{
 +      int rv;
 +      struct usb_driver *subdriver = NULL;
 +      struct qmi_wwan_state *info = (void *)&dev->data;
 +
 +      /* collect bulk endpoints */
 +      rv = usbnet_get_endpoints(dev, info->data);
 +      if (rv < 0)
 +              goto err;
 +
 +      /* update status endpoint if separate control interface */
 +      if (info->control != info->data)
 +              dev->status = &info->control->cur_altsetting->endpoint[0];
 +
 +      /* require interrupt endpoint for subdriver */
 +      if (!dev->status) {
 +              rv = -EINVAL;
 +              goto err;
 +      }
 +
 +      /* for subdriver power management */
 +      atomic_set(&info->pmcount, 0);
 +
 +      /* register subdriver */
 +      subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc, 512, &qmi_wwan_cdc_wdm_manage_power);
 +      if (IS_ERR(subdriver)) {
 +              dev_err(&info->control->dev, "subdriver registration failed\n");
 +              rv = PTR_ERR(subdriver);
 +              goto err;
 +      }
 +
 +      /* prevent usbnet from using status endpoint */
 +      dev->status = NULL;
 +
 +      /* save subdriver struct for suspend/resume wrappers */
 +      info->subdriver = subdriver;
 +
 +err:
 +      return rv;
 +}
 +
  static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
  {
        int status = -1;
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc net/core/dev.c
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -83,12 -83,11 +83,13 @@@ netdev_tx_t mac802154_tx(struct mac8021
  {
        struct xmit_work *work;
  
-       if (!(priv->phy->channels_supported[page] & (1 << chan)))
+       if (!(priv->phy->channels_supported[page] & (1 << chan))) {
                WARN_ON(1);
                return NETDEV_TX_OK;
+       }
  
 +      mac802154_monitors_rx(mac802154_to_priv(&priv->hw), skb);
 +
        if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
                u16 crc = crc_ccitt(0, skb->data, skb->len);
                u8 *data = skb_put(skb, 2);