Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+226 -11
+2 -2
drivers/net/ieee802154/ca8210.c
··· 2855 2855 ); 2856 2856 if (ret) { 2857 2857 dev_crit(&spi->dev, "request_irq %d failed\n", pdata->irq_id); 2858 - gpiod_unexport(gpio_to_desc(pdata->gpio_irq)); 2859 2858 gpio_free(pdata->gpio_irq); 2860 2859 } 2861 2860 ··· 2944 2945 ca8210_hw->phy->flags = 2945 2946 WPAN_PHY_FLAG_TXPOWER | 2946 2947 WPAN_PHY_FLAG_CCA_ED_LEVEL | 2947 - WPAN_PHY_FLAG_CCA_MODE; 2948 + WPAN_PHY_FLAG_CCA_MODE | 2949 + WPAN_PHY_FLAG_DATAGRAMS_ONLY; 2948 2950 } 2949 2951 2950 2952 /**
+3
include/net/cfg802154.h
··· 178 178 * setting. 179 179 * @WPAN_PHY_FLAG_STATE_QUEUE_STOPPED: Indicates that the transmit queue was 180 180 * temporarily stopped. 181 + * @WPAN_PHY_FLAG_DATAGRAMS_ONLY: Indicates that transceiver is only able to 182 + * send/receive datagrams. 181 183 */ 182 184 enum wpan_phy_flags { 183 185 WPAN_PHY_FLAG_TXPOWER = BIT(1), 184 186 WPAN_PHY_FLAG_CCA_ED_LEVEL = BIT(2), 185 187 WPAN_PHY_FLAG_CCA_MODE = BIT(3), 186 188 WPAN_PHY_FLAG_STATE_QUEUE_STOPPED = BIT(4), 189 + WPAN_PHY_FLAG_DATAGRAMS_ONLY = BIT(5), 187 190 }; 188 191 189 192 struct wpan_phy {
+19 -1
include/net/ieee802154_netdev.h
··· 74 74 #endif 75 75 } __packed; 76 76 77 + struct ieee802154_mac_cmd_pl { 78 + u8 cmd_id; 79 + } __packed; 80 + 77 81 struct ieee802154_sechdr { 78 82 #if defined(__LITTLE_ENDIAN_BITFIELD) 79 83 u8 level:3, ··· 153 149 struct ieee802154_beacon_hdr mac_pl; 154 150 }; 155 151 152 + struct ieee802154_mac_cmd_frame { 153 + struct ieee802154_hdr mhr; 154 + struct ieee802154_mac_cmd_pl mac_pl; 155 + }; 156 + 157 + struct ieee802154_beacon_req_frame { 158 + struct ieee802154_hdr mhr; 159 + struct ieee802154_mac_cmd_pl mac_pl; 160 + }; 161 + 156 162 /* pushes hdr onto the skb. fields of hdr->fc that can be calculated from 157 163 * the contents of hdr will be, and the actual value of those bits in 158 164 * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame ··· 188 174 */ 189 175 int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr); 190 176 191 - /* pushes a beacon frame into an skb */ 177 + /* pushes/pulls various frame types into/from an skb */ 192 178 int ieee802154_beacon_push(struct sk_buff *skb, 193 179 struct ieee802154_beacon_frame *beacon); 180 + int ieee802154_mac_cmd_push(struct sk_buff *skb, void *frame, 181 + const void *pl, unsigned int pl_len); 182 + int ieee802154_mac_cmd_pl_pull(struct sk_buff *skb, 183 + struct ieee802154_mac_cmd_pl *mac_pl); 194 184 195 185 int ieee802154_max_payload(const struct ieee802154_hdr *hdr); 196 186
+36
net/ieee802154/header_ops.c
··· 120 120 } 121 121 EXPORT_SYMBOL_GPL(ieee802154_hdr_push); 122 122 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 + 123 146 int ieee802154_beacon_push(struct sk_buff *skb, 124 147 struct ieee802154_beacon_frame *beacon) 125 148 { ··· 306 283 return pos; 307 284 } 308 285 EXPORT_SYMBOL_GPL(ieee802154_hdr_pull); 286 + 287 + int ieee802154_mac_cmd_pl_pull(struct sk_buff *skb, 288 + struct ieee802154_mac_cmd_pl *mac_pl) 289 + { 290 + if (!pskb_may_pull(skb, sizeof(*mac_pl))) 291 + return -EINVAL; 292 + 293 + memcpy(mac_pl, skb->data, sizeof(*mac_pl)); 294 + skb_pull(skb, sizeof(*mac_pl)); 295 + 296 + return 0; 297 + } 298 + EXPORT_SYMBOL_GPL(ieee802154_mac_cmd_pl_pull); 309 299 310 300 int 311 301 ieee802154_hdr_peek_addrs(const struct sk_buff *skb, struct ieee802154_hdr *hdr)
+12 -1
net/ieee802154/nl802154.c
··· 233 233 NLA_POLICY_RANGE(NLA_U8, NL802154_SCAN_DONE_REASON_FINISHED, 234 234 NL802154_SCAN_DONE_REASON_ABORTED), 235 235 [NL802154_ATTR_BEACON_INTERVAL] = 236 - NLA_POLICY_MAX(NLA_U8, IEEE802154_MAX_SCAN_DURATION), 236 + NLA_POLICY_MAX(NLA_U8, IEEE802154_ACTIVE_SCAN_DURATION), 237 237 238 238 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 239 239 [NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, }, ··· 1417 1417 return -EINVAL; 1418 1418 } 1419 1419 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 + 1420 1425 request = kzalloc(sizeof(*request), GFP_KERNEL); 1421 1426 if (!request) 1422 1427 return -ENOMEM; ··· 1431 1426 1432 1427 type = nla_get_u8(info->attrs[NL802154_ATTR_SCAN_TYPE]); 1433 1428 switch (type) { 1429 + case NL802154_SCAN_ACTIVE: 1434 1430 case NL802154_SCAN_PASSIVE: 1435 1431 request->type = type; 1436 1432 break; ··· 1587 1581 if (wpan_dev->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) { 1588 1582 NL_SET_ERR_MSG(info->extack, "Device is not part of any PAN"); 1589 1583 return -EPERM; 1584 + } 1585 + 1586 + if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) { 1587 + NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams"); 1588 + return -EOPNOTSUPP; 1590 1589 } 1591 1590 1592 1591 request = kzalloc(sizeof(*request), GFP_KERNEL);
+21
net/mac802154/ieee802154_i.h
··· 58 58 /* Scanning */ 59 59 u8 scan_page; 60 60 u8 scan_channel; 61 + struct ieee802154_beacon_req_frame scan_beacon_req; 61 62 struct cfg802154_scan_request __rcu *scan_req; 62 63 struct delayed_work scan_work; 63 64 ··· 71 70 /* Asynchronous tasks */ 72 71 struct list_head rx_beacon_list; 73 72 struct work_struct rx_beacon_work; 73 + struct list_head rx_mac_cmd_list; 74 + struct work_struct rx_mac_cmd_work; 74 75 75 76 bool started; 76 77 bool suspended; ··· 155 152 ieee802154_sdata_running(struct ieee802154_sub_if_data *sdata) 156 153 { 157 154 return test_bit(SDATA_STATE_RUNNING, &sdata->state); 155 + } 156 + 157 + static inline int ieee802154_get_mac_cmd(struct sk_buff *skb, u8 *mac_cmd) 158 + { 159 + struct ieee802154_mac_cmd_pl mac_pl; 160 + int ret; 161 + 162 + if (mac_cb(skb)->type != IEEE802154_FC_TYPE_MAC_CMD) 163 + return -EINVAL; 164 + 165 + ret = ieee802154_mac_cmd_pl_pull(skb, &mac_pl); 166 + if (ret) 167 + return ret; 168 + 169 + *mac_cmd = mac_pl.cmd_id; 170 + return 0; 158 171 } 159 172 160 173 extern struct ieee802154_mlme_ops mac802154_mlme_wpan; ··· 293 274 { 294 275 return test_bit(IEEE802154_IS_BEACONING, &local->ongoing); 295 276 } 277 + 278 + void mac802154_rx_mac_cmd_worker(struct work_struct *work); 296 279 297 280 /* interface handling */ 298 281 int ieee802154_iface_init(void);
+2
net/mac802154/main.c
··· 90 90 91 91 INIT_LIST_HEAD(&local->interfaces); 92 92 INIT_LIST_HEAD(&local->rx_beacon_list); 93 + INIT_LIST_HEAD(&local->rx_mac_cmd_list); 93 94 mutex_init(&local->iflist_mtx); 94 95 95 96 tasklet_setup(&local->tasklet, ieee802154_tasklet_handler); ··· 101 100 INIT_DELAYED_WORK(&local->scan_work, mac802154_scan_worker); 102 101 INIT_WORK(&local->rx_beacon_work, mac802154_rx_beacon_worker); 103 102 INIT_DELAYED_WORK(&local->beacon_work, mac802154_beacon_worker); 103 + INIT_WORK(&local->rx_mac_cmd_work, mac802154_rx_mac_cmd_worker); 104 104 105 105 /* init supported flags with 802.15.4 default ranges */ 106 106 phy->supported.max_minbe = 8;
+69 -1
net/mac802154/rx.c
··· 47 47 kfree(mac_pkt); 48 48 } 49 49 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 + 50 106 static int 51 107 ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata, 52 108 struct sk_buff *skb, const struct ieee802154_hdr *hdr) ··· 196 140 list_add_tail(&mac_pkt->node, &sdata->local->rx_beacon_list); 197 141 queue_work(sdata->local->mac_wq, &sdata->local->rx_beacon_work); 198 142 return NET_RX_SUCCESS; 199 - case IEEE802154_FC_TYPE_ACK: 143 + 200 144 case IEEE802154_FC_TYPE_MAC_CMD: 145 + dev_dbg(&sdata->dev->dev, "MAC COMMAND received\n"); 146 + mac_pkt = kzalloc(sizeof(*mac_pkt), GFP_ATOMIC); 147 + if (!mac_pkt) 148 + goto fail; 149 + 150 + mac_pkt->skb = skb_get(skb); 151 + mac_pkt->sdata = sdata; 152 + list_add_tail(&mac_pkt->node, &sdata->local->rx_mac_cmd_list); 153 + queue_work(sdata->local->mac_wq, &sdata->local->rx_mac_cmd_work); 154 + return NET_RX_SUCCESS; 155 + 156 + case IEEE802154_FC_TYPE_ACK: 201 157 goto fail; 202 158 203 159 case IEEE802154_FC_TYPE_DATA:
+62 -6
net/mac802154/scan.c
··· 18 18 19 19 #define IEEE802154_BEACON_MHR_SZ 13 20 20 #define IEEE802154_BEACON_PL_SZ 4 21 + #define IEEE802154_MAC_CMD_MHR_SZ 23 22 + #define IEEE802154_MAC_CMD_PL_SZ 1 21 23 #define IEEE802154_BEACON_SKB_SZ (IEEE802154_BEACON_MHR_SZ + \ 22 24 IEEE802154_BEACON_PL_SZ) 25 + #define IEEE802154_MAC_CMD_SKB_SZ (IEEE802154_MAC_CMD_MHR_SZ + \ 26 + IEEE802154_MAC_CMD_PL_SZ) 23 27 24 28 /* mac802154_scan_cleanup_locked() must be called upon scan completion or abort. 25 29 * - Completions are asynchronous, not locked by the rtnl and decided by the ··· 135 131 return 0; 136 132 } 137 133 134 + static int mac802154_scan_prepare_beacon_req(struct ieee802154_local *local) 135 + { 136 + memset(&local->scan_beacon_req, 0, sizeof(local->scan_beacon_req)); 137 + local->scan_beacon_req.mhr.fc.type = IEEE802154_FC_TYPE_MAC_CMD; 138 + local->scan_beacon_req.mhr.fc.dest_addr_mode = IEEE802154_SHORT_ADDRESSING; 139 + local->scan_beacon_req.mhr.fc.version = IEEE802154_2003_STD; 140 + local->scan_beacon_req.mhr.fc.source_addr_mode = IEEE802154_NO_ADDRESSING; 141 + local->scan_beacon_req.mhr.dest.mode = IEEE802154_ADDR_SHORT; 142 + local->scan_beacon_req.mhr.dest.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); 143 + local->scan_beacon_req.mhr.dest.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); 144 + local->scan_beacon_req.mac_pl.cmd_id = IEEE802154_CMD_BEACON_REQ; 145 + 146 + return 0; 147 + } 148 + 149 + static int mac802154_transmit_beacon_req(struct ieee802154_local *local, 150 + struct ieee802154_sub_if_data *sdata) 151 + { 152 + struct sk_buff *skb; 153 + int ret; 154 + 155 + skb = alloc_skb(IEEE802154_MAC_CMD_SKB_SZ, GFP_KERNEL); 156 + if (!skb) 157 + return -ENOBUFS; 158 + 159 + skb->dev = sdata->dev; 160 + 161 + ret = ieee802154_mac_cmd_push(skb, &local->scan_beacon_req, NULL, 0); 162 + if (ret) { 163 + kfree_skb(skb); 164 + return ret; 165 + } 166 + 167 + return ieee802154_mlme_tx(local, sdata, skb); 168 + } 169 + 138 170 void mac802154_scan_worker(struct work_struct *work) 139 171 { 140 172 struct ieee802154_local *local = ··· 246 206 goto end_scan; 247 207 } 248 208 209 + if (scan_req->type == NL802154_SCAN_ACTIVE) { 210 + ret = mac802154_transmit_beacon_req(local, sdata); 211 + if (ret) 212 + dev_err(&sdata->dev->dev, 213 + "Error when transmitting beacon request (%d)\n", ret); 214 + } 215 + 249 216 ieee802154_configure_durations(wpan_phy, page, channel); 250 217 scan_duration = mac802154_scan_get_channel_time(scan_req_duration, 251 218 wpan_phy->symbol_duration); ··· 278 231 if (mac802154_is_scanning(local)) 279 232 return -EBUSY; 280 233 281 - /* TODO: support other scanning type */ 282 - if (request->type != NL802154_SCAN_PASSIVE) 234 + if (request->type != NL802154_SCAN_PASSIVE && 235 + request->type != NL802154_SCAN_ACTIVE) 283 236 return -EOPNOTSUPP; 284 237 285 238 /* Store scanning parameters */ ··· 294 247 local->scan_page = request->page; 295 248 local->scan_channel = -1; 296 249 set_bit(IEEE802154_IS_SCANNING, &local->ongoing); 250 + if (request->type == NL802154_SCAN_ACTIVE) 251 + mac802154_scan_prepare_beacon_req(local); 297 252 298 253 nl802154_scan_started(request->wpan_phy, request->wpan_dev); 299 254 ··· 403 354 struct cfg802154_beacon_request *beacon_req; 404 355 struct ieee802154_sub_if_data *sdata; 405 356 struct wpan_dev *wpan_dev; 357 + u8 interval; 406 358 int ret; 407 359 408 360 rcu_read_lock(); ··· 424 374 } 425 375 426 376 wpan_dev = beacon_req->wpan_dev; 377 + interval = beacon_req->interval; 427 378 428 379 rcu_read_unlock(); 429 380 ··· 434 383 dev_err(&sdata->dev->dev, 435 384 "Beacon could not be transmitted (%d)\n", ret); 436 385 437 - queue_delayed_work(local->mac_wq, &local->beacon_work, 438 - local->beacon_interval); 386 + if (interval < IEEE802154_ACTIVE_SCAN_DURATION) 387 + queue_delayed_work(local->mac_wq, &local->beacon_work, 388 + local->beacon_interval); 439 389 } 440 390 441 391 int mac802154_stop_beacons_locked(struct ieee802154_local *local, ··· 491 439 local->beacon.mhr.source.pan_id = request->wpan_dev->pan_id; 492 440 local->beacon.mhr.source.extended_addr = request->wpan_dev->extended_addr; 493 441 local->beacon.mac_pl.beacon_order = request->interval; 494 - local->beacon.mac_pl.superframe_order = request->interval; 442 + if (request->interval <= IEEE802154_MAX_SCAN_DURATION) 443 + local->beacon.mac_pl.superframe_order = request->interval; 495 444 local->beacon.mac_pl.final_cap_slot = 0xf; 496 445 local->beacon.mac_pl.battery_life_ext = 0; 497 - /* TODO: Fill this field depending on the coordinator capacity */ 446 + /* TODO: Fill this field with the coordinator situation in the network */ 498 447 local->beacon.mac_pl.pan_coordinator = 1; 499 448 local->beacon.mac_pl.assoc_permit = 1; 449 + 450 + if (request->interval == IEEE802154_ACTIVE_SCAN_DURATION) 451 + return 0; 500 452 501 453 /* Start the beacon work */ 502 454 local->beacon_interval =