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

Commit 3b04ddde authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller
Browse files

[NET]: Move hardware header operations out of netdevice.



Since hardware header operations are part of the protocol class
not the device instance, make them into a separate object and
save memory.

Signed-off-by: default avatarStephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b95cce35
Loading
Loading
Loading
Loading
+23 −17
Original line number Original line Diff line number Diff line
@@ -159,15 +159,16 @@ MODULE_PARM_DESC(max_partial_datagrams,




static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
			    unsigned short type, void *daddr, void *saddr,
			    unsigned short type, const void *daddr,
			    unsigned len);
			    const void *saddr, unsigned len);
static int ether1394_rebuild_header(struct sk_buff *skb);
static int ether1394_rebuild_header(struct sk_buff *skb);
static int ether1394_header_parse(const struct sk_buff *skb,
static int ether1394_header_parse(const struct sk_buff *skb,
				  unsigned char *haddr);
				  unsigned char *haddr);
static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh);
static int ether1394_header_cache(const struct neighbour *neigh,
				  struct hh_cache *hh);
static void ether1394_header_cache_update(struct hh_cache *hh,
static void ether1394_header_cache_update(struct hh_cache *hh,
					  struct net_device *dev,
					  const struct net_device *dev,
					  unsigned char *haddr);
					  const unsigned char *haddr);
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev);
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev);
static void ether1394_iso(struct hpsb_iso *iso);
static void ether1394_iso(struct hpsb_iso *iso);


@@ -507,6 +508,14 @@ static void ether1394_reset_priv(struct net_device *dev, int set_mtu)
	spin_unlock_irqrestore(&priv->lock, flags);
	spin_unlock_irqrestore(&priv->lock, flags);
}
}


static const struct header_ops ether1394_header_ops = {
	.create		= ether1394_header,
	.rebuild	= ether1394_rebuild_header,
	.cache  	= ether1394_header_cache,
	.cache_update	= ether1394_header_cache_update,
	.parse		= ether1394_header_parse,
};

static void ether1394_init_dev(struct net_device *dev)
static void ether1394_init_dev(struct net_device *dev)
{
{
	dev->open		= ether1394_open;
	dev->open		= ether1394_open;
@@ -516,11 +525,7 @@ static void ether1394_init_dev(struct net_device *dev)
	dev->tx_timeout		= ether1394_tx_timeout;
	dev->tx_timeout		= ether1394_tx_timeout;
	dev->change_mtu		= ether1394_change_mtu;
	dev->change_mtu		= ether1394_change_mtu;


	dev->hard_header	= ether1394_header;
	dev->header_ops		= &ether1394_header_ops;
	dev->rebuild_header	= ether1394_rebuild_header;
	dev->hard_header_cache	= ether1394_header_cache;
	dev->header_cache_update= ether1394_header_cache_update;
	dev->hard_header_parse	= ether1394_header_parse;


	SET_ETHTOOL_OPS(dev, &ethtool_ops);
	SET_ETHTOOL_OPS(dev, &ethtool_ops);


@@ -711,8 +716,8 @@ static void ether1394_host_reset(struct hpsb_host *host)
 * saddr=NULL means use device source address
 * saddr=NULL means use device source address
 * daddr=NULL means leave destination address (eg unresolved arp). */
 * daddr=NULL means leave destination address (eg unresolved arp). */
static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
			    unsigned short type, void *daddr, void *saddr,
			    unsigned short type, const void *daddr,
			    unsigned len)
			    const void *saddr, unsigned len)
{
{
	struct eth1394hdr *eth =
	struct eth1394hdr *eth =
			(struct eth1394hdr *)skb_push(skb, ETH1394_HLEN);
			(struct eth1394hdr *)skb_push(skb, ETH1394_HLEN);
@@ -759,7 +764,8 @@ static int ether1394_header_parse(const struct sk_buff *skb,
	return ETH1394_ALEN;
	return ETH1394_ALEN;
}
}


static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh)
static int ether1394_header_cache(const struct neighbour *neigh,
				  struct hh_cache *hh)
{
{
	unsigned short type = hh->hh_type;
	unsigned short type = hh->hh_type;
	struct net_device *dev = neigh->dev;
	struct net_device *dev = neigh->dev;
@@ -778,8 +784,8 @@ static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh)


/* Called by Address Resolution module to notify changes in address. */
/* Called by Address Resolution module to notify changes in address. */
static void ether1394_header_cache_update(struct hh_cache *hh,
static void ether1394_header_cache_update(struct hh_cache *hh,
					  struct net_device *dev,
					  const struct net_device *dev,
					  unsigned char * haddr)
					  const unsigned char * haddr)
{
{
	memcpy((u8 *)hh->hh_data + 16 - ETH1394_HLEN, haddr, dev->addr_len);
	memcpy((u8 *)hh->hh_data + 16 - ETH1394_HLEN, haddr, dev->addr_len);
}
}
@@ -899,7 +905,7 @@ static u16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev,
	}
	}


	/* Now add the ethernet header. */
	/* Now add the ethernet header. */
	if (dev->hard_header(skb, dev, ntohs(ether_type), &dest_hw, NULL,
	if (dev_hard_header(skb, dev, ntohs(ether_type), &dest_hw, NULL,
			    skb->len) >= 0)
			    skb->len) >= 0)
		ret = ether1394_type_trans(skb, dev);
		ret = ether1394_type_trans(skb, dev);


