Commit 54426d01 authored by Patrick Mochel's avatar Patrick Mochel

Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin

into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-driverfs
parents 79281038 6865a163
...@@ -138,7 +138,7 @@ typedef struct actcapi_ncpd { ...@@ -138,7 +138,7 @@ typedef struct actcapi_ncpd {
typedef struct actcapi_msg { typedef struct actcapi_msg {
actcapi_msghdr hdr; actcapi_msghdr hdr;
union msg { union {
__u16 manuf_msg; __u16 manuf_msg;
struct manufacturer_req_net { struct manufacturer_req_net {
__u16 manuf_msg; __u16 manuf_msg;
......
...@@ -564,8 +564,8 @@ isdn_audio_eval_dtmf(modem_info * info) ...@@ -564,8 +564,8 @@ isdn_audio_eval_dtmf(modem_info * info)
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
save_flags(flags); save_flags(flags);
cli(); cli();
di = info->isdn_driver; di = isdn_slot_driver(info->isdn_slot);
ch = info->isdn_channel; ch = isdn_slot_channel(info->isdn_slot);
__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
dev->drv[di]->rcvcount[ch] += 2; dev->drv[di]->rcvcount[ch] += 2;
restore_flags(flags); restore_flags(flags);
...@@ -685,8 +685,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code) ...@@ -685,8 +685,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code)
ISDN_AUDIO_SKB_LOCK(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0;
save_flags(flags); save_flags(flags);
cli(); cli();
di = info->isdn_driver; di = isdn_slot_driver(info->isdn_slot);
ch = info->isdn_channel; ch = isdn_slot_channel(info->isdn_slot);
__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
dev->drv[di]->rcvcount[ch] += 2; dev->drv[di]->rcvcount[ch] += 2;
restore_flags(flags); restore_flags(flags);
......
This diff is collapsed.
...@@ -23,6 +23,32 @@ ...@@ -23,6 +23,32 @@
#undef ISDN_DEBUG_NET_DUMP #undef ISDN_DEBUG_NET_DUMP
#undef ISDN_DEBUG_NET_DIAL #undef ISDN_DEBUG_NET_DIAL
#undef ISDN_DEBUG_NET_ICALL #undef ISDN_DEBUG_NET_ICALL
#undef ISDN_DEBUG_STATCALLB
#undef ISDN_DEBUG_COMMAND
#ifdef ISDN_DEBUG_NET_DIAL
#define dbg_net_dial(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_dial(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_NET_ICALL
#define dbg_net_icall(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_icall(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_STATCALLB
#define dbg_statcallb(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_statcallb(arg...) do {} while (0)
#endif
#define isdn_BUG() \
do { printk(KERN_WARNING "ISDN Bug at %s:%d\n", __FILE__, __LINE__); \
} while(0)
#define HERE printk("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__)
/* Prototypes */ /* Prototypes */
extern void isdn_MOD_INC_USE_COUNT(void); extern void isdn_MOD_INC_USE_COUNT(void);
...@@ -30,20 +56,50 @@ extern void isdn_MOD_DEC_USE_COUNT(void); ...@@ -30,20 +56,50 @@ extern void isdn_MOD_DEC_USE_COUNT(void);
extern void isdn_lock_drivers(void); extern void isdn_lock_drivers(void);
extern void isdn_unlock_drivers(void); extern void isdn_unlock_drivers(void);
extern void isdn_free_channel(int di, int ch, int usage); extern void isdn_free_channel(int di, int ch, int usage);
extern void isdn_all_eaz(int di, int ch);
extern int isdn_command(isdn_ctrl *);
extern int isdn_dc2minor(int di, int ch); extern int isdn_dc2minor(int di, int ch);
extern void isdn_info_update(void); extern void isdn_info_update(void);
extern char *isdn_map_eaz2msn(char *msn, int di); extern char *isdn_map_eaz2msn(char *msn, int di);
extern void isdn_timer_ctrl(int tf, int onoff); extern void isdn_timer_ctrl(int tf, int onoff);
extern void isdn_unexclusive_channel(int di, int ch); extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **); extern int isdn_getnum(char **);
extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
extern int isdn_get_free_channel(int, int, int, int, int, char *);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
extern int isdn_msncmp( const char *, const char *); extern int isdn_msncmp( const char *, const char *);
extern int isdn_add_channels(driver *, int, int, int); extern int isdn_add_channels(driver *, int, int, int);
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
extern void isdn_dumppkt(char *, u_char *, int, int); extern void isdn_dumppkt(char *, u_char *, int, int);
#else
static inline void isdn_dumppkt(char *s, u_char *d, int l, int m) { }
#endif #endif
struct dial_info {
int l2_proto;
int l3_proto;
struct T30_s *fax;
unsigned char si1;
unsigned char si2;
unsigned char *msn;
unsigned char *phone;
};
extern struct list_head isdn_net_devs;
extern int isdn_get_free_slot(int, int, int, int, int, char *);
extern void isdn_slot_free(int slot, int usage);
extern void isdn_slot_all_eaz(int slot);
extern int isdn_slot_command(int slot, int cmd, isdn_ctrl *);
extern int isdn_slot_dial(int slot, struct dial_info *dial);
extern char *isdn_slot_map_eaz2msn(int slot, char *msn);
extern int isdn_slot_write(int slot, struct sk_buff *);
extern int isdn_slot_readbchan(int slot, u_char *, u_char *, int);
extern int isdn_slot_hdrlen(int slot);
extern int isdn_slot_driver(int slot);
extern int isdn_slot_channel(int slot);
extern int isdn_slot_usage(int slot);
extern void isdn_slot_set_usage(int slot, int usage);
extern char *isdn_slot_num(int slot);
extern int isdn_slot_m_idx(int slot);
extern void isdn_slot_set_m_idx(int slot, int midx);
extern void isdn_slot_set_rx_netdev(int sl, isdn_net_dev *nd);
extern void isdn_slot_set_st_netdev(int sl, isdn_net_dev *nd);
extern isdn_net_dev *isdn_slot_rx_netdev(int sl);
extern isdn_net_dev *isdn_slot_st_netdev(int sl);
This diff is collapsed.
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
#define CISCO_SLARP_REPLY 1 #define CISCO_SLARP_REPLY 1
#define CISCO_SLARP_KEEPALIVE 2 #define CISCO_SLARP_KEEPALIVE 2
extern char *isdn_net_new(char *, struct net_device *); extern int isdn_net_new(char *, struct net_device *);
extern char *isdn_net_newslave(char *); extern int isdn_net_newslave(char *);
extern int isdn_net_rm(char *); extern int isdn_net_rm(char *);
extern int isdn_net_rmall(void); extern int isdn_net_rmall(void);
extern int isdn_net_stat_callback(int, isdn_ctrl *); extern int isdn_net_stat_callback(int, isdn_ctrl *);
...@@ -44,7 +44,6 @@ extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *); ...@@ -44,7 +44,6 @@ extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
extern int isdn_net_delphone(isdn_net_ioctl_phone *); extern int isdn_net_delphone(isdn_net_ioctl_phone *);
extern int isdn_net_find_icall(int, int, int, setup_parm *); extern int isdn_net_find_icall(int, int, int, setup_parm *);
extern void isdn_net_hangup(struct net_device *); extern void isdn_net_hangup(struct net_device *);
extern void isdn_net_dial(void);
extern void isdn_net_autohup(void); extern void isdn_net_autohup(void);
extern int isdn_net_force_hangup(char *); extern int isdn_net_force_hangup(char *);
extern int isdn_net_force_dial(char *); extern int isdn_net_force_dial(char *);
...@@ -131,7 +130,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp) ...@@ -131,7 +130,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
if (master_lp->netdev->queue == lp) { if (master_lp->netdev->queue == lp) {
master_lp->netdev->queue = lp->next; master_lp->netdev->queue = lp->next;
if (lp->next == lp) { /* last in queue */ if (lp->next == lp) { /* last in queue */
master_lp->netdev->queue = master_lp->netdev->local; master_lp->netdev->queue = &master_lp->netdev->local;
} }
} }
lp->next = lp->last = lp; /* (re)set own pointers */ lp->next = lp->last = lp; /* (re)set own pointers */
......
...@@ -165,14 +165,15 @@ isdn_ppp_bind(isdn_net_local * lp) ...@@ -165,14 +165,15 @@ isdn_ppp_bind(isdn_net_local * lp)
save_flags(flags); save_flags(flags);
cli(); cli();
if (lp->pppbind < 0) { /* device bounded to ippp device ? */ if (lp->pppbind < 0) { /* device bounded to ippp device ? */
isdn_net_dev *net_dev = dev->netdev; struct list_head *l;
char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */ char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */
memset(exclusive, 0, ISDN_MAX_CHANNELS); memset(exclusive, 0, ISDN_MAX_CHANNELS);
while (net_dev) { /* step through net devices to find exclusive minors */ /* step through net devices to find exclusive minors */
isdn_net_local *lp = net_dev->local; list_for_each(l, &isdn_net_devs) {
isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
isdn_net_local *lp = &p->local;
if (lp->pppbind >= 0) if (lp->pppbind >= 0)
exclusive[lp->pppbind] = 1; exclusive[lp->pppbind] = 1;
net_dev = net_dev->next;
} }
/* /*
* search a free device / slot * search a free device / slot
...@@ -804,11 +805,11 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off) ...@@ -804,11 +805,11 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
if (proto != PPP_LCP) if (proto != PPP_LCP)
lp->huptimer = 0; lp->huptimer = 0;
if (lp->isdn_device < 0 || lp->isdn_channel < 0) { if (lp->isdn_slot < 0) {
retval = 0; retval = 0;
goto out; goto out;
} }
if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && if ((dev->drv[isdn_slot_driver(lp->isdn_slot)]->flags & DRV_FLAG_RUNNING) &&
lp->dialstate == 0 && lp->dialstate == 0 &&
(lp->flags & ISDN_NET_CONNECTED)) { (lp->flags & ISDN_NET_CONNECTED)) {
unsigned short hl; unsigned short hl;
...@@ -818,7 +819,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off) ...@@ -818,7 +819,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
* sk_buff. old call to dev_alloc_skb only reserved * sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want * 16 bytes, now we are looking what the driver want
*/ */
hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; hl = isdn_slot_hdrlen(lp->isdn_slot);
skb = alloc_skb(hl+count, GFP_ATOMIC); skb = alloc_skb(hl+count, GFP_ATOMIC);
if (!skb) { if (!skb) {
printk(KERN_WARNING "isdn_ppp_write: out of memory!\n"); printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
...@@ -974,7 +975,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf ...@@ -974,7 +975,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
int slot; int slot;
int proto; int proto;
if (net_dev->local->master) if (net_dev->local.master)
BUG(); // we're called with the master device always BUG(); // we're called with the master device always
slot = lp->ppp_slot; slot = lp->ppp_slot;
...@@ -1077,12 +1078,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff ...@@ -1077,12 +1078,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
case PPP_VJC_UNCOMP: case PPP_VJC_UNCOMP:
if (is->debug & 0x20) if (is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n"); printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
if (net_dev->local->ppp_slot < 0) { if (net_dev->local.ppp_slot < 0) {
printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n", printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
net_dev->local->ppp_slot); net_dev->local.ppp_slot);
goto drop_packet; goto drop_packet;
} }
if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) { if (slhc_remember(ippp_table[net_dev->local.ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n"); printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
goto drop_packet; goto drop_packet;
} }
...@@ -1103,12 +1104,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff ...@@ -1103,12 +1104,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
} }
skb_put(skb, skb_old->len + 128); skb_put(skb, skb_old->len + 128);
memcpy(skb->data, skb_old->data, skb_old->len); memcpy(skb->data, skb_old->data, skb_old->len);
if (net_dev->local->ppp_slot < 0) { if (net_dev->local.ppp_slot < 0) {
printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n", printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
net_dev->local->ppp_slot); net_dev->local.ppp_slot);
goto drop_packet; goto drop_packet;
} }
pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp, pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_slot]->slcomp,
skb->data, skb_old->len); skb->data, skb_old->len);
kfree_skb(skb_old); kfree_skb(skb_old);
if (pkt_len < 0) if (pkt_len < 0)
...@@ -1144,7 +1145,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff ...@@ -1144,7 +1145,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
return; return;
drop_packet: drop_packet:
net_dev->local->stats.rx_dropped++; net_dev->local.stats.rx_dropped++;
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -1263,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -1263,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
* sk_buff. old call to dev_alloc_skb only reserved * sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want. * 16 bytes, now we are looking what the driver want.
*/ */
hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER; hl = isdn_slot_hdrlen(lp->isdn_slot) + IPPP_MAX_HEADER;;
/* /*
* Note: hl might still be insufficient because the method * Note: hl might still be insufficient because the method
* above does not account for a possibible MPPP slave channel * above does not account for a possibible MPPP slave channel
...@@ -1976,7 +1977,7 @@ isdn_ppp_dial_slave(char *name) ...@@ -1976,7 +1977,7 @@ isdn_ppp_dial_slave(char *name)
if (!(ndev = isdn_net_findif(name))) if (!(ndev = isdn_net_findif(name)))
return 1; return 1;
lp = ndev->local; lp = &ndev->local;
if (!(lp->flags & ISDN_NET_CONNECTED)) if (!(lp->flags & ISDN_NET_CONNECTED))
return 5; return 5;
...@@ -2007,7 +2008,7 @@ isdn_ppp_hangup_slave(char *name) ...@@ -2007,7 +2008,7 @@ isdn_ppp_hangup_slave(char *name)
if (!(ndev = isdn_net_findif(name))) if (!(ndev = isdn_net_findif(name)))
return 1; return 1;
lp = ndev->local; lp = &ndev->local;
if (!(lp->flags & ISDN_NET_CONNECTED)) if (!(lp->flags & ISDN_NET_CONNECTED))
return 5; return 5;
...@@ -2094,7 +2095,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, ...@@ -2094,7 +2095,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
isdn_net_local *lp = is->lp; isdn_net_local *lp = is->lp;
/* Alloc large enough skb */ /* Alloc large enough skb */
hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; hl = isdn_slot_hdrlen(lp->isdn_slot);
skb = alloc_skb(len + hl + 16,GFP_ATOMIC); skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
if(!skb) { if(!skb) {
printk(KERN_WARNING printk(KERN_WARNING
......
This diff is collapsed.
...@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void); ...@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void);
extern void isdn_tty_modem_ring(void); extern void isdn_tty_modem_ring(void);
extern void isdn_tty_carrier_timeout(void); extern void isdn_tty_carrier_timeout(void);
extern void isdn_tty_modem_xmit(void); extern void isdn_tty_modem_xmit(void);
extern int isdn_tty_modem_init(void); extern int isdn_tty_init(void);
extern void isdn_tty_readmodem(void); extern void isdn_tty_readmodem(void);
extern int isdn_tty_find_icall(int, int, setup_parm *); extern int isdn_tty_find_icall(int, int, setup_parm *);
extern void isdn_tty_cleanup_xmit(modem_info *); extern void isdn_tty_cleanup_xmit(modem_info *);
...@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *); ...@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *); extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *); extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
#endif #endif
extern int isdn_tty_init(void);
extern void isdn_tty_exit(void);
...@@ -74,7 +74,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info) ...@@ -74,7 +74,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info)
case 2: /* +FCON */ case 2: /* +FCON */
/* Append CPN, if enabled */ /* Append CPN, if enabled */
if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) && if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) &&
(!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) { (!(isdn_slot_usage(info->isdn_slot) & ISDN_USAGE_OUTGOING))) {
sprintf(rs, "/%s", m->cpn); sprintf(rs, "/%s", m->cpn);
isdn_tty_at_cout(rs, info); isdn_tty_at_cout(rs, info);
} }
...@@ -360,12 +360,11 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info) ...@@ -360,12 +360,11 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
default: default:
PARSE_ERROR1; PARSE_ERROR1;
} }
c.command = ISDN_CMD_FAXCMD;
#ifdef ISDN_TTY_FAX_CMD_DEBUG #ifdef ISDN_TTY_FAX_CMD_DEBUG
printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n", printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n",
c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]); c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]);
#endif #endif
if (info->isdn_driver < 0) { if (info->isdn_slot < 0) {
save_flags(flags); save_flags(flags);
cli(); cli();
if ((c.parm.aux.subcmd == AT_EQ_VALUE) || if ((c.parm.aux.subcmd == AT_EQ_VALUE) ||
...@@ -374,32 +373,21 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info) ...@@ -374,32 +373,21 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
PARSE_ERROR1; PARSE_ERROR1;
} }
/* get a temporary connection to the first free fax driver */ /* get a temporary connection to the first free fax driver */
i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX, i = isdn_get_free_slot(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX,
ISDN_PROTO_L3_FCLASS1, -1, -1, "00"); ISDN_PROTO_L3_FCLASS1, -1, -1, "00");
if (i < 0) { if (i < 0) {
restore_flags(flags); restore_flags(flags);
PARSE_ERROR1; PARSE_ERROR1;
} }
info->isdn_driver = dev->drvmap[i]; info->isdn_slot = i;
info->isdn_channel = dev->chanmap[i]; isdn_slot_set_m_idx(i, info->line);
info->drv_index = i; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c);
dev->m_idx[i] = info->line; isdn_slot_free(info->isdn_slot, ISDN_USAGE_FAX);
c.driver = info->isdn_driver; isdn_slot_set_m_idx(i, -1);
c.arg = info->isdn_channel; info->isdn_slot = -1;
isdn_command(&c);
isdn_free_channel(info->isdn_driver, info->isdn_channel,
ISDN_USAGE_FAX);
info->isdn_driver = -1;
info->isdn_channel = -1;
if (info->drv_index >= 0) {
dev->m_idx[info->drv_index] = -1;
info->drv_index = -1;
}
restore_flags(flags); restore_flags(flags);
} else { } else {
c.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c);
c.arg = info->isdn_channel;
isdn_command(&c);
} }
return 1; return 1;
} }
...@@ -800,10 +788,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) ...@@ -800,10 +788,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
printk(KERN_DEBUG "isdn_tty: Fax FDR\n"); printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
#endif #endif
f->code = ISDN_TTY_FAX_DR; f->code = ISDN_TTY_FAX_DR;
cmd.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_FAXCMD;
isdn_command(&cmd);
if (f->phase == ISDN_FAX_PHASE_B) { if (f->phase == ISDN_FAX_PHASE_B) {
f->phase = ISDN_FAX_PHASE_C; f->phase = ISDN_FAX_PHASE_C;
} else if (f->phase == ISDN_FAX_PHASE_D) { } else if (f->phase == ISDN_FAX_PHASE_D) {
...@@ -855,10 +840,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) ...@@ -855,10 +840,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
#endif #endif
if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) { if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) {
f->code = ISDN_TTY_FAX_DT; f->code = ISDN_TTY_FAX_DT;
cmd.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_FAXCMD;
isdn_command(&cmd);
if (f->phase == ISDN_FAX_PHASE_D) { if (f->phase == ISDN_FAX_PHASE_D) {
f->phase = ISDN_FAX_PHASE_C; f->phase = ISDN_FAX_PHASE_C;
isdn_tty_fax_modem_result(7, info); /* CONNECT */ isdn_tty_fax_modem_result(7, info); /* CONNECT */
...@@ -913,10 +895,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) ...@@ -913,10 +895,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
PARSE_ERROR1; PARSE_ERROR1;
f->fet = par; f->fet = par;
f->code = ISDN_TTY_FAX_ET; f->code = ISDN_TTY_FAX_ET;
cmd.driver = info->isdn_driver; isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd);
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_FAXCMD;
isdn_command(&cmd);
#ifdef ISDN_TTY_FAX_STAT_DEBUG #ifdef ISDN_TTY_FAX_STAT_DEBUG
printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par); printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par);
#endif #endif
......
...@@ -515,14 +515,12 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb) ...@@ -515,14 +515,12 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb)
} }
int int
isdn_v110_stat_callback(int idx, isdn_ctrl * c) isdn_v110_stat_callback(struct isdn_v110 *iv110, isdn_ctrl *c)
{ {
isdn_v110_stream *v = NULL; isdn_v110_stream *v = NULL;
int i; int i;
int ret; int ret;
if (idx < 0)
return 0;
switch (c->command) { switch (c->command) {
case ISDN_STAT_BSENT: case ISDN_STAT_BSENT:
/* Keep the send-queue of the driver filled /* Keep the send-queue of the driver filled
...@@ -531,9 +529,9 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c) ...@@ -531,9 +529,9 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
* send down an Idle-Frame (or an Sync-Frame, if * send down an Idle-Frame (or an Sync-Frame, if
* v->SyncInit != 0). * v->SyncInit != 0).
*/ */
if (!(v = dev->v110[idx])) if (!(v = iv110->v110))
return 0; return 0;
atomic_inc(&dev->v110use[idx]); atomic_inc(&iv110->v110use);
if (v->skbidle > 0) { if (v->skbidle > 0) {
v->skbidle--; v->skbidle--;
ret = 1; ret = 1;
...@@ -560,38 +558,38 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c) ...@@ -560,38 +558,38 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
} else } else
break; break;
} }
atomic_dec(&dev->v110use[idx]); atomic_dec(&iv110->v110use);
return ret; return ret;
case ISDN_STAT_DHUP: case ISDN_STAT_DHUP:
case ISDN_STAT_BHUP: case ISDN_STAT_BHUP:
while (1) { while (1) {
atomic_inc(&dev->v110use[idx]); atomic_inc(&iv110->v110use);
if (atomic_dec_and_test(&dev->v110use[idx])) { if (atomic_dec_and_test(&iv110->v110use)) {
isdn_v110_close(dev->v110[idx]); isdn_v110_close(iv110->v110);
dev->v110[idx] = NULL; iv110->v110 = NULL;
break; break;
} }
sti(); sti();
} }
break; break;
case ISDN_STAT_BCONN: case ISDN_STAT_BCONN:
if (dev->v110emu[idx] && (dev->v110[idx] == NULL)) { if (iv110->v110emu && (iv110->v110 == NULL)) {
int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen; int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen;
int maxsize = dev->drv[c->driver]->interface->maxbufsize; int maxsize = dev->drv[c->driver]->interface->maxbufsize;
atomic_inc(&dev->v110use[idx]); atomic_inc(&iv110->v110use);
switch (dev->v110emu[idx]) { switch (iv110->v110emu) {
case ISDN_PROTO_L2_V11096: case ISDN_PROTO_L2_V11096:
dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize); iv110->v110 = isdn_v110_open(V110_9600, hdrlen, maxsize);
break; break;
case ISDN_PROTO_L2_V11019: case ISDN_PROTO_L2_V11019:
dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize); iv110->v110 = isdn_v110_open(V110_19200, hdrlen, maxsize);
break; break;
case ISDN_PROTO_L2_V11038: case ISDN_PROTO_L2_V11038:
dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize); iv110->v110 = isdn_v110_open(V110_38400, hdrlen, maxsize);
break; break;
default:; default:;
} }
if ((v = dev->v110[idx])) { if ((v = iv110->v110)) {
while (v->SyncInit) { while (v->SyncInit) {
struct sk_buff *skb = isdn_v110_sync(v); struct sk_buff *skb = isdn_v110_sync(v);
if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) { if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
...@@ -603,8 +601,8 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c) ...@@ -603,8 +601,8 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
v->skbidle++; v->skbidle++;
} }
} else } else
printk(KERN_WARNING "isdn_v110: Couldn't open stream for chan %d\n", idx); printk(KERN_WARNING "isdn_v110: Couldn't open stream\n");
atomic_dec(&dev->v110use[idx]); atomic_dec(&iv110->v110use);
} }
break; break;
default: default:
......
...@@ -9,8 +9,14 @@ ...@@ -9,8 +9,14 @@
* *
*/ */
#ifndef _isdn_v110_h_ #ifndef ISDN_V110_H
#define _isdn_v110_h_ #define ISDN_V110_H
struct isdn_v110 {
int v110emu; /* V.110 emulator-mode 0=none */
atomic_t v110use; /* Usage-Semaphore for stream */
isdn_v110_stream *v110; /* V.110 private data */
};
/* /*
* isdn_v110_encode will take raw data and encode it using V.110 * isdn_v110_encode will take raw data and encode it using V.110
...@@ -23,7 +29,7 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *); ...@@ -23,7 +29,7 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
*/ */
extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *); extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
extern int isdn_v110_stat_callback(int, isdn_ctrl *); extern int isdn_v110_stat_callback(struct isdn_v110 *v110, isdn_ctrl *);
extern void isdn_v110_close(isdn_v110_stream * v); extern void isdn_v110_close(isdn_v110_stream * v);
#endif #endif
...@@ -757,6 +757,10 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller) ...@@ -757,6 +757,10 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
int i; int i;
static char nphone[30]; static char nphone[30];
if (!card) {
printk("BUG!!!\n");
return "";
}
switch (card->ptype) { switch (card->ptype) {
case ISDN_PTYPE_EURO: case ISDN_PTYPE_EURO:
if (caller) { if (caller) {
...@@ -775,7 +779,7 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller) ...@@ -775,7 +779,7 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
return (&phone[strlen(phone) - 1]); return (&phone[strlen(phone) - 1]);
break; break;
} }
return ("\0"); return "";
} }
/* /*
...@@ -882,7 +886,7 @@ isdnloop_parse_cmd(isdnloop_card * card) ...@@ -882,7 +886,7 @@ isdnloop_parse_cmd(isdnloop_card * card)
isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1), isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1),
cmd.parm.setup.si1, cmd.parm.setup.si1,
cmd.parm.setup.si2, cmd.parm.setup.si2,
isdnloop_vstphone(card->rcard[ch], isdnloop_vstphone(card->rcard[ch - 1],
cmd.parm.setup.phone, 0)); cmd.parm.setup.phone, 0));
isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1); isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1);
/* Fall through */ /* Fall through */
......
...@@ -245,18 +245,12 @@ typedef struct { ...@@ -245,18 +245,12 @@ typedef struct {
#define ISDN_TIMER_MODEMPLUS 2 #define ISDN_TIMER_MODEMPLUS 2
#define ISDN_TIMER_MODEMRING 4 #define ISDN_TIMER_MODEMRING 4
#define ISDN_TIMER_MODEMXMIT 8 #define ISDN_TIMER_MODEMXMIT 8
#define ISDN_TIMER_NETDIAL 16
#define ISDN_TIMER_NETHANGUP 32 #define ISDN_TIMER_NETHANGUP 32
#define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */ #define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */
#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \ #define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
ISDN_TIMER_MODEMXMIT) ISDN_TIMER_MODEMXMIT)
#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \ #define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
ISDN_TIMER_NETDIAL | ISDN_TIMER_CARRIER) ISDN_TIMER_CARRIER)
/* Timeout-Values for isdn_net_dial() */
#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
/* GLOBAL_FLAGS */ /* GLOBAL_FLAGS */
#define ISDN_GLOBAL_STOPPED 1 #define ISDN_GLOBAL_STOPPED 1
...@@ -291,9 +285,10 @@ typedef struct { ...@@ -291,9 +285,10 @@ typedef struct {
typedef struct isdn_net_local_s { typedef struct isdn_net_local_s {
ulong magic; ulong magic;
char name[10]; /* Name of device */ char name[10]; /* Name of device */
struct timer_list dial_timer; /* dial timeout */
int dial_event; /* event in case of timer expiry */
struct net_device_stats stats; /* Ethernet Statistics */ struct net_device_stats stats; /* Ethernet Statistics */
int isdn_device; /* Index to isdn-device */ int isdn_slot; /* Index to isdn device/channel */
int isdn_channel; /* Index to isdn-channel */
int ppp_slot; /* PPPD device slot number */ int ppp_slot; /* PPPD device slot number */
int pre_device; /* Preselected isdn-device */ int pre_device; /* Preselected isdn-device */
int pre_channel; /* Preselected isdn-channel */ int pre_channel; /* Preselected isdn-channel */
...@@ -302,7 +297,6 @@ typedef struct isdn_net_local_s { ...@@ -302,7 +297,6 @@ typedef struct isdn_net_local_s {
int dialretry; /* Counter for Dialout-retries */ int dialretry; /* Counter for Dialout-retries */
int dialmax; /* Max. Number of Dial-retries */ int dialmax; /* Max. Number of Dial-retries */
int cbdelay; /* Delay before Callback starts */ int cbdelay; /* Delay before Callback starts */
int dtimer; /* Timeout-counter for dialing */
char msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */ char msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */
u_char cbhup; /* Flag: Reject Call before Callback*/ u_char cbhup; /* Flag: Reject Call before Callback*/
u_char dialstate; /* State for dialing */ u_char dialstate; /* State for dialing */
...@@ -387,12 +381,12 @@ typedef struct isdn_net_local_s { ...@@ -387,12 +381,12 @@ typedef struct isdn_net_local_s {
/* the interface itself */ /* the interface itself */
typedef struct isdn_net_dev_s { typedef struct isdn_net_dev_s {
isdn_net_local *local; isdn_net_local local;
isdn_net_local *queue; /* circular list of all bundled isdn_net_local *queue; /* circular list of all bundled
channels, which are currently channels, which are currently
online */ online */
spinlock_t queue_lock; /* lock to protect queue */ spinlock_t queue_lock; /* lock to protect queue */
void *next; /* Pointer to next isdn-interface */ struct list_head global_list; /* global list of all isdn_net_devs */
struct net_device dev; /* interface to upper levels */ struct net_device dev; /* interface to upper levels */
#ifdef CONFIG_ISDN_PPP #ifdef CONFIG_ISDN_PPP
ippp_bundle * pb; /* pointer to the common bundle structure ippp_bundle * pb; /* pointer to the common bundle structure
...@@ -480,9 +474,7 @@ typedef struct modem_info { ...@@ -480,9 +474,7 @@ typedef struct modem_info {
/* 2 = B-Channel is up, deliver d.*/ /* 2 = B-Channel is up, deliver d.*/
int dialing; /* Dial in progress or ATA */ int dialing; /* Dial in progress or ATA */
int rcvsched; /* Receive needs schedule */ int rcvsched; /* Receive needs schedule */
int isdn_driver; /* Index to isdn-driver */ int isdn_slot; /* Index to isdn-driver/channel */
int isdn_channel; /* Index to isdn-channel */
int drv_index; /* Index to dev->usage */
int ncarrier; /* Flag: schedule NO CARRIER */ int ncarrier; /* Flag: schedule NO CARRIER */
unsigned char last_cause[8]; /* Last cause message */ unsigned char last_cause[8]; /* Last cause message */
unsigned char last_num[ISDN_MSNLEN]; unsigned char last_num[ISDN_MSNLEN];
...@@ -608,24 +600,10 @@ typedef struct isdn_devt { ...@@ -608,24 +600,10 @@ typedef struct isdn_devt {
infostruct *infochain; /* List of open info-devs. */ infostruct *infochain; /* List of open info-devs. */
wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */ wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */
struct timer_list timer; /* Misc.-function Timer */ struct timer_list timer; /* Misc.-function Timer */
int chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel */
int drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index */
int usage[ISDN_MAX_CHANNELS]; /* Used by tty/ip/voice */
char num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
/* Remote number of active ch.*/
int m_idx[ISDN_MAX_CHANNELS]; /* Index for mdm.... */
driver *drv[ISDN_MAX_DRIVERS]; /* Array of drivers */ driver *drv[ISDN_MAX_DRIVERS]; /* Array of drivers */
isdn_net_dev *netdev; /* Linked list of net-if's */
char drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID */ char drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID */
struct task_struct *profd; /* For iprofd */ struct task_struct *profd; /* For iprofd */
modem mdm; /* tty-driver-data */ modem mdm; /* tty-driver-data */
isdn_net_dev *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers */
isdn_net_dev *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers */
ulong ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes */
ulong obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes */
int v110emu[ISDN_MAX_CHANNELS];/* V.110 emulator-mode 0=none */
atomic_t v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */
isdn_v110_stream *v110[ISDN_MAX_CHANNELS]; /* V.110 private data */
struct semaphore sem; /* serialize list access*/ struct semaphore sem; /* serialize list access*/
unsigned long global_features; unsigned long global_features;
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
......
...@@ -418,9 +418,7 @@ typedef struct { ...@@ -418,9 +418,7 @@ typedef struct {
char display[85];/* display message data */ char display[85];/* display message data */
isdn_cmd_stat isdn_io; /* ISDN IO-parameter/result */ isdn_cmd_stat isdn_io; /* ISDN IO-parameter/result */
aux_s aux; /* for modem commands/indications */ aux_s aux; /* for modem commands/indications */
#ifdef CONFIG_ISDN_TTY_FAX
T30_s *fax; /* Pointer to ttys fax struct */ T30_s *fax; /* Pointer to ttys fax struct */
#endif
ulong userdata; /* User Data */ ulong userdata; /* User Data */
} parm; } parm;
} isdn_ctrl; } isdn_ctrl;
......
...@@ -422,6 +422,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -422,6 +422,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
{ {
struct mm_struct * mm = current->mm; struct mm_struct * mm = current->mm;
struct vm_area_struct * vma, * prev; struct vm_area_struct * vma, * prev;
struct inode *inode = NULL;
unsigned int vm_flags; unsigned int vm_flags;
int correct_wcount = 0; int correct_wcount = 0;
int error; int error;
...@@ -469,17 +470,18 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -469,17 +470,18 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
} }
if (file) { if (file) {
inode = file->f_dentry->d_inode;
switch (flags & MAP_TYPE) { switch (flags & MAP_TYPE) {
case MAP_SHARED: case MAP_SHARED:
if ((prot & PROT_WRITE) && !(file->f_mode & FMODE_WRITE)) if ((prot & PROT_WRITE) && !(file->f_mode & FMODE_WRITE))
return -EACCES; return -EACCES;
/* Make sure we don't allow writing to an append-only file.. */ /* Make sure we don't allow writing to an append-only file.. */
if (IS_APPEND(file->f_dentry->d_inode) && (file->f_mode & FMODE_WRITE)) if (IS_APPEND(inode) && (file->f_mode & FMODE_WRITE))
return -EACCES; return -EACCES;
/* make sure there are no mandatory locks on the file. */ /* make sure there are no mandatory locks on the file. */
if (locks_verify_locked(file->f_dentry->d_inode)) if (locks_verify_locked(inode))
return -EAGAIN; return -EAGAIN;
vm_flags |= VM_SHARED | VM_MAYSHARE; vm_flags |= VM_SHARED | VM_MAYSHARE;
...@@ -603,7 +605,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -603,7 +605,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
vma_link(mm, vma, prev, rb_link, rb_parent); vma_link(mm, vma, prev, rb_link, rb_parent);
if (correct_wcount) if (correct_wcount)
atomic_inc(&file->f_dentry->d_inode->i_writecount); atomic_inc(&inode->i_writecount);
out: out:
mm->total_vm += len >> PAGE_SHIFT; mm->total_vm += len >> PAGE_SHIFT;
...@@ -615,7 +617,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -615,7 +617,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
unmap_and_free_vma: unmap_and_free_vma:
if (correct_wcount) if (correct_wcount)
atomic_inc(&file->f_dentry->d_inode->i_writecount); atomic_inc(&inode->i_writecount);
vma->vm_file = NULL; vma->vm_file = NULL;
fput(file); fput(file);
...@@ -755,38 +757,41 @@ struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr, ...@@ -755,38 +757,41 @@ struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
return prev ? prev->vm_next : vma; return prev ? prev->vm_next : vma;
} }
#ifdef ARCH_STACK_GROWSUP
/* /*
* vma is the first one with address < vma->vm_end, * vma is the first one with address > vma->vm_end. Have to extend vma.
* and even address < vma->vm_start. Have to extend vma.
*/ */
int expand_stack(struct vm_area_struct * vma, unsigned long address) int expand_stack(struct vm_area_struct * vma, unsigned long address)
{ {
unsigned long grow; unsigned long grow;
if (!(vma->vm_flags & VM_GROWSUP))
return -EFAULT;
/* /*
* vma->vm_start/vm_end cannot change under us because the caller * vma->vm_start/vm_end cannot change under us because the caller
* is required to hold the mmap_sem in write mode. We need to get * is required to hold the mmap_sem in read mode. We need to get
* the spinlock only before relocating the vma range ourself. * the spinlock only before relocating the vma range ourself.
*/ */
address += 4 + PAGE_SIZE - 1;
address &= PAGE_MASK; address &= PAGE_MASK;
spin_lock(&vma->vm_mm->page_table_lock); spin_lock(&vma->vm_mm->page_table_lock);
grow = (vma->vm_start - address) >> PAGE_SHIFT; grow = (address - vma->vm_end) >> PAGE_SHIFT;
/* Overcommit.. */ /* Overcommit.. */
if(!vm_enough_memory(grow)) { if (!vm_enough_memory(grow)) {
spin_unlock(&vma->vm_mm->page_table_lock); spin_unlock(&vma->vm_mm->page_table_lock);
return -ENOMEM; return -ENOMEM;
} }
if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur || if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur ||
((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
current->rlim[RLIMIT_AS].rlim_cur) { current->rlim[RLIMIT_AS].rlim_cur) {
spin_unlock(&vma->vm_mm->page_table_lock); spin_unlock(&vma->vm_mm->page_table_lock);
vm_unacct_memory(grow); vm_unacct_memory(grow);
return -ENOMEM; return -ENOMEM;
} }
vma->vm_start = address; vma->vm_end = address;
vma->vm_pgoff -= grow;
vma->vm_mm->total_vm += grow; vma->vm_mm->total_vm += grow;
if (vma->vm_flags & VM_LOCKED) if (vma->vm_flags & VM_LOCKED)
vma->vm_mm->locked_vm += grow; vma->vm_mm->locked_vm += grow;
...@@ -794,7 +799,6 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address) ...@@ -794,7 +799,6 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
return 0; return 0;
} }
#ifdef ARCH_STACK_GROWSUP
struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr) struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr)
{ {
struct vm_area_struct *vma, *prev; struct vm_area_struct *vma, *prev;
...@@ -811,6 +815,44 @@ struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long add ...@@ -811,6 +815,44 @@ struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long add
return prev; return prev;
} }
#else #else
/*
* vma is the first one with address < vma->vm_start. Have to extend vma.
*/
int expand_stack(struct vm_area_struct * vma, unsigned long address)
{
unsigned long grow;
/*
* vma->vm_start/vm_end cannot change under us because the caller
* is required to hold the mmap_sem in read mode. We need to get
* the spinlock only before relocating the vma range ourself.
*/
address &= PAGE_MASK;
spin_lock(&vma->vm_mm->page_table_lock);
grow = (vma->vm_start - address) >> PAGE_SHIFT;
/* Overcommit.. */
if (!vm_enough_memory(grow)) {
spin_unlock(&vma->vm_mm->page_table_lock);
return -ENOMEM;
}
if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
current->rlim[RLIMIT_AS].rlim_cur) {
spin_unlock(&vma->vm_mm->page_table_lock);
vm_unacct_memory(grow);
return -ENOMEM;
}
vma->vm_start = address;
vma->vm_pgoff -= grow;
vma->vm_mm->total_vm += grow;
if (vma->vm_flags & VM_LOCKED)
vma->vm_mm->locked_vm += grow;
spin_unlock(&vma->vm_mm->page_table_lock);
return 0;
}
struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr) struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr)
{ {
struct vm_area_struct * vma; struct vm_area_struct * vma;
......
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