Skip to content

Commit 2ffecf1

Browse files
committed
Merge tag 'ieee802154-for-net-next-2023-06-23' of gitolite.kernel.org:pub/scm/linux/kernel/git/wpan/wpan-next
Miquel Raynal says: ==================== Core WPAN changes: - Support for active scans - Support for answering BEACON_REQ - Specific MLME handling for limited devices WPAN driver changes: - ca8210: - Flag the devices as limited - Remove stray gpiod_unexport() call * tag 'ieee802154-for-net-next-2023-06-23' of gitolite.kernel.org:pub/scm/linux/kernel/git/wpan/wpan-next: ieee802154: ca8210: Remove stray gpiod_unexport() call ieee802154: ca8210: Flag the driver as being limited net: ieee802154: Handle limited devices with only datagram support mac802154: Handle received BEACON_REQ ieee802154: Add support for allowing to answer BEACON_REQ mac802154: Handle active scanning ieee802154: Add support for user active scan requests ==================== Link: https://lore.kernel.org/r/20230623195506.40b87b5f@xps-13 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 14fd5e0 + 18b849f commit 2ffecf1

9 files changed

Lines changed: 226 additions & 11 deletions

File tree

drivers/net/ieee802154/ca8210.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2855,7 +2855,6 @@ static int ca8210_interrupt_init(struct spi_device *spi)
28552855
);
28562856
if (ret) {
28572857
dev_crit(&spi->dev, "request_irq %d failed\n", pdata->irq_id);
2858-
gpiod_unexport(gpio_to_desc(pdata->gpio_irq));
28592858
gpio_free(pdata->gpio_irq);
28602859
}
28612860

@@ -2945,7 +2944,8 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
29452944
ca8210_hw->phy->flags =
29462945
WPAN_PHY_FLAG_TXPOWER |
29472946
WPAN_PHY_FLAG_CCA_ED_LEVEL |
2948-
WPAN_PHY_FLAG_CCA_MODE;
2947+
WPAN_PHY_FLAG_CCA_MODE |
2948+
WPAN_PHY_FLAG_DATAGRAMS_ONLY;
29492949
}
29502950

29512951
/**

include/net/cfg802154.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,15 @@ wpan_phy_cca_cmp(const struct wpan_phy_cca *a, const struct wpan_phy_cca *b)
178178
* setting.
179179
* @WPAN_PHY_FLAG_STATE_QUEUE_STOPPED: Indicates that the transmit queue was
180180
* temporarily stopped.
181+
* @WPAN_PHY_FLAG_DATAGRAMS_ONLY: Indicates that transceiver is only able to
182+
* send/receive datagrams.
181183
*/
182184
enum wpan_phy_flags {
183185
WPAN_PHY_FLAG_TXPOWER = BIT(1),
184186
WPAN_PHY_FLAG_CCA_ED_LEVEL = BIT(2),
185187
WPAN_PHY_FLAG_CCA_MODE = BIT(3),
186188
WPAN_PHY_FLAG_STATE_QUEUE_STOPPED = BIT(4),
189+
WPAN_PHY_FLAG_DATAGRAMS_ONLY = BIT(5),
187190
};
188191

189192
struct wpan_phy {

include/net/ieee802154_netdev.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ struct ieee802154_beacon_hdr {
7474
#endif
7575
} __packed;
7676

77+
struct ieee802154_mac_cmd_pl {
78+
u8 cmd_id;
79+
} __packed;
80+
7781
struct ieee802154_sechdr {
7882
#if defined(__LITTLE_ENDIAN_BITFIELD)
7983
u8 level:3,
@@ -149,6 +153,16 @@ struct ieee802154_beacon_frame {
149153
struct ieee802154_beacon_hdr mac_pl;
150154
};
151155

156+
struct ieee802154_mac_cmd_frame {
157+
struct ieee802154_hdr mhr;
158+
struct ieee802154_mac_cmd_pl mac_pl;
159+
};
160+
161+
struct ieee802154_beacon_req_frame {
162+
struct ieee802154_hdr mhr;
163+
struct ieee802154_mac_cmd_pl mac_pl;
164+
};
165+
152166
/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
153167
* the contents of hdr will be, and the actual value of those bits in
154168
* hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
@@ -174,9 +188,13 @@ int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
174188
*/
175189
int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
176190

177-
/* pushes a beacon frame into an skb */
191+
/* pushes/pulls various frame types into/from an skb */
178192
int ieee802154_beacon_push(struct sk_buff *skb,
179193
struct ieee802154_beacon_frame *beacon);
194+
int ieee802154_mac_cmd_push(struct sk_buff *skb, void *frame,
195+
const void *pl, unsigned int pl_len);
196+
int ieee802154_mac_cmd_pl_pull(struct sk_buff *skb,
197+
struct ieee802154_mac_cmd_pl *mac_pl);
180198

181199
int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
182200

net/ieee802154/header_ops.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,29 @@ ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr)
120120
}
121121
EXPORT_SYMBOL_GPL(ieee802154_hdr_push);
122122

