
This patch backports the struct net_device_ops changes added on 2.6.29.

If we add the compat.git netdev_attach_ops() implementation
for newer kernels upstream it means we do not have to use this
patch at all for older kernels.

mcgrof@tux ~/linux-stable (git::master)$ git describe --contains d314774cf2cd5dfeb39a00d37deee65d4c627927
v2.6.29-rc1~581^2~677

commit d314774cf2cd5dfeb39a00d37deee65d4c627927
Author: Stephen Hemminger <shemminger@vyatta.com>
Date:   Wed Nov 19 21:32:24 2008 -0800

    netdev: network device operations infrastructure
    
    This patch changes the network device internal API to move adminstrative
    operations out of the network device structure and into a separate structure.
    
    This patch involves some hackery to maintain compatablity between the
    new and old model, so all 300+ drivers don't have to be changed at once.
    For drivers that aren't converted yet, the netdevice_ops virt function list
    still resides in the net_device structure. For old protocols, the new
    net_device_ops are copied out to the old net_device pointers.
    
    After the transistion is completed the nag message can be changed to
    an WARN_ON, and the compatiablity code can be made configurable.
    
    Some function pointers aren't moved:
    * destructor can't be in net_device_ops because
      it may need to be referenced after the module is unloaded.
    * neighbor setup is manipulated in a couple of places that need special
      consideration
    * hard_start_xmit is in the fast path for transmit.
    
    Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -358,7 +358,7 @@ generic_rndis_bind(struct usbnet *dev, s
 	dev->rx_urb_size &= ~(dev->maxpacket - 1);
 	u.init->max_transfer_size = cpu_to_le32(dev->rx_urb_size);
 
-	net->netdev_ops = &rndis_netdev_ops;
+	netdev_attach_ops(net, &rndis_netdev_ops);
 
 	retval = rndis_command(dev, u.header, CONTROL_BUFFER_SIZE);
 	if (unlikely(retval < 0)) {
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1417,7 +1417,7 @@ usbnet_probe (struct usb_interface *udev
 		net->features |= NETIF_F_HIGHDMA;
 #endif
 
-	net->netdev_ops = &usbnet_netdev_ops;
+	netdev_attach_ops(net, &usbnet_netdev_ops);
 	net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
 	net->ethtool_ops = &usbnet_ethtool_ops;
 
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1285,7 +1285,7 @@ static const struct net_device_ops ath6k
 
 void init_netdev(struct net_device *dev)
 {
-	dev->netdev_ops = &ath6kl_netdev_ops;
+	netdev_attach_ops(dev, &ath6kl_netdev_ops);
 	dev->destructor = free_netdev;
 	dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
 
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -3436,7 +3436,7 @@ static int rndis_wlan_bind(struct usbnet
 	 * rndis_host wants to avoid all OID as much as possible
 	 * so do promisc/multicast handling in rndis_wlan.
 	 */
-	usbdev->net->netdev_ops = &rndis_wlan_netdev_ops;
+	netdev_attach_ops(usbdev->net, &rndis_wlan_netdev_ops);
 
 	tmp = cpu_to_le32(RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST);
 	retval = rndis_set_oid(usbdev,
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2175,7 +2175,7 @@ static int __devinit b44_init_one(struct
 	bp->rx_pending = B44_DEF_RX_RING_PENDING;
 	bp->tx_pending = B44_DEF_TX_RING_PENDING;
 
-	dev->netdev_ops = &b44_netdev_ops;
+	netdev_attach_ops(dev, &b44_netdev_ops);
 	netif_napi_add(dev, &bp->napi, b44_poll, 64);
 	dev->watchdog_timeo = B44_TX_TIMEOUT;
 	dev->irq = sdev->irq;
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -6106,7 +6106,7 @@ static struct net_device *ipw2100_alloc_
 	priv->ieee->perfect_rssi = -20;
 	priv->ieee->worst_rssi = -85;
 
-	dev->netdev_ops = &ipw2100_netdev_ops;
+	netdev_attach_ops(dev, &ipw2100_netdev_ops);
 	dev->ethtool_ops = &ipw2100_ethtool_ops;
 	dev->wireless_handlers = &ipw2100_wx_handler_def;
 	priv->wireless_data.libipw = priv->ieee;
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -11684,7 +11684,7 @@ static int ipw_prom_alloc(struct ipw_pri
 	memcpy(priv->prom_net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
 
 	priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
-	priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops;
+	netdev_attach_ops(priv->prom_net_dev, &ipw_prom_netdev_ops);
 
 	priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR;
 	SET_NETDEV_DEV(priv->prom_net_dev, &priv->pci_dev->dev);
@@ -11822,7 +11822,7 @@ static int __devinit ipw_pci_probe(struc
 	priv->ieee->perfect_rssi = -20;
 	priv->ieee->worst_rssi = -85;
 
-	net_dev->netdev_ops = &ipw_netdev_ops;
+	netdev_attach_ops(net_dev, &ipw_netdev_ops);
 	priv->wireless_data.spy_data = &priv->ieee->spy_data;
 	net_dev->wireless_data = &priv->wireless_data;
 	net_dev->wireless_handlers = &ipw_wx_handler_def;
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -993,7 +993,7 @@ struct lbs_private *lbs_add_card(void *c
 	wdev->netdev = dev;
 	priv->dev = dev;
 
- 	dev->netdev_ops = &lbs_netdev_ops;
+	netdev_attach_ops(dev, &lbs_netdev_ops);
 	dev->watchdog_timeo = 5 * HZ;
 	dev->ethtool_ops = &lbs_ethtool_ops;
 	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -1015,7 +1015,7 @@ static int lbs_add_mesh(struct lbs_priva
 	mesh_dev->ieee80211_ptr = mesh_wdev;
 	priv->mesh_dev = mesh_dev;
 
-	mesh_dev->netdev_ops = &mesh_netdev_ops;
+	netdev_attach_ops(mesh_dev, &mesh_netdev_ops);
 	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
 	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN);
 
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1299,7 +1299,7 @@ static const struct net_device_ops hwsim
 
 static void hwsim_mon_setup(struct net_device *dev)
 {
-	dev->netdev_ops = &hwsim_netdev_ops;
+	netdev_attach_ops(dev, &hwsim_netdev_ops);
 	dev->destructor = free_netdev;
 	ether_setup(dev);
 	dev->tx_queue_len = 0;
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -638,7 +638,7 @@ static const struct net_device_ops mwifi
 void mwifiex_init_priv_params(struct mwifiex_private *priv,
 						struct net_device *dev)
 {
-	dev->netdev_ops = &mwifiex_netdev_ops;
+	netdev_attach_ops(dev, &mwifiex_netdev_ops);
 	/* Initialize private structure */
 	priv->current_key_index = 0;
 	priv->media_connected = false;
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -224,7 +224,7 @@ void bnep_net_setup(struct net_device *d
 
 	ether_setup(dev);
 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
-	dev->netdev_ops = &bnep_netdev_ops;
+	netdev_attach_ops(dev, &bnep_netdev_ops);
 
 	dev->watchdog_timeo  = HZ * 2;
 }
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -2211,7 +2211,7 @@ static int atl1e_init_netdev(struct net_
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 	pci_set_drvdata(pdev, netdev);
 
-	netdev->netdev_ops = &atl1e_netdev_ops;
+	netdev_attach_ops(netdev, &atl1e_netdev_ops);
 
 	netdev->watchdog_timeo = AT_TX_WATCHDOG;
 	atl1e_set_ethtool_ops(netdev);
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2416,7 +2416,7 @@ static int atl1c_init_netdev(struct net_
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 	pci_set_drvdata(pdev, netdev);
 
-	netdev->netdev_ops = &atl1c_netdev_ops;
+	netdev_attach_ops(netdev, &atl1c_netdev_ops);
 	netdev->watchdog_timeo = AT_TX_WATCHDOG;
 	atl1c_set_ethtool_ops(netdev);
 
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -3010,7 +3010,7 @@ static int __devinit atl1_probe(struct p
 	adapter->mii.phy_id_mask = 0x1f;
 	adapter->mii.reg_num_mask = 0x1f;
 
-	netdev->netdev_ops = &atl1_netdev_ops;
+	netdev_attach_ops(netdev, &atl1_netdev_ops);
 	netdev->watchdog_timeo = 5 * HZ;
 	netif_napi_add(netdev, &adapter->napi, atl1_rings_clean, 64);
 
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1400,7 +1400,7 @@ static int __devinit atl2_probe(struct p
 
 	atl2_setup_pcicmd(pdev);
 
-	netdev->netdev_ops = &atl2_netdev_ops;
+	netdev_attach_ops(netdev, &atl2_netdev_ops);
 	atl2_set_ethtool_ops(netdev);
 	netdev->watchdog_timeo = 5 * HZ;
 	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -987,7 +987,7 @@ static void ieee80211_if_setup(struct ne
 {
 	ether_setup(dev);
 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
-	dev->netdev_ops = &ieee80211_dataif_ops;
+	netdev_attach_ops(dev, &ieee80211_dataif_ops);
 	dev->destructor = free_netdev;
 }
 
@@ -1143,7 +1143,7 @@ static void ieee80211_setup_sdata(struct
 
 	/* only monitor/p2p-device differ */
 	if (sdata->dev) {
-		sdata->dev->netdev_ops = &ieee80211_dataif_ops;
+		netdev_attach_ops(sdata->dev, &ieee80211_dataif_ops);
 		sdata->dev->type = ARPHRD_ETHER;
 	}
 
@@ -1177,7 +1177,7 @@ static void ieee80211_setup_sdata(struct
 		break;
 	case NL80211_IFTYPE_MONITOR:
 		sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP;
-		sdata->dev->netdev_ops = &ieee80211_monitorif_ops;
+		netdev_attach_ops(sdata->dev, &ieee80211_monitorif_ops);
 		sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
 				      MONITOR_FLAG_OTHER_BSS;
 		break;
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -2278,9 +2278,9 @@ int orinoco_if_add(struct orinoco_privat
 #endif
 	/* Default to standard ops if not set */
 	if (ops)
-		dev->netdev_ops = ops;
+		netdev_attach_ops(dev, ops);
 	else
-		dev->netdev_ops = &orinoco_netdev_ops;
+		netdev_attach_ops(dev, &orinoco_netdev_ops);
 
 	/* we use the default eth_mac_addr for setting the MAC addr */
 
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -925,9 +925,7 @@ static int wireless_process_ioctl(struct
 			return private(dev, iwr, cmd, info, handler);
 	}
 	/* Old driver API : call driver ioctl handler */
-	if (dev->netdev_ops->ndo_do_ioctl)
-		return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
-	return -EOPNOTSUPP;
+	return ndo_do_ioctl(dev, ifr, cmd);
 }
 
 /* If command is `set a parameter', or `get the encoding parameters',
