make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / atm / atmtcp.c
1 /* drivers/atm/atmtcp.c - ATM over TCP "device" driver */
2
3 /* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5
6 #include <linux/module.h>
7 #include <linux/wait.h>
8 #include <linux/atmdev.h>
9 #include <linux/atm_tcp.h>
10 #include <linux/bitops.h>
11 #include <asm/uaccess.h>
12 #include <asm/atomic.h>
13
14
15 extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
16
17
18 #define PRIV(dev) ((struct atmtcp_dev_data *) ((dev)->dev_data))
19
20
21 struct atmtcp_dev_data {
22         struct atm_vcc *vcc;    /* control VCC; NULL if detached */
23         int persist;            /* non-zero if persistent */
24 };
25
26
27 #define DEV_LABEL    "atmtcp"
28
29 #define MAX_VPI_BITS  8 /* simplifies life */
30 #define MAX_VCI_BITS 16
31
32
33 /*
34  * Hairy code ahead: the control VCC may be closed while we're still
35  * waiting for an answer, so we need to re-validate out_vcc every once
36  * in a while.
37  */
38
39
40 static int atmtcp_send_control(struct atm_vcc *vcc,int type,
41     const struct atmtcp_control *msg,int flag)
42 {
43         DECLARE_WAITQUEUE(wait,current);
44         struct atm_vcc *out_vcc;
45         struct sk_buff *skb;
46         struct atmtcp_control *new_msg;
47         int old_test;
48         int error = 0;
49
50         out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
51         if (!out_vcc) return -EUNATCH;
52         skb = alloc_skb(sizeof(*msg),GFP_KERNEL);
53         if (!skb) return -ENOMEM;
54         mb();
55         out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
56         if (!out_vcc) {
57                 dev_kfree_skb(skb);
58                 return -EUNATCH;
59         }
60         atm_force_charge(out_vcc,skb->truesize);
61         new_msg = (struct atmtcp_control *) skb_put(skb,sizeof(*new_msg));
62         *new_msg = *msg;
63         new_msg->hdr.length = ATMTCP_HDR_MAGIC;
64         new_msg->type = type;
65         memset(&new_msg->vcc,0,sizeof(atm_kptr_t));
66         *(struct atm_vcc **) &new_msg->vcc = vcc;
67         old_test = test_bit(flag,&vcc->flags);
68         out_vcc->push(out_vcc,skb);
69         add_wait_queue(&vcc->sleep,&wait);
70         while (test_bit(flag,&vcc->flags) == old_test) {
71                 mb();
72                 out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
73                 if (!out_vcc) {
74                         error = -EUNATCH;
75                         break;
76                 }
77                 set_current_state(TASK_UNINTERRUPTIBLE);
78                 schedule();
79         }
80         current->state = TASK_RUNNING;
81         remove_wait_queue(&vcc->sleep,&wait);
82         return error;
83 }
84
85
86 static int atmtcp_recv_control(const struct atmtcp_control *msg)
87 {
88         struct atm_vcc *vcc = *(struct atm_vcc **) &msg->vcc;
89
90         vcc->vpi = msg->addr.sap_addr.vpi;
91         vcc->vci = msg->addr.sap_addr.vci;
92         vcc->qos = msg->qos;
93         vcc->reply = msg->result;
94         switch (msg->type) {
95             case ATMTCP_CTRL_OPEN:
96                 change_bit(ATM_VF_READY,&vcc->flags);
97                 break;
98             case ATMTCP_CTRL_CLOSE:
99                 change_bit(ATM_VF_ADDR,&vcc->flags);
100                 break;
101             default:
102                 printk(KERN_ERR "atmtcp_recv_control: unknown type %d\n",
103                     msg->type);
104                 return -EINVAL;
105         }
106         wake_up(&vcc->sleep);
107         return 0;
108 }
109
110
111 static void atmtcp_v_dev_close(struct atm_dev *dev)
112 {
113         /* Nothing.... Isn't this simple :-)  -- REW */
114 }
115
116
117 static int atmtcp_v_open(struct atm_vcc *vcc,short vpi,int vci)
118 {
119         struct atmtcp_control msg;
120         int error;
121
122         memset(&msg,0,sizeof(msg));
123         msg.addr.sap_family = AF_ATMPVC;
124         msg.hdr.vpi = htons(vpi);
125         msg.addr.sap_addr.vpi = vpi;
126         msg.hdr.vci = htons(vci);
127         msg.addr.sap_addr.vci = vci;
128         error = atm_find_ci(vcc,&msg.addr.sap_addr.vpi,&msg.addr.sap_addr.vci);
129         if (error) return error;
130         if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) return 0;
131         msg.type = ATMTCP_CTRL_OPEN;
132         msg.qos = vcc->qos;
133         set_bit(ATM_VF_ADDR,&vcc->flags);
134         clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */
135         error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY);
136         if (error) return error;
137         return vcc->reply;
138 }
139
140
141 static void atmtcp_v_close(struct atm_vcc *vcc)
142 {
143         struct atmtcp_control msg;
144
145         memset(&msg,0,sizeof(msg));
146         msg.addr.sap_family = AF_ATMPVC;
147         msg.addr.sap_addr.vpi = vcc->vpi;
148         msg.addr.sap_addr.vci = vcc->vci;
149         clear_bit(ATM_VF_READY,&vcc->flags);
150         (void) atmtcp_send_control(vcc,ATMTCP_CTRL_CLOSE,&msg,ATM_VF_ADDR);
151 }
152
153
154 static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
155 {
156         struct atm_cirange ci;
157         struct atm_vcc *vcc;
158
159         if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD;
160         if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT;
161         if (ci.vpi_bits == ATM_CI_MAX) ci.vpi_bits = MAX_VPI_BITS;
162         if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS;
163         if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 ||
164             ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL;
165         for (vcc = dev->vccs; vcc; vcc = vcc->next)
166                 if ((vcc->vpi >> ci.vpi_bits) ||
167                     (vcc->vci >> ci.vci_bits)) return -EBUSY;
168         dev->ci_range = ci;
169         return 0;
170 }
171
172
173 static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb)
174 {
175         struct atmtcp_dev_data *dev_data;
176         struct atm_vcc *out_vcc=NULL; /* Initializer quietens GCC warning */
177         struct sk_buff *new_skb;
178         struct atmtcp_hdr *hdr;
179         int size;
180
181         if (vcc->qos.txtp.traffic_class == ATM_NONE) {
182                 if (vcc->pop) vcc->pop(vcc,skb);
183                 else dev_kfree_skb(skb);
184                 return -EINVAL;
185         }
186         dev_data = PRIV(vcc->dev);
187         if (dev_data) out_vcc = dev_data->vcc;
188         if (!dev_data || !out_vcc) {
189                 if (vcc->pop) vcc->pop(vcc,skb);
190                 else dev_kfree_skb(skb);
191                 if (dev_data) return 0;
192                 atomic_inc(&vcc->stats->tx_err);
193                 return -ENOLINK;
194         }
195         size = skb->len+sizeof(struct atmtcp_hdr);
196         new_skb = atm_alloc_charge(out_vcc,size,GFP_ATOMIC);
197         if (!new_skb) {
198                 if (vcc->pop) vcc->pop(vcc,skb);
199                 else dev_kfree_skb(skb);
200                 atomic_inc(&vcc->stats->tx_err);
201                 return -ENOBUFS;
202         }
203         hdr = (void *) skb_put(new_skb,sizeof(struct atmtcp_hdr));
204         hdr->vpi = htons(vcc->vpi);
205         hdr->vci = htons(vcc->vci);
206         hdr->length = htonl(skb->len);
207         memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
208         if (vcc->pop) vcc->pop(vcc,skb);
209         else dev_kfree_skb(skb);
210         out_vcc->push(out_vcc,new_skb);
211         atomic_inc(&vcc->stats->tx);
212         atomic_inc(&out_vcc->stats->rx);
213         return 0;
214 }
215
216
217 static int atmtcp_v_proc(struct atm_dev *dev,loff_t *pos,char *page)
218 {
219         struct atmtcp_dev_data *dev_data = PRIV(dev);
220
221         if (*pos) return 0;
222         if (!dev_data->persist) return sprintf(page,"ephemeral\n");
223         return sprintf(page,"persistent, %sconnected\n",
224             dev_data->vcc ? "" : "dis");
225 }
226
227
228 static void atmtcp_c_close(struct atm_vcc *vcc)
229 {
230         struct atm_dev *atmtcp_dev;
231         struct atmtcp_dev_data *dev_data;
232         struct atm_vcc *walk;
233
234         atmtcp_dev = (struct atm_dev *) vcc->dev_data;
235         dev_data = PRIV(atmtcp_dev);
236         dev_data->vcc = NULL;
237         if (dev_data->persist) return;
238         PRIV(atmtcp_dev) = NULL;
239         kfree(dev_data);
240         shutdown_atm_dev(atmtcp_dev);
241         vcc->dev_data = NULL;
242         for (walk = atmtcp_dev->vccs; walk; walk = walk->next)
243                 wake_up(&walk->sleep);
244 }
245
246
247 static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
248 {
249         struct atm_dev *dev;
250         struct atmtcp_hdr *hdr;
251         struct atm_vcc *out_vcc;
252         struct sk_buff *new_skb;
253         int result = 0;
254
255         if (!skb->len) return 0;
256         dev = vcc->dev_data;
257         hdr = (struct atmtcp_hdr *) skb->data;
258         if (hdr->length == ATMTCP_HDR_MAGIC) {
259                 result = atmtcp_recv_control(
260                     (struct atmtcp_control *) skb->data);
261                 goto done;
262         }
263         for (out_vcc = dev->vccs; out_vcc; out_vcc = out_vcc->next)
264                 if (out_vcc->vpi == ntohs(hdr->vpi) &&
265                     out_vcc->vci == ntohs(hdr->vci) &&
266                     out_vcc->qos.rxtp.traffic_class != ATM_NONE)
267                         break;
268         if (!out_vcc) {
269                 atomic_inc(&vcc->stats->tx_err);
270                 goto done;
271         }
272         skb_pull(skb,sizeof(struct atmtcp_hdr));
273         new_skb = atm_alloc_charge(out_vcc,skb->len,GFP_KERNEL);
274         if (!new_skb) {
275                 result = -ENOBUFS;
276                 goto done;
277         }
278         new_skb->stamp = xtime;
279         memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
280         out_vcc->push(out_vcc,new_skb);
281         atomic_inc(&vcc->stats->tx);
282         atomic_inc(&out_vcc->stats->rx);
283 done:
284         if (vcc->pop) vcc->pop(vcc,skb);
285         else dev_kfree_skb(skb);
286         return result;
287 }
288
289
290 /*
291  * Device operations for the virtual ATM devices created by ATMTCP.
292  */
293
294
295 static struct atmdev_ops atmtcp_v_dev_ops = {
296         dev_close:      atmtcp_v_dev_close,
297         open:           atmtcp_v_open,
298         close:          atmtcp_v_close,
299         ioctl:          atmtcp_v_ioctl,
300         send:           atmtcp_v_send,
301         proc_read:      atmtcp_v_proc,
302         owner:          THIS_MODULE
303 };
304
305
306 /*
307  * Device operations for the ATMTCP control device.
308  */
309
310
311 static struct atmdev_ops atmtcp_c_dev_ops = {
312         close:          atmtcp_c_close,
313         send:           atmtcp_c_send
314 };
315
316
317 static struct atm_dev atmtcp_control_dev = {
318         &atmtcp_c_dev_ops,
319         NULL,           /* no PHY */
320         "atmtcp",       /* type */
321         999,            /* dummy device number */
322         NULL,NULL,      /* pretend not to have any VCCs */
323         NULL,NULL,      /* no data */
324         { 0 },          /* no flags */
325         NULL,           /* no local address */
326         { 0 }           /* no ESI, no statistics */
327 };
328
329
330 static int atmtcp_create(int itf,int persist,struct atm_dev **result)
331 {
332         struct atmtcp_dev_data *dev_data;
333         struct atm_dev *dev;
334
335         dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL);
336         if (!dev_data)
337                 return -ENOMEM;
338
339         dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL);
340         if (!dev) {
341                 kfree(dev_data);
342                 return itf == -1 ? -ENOMEM : -EBUSY;
343         }
344         dev->ci_range.vpi_bits = MAX_VPI_BITS;
345         dev->ci_range.vci_bits = MAX_VCI_BITS;
346         PRIV(dev) = dev_data;
347         PRIV(dev)->vcc = NULL;
348         PRIV(dev)->persist = persist;
349         if (result) *result = dev;
350         return 0;
351 }
352
353
354 int atmtcp_attach(struct atm_vcc *vcc,int itf)
355 {
356         struct atm_dev *dev;
357
358         dev = NULL;
359         if (itf != -1) dev = atm_find_dev(itf);
360         if (dev) {
361                 if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
362                 if (PRIV(dev)->vcc) return -EBUSY;
363         }
364         else {
365                 int error;
366
367                 error = atmtcp_create(itf,0,&dev);
368                 if (error) return error;
369         }
370         PRIV(dev)->vcc = vcc;
371         bind_vcc(vcc,&atmtcp_control_dev);
372         set_bit(ATM_VF_META,&vcc->flags);
373         set_bit(ATM_VF_READY,&vcc->flags);
374         vcc->dev_data = dev;
375         (void) atm_init_aal5(vcc); /* @@@ losing AAL in transit ... */
376         vcc->stats = &atmtcp_control_dev.stats.aal5;
377         return dev->number;
378 }
379
380
381 int atmtcp_create_persistent(int itf)
382 {
383         return atmtcp_create(itf,1,NULL);
384 }
385
386
387 int atmtcp_remove_persistent(int itf)
388 {
389         struct atm_dev *dev;
390         struct atmtcp_dev_data *dev_data;
391
392         dev = atm_find_dev(itf);
393         if (!dev) return -ENODEV;
394         if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
395         dev_data = PRIV(dev);
396         if (!dev_data->persist) return 0;
397         dev_data->persist = 0;
398         if (PRIV(dev)->vcc) return 0;
399         kfree(dev_data);
400         shutdown_atm_dev(dev);
401         return 0;
402 }
403
404
405 #ifdef MODULE
406
407 int init_module(void)
408 {
409         atm_tcp_ops.attach = atmtcp_attach;
410         atm_tcp_ops.create_persistent = atmtcp_create_persistent;
411         atm_tcp_ops.remove_persistent = atmtcp_remove_persistent;
412         return 0;
413 }
414
415
416 void cleanup_module(void)
417 {
418         atm_tcp_ops.attach = NULL;
419         atm_tcp_ops.create_persistent = NULL;
420         atm_tcp_ops.remove_persistent = NULL;
421 }
422
423 MODULE_LICENSE("GPL");
424 #else
425
426 struct atm_tcp_ops atm_tcp_ops = {
427         atmtcp_attach,                  /* attach */
428         atmtcp_create_persistent,       /* create_persistent */
429         atmtcp_remove_persistent        /* remove_persistent */
430 };
431
432 #endif