Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: ISC
#
# Copyright (c) 2022 Broadcom Corporation
ccflags-y += \
-I $(src) \
-I $(src)/.. \
-I $(src)/../../include
obj-m += brcmfmac-cyw.o
brcmfmac-cyw-objs += \
core.o module.o
@@ -0,0 +1,378 @@
// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2022 Broadcom Corporation
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <core.h>
#include <bus.h>
#include <fwvid.h>
#include <fwil.h>
#include <fweh.h>
#include "vops.h"
#include "fwil_types.h"
/* event definitions */
#define BRCMF_CYW_E_EXT_AUTH_REQ 187
#define BRCMF_CYW_E_EXT_AUTH_FRAME_RX 188
#define BRCMF_CYW_E_MGMT_FRAME_TXS 189
#define BRCMF_CYW_E_MGMT_FRAME_TXS_OC 190
#define BRCMF_CYW_E_LAST 197
#define MGMT_AUTH_FRAME_DWELL_TIME 4000
#define MGMT_AUTH_FRAME_WAIT_TIME (MGMT_AUTH_FRAME_DWELL_TIME + 100)
static int brcmf_cyw_set_sae_pwd(struct brcmf_if *ifp,
struct cfg80211_crypto_settings *crypto)
{
struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_wsec_sae_pwd_le sae_pwd;
u16 pwd_len = crypto->sae_pwd_len;
int err;
if (pwd_len > BRCMF_WSEC_MAX_SAE_PASSWORD_LEN) {
bphy_err(drvr, "sae_password must be less than %d\n",
BRCMF_WSEC_MAX_SAE_PASSWORD_LEN);
return -EINVAL;
}
sae_pwd.key_len = cpu_to_le16(pwd_len);
memcpy(sae_pwd.key, crypto->sae_pwd, pwd_len);
err = brcmf_fil_iovar_data_set(ifp, "sae_password", &sae_pwd,
sizeof(sae_pwd));
if (err < 0)
bphy_err(drvr, "failed to set SAE password in firmware (len=%u)\n",
pwd_len);
return err;
}
static const struct brcmf_fweh_event_map brcmf_cyw_event_map = {
.items = {
{ BRCMF_E_EXT_AUTH_REQ, BRCMF_CYW_E_EXT_AUTH_REQ },
{ BRCMF_E_EXT_AUTH_FRAME_RX, BRCMF_CYW_E_EXT_AUTH_FRAME_RX },
{ BRCMF_E_MGMT_FRAME_TXSTATUS, BRCMF_CYW_E_MGMT_FRAME_TXS },
{
BRCMF_E_MGMT_FRAME_OFFCHAN_DONE,
BRCMF_CYW_E_MGMT_FRAME_TXS_OC
},
},
.n_items = 4
};
static int brcmf_cyw_alloc_fweh_info(struct brcmf_pub *drvr)
{
struct brcmf_fweh_info *fweh;
fweh = kzalloc_flex(*fweh, evt_handler, BRCMF_CYW_E_LAST);
if (!fweh)
return -ENOMEM;
fweh->num_event_codes = BRCMF_CYW_E_LAST;
fweh->event_map = &brcmf_cyw_event_map;
drvr->fweh = fweh;
return 0;
}
static int brcmf_cyw_activate_events(struct brcmf_if *ifp)
{
struct brcmf_fweh_info *fweh = ifp->drvr->fweh;
struct brcmf_eventmsgs_ext *eventmask_msg;
u32 msglen;
int err;
msglen = sizeof(*eventmask_msg) + fweh->event_mask_len;
eventmask_msg = kzalloc(msglen, GFP_KERNEL);
if (!eventmask_msg)
return -ENOMEM;
eventmask_msg->ver = EVENTMSGS_VER;
eventmask_msg->command = CYW_EVENTMSGS_SET_MASK;
eventmask_msg->len = fweh->event_mask_len;
memcpy(eventmask_msg->mask, fweh->event_mask, fweh->event_mask_len);
err = brcmf_fil_iovar_data_set(ifp, "event_msgs_ext", eventmask_msg,
msglen);
kfree(eventmask_msg);
return err;
}
static
int brcmf_cyw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_mgmt_tx_params *params, u64 *cookie)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct ieee80211_channel *chan = params->chan;
struct brcmf_pub *drvr = cfg->pub;
const u8 *buf = params->buf;
size_t len = params->len;
const struct ieee80211_mgmt *mgmt;
struct brcmf_cfg80211_vif *vif;
s32 err = 0;
bool ack = false;
__le16 hw_ch;
struct brcmf_mf_params_le *mf_params;
u32 mf_params_len;
s32 ready;
brcmf_dbg(TRACE, "Enter\n");
mgmt = (const struct ieee80211_mgmt *)buf;
if (!ieee80211_is_auth(mgmt->frame_control))
return brcmf_cfg80211_mgmt_tx(wiphy, wdev, params, cookie);
*cookie = 0;
vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
reinit_completion(&vif->mgmt_tx);
clear_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status);
clear_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status);
clear_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED,
&vif->mgmt_tx_status);
mf_params_len = offsetof(struct brcmf_mf_params_le, data) +
(len - DOT11_MGMT_HDR_LEN);
mf_params = kzalloc(mf_params_len, GFP_KERNEL);
if (!mf_params)
return -ENOMEM;
mf_params->dwell_time = cpu_to_le32(MGMT_AUTH_FRAME_DWELL_TIME);
mf_params->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN);
mf_params->frame_control = mgmt->frame_control;
if (chan) {
hw_ch = cpu_to_le16(chan->hw_value);
} else {
err = brcmf_fil_cmd_data_get(vif->ifp, BRCMF_C_GET_CHANNEL,
&hw_ch, sizeof(hw_ch));
if (err) {
bphy_err(drvr, "unable to get current hw channel\n");
goto free;
}
}
mf_params->channel = hw_ch;
memcpy(&mf_params->da[0], &mgmt->da[0], ETH_ALEN);
memcpy(&mf_params->bssid[0], &mgmt->bssid[0], ETH_ALEN);
mf_params->packet_id = cpu_to_le32(*cookie);
memcpy(mf_params->data, &buf[DOT11_MGMT_HDR_LEN],
le16_to_cpu(mf_params->len));
brcmf_dbg(TRACE, "Auth frame, cookie=%d, fc=%04x, len=%d, channel=%d\n",
le32_to_cpu(mf_params->packet_id),
le16_to_cpu(mf_params->frame_control),
le16_to_cpu(mf_params->len),
le16_to_cpu(mf_params->channel));
vif->mgmt_tx_id = le32_to_cpu(mf_params->packet_id);
set_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status);
err = brcmf_fil_bsscfg_data_set(vif->ifp, "mgmt_frame",
mf_params, mf_params_len);
if (err) {
bphy_err(drvr, "Failed to send Auth frame: err=%d\n",
err);
goto tx_status;
}
ready = wait_for_completion_timeout(&vif->mgmt_tx,
MGMT_AUTH_FRAME_WAIT_TIME);
if (test_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status)) {
brcmf_dbg(TRACE, "TX Auth frame operation is success\n");
ack = true;
} else {
bphy_err(drvr, "TX Auth frame operation is %s: status=%ld)\n",
ready ? "failed" : "timedout", vif->mgmt_tx_status);
}
tx_status:
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
GFP_KERNEL);
free:
kfree(mf_params);
return err;
}
static int
brcmf_cyw_external_auth(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_external_auth_params *params)
{
struct brcmf_if *ifp;
struct brcmf_pub *drvr;
struct brcmf_auth_req_status_le auth_status;
int ret = 0;
brcmf_dbg(TRACE, "Enter\n");
ifp = netdev_priv(dev);
drvr = ifp->drvr;
if (params->status == WLAN_STATUS_SUCCESS) {
auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_SUCCESS);
} else {
bphy_err(drvr, "External authentication failed: status=%d\n",
params->status);
auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_FAIL);
}
memcpy(auth_status.peer_mac, params->bssid, ETH_ALEN);
params->ssid.ssid_len = min_t(u8, params->ssid.ssid_len,
IEEE80211_MAX_SSID_LEN);
auth_status.ssid_len = cpu_to_le32(params->ssid.ssid_len);
memcpy(auth_status.ssid, params->ssid.ssid, params->ssid.ssid_len);
ret = brcmf_fil_iovar_data_set(ifp, "auth_status", &auth_status,
sizeof(auth_status));
if (ret < 0)
bphy_err(drvr, "auth_status iovar failed: ret=%d\n", ret);
return ret;
}
static void brcmf_cyw_get_cfg80211_ops(struct brcmf_pub *drvr)
{
drvr->ops->mgmt_tx = brcmf_cyw_mgmt_tx;
drvr->ops->external_auth = brcmf_cyw_external_auth;
}
static s32
brcmf_cyw_notify_ext_auth_req(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
struct brcmf_pub *drvr = ifp->drvr;
struct cfg80211_external_auth_params params;
struct brcmf_auth_req_status_le *auth_req =
(struct brcmf_auth_req_status_le *)data;
s32 err = 0;
brcmf_dbg(INFO, "Enter: event %s (%d) received\n",
brcmf_fweh_event_name(e->event_code), e->event_code);
if (e->datalen < sizeof(*auth_req)) {
bphy_err(drvr, "Event %s (%d) data too small. Ignore\n",
brcmf_fweh_event_name(e->event_code), e->event_code);
return -EINVAL;
}
memset(&params, 0, sizeof(params));
params.action = NL80211_EXTERNAL_AUTH_START;
params.key_mgmt_suite = WLAN_AKM_SUITE_SAE;
params.status = WLAN_STATUS_SUCCESS;
params.ssid.ssid_len = min_t(u32, 32, le32_to_cpu(auth_req->ssid_len));
memcpy(params.ssid.ssid, auth_req->ssid, params.ssid.ssid_len);
memcpy(params.bssid, auth_req->peer_mac, ETH_ALEN);
err = cfg80211_external_auth_request(ifp->ndev, &params, GFP_KERNEL);
if (err)
bphy_err(drvr, "Ext Auth request to supplicant failed (%d)\n",
err);
return err;
}
static s32
brcmf_notify_auth_frame_rx(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
struct brcmf_pub *drvr = ifp->drvr;
struct brcmf_cfg80211_info *cfg = drvr->config;
struct wireless_dev *wdev;
u32 mgmt_frame_len = e->datalen - sizeof(struct brcmf_rx_mgmt_data);
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
u8 *frame = (u8 *)(rxframe + 1);
struct brcmu_chan ch;
struct ieee80211_mgmt *mgmt_frame;
s32 freq;
brcmf_dbg(INFO, "Enter: event %s (%d) received\n",
brcmf_fweh_event_name(e->event_code), e->event_code);
if (e->datalen < sizeof(*rxframe)) {
bphy_err(drvr, "Event %s (%d) data too small. Ignore\n",
brcmf_fweh_event_name(e->event_code), e->event_code);
return -EINVAL;
}
if (mgmt_frame_len < offsetof(struct ieee80211_mgmt, u)) {
bphy_err(drvr, "Event %s (%d) frame too small. Ignore\n",
brcmf_fweh_event_name(e->event_code), e->event_code);
return -EINVAL;
}
wdev = &ifp->vif->wdev;
WARN_ON(!wdev);
ch.chspec = be16_to_cpu(rxframe->chanspec);
cfg->d11inf.decchspec(&ch);
mgmt_frame = kzalloc(mgmt_frame_len, GFP_KERNEL);
if (!mgmt_frame)
return -ENOMEM;
mgmt_frame->frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH);
memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN);
memcpy(mgmt_frame->sa, e->addr, ETH_ALEN);
brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mgmt_frame->bssid,
ETH_ALEN);
frame += offsetof(struct ieee80211_mgmt, u);
memcpy(&mgmt_frame->u, frame,
mgmt_frame_len - offsetof(struct ieee80211_mgmt, u));
freq = ieee80211_channel_to_frequency(ch.control_ch_num,
ch.band == BRCMU_CHAN_BAND_2G ?
NL80211_BAND_2GHZ :
NL80211_BAND_5GHZ);
cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len,
NL80211_RXMGMT_FLAG_EXTERNAL_AUTH);
kfree(mgmt_frame);
return 0;
}
static s32
brcmf_notify_mgmt_tx_status(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
struct brcmf_cfg80211_vif *vif = ifp->vif;
u32 *packet_id = (u32 *)data;
brcmf_dbg(INFO, "Enter: event %s (%d), status=%d\n",
brcmf_fweh_event_name(e->event_code), e->event_code,
e->status);
if (!test_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status) ||
(*packet_id != vif->mgmt_tx_id))
return 0;
if (e->event_code == BRCMF_E_MGMT_FRAME_TXSTATUS) {
if (e->status == BRCMF_E_STATUS_SUCCESS)
set_bit(BRCMF_MGMT_TX_ACK, &vif->mgmt_tx_status);
else
set_bit(BRCMF_MGMT_TX_NOACK, &vif->mgmt_tx_status);
} else {
set_bit(BRCMF_MGMT_TX_OFF_CHAN_COMPLETED, &vif->mgmt_tx_status);
}
complete(&vif->mgmt_tx);
return 0;
}
static void brcmf_cyw_register_event_handlers(struct brcmf_pub *drvr)
{
brcmf_fweh_register(drvr, BRCMF_E_EXT_AUTH_REQ,
brcmf_cyw_notify_ext_auth_req);
brcmf_fweh_register(drvr, BRCMF_E_EXT_AUTH_FRAME_RX,
brcmf_notify_auth_frame_rx);
brcmf_fweh_register(drvr, BRCMF_E_MGMT_FRAME_TXSTATUS,
brcmf_notify_mgmt_tx_status);
brcmf_fweh_register(drvr, BRCMF_E_MGMT_FRAME_OFFCHAN_DONE,
brcmf_notify_mgmt_tx_status);
}
const struct brcmf_fwvid_ops brcmf_cyw_ops = {
.set_sae_password = brcmf_cyw_set_sae_pwd,
.alloc_fweh_info = brcmf_cyw_alloc_fweh_info,
.activate_events = brcmf_cyw_activate_events,
.get_cfg80211_ops = brcmf_cyw_get_cfg80211_ops,
.register_event_handlers = brcmf_cyw_register_event_handlers,
};
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2012 Broadcom Corporation
*/
#ifndef CYW_FWIL_TYPES_H_
#define CYW_FWIL_TYPES_H_
#include <fwil_types.h>
enum brcmf_event_msgs_ext_command {
CYW_EVENTMSGS_NONE = 0,
CYW_EVENTMSGS_SET_BIT = 1,
CYW_EVENTMSGS_RESET_BIT = 2,
CYW_EVENTMSGS_SET_MASK = 3,
};
#define EVENTMSGS_VER 1
#define EVENTMSGS_EXT_STRUCT_SIZE offsetof(struct eventmsgs_ext, mask[0])
/**
* struct brcmf_eventmsgs_ext - structure used with "eventmsgs_ext" iovar.
*
* @ver: version.
* @command: requested operation (see &enum event_msgs_ext_command).
* @len: length of the @mask array.
* @maxgetsize: indicates maximum mask size that may be returned by firmware
* upon iovar GET.
* @mask: array where each bit represents firmware event.
*/
struct brcmf_eventmsgs_ext {
u8 ver;
u8 command;
u8 len;
u8 maxgetsize;
u8 mask[] __counted_by(len);
};
#define BRCMF_EXTAUTH_START 1
#define BRCMF_EXTAUTH_ABORT 2
#define BRCMF_EXTAUTH_FAIL 3
#define BRCMF_EXTAUTH_SUCCESS 4
/**
* struct brcmf_auth_req_status_le - external auth request and status update
*
* @flags: flags for external auth status
* @peer_mac: peer MAC address
* @ssid_len: length of ssid
* @ssid: ssid characters
* @pmkid: PMKSA identifier
*/
struct brcmf_auth_req_status_le {
__le16 flags;
u8 peer_mac[ETH_ALEN];
__le32 ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 pmkid[WLAN_PMKID_LEN];
};
/**
* struct brcmf_mf_params_le - management frame parameters for mgmt_frame iovar
*
* @version: version of the iovar
* @dwell_time: dwell duration in ms
* @len: length of frame data
* @frame_control: frame control
* @channel: channel
* @da: peer MAC address
* @bssid: BSS network identifier
* @packet_id: packet identifier
* @data: frame data
*/
struct brcmf_mf_params_le {
__le32 version;
__le32 dwell_time;
__le16 len;
__le16 frame_control;
__le16 channel;
u8 da[ETH_ALEN];
u8 bssid[ETH_ALEN];
__le32 packet_id;
u8 data[] __counted_by_le(len);
};
#endif /* CYW_FWIL_TYPES_H_ */
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2022 Broadcom Corporation
*/
#include <linux/module.h>
#include <bus.h>
#include <core.h>
#include <fwvid.h>
#include "vops.h"
static int __init brcmf_cyw_init(void)
{
return brcmf_fwvid_register_vendor(BRCMF_FWVENDOR_CYW, THIS_MODULE,
&brcmf_cyw_ops);
}
static void __exit brcmf_cyw_exit(void)
{
brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_CYW, THIS_MODULE);
}
MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Cypress/Infineon chipsets");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_IMPORT_NS("BRCMFMAC");
module_init(brcmf_cyw_init);
module_exit(brcmf_cyw_exit);
@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2022 Broadcom Corporation
*/
#ifndef _BRCMFMAC_CYW_VOPS_H
#define _BRCMFMAC_CYW_VOPS_H
extern const struct brcmf_fwvid_ops brcmf_cyw_ops;
#define CYW_VOPS (&brcmf_cyw_ops)
#endif /* _BRCMFMAC_CYW_VOPS_H */