OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [tags/] [linux-2.6/] [linux-2.6.24_or32_unified_v2.3/] [net/] [atm/] [signaling.c] - Blame information for rev 8

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/* net/atm/signaling.c - ATM signaling */
2
 
3
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
 
5
 
6
#include <linux/errno.h>        /* error codes */
7
#include <linux/kernel.h>       /* printk */
8
#include <linux/skbuff.h>
9
#include <linux/wait.h>
10
#include <linux/sched.h>        /* jiffies and HZ */
11
#include <linux/atm.h>          /* ATM stuff */
12
#include <linux/atmsap.h>
13
#include <linux/atmsvc.h>
14
#include <linux/atmdev.h>
15
#include <linux/bitops.h>
16
 
17
#include "resources.h"
18
#include "signaling.h"
19
 
20
 
21
#undef WAIT_FOR_DEMON           /* #define this if system calls on SVC sockets
22
                                   should block until the demon runs.
23
                                   Danger: may cause nasty hangs if the demon
24
                                   crashes. */
25
 
26
struct atm_vcc *sigd = NULL;
27
#ifdef WAIT_FOR_DEMON
28
static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);
29
#endif
30
 
31
 
32
static void sigd_put_skb(struct sk_buff *skb)
33
{
34
#ifdef WAIT_FOR_DEMON
35
        DECLARE_WAITQUEUE(wait,current);
36
 
37
        add_wait_queue(&sigd_sleep,&wait);
38
        while (!sigd) {
39
                set_current_state(TASK_UNINTERRUPTIBLE);
40
                pr_debug("atmsvc: waiting for signaling demon...\n");
41
                schedule();
42
        }
43
        current->state = TASK_RUNNING;
44
        remove_wait_queue(&sigd_sleep,&wait);
45
#else
46
        if (!sigd) {
47
                pr_debug("atmsvc: no signaling demon\n");
48
                kfree_skb(skb);
49
                return;
50
        }
51
#endif
52
        atm_force_charge(sigd,skb->truesize);
53
        skb_queue_tail(&sk_atm(sigd)->sk_receive_queue,skb);
54
        sk_atm(sigd)->sk_data_ready(sk_atm(sigd), skb->len);
55
}
56
 
57
 
58
static void modify_qos(struct atm_vcc *vcc,struct atmsvc_msg *msg)
59
{
60
        struct sk_buff *skb;
61
 
62
        if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
63
            !test_bit(ATM_VF_READY,&vcc->flags))
64
                return;
65
        msg->type = as_error;
66
        if (!vcc->dev->ops->change_qos) msg->reply = -EOPNOTSUPP;
67
        else {
68
                /* should lock VCC */
69
                msg->reply = vcc->dev->ops->change_qos(vcc,&msg->qos,
70
                    msg->reply);
71
                if (!msg->reply) msg->type = as_okay;
72
        }
73
        /*
74
         * Should probably just turn around the old skb. But the, the buffer
75
         * space accounting needs to follow the change too. Maybe later.
76
         */
77
        while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL)))
78
                schedule();
79
        *(struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg)) = *msg;
80
        sigd_put_skb(skb);
81
}
82
 
83
 
84
static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
85
{
86
        struct atmsvc_msg *msg;
87
        struct atm_vcc *session_vcc;
88
        struct sock *sk;
89
 
90
        msg = (struct atmsvc_msg *) skb->data;
91
        atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
92
        vcc = *(struct atm_vcc **) &msg->vcc;
93
        pr_debug("sigd_send %d (0x%lx)\n",(int) msg->type,
94
          (unsigned long) vcc);
95
        sk = sk_atm(vcc);
96
 
97
        switch (msg->type) {
98
                case as_okay:
99
                        sk->sk_err = -msg->reply;
100
                        clear_bit(ATM_VF_WAITING, &vcc->flags);
101
                        if (!*vcc->local.sas_addr.prv &&
102
                            !*vcc->local.sas_addr.pub) {
103
                                vcc->local.sas_family = AF_ATMSVC;
104
                                memcpy(vcc->local.sas_addr.prv,
105
                                    msg->local.sas_addr.prv,ATM_ESA_LEN);
106
                                memcpy(vcc->local.sas_addr.pub,
107
                                    msg->local.sas_addr.pub,ATM_E164_LEN+1);
108
                        }
109
                        session_vcc = vcc->session ? vcc->session : vcc;
110
                        if (session_vcc->vpi || session_vcc->vci) break;
111
                        session_vcc->itf = msg->pvc.sap_addr.itf;
112
                        session_vcc->vpi = msg->pvc.sap_addr.vpi;
113
                        session_vcc->vci = msg->pvc.sap_addr.vci;
114
                        if (session_vcc->vpi || session_vcc->vci)
115
                                session_vcc->qos = msg->qos;
116
                        break;
117
                case as_error:
118
                        clear_bit(ATM_VF_REGIS,&vcc->flags);
119
                        clear_bit(ATM_VF_READY,&vcc->flags);
120
                        sk->sk_err = -msg->reply;
121
                        clear_bit(ATM_VF_WAITING, &vcc->flags);
122
                        break;
123
                case as_indicate:
124
                        vcc = *(struct atm_vcc **) &msg->listen_vcc;
125
                        sk = sk_atm(vcc);
126
                        pr_debug("as_indicate!!!\n");
127
                        lock_sock(sk);
128
                        if (sk_acceptq_is_full(sk)) {
129
                                sigd_enq(NULL,as_reject,vcc,NULL,NULL);
130
                                dev_kfree_skb(skb);
131
                                goto as_indicate_complete;
132
                        }
133
                        sk->sk_ack_backlog++;
134
                        skb_queue_tail(&sk->sk_receive_queue, skb);
135
                        pr_debug("waking sk->sk_sleep 0x%p\n", sk->sk_sleep);
136
                        sk->sk_state_change(sk);
137
as_indicate_complete:
138
                        release_sock(sk);
139
                        return 0;
140
                case as_close:
141
                        set_bit(ATM_VF_RELEASED,&vcc->flags);
142
                        vcc_release_async(vcc, msg->reply);
143
                        goto out;
144
                case as_modify:
145
                        modify_qos(vcc,msg);
146
                        break;
147
                case as_addparty:
148
                case as_dropparty:
149
                        sk->sk_err_soft = msg->reply;   /* < 0 failure, otherwise ep_ref */
150
                        clear_bit(ATM_VF_WAITING, &vcc->flags);
151
                        break;
152
                default:
153
                        printk(KERN_ALERT "sigd_send: bad message type %d\n",
154
                            (int) msg->type);
155
                        return -EINVAL;
156
        }
157
        sk->sk_state_change(sk);
158
out:
159
        dev_kfree_skb(skb);
160
        return 0;
161
}
162
 
