diff options
author | Krzysztof Halasa <khc@pm.waw.pl> | 2008-02-01 16:34:30 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-02-05 13:31:38 -0500 |
commit | 983e23041b28abb113862b2935a85cfb9aab4f5a (patch) | |
tree | 406e55e0657d308fb92b17dcaab0292b157c1c28 /drivers | |
parent | d2f4fbe2982b3b9e46deea8d7288ea8f8d7b5bc4 (diff) |
Generic HDLC - fix kernel panic
Fixes kernel panic in Frame Relay mode
Signed-off-by: Krzysztof Halasa <khc@pm.waw.pl>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wan/hdlc_fr.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 071a64cacd5c..51296c2b8b89 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c | |||
@@ -136,6 +136,10 @@ typedef struct pvc_device_struct { | |||
136 | }state; | 136 | }state; |
137 | }pvc_device; | 137 | }pvc_device; |
138 | 138 | ||
139 | struct pvc_desc { | ||
140 | struct net_device_stats stats; | ||
141 | pvc_device *pvc; | ||
142 | }; | ||
139 | 143 | ||
140 | struct frad_state { | 144 | struct frad_state { |
141 | fr_proto settings; | 145 | fr_proto settings; |
@@ -171,17 +175,20 @@ static inline void dlci_to_q922(u8 *hdr, u16 dlci) | |||
171 | } | 175 | } |
172 | 176 | ||
173 | 177 | ||
174 | static inline struct frad_state * state(hdlc_device *hdlc) | 178 | static inline struct frad_state* state(hdlc_device *hdlc) |
175 | { | 179 | { |
176 | return(struct frad_state *)(hdlc->state); | 180 | return(struct frad_state *)(hdlc->state); |
177 | } | 181 | } |
178 | 182 | ||
179 | 183 | static inline struct pvc_desc* pvcdev_to_desc(struct net_device *dev) | |
180 | static __inline__ pvc_device* dev_to_pvc(struct net_device *dev) | ||
181 | { | 184 | { |
182 | return dev->priv; | 185 | return dev->priv; |
183 | } | 186 | } |
184 | 187 | ||
188 | static inline struct net_device_stats* pvc_get_stats(struct net_device *dev) | ||
189 | { | ||
190 | return &pvcdev_to_desc(dev)->stats; | ||
191 | } | ||
185 | 192 | ||
186 | static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) | 193 | static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) |
187 | { | 194 | { |
@@ -351,7 +358,7 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) | |||
351 | 358 | ||
352 | static int pvc_open(struct net_device *dev) | 359 | static int pvc_open(struct net_device *dev) |
353 | { | 360 | { |
354 | pvc_device *pvc = dev_to_pvc(dev); | 361 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
355 | 362 | ||
356 | if ((pvc->frad->flags & IFF_UP) == 0) | 363 | if ((pvc->frad->flags & IFF_UP) == 0) |
357 | return -EIO; /* Frad must be UP in order to activate PVC */ | 364 | return -EIO; /* Frad must be UP in order to activate PVC */ |
@@ -371,7 +378,7 @@ static int pvc_open(struct net_device *dev) | |||
371 | 378 | ||
372 | static int pvc_close(struct net_device *dev) | 379 | static int pvc_close(struct net_device *dev) |
373 | { | 380 | { |
374 | pvc_device *pvc = dev_to_pvc(dev); | 381 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
375 | 382 | ||
376 | if (--pvc->open_count == 0) { | 383 | if (--pvc->open_count == 0) { |
377 | hdlc_device *hdlc = dev_to_hdlc(pvc->frad); | 384 | hdlc_device *hdlc = dev_to_hdlc(pvc->frad); |
@@ -390,7 +397,7 @@ static int pvc_close(struct net_device *dev) | |||
390 | 397 | ||
391 | static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 398 | static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
392 | { | 399 | { |
393 | pvc_device *pvc = dev_to_pvc(dev); | 400 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
394 | fr_proto_pvc_info info; | 401 | fr_proto_pvc_info info; |
395 | 402 | ||
396 | if (ifr->ifr_settings.type == IF_GET_PROTO) { | 403 | if (ifr->ifr_settings.type == IF_GET_PROTO) { |
@@ -416,17 +423,9 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
416 | return -EINVAL; | 423 | return -EINVAL; |
417 | } | 424 | } |
418 | 425 | ||
419 | |||
420 | static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) | ||
421 | { | ||
422 | return &dev_to_desc(dev)->stats; | ||
423 | } | ||
424 | |||
425 | |||
426 | |||
427 | static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) | 426 | static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) |
428 | { | 427 | { |
429 | pvc_device *pvc = dev_to_pvc(dev); | 428 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
430 | struct net_device_stats *stats = pvc_get_stats(dev); | 429 | struct net_device_stats *stats = pvc_get_stats(dev); |
431 | 430 | ||
432 | if (pvc->state.active) { | 431 | if (pvc->state.active) { |
@@ -1109,11 +1108,10 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) | |||
1109 | used = pvc_is_used(pvc); | 1108 | used = pvc_is_used(pvc); |
1110 | 1109 | ||
1111 | if (type == ARPHRD_ETHER) | 1110 | if (type == ARPHRD_ETHER) |
1112 | dev = alloc_netdev(sizeof(struct net_device_stats), | 1111 | dev = alloc_netdev(sizeof(struct pvc_desc), "pvceth%d", |
1113 | "pvceth%d", ether_setup); | 1112 | ether_setup); |
1114 | else | 1113 | else |
1115 | dev = alloc_netdev(sizeof(struct net_device_stats), | 1114 | dev = alloc_netdev(sizeof(struct pvc_desc), "pvc%d", pvc_setup); |
1116 | "pvc%d", pvc_setup); | ||
1117 | 1115 | ||
1118 | if (!dev) { | 1116 | if (!dev) { |
1119 | printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", | 1117 | printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", |
@@ -1137,7 +1135,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) | |||
1137 | dev->change_mtu = pvc_change_mtu; | 1135 | dev->change_mtu = pvc_change_mtu; |
1138 | dev->mtu = HDLC_MAX_MTU; | 1136 | dev->mtu = HDLC_MAX_MTU; |
1139 | dev->tx_queue_len = 0; | 1137 | dev->tx_queue_len = 0; |
1140 | dev->priv = pvc; | 1138 | pvcdev_to_desc(dev)->pvc = pvc; |
1141 | 1139 | ||
1142 | result = dev_alloc_name(dev, dev->name); | 1140 | result = dev_alloc_name(dev, dev->name); |
1143 | if (result < 0) { | 1141 | if (result < 0) { |