Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
net
irda
sir_dongle.c
Go to the documentation of this file.
1
/*********************************************************************
2
*
3
* sir_dongle.c: manager for serial dongle protocol drivers
4
*
5
* Copyright (c) 2002 Martin Diehl
6
*
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License as
9
* published by the Free Software Foundation; either version 2 of
10
* the License, or (at your option) any later version.
11
*
12
********************************************************************/
13
14
#include <linux/module.h>
15
#include <linux/kernel.h>
16
#include <
linux/init.h
>
17
#include <
linux/kmod.h
>
18
#include <
linux/mutex.h
>
19
20
#include <
net/irda/irda.h
>
21
22
#include "
sir-dev.h
"
23
24
/**************************************************************************
25
*
26
* dongle registration and attachment
27
*
28
*/
29
30
static
LIST_HEAD
(dongle_list);
/* list of registered dongle drivers */
31
static
DEFINE_MUTEX
(dongle_list_lock);
/* protects the list */
32
33
int
irda_register_dongle
(
struct
dongle_driver
*
new
)
34
{
35
struct
list_head
*
entry
;
36
struct
dongle_driver
*drv;
37
38
IRDA_DEBUG
(0,
"%s : registering dongle \"%s\" (%d).\n"
,
39
__func__, new->driver_name, new->type);
40
41
mutex_lock
(&dongle_list_lock);
42
list_for_each
(entry, &
dongle_list
) {
43
drv =
list_entry
(entry,
struct
dongle_driver
,
dongle_list
);
44
if
(new->type == drv->
type
) {
45
mutex_unlock
(&dongle_list_lock);
46
return
-
EEXIST
;
47
}
48
}
49
list_add(&new->dongle_list, &
dongle_list
);
50
mutex_unlock
(&dongle_list_lock);
51
return
0;
52
}
53
EXPORT_SYMBOL
(
irda_register_dongle
);
54
55
int
irda_unregister_dongle
(
struct
dongle_driver
*drv)
56
{
57
mutex_lock
(&dongle_list_lock);
58
list_del
(&drv->
dongle_list
);
59
mutex_unlock
(&dongle_list_lock);
60
return
0;
61
}
62
EXPORT_SYMBOL
(
irda_unregister_dongle
);
63
64
int
sirdev_get_dongle
(
struct
sir_dev
*
dev
,
IRDA_DONGLE
type
)
65
{
66
struct
list_head
*
entry
;
67
const
struct
dongle_driver
*drv =
NULL
;
68
int
err
= -
EINVAL
;
69
70
request_module(
"irda-dongle-%d"
, type);
71
72
if
(dev->
dongle_drv
!=
NULL
)
73
return
-
EBUSY
;
74
75
/* serialize access to the list of registered dongles */
76
mutex_lock
(&dongle_list_lock);
77
78
list_for_each
(entry, &
dongle_list
) {
79
drv =
list_entry
(entry,
struct
dongle_driver
,
dongle_list
);
80
if
(drv->
type
== type)
81
break
;
82
else
83
drv =
NULL
;
84
}
85
86
if
(!drv) {
87
err = -
ENODEV
;
88
goto
out_unlock;
/* no such dongle */
89
}
90
91
/* handling of SMP races with dongle module removal - three cases:
92
* 1) dongle driver was already unregistered - then we haven't found the
93
* requested dongle above and are already out here
94
* 2) the module is already marked deleted but the driver is still
95
* registered - then the try_module_get() below will fail
96
* 3) the try_module_get() below succeeds before the module is marked
97
* deleted - then sys_delete_module() fails and prevents the removal
98
* because the module is in use.
99
*/
100
101
if
(!try_module_get(drv->
owner
)) {
102
err = -
ESTALE
;
103
goto
out_unlock;
/* rmmod already pending */
104
}
105
dev->
dongle_drv
= drv;
106
107
if
(!drv->
open
|| (err=drv->
open
(dev))!=0)
108
goto
out_reject;
/* failed to open driver */
109
110
mutex_unlock
(&dongle_list_lock);
111
return
0;
112
113
out_reject:
114
dev->
dongle_drv
=
NULL
;
115
module_put(drv->
owner
);
116
out_unlock:
117
mutex_unlock
(&dongle_list_lock);
118
return
err
;
119
}
120
121
int
sirdev_put_dongle
(
struct
sir_dev
*
dev
)
122
{
123
const
struct
dongle_driver
*drv = dev->
dongle_drv
;
124
125
if
(drv) {
126
if
(drv->
close
)
127
drv->
close
(dev);
/* close this dongle instance */
128
129
dev->
dongle_drv
=
NULL
;
/* unlink the dongle driver */
130
module_put(drv->
owner
);
/* decrement driver's module refcount */
131
}
132
133
return
0;
134
}
Generated on Thu Jan 10 2013 14:06:53 for Linux Kernel by
1.8.2