lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID:
 <PAWPR04MB99105D54225EAEF18A1E06C99CBF2@PAWPR04MB9910.eurprd04.prod.outlook.com>
Date: Fri, 18 Apr 2025 08:12:15 +0000
From: Jeff Chen <jeff.chen_1@....com>
To: Sascha Hauer <s.hauer@...gutronix.de>, Brian Norris
	<briannorris@...omium.org>, Francesco Dolcini <francesco@...cini.it>, Ulf
 Hansson <ulf.hansson@...aro.org>
CC: "linux-wireless@...r.kernel.org" <linux-wireless@...r.kernel.org>,
	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
	"linux-mmc@...r.kernel.org" <linux-mmc@...r.kernel.org>
Subject: RE: [EXT] [PATCH do not merge 2/4] wifi: mwifiex: handle VDLL

> -----Original Message-----
> From: Sascha Hauer <s.hauer@...gutronix.de>
> Sent: Wednesday, March 26, 2025 8:19 PM
> To: Brian Norris <briannorris@...omium.org>; Francesco Dolcini
> <francesco@...cini.it>; Ulf Hansson <ulf.hansson@...aro.org>
> Cc: linux-wireless@...r.kernel.org; linux-kernel@...r.kernel.org;
> linux-mmc@...r.kernel.org; Sascha Hauer <s.hauer@...gutronix.de>
> Subject: [EXT] [PATCH do not merge 2/4] wifi: mwifiex: handle VDLL
> 
> Caution: This is an external email. Please take care when clicking links or
> opening attachments. When in doubt, report the message using the 'Report
> this email' button
> 
> 
> Some adapters send events to the Kernel requesting VDLL images. When we
> receive such an event we have to upload parts of the firmware image to the
> device.
> 
> When the firmware requests a VDLL image then we have to bypass the
> pending command queue and have to send it immediately. Failing to do so will
> cause every other command sent from the queue to timeout.
> 
> There is this check currently in mwifiex_download_vdll_block():
> 
>         if (adapter->cmd_sent) {
>                 mwifiex_dbg(adapter, MSG, "%s: adapter is busy\n",
> __func__);
>                 return -EBUSY;
>         }
> 
> The downstream driver has this check as well. However, the downstream
> driver tries to defer sending the VDLL command when this happens. It sets a
> variable in the private driver struct where the main process picks it up later.  I
> am not sure if this can work, because when
> adapter->cmd_sent is true then it's already too late, we already missed
> to send the VDLL image before the next command. In my tests I never saw the
> above trigger, but this surely a place to have a closer look at.
> 
> Signed-off-by: Sascha Hauer <s.hauer@...gutronix.de>
> ---
>  drivers/net/wireless/marvell/mwifiex/cmdevt.c    | 86
> ++++++++++++++++++++++++
>  drivers/net/wireless/marvell/mwifiex/fw.h        | 16 +++++
>  drivers/net/wireless/marvell/mwifiex/main.h      |  4 ++
>  drivers/net/wireless/marvell/mwifiex/sta_event.c |  4 ++
> drivers/net/wireless/marvell/mwifiex/uap_event.c |  4 ++
>  5 files changed, 114 insertions(+)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> index b30ed321c6251..916d0b804bec3 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> @@ -1716,3 +1716,89 @@ int mwifiex_ret_wakeup_reason(struct
> mwifiex_private *priv,
> 
>         return 0;
>  }
> +
> +static int mwifiex_download_vdll_block(struct mwifiex_adapter *adapter,
> u32 offset,
> +                                      u16 block_len) {
> +       int ret;
> +       struct host_cmd_ds_gen *cmd_hdr = NULL;
> +       u16 msg_len = block_len + sizeof(*cmd_hdr);
> +       struct sk_buff *skb;
> +       u32 fw_offset;
> +
> +       block_len = min(block_len, adapter->vdll_len - offset);
> +
> +       if (offset > adapter->vdll_len)
> +               return -EINVAL;
> +
> +       if (adapter->cmd_sent) {
> +               mwifiex_dbg(adapter, MSG, "%s: adapter is busy\n",
> __func__);
> +               return -EBUSY;
> +       }

Shared the handling of VDLL events in the nxpwifi driver:  
- When “cmd_sent” is true: The VDLL block download is deferred, with its offset and length stored for later processing.
- When no command is active (“cmd_sent” is false): The VDLL block is downloaded immediately in the nxpwifi_main_process.

int nxpwifi_process_vdll_event(struct nxpwifi_private *priv,
                              struct sk_buff *skb)
{
:
                       if (!adapter->cmd_sent) {
                               ret = nxpwifi_download_vdll_block(adapter,
                                                                 ctrl->vdll_mem
                                                                 + offset,
                                                                 block_len);
                               if (ret)
                                       nxpwifi_dbg(adapter, ERROR,
                                                   "Download VDLL failed\n");
                       } else {
                               nxpwifi_dbg(adapter, EVENT,
                                           "Delay download VDLL block\n");
                               ctrl->pending_block_len = block_len;
                               ctrl->pending_block = ctrl->vdll_mem + offset;
                       }
:
}

int nxpwifi_main_process(struct nxpwifi_adapter *adapter)
{
:
               if (!adapter->cmd_sent &&
                   adapter->vdll_ctrl.pending_block) {
                       struct vdll_dnld_ctrl *ctrl = &adapter->vdll_ctrl;

                       nxpwifi_download_vdll_block(adapter, ctrl->pending_block,
                                                   ctrl->pending_block_len);
                       ctrl->pending_block = NULL;
               }
:
}

> +
> +       skb = dev_alloc_skb(msg_len + MWIFIEX_TYPE_LEN);
> +       if (!skb) {
> +               mwifiex_dbg(adapter, ERROR,
> +                               "SLEEP_CFM: dev_alloc_skb failed\n");
> +               return -ENOMEM;
> +       }
> +
> +       skb_put(skb, msg_len);
> +
> +       cmd_hdr = (void *)skb->data;
> +       cmd_hdr->command = cpu_to_le16(HostCmd_CMD_VDLL);
> +       cmd_hdr->seq_num = cpu_to_le16(0xFF00);
> +       cmd_hdr->size = cpu_to_le16(msg_len);
> +
> +       fw_offset = adapter->firmware->size - adapter->vdll_len + offset;
> +       memcpy(skb->data + sizeof(*cmd_hdr), adapter->firmware->data +
> + fw_offset, block_len);
> +
> +       skb_push(skb, adapter->intf_hdr_len);
> +
> +       ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_VDLL,
> skb, NULL);
> +       if (ret < 0)
> +               mwifiex_dbg(adapter, MSG, "DNLD_VDLL: Host to Card
> + Failed\n");
> +
> +       dev_kfree_skb_any(skb);
> +
> +       return ret;
> +
> +}
> +
> +int mwifiex_process_vdll_event(struct mwifiex_private *priv, struct
> +sk_buff *event_skb) {
> +       int status = 0;
> +       struct mwifiex_vdll_ind *ind;
> +       struct mwifiex_adapter *adapter = priv->adapter;
> +
> +       ind = (struct mwifiex_vdll_ind *)(event_skb->data +
> + sizeof(u32));
> +
> +       switch (le16_to_cpu(ind->type)) {
> +       case VDLL_IND_TYPE_REQ:
> +               mwifiex_download_vdll_block(adapter,
> le32_to_cpu(ind->offset),
> +
> le16_to_cpu(ind->block_len));
> +               break;
> +       case VDLL_IND_TYPE_OFFSET:
> +               adapter->vdll_len = le32_to_cpu(ind->offset);
> +               mwifiex_dbg(adapter, MSG, "VDLL_IND (OFFSET):
> offset=0x%x\n",
> +                           adapter->vdll_len);
> +               break;
> +       case VDLL_IND_TYPE_ERR_SIG:
> +               mwifiex_dbg(adapter, MSG, "VDLL_IND (SIG ERR).\n");
> +               break;
> +       case VDLL_IND_TYPE_ERR_ID:
> +               mwifiex_dbg(adapter, MSG, "VDLL_IND (ID ERR).\n");
> +               break;
> +       case VDLL_IND_TYPE_SEC_ERR_ID:
> +               mwifiex_dbg(adapter, MSG, "VDLL_IND (SECURE ERR).\n");
> +               break;
> +       case VDLL_IND_TYPE_INTF_RESET:
> +               mwifiex_dbg(adapter, MSG, "VDLL_IND (INTF_RESET)\n");
> +               break;
> +       default:
> +               mwifiex_dbg(adapter, MSG, "unknown vdll ind
> type=%d\n", ind->type);
> +               break;
> +       }
> +
> +       return status;
> +}
> diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h
> b/drivers/net/wireless/marvell/mwifiex/fw.h
> index 4a96281792cc1..92541bc6d0122 100644
> --- a/drivers/net/wireless/marvell/mwifiex/fw.h
> +++ b/drivers/net/wireless/marvell/mwifiex/fw.h
> @@ -406,6 +406,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
>  #define HostCmd_CMD_FW_DUMP_EVENT                    0x0125
>  #define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG               0x0223
>  #define HostCmd_CMD_STA_CONFIGURE                    0x023f
> +#define HostCmd_CMD_VDLL                             0x0240
>  #define HostCmd_CMD_CHAN_REGION_CFG                  0x0242
>  #define HostCmd_CMD_PACKET_AGGR_CTRL                 0x0251
>  #define HostCmd_CMD_ADD_NEW_STATION                  0x025f
> @@ -584,6 +585,7 @@ enum mwifiex_channel_flags {
>  #define EVENT_FW_DUMP_INFO             0x00000073
>  #define EVENT_TX_STATUS_REPORT         0x00000074
>  #define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076
> +#define EVENT_VDLL_IND                 0x00000081
> 
>  #define EVENT_ID_MASK                   0xffff
>  #define BSS_NUM_MASK                    0xf
> @@ -2449,4 +2451,18 @@ struct hw_spec_max_conn {
>         u8 max_sta_conn;
>  } __packed;
> 
> +#define VDLL_IND_TYPE_REQ              0 /* req host side download
> vdll block */
> +#define VDLL_IND_TYPE_OFFSET           1 /* notify vdll start offset in
> firmware image */
> +#define VDLL_IND_TYPE_ERR_SIG          2 /* notify vdll download error:
> signature error */
> +#define VDLL_IND_TYPE_ERR_ID           3 /* notify vdll download error:
> ID error */
> +#define VDLL_IND_TYPE_SEC_ERR_ID       4 /* notify vdll download error:
> Secure error */
> +#define VDLL_IND_TYPE_INTF_RESET       5 /* req host side interface
> reset */
> +
> +struct mwifiex_vdll_ind {
> +       __le16 type;
> +       __le16 vdllId;
> +       __le32 offset;
> +       __le16 block_len;
> +} __packed;
> +
>  #endif /* !_MWIFIEX_FW_H_ */
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.h
> b/drivers/net/wireless/marvell/mwifiex/main.h
> index 0674dcf7a5374..5adbf66957e14 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.h
> +++ b/drivers/net/wireless/marvell/mwifiex/main.h
> @@ -131,6 +131,7 @@ enum {
>  #define MWIFIEX_TYPE_DATA                              0
>  #define MWIFIEX_TYPE_AGGR_DATA                         10
>  #define MWIFIEX_TYPE_EVENT                             3
> +#define MWIFIEX_TYPE_VDLL                              4
> 
>  #define MAX_BITMAP_RATES_SIZE                  18
> 
> @@ -1041,6 +1042,8 @@ struct mwifiex_adapter {
>         struct delayed_work devdump_work;
> 
>         bool ignore_btcoex_events;
> +
> +       u32 vdll_len;
>  };
> 
>  void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); @@
> -1252,6 +1255,7 @@ int mwifiex_cmd_802_11_bg_scan_config(struct
> mwifiex_private *priv,
>                                       struct host_cmd_ds_command
> *cmd,
>                                       void *data_buf);  int
> mwifiex_stop_bg_scan(struct mwifiex_private *priv);
> +int mwifiex_process_vdll_event(struct mwifiex_private *priv, struct
> +sk_buff *event_skb);
> 
>  /*
>   * This function checks if the queuing is RA based or not.
> diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c
> b/drivers/net/wireless/marvell/mwifiex/sta_event.c
> index 400348abeee54..e516f44f1804d 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
> @@ -1084,6 +1084,10 @@ int mwifiex_process_sta_event(struct
> mwifiex_private *priv)
>                 mwifiex_dbg(adapter, EVENT, "event: firmware debug
> info\n");
>                 mwifiex_fw_dump_info_event(priv, adapter->event_skb);
>                 break;
> +       case EVENT_VDLL_IND:
> +               mwifiex_dbg(adapter, EVENT, "event: VDLL event\n");
> +               mwifiex_process_vdll_event(priv, adapter->event_skb);
> +               break;
>         /* Debugging event; not used, but let's not print an ERROR for it. */
>         case EVENT_UNKNOWN_DEBUG:
>                 mwifiex_dbg(adapter, EVENT, "event: debug\n"); diff --git
> a/drivers/net/wireless/marvell/mwifiex/uap_event.c
> b/drivers/net/wireless/marvell/mwifiex/uap_event.c
> index 58ef5020a46a7..80a9c433db64a 100644
> --- a/drivers/net/wireless/marvell/mwifiex/uap_event.c
> +++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c
> @@ -317,6 +317,10 @@ int mwifiex_process_uap_event(struct
> mwifiex_private *priv)
>                 memset(&priv->roc_cfg, 0x00, sizeof(struct
> mwifiex_roc_cfg));
>                 break;
> 
> +       case EVENT_VDLL_IND:
> +               mwifiex_dbg(adapter, EVENT, "event: handle VDLL
> event...\n");
> +               mwifiex_process_vdll_event(priv, adapter->event_skb);
> +               break;
>         default:
>                 mwifiex_dbg(adapter, EVENT,
>                             "event: unknown event id: %#x\n",
> eventcause);
> 
> --
> 2.39.5
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