aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154
diff options
context:
space:
mode:
authorAlexander Aring <alex.aring@gmail.com>2014-11-09 02:36:50 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-11-09 13:50:28 -0500
commitfcf39e6e88e9492f6688ec8ba4e1be622b904232 (patch)
treeae87d1f093f7b8baa69cc438af36d14ba1866abe /net/ieee802154
parent190ac1ca33442dc25a172ece0f34746a7e1514f3 (diff)
ieee802154: add wpan_dev_list
This patch adds a wpan_dev_list list into cfg802154_registered_device struct. Also adding new wpan_dev into this list while cfg802154_netdev_notifier_call. This behaviour is mostly grab from wireless core.c implementation and is needed for preparing nl802154 framework. Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/ieee802154')
-rw-r--r--net/ieee802154/core.c95
-rw-r--r--net/ieee802154/core.h11
2 files changed, 103 insertions, 3 deletions
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index 11a1d2ed5b26..3ee00bf0e514 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -102,12 +102,15 @@ wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size)
102 102
103 mutex_init(&rdev->wpan_phy.pib_lock); 103 mutex_init(&rdev->wpan_phy.pib_lock);
104 104
105 INIT_LIST_HEAD(&rdev->wpan_dev_list);
105 device_initialize(&rdev->wpan_phy.dev); 106 device_initialize(&rdev->wpan_phy.dev);
106 dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy_idx); 107 dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy_idx);
107 108
108 rdev->wpan_phy.dev.class = &wpan_phy_class; 109 rdev->wpan_phy.dev.class = &wpan_phy_class;
109 rdev->wpan_phy.dev.platform_data = rdev; 110 rdev->wpan_phy.dev.platform_data = rdev;
110 111
112 init_waitqueue_head(&rdev->dev_wait);
113
111 return &rdev->wpan_phy; 114 return &rdev->wpan_phy;
112} 115}
113EXPORT_SYMBOL(wpan_phy_new); 116EXPORT_SYMBOL(wpan_phy_new);
@@ -140,13 +143,18 @@ void wpan_phy_unregister(struct wpan_phy *phy)
140{ 143{
141 struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(phy); 144 struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(phy);
142 145
143 /* TODO open count */ 146 wait_event(rdev->dev_wait, ({
147 int __count;
148 rtnl_lock();
149 __count = rdev->opencount;
150 rtnl_unlock();
151 __count == 0; }));
144 152
145 rtnl_lock(); 153 rtnl_lock();
146 /* TODO nl802154 phy notify */ 154 /* TODO nl802154 phy notify */
147 /* TODO phy registered lock */ 155 /* TODO phy registered lock */
148 156
149 /* TODO WARN_ON wpan_dev_list */ 157 WARN_ON(!list_empty(&rdev->wpan_dev_list));
150 158
151 /* First remove the hardware from everywhere, this makes 159 /* First remove the hardware from everywhere, this makes
152 * it impossible to find from userspace. 160 * it impossible to find from userspace.
@@ -173,6 +181,79 @@ void cfg802154_dev_free(struct cfg802154_registered_device *rdev)
173 kfree(rdev); 181 kfree(rdev);
174} 182}
175 183
184static void
185cfg802154_update_iface_num(struct cfg802154_registered_device *rdev,
186 int iftype, int num)
187{
188 ASSERT_RTNL();
189
190 rdev->num_running_ifaces += num;
191}
192
193static int cfg802154_netdev_notifier_call(struct notifier_block *nb,
194 unsigned long state, void *ptr)
195{
196 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
197 struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
198 struct cfg802154_registered_device *rdev;
199
200 if (!wpan_dev)
201 return NOTIFY_DONE;
202
203 rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
204
205 /* TODO WARN_ON unspec type */
206
207 switch (state) {
208 /* TODO NETDEV_DEVTYPE */
209 case NETDEV_REGISTER:
210 wpan_dev->identifier = ++rdev->wpan_dev_id;
211 list_add_rcu(&wpan_dev->list, &rdev->wpan_dev_list);
212 rdev->devlist_generation++;
213
214 wpan_dev->netdev = dev;
215 break;
216 case NETDEV_DOWN:
217 cfg802154_update_iface_num(rdev, wpan_dev->iftype, -1);
218
219 rdev->opencount--;
220 wake_up(&rdev->dev_wait);
221 break;
222 case NETDEV_UP:
223 cfg802154_update_iface_num(rdev, wpan_dev->iftype, 1);
224
225 rdev->opencount++;
226 break;
227 case NETDEV_UNREGISTER:
228 /* It is possible to get NETDEV_UNREGISTER
229 * multiple times. To detect that, check
230 * that the interface is still on the list
231 * of registered interfaces, and only then
232 * remove and clean it up.
233 */
234 if (!list_empty(&wpan_dev->list)) {
235 list_del_rcu(&wpan_dev->list);
236 rdev->devlist_generation++;
237 }
238 /* synchronize (so that we won't find this netdev
239 * from other code any more) and then clear the list
240 * head so that the above code can safely check for
241 * !list_empty() to avoid double-cleanup.
242 */
243 synchronize_rcu();
244 INIT_LIST_HEAD(&wpan_dev->list);
245 break;
246 default:
247 return NOTIFY_DONE;
248 }
249
250 return NOTIFY_OK;
251}
252
253static struct notifier_block cfg802154_netdev_notifier = {
254 .notifier_call = cfg802154_netdev_notifier_call,
255};
256
176static int __init wpan_phy_class_init(void) 257static int __init wpan_phy_class_init(void)
177{ 258{
178 int rc; 259 int rc;
@@ -181,11 +262,18 @@ static int __init wpan_phy_class_init(void)
181 if (rc) 262 if (rc)
182 goto err; 263 goto err;
183 264
184 rc = ieee802154_nl_init(); 265 rc = register_netdevice_notifier(&cfg802154_netdev_notifier);
185 if (rc) 266 if (rc)
186 goto err_nl; 267 goto err_nl;
187 268
269 rc = ieee802154_nl_init();
270 if (rc)
271 goto err_notifier;
272
188 return 0; 273 return 0;
274
275err_notifier:
276 unregister_netdevice_notifier(&cfg802154_netdev_notifier);
189err_nl: 277err_nl:
190 wpan_phy_sysfs_exit(); 278 wpan_phy_sysfs_exit();
191err: 279err:
@@ -196,6 +284,7 @@ subsys_initcall(wpan_phy_class_init);
196static void __exit wpan_phy_class_exit(void) 284static void __exit wpan_phy_class_exit(void)
197{ 285{
198 ieee802154_nl_exit(); 286 ieee802154_nl_exit();
287 unregister_netdevice_notifier(&cfg802154_netdev_notifier);
199 wpan_phy_sysfs_exit(); 288 wpan_phy_sysfs_exit();
200} 289}
201module_exit(wpan_phy_class_exit); 290module_exit(wpan_phy_class_exit);
diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h
index 38887cb2eaf4..e708d9d5878b 100644
--- a/net/ieee802154/core.h
+++ b/net/ieee802154/core.h
@@ -10,6 +10,17 @@ struct cfg802154_registered_device {
10 /* wpan_phy index, internal only */ 10 /* wpan_phy index, internal only */
11 int wpan_phy_idx; 11 int wpan_phy_idx;
12 12
13 /* also protected by devlist_mtx */
14 int opencount;
15 wait_queue_head_t dev_wait;
16
17 /* protected by RTNL only */
18 int num_running_ifaces;
19
20 /* associated wpan interfaces, protected by rtnl or RCU */
21 struct list_head wpan_dev_list;
22 int devlist_generation, wpan_dev_id;
23
13 /* must be last because of the way we do wpan_phy_priv(), 24 /* must be last because of the way we do wpan_phy_priv(),
14 * and it should at least be aligned to NETDEV_ALIGN 25 * and it should at least be aligned to NETDEV_ALIGN
15 */ 26 */