123+
int ieee802154_mac_cmd_push(struct sk_buff *skb, void *f,
124+
const void *pl, unsigned int pl_len)
125+
{
126+
struct ieee802154_mac_cmd_frame *frame = f;
127+
struct ieee802154_mac_cmd_pl *mac_pl = &frame->mac_pl;
128+
struct ieee802154_hdr *mhr = &frame->mhr;
129+
int ret;
130+
131+
skb_reserve(skb, sizeof(*mhr));
132+
ret = ieee802154_hdr_push(skb, mhr);
133+
if (ret < 0)
134+
return ret;
135+
136+
skb_reset_mac_header(skb);
137+
skb->mac_len = ret;
138+
139+
skb_put_data(skb, mac_pl, sizeof(*mac_pl));
140+
skb_put_data(skb, pl, pl_len);
141+
142+
return 0;
143+
}
144+
EXPORT_SYMBOL_GPL(ieee802154_mac_cmd_push);
145+
123146
int ieee802154_beacon_push(struct sk_buff *skb,
124147
struct ieee802154_beacon_frame *beacon)
125148
{
@@ -284,6 +307,19 @@ ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr)
284307
}
285308
EXPORT_SYMBOL_GPL(ieee802154_hdr_pull);
286309

310+
int ieee802154_mac_cmd_pl_pull(struct sk_buff *skb,
311+
struct ieee802154_mac_cmd_pl *mac_pl)
312+
{
313+
if (!pskb_may_pull(skb, sizeof(*mac_pl)))
314+
return -EINVAL;
315+
316+
memcpy(mac_pl, skb->data, sizeof(*mac_pl));
317+
skb_pull(skb, sizeof(*mac_pl));
318+
319+
return 0;
320+
}
321+
EXPORT_SYMBOL_GPL(ieee802154_mac_cmd_pl_pull);
322+
287323
int
288324
ieee802154_hdr_peek_addrs(const struct sk_buff *skb, struct ieee802154_hdr *hdr)
289325
{

net/ieee802154/nl802154.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
233233
NLA_POLICY_RANGE(NLA_U8, NL802154_SCAN_DONE_REASON_FINISHED,
234234
NL802154_SCAN_DONE_REASON_ABORTED),
235235
[NL802154_ATTR_BEACON_INTERVAL] =
236-
NLA_POLICY_MAX(NLA_U8, IEEE802154_MAX_SCAN_DURATION),
236+
NLA_POLICY_MAX(NLA_U8, IEEE802154_ACTIVE_SCAN_DURATION),
237237

238238
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
239239
[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
@@ -1417,6 +1417,11 @@ static int nl802154_trigger_scan(struct sk_buff *skb, struct genl_info *info)
14171417
return -EINVAL;
14181418
}
14191419

1420+
if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
1421+
NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
1422+
return -EOPNOTSUPP;
1423+
}
1424+
14201425
request = kzalloc(sizeof(*request), GFP_KERNEL);
14211426
if (!request)
14221427
return -ENOMEM;
@@ -1426,6 +1431,7 @@ static int nl802154_trigger_scan(struct sk_buff *skb, struct genl_info *info)
14261431

14271432
type = nla_get_u8(info->attrs[NL802154_ATTR_SCAN_TYPE]);
14281433
switch (type) {
1434+
case NL802154_SCAN_ACTIVE:
14291435
case NL802154_SCAN_PASSIVE:
14301436
request->type = type;
14311437
break;
@@ -1583,6 +1589,11 @@ nl802154_send_beacons(struct sk_buff *skb, struct genl_info *info)
15831589
return -EPERM;
15841590
}
15851591

1592+
if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
1593+
NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
1594+
return -EOPNOTSUPP;
1595+
}
1596+
15861597
request = kzalloc(sizeof(*request), GFP_KERNEL);
15871598
if (!request)
15881599
return -ENOMEM;

net/mac802154/ieee802154_i.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct ieee802154_local {
5858
/* Scanning */
5959
u8 scan_page;
6060
u8 scan_channel;
61+
struct ieee802154_beacon_req_frame scan_beacon_req;
6162
struct cfg802154_scan_request __rcu *scan_req;
6263
struct delayed_work scan_work;
6364

@@ -70,6 +71,8 @@ struct ieee802154_local {
7071
/* Asynchronous tasks */
7172
struct list_head rx_beacon_list;
7273
struct work_struct rx_beacon_work;
74+
struct list_head rx_mac_cmd_list;
75+
struct work_struct rx_mac_cmd_work;
7376

7477
bool started;
7578
bool suspended;
@@ -154,6 +157,22 @@ ieee802154_sdata_running(struct ieee802154_sub_if_data *sdata)
154157
return test_bit(SDATA_STATE_RUNNING, &sdata->state);
155158
}
156159

160+
static inline int ieee802154_get_mac_cmd(struct sk_buff *skb, u8 *mac_cmd)
161+
{
162+
struct ieee802154_mac_cmd_pl mac_pl;
163+
int ret;
164+
165+
if (mac_cb(skb)->type != IEEE802154_FC_TYPE_MAC_CMD)
166+
return -EINVAL;
167+
168+
ret = ieee802154_mac_cmd_pl_pull(skb, &mac_pl);
169+
if (ret)
170+
return ret;
171+
172+
*mac_cmd = mac_pl.cmd_id;
173+
return 0;
174+
}
175+
157176
extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
158177

159178
void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb);
@@ -275,6 +294,8 @@ static inline bool mac802154_is_beaconing(struct ieee802154_local *local)
275294
return test_bit(IEEE802154_IS_BEACONING, &local->ongoing);
276295
}
277296

