diff options
-rw-r--r-- | include/net/caif/cfsrvl.h | 29 | ||||
-rw-r--r-- | net/caif/cfrfml.c | 4 | ||||
-rw-r--r-- | net/caif/cfsrvl.c | 35 |
3 files changed, 47 insertions, 21 deletions
diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h index 6c8279c1ae9a..0f5905241843 100644 --- a/include/net/caif/cfsrvl.h +++ b/include/net/caif/cfsrvl.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/stddef.h> | 10 | #include <linux/stddef.h> |
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/kref.h> | 12 | #include <linux/kref.h> |
13 | #include <linux/rculist.h> | ||
13 | 14 | ||
14 | struct cfsrvl { | 15 | struct cfsrvl { |
15 | struct cflayer layer; | 16 | struct cflayer layer; |
@@ -17,9 +18,11 @@ struct cfsrvl { | |||
17 | bool phy_flow_on; | 18 | bool phy_flow_on; |
18 | bool modem_flow_on; | 19 | bool modem_flow_on; |
19 | bool supports_flowctrl; | 20 | bool supports_flowctrl; |
20 | void (*release)(struct kref *); | 21 | void (*release)(struct cflayer *layer); |
21 | struct dev_info dev_info; | 22 | struct dev_info dev_info; |
22 | struct kref ref; | 23 | void (*hold)(struct cflayer *lyr); |
24 | void (*put)(struct cflayer *lyr); | ||
25 | struct rcu_head rcu; | ||
23 | }; | 26 | }; |
24 | 27 | ||
25 | struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info); | 28 | struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info); |
@@ -29,6 +32,10 @@ struct cflayer *cfvidl_create(u8 linkid, struct dev_info *dev_info); | |||
29 | struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info, | 32 | struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info, |
30 | int mtu_size); | 33 | int mtu_size); |
31 | struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info); | 34 | struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info); |
35 | |||
36 | void cfsrvl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | ||
37 | int phyid); | ||
38 | |||
32 | bool cfsrvl_phyid_match(struct cflayer *layer, int phyid); | 39 | bool cfsrvl_phyid_match(struct cflayer *layer, int phyid); |
33 | 40 | ||
34 | void cfsrvl_init(struct cfsrvl *service, | 41 | void cfsrvl_init(struct cfsrvl *service, |
@@ -40,23 +47,19 @@ u8 cfsrvl_getphyid(struct cflayer *layer); | |||
40 | 47 | ||
41 | static inline void cfsrvl_get(struct cflayer *layr) | 48 | static inline void cfsrvl_get(struct cflayer *layr) |
42 | { | 49 | { |
43 | struct cfsrvl *s; | 50 | struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); |
44 | if (layr == NULL) | 51 | if (layr == NULL || layr->up == NULL || s->hold == NULL) |
45 | return; | 52 | return; |
46 | s = container_of(layr, struct cfsrvl, layer); | 53 | |
47 | kref_get(&s->ref); | 54 | s->hold(layr->up); |
48 | } | 55 | } |
49 | 56 | ||
50 | static inline void cfsrvl_put(struct cflayer *layr) | 57 | static inline void cfsrvl_put(struct cflayer *layr) |
51 | { | 58 | { |
52 | struct cfsrvl *s; | 59 | struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); |
53 | if (layr == NULL) | 60 | if (layr == NULL || layr->up == NULL || s->hold == NULL) |
54 | return; | 61 | return; |
55 | s = container_of(layr, struct cfsrvl, layer); | ||
56 | 62 | ||
57 | WARN_ON(!s->release); | 63 | s->put(layr->up); |
58 | if (s->release) | ||
59 | kref_put(&s->ref, s->release); | ||
60 | } | 64 | } |
61 | |||
62 | #endif /* CFSRVL_H_ */ | 65 | #endif /* CFSRVL_H_ */ |
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index e2fb5fa75795..0deabb440051 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c | |||
@@ -31,9 +31,9 @@ struct cfrfml { | |||
31 | spinlock_t sync; | 31 | spinlock_t sync; |
32 | }; | 32 | }; |
33 | 33 | ||
34 | static void cfrfml_release(struct kref *kref) | 34 | static void cfrfml_release(struct cflayer *layer) |
35 | { | 35 | { |
36 | struct cfsrvl *srvl = container_of(kref, struct cfsrvl, ref); | 36 | struct cfsrvl *srvl = container_of(layer, struct cfsrvl, layer); |
37 | struct cfrfml *rfml = container_obj(&srvl->layer); | 37 | struct cfrfml *rfml = container_obj(&srvl->layer); |
38 | 38 | ||
39 | if (rfml->incomplete_frm) | 39 | if (rfml->incomplete_frm) |
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index 24ba392f203b..535a1e72b366 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/module.h> | ||
13 | #include <net/caif/caif_layer.h> | 14 | #include <net/caif/caif_layer.h> |
14 | #include <net/caif/cfsrvl.h> | 15 | #include <net/caif/cfsrvl.h> |
15 | #include <net/caif/cfpkt.h> | 16 | #include <net/caif/cfpkt.h> |
@@ -27,8 +28,8 @@ static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
27 | { | 28 | { |
28 | struct cfsrvl *service = container_obj(layr); | 29 | struct cfsrvl *service = container_obj(layr); |
29 | 30 | ||
30 | caif_assert(layr->up != NULL); | 31 | if (layr->up == NULL || layr->up->ctrlcmd == NULL) |
31 | caif_assert(layr->up->ctrlcmd != NULL); | 32 | return; |
32 | 33 | ||
33 | switch (ctrl) { | 34 | switch (ctrl) { |
34 | case CAIF_CTRLCMD_INIT_RSP: | 35 | case CAIF_CTRLCMD_INIT_RSP: |
@@ -151,9 +152,9 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) | |||
151 | return -EINVAL; | 152 | return -EINVAL; |
152 | } | 153 | } |
153 | 154 | ||
154 | static void cfsrvl_release(struct kref *kref) | 155 | static void cfsrvl_release(struct cflayer *layer) |
155 | { | 156 | { |
156 | struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); | 157 | struct cfsrvl *service = container_of(layer, struct cfsrvl, layer); |
157 | kfree(service); | 158 | kfree(service); |
158 | } | 159 | } |
159 | 160 | ||
@@ -173,10 +174,8 @@ void cfsrvl_init(struct cfsrvl *service, | |||
173 | service->dev_info = *dev_info; | 174 | service->dev_info = *dev_info; |
174 | service->supports_flowctrl = supports_flowctrl; | 175 | service->supports_flowctrl = supports_flowctrl; |
175 | service->release = cfsrvl_release; | 176 | service->release = cfsrvl_release; |
176 | kref_init(&service->ref); | ||
177 | } | 177 | } |
178 | 178 | ||
179 | |||
180 | bool cfsrvl_ready(struct cfsrvl *service, int *err) | 179 | bool cfsrvl_ready(struct cfsrvl *service, int *err) |
181 | { | 180 | { |
182 | if (service->open && service->modem_flow_on && service->phy_flow_on) | 181 | if (service->open && service->modem_flow_on && service->phy_flow_on) |
@@ -189,6 +188,7 @@ bool cfsrvl_ready(struct cfsrvl *service, int *err) | |||
189 | *err = -EAGAIN; | 188 | *err = -EAGAIN; |
190 | return false; | 189 | return false; |
191 | } | 190 | } |
191 | |||
192 | u8 cfsrvl_getphyid(struct cflayer *layer) | 192 | u8 cfsrvl_getphyid(struct cflayer *layer) |
193 | { | 193 | { |
194 | struct cfsrvl *servl = container_obj(layer); | 194 | struct cfsrvl *servl = container_obj(layer); |
@@ -200,3 +200,26 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid) | |||
200 | struct cfsrvl *servl = container_obj(layer); | 200 | struct cfsrvl *servl = container_obj(layer); |
201 | return servl->dev_info.id == phyid; | 201 | return servl->dev_info.id == phyid; |
202 | } | 202 | } |
203 | |||
204 | void caif_free_client(struct cflayer *adap_layer) | ||
205 | { | ||
206 | struct cfsrvl *servl; | ||
207 | if (adap_layer == NULL || adap_layer->dn == NULL) | ||
208 | return; | ||
209 | servl = container_obj(adap_layer->dn); | ||
210 | servl->release(&servl->layer); | ||
211 | } | ||
212 | EXPORT_SYMBOL(caif_free_client); | ||
213 | |||
214 | void caif_client_register_refcnt(struct cflayer *adapt_layer, | ||
215 | void (*hold)(struct cflayer *lyr), | ||
216 | void (*put)(struct cflayer *lyr)) | ||
217 | { | ||
218 | struct cfsrvl *service; | ||
219 | service = container_of(adapt_layer->dn, struct cfsrvl, layer); | ||
220 | |||
221 | WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL); | ||
222 | service->hold = hold; | ||
223 | service->put = put; | ||
224 | } | ||
225 | EXPORT_SYMBOL(caif_client_register_refcnt); | ||