163
 
164
void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type,
165
    struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
166
    const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply)
167
{
168
        struct sk_buff *skb;
169
        struct atmsvc_msg *msg;
170
        static unsigned session = 0;
171
 
172
        pr_debug("sigd_enq %d (0x%p)\n",(int) type,vcc);
173
        while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL)))
174
                schedule();
175
        msg = (struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg));
176
        memset(msg,0,sizeof(*msg));
177
        msg->type = type;
178
        *(struct atm_vcc **) &msg->vcc = vcc;
179
        *(struct atm_vcc **) &msg->listen_vcc = listen_vcc;
180
        msg->reply = reply;
181
        if (qos) msg->qos = *qos;
182
        if (vcc) msg->sap = vcc->sap;
183
        if (svc) msg->svc = *svc;
184
        if (vcc) msg->local = vcc->local;
185
        if (pvc) msg->pvc = *pvc;
186
        if (vcc) {
187
                if (type == as_connect && test_bit(ATM_VF_SESSION, &vcc->flags))
188
                        msg->session = ++session;
189
                        /* every new pmp connect gets the next session number */
190
        }
191
        sigd_put_skb(skb);
192
        if (vcc) set_bit(ATM_VF_REGIS,&vcc->flags);
193
}
194
 
195
 
196
void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
197
    struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
198
    const struct sockaddr_atmsvc *svc)
199
{
200
        sigd_enq2(vcc,type,listen_vcc,pvc,svc,vcc ? &vcc->qos : NULL,0);
201
        /* other ISP applications may use "reply" */
202
}
203
 
204
 
205
static void purge_vcc(struct atm_vcc *vcc)
206
{
207
        if (sk_atm(vcc)->sk_family == PF_ATMSVC &&
208
            !test_bit(ATM_VF_META, &vcc->flags)) {
209
                set_bit(ATM_VF_RELEASED, &vcc->flags);
210
                clear_bit(ATM_VF_REGIS, &vcc->flags);
211
                vcc_release_async(vcc, -EUNATCH);
212
        }
213
}
214
 
215
 
216
static void sigd_close(struct atm_vcc *vcc)
217
{
218
        struct hlist_node *node;
219
        struct sock *s;
220
        int i;
221
 
222
        pr_debug("sigd_close\n");
223
        sigd = NULL;
224
        if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
225
                printk(KERN_ERR "sigd_close: closing with requests pending\n");
226
        skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
227
 
228
        read_lock(&vcc_sklist_lock);
229
        for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
230
                struct hlist_head *head = &vcc_hash[i];
231
 
232
                sk_for_each(s, node, head) {
233
                        vcc = atm_sk(s);
234
 
235
                        purge_vcc(vcc);
236
                }
237
        }
238
        read_unlock(&vcc_sklist_lock);
239
}
240
 
241
 
242
static struct atmdev_ops sigd_dev_ops = {
243
        .close = sigd_close,
244
        .send = sigd_send
245
};
246
 
247
 
248
static struct atm_dev sigd_dev = {
249
        .ops =          &sigd_dev_ops,
250
        .type =         "sig",
251
        .number =       999,
252
        .lock =         __SPIN_LOCK_UNLOCKED(sigd_dev.lock)
253
};
254
 
255
 
256
int sigd_attach(struct atm_vcc *vcc)
257
{
258
        if (sigd) return -EADDRINUSE;
259
        pr_debug("sigd_attach\n");
260
        sigd = vcc;
261
        vcc->dev = &sigd_dev;
262
        vcc_insert_socket(sk_atm(vcc));
263
        set_bit(ATM_VF_META,&vcc->flags);
264
        set_bit(ATM_VF_READY,&vcc->flags);
265
#ifdef WAIT_FOR_DEMON
266
        wake_up(&sigd_sleep);
267
#endif
268
        return 0;
269
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.