cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

iwl-mei.h (18696B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2021 Intel Corporation
      4 */
      5
      6#ifndef __iwl_mei_h__
      7#define __iwl_mei_h__
      8
      9#include <linux/if_ether.h>
     10#include <linux/skbuff.h>
     11#include <linux/ieee80211.h>
     12
     13/**
     14 * DOC: Introduction
     15 *
     16 * iwlmei is the kernel module that is in charge of the commnunication between
     17 * the iwlwifi driver and the CSME firmware's WLAN driver. This communication
     18 * uses the SAP protocol defined in another file.
     19 * iwlwifi can request or release ownership on the WiFi device through iwlmei.
     20 * iwlmei may notify iwlwifi about certain events: what filter iwlwifi should
     21 * use to passthrough inbound packets to the CSME firmware for example. iwlmei
     22 * may also use iwlwifi to send traffic. This means that we need communication
     23 * from iwlmei to iwlwifi and the other way around.
     24 */
     25
     26/**
     27 * DOC: Life cycle
     28 *
     29 * iwlmei exports symbols that are needed by iwlwifi so that iwlmei will always
     30 * be loaded when iwlwifi is alive. iwlwifi registers itself to iwlmei and
     31 * provides the pointers to the functions that iwlmei calls whenever needed.
     32 * iwlwifi calls iwlmei through direct and context-free function calls.
     33 * It is assumed that only one device is accessible to the CSME firmware and
     34 * under the scope of iwlmei so that it is valid not to have any context passed
     35 * to iwlmei's functions.
     36 *
     37 * There are cases in which iwlmei can't access the CSME firmware, because the
     38 * CSME firmware is undergoing a reset, or the mei bus decided to unbind the
     39 * device. In those cases, iwlmei will need not to send requests over the mei
     40 * bus. Instead, it needs to cache the requests from iwlwifi and fulfill them
     41 * when the mei bus is available again.
     42 *
     43 * iwlmei can call iwlwifi as long as iwlwifi is registered to iwlmei. When
     44 * iwlwifi goes down (the PCI device is unbound, or the iwlwifi is unloaded)
     45 * iwlwifi needs to unregister from iwlmei.
     46 */
     47
     48/**
     49 * DOC: Memory layout
     50 *
     51 * Since iwlwifi calls iwlmei without any context, iwlmei needs to hold a
     52 * global pointer to its data (which is in the mei client device's private
     53 * data area). If there was no bind on the mei bus, this pointer is NULL and
     54 * iwlmei knows not access to the CSME firmware upon requests from iwlwifi.
     55 *
     56 * iwlmei needs to cache requests from iwlwifi when there is no mei client
     57 * device available (when iwlmei has been removed from the mei bus). In this
     58 * case, all iwlmei's data that resides in the mei client device's private data
     59 * area is unavailable. For this specific case, a separate caching area is
     60 * needed.
     61 */
     62
     63/**
     64 * DOC: Concurrency
     65 *
     66 * iwlwifi can call iwlmei at any time. iwlmei will take care to synchronize
     67 * the calls from iwlwifi with its internal flows. iwlwifi must not call iwlmei
     68 * in flows that cannot sleep. Moreover, iwlwifi must not call iwlmei in flows
     69 * that originated from iwlmei.
     70 */
     71
     72/**
     73 * DOC: Probe and remove from mei bus driver
     74 *
     75 * When the mei bus driver enumerates its devices, it calls the iwlmei's probe
     76 * function which will send the %SAP_ME_MSG_START message. The probe completes
     77 * before the response (%SAP_ME_MSG_START_OK) is received. This response will
     78 * be handle by the Rx path. Once it arrives, the connection to the CSME
     79 * firmware is considered established and iwlwifi's requests can be treated
     80 * against the CSME firmware.
     81 *
     82 * When the mei bus driver removes the device, iwlmei loses all the data that
     83 * was attached to the mei client device. It clears the global pointer to the
     84 * mei client device since it is not available anymore. This will cause all the
     85 * requests coming from iwlwifi to be cached. This flow takes the global mutex
     86 * to be synchronized with all the requests coming from iwlwifi.
     87 */
     88
     89/**
     90 * DOC: Driver load when CSME owns the device
     91 *
     92 * When the driver (iwlwifi) is loaded while CSME owns the device,
     93 * it'll ask CSME to release the device through HW registers. CSME
     94 * will release the device only in the case that there is no connection
     95 * through the mei bus. If there is a mei bus connection, CSME will refuse
     96 * to release the ownership on the device through the HW registers. In that
     97 * case, iwlwifi must first request ownership using the SAP protocol.
     98 *
     99 * Once iwlwifi will request ownership through the SAP protocol, CSME will
    100 * grant the ownership on the device through the HW registers as well.
    101 * In order to request ownership over SAP, we first need to have an interface
    102 * which means that we need to register to mac80211.
    103 * This can't happen before we get the NVM that contains all the capabilities
    104 * of the device. Reading the NVM usually requires the load the firmware, but
    105 * this is impossible as long as we don't have ownership on the device.
    106 * In order to solve this chicken and egg problem, the host driver can get
    107 * the NVM through CSME which owns the device. It can send
    108 * %SAP_MSG_NOTIF_GET_NVM, which will be replied by %SAP_MSG_NOTIF_NVM with
    109 * the NVM's content that the host driver needs.
    110 */
    111
    112/**
    113 * DOC: CSME behavior regarding the ownership requests
    114 *
    115 * The ownership requests from the host can come in two different ways:
    116 *  - the HW registers in iwl_pcie_set_hw_ready
    117 *  - using the Software Arbitration Protocol (SAP)
    118 *
    119 * The host can ask CSME who owns the device with %SAP_MSG_NOTIF_WHO_OWNS_NIC,
    120 * and it can request ownership with %SAP_MSG_NOTIF_HOST_ASKS_FOR_NIC_OWNERSHIP.
    121 * The host will first use %SAP_MSG_NOTIF_WHO_OWNS_NIC to know what state
    122 * CSME is in. In case CSME thinks it owns the device, the host can ask for
    123 * ownership with %SAP_MSG_NOTIF_HOST_ASKS_FOR_NIC_OWNERSHIP.
    124 *
    125 * Here the table that describes CSME's behavior upon ownership request:
    126 *
    127 * +-------------------+------------+--------------+-----------------------------+------------+
    128 * | State             | HW reg bit | Reply for    | Event                       | HW reg bit |
    129 * |                   | before     | WHO_OWNS_NIC |                             | after      |
    130 * +===================+============+==============+=============================+============+
    131 * | WiAMT not         | 0          | Host         | HW register or              | 0          |
    132 * | operational       | Host owner |              | HOST_ASKS_FOR_NIC_OWNERSHIP | Host owner |
    133 * +-------------------+------------+--------------+-----------------------------+------------+
    134 * | Operational &     | 1          | N/A          | HW register                 | 0          |
    135 * | SAP down &        | CSME owner |              |                             | Host owner |
    136 * | no session active |            |              |                             |            |
    137 * +-------------------+------------+--------------+-----------------------------+------------+
    138 * | Operational &     | 1          | CSME         | HW register                 | 1          |
    139 * | SAP up            | CSME owner |              |                             | CSME owner |
    140 * +-------------------+------------+--------------+-----------------------------+------------+
    141 * | Operational &     | 1          | CSME         | HOST_ASKS_FOR_NIC_OWNERSHIP | 0          |
    142 * | SAP up            | CSME owner |              |                             | Host owner |
    143 * +-------------------+------------+--------------+-----------------------------+------------+
    144 */
    145
    146/**
    147 * DOC: Driver load when CSME is associated and a session is active
    148 *
    149 * A "session" is active when CSME is associated to an access point and the
    150 * link is used to attach a remote driver or to control the system remotely.
    151 * When a session is active, we want to make sure it won't disconnect when we
    152 * take ownership on the device.
    153 * In this case, the driver can get the device, but it'll need to make
    154 * sure that it'll connect to the exact same AP (same BSSID).
    155 * In order to do so, CSME will send the connection parameters through
    156 * SAP and then the host can check if it can connect to this same AP.
    157 * If yes, it can request ownership through SAP and connect quickly without
    158 * scanning all the channels, but just probing the AP on the channel that
    159 * CSME was connected to.
    160 * In order to signal this specific scenario to iwlwifi, iwlmei will
    161 * immediately require iwlwifi to report RF-Kill to the network stack. This
    162 * RF-Kill will prevent the stack from getting the device, and it has a reason
    163 * that tells the userspace that the device is in RF-Kill because it is not
    164 * owned by the host. Once the userspace has configured the right profile,
    165 * it'll be able to let iwlmei know that it can request ownership over SAP
    166 * which will remove the RF-Kill, and finally allow the host to connect.
    167 * The host has then 3 seconds to connect (including DHCP). Had the host
    168 * failed to connect within those 3 seconds, CSME will take the device back.
    169 */
    170
    171/**
    172 * DOC: Datapath
    173 *
    174 * CSME can transmit packets, through the netdev that it gets from the wifi
    175 * driver. It'll send packet in the 802.3 format and simply call
    176 * dev_queue_xmit.
    177 *
    178 * For Rx, iwlmei registers a Rx handler that it attaches to the netdev. iwlmei
    179 * may catch packets and send them to CSME, it can then either drop them so
    180 * that they are invisible to user space, or let them go the user space.
    181 *
    182 * Packets transmitted by the user space do not need to be forwarded to CSME
    183 * with the exception of the DHCP request. In order to know what IP is used
    184 * by the user space, CSME needs to get the DHCP request. See
    185 * iwl_mei_tx_copy_to_csme().
    186 */
    187
    188/**
    189 * enum iwl_mei_nvm_caps - capabilities for MEI NVM
    190 * @MEI_NVM_CAPS_LARI_SUPPORT: Lari is supported
    191 * @MEI_NVM_CAPS_11AX_SUPPORT: 11AX is supported
    192 */
    193enum iwl_mei_nvm_caps {
    194	MEI_NVM_CAPS_LARI_SUPPORT	= BIT(0),
    195	MEI_NVM_CAPS_11AX_SUPPORT	= BIT(1),
    196};
    197
    198/**
    199 * struct iwl_mei_nvm - used to pass the NVM from CSME
    200 * @hw_addr: The MAC address
    201 * @n_hw_addrs: The number of MAC addresses
    202 * @reserved: For alignment.
    203 * @radio_cfg: The radio configuration.
    204 * @caps: See &enum iwl_mei_nvm_caps.
    205 * @nvm_version: The version of the NVM.
    206 * @channels: The data for each channel.
    207 *
    208 * If a field is added, it must correspond to the SAP structure.
    209 */
    210struct iwl_mei_nvm {
    211	u8 hw_addr[ETH_ALEN];
    212	u8 n_hw_addrs;
    213	u8 reserved;
    214	u32 radio_cfg;
    215	u32 caps;
    216	u32 nvm_version;
    217	u32 channels[110];
    218};
    219
    220/**
    221 * enum iwl_mei_pairwise_cipher - cipher for UCAST key
    222 * @IWL_MEI_CIPHER_NONE: none
    223 * @IWL_MEI_CIPHER_CCMP: ccmp
    224 * @IWL_MEI_CIPHER_GCMP: gcmp
    225 * @IWL_MEI_CIPHER_GCMP_256: gcmp 256
    226 *
    227 * Note that those values are dictated by the CSME firmware API (see sap.h)
    228 */
    229enum iwl_mei_pairwise_cipher {
    230	IWL_MEI_CIPHER_NONE	= 0,
    231	IWL_MEI_CIPHER_CCMP	= 4,
    232	IWL_MEI_CIPHER_GCMP	= 8,
    233	IWL_MEI_CIPHER_GCMP_256 = 9,
    234};
    235
    236/**
    237 * enum iwl_mei_akm_auth - a combination of AKM and AUTH method
    238 * @IWL_MEI_AKM_AUTH_OPEN: No encryption
    239 * @IWL_MEI_AKM_AUTH_RSNA: 1X profile
    240 * @IWL_MEI_AKM_AUTH_RSNA_PSK: PSK profile
    241 * @IWL_MEI_AKM_AUTH_SAE: SAE profile
    242 *
    243 * Note that those values are dictated by the CSME firmware API (see sap.h)
    244 */
    245enum iwl_mei_akm_auth {
    246	IWL_MEI_AKM_AUTH_OPEN		= 0,
    247	IWL_MEI_AKM_AUTH_RSNA		= 6,
    248	IWL_MEI_AKM_AUTH_RSNA_PSK	= 7,
    249	IWL_MEI_AKM_AUTH_SAE		= 9,
    250};
    251
    252/**
    253 * struct iwl_mei_conn_info - connection info
    254 * @lp_state: link protection state
    255 * @auth_mode: authentication mode
    256 * @ssid_len: the length of SSID
    257 * @ssid: the SSID
    258 * @pairwise_cipher: the cipher used for unicast packets
    259 * @channel: the associated channel
    260 * @band: the associated band
    261 * @bssid: the BSSID
    262 */
    263struct iwl_mei_conn_info {
    264	u8 lp_state;
    265	u8 auth_mode;
    266	u8 ssid_len;
    267	u8 channel;
    268	u8 band;
    269	u8 pairwise_cipher;
    270	u8 bssid[ETH_ALEN];
    271	u8 ssid[IEEE80211_MAX_SSID_LEN];
    272};
    273
    274/**
    275 * struct iwl_mei_colloc_info - collocated AP info
    276 * @channel: the channel of the collocated AP
    277 * @bssid: the BSSID of the collocated AP
    278 */
    279struct iwl_mei_colloc_info {
    280	u8 channel;
    281	u8 bssid[ETH_ALEN];
    282};
    283
    284/*
    285 * struct iwl_mei_ops - driver's operations called by iwlmei
    286 * Operations will not be called more than once concurrently.
    287 * It's not allowed to call iwlmei functions from this context.
    288 *
    289 * @me_conn_status: provide information about CSME's current connection.
    290 * @rfkill: called when the wifi driver should report a change in the rfkill
    291 *	status.
    292 * @roaming_forbidden: indicates whether roaming is forbidden.
    293 * @sap_connected: indicate that SAP is now connected. Will be called in case
    294 *	the wifi driver registered to iwlmei before SAP connection succeeded or
    295 *	when the SAP connection is re-established.
    296 * @nic_stolen: this means that device is no longer available. The device can
    297 *	still be used until the callback returns.
    298 */
    299struct iwl_mei_ops {
    300	void (*me_conn_status)(void *priv,
    301			       const struct iwl_mei_conn_info *conn_info);
    302	void (*rfkill)(void *priv, bool blocked);
    303	void (*roaming_forbidden)(void *priv, bool forbidden);
    304	void (*sap_connected)(void *priv);
    305	void (*nic_stolen)(void *priv);
    306};
    307
    308#if IS_ENABLED(CONFIG_IWLMEI)
    309
    310/**
    311 * iwl_mei_is_connected() - is the connection to the CSME firmware established?
    312 *
    313 * Return: true if we have a SAP connection
    314 */
    315bool iwl_mei_is_connected(void);
    316
    317/**
    318 * iwl_mei_get_nvm() - returns the NVM for the device
    319 *
    320 * It is the caller's responsibility to free the memory returned
    321 * by this function.
    322 * This function blocks (sleeps) until the NVM is ready.
    323 *
    324 * Return: the NVM as received from CSME
    325 */
    326struct iwl_mei_nvm *iwl_mei_get_nvm(void);
    327
    328/**
    329 * iwl_mei_get_ownership() - request ownership
    330 *
    331 * This function blocks until ownership is granted or timeout expired.
    332 *
    333 * Return: 0 in case we could get ownership on the device
    334 */
    335int iwl_mei_get_ownership(void);
    336
    337/**
    338 * iwl_mei_set_rfkill_state() - set SW and HW RF kill states
    339 * @hw_rfkill: HW RF kill state.
    340 * @sw_rfkill: SW RF kill state.
    341 *
    342 * This function must be called when SW RF kill is issued by the user.
    343 */
    344void iwl_mei_set_rfkill_state(bool hw_rfkill, bool sw_rfkill);
    345
    346/**
    347 * iwl_mei_set_nic_info() - set mac address
    348 * @mac_address: mac address to set
    349 * @nvm_address: NVM mac adsress to set
    350 *
    351 * This function must be called upon mac address change.
    352 */
    353void iwl_mei_set_nic_info(const u8 *mac_address, const u8 *nvm_address);
    354
    355/**
    356 * iwl_mei_set_country_code() - set new country code
    357 * @mcc: the new applied MCC
    358 *
    359 * This function must be called upon country code update
    360 */
    361void iwl_mei_set_country_code(u16 mcc);
    362
    363/**
    364 * iwl_mei_set_power_limit() - set TX power limit
    365 * @power_limit: pointer to an array of 10 elements (le16) represents the power
    366 * restrictions per chain.
    367 *
    368 * This function must be called upon power restrictions change
    369 */
    370void iwl_mei_set_power_limit(const __le16 *power_limit);
    371
    372/**
    373 * iwl_mei_register() - register the wifi driver to iwlmei
    374 * @priv: a pointer to the wifi driver's context. Cannot be NULL.
    375 * @ops: the ops structure.
    376 *
    377 * Return: 0 unless something went wrong. It is illegal to call any
    378 * other API function before this function is called and succeeds.
    379 *
    380 * Only one wifi driver instance (wifi device instance really)
    381 * can register at a time.
    382 */
    383int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops);
    384
    385/**
    386 * iwl_mei_start_unregister() - unregister the wifi driver from iwlmei
    387 *
    388 * From this point on, iwlmei will not used the callbacks provided by
    389 * the driver, but the device is still usable.
    390 */
    391void iwl_mei_start_unregister(void);
    392
    393/**
    394 * iwl_mei_unregister_complete() - complete the unregistration
    395 *
    396 * Must be called after iwl_mei_start_unregister. When this function returns,
    397 * the device is owned by CSME.
    398 */
    399void iwl_mei_unregister_complete(void);
    400
    401/**
    402 * iwl_mei_set_netdev() - sets the netdev for Tx / Rx.
    403 * @netdev: the net_device
    404 *
    405 * The caller should set the netdev to a non-NULL value when the
    406 * interface is added. Packets might be sent to the driver immediately
    407 * afterwards.
    408 * The caller should set the netdev to NULL when the interface is removed.
    409 * This function will call synchronize_net() after setting the netdev to NULL.
    410 * Only when this function returns, can the caller assume that iwlmei will
    411 * no longer inject packets into the netdev's Tx path.
    412 *
    413 * Context: This function can sleep and assumes rtnl_lock is taken.
    414 * The netdev must be set to NULL before iwl_mei_start_unregister() is called.
    415 */
    416void iwl_mei_set_netdev(struct net_device *netdev);
    417
    418/**
    419 * iwl_mei_tx_copy_to_csme() - must be called for each packet sent by
    420 * the wifi driver.
    421 * @skb: the skb sent
    422 * @ivlen: the size of the IV that needs to be skipped after the MAC and
    423 *	before the SNAP header.
    424 *
    425 * This function doesn't take any lock, it simply tries to catch DHCP
    426 * packets sent by the wifi driver. If the packet is a DHCP packet, it
    427 * will send it to CSME. This function must not be called for virtual
    428 * interfaces that are not monitored by CSME, meaning it must be called
    429 * only for packets transmitted by the netdevice that was registered
    430 * with iwl_mei_set_netdev().
    431 */
    432void iwl_mei_tx_copy_to_csme(struct sk_buff *skb, unsigned int ivlen);
    433
    434/**
    435 * iwl_mei_host_associated() - must be called when iwlwifi associated.
    436 * @conn_info: pointer to the connection info structure.
    437 * @colloc_info: pointer to the collocated AP info. This is relevant only in
    438 *	case of UHB associated AP, otherwise set to NULL.
    439 */
    440void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info,
    441			     const struct iwl_mei_colloc_info *colloc_info);
    442
    443/**
    444 * iwl_mei_host_disassociated() - must be called when iwlwifi disassociated.
    445 */
    446void iwl_mei_host_disassociated(void);
    447
    448/**
    449 * iwl_mei_device_down() - must be called when the device is down
    450 */
    451void iwl_mei_device_down(void);
    452
    453#else
    454
    455static inline bool iwl_mei_is_connected(void)
    456{ return false; }
    457
    458static inline struct iwl_mei_nvm *iwl_mei_get_nvm(void)
    459{ return NULL; }
    460
    461static inline int iwl_mei_get_ownership(void)
    462{ return 0; }
    463
    464static inline void iwl_mei_set_rfkill_state(bool hw_rfkill, bool sw_rfkill)
    465{}
    466
    467static inline void iwl_mei_set_nic_info(const u8 *mac_address, const u8 *nvm_address)
    468{}
    469
    470static inline void iwl_mei_set_country_code(u16 mcc)
    471{}
    472
    473static inline void iwl_mei_set_power_limit(__le16 *power_limit)
    474{}
    475
    476static inline int iwl_mei_register(void *priv,
    477				   const struct iwl_mei_ops *ops)
    478{ return 0; }
    479
    480static inline void iwl_mei_start_unregister(void)
    481{}
    482
    483static inline void iwl_mei_unregister_complete(void)
    484{}
    485
    486static inline void iwl_mei_set_netdev(struct net_device *netdev)
    487{}
    488
    489static inline void iwl_mei_tx_copy_to_csme(struct sk_buff *skb,
    490					   unsigned int ivlen)
    491{}
    492
    493static inline void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info,
    494					   const struct iwl_mei_colloc_info *colloc_info)
    495{}
    496
    497static inline void iwl_mei_host_disassociated(void)
    498{}
    499
    500static inline void iwl_mei_device_down(void)
    501{}
    502
    503#endif /* CONFIG_IWLMEI */
    504
    505#endif /* __iwl_mei_h__ */