diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-10-09 04:40:57 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:52:52 -0400 |
commit | 3b04ddde02cf1b6f14f2697da5c20eca5715017f (patch) | |
tree | 9da1341a5a399a507b5ea6bf5a3047506b8d8f8f /drivers/isdn | |
parent | b95cce3576813ac3f86bafa6b5daaaaf7574b0fe (diff) |
[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: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/i4l/isdn_net.c | 105 |
1 files changed, 36 insertions, 69 deletions
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index aa83277aba74..54546604656d 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c | |||
@@ -1873,54 +1873,14 @@ isdn_net_rcv_skb(int idx, struct sk_buff *skb) | |||
1873 | return 0; | 1873 | return 0; |
1874 | } | 1874 | } |
1875 | 1875 | ||
1876 | static int | ||
1877 | my_eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, | ||
1878 | void *daddr, void *saddr, unsigned len) | ||
1879 | { | ||
1880 | struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); | ||
1881 | |||
1882 | /* | ||
1883 | * Set the protocol type. For a packet of type ETH_P_802_3 we | ||
1884 | * put the length here instead. It is up to the 802.2 layer to | ||
1885 | * carry protocol information. | ||
1886 | */ | ||
1887 | |||
1888 | if (type != ETH_P_802_3) | ||
1889 | eth->h_proto = htons(type); | ||
1890 | else | ||
1891 | eth->h_proto = htons(len); | ||
1892 | |||
1893 | /* | ||
1894 | * Set the source hardware address. | ||
1895 | */ | ||
1896 | if (saddr) | ||
1897 | memcpy(eth->h_source, saddr, dev->addr_len); | ||
1898 | else | ||
1899 | memcpy(eth->h_source, dev->dev_addr, dev->addr_len); | ||
1900 | |||
1901 | /* | ||
1902 | * Anyway, the loopback-device should never use this function... | ||
1903 | */ | ||
1904 | |||
1905 | if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { | ||
1906 | memset(eth->h_dest, 0, dev->addr_len); | ||
1907 | return ETH_HLEN /*(dev->hard_header_len)*/; | ||
1908 | } | ||
1909 | if (daddr) { | ||
1910 | memcpy(eth->h_dest, daddr, dev->addr_len); | ||
1911 | return ETH_HLEN /*dev->hard_header_len*/; | ||
1912 | } | ||
1913 | return -ETH_HLEN /*dev->hard_header_len*/; | ||
1914 | } | ||
1915 | |||
1916 | /* | 1876 | /* |
1917 | * build an header | 1877 | * build an header |
1918 | * depends on encaps that is being used. | 1878 | * depends on encaps that is being used. |
1919 | */ | 1879 | */ |
1920 | 1880 | ||
1921 | static int | 1881 | static int isdn_net_header(struct sk_buff *skb, struct net_device *dev, |
1922 | isdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, | 1882 | unsigned short type, |
1923 | void *daddr, void *saddr, unsigned plen) | 1883 | const void *daddr, const void *saddr, unsigned plen) |
1924 | { | 1884 | { |
1925 | isdn_net_local *lp = dev->priv; | 1885 | isdn_net_local *lp = dev->priv; |
1926 | unsigned char *p; | 1886 | unsigned char *p; |
@@ -1928,7 +1888,7 @@ isdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type | |||
1928 | 1888 | ||
1929 | switch (lp->p_encap) { | 1889 | switch (lp->p_encap) { |
1930 | case ISDN_NET_ENCAP_ETHER: | 1890 | case ISDN_NET_ENCAP_ETHER: |
1931 | len = my_eth_header(skb, dev, type, daddr, saddr, plen); | 1891 | len = eth_header(skb, dev, type, daddr, saddr, plen); |
1932 | break; | 1892 | break; |
1933 | #ifdef CONFIG_ISDN_PPP | 1893 | #ifdef CONFIG_ISDN_PPP |
1934 | case ISDN_NET_ENCAP_SYNCPPP: | 1894 | case ISDN_NET_ENCAP_SYNCPPP: |
@@ -2005,6 +1965,32 @@ isdn_net_rebuild_header(struct sk_buff *skb) | |||
2005 | return ret; | 1965 | return ret; |
2006 | } | 1966 | } |
2007 | 1967 | ||
1968 | static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh) | ||
1969 | { | ||
1970 | const struct net_device *dev = neigh->dev; | ||
1971 | isdn_net_local *lp = dev->priv; | ||
1972 | |||
1973 | if (lp->p_encap == ISDN_NET_ENCAP_ETHER) | ||
1974 | return eth_header_cache(neigh, hh); | ||
1975 | return -1; | ||
1976 | } | ||
1977 | |||
1978 | static void isdn_header_cache_update(struct hh_cache *hh, | ||
1979 | const struct net_device *dev, | ||
1980 | const unsigned char *haddr) | ||
1981 | { | ||
1982 | isdn_net_local *lp = dev->priv; | ||
1983 | if (lp->p_encap == ISDN_NET_ENCAP_ETHER) | ||
1984 | return eth_header_cache_update(hh, dev, haddr); | ||
1985 | } | ||
1986 | |||
1987 | static const struct header_ops isdn_header_ops = { | ||
1988 | .create = isdn_net_header, | ||
1989 | .rebuild = isdn_net_rebuild_header, | ||
1990 | .cache = isdn_header_cache, | ||
1991 | .cache_update = isdn_header_cache_update, | ||
1992 | }; | ||
1993 | |||
2008 | /* | 1994 | /* |
2009 | * Interface-setup. (just after registering a new interface) | 1995 | * Interface-setup. (just after registering a new interface) |
2010 | */ | 1996 | */ |
@@ -2012,18 +1998,12 @@ static int | |||
2012 | isdn_net_init(struct net_device *ndev) | 1998 | isdn_net_init(struct net_device *ndev) |
2013 | { | 1999 | { |
2014 | ushort max_hlhdr_len = 0; | 2000 | ushort max_hlhdr_len = 0; |
2015 | isdn_net_local *lp = (isdn_net_local *) ndev->priv; | 2001 | int drvidx; |
2016 | int drvidx, i; | ||
2017 | 2002 | ||
2018 | ether_setup(ndev); | 2003 | ether_setup(ndev); |
2019 | lp->org_hhc = ndev->hard_header_cache; | 2004 | ndev->header_ops = NULL; |
2020 | lp->org_hcu = ndev->header_cache_update; | ||
2021 | 2005 | ||
2022 | /* Setup the generic properties */ | 2006 | /* Setup the generic properties */ |
2023 | |||
2024 | ndev->hard_header = NULL; | ||
2025 | ndev->hard_header_cache = NULL; | ||
2026 | ndev->header_cache_update = NULL; | ||
2027 | ndev->mtu = 1500; | 2007 | ndev->mtu = 1500; |
2028 | ndev->flags = IFF_NOARP|IFF_POINTOPOINT; | 2008 | ndev->flags = IFF_NOARP|IFF_POINTOPOINT; |
2029 | ndev->type = ARPHRD_ETHER; | 2009 | ndev->type = ARPHRD_ETHER; |
@@ -2032,9 +2012,6 @@ isdn_net_init(struct net_device *ndev) | |||
2032 | /* for clients with MPPP maybe higher values better */ | 2012 | /* for clients with MPPP maybe higher values better */ |
2033 | ndev->tx_queue_len = 30; | 2013 | ndev->tx_queue_len = 30; |
2034 | 2014 | ||
2035 | for (i = 0; i < ETH_ALEN; i++) | ||
2036 | ndev->broadcast[i] = 0xff; | ||
2037 | |||
2038 | /* The ISDN-specific entries in the device structure. */ | 2015 | /* The ISDN-specific entries in the device structure. */ |
2039 | ndev->open = &isdn_net_open; | 2016 | ndev->open = &isdn_net_open; |
2040 | ndev->hard_start_xmit = &isdn_net_start_xmit; | 2017 | ndev->hard_start_xmit = &isdn_net_start_xmit; |
@@ -2052,7 +2029,6 @@ isdn_net_init(struct net_device *ndev) | |||
2052 | ndev->hard_header_len = ETH_HLEN + max_hlhdr_len; | 2029 | ndev->hard_header_len = ETH_HLEN + max_hlhdr_len; |
2053 | ndev->stop = &isdn_net_close; | 2030 | ndev->stop = &isdn_net_close; |
2054 | ndev->get_stats = &isdn_net_get_stats; | 2031 | ndev->get_stats = &isdn_net_get_stats; |
2055 | ndev->rebuild_header = &isdn_net_rebuild_header; | ||
2056 | ndev->do_ioctl = NULL; | 2032 | ndev->do_ioctl = NULL; |
2057 | return 0; | 2033 | return 0; |
2058 | } | 2034 | } |
@@ -2861,21 +2837,14 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) | |||
2861 | } | 2837 | } |
2862 | if (cfg->p_encap != lp->p_encap) { | 2838 | if (cfg->p_encap != lp->p_encap) { |
2863 | if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) { | 2839 | if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) { |
2864 | p->dev.hard_header = NULL; | 2840 | p->dev.header_ops = NULL; |
2865 | p->dev.hard_header_cache = NULL; | ||
2866 | p->dev.header_cache_update = NULL; | ||
2867 | p->dev.flags = IFF_NOARP|IFF_POINTOPOINT; | 2841 | p->dev.flags = IFF_NOARP|IFF_POINTOPOINT; |
2868 | } else { | 2842 | } else { |
2869 | p->dev.hard_header = isdn_net_header; | 2843 | p->dev.header_ops = &isdn_header_ops; |
2870 | if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) { | 2844 | if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) |
2871 | p->dev.hard_header_cache = lp->org_hhc; | ||
2872 | p->dev.header_cache_update = lp->org_hcu; | ||
2873 | p->dev.flags = IFF_BROADCAST | IFF_MULTICAST; | 2845 | p->dev.flags = IFF_BROADCAST | IFF_MULTICAST; |
2874 | } else { | 2846 | else |
2875 | p->dev.hard_header_cache = NULL; | ||
2876 | p->dev.header_cache_update = NULL; | ||
2877 | p->dev.flags = IFF_NOARP|IFF_POINTOPOINT; | 2847 | p->dev.flags = IFF_NOARP|IFF_POINTOPOINT; |
2878 | } | ||
2879 | } | 2848 | } |
2880 | } | 2849 | } |
2881 | lp->p_encap = cfg->p_encap; | 2850 | lp->p_encap = cfg->p_encap; |
@@ -3127,8 +3096,6 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) | |||
3127 | ((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave; | 3096 | ((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave; |
3128 | } else { | 3097 | } else { |
3129 | /* Unregister only if it's a master-device */ | 3098 | /* Unregister only if it's a master-device */ |
3130 | p->dev.hard_header_cache = p->local->org_hhc; | ||
3131 | p->dev.header_cache_update = p->local->org_hcu; | ||
3132 | unregister_netdev(&p->dev); | 3099 | unregister_netdev(&p->dev); |
3133 | } | 3100 | } |
3134 | /* Unlink device from chain */ | 3101 | /* Unlink device from chain */ |