Commit 1ad691d2 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Introduce generic init/cleanup callbacks

X25 needs notification when encapsulation is set to X25 and when
it is changed to something else again, so let's have some callbacks
for init/cleanup.
parent a29e933e
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "isdn_net.h" #include "isdn_net.h"
#include "isdn_ciscohdlck.h" #include "isdn_ciscohdlck.h"
#include <linux/if_arp.h>
#include <linux/inetdevice.h> #include <linux/inetdevice.h>
/* /*
...@@ -394,6 +395,7 @@ struct isdn_netif_ops ciscohdlck_ops = { ...@@ -394,6 +395,7 @@ struct isdn_netif_ops ciscohdlck_ops = {
.hard_header = isdn_ciscohdlck_header, .hard_header = isdn_ciscohdlck_header,
.do_ioctl = isdn_ciscohdlck_dev_ioctl, .do_ioctl = isdn_ciscohdlck_dev_ioctl,
.flags = IFF_NOARP | IFF_POINTOPOINT, .flags = IFF_NOARP | IFF_POINTOPOINT,
.type = ARPHRD_CISCO,
.receive = isdn_ciscohdlck_receive, .receive = isdn_ciscohdlck_receive,
.connected = isdn_ciscohdlck_connected, .connected = isdn_ciscohdlck_connected,
.disconnected = isdn_ciscohdlck_disconnected, .disconnected = isdn_ciscohdlck_disconnected,
......
...@@ -107,45 +107,18 @@ struct concap_proto * isdn_concap_new( int encap ) ...@@ -107,45 +107,18 @@ struct concap_proto * isdn_concap_new( int encap )
return NULL; return NULL;
} }
void isdn_x25_cleanup(isdn_net_dev *p)
{
isdn_net_local *lp = &p->local;
struct concap_proto * cprot = p -> cprot;
unsigned long flags;
/* delete old encapsulation protocol if present ... */
save_flags(flags);
cli(); /* avoid races with incoming events trying to
call cprot->pops methods */
if( cprot && cprot -> pops )
cprot -> pops -> proto_del ( cprot );
p -> cprot = NULL;
lp -> dops = NULL;
restore_flags(flags);
}
void isdn_x25_open(struct net_device *dev) void isdn_x25_open(struct net_device *dev)
{ {
struct concap_proto * cprot =
( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
struct concap_proto * dops =
( (isdn_net_local *) dev->priv ) -> dops;
unsigned long flags; unsigned long flags;
isdn_net_local *lp = dev->priv;
/* ... , prepare for configuration of new one ... */
switch ( lp->p_encap ){
case ISDN_NET_ENCAP_X25IFACE:
lp -> dops = &isdn_concap_reliable_dl_dops;
}
/* ... and allocate new one ... */
p -> cprot = isdn_concap_new( cfg -> p_encap );
/* p -> cprot == NULL now if p_encap is not supported
by means of the concap_proto mechanism */
if (!p->cprot)
return;
save_flags(flags); save_flags(flags);
cli(); /* Avoid glitch on writes to CMD regs */ cli(); /* Avoid glitch on writes to CMD regs */
if( p -> cprot -> pops && lp -> dops ) if( cprot -> pops && dops )
p -> cprot -> pops -> restart ( p -> cprot, dev, lp -> dops ); cprot -> pops -> restart ( cprot, dev, dops );
restore_flags(flags); restore_flags(flags);
} }
...@@ -220,6 +193,46 @@ isdn_x25_receive(isdn_net_dev *p, isdn_net_local *olp, struct sk_buff *skb) ...@@ -220,6 +193,46 @@ isdn_x25_receive(isdn_net_dev *p, isdn_net_local *olp, struct sk_buff *skb)
} }
} }
static void
isdn_x25_init(struct net_device *dev)
{
unsigned long flags;
isdn_net_local *lp = dev->priv;
/* ... , prepare for configuration of new one ... */
switch ( lp->p_encap ){
case ISDN_NET_ENCAP_X25IFACE:
lp -> dops = &isdn_concap_reliable_dl_dops;
}
/* ... and allocate new one ... */
p -> cprot = isdn_concap_new( cfg -> p_encap );
/* p -> cprot == NULL now if p_encap is not supported
by means of the concap_proto mechanism */
if (!p->cprot)
return -EINVAL;
return 0;
}
static void
isdn_x25_cleanup(isdn_net_dev *p)
{
isdn_net_local *lp = &p->local;
struct concap_proto * cprot = p -> cprot;
unsigned long flags;
/* delete old encapsulation protocol if present ... */
save_flags(flags);
cli(); /* avoid races with incoming events trying to
call cprot->pops methods */
if( cprot && cprot -> pops )
cprot -> pops -> proto_del ( cprot );
p -> cprot = NULL;
lp -> dops = NULL;
restore_flags(flags);
}
void isdn_x25_realrm(isdn_net_dev *p) void isdn_x25_realrm(isdn_net_dev *p)
{ {
if( p -> cprot && p -> cprot -> pops ) if( p -> cprot && p -> cprot -> pops )
...@@ -232,6 +245,8 @@ struct isdn_netif_ops isdn_x25_ops = { ...@@ -232,6 +245,8 @@ struct isdn_netif_ops isdn_x25_ops = {
.receive = isdn_x25_receive, .receive = isdn_x25_receive,
.connected = isdn_x25_connected, .connected = isdn_x25_connected,
.disconnected = isdn_x25_disconnected, .disconnected = isdn_x25_disconnected,
.init = isdn_x25_init,
.cleanup = isdn_x25_cleanup,
}; };
#endif /* CONFIG_ISDN_X25 */ #endif /* CONFIG_ISDN_X25 */
...@@ -16,19 +16,12 @@ struct concap_proto *isdn_concap_new(int); ...@@ -16,19 +16,12 @@ struct concap_proto *isdn_concap_new(int);
extern struct isdn_netif_ops isdn_x25_ops; extern struct isdn_netif_ops isdn_x25_ops;
void isdn_x25_cleanup(isdn_net_dev *p);
void isdn_x25_open(struct net_device *dev); void isdn_x25_open(struct net_device *dev);
void isdn_x25_close(struct net_device *dev); void isdn_x25_close(struct net_device *dev);
int isdn_x25_start_xmit(struct sk_buff *skb, struct net_device *dev); int isdn_x25_start_xmit(struct sk_buff *skb, struct net_device *dev);
void isdn_x25_realrm(isdn_net_dev *p);
#else #else
static inline void
isdn_x25_cleanup(isdn_net_dev *p)
{
}
static inline void static inline void
isdn_x25_open(struct net_device *dev) isdn_x25_open(struct net_device *dev)
{ {
...@@ -45,9 +38,4 @@ isdn_x25_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -45,9 +38,4 @@ isdn_x25_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 0; return 0;
} }
static inline void
isdn_x25_realrm(isdn_net_dev *p)
{
}
#endif #endif
...@@ -203,10 +203,10 @@ register_isdn_netif(int encap, struct isdn_netif_ops *ops) ...@@ -203,10 +203,10 @@ register_isdn_netif(int encap, struct isdn_netif_ops *ops)
/* Prototypes */ /* Prototypes */
int isdn_net_force_dial_lp(isdn_net_local *); static int isdn_net_force_dial_lp(isdn_net_local *);
static int isdn_net_start_xmit(struct sk_buff *, struct net_device *); static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
static void do_dialout(isdn_net_local *lp); static void do_dialout(isdn_net_local *lp);
static int isdn_net_set_encap(isdn_net_dev *p, int encap);
static int isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg); static int isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg);
char *isdn_net_revision = "$Revision: 1.140.6.11 $"; char *isdn_net_revision = "$Revision: 1.140.6.11 $";
...@@ -1520,7 +1520,7 @@ isdn_net_findif(char *name) ...@@ -1520,7 +1520,7 @@ isdn_net_findif(char *name)
* This is called from the userlevel-routine below or * This is called from the userlevel-routine below or
* from isdn_net_start_xmit(). * from isdn_net_start_xmit().
*/ */
int static int
isdn_net_force_dial_lp(isdn_net_local *lp) isdn_net_force_dial_lp(isdn_net_local *lp)
{ {
int slot; int slot;
...@@ -1606,7 +1606,6 @@ isdn_net_new(char *name, struct net_device *master) ...@@ -1606,7 +1606,6 @@ isdn_net_new(char *name, struct net_device *master)
strcpy(netdev->dev.name, name); strcpy(netdev->dev.name, name);
netdev->dev.priv = &netdev->local; netdev->dev.priv = &netdev->local;
netdev->dev.init = isdn_net_init; netdev->dev.init = isdn_net_init;
netdev->local.p_encap = ISDN_NET_ENCAP_RAWIP;
if (master) { if (master) {
/* Device shall be a slave */ /* Device shall be a slave */
struct net_device *p = (((isdn_net_local *) master->priv)->slave); struct net_device *p = (((isdn_net_local *) master->priv)->slave);
...@@ -1653,6 +1652,7 @@ isdn_net_new(char *name, struct net_device *master) ...@@ -1653,6 +1652,7 @@ isdn_net_new(char *name, struct net_device *master)
netdev->local.exclusive = -1; netdev->local.exclusive = -1;
netdev->local.ppp_slot = -1; netdev->local.ppp_slot = -1;
netdev->local.pppbind = -1; netdev->local.pppbind = -1;
netdev->local.p_encap = -1;
skb_queue_head_init(&netdev->local.super_tx_queue); skb_queue_head_init(&netdev->local.super_tx_queue);
netdev->local.l2_proto = ISDN_PROTO_L2_X75I; netdev->local.l2_proto = ISDN_PROTO_L2_X75I;
netdev->local.l3_proto = ISDN_PROTO_L3_TRANS; netdev->local.l3_proto = ISDN_PROTO_L3_TRANS;
...@@ -1678,6 +1678,7 @@ isdn_net_new(char *name, struct net_device *master) ...@@ -1678,6 +1678,7 @@ isdn_net_new(char *name, struct net_device *master)
spin_lock_init(&netdev->local.lock); spin_lock_init(&netdev->local.lock);
INIT_LIST_HEAD(&netdev->local.phone[0]); INIT_LIST_HEAD(&netdev->local.phone[0]);
INIT_LIST_HEAD(&netdev->local.phone[1]); INIT_LIST_HEAD(&netdev->local.phone[1]);
isdn_net_set_encap(netdev, ISDN_NET_ENCAP_RAWIP);
/* Put into to netdev-chain */ /* Put into to netdev-chain */
list_add(&netdev->global_list, &isdn_net_devs); list_add(&netdev->global_list, &isdn_net_devs);
...@@ -1709,12 +1710,12 @@ isdn_net_newslave(char *parm) ...@@ -1709,12 +1710,12 @@ isdn_net_newslave(char *parm)
} }
static int static int
isdn_net_set_encap(isdn_net_dev *p, isdn_net_ioctl_cfg *cfg) isdn_net_set_encap(isdn_net_dev *p, int encap)
{ {
isdn_net_local *lp = &p->local; isdn_net_local *lp = &p->local;
int retval = 0; int retval = 0;
if (lp->p_encap == cfg->p_encap){ if (lp->p_encap == encap){
/* nothing to do */ /* nothing to do */
retval = 0; retval = 0;
goto out; goto out;
...@@ -1723,30 +1724,34 @@ isdn_net_set_encap(isdn_net_dev *p, isdn_net_ioctl_cfg *cfg) ...@@ -1723,30 +1724,34 @@ isdn_net_set_encap(isdn_net_dev *p, isdn_net_ioctl_cfg *cfg)
retval = -EBUSY; retval = -EBUSY;
goto out; goto out;
} }
switch (lp->p_encap) { if (lp->ops && lp->ops->cleanup)
case ISDN_NET_ENCAP_X25IFACE: lp->ops->cleanup(lp);
isdn_x25_cleanup(p);
break;
}
if (cfg->p_encap < 0 || cfg->p_encap >= ISDN_NET_ENCAP_NR) { if (encap < 0 || encap >= ISDN_NET_ENCAP_NR) {
lp->p_encap = -1; lp->p_encap = -1;
lp->ops = NULL; lp->ops = NULL;
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
} }
lp->p_encap = encap;
lp->ops = netif_ops[encap];
p->dev.hard_header = lp->ops->hard_header; p->dev.hard_header = lp->ops->hard_header;
p->dev.rebuild_header = lp->ops->rebuild_header; p->dev.rebuild_header = lp->ops->rebuild_header;
p->dev.do_ioctl = lp->ops->do_ioctl; p->dev.do_ioctl = lp->ops->do_ioctl;
p->dev.hard_header_cache = lp->ops->hard_header_cache; p->dev.hard_header_cache = lp->ops->hard_header_cache;
p->dev.header_cache_update = lp->ops->header_cache_update; p->dev.header_cache_update = lp->ops->header_cache_update;
p->dev.flags = lp->ops->flags;
p->dev.type = lp->ops->type;
p->dev.addr_len = lp->ops->addr_len;
if (lp->ops->init)
retval = lp->ops->init(lp);
lp->p_encap = cfg->p_encap; if (retval != 0) {
lp->ops = netif_ops[lp->p_encap];
if (retval != 0)
lp->p_encap = -1; lp->p_encap = -1;
lp->ops = NULL;
}
out: out:
return retval; return retval;
} }
...@@ -1854,7 +1859,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg *cfg) ...@@ -1854,7 +1859,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
goto out; goto out;
} }
retval = isdn_net_set_encap(p, cfg); retval = isdn_net_set_encap(p, cfg->p_encap);
if (retval) if (retval)
goto out; goto out;
...@@ -2163,7 +2168,7 @@ isdn_net_realrm(isdn_net_dev *p) ...@@ -2163,7 +2168,7 @@ isdn_net_realrm(isdn_net_dev *p)
restore_flags(flags); restore_flags(flags);
return -EBUSY; return -EBUSY;
} }
isdn_x25_realrm(p); isdn_net_set_encap(p, -1);
/* Free all phone-entries */ /* Free all phone-entries */
isdn_net_rmallphone(p); isdn_net_rmallphone(p);
...@@ -2271,6 +2276,7 @@ isdn_iptyp_receive(isdn_net_dev *p, isdn_net_local *olp, ...@@ -2271,6 +2276,7 @@ isdn_iptyp_receive(isdn_net_dev *p, isdn_net_local *olp,
static struct isdn_netif_ops iptyp_ops = { static struct isdn_netif_ops iptyp_ops = {
.hard_header = isdn_iptyp_header, .hard_header = isdn_iptyp_header,
.flags = IFF_NOARP | IFF_POINTOPOINT, .flags = IFF_NOARP | IFF_POINTOPOINT,
.type = ARPHRD_PPP,
.addr_len = 2, .addr_len = 2,
.receive = isdn_iptyp_receive, .receive = isdn_iptyp_receive,
}; };
...@@ -2303,6 +2309,7 @@ isdn_uihdlc_receive(isdn_net_dev *p, isdn_net_local *olp, ...@@ -2303,6 +2309,7 @@ isdn_uihdlc_receive(isdn_net_dev *p, isdn_net_local *olp,
static struct isdn_netif_ops uihdlc_ops = { static struct isdn_netif_ops uihdlc_ops = {
.hard_header = isdn_uihdlc_header, .hard_header = isdn_uihdlc_header,
.flags = IFF_NOARP | IFF_POINTOPOINT, .flags = IFF_NOARP | IFF_POINTOPOINT,
.type = ARPHRD_HDLC,
.addr_len = 2, .addr_len = 2,
.receive = isdn_uihdlc_receive, .receive = isdn_uihdlc_receive,
}; };
...@@ -2324,6 +2331,7 @@ isdn_rawip_receive(isdn_net_dev *p, isdn_net_local *olp, ...@@ -2324,6 +2331,7 @@ isdn_rawip_receive(isdn_net_dev *p, isdn_net_local *olp,
static struct isdn_netif_ops rawip_ops = { static struct isdn_netif_ops rawip_ops = {
.flags = IFF_NOARP | IFF_POINTOPOINT, .flags = IFF_NOARP | IFF_POINTOPOINT,
.type = ARPHRD_PPP,
.receive = isdn_rawip_receive, .receive = isdn_rawip_receive,
}; };
......
...@@ -306,6 +306,8 @@ struct isdn_netif_ops { ...@@ -306,6 +306,8 @@ struct isdn_netif_ops {
void (*disconnected)(struct isdn_net_local_s *lp); void (*disconnected)(struct isdn_net_local_s *lp);
int (*bind)(struct isdn_net_local_s *lp); int (*bind)(struct isdn_net_local_s *lp);
void (*unbind)(struct isdn_net_local_s *lp); void (*unbind)(struct isdn_net_local_s *lp);
int (*init)(struct isdn_net_local_s *lp);
void (*cleanup)(struct isdn_net_local_s *lp);
}; };
/* Local interface-data */ /* Local interface-data */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment