xref: /openbmc/linux/net/mac802154/cfg.c (revision 179dd8c0)
1 /* This program is free software; you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License version 2
3  * as published by the Free Software Foundation.
4  *
5  * This program is distributed in the hope that it will be useful,
6  * but WITHOUT ANY WARRANTY; without even the implied warranty of
7  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8  * GNU General Public License for more details.
9  *
10  * Authors:
11  * Alexander Aring <aar@pengutronix.de>
12  *
13  * Based on: net/mac80211/cfg.c
14  */
15 
16 #include <net/rtnetlink.h>
17 #include <net/cfg802154.h>
18 
19 #include "ieee802154_i.h"
20 #include "driver-ops.h"
21 #include "cfg.h"
22 
23 static struct net_device *
24 ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy,
25 				const char *name,
26 				unsigned char name_assign_type, int type)
27 {
28 	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
29 	struct net_device *dev;
30 
31 	rtnl_lock();
32 	dev = ieee802154_if_add(local, name, name_assign_type, type,
33 				cpu_to_le64(0x0000000000000000ULL));
34 	rtnl_unlock();
35 
36 	return dev;
37 }
38 
39 static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy,
40 					    struct net_device *dev)
41 {
42 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
43 
44 	ieee802154_if_remove(sdata);
45 }
46 
47 static int
48 ieee802154_add_iface(struct wpan_phy *phy, const char *name,
49 		     unsigned char name_assign_type,
50 		     enum nl802154_iftype type, __le64 extended_addr)
51 {
52 	struct ieee802154_local *local = wpan_phy_priv(phy);
53 	struct net_device *err;
54 
55 	err = ieee802154_if_add(local, name, name_assign_type, type,
56 				extended_addr);
57 	return PTR_ERR_OR_ZERO(err);
58 }
59 
60 static int
61 ieee802154_del_iface(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev)
62 {
63 	ieee802154_if_remove(IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev));
64 
65 	return 0;
66 }
67 
68 static int
69 ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
70 {
71 	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
72 	int ret;
73 
74 	ASSERT_RTNL();
75 
76 	if (wpan_phy->current_page == page &&
77 	    wpan_phy->current_channel == channel)
78 		return 0;
79 
80 	ret = drv_set_channel(local, page, channel);
81 	if (!ret) {
82 		wpan_phy->current_page = page;
83 		wpan_phy->current_channel = channel;
84 	}
85 
86 	return ret;
87 }
88 
89 static int
90 ieee802154_set_cca_mode(struct wpan_phy *wpan_phy,
91 			const struct wpan_phy_cca *cca)
92 {
93 	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
94 	int ret;
95 
96 	ASSERT_RTNL();
97 
98 	if (wpan_phy_cca_cmp(&wpan_phy->cca, cca))
99 		return 0;
100 
101 	ret = drv_set_cca_mode(local, cca);
102 	if (!ret)
103 		wpan_phy->cca = *cca;
104 
105 	return ret;
106 }
107 
108 static int
109 ieee802154_set_cca_ed_level(struct wpan_phy *wpan_phy, s32 ed_level)
110 {
111 	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
112 	int ret;
113 
114 	ASSERT_RTNL();
115 
116 	if (wpan_phy->cca_ed_level == ed_level)
117 		return 0;
118 
119 	ret = drv_set_cca_ed_level(local, ed_level);
120 	if (!ret)
121 		wpan_phy->cca_ed_level = ed_level;
122 
123 	return ret;
124 }
125 
126 static int
127 ieee802154_set_tx_power(struct wpan_phy *wpan_phy, s32 power)
128 {
129 	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
130 	int ret;
131 
132 	ASSERT_RTNL();
133 
134 	if (wpan_phy->transmit_power == power)
135 		return 0;
136 
137 	ret = drv_set_tx_power(local, power);
138 	if (!ret)
139 		wpan_phy->transmit_power = power;
140 
141 	return ret;
142 }
143 
144 static int
145 ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
146 		      __le16 pan_id)
147 {
148 	ASSERT_RTNL();
149 
150 	if (wpan_dev->pan_id == pan_id)
151 		return 0;
152 
153 	wpan_dev->pan_id = pan_id;
154 	return 0;
155 }
156 
157 static int
158 ieee802154_set_backoff_exponent(struct wpan_phy *wpan_phy,
159 				struct wpan_dev *wpan_dev,
160 				u8 min_be, u8 max_be)
161 {
162 	ASSERT_RTNL();
163 
164 	if (wpan_dev->min_be == min_be &&
165 	    wpan_dev->max_be == max_be)
166 		return 0;
167 
168 	wpan_dev->min_be = min_be;
169 	wpan_dev->max_be = max_be;
170 	return 0;
171 }
172 
173 static int
174 ieee802154_set_short_addr(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
175 			  __le16 short_addr)
176 {
177 	ASSERT_RTNL();
178 
179 	if (wpan_dev->short_addr == short_addr)
180 		return 0;
181 
182 	wpan_dev->short_addr = short_addr;
183 	return 0;
184 }
185 
186 static int
187 ieee802154_set_max_csma_backoffs(struct wpan_phy *wpan_phy,
188 				 struct wpan_dev *wpan_dev,
189 				 u8 max_csma_backoffs)
190 {
191 	ASSERT_RTNL();
192 
193 	if (wpan_dev->csma_retries == max_csma_backoffs)
194 		return 0;
195 
196 	wpan_dev->csma_retries = max_csma_backoffs;
197 	return 0;
198 }
199 
200 static int
201 ieee802154_set_max_frame_retries(struct wpan_phy *wpan_phy,
202 				 struct wpan_dev *wpan_dev,
203 				 s8 max_frame_retries)
204 {
205 	ASSERT_RTNL();
206 
207 	if (wpan_dev->frame_retries == max_frame_retries)
208 		return 0;
209 
210 	wpan_dev->frame_retries = max_frame_retries;
211 	return 0;
212 }
213 
214 static int
215 ieee802154_set_lbt_mode(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
216 			bool mode)
217 {
218 	ASSERT_RTNL();
219 
220 	if (wpan_dev->lbt == mode)
221 		return 0;
222 
223 	wpan_dev->lbt = mode;
224 	return 0;
225 }
226 
227 const struct cfg802154_ops mac802154_config_ops = {
228 	.add_virtual_intf_deprecated = ieee802154_add_iface_deprecated,
229 	.del_virtual_intf_deprecated = ieee802154_del_iface_deprecated,
230 	.add_virtual_intf = ieee802154_add_iface,
231 	.del_virtual_intf = ieee802154_del_iface,
232 	.set_channel = ieee802154_set_channel,
233 	.set_cca_mode = ieee802154_set_cca_mode,
234 	.set_cca_ed_level = ieee802154_set_cca_ed_level,
235 	.set_tx_power = ieee802154_set_tx_power,
236 	.set_pan_id = ieee802154_set_pan_id,
237 	.set_short_addr = ieee802154_set_short_addr,
238 	.set_backoff_exponent = ieee802154_set_backoff_exponent,
239 	.set_max_csma_backoffs = ieee802154_set_max_csma_backoffs,
240 	.set_max_frame_retries = ieee802154_set_max_frame_retries,
241 	.set_lbt_mode = ieee802154_set_lbt_mode,
242 };
243