@@ -204,6 +204,16 @@ enum ieee802154_hw_flags {
*
* set_promiscuous_mode
* Enables or disable promiscuous mode.
+ *
+ * enter_scan_mode
+ * Enters the scan mode, may then refuse certain operations.
+ * Can be NULL, if the driver has no internal configuration to do.
+ * Returns either zero, or negative errno.
+ *
+ * exit_scan_mode
+ * Exits the scan mode and returns to a fully functioning state.
+ * Should only be provided if ->enter_scan_mode() is populated.
+ * Returns either zero, or negative errno.
*/
struct ieee802154_ops {
struct module *owner;
@@ -230,6 +240,9 @@ struct ieee802154_ops {
s8 retries);
int (*set_promiscuous_mode)(struct ieee802154_hw *hw,
const bool on);
+ int (*enter_scan_mode)(struct ieee802154_hw *hw,
+ struct cfg802154_scan_request *request);
+ int (*exit_scan_mode)(struct ieee802154_hw *hw);
};
/**
@@ -282,4 +282,37 @@ drv_set_promiscuous_mode(struct ieee802154_local *local, bool on)
return ret;
}
+static inline int drv_enter_scan_mode(struct ieee802154_local *local,
+ struct cfg802154_scan_request *request)
+{
+ int ret;
+
+ might_sleep();
+
+ if (!local->ops->enter_scan_mode || !local->ops->exit_scan_mode)
+ return 0;
+
+ trace_802154_drv_enter_scan_mode(local, request);
+ ret = local->ops->enter_scan_mode(&local->hw, request);
+ trace_802154_drv_return_int(local, ret);
+
+ return ret;
+}
+
+static inline int drv_exit_scan_mode(struct ieee802154_local *local)
+{
+ int ret;
+
+ might_sleep();
+
+ if (!local->ops->exit_scan_mode)
+ return 0;
+
+ trace_802154_drv_exit_scan_mode(local);
+ ret = local->ops->exit_scan_mode(&local->hw);
+ trace_802154_drv_return_int(local, ret);
+
+ return ret;
+}
+
#endif /* __MAC802154_DRIVER_OPS */
@@ -87,6 +87,8 @@ int mac802154_abort_scan_locked(struct ieee802154_local *local)
if (!local->scanning)
return -ESRCH;
+ drv_exit_scan_mode(local);
+
cancel_delayed_work(&local->scan_work);
return mac802154_end_of_scan(local);
@@ -186,6 +188,11 @@ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
else
local->scan_addr = cpu_to_le64(get_unaligned_be64(sdata->dev->dev_addr));
+ /* Inform the hardware about the scanning operation starting */
+ ret = drv_enter_scan_mode(local, request);
+ if (ret)
+ return ret;
+
local->scan_channel_idx = -1;
local->scanning = true;
@@ -264,6 +264,34 @@ TRACE_EVENT(802154_drv_set_promiscuous_mode,
BOOL_TO_STR(__entry->on))
);
+TRACE_EVENT(802154_drv_enter_scan_mode,
+ TP_PROTO(struct ieee802154_local *local,
+ struct cfg802154_scan_request *request),
+ TP_ARGS(local, request),
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u8, page)
+ __field(u32, channels)
+ __field(u8, duration)
+ __field(u64, addr)
+ ),
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->page = request->page;
+ __entry->channels = request->channels;
+ __entry->duration = request->duration;
+ __entry->addr = local->scan_addr;
+ ),
+ TP_printk(LOCAL_PR_FMT ", scan, page: %d, channels: %x, duration %d, addr: 0x%llx",
+ LOCAL_PR_ARG, __entry->page, __entry->channels,
+ __entry->duration, __entry->addr)
+);
+
+DEFINE_EVENT(local_only_evt4, 802154_drv_exit_scan_mode,
+ TP_PROTO(struct ieee802154_local *local),
+ TP_ARGS(local)
+);
+
#endif /* !__MAC802154_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH