caif: Use RCU instead of spin-lock in caif_dev.c
[pandora-kernel.git] / net / caif / caif_dev.c
1 /*
2  * CAIF Interface registration.
3  * Copyright (C) ST-Ericsson AB 2010
4  * Author:      Sjur Brendeland/sjur.brandeland@stericsson.com
5  * License terms: GNU General Public License (GPL) version 2
6  *
7  * Borrowed heavily from file: pn_dev.c. Thanks to
8  *  Remi Denis-Courmont <remi.denis-courmont@nokia.com>
9  *  and Sakari Ailus <sakari.ailus@nokia.com>
10  */
11
12 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
13
14 #include <linux/version.h>
15 #include <linux/kernel.h>
16 #include <linux/if_arp.h>
17 #include <linux/net.h>
18 #include <linux/netdevice.h>
19 #include <linux/mutex.h>
20 #include <net/netns/generic.h>
21 #include <net/net_namespace.h>
22 #include <net/pkt_sched.h>
23 #include <net/caif/caif_device.h>
24 #include <net/caif/caif_dev.h>
25 #include <net/caif/caif_layer.h>
26 #include <net/caif/cfpkt.h>
27 #include <net/caif/cfcnfg.h>
28
29 MODULE_LICENSE("GPL");
30
31 /* Used for local tracking of the CAIF net devices */
32 struct caif_device_entry {
33         struct cflayer layer;
34         struct list_head list;
35         struct net_device *netdev;
36         int __percpu *pcpu_refcnt;
37 };
38
39 struct caif_device_entry_list {
40         struct list_head list;
41         /* Protects simulanous deletes in list */
42         struct mutex lock;
43 };
44
45 struct caif_net {
46         struct caif_device_entry_list caifdevs;
47 };
48
49 static int caif_net_id;
50 static struct cfcnfg *cfg;
51
52 static struct caif_device_entry_list *caif_device_list(struct net *net)
53 {
54         struct caif_net *caifn;
55         BUG_ON(!net);
56         caifn = net_generic(net, caif_net_id);
57         BUG_ON(!caifn);
58         return &caifn->caifdevs;
59 }
60
61 static void caifd_put(struct caif_device_entry *e)
62 {
63         irqsafe_cpu_dec(*e->pcpu_refcnt);
64 }
65
66 static void caifd_hold(struct caif_device_entry *e)
67 {
68         irqsafe_cpu_inc(*e->pcpu_refcnt);
69 }
70
71 static int caifd_refcnt_read(struct caif_device_entry *e)
72 {
73         int i, refcnt = 0;
74         for_each_possible_cpu(i)
75                 refcnt += *per_cpu_ptr(e->pcpu_refcnt, i);
76         return refcnt;
77 }
78
79 /* Allocate new CAIF device. */
80 static struct caif_device_entry *caif_device_alloc(struct net_device *dev)
81 {
82         struct caif_device_entry_list *caifdevs;
83         struct caif_device_entry *caifd;
84
85         caifdevs = caif_device_list(dev_net(dev));
86         BUG_ON(!caifdevs);
87
88         caifd = kzalloc(sizeof(*caifd), GFP_ATOMIC);
89         if (!caifd)
90                 return NULL;
91         caifd->pcpu_refcnt = alloc_percpu(int);
92         caifd->netdev = dev;
93         dev_hold(dev);
94         return caifd;
95 }
96
97 static struct caif_device_entry *caif_get(struct net_device *dev)
98 {
99         struct caif_device_entry_list *caifdevs =
100             caif_device_list(dev_net(dev));
101         struct caif_device_entry *caifd;
102         BUG_ON(!caifdevs);
103         list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
104                 if (caifd->netdev == dev)
105                         return caifd;
106         }
107         return NULL;
108 }
109
110 static int transmit(struct cflayer *layer, struct cfpkt *pkt)
111 {
112         struct caif_device_entry *caifd =
113             container_of(layer, struct caif_device_entry, layer);
114         struct sk_buff *skb;
115
116         skb = cfpkt_tonative(pkt);
117         skb->dev = caifd->netdev;
118
119         dev_queue_xmit(skb);
120
121         return 0;
122 }
123
124 /*
125  * Stuff received packets into the CAIF stack.
126  * On error, returns non-zero and releases the skb.
127  */
128 static int receive(struct sk_buff *skb, struct net_device *dev,
129                    struct packet_type *pkttype, struct net_device *orig_dev)
130 {
131         struct cfpkt *pkt;
132         struct caif_device_entry *caifd;
133
134         pkt = cfpkt_fromnative(CAIF_DIR_IN, skb);
135
136         rcu_read_lock();
137         caifd = caif_get(dev);
138
139         if (!caifd || !caifd->layer.up || !caifd->layer.up->receive ||
140                         !netif_oper_up(caifd->netdev)) {
141                 rcu_read_unlock();
142                 kfree_skb(skb);
143                 return NET_RX_DROP;
144         }
145
146         /* Hold reference to netdevice while using CAIF stack */
147         caifd_hold(caifd);
148         rcu_read_unlock();
149
150         caifd->layer.up->receive(caifd->layer.up, pkt);
151
152         /* Release reference to stack upwards */
153         caifd_put(caifd);
154         return 0;
155 }
156
157 static struct packet_type caif_packet_type __read_mostly = {
158         .type = cpu_to_be16(ETH_P_CAIF),
159         .func = receive,
160 };
161
162 static void dev_flowctrl(struct net_device *dev, int on)
163 {
164         struct caif_device_entry *caifd;
165
166         rcu_read_lock();
167
168         caifd = caif_get(dev);
169         if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) {
170                 rcu_read_unlock();
171                 return;
172         }
173
174         caifd_hold(caifd);
175         rcu_read_unlock();
176
177         caifd->layer.up->ctrlcmd(caifd->layer.up,
178                                  on ?
179                                  _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND :
180                                  _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND,
181                                  caifd->layer.id);
182         caifd_put(caifd);
183 }
184
185 /* notify Caif of device events */
186 static int caif_device_notify(struct notifier_block *me, unsigned long what,
187                               void *arg)
188 {
189         struct net_device *dev = arg;
190         struct caif_device_entry *caifd = NULL;
191         struct caif_dev_common *caifdev;
192         enum cfcnfg_phy_preference pref;
193         enum cfcnfg_phy_type phy_type;
194         struct caif_device_entry_list *caifdevs =
195             caif_device_list(dev_net(dev));
196
197         if (dev->type != ARPHRD_CAIF)
198                 return 0;
199
200         switch (what) {
201         case NETDEV_REGISTER:
202                 caifd = caif_device_alloc(dev);
203                 if (!caifd)
204                         return 0;
205
206                 caifdev = netdev_priv(dev);
207                 caifdev->flowctrl = dev_flowctrl;
208
209                 caifd->layer.transmit = transmit;
210
211                 if (caifdev->use_frag)
212                         phy_type = CFPHYTYPE_FRAG;
213                 else
214                         phy_type = CFPHYTYPE_CAIF;
215
216                 switch (caifdev->link_select) {
217                 case CAIF_LINK_HIGH_BANDW:
218                         pref = CFPHYPREF_HIGH_BW;
219                         break;
220                 case CAIF_LINK_LOW_LATENCY:
221                         pref = CFPHYPREF_LOW_LAT;
222                         break;
223                 default:
224                         pref = CFPHYPREF_HIGH_BW;
225                         break;
226                 }
227                 strncpy(caifd->layer.name, dev->name,
228                         sizeof(caifd->layer.name) - 1);
229                 caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0;
230
231                 mutex_lock(&caifdevs->lock);
232                 list_add_rcu(&caifd->list, &caifdevs->list);
233
234                 cfcnfg_add_phy_layer(cfg,
235                                      phy_type,
236                                      dev,
237                                      &caifd->layer,
238                                      0,
239                                      pref,
240                                      caifdev->use_fcs,
241                                      caifdev->use_stx);
242                 mutex_unlock(&caifdevs->lock);
243                 break;
244
245         case NETDEV_UP:
246                 rcu_read_lock();
247
248                 caifd = caif_get(dev);
249                 if (caifd == NULL) {
250                         rcu_read_unlock();
251                         break;
252                 }
253
254                 cfcnfg_set_phy_state(cfg, &caifd->layer, true);
255                 rcu_read_unlock();
256
257                 break;
258
259         case NETDEV_DOWN:
260                 rcu_read_lock();
261
262                 caifd = caif_get(dev);
263                 if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) {
264                         rcu_read_unlock();
265                         return -EINVAL;
266                 }
267
268                 cfcnfg_set_phy_state(cfg, &caifd->layer, false);
269                 caifd_hold(caifd);
270                 rcu_read_unlock();
271
272                 caifd->layer.up->ctrlcmd(caifd->layer.up,
273                                          _CAIF_CTRLCMD_PHYIF_DOWN_IND,
274                                          caifd->layer.id);
275                 caifd_put(caifd);
276                 break;
277
278         case NETDEV_UNREGISTER:
279                 mutex_lock(&caifdevs->lock);
280
281                 caifd = caif_get(dev);
282                 if (caifd == NULL) {
283                         mutex_unlock(&caifdevs->lock);
284                         break;
285                 }
286                 list_del_rcu(&caifd->list);
287
288                 /*
289                  * NETDEV_UNREGISTER is called repeatedly until all reference
290                  * counts for the net-device are released. If references to
291                  * caifd is taken, simply ignore NETDEV_UNREGISTER and wait for
292                  * the next call to NETDEV_UNREGISTER.
293                  *
294                  * If any packets are in flight down the CAIF Stack,
295                  * cfcnfg_del_phy_layer will return nonzero.
296                  * If no packets are in flight, the CAIF Stack associated
297                  * with the net-device un-registering is freed.
298                  */
299
300                 if (caifd_refcnt_read(caifd) != 0 ||
301                         cfcnfg_del_phy_layer(cfg, &caifd->layer) != 0) {
302
303                         pr_info("Wait for device inuse\n");
304                         /* Enrole device if CAIF Stack is still in use */
305                         list_add_rcu(&caifd->list, &caifdevs->list);
306                         mutex_unlock(&caifdevs->lock);
307                         break;
308                 }
309
310                 synchronize_rcu();
311                 dev_put(caifd->netdev);
312                 free_percpu(caifd->pcpu_refcnt);
313                 kfree(caifd);
314
315                 mutex_unlock(&caifdevs->lock);
316                 break;
317         }
318         return 0;
319 }
320
321 static struct notifier_block caif_device_notifier = {
322         .notifier_call = caif_device_notify,
323         .priority = 0,
324 };
325
326 int caif_connect_client(struct caif_connect_request *conn_req,
327                        struct cflayer *client_layer, int *ifindex,
328                        int *headroom, int *tailroom)
329 {
330         struct cfctrl_link_param param;
331         int ret;
332
333         ret = caif_connect_req_to_link_param(cfg, conn_req, &param);
334         if (ret)
335                 return ret;
336         /* Hook up the adaptation layer. */
337         return cfcnfg_add_adaptation_layer(cfg, &param,
338                                        client_layer, ifindex,
339                                        headroom, tailroom);
340 }
341 EXPORT_SYMBOL(caif_connect_client);
342
343 int caif_disconnect_client(struct cflayer *adap_layer)
344 {
345         return cfcnfg_disconn_adapt_layer(cfg, adap_layer);
346 }
347 EXPORT_SYMBOL(caif_disconnect_client);
348
349 /* Per-namespace Caif devices handling */
350 static int caif_init_net(struct net *net)
351 {
352         struct caif_net *caifn = net_generic(net, caif_net_id);
353         INIT_LIST_HEAD(&caifn->caifdevs.list);
354         mutex_init(&caifn->caifdevs.lock);
355         return 0;
356 }
357
358 static void caif_exit_net(struct net *net)
359 {
360         struct caif_device_entry *caifd, *tmp;
361         struct caif_device_entry_list *caifdevs =
362             caif_device_list(net);
363
364         rtnl_lock();
365         mutex_lock(&caifdevs->lock);
366
367         list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) {
368                 int i = 0;
369                 list_del_rcu(&caifd->list);
370                 cfcnfg_set_phy_state(cfg, &caifd->layer, false);
371
372                 while (i < 10 &&
373                         (caifd_refcnt_read(caifd) != 0 ||
374                         cfcnfg_del_phy_layer(cfg, &caifd->layer) != 0)) {
375
376                         pr_info("Wait for device inuse\n");
377                         msleep(250);
378                         i++;
379                 }
380                 synchronize_rcu();
381                 dev_put(caifd->netdev);
382                 free_percpu(caifd->pcpu_refcnt);
383                 kfree(caifd);
384         }
385
386
387         mutex_unlock(&caifdevs->lock);
388         rtnl_unlock();
389 }
390
391 static struct pernet_operations caif_net_ops = {
392         .init = caif_init_net,
393         .exit = caif_exit_net,
394         .id   = &caif_net_id,
395         .size = sizeof(struct caif_net),
396 };
397
398 /* Initialize Caif devices list */
399 static int __init caif_device_init(void)
400 {
401         int result;
402
403         cfg = cfcnfg_create();
404         if (!cfg) {
405                 pr_warn("can't create cfcnfg\n");
406                 goto err_cfcnfg_create_failed;
407         }
408         result = register_pernet_device(&caif_net_ops);
409
410         if (result) {
411                 kfree(cfg);
412                 cfg = NULL;
413                 return result;
414         }
415         dev_add_pack(&caif_packet_type);
416         register_netdevice_notifier(&caif_device_notifier);
417
418         return result;
419 err_cfcnfg_create_failed:
420         return -ENODEV;
421 }
422
423 static void __exit caif_device_exit(void)
424 {
425         dev_remove_pack(&caif_packet_type);
426         unregister_pernet_device(&caif_net_ops);
427         unregister_netdevice_notifier(&caif_device_notifier);
428         cfcnfg_remove(cfg);
429 }
430
431 module_init(caif_device_init);
432 module_exit(caif_device_exit);