+6 −2
Original line number Original line Diff line number Diff line
@@ -780,7 +780,7 @@ static void ipoib_timeout(struct net_device *dev)
static int ipoib_hard_header(struct sk_buff *skb,
static int ipoib_hard_header(struct sk_buff *skb,
			     struct net_device *dev,
			     struct net_device *dev,
			     unsigned short type,
			     unsigned short type,
			     void *daddr, void *saddr, unsigned len)
			     const void *daddr, const void *saddr, unsigned len)
{
{
	struct ipoib_header *header;
	struct ipoib_header *header;


@@ -940,6 +940,10 @@ void ipoib_dev_cleanup(struct net_device *dev)
	priv->tx_ring = NULL;
	priv->tx_ring = NULL;
}
}


static const struct header_ops ipoib_header_ops = {
	.create	= ipoib_hard_header,
};

static void ipoib_setup(struct net_device *dev)
static void ipoib_setup(struct net_device *dev)
{
{
	struct ipoib_dev_priv *priv = netdev_priv(dev);
	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -950,7 +954,7 @@ static void ipoib_setup(struct net_device *dev)
	dev->hard_start_xmit 	 = ipoib_start_xmit;
	dev->hard_start_xmit 	 = ipoib_start_xmit;
	dev->get_stats 		 = ipoib_get_stats;
	dev->get_stats 		 = ipoib_get_stats;
	dev->tx_timeout 	 = ipoib_timeout;
	dev->tx_timeout 	 = ipoib_timeout;
	dev->hard_header 	 = ipoib_hard_header;
	dev->header_ops 	 = &ipoib_header_ops;
	dev->set_multicast_list  = ipoib_set_mcast_list;
	dev->set_multicast_list  = ipoib_set_mcast_list;
	dev->neigh_setup         = ipoib_neigh_setup_dev;
	dev->neigh_setup         = ipoib_neigh_setup_dev;


+36 −69
Original line number Original line Diff line number Diff line
@@ -1873,54 +1873,14 @@ isdn_net_rcv_skb(int idx, struct sk_buff *skb)
	return 0;
	return 0;
}
}


static int
my_eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
	      void *daddr, void *saddr, unsigned len)
{
	struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);

	/*
	 * Set the protocol type. For a packet of type ETH_P_802_3 we
	 * put the length here instead. It is up to the 802.2 layer to
	 * carry protocol information.
	 */

	if (type != ETH_P_802_3)
		eth->h_proto = htons(type);
	else
		eth->h_proto = htons(len);

	/*
	 * Set the source hardware address.
	 */
	if (saddr)
		memcpy(eth->h_source, saddr, dev->addr_len);
	else
		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);

	/*
	 * Anyway, the loopback-device should never use this function...
	 */

	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
		memset(eth->h_dest, 0, dev->addr_len);
		return ETH_HLEN /*(dev->hard_header_len)*/;
	}
	if (daddr) {
		memcpy(eth->h_dest, daddr, dev->addr_len);
		return ETH_HLEN /*dev->hard_header_len*/;
	}
	return -ETH_HLEN /*dev->hard_header_len*/;
}

/*
/*
 *  build an header
 *  build an header
 *  depends on encaps that is being used.
 *  depends on encaps that is being used.
 */
 */


