diff options
Diffstat (limited to 'drivers/net/wan/hdlc_fr.c')
| -rw-r--r-- | drivers/net/wan/hdlc_fr.c | 283 |
1 files changed, 114 insertions, 169 deletions
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index b45ab680d2d..7c6cb4f3179 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -33,21 +33,19 @@ */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/poll.h> #include <linux/errno.h> +#include <linux/etherdevice.h> +#include <linux/hdlc.h> #include <linux/if_arp.h> +#include <linux/inetdevice.h> #include <linux/init.h> -#include <linux/skbuff.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/pkt_sched.h> -#include <linux/random.h> -#include <linux/inetdevice.h> -#include <linux/lapb.h> +#include <linux/poll.h> #include <linux/rtnetlink.h> -#include <linux/etherdevice.h> -#include <linux/hdlc.h> +#include <linux/skbuff.h> +#include <linux/slab.h> #undef DEBUG_PKT #undef DEBUG_ECN @@ -97,7 +95,7 @@ typedef struct { unsigned ea1: 1; unsigned cr: 1; unsigned dlcih: 6; - + unsigned ea2: 1; unsigned de: 1; unsigned becn: 1; @@ -114,7 +112,7 @@ typedef struct { unsigned de: 1; unsigned ea2: 1; #endif -}__attribute__ ((packed)) fr_hdr; +}__packed fr_hdr; typedef struct pvc_device_struct { @@ -136,7 +134,6 @@ typedef struct pvc_device_struct { }state; }pvc_device; - struct frad_state { fr_proto settings; pvc_device *first_pvc; @@ -171,18 +168,12 @@ static inline void dlci_to_q922(u8 *hdr, u16 dlci) } -static inline struct frad_state * state(hdlc_device *hdlc) +static inline struct frad_state* state(hdlc_device *hdlc) { return(struct frad_state *)(hdlc->state); } -static __inline__ pvc_device* dev_to_pvc(struct net_device *dev) -{ - return dev->priv; -} - - static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) { pvc_device *pvc = state(hdlc)->first_pvc; @@ -191,7 +182,7 @@ static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) if (pvc->dlci == dlci) return pvc; if (pvc->dlci > dlci) - return NULL; /* the listed is sorted */ + return NULL; /* the list is sorted */ pvc = pvc->next; } @@ -212,14 +203,13 @@ static pvc_device* add_pvc(struct net_device *dev, u16 dlci) pvc_p = &(*pvc_p)->next; } - pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC); + pvc = kzalloc(sizeof(pvc_device), GFP_ATOMIC); #ifdef DEBUG_PVC printk(KERN_DEBUG "add_pvc: allocated pvc %p, frad %p\n", pvc, dev); #endif if (!pvc) return NULL; - memset(pvc, 0, sizeof(pvc_device)); pvc->dlci = dlci; pvc->frad = dev; pvc->next = *pvc_p; /* Put it in the chain */ @@ -288,31 +278,31 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) struct sk_buff *skb = *skb_p; switch (skb->protocol) { - case __constant_ntohs(NLPID_CCITT_ANSI_LMI): + case cpu_to_be16(NLPID_CCITT_ANSI_LMI): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_CCITT_ANSI_LMI; break; - case __constant_ntohs(NLPID_CISCO_LMI): + case cpu_to_be16(NLPID_CISCO_LMI): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_CISCO_LMI; break; - case __constant_ntohs(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_IP; break; - case __constant_ntohs(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IPV6): head_len = 4; skb_push(skb, head_len); skb->data[3] = NLPID_IPV6; break; - case __constant_ntohs(ETH_P_802_3): + case cpu_to_be16(ETH_P_802_3): head_len = 10; if (skb_headroom(skb) < head_len) { struct sk_buff *skb2 = skb_realloc_headroom(skb, @@ -340,7 +330,7 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) skb->data[5] = FR_PAD; skb->data[6] = FR_PAD; skb->data[7] = FR_PAD; - *(u16*)(skb->data + 8) = skb->protocol; + *(__be16*)(skb->data + 8) = skb->protocol; } dlci_to_q922(skb->data, dlci); @@ -352,7 +342,7 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) static int pvc_open(struct net_device *dev) { - pvc_device *pvc = dev_to_pvc(dev); + pvc_device *pvc = dev->ml_priv; if ((pvc->frad->flags & IFF_UP) == 0) return -EIO; /* Frad must be UP in order to activate PVC */ @@ -372,7 +362,7 @@ static int pvc_open(struct net_device *dev) static int pvc_close(struct net_device *dev) { - pvc_device *pvc = dev_to_pvc(dev); + pvc_device *pvc = dev->ml_priv; if (--pvc->open_count == 0) { hdlc_device *hdlc = dev_to_hdlc(pvc->frad); @@ -391,7 +381,7 @@ static int pvc_close(struct net_device *dev) static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - pvc_device *pvc = dev_to_pvc(dev); + pvc_device *pvc = dev->ml_priv; fr_proto_pvc_info info; if (ifr->ifr_settings.type == IF_GET_PROTO) { @@ -417,18 +407,9 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EINVAL; } - -static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) -{ - return &dev_to_desc(dev)->stats; -} - - - -static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev) { - pvc_device *pvc = dev_to_pvc(dev); - struct net_device_stats *stats = pvc_get_stats(dev); + pvc_device *pvc = dev->ml_priv; if (pvc->state.active) { if (dev->type == ARPHRD_ETHER) { @@ -438,54 +419,41 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) if (skb_tailroom(skb) < pad) if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) { - stats->tx_dropped++; + dev->stats.tx_dropped++; dev_kfree_skb(skb); - return 0; + return NETDEV_TX_OK; } skb_put(skb, pad); memset(skb->data + len, 0, pad); } - skb->protocol = __constant_htons(ETH_P_802_3); + skb->protocol = cpu_to_be16(ETH_P_802_3); } if (!fr_hard_header(&skb, pvc->dlci)) { - stats->tx_bytes += skb->len; - stats->tx_packets++; + dev->stats.tx_bytes += skb->len; + dev->stats.tx_packets++; if (pvc->state.fecn) /* TX Congestion counter */ - stats->tx_compressed++; + dev->stats.tx_compressed++; skb->dev = pvc->frad; dev_queue_xmit(skb); - return 0; + return NETDEV_TX_OK; } } - stats->tx_dropped++; + dev->stats.tx_dropped++; dev_kfree_skb(skb); - return 0; -} - - - -static int pvc_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; + return NETDEV_TX_OK; } - - static inline void fr_log_dlci_active(pvc_device *pvc) { - printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", - pvc->frad->name, - pvc->dlci, - pvc->main ? pvc->main->name : "", - pvc->main && pvc->ether ? " " : "", - pvc->ether ? pvc->ether->name : "", - pvc->state.new ? " new" : "", - !pvc->state.exist ? "deleted" : - pvc->state.active ? "active" : "inactive"); + netdev_info(pvc->frad, "DLCI %d [%s%s%s]%s %s\n", + pvc->dlci, + pvc->main ? pvc->main->name : "", + pvc->main && pvc->ether ? " " : "", + pvc->ether ? pvc->ether->name : "", + pvc->state.new ? " new" : "", + !pvc->state.exist ? "deleted" : + pvc->state.active ? "active" : "inactive"); } @@ -512,28 +480,26 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) if (dce && fullrep) { len += state(hdlc)->dce_pvc_count * (2 + stat_len); if (len > HDLC_MAX_MRU) { - printk(KERN_WARNING "%s: Too many PVCs while sending " - "LMI full report\n", dev->name); + netdev_warn(dev, "Too many PVCs while sending LMI full report\n"); return; } } skb = dev_alloc_skb(len); if (!skb) { - printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n", - dev->name); + netdev_warn(dev, "Memory squeeze on fr_lmi_send()\n"); return; } memset(skb->data, 0, len); skb_reserve(skb, 4); if (lmi == LMI_CISCO) { - skb->protocol = __constant_htons(NLPID_CISCO_LMI); + skb->protocol = cpu_to_be16(NLPID_CISCO_LMI); fr_hard_header(&skb, LMI_CISCO_DLCI); } else { - skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI); + skb->protocol = cpu_to_be16(NLPID_CCITT_ANSI_LMI); fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI); } - data = skb->tail; + data = skb_tail_pointer(skb); data[i++] = LMI_CALLREF; data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY; if (lmi == LMI_ANSI) @@ -590,7 +556,7 @@ static void fr_lmi_send(struct net_device *dev, int fullrep) skb_put(skb, i); skb->priority = TC_PRIO_CONTROL; skb->dev = dev; - skb->nh.raw = skb->data; + skb_reset_network_header(skb); dev_queue_xmit(skb); } @@ -646,8 +612,7 @@ static void fr_timer(unsigned long arg) state(hdlc)->last_errors <<= 1; /* Shift the list */ if (state(hdlc)->request) { if (state(hdlc)->reliable) - printk(KERN_INFO "%s: No LMI status reply " - "received\n", dev->name); + netdev_info(dev, "No LMI status reply received\n"); state(hdlc)->last_errors |= 1; } @@ -659,8 +624,7 @@ static void fr_timer(unsigned long arg) } if (state(hdlc)->reliable != reliable) { - printk(KERN_INFO "%s: Link %sreliable\n", dev->name, - reliable ? "" : "un"); + netdev_info(dev, "Link %sreliable\n", reliable ? "" : "un"); fr_set_link_state(reliable, dev); } @@ -696,33 +660,32 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH)) { - printk(KERN_INFO "%s: Short LMI frame\n", dev->name); + netdev_info(dev, "Short LMI frame\n"); return 1; } if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI : NLPID_CCITT_ANSI_LMI)) { - printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n", - dev->name); + netdev_info(dev, "Received non-LMI frame with LMI DLCI\n"); return 1; } if (skb->data[4] != LMI_CALLREF) { - printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n", - dev->name, skb->data[4]); + netdev_info(dev, "Invalid LMI Call reference (0x%02X)\n", + skb->data[4]); return 1; } if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) { - printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n", - dev->name, skb->data[5]); + netdev_info(dev, "Invalid LMI Message type (0x%02X)\n", + skb->data[5]); return 1; } if (lmi == LMI_ANSI) { if (skb->data[6] != LMI_ANSI_LOCKSHIFT) { - printk(KERN_INFO "%s: Not ANSI locking shift in LMI" - " message (0x%02X)\n", dev->name, skb->data[6]); + netdev_info(dev, "Not ANSI locking shift in LMI message (0x%02X)\n", + skb->data[6]); return 1; } i = 7; @@ -731,34 +694,34 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : LMI_ANSI_CISCO_REPTYPE)) { - printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n", - dev->name, skb->data[i]); + netdev_info(dev, "Not an LMI Report type IE (0x%02X)\n", + skb->data[i]); return 1; } if (skb->data[++i] != LMI_REPT_LEN) { - printk(KERN_INFO "%s: Invalid LMI Report type IE length" - " (%u)\n", dev->name, skb->data[i]); + netdev_info(dev, "Invalid LMI Report type IE length (%u)\n", + skb->data[i]); return 1; } reptype = skb->data[++i]; if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) { - printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n", - dev->name, reptype); + netdev_info(dev, "Unsupported LMI Report type (0x%02X)\n", + reptype); return 1; } if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE)) { - printk(KERN_INFO "%s: Not an LMI Link integrity verification" - " IE (0x%02X)\n", dev->name, skb->data[i]); + netdev_info(dev, "Not an LMI Link integrity verification IE (0x%02X)\n", + skb->data[i]); return 1; } if (skb->data[++i] != LMI_INTEG_LEN) { - printk(KERN_INFO "%s: Invalid LMI Link integrity verification" - " IE length (%u)\n", dev->name, skb->data[i]); + netdev_info(dev, "Invalid LMI Link integrity verification IE length (%u)\n", + skb->data[i]); return 1; } i++; @@ -832,14 +795,14 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : LMI_ANSI_CISCO_PVCSTAT)) { - printk(KERN_INFO "%s: Not an LMI PVC status IE" - " (0x%02X)\n", dev->name, skb->data[i]); + netdev_info(dev, "Not an LMI PVC status IE (0x%02X)\n", + skb->data[i]); return 1; } if (skb->data[++i] != stat_len) { - printk(KERN_INFO "%s: Invalid LMI PVC status IE length" - " (%u)\n", dev->name, skb->data[i]); + netdev_info(dev, "Invalid LMI PVC status IE length (%u)\n", + skb->data[i]); return 1; } i++; @@ -860,9 +823,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) pvc = add_pvc(dev, dlci); if (!pvc && !no_ram) { - printk(KERN_WARNING - "%s: Memory squeeze on fr_lmi_recv()\n", - dev->name); + netdev_warn(dev, "Memory squeeze on fr_lmi_recv()\n"); no_ram = 1; } @@ -933,8 +894,8 @@ static int fr_rx(struct sk_buff *skb) pvc = find_pvc(hdlc, dlci); if (!pvc) { #ifdef DEBUG_PKT - printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n", - frad->name, dlci); + netdev_info(frad, "No PVC for received frame's DLCI %d\n", + dlci); #endif dev_kfree_skb_any(skb); return NET_RX_DROP; @@ -958,7 +919,7 @@ static int fr_rx(struct sk_buff *skb) if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { - dev_to_desc(frad)->stats.rx_dropped++; + frad->stats.rx_dropped++; return NET_RX_DROP; } @@ -974,8 +935,8 @@ static int fr_rx(struct sk_buff *skb) } else if (skb->len > 10 && data[3] == FR_PAD && data[4] == NLPID_SNAP && data[5] == FR_PAD) { - u16 oui = ntohs(*(u16*)(data + 6)); - u16 pid = ntohs(*(u16*)(data + 8)); + u16 oui = ntohs(*(__be16*)(data + 6)); + u16 pid = ntohs(*(__be16*)(data + 8)); skb_pull(skb, 10); switch ((((u32)oui) << 16) | pid) { @@ -993,24 +954,23 @@ static int fr_rx(struct sk_buff *skb) break; default: - printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " - "PID=%x\n", frad->name, oui, pid); + netdev_info(frad, "Unsupported protocol, OUI=%x PID=%x\n", + oui, pid); dev_kfree_skb_any(skb); return NET_RX_DROP; } } else { - printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " - "length = %i\n", frad->name, data[3], skb->len); + netdev_info(frad, "Unsupported protocol, NLPID=%x length=%i\n", + data[3], skb->len); dev_kfree_skb_any(skb); return NET_RX_DROP; } if (dev) { - struct net_device_stats *stats = pvc_get_stats(dev); - stats->rx_packets++; /* PVC traffic */ - stats->rx_bytes += skb->len; + dev->stats.rx_packets++; /* PVC traffic */ + dev->stats.rx_bytes += skb->len; if (pvc->state.becn) - stats->rx_compressed++; + dev->stats.rx_compressed++; skb->dev = dev; netif_rx(skb); return NET_RX_SUCCESS; @@ -1020,7 +980,7 @@ static int fr_rx(struct sk_buff *skb) } rx_error: - dev_to_desc(frad)->stats.rx_errors++; /* Mark error */ + frad->stats.rx_errors++; /* Mark error */ dev_kfree_skb_any(skb); return NET_RX_DROP; } @@ -1086,22 +1046,26 @@ static void pvc_setup(struct net_device *dev) dev->flags = IFF_POINTOPOINT; dev->hard_header_len = 10; dev->addr_len = 2; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; } +static const struct net_device_ops pvc_ops = { + .ndo_open = pvc_open, + .ndo_stop = pvc_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = pvc_xmit, + .ndo_do_ioctl = pvc_ioctl, +}; + static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) { hdlc_device *hdlc = dev_to_hdlc(frad); - pvc_device *pvc = NULL; + pvc_device *pvc; struct net_device *dev; - int result, used; - char * prefix = "pvc%d"; - - if (type == ARPHRD_ETHER) - prefix = "pvceth%d"; + int used; if ((pvc = add_pvc(frad, dlci)) == NULL) { - printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", - frad->name); + netdev_warn(frad, "Memory squeeze on fr_add_pvc()\n"); return -ENOBUFS; } @@ -1110,43 +1074,28 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) used = pvc_is_used(pvc); - if (type == ARPHRD_ETHER) - dev = alloc_netdev(sizeof(struct net_device_stats), - "pvceth%d", ether_setup); - else - dev = alloc_netdev(sizeof(struct net_device_stats), - "pvc%d", pvc_setup); + if (type == ARPHRD_ETHER) { + dev = alloc_netdev(0, "pvceth%d", ether_setup); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + } else + dev = alloc_netdev(0, "pvc%d", pvc_setup); if (!dev) { - printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", - frad->name); + netdev_warn(frad, "Memory squeeze on fr_pvc()\n"); delete_unused_pvcs(hdlc); return -ENOBUFS; } - if (type == ARPHRD_ETHER) { - memcpy(dev->dev_addr, "\x00\x01", 2); - get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); - } else { - *(u16*)dev->dev_addr = htons(dlci); + if (type == ARPHRD_ETHER) + eth_hw_addr_random(dev); + else { + *(__be16*)dev->dev_addr = htons(dlci); dlci_to_q922(dev->broadcast, dlci); } - dev->hard_start_xmit = pvc_xmit; - dev->get_stats = pvc_get_stats; - dev->open = pvc_open; - dev->stop = pvc_close; - dev->do_ioctl = pvc_ioctl; - dev->change_mtu = pvc_change_mtu; + dev->netdev_ops = &pvc_ops; dev->mtu = HDLC_MAX_MTU; dev->tx_queue_len = 0; - dev->priv = pvc; - - result = dev_alloc_name(dev, dev->name); - if (result < 0) { - free_netdev(dev); - delete_unused_pvcs(hdlc); - return result; - } + dev->ml_priv = pvc; if (register_netdevice(dev) != 0) { free_netdev(dev); @@ -1221,6 +1170,7 @@ static struct hdlc_proto proto = { .stop = fr_stop, .detach = fr_destroy, .ioctl = fr_ioctl, + .netif_rx = fr_rx, .module = THIS_MODULE, }; @@ -1248,10 +1198,10 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) return 0; case IF_PROTO_FR: - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - if(dev->flags & IFF_UP) + if (dev->flags & IFF_UP) return -EBUSY; if (copy_from_user(&new_settings, fr_s, size)) @@ -1279,7 +1229,7 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) return result; if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */ - result = attach_hdlc_protocol(dev, &proto, fr_rx, + result = attach_hdlc_protocol(dev, &proto, sizeof(struct frad_state)); if (result) return result; @@ -1287,12 +1237,7 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) state(hdlc)->dce_pvc_count = 0; } memcpy(&state(hdlc)->settings, &new_settings, size); - - dev->hard_start_xmit = hdlc->xmit; - dev->hard_header = NULL; dev->type = ARPHRD_FRAD; - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - dev->addr_len = 0; return 0; case IF_PROTO_FR_ADD_PVC: @@ -1302,7 +1247,7 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */ return -EINVAL; - if(!capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user(&pvc, ifr->ifr_settings.ifs_ifsu.fr_pvc, |
