aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wan/hdlc_fr.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 17:41:24 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 17:41:24 -0400
commita77c64c1a641950626181b4857abb701d8f38ccc (patch)
tree9bfd2a99cc969b3d863d583b9ef18114a4fc4793 /drivers/net/wan/hdlc_fr.c
parentac7f6b5e44cb0982b98c31fa33298ba73fb5dcfc (diff)
parent0ba8821b12231386c8c1d506c682061f7225ae49 (diff)
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (48 commits) [PATCH] bonding: update version number [PATCH] git-netdev-all: pc300_tty build fix [PATCH] Make PC300 WAN driver compile again [PATCH] Modularize generic HDLC [PATCH] more s2io __iomem annotations [PATCH] restore __iomem annotations in e1000 [PATCH] 64bit bugs in s2io [PATCH] bonding: Fix primary selection error at enslavement time [PATCH] bonding: Don't mangle LACPDUs [PATCH] bonding: Validate probe replies in ARP monitor [PATCH] bonding: Don't release slaves when master is admin down [PATCH] bonding: Add priv_flag to avoid event mishandling [PATCH] bonding: Handle large hard_header_len [PATCH] bonding: Remove unneeded NULL test [PATCH] bonding: Format fix in seq_printf call [PATCH] bonding: Convert delay value from s16 to int [PATCH] bonding: Allow bonding to enslave a 10 Gig adapter Delete unused drivers/net/gt64240eth.h [PATCH] skge: fiber support [PATCH] fix possible NULL ptr deref in forcedeth ...
Diffstat (limited to 'drivers/net/wan/hdlc_fr.c')
-rw-r--r--drivers/net/wan/hdlc_fr.c389
1 files changed, 237 insertions, 152 deletions
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 7bb737bbdeb9..b45ab680d2d6 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -2,7 +2,7 @@
2 * Generic HDLC support routines for Linux 2 * Generic HDLC support routines for Linux
3 * Frame Relay support 3 * Frame Relay support
4 * 4 *
5 * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl> 5 * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License 8 * under the terms of version 2 of the GNU General Public License
@@ -52,6 +52,8 @@
52#undef DEBUG_PKT 52#undef DEBUG_PKT
53#undef DEBUG_ECN 53#undef DEBUG_ECN
54#undef DEBUG_LINK 54#undef DEBUG_LINK
55#undef DEBUG_PROTO
56#undef DEBUG_PVC
55 57
56#define FR_UI 0x03 58#define FR_UI 0x03
57#define FR_PAD 0x00 59#define FR_PAD 0x00
@@ -115,13 +117,53 @@ typedef struct {
115}__attribute__ ((packed)) fr_hdr; 117}__attribute__ ((packed)) fr_hdr;
116 118
117 119
120typedef struct pvc_device_struct {
121 struct net_device *frad;
122 struct net_device *main;
123 struct net_device *ether; /* bridged Ethernet interface */
124 struct pvc_device_struct *next; /* Sorted in ascending DLCI order */
125 int dlci;
126 int open_count;
127
128 struct {
129 unsigned int new: 1;
130 unsigned int active: 1;
131 unsigned int exist: 1;
132 unsigned int deleted: 1;
133 unsigned int fecn: 1;
134 unsigned int becn: 1;
135 unsigned int bandwidth; /* Cisco LMI reporting only */
136 }state;
137}pvc_device;
138
139
140struct frad_state {
141 fr_proto settings;
142 pvc_device *first_pvc;
143 int dce_pvc_count;
144
145 struct timer_list timer;
146 unsigned long last_poll;
147 int reliable;
148 int dce_changed;
149 int request;
150 int fullrep_sent;
151 u32 last_errors; /* last errors bit list */
152 u8 n391cnt;
153 u8 txseq; /* TX sequence number */
154 u8 rxseq; /* RX sequence number */
155};
156
157
158static int fr_ioctl(struct net_device *dev, struct ifreq *ifr);
159
160
118static inline u16 q922_to_dlci(u8 *hdr) 161static inline u16 q922_to_dlci(u8 *hdr)
119{ 162{
120 return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4); 163 return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4);
121} 164}
122 165
123 166
124
125static inline void dlci_to_q922(u8 *hdr, u16 dlci) 167static inline void dlci_to_q922(u8 *hdr, u16 dlci)
126{ 168{
127 hdr[0] = (dlci >> 2) & 0xFC; 169 hdr[0] = (dlci >> 2) & 0xFC;
@@ -129,10 +171,21 @@ static inline void dlci_to_q922(u8 *hdr, u16 dlci)
129} 171}
130 172
131 173
174static inline struct frad_state * state(hdlc_device *hdlc)
175{
176 return(struct frad_state *)(hdlc->state);
177}
178
179
180static __inline__ pvc_device* dev_to_pvc(struct net_device *dev)
181{
182 return dev->priv;
183}
184
132 185
133static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) 186static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
134{ 187{
135 pvc_device *pvc = hdlc->state.fr.first_pvc; 188 pvc_device *pvc = state(hdlc)->first_pvc;
136 189
137 while (pvc) { 190 while (pvc) {
138 if (pvc->dlci == dlci) 191 if (pvc->dlci == dlci)
@@ -146,10 +199,10 @@ static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
146} 199}
147 200
148 201
149static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci) 202static pvc_device* add_pvc(struct net_device *dev, u16 dlci)
150{ 203{
151 hdlc_device *hdlc = dev_to_hdlc(dev); 204 hdlc_device *hdlc = dev_to_hdlc(dev);
152 pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc; 205 pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc;
153 206
154 while (*pvc_p) { 207 while (*pvc_p) {
155 if ((*pvc_p)->dlci == dlci) 208 if ((*pvc_p)->dlci == dlci)
@@ -160,12 +213,15 @@ static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
160 } 213 }
161 214
162 pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC); 215 pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC);
216#ifdef DEBUG_PVC
217 printk(KERN_DEBUG "add_pvc: allocated pvc %p, frad %p\n", pvc, dev);
218#endif
163 if (!pvc) 219 if (!pvc)
164 return NULL; 220 return NULL;
165 221
166 memset(pvc, 0, sizeof(pvc_device)); 222 memset(pvc, 0, sizeof(pvc_device));
167 pvc->dlci = dlci; 223 pvc->dlci = dlci;
168 pvc->master = dev; 224 pvc->frad = dev;
169 pvc->next = *pvc_p; /* Put it in the chain */ 225 pvc->next = *pvc_p; /* Put it in the chain */
170 *pvc_p = pvc; 226 *pvc_p = pvc;
171 return pvc; 227 return pvc;
@@ -174,7 +230,7 @@ static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
174 230
175static inline int pvc_is_used(pvc_device *pvc) 231static inline int pvc_is_used(pvc_device *pvc)
176{ 232{
177 return pvc->main != NULL || pvc->ether != NULL; 233 return pvc->main || pvc->ether;
178} 234}
179 235
180 236
@@ -200,11 +256,14 @@ static inline void pvc_carrier(int on, pvc_device *pvc)
200 256
201static inline void delete_unused_pvcs(hdlc_device *hdlc) 257static inline void delete_unused_pvcs(hdlc_device *hdlc)
202{ 258{
203 pvc_device **pvc_p = &hdlc->state.fr.first_pvc; 259 pvc_device **pvc_p = &state(hdlc)->first_pvc;
204 260
205 while (*pvc_p) { 261 while (*pvc_p) {
206 if (!pvc_is_used(*pvc_p)) { 262 if (!pvc_is_used(*pvc_p)) {
207 pvc_device *pvc = *pvc_p; 263 pvc_device *pvc = *pvc_p;
264#ifdef DEBUG_PVC
265 printk(KERN_DEBUG "freeing unused pvc: %p\n", pvc);
266#endif
208 *pvc_p = pvc->next; 267 *pvc_p = pvc->next;
209 kfree(pvc); 268 kfree(pvc);
210 continue; 269 continue;
@@ -295,16 +354,16 @@ static int pvc_open(struct net_device *dev)
295{ 354{
296 pvc_device *pvc = dev_to_pvc(dev); 355 pvc_device *pvc = dev_to_pvc(dev);
297 356
298 if ((pvc->master->flags & IFF_UP) == 0) 357 if ((pvc->frad->flags & IFF_UP) == 0)
299 return -EIO; /* Master must be UP in order to activate PVC */ 358 return -EIO; /* Frad must be UP in order to activate PVC */
300 359
301 if (pvc->open_count++ == 0) { 360 if (pvc->open_count++ == 0) {
302 hdlc_device *hdlc = dev_to_hdlc(pvc->master); 361 hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
303 if (hdlc->state.fr.settings.lmi == LMI_NONE) 362 if (state(hdlc)->settings.lmi == LMI_NONE)
304 pvc->state.active = netif_carrier_ok(pvc->master); 363 pvc->state.active = netif_carrier_ok(pvc->frad);
305 364
306 pvc_carrier(pvc->state.active, pvc); 365 pvc_carrier(pvc->state.active, pvc);
307 hdlc->state.fr.dce_changed = 1; 366 state(hdlc)->dce_changed = 1;
308 } 367 }
309 return 0; 368 return 0;
310} 369}
@@ -316,12 +375,12 @@ static int pvc_close(struct net_device *dev)
316 pvc_device *pvc = dev_to_pvc(dev); 375 pvc_device *pvc = dev_to_pvc(dev);
317 376
318 if (--pvc->open_count == 0) { 377 if (--pvc->open_count == 0) {
319 hdlc_device *hdlc = dev_to_hdlc(pvc->master); 378 hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
320 if (hdlc->state.fr.settings.lmi == LMI_NONE) 379 if (state(hdlc)->settings.lmi == LMI_NONE)
321 pvc->state.active = 0; 380 pvc->state.active = 0;
322 381
323 if (hdlc->state.fr.settings.dce) { 382 if (state(hdlc)->settings.dce) {
324 hdlc->state.fr.dce_changed = 1; 383 state(hdlc)->dce_changed = 1;
325 pvc->state.active = 0; 384 pvc->state.active = 0;
326 } 385 }
327 } 386 }
@@ -348,7 +407,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
348 } 407 }
349 408
350 info.dlci = pvc->dlci; 409 info.dlci = pvc->dlci;
351 memcpy(info.master, pvc->master->name, IFNAMSIZ); 410 memcpy(info.master, pvc->frad->name, IFNAMSIZ);
352 if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info, 411 if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info,
353 &info, sizeof(info))) 412 &info, sizeof(info)))
354 return -EFAULT; 413 return -EFAULT;
@@ -361,7 +420,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
361 420
362static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) 421static inline struct net_device_stats *pvc_get_stats(struct net_device *dev)
363{ 422{
364 return netdev_priv(dev); 423 return &dev_to_desc(dev)->stats;
365} 424}
366 425
367 426
@@ -393,7 +452,7 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
393 stats->tx_packets++; 452 stats->tx_packets++;
394 if (pvc->state.fecn) /* TX Congestion counter */ 453 if (pvc->state.fecn) /* TX Congestion counter */
395 stats->tx_compressed++; 454 stats->tx_compressed++;
396 skb->dev = pvc->master; 455 skb->dev = pvc->frad;
397 dev_queue_xmit(skb); 456 dev_queue_xmit(skb);
398 return 0; 457 return 0;
399 } 458 }
@@ -419,7 +478,7 @@ static int pvc_change_mtu(struct net_device *dev, int new_mtu)
419static inline void fr_log_dlci_active(pvc_device *pvc) 478static inline void fr_log_dlci_active(pvc_device *pvc)
420{ 479{
421 printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", 480 printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
422 pvc->master->name, 481 pvc->frad->name,
423 pvc->dlci, 482 pvc->dlci,
424 pvc->main ? pvc->main->name : "", 483 pvc->main ? pvc->main->name : "",
425 pvc->main && pvc->ether ? " " : "", 484 pvc->main && pvc->ether ? " " : "",
@@ -438,21 +497,20 @@ static inline u8 fr_lmi_nextseq(u8 x)
438} 497}
439 498
440 499
441
442static void fr_lmi_send(struct net_device *dev, int fullrep) 500static void fr_lmi_send(struct net_device *dev, int fullrep)
443{ 501{
444 hdlc_device *hdlc = dev_to_hdlc(dev); 502 hdlc_device *hdlc = dev_to_hdlc(dev);
445 struct sk_buff *skb; 503 struct sk_buff *skb;
446 pvc_device *pvc = hdlc->state.fr.first_pvc; 504 pvc_device *pvc = state(hdlc)->first_pvc;
447 int lmi = hdlc->state.fr.settings.lmi; 505 int lmi = state(hdlc)->settings.lmi;
448 int dce = hdlc->state.fr.settings.dce; 506 int dce = state(hdlc)->settings.dce;
449 int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH; 507 int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
450 int stat_len = (lmi == LMI_CISCO) ? 6 : 3; 508 int stat_len = (lmi == LMI_CISCO) ? 6 : 3;
451 u8 *data; 509 u8 *data;
452 int i = 0; 510 int i = 0;
453 511
454 if (dce && fullrep) { 512 if (dce && fullrep) {
455 len += hdlc->state.fr.dce_pvc_count * (2 + stat_len); 513 len += state(hdlc)->dce_pvc_count * (2 + stat_len);
456 if (len > HDLC_MAX_MRU) { 514 if (len > HDLC_MAX_MRU) {
457 printk(KERN_WARNING "%s: Too many PVCs while sending " 515 printk(KERN_WARNING "%s: Too many PVCs while sending "
458 "LMI full report\n", dev->name); 516 "LMI full report\n", dev->name);
@@ -486,8 +544,9 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
486 data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY; 544 data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;
487 data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE; 545 data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE;
488 data[i++] = LMI_INTEG_LEN; 546 data[i++] = LMI_INTEG_LEN;
489 data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq); 547 data[i++] = state(hdlc)->txseq =
490 data[i++] = hdlc->state.fr.rxseq; 548 fr_lmi_nextseq(state(hdlc)->txseq);
549 data[i++] = state(hdlc)->rxseq;
491 550
492 if (dce && fullrep) { 551 if (dce && fullrep) {
493 while (pvc) { 552 while (pvc) {
@@ -496,7 +555,7 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
496 data[i++] = stat_len; 555 data[i++] = stat_len;
497 556
498 /* LMI start/restart */ 557 /* LMI start/restart */
499 if (hdlc->state.fr.reliable && !pvc->state.exist) { 558 if (state(hdlc)->reliable && !pvc->state.exist) {
500 pvc->state.exist = pvc->state.new = 1; 559 pvc->state.exist = pvc->state.new = 1;
501 fr_log_dlci_active(pvc); 560 fr_log_dlci_active(pvc);
502 } 561 }
@@ -541,15 +600,15 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
541static void fr_set_link_state(int reliable, struct net_device *dev) 600static void fr_set_link_state(int reliable, struct net_device *dev)
542{ 601{
543 hdlc_device *hdlc = dev_to_hdlc(dev); 602 hdlc_device *hdlc = dev_to_hdlc(dev);
544 pvc_device *pvc = hdlc->state.fr.first_pvc; 603 pvc_device *pvc = state(hdlc)->first_pvc;
545 604
546 hdlc->state.fr.reliable = reliable; 605 state(hdlc)->reliable = reliable;
547 if (reliable) { 606 if (reliable) {
548 netif_dormant_off(dev); 607 netif_dormant_off(dev);
549 hdlc->state.fr.n391cnt = 0; /* Request full status */ 608 state(hdlc)->n391cnt = 0; /* Request full status */
550 hdlc->state.fr.dce_changed = 1; 609 state(hdlc)->dce_changed = 1;
551 610
552 if (hdlc->state.fr.settings.lmi == LMI_NONE) { 611 if (state(hdlc)->settings.lmi == LMI_NONE) {
553 while (pvc) { /* Activate all PVCs */ 612 while (pvc) { /* Activate all PVCs */
554 pvc_carrier(1, pvc); 613 pvc_carrier(1, pvc);
555 pvc->state.exist = pvc->state.active = 1; 614 pvc->state.exist = pvc->state.active = 1;
@@ -563,7 +622,7 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
563 pvc_carrier(0, pvc); 622 pvc_carrier(0, pvc);
564 pvc->state.exist = pvc->state.active = 0; 623 pvc->state.exist = pvc->state.active = 0;
565 pvc->state.new = 0; 624 pvc->state.new = 0;
566 if (!hdlc->state.fr.settings.dce) 625 if (!state(hdlc)->settings.dce)
567 pvc->state.bandwidth = 0; 626 pvc->state.bandwidth = 0;
568 pvc = pvc->next; 627 pvc = pvc->next;
569 } 628 }
@@ -571,7 +630,6 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
571} 630}
572 631
573 632
574
575static void fr_timer(unsigned long arg) 633static void fr_timer(unsigned long arg)
576{ 634{
577 struct net_device *dev = (struct net_device *)arg; 635 struct net_device *dev = (struct net_device *)arg;
@@ -579,62 +637,61 @@ static void fr_timer(unsigned long arg)
579 int i, cnt = 0, reliable; 637 int i, cnt = 0, reliable;
580 u32 list; 638 u32 list;
581 639
582 if (hdlc->state.fr.settings.dce) { 640 if (state(hdlc)->settings.dce) {
583 reliable = hdlc->state.fr.request && 641 reliable = state(hdlc)->request &&
584 time_before(jiffies, hdlc->state.fr.last_poll + 642 time_before(jiffies, state(hdlc)->last_poll +
585 hdlc->state.fr.settings.t392 * HZ); 643 state(hdlc)->settings.t392 * HZ);
586 hdlc->state.fr.request = 0; 644 state(hdlc)->request = 0;
587 } else { 645 } else {
588 hdlc->state.fr.last_errors <<= 1; /* Shift the list */ 646 state(hdlc)->last_errors <<= 1; /* Shift the list */
589 if (hdlc->state.fr.request) { 647 if (state(hdlc)->request) {
590 if (hdlc->state.fr.reliable) 648 if (state(hdlc)->reliable)
591 printk(KERN_INFO "%s: No LMI status reply " 649 printk(KERN_INFO "%s: No LMI status reply "
592 "received\n", dev->name); 650 "received\n", dev->name);
593 hdlc->state.fr.last_errors |= 1; 651 state(hdlc)->last_errors |= 1;
594 } 652 }
595 653
596 list = hdlc->state.fr.last_errors; 654 list = state(hdlc)->last_errors;
597 for (i = 0; i < hdlc->state.fr.settings.n393; i++, list >>= 1) 655 for (i = 0; i < state(hdlc)->settings.n393; i++, list >>= 1)
598 cnt += (list & 1); /* errors count */ 656 cnt += (list & 1); /* errors count */
599 657
600 reliable = (cnt < hdlc->state.fr.settings.n392); 658 reliable = (cnt < state(hdlc)->settings.n392);
601 } 659 }
602 660
603 if (hdlc->state.fr.reliable != reliable) { 661 if (state(hdlc)->reliable != reliable) {
604 printk(KERN_INFO "%s: Link %sreliable\n", dev->name, 662 printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
605 reliable ? "" : "un"); 663 reliable ? "" : "un");
606 fr_set_link_state(reliable, dev); 664 fr_set_link_state(reliable, dev);
607 } 665 }
608 666
609 if (hdlc->state.fr.settings.dce) 667 if (state(hdlc)->settings.dce)
610 hdlc->state.fr.timer.expires = jiffies + 668 state(hdlc)->timer.expires = jiffies +
611 hdlc->state.fr.settings.t392 * HZ; 669 state(hdlc)->settings.t392 * HZ;
612 else { 670 else {
613 if (hdlc->state.fr.n391cnt) 671 if (state(hdlc)->n391cnt)
614 hdlc->state.fr.n391cnt--; 672 state(hdlc)->n391cnt--;
615 673
616 fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0); 674 fr_lmi_send(dev, state(hdlc)->n391cnt == 0);
617 675
618 hdlc->state.fr.last_poll = jiffies; 676 state(hdlc)->last_poll = jiffies;
619 hdlc->state.fr.request = 1; 677 state(hdlc)->request = 1;
620 hdlc->state.fr.timer.expires = jiffies + 678 state(hdlc)->timer.expires = jiffies +
621 hdlc->state.fr.settings.t391 * HZ; 679 state(hdlc)->settings.t391 * HZ;
622 } 680 }
623 681
624 hdlc->state.fr.timer.function = fr_timer; 682 state(hdlc)->timer.function = fr_timer;
625 hdlc->state.fr.timer.data = arg; 683 state(hdlc)->timer.data = arg;
626 add_timer(&hdlc->state.fr.timer); 684 add_timer(&state(hdlc)->timer);
627} 685}
628 686
629 687
630
631static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) 688static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
632{ 689{
633 hdlc_device *hdlc = dev_to_hdlc(dev); 690 hdlc_device *hdlc = dev_to_hdlc(dev);
634 pvc_device *pvc; 691 pvc_device *pvc;
635 u8 rxseq, txseq; 692 u8 rxseq, txseq;
636 int lmi = hdlc->state.fr.settings.lmi; 693 int lmi = state(hdlc)->settings.lmi;
637 int dce = hdlc->state.fr.settings.dce; 694 int dce = state(hdlc)->settings.dce;
638 int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i; 695 int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i;
639 696
640 if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH : 697 if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
@@ -645,8 +702,8 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
645 702
646 if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI : 703 if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
647 NLPID_CCITT_ANSI_LMI)) { 704 NLPID_CCITT_ANSI_LMI)) {
648 printk(KERN_INFO "%s: Received non-LMI frame with LMI" 705 printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
649 " DLCI\n", dev->name); 706 dev->name);
650 return 1; 707 return 1;
651 } 708 }
652 709
@@ -706,53 +763,53 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
706 } 763 }
707 i++; 764 i++;
708 765
709 hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */ 766 state(hdlc)->rxseq = skb->data[i++]; /* TX sequence from peer */
710 rxseq = skb->data[i++]; /* Should confirm our sequence */ 767 rxseq = skb->data[i++]; /* Should confirm our sequence */
711 768
712 txseq = hdlc->state.fr.txseq; 769 txseq = state(hdlc)->txseq;
713 770
714 if (dce) 771 if (dce)
715 hdlc->state.fr.last_poll = jiffies; 772 state(hdlc)->last_poll = jiffies;
716 773
717 error = 0; 774 error = 0;
718 if (!hdlc->state.fr.reliable) 775 if (!state(hdlc)->reliable)
719 error = 1; 776 error = 1;
720 777
721 if (rxseq == 0 || rxseq != txseq) { 778 if (rxseq == 0 || rxseq != txseq) { /* Ask for full report next time */
722 hdlc->state.fr.n391cnt = 0; /* Ask for full report next time */ 779 state(hdlc)->n391cnt = 0;
723 error = 1; 780 error = 1;
724 } 781 }
725 782
726 if (dce) { 783 if (dce) {
727 if (hdlc->state.fr.fullrep_sent && !error) { 784 if (state(hdlc)->fullrep_sent && !error) {
728/* Stop sending full report - the last one has been confirmed by DTE */ 785/* Stop sending full report - the last one has been confirmed by DTE */
729 hdlc->state.fr.fullrep_sent = 0; 786 state(hdlc)->fullrep_sent = 0;
730 pvc = hdlc->state.fr.first_pvc; 787 pvc = state(hdlc)->first_pvc;
731 while (pvc) { 788 while (pvc) {
732 if (pvc->state.new) { 789 if (pvc->state.new) {
733 pvc->state.new = 0; 790 pvc->state.new = 0;
734 791
735/* Tell DTE that new PVC is now active */ 792/* Tell DTE that new PVC is now active */
736 hdlc->state.fr.dce_changed = 1; 793 state(hdlc)->dce_changed = 1;
737 } 794 }
738 pvc = pvc->next; 795 pvc = pvc->next;
739 } 796 }
740 } 797 }
741 798
742 if (hdlc->state.fr.dce_changed) { 799 if (state(hdlc)->dce_changed) {
743 reptype = LMI_FULLREP; 800 reptype = LMI_FULLREP;
744 hdlc->state.fr.fullrep_sent = 1; 801 state(hdlc)->fullrep_sent = 1;
745 hdlc->state.fr.dce_changed = 0; 802 state(hdlc)->dce_changed = 0;
746 } 803 }
747 804
748 hdlc->state.fr.request = 1; /* got request */ 805 state(hdlc)->request = 1; /* got request */
749 fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0); 806 fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
750 return 0; 807 return 0;
751 } 808 }
752 809
753 /* DTE */ 810 /* DTE */
754 811
755 hdlc->state.fr.request = 0; /* got response, no request pending */ 812 state(hdlc)->request = 0; /* got response, no request pending */
756 813
757 if (error) 814 if (error)
758 return 0; 815 return 0;
@@ -760,7 +817,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
760 if (reptype != LMI_FULLREP) 817 if (reptype != LMI_FULLREP)
761 return 0; 818 return 0;
762 819
763 pvc = hdlc->state.fr.first_pvc; 820 pvc = state(hdlc)->first_pvc;
764 821
765 while (pvc) { 822 while (pvc) {
766 pvc->state.deleted = 1; 823 pvc->state.deleted = 1;
@@ -827,7 +884,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
827 i += stat_len; 884 i += stat_len;
828 } 885 }
829 886
830 pvc = hdlc->state.fr.first_pvc; 887 pvc = state(hdlc)->first_pvc;
831 888
832 while (pvc) { 889 while (pvc) {
833 if (pvc->state.deleted && pvc->state.exist) { 890 if (pvc->state.deleted && pvc->state.exist) {
@@ -841,17 +898,16 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
841 } 898 }
842 899
843 /* Next full report after N391 polls */ 900 /* Next full report after N391 polls */
844 hdlc->state.fr.n391cnt = hdlc->state.fr.settings.n391; 901 state(hdlc)->n391cnt = state(hdlc)->settings.n391;
845 902
846 return 0; 903 return 0;
847} 904}
848 905
849 906
850
851static int fr_rx(struct sk_buff *skb) 907static int fr_rx(struct sk_buff *skb)
852{ 908{
853 struct net_device *ndev = skb->dev; 909 struct net_device *frad = skb->dev;
854 hdlc_device *hdlc = dev_to_hdlc(ndev); 910 hdlc_device *hdlc = dev_to_hdlc(frad);
855 fr_hdr *fh = (fr_hdr*)skb->data; 911 fr_hdr *fh = (fr_hdr*)skb->data;
856 u8 *data = skb->data; 912 u8 *data = skb->data;
857 u16 dlci; 913 u16 dlci;
@@ -864,11 +920,11 @@ static int fr_rx(struct sk_buff *skb)
864 dlci = q922_to_dlci(skb->data); 920 dlci = q922_to_dlci(skb->data);
865 921
866 if ((dlci == LMI_CCITT_ANSI_DLCI && 922 if ((dlci == LMI_CCITT_ANSI_DLCI &&
867 (hdlc->state.fr.settings.lmi == LMI_ANSI || 923 (state(hdlc)->settings.lmi == LMI_ANSI ||
868 hdlc->state.fr.settings.lmi == LMI_CCITT)) || 924 state(hdlc)->settings.lmi == LMI_CCITT)) ||
869 (dlci == LMI_CISCO_DLCI && 925 (dlci == LMI_CISCO_DLCI &&
870 hdlc->state.fr.settings.lmi == LMI_CISCO)) { 926 state(hdlc)->settings.lmi == LMI_CISCO)) {
871 if (fr_lmi_recv(ndev, skb)) 927 if (fr_lmi_recv(frad, skb))
872 goto rx_error; 928 goto rx_error;
873 dev_kfree_skb_any(skb); 929 dev_kfree_skb_any(skb);
874 return NET_RX_SUCCESS; 930 return NET_RX_SUCCESS;
@@ -878,7 +934,7 @@ static int fr_rx(struct sk_buff *skb)
878 if (!pvc) { 934 if (!pvc) {
879#ifdef DEBUG_PKT 935#ifdef DEBUG_PKT
880 printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n", 936 printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
881 ndev->name, dlci); 937 frad->name, dlci);
882#endif 938#endif
883 dev_kfree_skb_any(skb); 939 dev_kfree_skb_any(skb);
884 return NET_RX_DROP; 940 return NET_RX_DROP;
@@ -886,7 +942,7 @@ static int fr_rx(struct sk_buff *skb)
886 942
887 if (pvc->state.fecn != fh->fecn) { 943 if (pvc->state.fecn != fh->fecn) {
888#ifdef DEBUG_ECN 944#ifdef DEBUG_ECN
889 printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name, 945 printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", frad->name,
890 dlci, fh->fecn ? "N" : "FF"); 946 dlci, fh->fecn ? "N" : "FF");
891#endif 947#endif
892 pvc->state.fecn ^= 1; 948 pvc->state.fecn ^= 1;
@@ -894,7 +950,7 @@ static int fr_rx(struct sk_buff *skb)
894 950
895 if (pvc->state.becn != fh->becn) { 951 if (pvc->state.becn != fh->becn) {
896#ifdef DEBUG_ECN 952#ifdef DEBUG_ECN
897 printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name, 953 printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", frad->name,
898 dlci, fh->becn ? "N" : "FF"); 954 dlci, fh->becn ? "N" : "FF");
899#endif 955#endif
900 pvc->state.becn ^= 1; 956 pvc->state.becn ^= 1;
@@ -902,7 +958,7 @@ static int fr_rx(struct sk_buff *skb)
902 958
903 959
904 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { 960 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
905 hdlc->stats.rx_dropped++; 961 dev_to_desc(frad)->stats.rx_dropped++;
906 return NET_RX_DROP; 962 return NET_RX_DROP;
907 } 963 }
908 964
@@ -938,13 +994,13 @@ static int fr_rx(struct sk_buff *skb)
938 994
939 default: 995 default:
940 printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " 996 printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
941 "PID=%x\n", ndev->name, oui, pid); 997 "PID=%x\n", frad->name, oui, pid);
942 dev_kfree_skb_any(skb); 998 dev_kfree_skb_any(skb);
943 return NET_RX_DROP; 999 return NET_RX_DROP;
944 } 1000 }
945 } else { 1001 } else {
946 printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " 1002 printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
947 "length = %i\n", ndev->name, data[3], skb->len); 1003 "length = %i\n", frad->name, data[3], skb->len);
948 dev_kfree_skb_any(skb); 1004 dev_kfree_skb_any(skb);
949 return NET_RX_DROP; 1005 return NET_RX_DROP;
950 } 1006 }
@@ -964,7 +1020,7 @@ static int fr_rx(struct sk_buff *skb)
964 } 1020 }
965 1021
966 rx_error: 1022 rx_error:
967 hdlc->stats.rx_errors++; /* Mark error */ 1023 dev_to_desc(frad)->stats.rx_errors++; /* Mark error */
968 dev_kfree_skb_any(skb); 1024 dev_kfree_skb_any(skb);
969 return NET_RX_DROP; 1025 return NET_RX_DROP;
970} 1026}
@@ -977,44 +1033,42 @@ static void fr_start(struct net_device *dev)
977#ifdef DEBUG_LINK 1033#ifdef DEBUG_LINK
978 printk(KERN_DEBUG "fr_start\n"); 1034 printk(KERN_DEBUG "fr_start\n");
979#endif 1035#endif
980 if (hdlc->state.fr.settings.lmi != LMI_NONE) { 1036 if (state(hdlc)->settings.lmi != LMI_NONE) {
981 hdlc->state.fr.reliable = 0; 1037 state(hdlc)->reliable = 0;
982 hdlc->state.fr.dce_changed = 1; 1038 state(hdlc)->dce_changed = 1;
983 hdlc->state.fr.request = 0; 1039 state(hdlc)->request = 0;
984 hdlc->state.fr.fullrep_sent = 0; 1040 state(hdlc)->fullrep_sent = 0;
985 hdlc->state.fr.last_errors = 0xFFFFFFFF; 1041 state(hdlc)->last_errors = 0xFFFFFFFF;
986 hdlc->state.fr.n391cnt = 0; 1042 state(hdlc)->n391cnt = 0;
987 hdlc->state.fr.txseq = hdlc->state.fr.rxseq = 0; 1043 state(hdlc)->txseq = state(hdlc)->rxseq = 0;
988 1044
989 init_timer(&hdlc->state.fr.timer); 1045 init_timer(&state(hdlc)->timer);
990 /* First poll after 1 s */ 1046 /* First poll after 1 s */
991 hdlc->state.fr.timer.expires = jiffies + HZ; 1047 state(hdlc)->timer.expires = jiffies + HZ;
992 hdlc->state.fr.timer.function = fr_timer; 1048 state(hdlc)->timer.function = fr_timer;
993 hdlc->state.fr.timer.data = (unsigned long)dev; 1049 state(hdlc)->timer.data = (unsigned long)dev;
994 add_timer(&hdlc->state.fr.timer); 1050 add_timer(&state(hdlc)->timer);
995 } else 1051 } else
996 fr_set_link_state(1, dev); 1052 fr_set_link_state(1, dev);
997} 1053}
998 1054
999 1055
1000
1001static void fr_stop(struct net_device *dev) 1056static void fr_stop(struct net_device *dev)
1002{ 1057{
1003 hdlc_device *hdlc = dev_to_hdlc(dev); 1058 hdlc_device *hdlc = dev_to_hdlc(dev);
1004#ifdef DEBUG_LINK 1059#ifdef DEBUG_LINK
1005 printk(KERN_DEBUG "fr_stop\n"); 1060 printk(KERN_DEBUG "fr_stop\n");
1006#endif 1061#endif
1007 if (hdlc->state.fr.settings.lmi != LMI_NONE) 1062 if (state(hdlc)->settings.lmi != LMI_NONE)
1008 del_timer_sync(&hdlc->state.fr.timer); 1063 del_timer_sync(&state(hdlc)->timer);
1009 fr_set_link_state(0, dev); 1064 fr_set_link_state(0, dev);
1010} 1065}
1011 1066
1012 1067
1013
1014static void fr_close(struct net_device *dev) 1068static void fr_close(struct net_device *dev)
1015{ 1069{
1016 hdlc_device *hdlc = dev_to_hdlc(dev); 1070 hdlc_device *hdlc = dev_to_hdlc(dev);
1017 pvc_device *pvc = hdlc->state.fr.first_pvc; 1071 pvc_device *pvc = state(hdlc)->first_pvc;
1018 1072
1019 while (pvc) { /* Shutdown all PVCs for this FRAD */ 1073 while (pvc) { /* Shutdown all PVCs for this FRAD */
1020 if (pvc->main) 1074 if (pvc->main)
@@ -1025,7 +1079,8 @@ static void fr_close(struct net_device *dev)
1025 } 1079 }
1026} 1080}
1027 1081
1028static void dlci_setup(struct net_device *dev) 1082
1083static void pvc_setup(struct net_device *dev)
1029{ 1084{
1030 dev->type = ARPHRD_DLCI; 1085 dev->type = ARPHRD_DLCI;
1031 dev->flags = IFF_POINTOPOINT; 1086 dev->flags = IFF_POINTOPOINT;
@@ -1033,9 +1088,9 @@ static void dlci_setup(struct net_device *dev)
1033 dev->addr_len = 2; 1088 dev->addr_len = 2;
1034} 1089}
1035 1090
1036static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type) 1091static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
1037{ 1092{
1038 hdlc_device *hdlc = dev_to_hdlc(master); 1093 hdlc_device *hdlc = dev_to_hdlc(frad);
1039 pvc_device *pvc = NULL; 1094 pvc_device *pvc = NULL;
1040 struct net_device *dev; 1095 struct net_device *dev;
1041 int result, used; 1096 int result, used;
@@ -1044,9 +1099,9 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
1044 if (type == ARPHRD_ETHER) 1099 if (type == ARPHRD_ETHER)
1045 prefix = "pvceth%d"; 1100 prefix = "pvceth%d";
1046 1101
1047 if ((pvc = add_pvc(master, dlci)) == NULL) { 1102 if ((pvc = add_pvc(frad, dlci)) == NULL) {
1048 printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", 1103 printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
1049 master->name); 1104 frad->name);
1050 return -ENOBUFS; 1105 return -ENOBUFS;
1051 } 1106 }
1052 1107
@@ -1060,11 +1115,11 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
1060 "pvceth%d", ether_setup); 1115 "pvceth%d", ether_setup);
1061 else 1116 else
1062 dev = alloc_netdev(sizeof(struct net_device_stats), 1117 dev = alloc_netdev(sizeof(struct net_device_stats),
1063 "pvc%d", dlci_setup); 1118 "pvc%d", pvc_setup);
1064 1119
1065 if (!dev) { 1120 if (!dev) {
1066 printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", 1121 printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
1067 master->name); 1122 frad->name);
1068 delete_unused_pvcs(hdlc); 1123 delete_unused_pvcs(hdlc);
1069 return -ENOBUFS; 1124 return -ENOBUFS;
1070 } 1125 }
@@ -1102,8 +1157,8 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
1102 dev->destructor = free_netdev; 1157 dev->destructor = free_netdev;
1103 *get_dev_p(pvc, type) = dev; 1158 *get_dev_p(pvc, type) = dev;
1104 if (!used) { 1159 if (!used) {
1105 hdlc->state.fr.dce_changed = 1; 1160 state(hdlc)->dce_changed = 1;
1106 hdlc->state.fr.dce_pvc_count++; 1161 state(hdlc)->dce_pvc_count++;
1107 } 1162 }
1108 return 0; 1163 return 0;
1109} 1164}
@@ -1128,8 +1183,8 @@ static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
1128 *get_dev_p(pvc, type) = NULL; 1183 *get_dev_p(pvc, type) = NULL;
1129 1184
1130 if (!pvc_is_used(pvc)) { 1185 if (!pvc_is_used(pvc)) {
1131 hdlc->state.fr.dce_pvc_count--; 1186 state(hdlc)->dce_pvc_count--;
1132 hdlc->state.fr.dce_changed = 1; 1187 state(hdlc)->dce_changed = 1;
1133 } 1188 }
1134 delete_unused_pvcs(hdlc); 1189 delete_unused_pvcs(hdlc);
1135 return 0; 1190 return 0;
@@ -1137,14 +1192,13 @@ static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
1137 1192
1138 1193
1139 1194
1140static void fr_destroy(hdlc_device *hdlc) 1195static void fr_destroy(struct net_device *frad)
1141{ 1196{
1142 pvc_device *pvc; 1197 hdlc_device *hdlc = dev_to_hdlc(frad);
1143 1198 pvc_device *pvc = state(hdlc)->first_pvc;
1144 pvc = hdlc->state.fr.first_pvc; 1199 state(hdlc)->first_pvc = NULL; /* All PVCs destroyed */
1145 hdlc->state.fr.first_pvc = NULL; /* All PVCs destroyed */ 1200 state(hdlc)->dce_pvc_count = 0;
1146 hdlc->state.fr.dce_pvc_count = 0; 1201 state(hdlc)->dce_changed = 1;
1147 hdlc->state.fr.dce_changed = 1;
1148 1202
1149 while (pvc) { 1203 while (pvc) {
1150 pvc_device *next = pvc->next; 1204 pvc_device *next = pvc->next;
@@ -1161,8 +1215,17 @@ static void fr_destroy(hdlc_device *hdlc)
1161} 1215}
1162 1216
1163 1217
1218static struct hdlc_proto proto = {
1219 .close = fr_close,
1220 .start = fr_start,
1221 .stop = fr_stop,
1222 .detach = fr_destroy,
1223 .ioctl = fr_ioctl,
1224 .module = THIS_MODULE,
1225};
1226
1164 1227
1165int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) 1228static int fr_ioctl(struct net_device *dev, struct ifreq *ifr)
1166{ 1229{
1167 fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr; 1230 fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr;
1168 const size_t size = sizeof(fr_proto); 1231 const size_t size = sizeof(fr_proto);
@@ -1173,12 +1236,14 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
1173 1236
1174 switch (ifr->ifr_settings.type) { 1237 switch (ifr->ifr_settings.type) {
1175 case IF_GET_PROTO: 1238 case IF_GET_PROTO:
1239 if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */
1240 return -EINVAL;
1176 ifr->ifr_settings.type = IF_PROTO_FR; 1241 ifr->ifr_settings.type = IF_PROTO_FR;
1177 if (ifr->ifr_settings.size < size) { 1242 if (ifr->ifr_settings.size < size) {
1178 ifr->ifr_settings.size = size; /* data size wanted */ 1243 ifr->ifr_settings.size = size; /* data size wanted */
1179 return -ENOBUFS; 1244 return -ENOBUFS;
1180 } 1245 }
1181 if (copy_to_user(fr_s, &hdlc->state.fr.settings, size)) 1246 if (copy_to_user(fr_s, &state(hdlc)->settings, size))
1182 return -EFAULT; 1247 return -EFAULT;
1183 return 0; 1248 return 0;
1184 1249
@@ -1213,20 +1278,16 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
1213 if (result) 1278 if (result)
1214 return result; 1279 return result;
1215 1280
1216 if (hdlc->proto.id != IF_PROTO_FR) { 1281 if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */
1217 hdlc_proto_detach(hdlc); 1282 result = attach_hdlc_protocol(dev, &proto, fr_rx,
1218 hdlc->state.fr.first_pvc = NULL; 1283 sizeof(struct frad_state));
1219 hdlc->state.fr.dce_pvc_count = 0; 1284 if (result)
1285 return result;
1286 state(hdlc)->first_pvc = NULL;
1287 state(hdlc)->dce_pvc_count = 0;
1220 } 1288 }
1221 memcpy(&hdlc->state.fr.settings, &new_settings, size); 1289 memcpy(&state(hdlc)->settings, &new_settings, size);
1222 memset(&hdlc->proto, 0, sizeof(hdlc->proto)); 1290
1223
1224 hdlc->proto.close = fr_close;
1225 hdlc->proto.start = fr_start;
1226 hdlc->proto.stop = fr_stop;
1227 hdlc->proto.detach = fr_destroy;
1228 hdlc->proto.netif_rx = fr_rx;
1229 hdlc->proto.id = IF_PROTO_FR;
1230 dev->hard_start_xmit = hdlc->xmit; 1291 dev->hard_start_xmit = hdlc->xmit;
1231 dev->hard_header = NULL; 1292 dev->hard_header = NULL;
1232 dev->type = ARPHRD_FRAD; 1293 dev->type = ARPHRD_FRAD;
@@ -1238,6 +1299,9 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
1238 case IF_PROTO_FR_DEL_PVC: 1299 case IF_PROTO_FR_DEL_PVC:
1239 case IF_PROTO_FR_ADD_ETH_PVC: 1300 case IF_PROTO_FR_ADD_ETH_PVC:
1240 case IF_PROTO_FR_DEL_ETH_PVC: 1301 case IF_PROTO_FR_DEL_ETH_PVC:
1302 if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */
1303 return -EINVAL;
1304
1241 if(!capable(CAP_NET_ADMIN)) 1305 if(!capable(CAP_NET_ADMIN))
1242 return -EPERM; 1306 return -EPERM;
1243 1307
@@ -1263,3 +1327,24 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
1263 1327
1264 return -EINVAL; 1328 return -EINVAL;
1265} 1329}
1330
1331
1332static int __init mod_init(void)
1333{
1334 register_hdlc_protocol(&proto);
1335 return 0;
1336}
1337
1338
1339static void __exit mod_exit(void)
1340{
1341 unregister_hdlc_protocol(&proto);
1342}
1343
1344
1345module_init(mod_init);
1346module_exit(mod_exit);
1347
1348MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
1349MODULE_DESCRIPTION("Frame-Relay protocol support for generic HDLC");
1350MODULE_LICENSE("GPL v2");