static int
static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,
isdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
			   unsigned short type,
		void *daddr, void *saddr, unsigned plen)
			   const void *daddr, const void *saddr, unsigned plen)
{
{
	isdn_net_local *lp = dev->priv;
	isdn_net_local *lp = dev->priv;
	unsigned char *p;
	unsigned char *p;
@@ -1928,7 +1888,7 @@ isdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type


	switch (lp->p_encap) {
	switch (lp->p_encap) {
		case ISDN_NET_ENCAP_ETHER:
		case ISDN_NET_ENCAP_ETHER:
			len = my_eth_header(skb, dev, type, daddr, saddr, plen);
			len = eth_header(skb, dev, type, daddr, saddr, plen);
			break;
			break;
#ifdef CONFIG_ISDN_PPP
#ifdef CONFIG_ISDN_PPP
		case ISDN_NET_ENCAP_SYNCPPP:
		case ISDN_NET_ENCAP_SYNCPPP:
@@ -2005,6 +1965,32 @@ isdn_net_rebuild_header(struct sk_buff *skb)
	return ret;
	return ret;
}
}


static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
{
	const struct net_device *dev = neigh->dev;
	isdn_net_local *lp = dev->priv;

	if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
		return eth_header_cache(neigh, hh);
	return -1;
}

static void isdn_header_cache_update(struct hh_cache *hh,
				     const struct net_device *dev,
				     const unsigned char *haddr)
{
	isdn_net_local *lp = dev->priv;
	if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
		return eth_header_cache_update(hh, dev, haddr);
}

static const struct header_ops isdn_header_ops = {
	.create = isdn_net_header,
	.rebuild = isdn_net_rebuild_header,
	.cache = isdn_header_cache,
	.cache_update = isdn_header_cache_update,
};

/*
/*
 * Interface-setup. (just after registering a new interface)
 * Interface-setup. (just after registering a new interface)
 */
 */
@@ -2012,18 +1998,12 @@ static int
isdn_net_init(struct net_device *ndev)
isdn_net_init(struct net_device *ndev)
{
{
	ushort max_hlhdr_len = 0;
	ushort max_hlhdr_len = 0;
	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
	int drvidx;
	int drvidx, i;


	ether_setup(ndev);
	ether_setup(ndev);
	lp->org_hhc = ndev->hard_header_cache;
	ndev->header_ops = NULL;
	lp->org_hcu = ndev->header_cache_update;


	/* Setup the generic properties */
	/* Setup the generic properties */

	ndev->hard_header = NULL;
	ndev->hard_header_cache = NULL;
	ndev->header_cache_update = NULL;
	ndev->mtu = 1500;
	ndev->mtu = 1500;
	ndev->flags = IFF_NOARP|IFF_POINTOPOINT;
	ndev->flags = IFF_NOARP|IFF_POINTOPOINT;
	ndev->type = ARPHRD_ETHER;
	ndev->type = ARPHRD_ETHER;
@@ -2032,9 +2012,6 @@ isdn_net_init(struct net_device *ndev)
	/* for clients with MPPP maybe higher values better */
	/* for clients with MPPP maybe higher values better */
	ndev->tx_queue_len = 30;
	ndev->tx_queue_len = 30;


	for (i = 0; i < ETH_ALEN; i++)
		ndev->broadcast[i] = 0xff;

	/* The ISDN-specific entries in the device structure. */
	/* The ISDN-specific entries in the device structure. */
	ndev->open = &isdn_net_open;
	ndev->open = &isdn_net_open;
	ndev->hard_start_xmit = &isdn_net_start_xmit;
	ndev->hard_start_xmit = &isdn_net_start_xmit;
@@ -2052,7 +2029,6 @@ isdn_net_init(struct net_device *ndev)
	ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
	ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
	ndev->stop = &isdn_net_close;
	ndev->stop = &isdn_net_close;
	ndev->get_stats = &isdn_net_get_stats;
	ndev->get_stats = &isdn_net_get_stats;
	ndev->rebuild_header = &isdn_net_rebuild_header;
	ndev->do_ioctl = NULL;
	ndev->do_ioctl = NULL;
	return 0;
	return 0;
}
}
@@ -2861,23 +2837,16 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
		}
		}
		if (cfg->p_encap != lp->p_encap) {
		if (cfg->p_encap != lp->p_encap) {
			if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
			if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
				p->dev.hard_header = NULL;
				p->dev.header_ops = NULL;
				p->dev.hard_header_cache = NULL;
				p->dev.header_cache_update = NULL;
				p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
				p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
			} else {
			} else {
				p->dev.hard_header = isdn_net_header;
				p->dev.header_ops = &isdn_header_ops;
				if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) {
				if (cfg->p_encap == ISDN_NET_ENCAP_ETHER)
					p->dev.hard_header_cache = lp->org_hhc;
					p->dev.header_cache_update = lp->org_hcu;
					p->dev.flags = IFF_BROADCAST | IFF_MULTICAST;
					p->dev.flags = IFF_BROADCAST | IFF_MULTICAST;
				} else {
				else
					p->dev.hard_header_cache = NULL;
					p->dev.header_cache_update = NULL;
					p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
					p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
			}
			}
		}
		}
		}
		lp->p_encap = cfg->p_encap;
		lp->p_encap = cfg->p_encap;
		return 0;
		return 0;
	}
	}
