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) { |