297+
void mac802154_rx_mac_cmd_worker(struct work_struct *work);
298+
278299
/* interface handling */
279300
int ieee802154_iface_init(void);
280301
void ieee802154_iface_exit(void);

net/mac802154/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
9090

9191
INIT_LIST_HEAD(&local->interfaces);
9292
INIT_LIST_HEAD(&local->rx_beacon_list);
93+
INIT_LIST_HEAD(&local->rx_mac_cmd_list);
9394
mutex_init(&local->iflist_mtx);
9495

9596
tasklet_setup(&local->tasklet, ieee802154_tasklet_handler);
@@ -100,6 +101,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
100101
INIT_DELAYED_WORK(&local->scan_work, mac802154_scan_worker);
101102
INIT_WORK(&local->rx_beacon_work, mac802154_rx_beacon_worker);
102103
INIT_DELAYED_WORK(&local->beacon_work, mac802154_beacon_worker);
104+
INIT_WORK(&local->rx_mac_cmd_work, mac802154_rx_mac_cmd_worker);
103105

104106
/* init supported flags with 802.15.4 default ranges */
105107
phy->supported.max_minbe = 8;

net/mac802154/rx.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,62 @@ void mac802154_rx_beacon_worker(struct work_struct *work)
4747
kfree(mac_pkt);
4848
}
4949

50+
static bool mac802154_should_answer_beacon_req(struct ieee802154_local *local)
51+
{
52+
struct cfg802154_beacon_request *beacon_req;
53+
unsigned int interval;
54+
55+
rcu_read_lock();
56+
beacon_req = rcu_dereference(local->beacon_req);
57+
if (!beacon_req) {
58+
rcu_read_unlock();
59+
return false;
60+
}
61+
62+
interval = beacon_req->interval;
63+
rcu_read_unlock();
64+
65+
if (!mac802154_is_beaconing(local))
66+
return false;
67+
68+
return interval == IEEE802154_ACTIVE_SCAN_DURATION;
69+
}
70+
71+
void mac802154_rx_mac_cmd_worker(struct work_struct *work)
72+
{
73+
struct ieee802154_local *local =
74+
container_of(work, struct ieee802154_local, rx_mac_cmd_work);
75+
struct cfg802154_mac_pkt *mac_pkt;
76+
u8 mac_cmd;
77+
int rc;
78+
79+
mac_pkt = list_first_entry_or_null(&local->rx_mac_cmd_list,
80+
struct cfg802154_mac_pkt, node);
81+
if (!mac_pkt)
82+
return;
83+
84+
rc = ieee802154_get_mac_cmd(mac_pkt->skb, &mac_cmd);
85+
if (rc)
86+
goto out;
87+
88+
switch (mac_cmd) {
89+
case IEEE802154_CMD_BEACON_REQ:
90+
dev_dbg(&mac_pkt->sdata->dev->dev, "processing BEACON REQ\n");
91+
if (!mac802154_should_answer_beacon_req(local))
92+
break;
93+
94+
queue_delayed_work(local->mac_wq, &local->beacon_work, 0);
95+
break;
96+
default:
97+
break;
98+
}
99+
100+
out:
101+
list_del(&mac_pkt->node);
102+
kfree_skb(mac_pkt->skb);
103+
kfree(mac_pkt);
104+
}
105+
50106
static int
51107
ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
52108
struct sk_buff *skb, const struct ieee802154_hdr *hdr)
@@ -140,8 +196,20 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
140196
list_add_tail(&mac_pkt->node, &sdata->local->rx_beacon_list);
141197
queue_work(sdata->local->mac_wq, &sdata->local->rx_beacon_work);
142198
return NET_RX_SUCCESS;
143-
case IEEE802154_FC_TYPE_ACK:
199+
144200
case IEEE802154_FC_TYPE_MAC_CMD:
201+
dev_dbg(&sdata->dev->dev, "MAC COMMAND received\n");
202+
mac_pkt = kzalloc(sizeof(*mac_pkt), GFP_ATOMIC);
203+
if (!mac_pkt)
204+
goto fail;
205+
206+
mac_pkt->skb = skb_get(skb);
207+
mac_pkt->sdata = sdata;
208+
list_add_tail(&mac_pkt->node, &sdata->local->rx_mac_cmd_list);
209+
queue_work(sdata->local->mac_wq, &sdata->local->rx_mac_cmd_work);
210+
return NET_RX_SUCCESS;
211+
212+
case IEEE802154_FC_TYPE_ACK:
145213
goto fail;
146214

147215
case IEEE802154_FC_TYPE_DATA:

0 commit comments

Comments
 (0)