Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/gigaset/ser-gigaset.c
15109 views
1
/* This is the serial hardware link layer (HLL) for the Gigaset 307x isdn
2
* DECT base (aka Sinus 45 isdn) using the RS232 DECT data module M101,
3
* written as a line discipline.
4
*
5
* =====================================================================
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License as
8
* published by the Free Software Foundation; either version 2 of
9
* the License, or (at your option) any later version.
10
* =====================================================================
11
*/
12
13
#include "gigaset.h"
14
#include <linux/module.h>
15
#include <linux/moduleparam.h>
16
#include <linux/platform_device.h>
17
#include <linux/completion.h>
18
19
/* Version Information */
20
#define DRIVER_AUTHOR "Tilman Schmidt"
21
#define DRIVER_DESC "Serial Driver for Gigaset 307x using Siemens M101"
22
23
#define GIGASET_MINORS 1
24
#define GIGASET_MINOR 0
25
#define GIGASET_MODULENAME "ser_gigaset"
26
#define GIGASET_DEVNAME "ttyGS"
27
28
/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
29
#define IF_WRITEBUF 264
30
31
MODULE_AUTHOR(DRIVER_AUTHOR);
32
MODULE_DESCRIPTION(DRIVER_DESC);
33
MODULE_LICENSE("GPL");
34
MODULE_ALIAS_LDISC(N_GIGASET_M101);
35
36
static int startmode = SM_ISDN;
37
module_param(startmode, int, S_IRUGO);
38
MODULE_PARM_DESC(startmode, "initial operation mode");
39
static int cidmode = 1;
40
module_param(cidmode, int, S_IRUGO);
41
MODULE_PARM_DESC(cidmode, "stay in CID mode when idle");
42
43
static struct gigaset_driver *driver;
44
45
struct ser_cardstate {
46
struct platform_device dev;
47
struct tty_struct *tty;
48
atomic_t refcnt;
49
struct completion dead_cmp;
50
};
51
52
static struct platform_driver device_driver = {
53
.driver = {
54
.name = GIGASET_MODULENAME,
55
},
56
};
57
58
static void flush_send_queue(struct cardstate *);
59
60
/* transmit data from current open skb
61
* result: number of bytes sent or error code < 0
62
*/
63
static int write_modem(struct cardstate *cs)
64
{
65
struct tty_struct *tty = cs->hw.ser->tty;
66
struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
67
struct sk_buff *skb = bcs->tx_skb;
68
int sent = -EOPNOTSUPP;
69
70
if (!tty || !tty->driver || !skb)
71
return -EINVAL;
72
73
if (!skb->len) {
74
dev_kfree_skb_any(skb);
75
bcs->tx_skb = NULL;
76
return -EINVAL;
77
}
78
79
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
80
if (tty->ops->write)
81
sent = tty->ops->write(tty, skb->data, skb->len);
82
gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent);
83
if (sent < 0) {
84
/* error */
85
flush_send_queue(cs);
86
return sent;
87
}
88
skb_pull(skb, sent);
89
if (!skb->len) {
90
/* skb sent completely */
91
gigaset_skb_sent(bcs, skb);
92
93
gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
94
(unsigned long) skb);
95
dev_kfree_skb_any(skb);
96
bcs->tx_skb = NULL;
97
}
98
return sent;
99
}
100
101
/*
102
* transmit first queued command buffer
103
* result: number of bytes sent or error code < 0
104
*/
105
static int send_cb(struct cardstate *cs)
106
{
107
struct tty_struct *tty = cs->hw.ser->tty;
108
struct cmdbuf_t *cb, *tcb;
109
unsigned long flags;
110
int sent = 0;
111
112
if (!tty || !tty->driver)
113
return -EFAULT;
114
115
cb = cs->cmdbuf;
116
if (!cb)
117
return 0; /* nothing to do */
118
119
if (cb->len) {
120
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
121
sent = tty->ops->write(tty, cb->buf + cb->offset, cb->len);
122
if (sent < 0) {
123
/* error */
124
gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent);
125
flush_send_queue(cs);
126
return sent;
127
}
128
cb->offset += sent;
129
cb->len -= sent;
130
gig_dbg(DEBUG_OUTPUT, "send_cb: sent %d, left %u, queued %u",
131
sent, cb->len, cs->cmdbytes);
132
}
133
134
while (cb && !cb->len) {
135
spin_lock_irqsave(&cs->cmdlock, flags);
136
cs->cmdbytes -= cs->curlen;
137
tcb = cb;
138
cs->cmdbuf = cb = cb->next;
139
if (cb) {
140
cb->prev = NULL;
141
cs->curlen = cb->len;
142
} else {
143
cs->lastcmdbuf = NULL;
144
cs->curlen = 0;
145
}
146
spin_unlock_irqrestore(&cs->cmdlock, flags);
147
148
if (tcb->wake_tasklet)
149
tasklet_schedule(tcb->wake_tasklet);
150
kfree(tcb);
151
}
152
return sent;
153
}
154
155
/*
156
* send queue tasklet
157
* If there is already a skb opened, put data to the transfer buffer
158
* by calling "write_modem".
159
* Otherwise take a new skb out of the queue.
160
*/
161
static void gigaset_modem_fill(unsigned long data)
162
{
163
struct cardstate *cs = (struct cardstate *) data;
164
struct bc_state *bcs;
165
struct sk_buff *nextskb;
166
int sent = 0;
167
168
if (!cs) {
169
gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__);
170
return;
171
}
172
bcs = cs->bcs;
173
if (!bcs) {
174
gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__);
175
return;
176
}
177
if (!bcs->tx_skb) {
178
/* no skb is being sent; send command if any */
179
sent = send_cb(cs);
180
gig_dbg(DEBUG_OUTPUT, "%s: send_cb -> %d", __func__, sent);
181
if (sent)
182
/* something sent or error */
183
return;
184
185
/* no command to send; get skb */
186
nextskb = skb_dequeue(&bcs->squeue);
187
if (!nextskb)
188
/* no skb either, nothing to do */
189
return;
190
bcs->tx_skb = nextskb;
191
192
gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)",
193
(unsigned long) bcs->tx_skb);
194
}
195
196
/* send skb */
197
gig_dbg(DEBUG_OUTPUT, "%s: tx_skb", __func__);
198
if (write_modem(cs) < 0)
199
gig_dbg(DEBUG_OUTPUT, "%s: write_modem failed", __func__);
200
}
201
202
/*
203
* throw away all data queued for sending
204
*/
205
static void flush_send_queue(struct cardstate *cs)
206
{
207
struct sk_buff *skb;
208
struct cmdbuf_t *cb;
209
unsigned long flags;
210
211
/* command queue */
212
spin_lock_irqsave(&cs->cmdlock, flags);
213
while ((cb = cs->cmdbuf) != NULL) {
214
cs->cmdbuf = cb->next;
215
if (cb->wake_tasklet)
216
tasklet_schedule(cb->wake_tasklet);
217
kfree(cb);
218
}
219
cs->cmdbuf = cs->lastcmdbuf = NULL;
220
cs->cmdbytes = cs->curlen = 0;
221
spin_unlock_irqrestore(&cs->cmdlock, flags);
222
223
/* data queue */
224
if (cs->bcs->tx_skb)
225
dev_kfree_skb_any(cs->bcs->tx_skb);
226
while ((skb = skb_dequeue(&cs->bcs->squeue)) != NULL)
227
dev_kfree_skb_any(skb);
228
}
229
230
231
/* Gigaset Driver Interface */
232
/* ======================== */
233
234
/*
235
* queue an AT command string for transmission to the Gigaset device
236
* parameters:
237
* cs controller state structure
238
* buf buffer containing the string to send
239
* len number of characters to send
240
* wake_tasklet tasklet to run when transmission is complete, or NULL
241
* return value:
242
* number of bytes queued, or error code < 0
243
*/
244
static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
245
{
246
unsigned long flags;
247
248
gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
249
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
250
"CMD Transmit", cb->len, cb->buf);
251
252
spin_lock_irqsave(&cs->cmdlock, flags);
253
cb->prev = cs->lastcmdbuf;
254
if (cs->lastcmdbuf)
255
cs->lastcmdbuf->next = cb;
256
else {
257
cs->cmdbuf = cb;
258
cs->curlen = cb->len;
259
}
260
cs->cmdbytes += cb->len;
261
cs->lastcmdbuf = cb;
262
spin_unlock_irqrestore(&cs->cmdlock, flags);
263
264
spin_lock_irqsave(&cs->lock, flags);
265
if (cs->connected)
266
tasklet_schedule(&cs->write_tasklet);
267
spin_unlock_irqrestore(&cs->lock, flags);
268
return cb->len;
269
}
270
271
/*
272
* tty_driver.write_room interface routine
273
* return number of characters the driver will accept to be written
274
* parameter:
275
* controller state structure
276
* return value:
277
* number of characters
278
*/
279
static int gigaset_write_room(struct cardstate *cs)
280
{
281
unsigned bytes;
282
283
bytes = cs->cmdbytes;
284
return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0;
285
}
286
287
/*
288
* tty_driver.chars_in_buffer interface routine
289
* return number of characters waiting to be sent
290
* parameter:
291
* controller state structure
292
* return value:
293
* number of characters
294
*/
295
static int gigaset_chars_in_buffer(struct cardstate *cs)
296
{
297
return cs->cmdbytes;
298
}
299
300
/*
301
* implementation of ioctl(GIGASET_BRKCHARS)
302
* parameter:
303
* controller state structure
304
* return value:
305
* -EINVAL (unimplemented function)
306
*/
307
static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
308
{
309
/* not implemented */
310
return -EINVAL;
311
}
312
313
/*
314
* Open B channel
315
* Called by "do_action" in ev-layer.c
316
*/
317
static int gigaset_init_bchannel(struct bc_state *bcs)
318
{
319
/* nothing to do for M10x */
320
gigaset_bchannel_up(bcs);
321
return 0;
322
}
323
324
/*
325
* Close B channel
326
* Called by "do_action" in ev-layer.c
327
*/
328
static int gigaset_close_bchannel(struct bc_state *bcs)
329
{
330
/* nothing to do for M10x */
331
gigaset_bchannel_down(bcs);
332
return 0;
333
}
334
335
/*
336
* Set up B channel structure
337
* This is called by "gigaset_initcs" in common.c
338
*/
339
static int gigaset_initbcshw(struct bc_state *bcs)
340
{
341
/* unused */
342
bcs->hw.ser = NULL;
343
return 1;
344
}
345
346
/*
347
* Free B channel structure
348
* Called by "gigaset_freebcs" in common.c
349
*/
350
static int gigaset_freebcshw(struct bc_state *bcs)
351
{
352
/* unused */
353
return 1;
354
}
355
356
/*
357
* Reinitialize B channel structure
358
* This is called by "bcs_reinit" in common.c
359
*/
360
static void gigaset_reinitbcshw(struct bc_state *bcs)
361
{
362
/* nothing to do for M10x */
363
}
364
365
/*
366
* Free hardware specific device data
367
* This will be called by "gigaset_freecs" in common.c
368
*/
369
static void gigaset_freecshw(struct cardstate *cs)
370
{
371
tasklet_kill(&cs->write_tasklet);
372
if (!cs->hw.ser)
373
return;
374
dev_set_drvdata(&cs->hw.ser->dev.dev, NULL);
375
platform_device_unregister(&cs->hw.ser->dev);
376
kfree(cs->hw.ser);
377
cs->hw.ser = NULL;
378
}
379
380
static void gigaset_device_release(struct device *dev)
381
{
382
struct platform_device *pdev = to_platform_device(dev);
383
384
/* adapted from platform_device_release() in drivers/base/platform.c */
385
kfree(dev->platform_data);
386
kfree(pdev->resource);
387
}
388
389
/*
390
* Set up hardware specific device data
391
* This is called by "gigaset_initcs" in common.c
392
*/
393
static int gigaset_initcshw(struct cardstate *cs)
394
{
395
int rc;
396
struct ser_cardstate *scs;
397
398
scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL);
399
if (!scs) {
400
pr_err("out of memory\n");
401
return 0;
402
}
403
cs->hw.ser = scs;
404
405
cs->hw.ser->dev.name = GIGASET_MODULENAME;
406
cs->hw.ser->dev.id = cs->minor_index;
407
cs->hw.ser->dev.dev.release = gigaset_device_release;
408
rc = platform_device_register(&cs->hw.ser->dev);
409
if (rc != 0) {
410
pr_err("error %d registering platform device\n", rc);
411
kfree(cs->hw.ser);
412
cs->hw.ser = NULL;
413
return 0;
414
}
415
dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
416
417
tasklet_init(&cs->write_tasklet,
418
gigaset_modem_fill, (unsigned long) cs);
419
return 1;
420
}
421
422
/*
423
* set modem control lines
424
* Parameters:
425
* card state structure
426
* modem control line state ([TIOCM_DTR]|[TIOCM_RTS])
427
* Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c
428
* and by "if_lock" and "if_termios" in interface.c
429
*/
430
static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
431
unsigned new_state)
432
{
433
struct tty_struct *tty = cs->hw.ser->tty;
434
unsigned int set, clear;
435
436
if (!tty || !tty->driver || !tty->ops->tiocmset)
437
return -EINVAL;
438
set = new_state & ~old_state;
439
clear = old_state & ~new_state;
440
if (!set && !clear)
441
return 0;
442
gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
443
return tty->ops->tiocmset(tty, set, clear);
444
}
445
446
static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
447
{
448
return -EINVAL;
449
}
450
451
static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
452
{
453
return -EINVAL;
454
}
455
456
static const struct gigaset_ops ops = {
457
gigaset_write_cmd,
458
gigaset_write_room,
459
gigaset_chars_in_buffer,
460
gigaset_brkchars,
461
gigaset_init_bchannel,
462
gigaset_close_bchannel,
463
gigaset_initbcshw,
464
gigaset_freebcshw,
465
gigaset_reinitbcshw,
466
gigaset_initcshw,
467
gigaset_freecshw,
468
gigaset_set_modem_ctrl,
469
gigaset_baud_rate,
470
gigaset_set_line_ctrl,
471
gigaset_m10x_send_skb, /* asyncdata.c */
472
gigaset_m10x_input, /* asyncdata.c */
473
};
474
475
476
/* Line Discipline Interface */
477
/* ========================= */
478
479
/* helper functions for cardstate refcounting */
480
static struct cardstate *cs_get(struct tty_struct *tty)
481
{
482
struct cardstate *cs = tty->disc_data;
483
484
if (!cs || !cs->hw.ser) {
485
gig_dbg(DEBUG_ANY, "%s: no cardstate", __func__);
486
return NULL;
487
}
488
atomic_inc(&cs->hw.ser->refcnt);
489
return cs;
490
}
491
492
static void cs_put(struct cardstate *cs)
493
{
494
if (atomic_dec_and_test(&cs->hw.ser->refcnt))
495
complete(&cs->hw.ser->dead_cmp);
496
}
497
498
/*
499
* Called by the tty driver when the line discipline is pushed onto the tty.
500
* Called in process context.
501
*/
502
static int
503
gigaset_tty_open(struct tty_struct *tty)
504
{
505
struct cardstate *cs;
506
507
gig_dbg(DEBUG_INIT, "Starting HLL for Gigaset M101");
508
509
pr_info(DRIVER_DESC "\n");
510
511
if (!driver) {
512
pr_err("%s: no driver structure\n", __func__);
513
return -ENODEV;
514
}
515
516
/* allocate memory for our device state and initialize it */
517
cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
518
if (!cs)
519
goto error;
520
521
cs->dev = &cs->hw.ser->dev.dev;
522
cs->hw.ser->tty = tty;
523
atomic_set(&cs->hw.ser->refcnt, 1);
524
init_completion(&cs->hw.ser->dead_cmp);
525
526
tty->disc_data = cs;
527
528
/* OK.. Initialization of the datastructures and the HW is done.. Now
529
* startup system and notify the LL that we are ready to run
530
*/
531
if (startmode == SM_LOCKED)
532
cs->mstate = MS_LOCKED;
533
if (!gigaset_start(cs)) {
534
tasklet_kill(&cs->write_tasklet);
535
goto error;
536
}
537
538
gig_dbg(DEBUG_INIT, "Startup of HLL done");
539
return 0;
540
541
error:
542
gig_dbg(DEBUG_INIT, "Startup of HLL failed");
543
tty->disc_data = NULL;
544
gigaset_freecs(cs);
545
return -ENODEV;
546
}
547
548
/*
549
* Called by the tty driver when the line discipline is removed.
550
* Called from process context.
551
*/
552
static void
553
gigaset_tty_close(struct tty_struct *tty)
554
{
555
struct cardstate *cs = tty->disc_data;
556
557
gig_dbg(DEBUG_INIT, "Stopping HLL for Gigaset M101");
558
559
if (!cs) {
560
gig_dbg(DEBUG_INIT, "%s: no cardstate", __func__);
561
return;
562
}
563
564
/* prevent other callers from entering ldisc methods */
565
tty->disc_data = NULL;
566
567
if (!cs->hw.ser)
568
pr_err("%s: no hw cardstate\n", __func__);
569
else {
570
/* wait for running methods to finish */
571
if (!atomic_dec_and_test(&cs->hw.ser->refcnt))
572
wait_for_completion(&cs->hw.ser->dead_cmp);
573
}
574
575
/* stop operations */
576
gigaset_stop(cs);
577
tasklet_kill(&cs->write_tasklet);
578
flush_send_queue(cs);
579
cs->dev = NULL;
580
gigaset_freecs(cs);
581
582
gig_dbg(DEBUG_INIT, "Shutdown of HLL done");
583
}
584
585
/*
586
* Called by the tty driver when the tty line is hung up.
587
* Wait for I/O to driver to complete and unregister ISDN device.
588
* This is already done by the close routine, so just call that.
589
* Called from process context.
590
*/
591
static int gigaset_tty_hangup(struct tty_struct *tty)
592
{
593
gigaset_tty_close(tty);
594
return 0;
595
}
596
597
/*
598
* Read on the tty.
599
* Unused, received data goes only to the Gigaset driver.
600
*/
601
static ssize_t
602
gigaset_tty_read(struct tty_struct *tty, struct file *file,
603
unsigned char __user *buf, size_t count)
604
{
605
return -EAGAIN;
606
}
607
608
/*
609
* Write on the tty.
610
* Unused, transmit data comes only from the Gigaset driver.
611
*/
612
static ssize_t
613
gigaset_tty_write(struct tty_struct *tty, struct file *file,
614
const unsigned char *buf, size_t count)
615
{
616
return -EAGAIN;
617
}
618
619
/*
620
* Ioctl on the tty.
621
* Called in process context only.
622
* May be re-entered by multiple ioctl calling threads.
623
*/
624
static int
625
gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
626
unsigned int cmd, unsigned long arg)
627
{
628
struct cardstate *cs = cs_get(tty);
629
int rc, val;
630
int __user *p = (int __user *)arg;
631
632
if (!cs)
633
return -ENXIO;
634
635
switch (cmd) {
636
637
case FIONREAD:
638
/* unused, always return zero */
639
val = 0;
640
rc = put_user(val, p);
641
break;
642
643
case TCFLSH:
644
/* flush our buffers and the serial port's buffer */
645
switch (arg) {
646
case TCIFLUSH:
647
/* no own input buffer to flush */
648
break;
649
case TCIOFLUSH:
650
case TCOFLUSH:
651
flush_send_queue(cs);
652
break;
653
}
654
/* Pass through */
655
656
default:
657
/* pass through to underlying serial device */
658
rc = n_tty_ioctl_helper(tty, file, cmd, arg);
659
break;
660
}
661
cs_put(cs);
662
return rc;
663
}
664
665
/*
666
* Called by the tty driver when a block of data has been received.
667
* Will not be re-entered while running but other ldisc functions
668
* may be called in parallel.
669
* Can be called from hard interrupt level as well as soft interrupt
670
* level or mainline.
671
* Parameters:
672
* tty tty structure
673
* buf buffer containing received characters
674
* cflags buffer containing error flags for received characters (ignored)
675
* count number of received characters
676
*/
677
static void
678
gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
679
char *cflags, int count)
680
{
681
struct cardstate *cs = cs_get(tty);
682
unsigned tail, head, n;
683
struct inbuf_t *inbuf;
684
685
if (!cs)
686
return;
687
inbuf = cs->inbuf;
688
if (!inbuf) {
689
dev_err(cs->dev, "%s: no inbuf\n", __func__);
690
cs_put(cs);
691
return;
692
}
693
694
tail = inbuf->tail;
695
head = inbuf->head;
696
gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes",
697
head, tail, count);
698
699
if (head <= tail) {
700
/* possible buffer wraparound */
701
n = min_t(unsigned, count, RBUFSIZE - tail);
702
memcpy(inbuf->data + tail, buf, n);
703
tail = (tail + n) % RBUFSIZE;
704
buf += n;
705
count -= n;
706
}
707
708
if (count > 0) {
709
/* tail < head and some data left */
710
n = head - tail - 1;
711
if (count > n) {
712
dev_err(cs->dev,
713
"inbuf overflow, discarding %d bytes\n",
714
count - n);
715
count = n;
716
}
717
memcpy(inbuf->data + tail, buf, count);
718
tail += count;
719
}
720
721
gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
722
inbuf->tail = tail;
723
724
/* Everything was received .. Push data into handler */
725
gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
726
gigaset_schedule_event(cs);
727
cs_put(cs);
728
}
729
730
/*
731
* Called by the tty driver when there's room for more data to send.
732
*/
733
static void
734
gigaset_tty_wakeup(struct tty_struct *tty)
735
{
736
struct cardstate *cs = cs_get(tty);
737
738
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
739
if (!cs)
740
return;
741
tasklet_schedule(&cs->write_tasklet);
742
cs_put(cs);
743
}
744
745
static struct tty_ldisc_ops gigaset_ldisc = {
746
.owner = THIS_MODULE,
747
.magic = TTY_LDISC_MAGIC,
748
.name = "ser_gigaset",
749
.open = gigaset_tty_open,
750
.close = gigaset_tty_close,
751
.hangup = gigaset_tty_hangup,
752
.read = gigaset_tty_read,
753
.write = gigaset_tty_write,
754
.ioctl = gigaset_tty_ioctl,
755
.receive_buf = gigaset_tty_receive,
756
.write_wakeup = gigaset_tty_wakeup,
757
};
758
759
760
/* Initialization / Shutdown */
761
/* ========================= */
762
763
static int __init ser_gigaset_init(void)
764
{
765
int rc;
766
767
gig_dbg(DEBUG_INIT, "%s", __func__);
768
rc = platform_driver_register(&device_driver);
769
if (rc != 0) {
770
pr_err("error %d registering platform driver\n", rc);
771
return rc;
772
}
773
774
/* allocate memory for our driver state and initialize it */
775
driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
776
GIGASET_MODULENAME, GIGASET_DEVNAME,
777
&ops, THIS_MODULE);
778
if (!driver)
779
goto error;
780
781
rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc);
782
if (rc != 0) {
783
pr_err("error %d registering line discipline\n", rc);
784
goto error;
785
}
786
787
return 0;
788
789
error:
790
if (driver) {
791
gigaset_freedriver(driver);
792
driver = NULL;
793
}
794
platform_driver_unregister(&device_driver);
795
return rc;
796
}
797
798
static void __exit ser_gigaset_exit(void)
799
{
800
int rc;
801
802
gig_dbg(DEBUG_INIT, "%s", __func__);
803
804
if (driver) {
805
gigaset_freedriver(driver);
806
driver = NULL;
807
}
808
809
rc = tty_unregister_ldisc(N_GIGASET_M101);
810
if (rc != 0)
811
pr_err("error %d unregistering line discipline\n", rc);
812
813
platform_driver_unregister(&device_driver);
814
}
815
816
module_init(ser_gigaset_init);
817
module_exit(ser_gigaset_exit);
818
819