@@ -3127,8 +3096,6 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
			((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave;
			((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave;
	} else {
	} else {
		/* Unregister only if it's a master-device */
		/* Unregister only if it's a master-device */
		p->dev.hard_header_cache = p->local->org_hhc;
		p->dev.header_cache_update = p->local->org_hcu;
		unregister_netdev(&p->dev);
		unregister_netdev(&p->dev);
	}
	}
	/* Unlink device from chain */
	/* Unlink device from chain */
+8 −1
Original line number Original line Diff line number Diff line
@@ -1225,10 +1225,17 @@ static struct net_device_stats * dvb_net_get_stats(struct net_device *dev)
	return &((struct dvb_net_priv*) dev->priv)->stats;
	return &((struct dvb_net_priv*) dev->priv)->stats;
}
}


static const struct header_ops dvb_header_ops = {
	.create		= eth_header,
	.parse		= eth_header_parse,
	.rebuild	= eth_rebuild_header,
};

static void dvb_net_setup(struct net_device *dev)
static void dvb_net_setup(struct net_device *dev)
{
{
	ether_setup(dev);
	ether_setup(dev);


	dev->header_ops		= &dvb_header_ops;
	dev->open		= dvb_net_open;
	dev->open		= dvb_net_open;
	dev->stop		= dvb_net_stop;
	dev->stop		= dvb_net_stop;
	dev->hard_start_xmit	= dvb_net_tx;
	dev->hard_start_xmit	= dvb_net_tx;
@@ -1237,7 +1244,7 @@ static void dvb_net_setup(struct net_device *dev)
	dev->set_mac_address    = dvb_net_set_mac;
	dev->set_mac_address    = dvb_net_set_mac;
	dev->mtu		= 4096;
	dev->mtu		= 4096;
	dev->mc_count           = 0;
	dev->mc_count           = 0;
	dev->hard_header_cache  = NULL;

	dev->flags |= IFF_NOARP;
	dev->flags |= IFF_NOARP;
}
}


+1 −19
Original line number Original line Diff line number Diff line
@@ -194,10 +194,6 @@ static void cops_timeout(struct net_device *dev);
static void cops_rx (struct net_device *dev);
static void cops_rx (struct net_device *dev);
static int  cops_send_packet (struct sk_buff *skb, struct net_device *dev);
static int  cops_send_packet (struct sk_buff *skb, struct net_device *dev);
static void set_multicast_list (struct net_device *dev);
static void set_multicast_list (struct net_device *dev);
static int  cops_hard_header (struct sk_buff *skb, struct net_device *dev,
			      unsigned short type, void *daddr, void *saddr, 
			      unsigned len);

static int  cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static int  cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static int  cops_close (struct net_device *dev);
static int  cops_close (struct net_device *dev);
static struct net_device_stats *cops_get_stats (struct net_device *dev);
static struct net_device_stats *cops_get_stats (struct net_device *dev);
@@ -331,7 +327,6 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
	dev->base_addr = ioaddr;
	dev->base_addr = ioaddr;


        lp = netdev_priv(dev);
        lp = netdev_priv(dev);
        memset(lp, 0, sizeof(struct cops_local));
        spin_lock_init(&lp->lock);
        spin_lock_init(&lp->lock);


	/* Copy local board variable to lp struct. */
	/* Copy local board variable to lp struct. */
@@ -340,7 +335,7 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
	dev->hard_start_xmit    = cops_send_packet;
	dev->hard_start_xmit    = cops_send_packet;
	dev->tx_timeout		= cops_timeout;
	dev->tx_timeout		= cops_timeout;
	dev->watchdog_timeo	= HZ * 2;
	dev->watchdog_timeo	= HZ * 2;
	dev->hard_header	= cops_hard_header;

        dev->get_stats          = cops_get_stats;
        dev->get_stats          = cops_get_stats;
	dev->open               = cops_open;
	dev->open               = cops_open;
        dev->stop               = cops_close;
        dev->stop               = cops_close;
@@ -944,19 +939,6 @@ static void set_multicast_list(struct net_device *dev)
		printk("%s: set_multicast_list executed\n", dev->name);
		printk("%s: set_multicast_list executed\n", dev->name);
}
}


/*
 *      Another Dummy function to keep the Appletalk layer happy.
 */
 
static int cops_hard_header(struct sk_buff *skb, struct net_device *dev,
			    unsigned short type, void *daddr, void *saddr, 
			    unsigned len)
{
        if(cops_debug >= 3)
                printk("%s: cops_hard_header executed. Wow!\n", dev->name);
        return 0;
}

/*
/*
 *      System ioctls for the COPS LocalTalk card.
 *      System ioctls for the COPS LocalTalk card.
 */
 */
Loading