1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2021 Intel Corporation
6 #include <linux/nl80211-vnd-intel.h>
7 #include <net/netlink.h>
9 static const struct nla_policy
10 iwl_mvm_vendor_attr_policy
[NUM_IWL_MVM_VENDOR_ATTR
] = {
11 [IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN
] = { .type
= NLA_U8
},
12 [IWL_MVM_VENDOR_ATTR_AUTH_MODE
] = { .type
= NLA_U32
},
13 [IWL_MVM_VENDOR_ATTR_CHANNEL_NUM
] = { .type
= NLA_U8
},
14 [IWL_MVM_VENDOR_ATTR_SSID
] = { .type
= NLA_BINARY
,
15 .len
= IEEE80211_MAX_SSID_LEN
},
16 [IWL_MVM_VENDOR_ATTR_BAND
] = { .type
= NLA_U8
},
17 [IWL_MVM_VENDOR_ATTR_COLLOC_CHANNEL
] = { .type
= NLA_U8
},
18 [IWL_MVM_VENDOR_ATTR_COLLOC_ADDR
] = { .type
= NLA_BINARY
, .len
= ETH_ALEN
},
21 static int iwl_mvm_vendor_get_csme_conn_info(struct wiphy
*wiphy
,
22 struct wireless_dev
*wdev
,
23 const void *data
, int data_len
)
25 struct ieee80211_hw
*hw
= wiphy_to_ieee80211_hw(wiphy
);
26 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
27 struct iwl_mvm_csme_conn_info
*csme_conn_info
;
31 mutex_lock(&mvm
->mutex
);
32 csme_conn_info
= iwl_mvm_get_csme_conn_info(mvm
);
34 if (!csme_conn_info
) {
39 skb
= cfg80211_vendor_cmd_alloc_reply_skb(wiphy
, 200);
45 if (nla_put_u32(skb
, IWL_MVM_VENDOR_ATTR_AUTH_MODE
,
46 csme_conn_info
->conn_info
.auth_mode
) ||
47 nla_put(skb
, IWL_MVM_VENDOR_ATTR_SSID
,
48 csme_conn_info
->conn_info
.ssid_len
,
49 csme_conn_info
->conn_info
.ssid
) ||
50 nla_put_u32(skb
, IWL_MVM_VENDOR_ATTR_STA_CIPHER
,
51 csme_conn_info
->conn_info
.pairwise_cipher
) ||
52 nla_put_u8(skb
, IWL_MVM_VENDOR_ATTR_CHANNEL_NUM
,
53 csme_conn_info
->conn_info
.channel
) ||
54 nla_put(skb
, IWL_MVM_VENDOR_ATTR_ADDR
, ETH_ALEN
,
55 csme_conn_info
->conn_info
.bssid
)) {
61 mutex_unlock(&mvm
->mutex
);
65 return cfg80211_vendor_cmd_reply(skb
);
68 static int iwl_mvm_vendor_host_get_ownership(struct wiphy
*wiphy
,
69 struct wireless_dev
*wdev
,
70 const void *data
, int data_len
)
72 struct ieee80211_hw
*hw
= wiphy_to_ieee80211_hw(wiphy
);
73 struct iwl_mvm
*mvm
= IWL_MAC80211_GET_MVM(hw
);
76 mutex_lock(&mvm
->mutex
);
77 ret
= iwl_mvm_mei_get_ownership(mvm
);
78 mutex_unlock(&mvm
->mutex
);
83 static const struct wiphy_vendor_command iwl_mvm_vendor_commands
[] = {
86 .vendor_id
= INTEL_OUI
,
87 .subcmd
= IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO
,
89 .doit
= iwl_mvm_vendor_get_csme_conn_info
,
90 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
,
91 .policy
= iwl_mvm_vendor_attr_policy
,
92 .maxattr
= MAX_IWL_MVM_VENDOR_ATTR
,
96 .vendor_id
= INTEL_OUI
,
97 .subcmd
= IWL_MVM_VENDOR_CMD_HOST_GET_OWNERSHIP
,
99 .doit
= iwl_mvm_vendor_host_get_ownership
,
100 .flags
= WIPHY_VENDOR_CMD_NEED_WDEV
,
101 .policy
= iwl_mvm_vendor_attr_policy
,
102 .maxattr
= MAX_IWL_MVM_VENDOR_ATTR
,
106 enum iwl_mvm_vendor_events_idx
{
107 /* 0x0 - 0x3 are deprecated */
108 IWL_MVM_VENDOR_EVENT_IDX_ROAMING_FORBIDDEN
= 4,
109 NUM_IWL_MVM_VENDOR_EVENT_IDX
112 static const struct nl80211_vendor_cmd_info
113 iwl_mvm_vendor_events
[NUM_IWL_MVM_VENDOR_EVENT_IDX
] = {
114 [IWL_MVM_VENDOR_EVENT_IDX_ROAMING_FORBIDDEN
] = {
115 .vendor_id
= INTEL_OUI
,
116 .subcmd
= IWL_MVM_VENDOR_CMD_ROAMING_FORBIDDEN_EVENT
,
120 void iwl_mvm_vendor_cmds_register(struct iwl_mvm
*mvm
)
122 mvm
->hw
->wiphy
->vendor_commands
= iwl_mvm_vendor_commands
;
123 mvm
->hw
->wiphy
->n_vendor_commands
= ARRAY_SIZE(iwl_mvm_vendor_commands
);
124 mvm
->hw
->wiphy
->vendor_events
= iwl_mvm_vendor_events
;
125 mvm
->hw
->wiphy
->n_vendor_events
= ARRAY_SIZE(iwl_mvm_vendor_events
);
128 void iwl_mvm_send_roaming_forbidden_event(struct iwl_mvm
*mvm
,
129 struct ieee80211_vif
*vif
,
132 struct sk_buff
*msg
=
133 cfg80211_vendor_event_alloc(mvm
->hw
->wiphy
,
134 ieee80211_vif_to_wdev(vif
),
135 200, IWL_MVM_VENDOR_EVENT_IDX_ROAMING_FORBIDDEN
,
143 if (nla_put(msg
, IWL_MVM_VENDOR_ATTR_VIF_ADDR
,
144 ETH_ALEN
, vif
->addr
) ||
145 nla_put_u8(msg
, IWL_MVM_VENDOR_ATTR_ROAMING_FORBIDDEN
, forbidden
))
146 goto nla_put_failure
;
148 cfg80211_vendor_event(msg
, GFP_ATOMIC
);