From: Xinming Hu <[email protected]>
This patch refactor current device dump code to make it generic
for subsequent implementation on usb interface.
Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
Signed-off-by: Ganapathi Bhat <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/main.c | 90 +++++++++++++++--------------
drivers/net/wireless/marvell/mwifiex/main.h | 11 +++-
drivers/net/wireless/marvell/mwifiex/pcie.c | 13 +++--
drivers/net/wireless/marvell/mwifiex/sdio.c | 14 +++--
4 files changed, 74 insertions(+), 54 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index ee40b73..919d91a 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1052,9 +1052,26 @@ void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter)
}
EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync);
-int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info)
+void mwifiex_upload_device_dump(unsigned long function_context)
{
- void *p;
+ struct mwifiex_adapter *adapter =
+ (struct mwifiex_adapter *)function_context;
+
+ /* Dump all the memory data into single file, a userspace script will
+ * be used to split all the memory data to multiple files
+ */
+ mwifiex_dbg(adapter, MSG,
+ "== mwifiex dump information to /sys/class/devcoredump start");
+ dev_coredumpv(adapter->dev, adapter->devdump_data, adapter->devdump_len,
+ GFP_KERNEL);
+ mwifiex_dbg(adapter, MSG,
+ "== mwifiex dump information to /sys/class/devcoredump end");
+}
+EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
+
+void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter)
+{
+ char *p;
char drv_version[64];
struct usb_card_rec *cardp;
struct sdio_mmc_card *sdio_card;
@@ -1062,17 +1079,12 @@ int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info)
int i, idx;
struct netdev_queue *txq;
struct mwifiex_debug_info *debug_info;
- void *drv_info_dump;
mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump start===\n");
- /* memory allocate here should be free in mwifiex_upload_device_dump*/
- drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX);
-
- if (!drv_info_dump)
- return 0;
-
- p = (char *)(drv_info_dump);
+ p = adapter->devdump_data;
+ strcpy(p, "========Start dump driverinfo========\n");
+ p += strlen("========Start dump driverinfo========\n");
p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
mwifiex_drv_get_driver_version(adapter, drv_version,
@@ -1156,21 +1168,18 @@ int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info)
kfree(debug_info);
}
+ strcpy(p, "\n========End dump========\n");
+ p += strlen("\n========End dump========\n");
mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump end===\n");
- *drv_info = drv_info_dump;
- return p - drv_info_dump;
+ adapter->devdump_len = p - adapter->devdump_data;
}
EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump);
-void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
- int drv_info_size)
+void mwifiex_prepare_fw_dump_info(struct mwifiex_adapter *adapter)
{
- u8 idx, *dump_data, *fw_dump_ptr;
- u32 dump_len;
-
- dump_len = (strlen("========Start dump driverinfo========\n") +
- drv_info_size +
- strlen("\n========End dump========\n"));
+ u8 idx;
+ char *fw_dump_ptr;
+ u32 dump_len = 0;
for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
@@ -1185,24 +1194,24 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
}
}
- dump_data = vzalloc(dump_len + 1);
- if (!dump_data)
- goto done;
-
- fw_dump_ptr = dump_data;
+ if (dump_len + 1 + adapter->devdump_len > MWIFIEX_FW_DUMP_SIZE) {
+ /* Realloc in case buffer overflow */
+ fw_dump_ptr = vzalloc(dump_len + 1 + adapter->devdump_len);
+ mwifiex_dbg(adapter, MSG, "Realloc device dump data.");
+ if (!fw_dump_ptr) {
+ vfree(adapter->devdump_data);
+ mwifiex_dbg(adapter, ERROR,
+ "vzalloc devdump data failure!\n");
+ return;
+ }
- /* Dump all the memory data into single file, a userspace script will
- * be used to split all the memory data to multiple files
- */
- mwifiex_dbg(adapter, MSG,
- "== mwifiex dump information to /sys/class/devcoredump start");
+ memmove(fw_dump_ptr, adapter->devdump_data,
+ adapter->devdump_len);
+ vfree(adapter->devdump_data);
+ adapter->devdump_data = fw_dump_ptr;
+ }
- strcpy(fw_dump_ptr, "========Start dump driverinfo========\n");
- fw_dump_ptr += strlen("========Start dump driverinfo========\n");
- memcpy(fw_dump_ptr, drv_info, drv_info_size);
- fw_dump_ptr += drv_info_size;
- strcpy(fw_dump_ptr, "\n========End dump========\n");
- fw_dump_ptr += strlen("\n========End dump========\n");
+ fw_dump_ptr = adapter->devdump_data + adapter->devdump_len;
for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
@@ -1229,11 +1238,8 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
/* device dump data will be free in device coredump release function
* after 5 min
*/
- dev_coredumpv(adapter->dev, dump_data, dump_len, GFP_KERNEL);
- mwifiex_dbg(adapter, MSG,
- "== mwifiex dump information to /sys/class/devcoredump end");
+ adapter->devdump_len = fw_dump_ptr - adapter->devdump_data;
-done:
for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
&adapter->mem_type_mapping_tbl[idx];
@@ -1242,10 +1248,8 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
entry->mem_ptr = NULL;
entry->mem_size = 0;
}
-
- vfree(drv_info);
}
-EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
+EXPORT_SYMBOL_GPL(mwifiex_prepare_fw_dump_info);
/*
* CFG802.11 network device handler for statistics retrieval.
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 0aaae08..e308b8a 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -94,6 +94,8 @@ enum {
#define MAX_EVENT_SIZE 2048
+#define MWIFIEX_FW_DUMP_SIZE (2 * 1024 * 1024)
+
#define ARP_FILTER_MAX_BUF_SIZE 68
#define MWIFIEX_KEY_BUFFER_SIZE 16
@@ -1033,6 +1035,9 @@ struct mwifiex_adapter {
bool wake_by_wifi;
/* Aggregation parameters*/
struct bus_aggr_params bus_aggr;
+ /* Device dump data/length */
+ char *devdump_data;
+ int devdump_len;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1654,9 +1659,9 @@ void mwifiex_hist_data_add(struct mwifiex_private *priv,
u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
u8 rx_rate, u8 ht_info);
-int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info);
-void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
- int drv_info_size);
+void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter);
+void mwifiex_prepare_fw_dump_info(struct mwifiex_adapter *adapter);
+void mwifiex_upload_device_dump(unsigned long function_context);
void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action,
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index cd31494..dbc5944 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2769,12 +2769,17 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
{
- int drv_info_size;
- void *drv_info;
+ adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
+ if (!adapter->devdump_data) {
+ mwifiex_dbg(adapter, ERROR,
+ "vzalloc devdump data failure!\n");
+ return;
+ }
- drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info);
+ mwifiex_drv_info_dump(adapter);
mwifiex_pcie_fw_dump(adapter);
- mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
+ mwifiex_prepare_fw_dump_info(adapter);
+ mwifiex_upload_device_dump((unsigned long)adapter);
}
static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index fd5183c..8010109 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -2505,15 +2505,21 @@ static void mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter)
static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)
{
struct sdio_mmc_card *card = adapter->card;
- int drv_info_size;
- void *drv_info;
- drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info);
+ adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
+ if (!adapter->devdump_data) {
+ mwifiex_dbg(adapter, ERROR,
+ "vzalloc devdump data failure!\n");
+ return;
+ }
+
+ mwifiex_drv_info_dump(adapter);
if (card->fw_dump_enh)
mwifiex_sdio_generic_fw_dump(adapter);
else
mwifiex_sdio_fw_dump(adapter);
- mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
+ mwifiex_prepare_fw_dump_info(adapter);
+ mwifiex_upload_device_dump((unsigned long)adapter);
}
static void mwifiex_sdio_work(struct work_struct *work)
--
1.9.1
From: Xinming Hu <[email protected]>
Firmware dump on usb interface is different with current
sdio/pcie chipset, which is based on register operation.
When firmware hang on usb interface, context dump will be
upload to host using 0x73 firmware debug event.
This patch store dump data from debug event and send to
userspace using device coredump API.
Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
Signed-off-by: Ganapathi Bhat <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/fw.h | 1 +
drivers/net/wireless/marvell/mwifiex/init.c | 3 ++
drivers/net/wireless/marvell/mwifiex/main.h | 2 ++
drivers/net/wireless/marvell/mwifiex/sta_event.c | 39 ++++++++++++++++++++++++
4 files changed, 45 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 9e75522..610a3ea 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -568,6 +568,7 @@ enum mwifiex_channel_flags {
#define EVENT_BG_SCAN_STOPPED 0x00000065
#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
#define EVENT_MULTI_CHAN_INFO 0x0000006a
+#define EVENT_FW_DUMP_INFO 0x00000073
#define EVENT_TX_STATUS_REPORT 0x00000074
#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index e11919d..389d725 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -315,6 +315,8 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->active_scan_triggered = false;
setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
(unsigned long)adapter);
+ setup_timer(&adapter->devdump_timer, mwifiex_upload_device_dump,
+ (unsigned long)adapter);
}
/*
@@ -397,6 +399,7 @@ static void mwifiex_invalidate_lists(struct mwifiex_adapter *adapter)
mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
{
del_timer(&adapter->wakeup_timer);
+ del_timer_sync(&adapter->devdump_timer);
mwifiex_cancel_all_pending_cmd(adapter);
wake_up_interruptible(&adapter->cmd_wait_q.wait);
wake_up_interruptible(&adapter->hs_activate_wait_q);
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index e308b8a..6b00294 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1038,6 +1038,7 @@ struct mwifiex_adapter {
/* Device dump data/length */
char *devdump_data;
int devdump_len;
+ struct timer_list devdump_timer;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1680,6 +1681,7 @@ void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter);
int mwifiex_set_mac_address(struct mwifiex_private *priv,
struct net_device *dev);
+void mwifiex_devdump_tmo_func(unsigned long function_context);
#ifdef CONFIG_DEBUG_FS
void mwifiex_debugfs_init(void);
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index 839df8a..bcf2fa2 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -586,6 +586,40 @@ void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
adapter->coex_rx_win_size);
}
+static void
+mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
+ struct sk_buff *event_skb)
+{
+ struct mwifiex_adapter *adapter = priv->adapter;
+
+ if (adapter->iface_type != MWIFIEX_USB) {
+ mwifiex_dbg(adapter, MSG,
+ "event is not on usb interface, ignore it\n");
+ return;
+ }
+
+ if (!adapter->devdump_data) {
+ /* When receive the first event, allocate device dump
+ * buffer, dump driver info.
+ */
+ adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
+ if (!adapter->devdump_data) {
+ mwifiex_dbg(adapter, ERROR,
+ "vzalloc devdump data failure!\n");
+ return;
+ }
+
+ mwifiex_drv_info_dump(adapter);
+ }
+
+ memmove(adapter->devdump_data + adapter->devdump_len,
+ adapter->event_body, event_skb->len - MWIFIEX_EVENT_HEADER_LEN);
+ adapter->devdump_len += (event_skb->len - MWIFIEX_EVENT_HEADER_LEN);
+ /* If no proceeded event arrive in 10s, upload device dump data*/
+ mod_timer(&adapter->devdump_timer,
+ jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
+}
+
/*
* This function handles events generated by firmware.
*
@@ -638,6 +672,7 @@ void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
* - EVENT_DELBA
* - EVENT_BA_STREAM_TIEMOUT
* - EVENT_AMSDU_AGGR_CTRL
+ * - EVENT_FW_DUMP_INFO
*/
int mwifiex_process_sta_event(struct mwifiex_private *priv)
{
@@ -1009,6 +1044,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
adapter->event_skb->len -
sizeof(eventcause));
break;
+ case EVENT_FW_DUMP_INFO:
+ mwifiex_dbg(adapter, EVENT, "event: firmware debug info\n");
+ mwifiex_fw_dump_info_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");
--
1.9.1
Hi,
On Mon, Aug 14, 2017 at 12:19:02PM +0000, Xinming Hu wrote:
> From: Xinming Hu <[email protected]>
>
> Firmware dump on usb interface is different with current
> sdio/pcie chipset, which is based on register operation.
>
> When firmware hang on usb interface, context dump will be
> upload to host using 0x73 firmware debug event.
>
> This patch store dump data from debug event and send to
> userspace using device coredump API.
>
> Signed-off-by: Xinming Hu <[email protected]>
> Signed-off-by: Cathy Luo <[email protected]>
> Signed-off-by: Ganapathi Bhat <[email protected]>
> ---
> drivers/net/wireless/marvell/mwifiex/fw.h | 1 +
> drivers/net/wireless/marvell/mwifiex/init.c | 3 ++
> drivers/net/wireless/marvell/mwifiex/main.h | 2 ++
> drivers/net/wireless/marvell/mwifiex/sta_event.c | 39 ++++++++++++++++++++++++
> 4 files changed, 45 insertions(+)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
> index 9e75522..610a3ea 100644
> --- a/drivers/net/wireless/marvell/mwifiex/fw.h
> +++ b/drivers/net/wireless/marvell/mwifiex/fw.h
> @@ -568,6 +568,7 @@ enum mwifiex_channel_flags {
> #define EVENT_BG_SCAN_STOPPED 0x00000065
> #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
> #define EVENT_MULTI_CHAN_INFO 0x0000006a
> +#define EVENT_FW_DUMP_INFO 0x00000073
> #define EVENT_TX_STATUS_REPORT 0x00000074
> #define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
> index e11919d..389d725 100644
> --- a/drivers/net/wireless/marvell/mwifiex/init.c
> +++ b/drivers/net/wireless/marvell/mwifiex/init.c
> @@ -315,6 +315,8 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
> adapter->active_scan_triggered = false;
> setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
> (unsigned long)adapter);
> + setup_timer(&adapter->devdump_timer, mwifiex_upload_device_dump,
> + (unsigned long)adapter);
> }
>
> /*
> @@ -397,6 +399,7 @@ static void mwifiex_invalidate_lists(struct mwifiex_adapter *adapter)
> mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
> {
> del_timer(&adapter->wakeup_timer);
> + del_timer_sync(&adapter->devdump_timer);
> mwifiex_cancel_all_pending_cmd(adapter);
> wake_up_interruptible(&adapter->cmd_wait_q.wait);
> wake_up_interruptible(&adapter->hs_activate_wait_q);
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
> index e308b8a..6b00294 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.h
> +++ b/drivers/net/wireless/marvell/mwifiex/main.h
> @@ -1038,6 +1038,7 @@ struct mwifiex_adapter {
> /* Device dump data/length */
> char *devdump_data;
> int devdump_len;
> + struct timer_list devdump_timer;
> };
>
> void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
> @@ -1680,6 +1681,7 @@ void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
> void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter);
> int mwifiex_set_mac_address(struct mwifiex_private *priv,
> struct net_device *dev);
> +void mwifiex_devdump_tmo_func(unsigned long function_context);
>
> #ifdef CONFIG_DEBUG_FS
> void mwifiex_debugfs_init(void);
> diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
> index 839df8a..bcf2fa2 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
> @@ -586,6 +586,40 @@ void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
> adapter->coex_rx_win_size);
> }
>
> +static void
> +mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
> + struct sk_buff *event_skb)
> +{
> + struct mwifiex_adapter *adapter = priv->adapter;
> +
> + if (adapter->iface_type != MWIFIEX_USB) {
> + mwifiex_dbg(adapter, MSG,
> + "event is not on usb interface, ignore it\n");
> + return;
> + }
> +
> + if (!adapter->devdump_data) {
> + /* When receive the first event, allocate device dump
> + * buffer, dump driver info.
> + */
> + adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
Does this ever get freed?
> + if (!adapter->devdump_data) {
> + mwifiex_dbg(adapter, ERROR,
> + "vzalloc devdump data failure!\n");
> + return;
> + }
> +
> + mwifiex_drv_info_dump(adapter);
> + }
> +
> + memmove(adapter->devdump_data + adapter->devdump_len,
> + adapter->event_body, event_skb->len - MWIFIEX_EVENT_HEADER_LEN);
> + adapter->devdump_len += (event_skb->len - MWIFIEX_EVENT_HEADER_LEN);
Are you going to try to check for overflow?
> + /* If no proceeded event arrive in 10s, upload device dump data*/
You missed a space at the end of the comment. Should be:
/* If no proceeded event arrive in 10s, upload device dump data. */
Also, is that really the only way to signal that the firmware dump has
completed? By timing out? That seems like a very bad design. Can you
implement an "end of transmission" signal?
Brian
> + mod_timer(&adapter->devdump_timer,
> + jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
> +}
> +
> /*
> * This function handles events generated by firmware.
> *
> @@ -638,6 +672,7 @@ void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
> * - EVENT_DELBA
> * - EVENT_BA_STREAM_TIEMOUT
> * - EVENT_AMSDU_AGGR_CTRL
> + * - EVENT_FW_DUMP_INFO
> */
> int mwifiex_process_sta_event(struct mwifiex_private *priv)
> {
> @@ -1009,6 +1044,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
> adapter->event_skb->len -
> sizeof(eventcause));
> break;
> + case EVENT_FW_DUMP_INFO:
> + mwifiex_dbg(adapter, EVENT, "event: firmware debug info\n");
> + mwifiex_fw_dump_info_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");
> --
> 1.9.1
>
From: Xinming Hu <[email protected]>
This patch extend device_dump debugfs function to make it
works for usb interface.
Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
Signed-off-by: Ganapathi Bhat <[email protected]>
---
drivers/net/wireless/marvell/mwifiex/cmdevt.c | 11 +++++++----
drivers/net/wireless/marvell/mwifiex/debugfs.c | 9 +++++----
drivers/net/wireless/marvell/mwifiex/fw.h | 1 +
drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 4 ++++
4 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 0edc5d6..b16dd6a 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -290,13 +290,16 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] =
get_unaligned_le16((u8 *)host_cmd + S_DS_GEN);
+ /* Setup the timer after transmit command, except that specific
+ * command might not have command response.
+ */
+ if (cmd_code != HostCmd_CMD_FW_DUMP_EVENT)
+ mod_timer(&adapter->cmd_timer,
+ jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
+
/* Clear BSS_NO_BITS from HostCmd */
cmd_code &= HostCmd_CMD_ID_MASK;
- /* Setup the timer after transmit command */
- mod_timer(&adapter->cmd_timer,
- jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
-
return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
index 6f4239b..5d476de 100644
--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@ -168,10 +168,11 @@
{
struct mwifiex_private *priv = file->private_data;
- if (!priv->adapter->if_ops.device_dump)
- return -EIO;
-
- priv->adapter->if_ops.device_dump(priv->adapter);
+ if (priv->adapter->iface_type == MWIFIEX_USB)
+ mwifiex_send_cmd(priv, HostCmd_CMD_FW_DUMP_EVENT,
+ HostCmd_ACT_GEN_SET, 0, NULL, true);
+ else
+ priv->adapter->if_ops.device_dump(priv->adapter);
return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 610a3ea..2d3a644 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -398,6 +398,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_TDLS_CONFIG 0x0100
#define HostCmd_CMD_MC_POLICY 0x0121
#define HostCmd_CMD_TDLS_OPER 0x0122
+#define HostCmd_CMD_FW_DUMP_EVENT 0x0125
#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223
#define HostCmd_CMD_CHAN_REGION_CFG 0x0242
#define HostCmd_CMD_PACKET_AGGR_CTRL 0x0251
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index fb09014..211e47d 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -2206,6 +2206,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
case HostCmd_CMD_CHAN_REGION_CFG:
ret = mwifiex_cmd_chan_region_cfg(priv, cmd_ptr, cmd_action);
break;
+ case HostCmd_CMD_FW_DUMP_EVENT:
+ cmd_ptr->command = cpu_to_le16(cmd_no);
+ cmd_ptr->size = cpu_to_le16(S_DS_GEN);
+ break;
default:
mwifiex_dbg(priv->adapter, ERROR,
"PREP_CMD: unknown cmd- %#x\n", cmd_no);
--
1.9.1
On Mon, Aug 14, 2017 at 12:19:01PM +0000, Xinming Hu wrote:
> From: Xinming Hu <[email protected]>
>
> This patch refactor current device dump code to make it generic
> for subsequent implementation on usb interface.
>
> Signed-off-by: Xinming Hu <[email protected]>
> Signed-off-by: Cathy Luo <[email protected]>
> Signed-off-by: Ganapathi Bhat <[email protected]>
> ---
> drivers/net/wireless/marvell/mwifiex/main.c | 90 +++++++++++++++--------------
> drivers/net/wireless/marvell/mwifiex/main.h | 11 +++-
> drivers/net/wireless/marvell/mwifiex/pcie.c | 13 +++--
> drivers/net/wireless/marvell/mwifiex/sdio.c | 14 +++--
> 4 files changed, 74 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
> index ee40b73..919d91a 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.c
> +++ b/drivers/net/wireless/marvell/mwifiex/main.c
> @@ -1052,9 +1052,26 @@ void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter)
> }
> EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync);
>
> -int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info)
> +void mwifiex_upload_device_dump(unsigned long function_context)
My eyes! It burns!
Most callers don't need the casting, so this looks terribly unsafe.
Please keep the casting to only where it's needed (i.e., in the
timer-related code).
Also, why can't the caller pass in the dump data/len values? You're
making PCIe and SDIO look even uglier, just because you can't figure out
how to wrap this nicely for USB.
You might do better to consider how to make this nicer by implementing
better driver callbacks, and doing most of the work in the core.
Overall, you shouldn't need so many exported symbols.
> {
> - void *p;
> + struct mwifiex_adapter *adapter =
> + (struct mwifiex_adapter *)function_context;
> +
> + /* Dump all the memory data into single file, a userspace script will
> + * be used to split all the memory data to multiple files
> + */
> + mwifiex_dbg(adapter, MSG,
> + "== mwifiex dump information to /sys/class/devcoredump start");
> + dev_coredumpv(adapter->dev, adapter->devdump_data, adapter->devdump_len,
> + GFP_KERNEL);
> + mwifiex_dbg(adapter, MSG,
> + "== mwifiex dump information to /sys/class/devcoredump end");
> +}
> +EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
> +
> +void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter)
> +{
> + char *p;
> char drv_version[64];
> struct usb_card_rec *cardp;
> struct sdio_mmc_card *sdio_card;
> @@ -1062,17 +1079,12 @@ int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info)
> int i, idx;
> struct netdev_queue *txq;
> struct mwifiex_debug_info *debug_info;
> - void *drv_info_dump;
>
> mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump start===\n");
>
> - /* memory allocate here should be free in mwifiex_upload_device_dump*/
> - drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX);
> -
> - if (!drv_info_dump)
> - return 0;
> -
> - p = (char *)(drv_info_dump);
> + p = adapter->devdump_data;
> + strcpy(p, "========Start dump driverinfo========\n");
> + p += strlen("========Start dump driverinfo========\n");
> p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
>
> mwifiex_drv_get_driver_version(adapter, drv_version,
> @@ -1156,21 +1168,18 @@ int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info)
> kfree(debug_info);
> }
>
> + strcpy(p, "\n========End dump========\n");
> + p += strlen("\n========End dump========\n");
> mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump end===\n");
> - *drv_info = drv_info_dump;
> - return p - drv_info_dump;
> + adapter->devdump_len = p - adapter->devdump_data;
> }
> EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump);
>
> -void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
> - int drv_info_size)
> +void mwifiex_prepare_fw_dump_info(struct mwifiex_adapter *adapter)
> {
> - u8 idx, *dump_data, *fw_dump_ptr;
> - u32 dump_len;
> -
> - dump_len = (strlen("========Start dump driverinfo========\n") +
> - drv_info_size +
> - strlen("\n========End dump========\n"));
> + u8 idx;
> + char *fw_dump_ptr;
> + u32 dump_len = 0;
>
> for (idx = 0; idx < adapter->num_mem_types; idx++) {
> struct memory_type_mapping *entry =
> @@ -1185,24 +1194,24 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
> }
> }
>
> - dump_data = vzalloc(dump_len + 1);
> - if (!dump_data)
> - goto done;
> -
> - fw_dump_ptr = dump_data;
> + if (dump_len + 1 + adapter->devdump_len > MWIFIEX_FW_DUMP_SIZE) {
> + /* Realloc in case buffer overflow */
> + fw_dump_ptr = vzalloc(dump_len + 1 + adapter->devdump_len);
> + mwifiex_dbg(adapter, MSG, "Realloc device dump data.");
> + if (!fw_dump_ptr) {
> + vfree(adapter->devdump_data);
> + mwifiex_dbg(adapter, ERROR,
> + "vzalloc devdump data failure!\n");
> + return;
> + }
>
> - /* Dump all the memory data into single file, a userspace script will
> - * be used to split all the memory data to multiple files
> - */
> - mwifiex_dbg(adapter, MSG,
> - "== mwifiex dump information to /sys/class/devcoredump start");
> + memmove(fw_dump_ptr, adapter->devdump_data,
> + adapter->devdump_len);
> + vfree(adapter->devdump_data);
> + adapter->devdump_data = fw_dump_ptr;
> + }
>
> - strcpy(fw_dump_ptr, "========Start dump driverinfo========\n");
> - fw_dump_ptr += strlen("========Start dump driverinfo========\n");
> - memcpy(fw_dump_ptr, drv_info, drv_info_size);
> - fw_dump_ptr += drv_info_size;
> - strcpy(fw_dump_ptr, "\n========End dump========\n");
> - fw_dump_ptr += strlen("\n========End dump========\n");
> + fw_dump_ptr = adapter->devdump_data + adapter->devdump_len;
>
> for (idx = 0; idx < adapter->num_mem_types; idx++) {
> struct memory_type_mapping *entry =
> @@ -1229,11 +1238,8 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
> /* device dump data will be free in device coredump release function
> * after 5 min
> */
> - dev_coredumpv(adapter->dev, dump_data, dump_len, GFP_KERNEL);
> - mwifiex_dbg(adapter, MSG,
> - "== mwifiex dump information to /sys/class/devcoredump end");
> + adapter->devdump_len = fw_dump_ptr - adapter->devdump_data;
>
> -done:
> for (idx = 0; idx < adapter->num_mem_types; idx++) {
> struct memory_type_mapping *entry =
> &adapter->mem_type_mapping_tbl[idx];
> @@ -1242,10 +1248,8 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
> entry->mem_ptr = NULL;
> entry->mem_size = 0;
> }
> -
> - vfree(drv_info);
> }
> -EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump);
> +EXPORT_SYMBOL_GPL(mwifiex_prepare_fw_dump_info);
>
> /*
> * CFG802.11 network device handler for statistics retrieval.
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
> index 0aaae08..e308b8a 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.h
> +++ b/drivers/net/wireless/marvell/mwifiex/main.h
> @@ -94,6 +94,8 @@ enum {
>
> #define MAX_EVENT_SIZE 2048
>
> +#define MWIFIEX_FW_DUMP_SIZE (2 * 1024 * 1024)
> +
> #define ARP_FILTER_MAX_BUF_SIZE 68
>
> #define MWIFIEX_KEY_BUFFER_SIZE 16
> @@ -1033,6 +1035,9 @@ struct mwifiex_adapter {
> bool wake_by_wifi;
> /* Aggregation parameters*/
> struct bus_aggr_params bus_aggr;
> + /* Device dump data/length */
> + char *devdump_data;
Should be 'void *'.
> + int devdump_len;
I really really don't like you sticking yet another transient piece of
data here. IIUC, you're just admitting that (after the first dump)
you're going to waste 2MB+ of memory forever? Please try harder than
that.
> };
>
> void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
> @@ -1654,9 +1659,9 @@ void mwifiex_hist_data_add(struct mwifiex_private *priv,
> u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
> u8 rx_rate, u8 ht_info);
>
> -int mwifiex_drv_info_dump(struct mwifiex_adapter *adapter, void **drv_info);
> -void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
> - int drv_info_size);
> +void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter);
> +void mwifiex_prepare_fw_dump_info(struct mwifiex_adapter *adapter);
> +void mwifiex_upload_device_dump(unsigned long function_context);
> void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
> void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
> int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action,
> diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
> index cd31494..dbc5944 100644
> --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> @@ -2769,12 +2769,17 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
>
> static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
> {
> - int drv_info_size;
> - void *drv_info;
> + adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
> + if (!adapter->devdump_data) {
> + mwifiex_dbg(adapter, ERROR,
> + "vzalloc devdump data failure!\n");
> + return;
> + }
>
> - drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info);
> + mwifiex_drv_info_dump(adapter);
> mwifiex_pcie_fw_dump(adapter);
> - mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
> + mwifiex_prepare_fw_dump_info(adapter);
> + mwifiex_upload_device_dump((unsigned long)adapter);
How did you manage to make 4 separate function calls into 5 separate
function calls and 1 memory allocation? I'm pretty sure you're going the
wrong direction on this refactoring.
Brian
> }
>
> static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
> diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
> index fd5183c..8010109 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sdio.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
> @@ -2505,15 +2505,21 @@ static void mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter)
> static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter)
> {
> struct sdio_mmc_card *card = adapter->card;
> - int drv_info_size;
> - void *drv_info;
>
> - drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info);
> + adapter->devdump_data = vzalloc(MWIFIEX_FW_DUMP_SIZE);
> + if (!adapter->devdump_data) {
> + mwifiex_dbg(adapter, ERROR,
> + "vzalloc devdump data failure!\n");
> + return;
> + }
> +
> + mwifiex_drv_info_dump(adapter);
> if (card->fw_dump_enh)
> mwifiex_sdio_generic_fw_dump(adapter);
> else
> mwifiex_sdio_fw_dump(adapter);
> - mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
> + mwifiex_prepare_fw_dump_info(adapter);
> + mwifiex_upload_device_dump((unsigned long)adapter);
> }
>
> static void mwifiex_sdio_work(struct work_struct *work)
> --
> 1.9.1
>
Hi,
On Mon, Aug 14, 2017 at 12:19:03PM +0000, Xinming Hu wrote:
> From: Xinming Hu <[email protected]>
>
> This patch extend device_dump debugfs function to make it
> works for usb interface.
>
> Signed-off-by: Xinming Hu <[email protected]>
> Signed-off-by: Cathy Luo <[email protected]>
> Signed-off-by: Ganapathi Bhat <[email protected]>
> ---
> drivers/net/wireless/marvell/mwifiex/cmdevt.c | 11 +++++++----
> drivers/net/wireless/marvell/mwifiex/debugfs.c | 9 +++++----
> drivers/net/wireless/marvell/mwifiex/fw.h | 1 +
> drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 4 ++++
> 4 files changed, 17 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> index 0edc5d6..b16dd6a 100644
> --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
> @@ -290,13 +290,16 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
> adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] =
> get_unaligned_le16((u8 *)host_cmd + S_DS_GEN);
>
> + /* Setup the timer after transmit command, except that specific
> + * command might not have command response.
> + */
> + if (cmd_code != HostCmd_CMD_FW_DUMP_EVENT)
> + mod_timer(&adapter->cmd_timer,
> + jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
> +
> /* Clear BSS_NO_BITS from HostCmd */
> cmd_code &= HostCmd_CMD_ID_MASK;
>
> - /* Setup the timer after transmit command */
> - mod_timer(&adapter->cmd_timer,
> - jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
> -
> return 0;
> }
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
> index 6f4239b..5d476de 100644
> --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
> +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
> @@ -168,10 +168,11 @@
> {
> struct mwifiex_private *priv = file->private_data;
>
> - if (!priv->adapter->if_ops.device_dump)
> - return -EIO;
> -
> - priv->adapter->if_ops.device_dump(priv->adapter);
> + if (priv->adapter->iface_type == MWIFIEX_USB)
> + mwifiex_send_cmd(priv, HostCmd_CMD_FW_DUMP_EVENT,
> + HostCmd_ACT_GEN_SET, 0, NULL, true);
Why couldn't you just implement the device_dump() callback?
> + else
> + priv->adapter->if_ops.device_dump(priv->adapter);
>
> return 0;
> }
> diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
> index 610a3ea..2d3a644 100644
> --- a/drivers/net/wireless/marvell/mwifiex/fw.h
> +++ b/drivers/net/wireless/marvell/mwifiex/fw.h
> @@ -398,6 +398,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
> #define HostCmd_CMD_TDLS_CONFIG 0x0100
> #define HostCmd_CMD_MC_POLICY 0x0121
> #define HostCmd_CMD_TDLS_OPER 0x0122
> +#define HostCmd_CMD_FW_DUMP_EVENT 0x0125
> #define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223
> #define HostCmd_CMD_CHAN_REGION_CFG 0x0242
> #define HostCmd_CMD_PACKET_AGGR_CTRL 0x0251
> diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
> index fb09014..211e47d 100644
> --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
> +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
> @@ -2206,6 +2206,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
> case HostCmd_CMD_CHAN_REGION_CFG:
> ret = mwifiex_cmd_chan_region_cfg(priv, cmd_ptr, cmd_action);
> break;
> + case HostCmd_CMD_FW_DUMP_EVENT:
> + cmd_ptr->command = cpu_to_le16(cmd_no);
> + cmd_ptr->size = cpu_to_le16(S_DS_GEN);
> + break;
> default:
> mwifiex_dbg(priv->adapter, ERROR,
> "PREP_CMD: unknown cmd- %#x\n", cmd_no);
> --
> 1.9.1
>
SGkgQnJpYW4sDQoNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBCcmlh
biBOb3JyaXMgW21haWx0bzpicmlhbm5vcnJpc0BjaHJvbWl1bS5vcmddDQo+IFNlbnQ6IDIwMTfE
6jjUwjE1yNUgNzo0NQ0KPiBUbzogWGlubWluZyBIdSA8aHV4aW5taW5nODIwQGdtYWlsLmNvbT4N
Cj4gQ2M6IExpbnV4IFdpcmVsZXNzIDxsaW51eC13aXJlbGVzc0B2Z2VyLmtlcm5lbC5vcmc+OyBL
YWxsZSBWYWxvDQo+IDxrdmFsb0Bjb2RlYXVyb3JhLm9yZz47IERtaXRyeSBUb3Jva2hvdiA8ZHRv
ckBnb29nbGUuY29tPjsNCj4gcmFqYXRqYUBnb29nbGUuY29tOyBaaGl5dWFuIFlhbmcgPHlhbmd6
eUBtYXJ2ZWxsLmNvbT47IFRpbSBTb25nDQo+IDxzb25ndGFvQG1hcnZlbGwuY29tPjsgQ2F0aHkg
THVvIDxjbHVvQG1hcnZlbGwuY29tPjsgR2FuYXBhdGhpIEJoYXQNCj4gPGdiaGF0QG1hcnZlbGwu
Y29tPjsgWGlubWluZyBIdSA8aHV4bUBtYXJ2ZWxsLmNvbT4NCj4gU3ViamVjdDogW0VYVF0gUmU6
IFtQQVRDSCAxLzNdIG13aWZpZXg6IHJlZmFjdG9yIGRldmljZSBkdW1wIGNvZGUgdG8gbWFrZSBp
dA0KPiBnZW5lcmljIGZvciB1c2IgaW50ZXJmYWNlDQo+IA0KPiBFeHRlcm5hbCBFbWFpbA0KPiAN
Cj4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLQ0KPiBPbiBNb24sIEF1ZyAxNCwgMjAxNyBhdCAxMjoxOTowMVBNICsw
MDAwLCBYaW5taW5nIEh1IHdyb3RlOg0KPiA+IEZyb206IFhpbm1pbmcgSHUgPGh1eG1AbWFydmVs
bC5jb20+DQo+ID4NCj4gPiBUaGlzIHBhdGNoIHJlZmFjdG9yIGN1cnJlbnQgZGV2aWNlIGR1bXAg
Y29kZSB0byBtYWtlIGl0IGdlbmVyaWMgZm9yDQo+ID4gc3Vic2VxdWVudCBpbXBsZW1lbnRhdGlv
biBvbiB1c2IgaW50ZXJmYWNlLg0KPiA+DQo+ID4gU2lnbmVkLW9mZi1ieTogWGlubWluZyBIdSA8
aHV4bUBtYXJ2ZWxsLmNvbT4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBDYXRoeSBMdW8gPGNsdW9AbWFy
dmVsbC5jb20+DQo+ID4gU2lnbmVkLW9mZi1ieTogR2FuYXBhdGhpIEJoYXQgPGdiaGF0QG1hcnZl
bGwuY29tPg0KPiA+IC0tLQ0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZp
ZXgvbWFpbi5jIHwgOTANCj4gPiArKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tLQ0KPiA+IGRy
aXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmggfCAxMSArKystDQo+ID4g
ZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3BjaWUuYyB8IDEzICsrKy0tDQo+
ID4gZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3NkaW8uYyB8IDE0ICsrKy0t
DQo+ID4gIDQgZmlsZXMgY2hhbmdlZCwgNzQgaW5zZXJ0aW9ucygrKSwgNTQgZGVsZXRpb25zKC0p
DQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lm
aWV4L21haW4uYw0KPiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21h
aW4uYw0KPiA+IGluZGV4IGVlNDBiNzMuLjkxOWQ5MWEgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVy
cy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21haW4uYw0KPiA+ICsrKyBiL2RyaXZlcnMv
bmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmMNCj4gPiBAQCAtMTA1Miw5ICsxMDUy
LDI2IEBAIHZvaWQgbXdpZmlleF9tdWx0aV9jaGFuX3Jlc3luYyhzdHJ1Y3QNCj4gPiBtd2lmaWV4
X2FkYXB0ZXIgKmFkYXB0ZXIpICB9DQo+ID4gRVhQT1JUX1NZTUJPTF9HUEwobXdpZmlleF9tdWx0
aV9jaGFuX3Jlc3luYyk7DQo+ID4NCj4gPiAtaW50IG13aWZpZXhfZHJ2X2luZm9fZHVtcChzdHJ1
Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVyLCB2b2lkDQo+ID4gKipkcnZfaW5mbykNCj4gPiAr
dm9pZCBtd2lmaWV4X3VwbG9hZF9kZXZpY2VfZHVtcCh1bnNpZ25lZCBsb25nIGZ1bmN0aW9uX2Nv
bnRleHQpDQo+IA0KPiBNeSBleWVzISBJdCBidXJucyENCj4gDQo+IE1vc3QgY2FsbGVycyBkb24n
dCBuZWVkIHRoZSBjYXN0aW5nLCBzbyB0aGlzIGxvb2tzIHRlcnJpYmx5IHVuc2FmZS4NCj4gUGxl
YXNlIGtlZXAgdGhlIGNhc3RpbmcgdG8gb25seSB3aGVyZSBpdCdzIG5lZWRlZCAoaS5lLiwgaW4g
dGhlIHRpbWVyLXJlbGF0ZWQNCj4gY29kZSkuDQoNCk15IGZhdWx0LCB3aWxsIGNvcnJlY3QgaXQg
aW4gVjIuDQoNCj4gDQo+IEFsc28sIHdoeSBjYW4ndCB0aGUgY2FsbGVyIHBhc3MgaW4gdGhlIGR1
bXAgZGF0YS9sZW4gdmFsdWVzPyBZb3UncmUgbWFraW5nIFBDSWUNCj4gYW5kIFNESU8gbG9vayBl
dmVuIHVnbGllciwganVzdCBiZWNhdXNlIHlvdSBjYW4ndCBmaWd1cmUgb3V0IGhvdyB0byB3cmFw
IHRoaXMNCj4gbmljZWx5IGZvciBVU0IuDQo+IA0KPiBZb3UgbWlnaHQgZG8gYmV0dGVyIHRvIGNv
bnNpZGVyIGhvdyB0byBtYWtlIHRoaXMgbmljZXIgYnkgaW1wbGVtZW50aW5nIGJldHRlcg0KPiBk
cml2ZXIgY2FsbGJhY2tzLCBhbmQgZG9pbmcgbW9zdCBvZiB0aGUgd29yayBpbiB0aGUgY29yZS4N
Cj4gT3ZlcmFsbCwgeW91IHNob3VsZG4ndCBuZWVkIHNvIG1hbnkgZXhwb3J0ZWQgc3ltYm9scy4N
Cj4gDQoNClBsZWFzZSBjaGVjayB0aGUgY29tbWVudHMgYmVsb3cuDQoNCj4gPiAgew0KPiA+IC0J
dm9pZCAqcDsNCj4gPiArCXN0cnVjdCBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIgPQ0KPiA+ICsJ
CShzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyICopZnVuY3Rpb25fY29udGV4dDsNCj4gPiArDQo+ID4g
KwkvKiBEdW1wIGFsbCB0aGUgbWVtb3J5IGRhdGEgaW50byBzaW5nbGUgZmlsZSwgYSB1c2Vyc3Bh
Y2Ugc2NyaXB0IHdpbGwNCj4gPiArCSAqIGJlIHVzZWQgdG8gc3BsaXQgYWxsIHRoZSBtZW1vcnkg
ZGF0YSB0byBtdWx0aXBsZSBmaWxlcw0KPiA+ICsJICovDQo+ID4gKwltd2lmaWV4X2RiZyhhZGFw
dGVyLCBNU0csDQo+ID4gKwkJICAgICI9PSBtd2lmaWV4IGR1bXAgaW5mb3JtYXRpb24gdG8gL3N5
cy9jbGFzcy9kZXZjb3JlZHVtcA0KPiBzdGFydCIpOw0KPiA+ICsJZGV2X2NvcmVkdW1wdihhZGFw
dGVyLT5kZXYsIGFkYXB0ZXItPmRldmR1bXBfZGF0YSwNCj4gYWRhcHRlci0+ZGV2ZHVtcF9sZW4s
DQo+ID4gKwkJICAgICAgR0ZQX0tFUk5FTCk7DQo+ID4gKwltd2lmaWV4X2RiZyhhZGFwdGVyLCBN
U0csDQo+ID4gKwkJICAgICI9PSBtd2lmaWV4IGR1bXAgaW5mb3JtYXRpb24gdG8gL3N5cy9jbGFz
cy9kZXZjb3JlZHVtcA0KPiBlbmQiKTsgfQ0KPiA+ICtFWFBPUlRfU1lNQk9MX0dQTChtd2lmaWV4
X3VwbG9hZF9kZXZpY2VfZHVtcCk7DQo+ID4gKw0KPiA+ICt2b2lkIG13aWZpZXhfZHJ2X2luZm9f
ZHVtcChzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVyKSB7DQo+ID4gKwljaGFyICpwOw0K
PiA+ICAJY2hhciBkcnZfdmVyc2lvbls2NF07DQo+ID4gIAlzdHJ1Y3QgdXNiX2NhcmRfcmVjICpj
YXJkcDsNCj4gPiAgCXN0cnVjdCBzZGlvX21tY19jYXJkICpzZGlvX2NhcmQ7DQo+ID4gQEAgLTEw
NjIsMTcgKzEwNzksMTIgQEAgaW50IG13aWZpZXhfZHJ2X2luZm9fZHVtcChzdHJ1Y3QNCj4gbXdp
ZmlleF9hZGFwdGVyICphZGFwdGVyLCB2b2lkICoqZHJ2X2luZm8pDQo+ID4gIAlpbnQgaSwgaWR4
Ow0KPiA+ICAJc3RydWN0IG5ldGRldl9xdWV1ZSAqdHhxOw0KPiA+ICAJc3RydWN0IG13aWZpZXhf
ZGVidWdfaW5mbyAqZGVidWdfaW5mbzsNCj4gPiAtCXZvaWQgKmRydl9pbmZvX2R1bXA7DQo+ID4N
Cj4gPiAgCW13aWZpZXhfZGJnKGFkYXB0ZXIsIE1TRywgIj09PW13aWZpZXggZHJpdmVyaW5mbyBk
dW1wIHN0YXJ0PT09XG4iKTsNCj4gPg0KPiA+IC0JLyogbWVtb3J5IGFsbG9jYXRlIGhlcmUgc2hv
dWxkIGJlIGZyZWUgaW4gbXdpZmlleF91cGxvYWRfZGV2aWNlX2R1bXAqLw0KPiA+IC0JZHJ2X2lu
Zm9fZHVtcCA9IHZ6YWxsb2MoTVdJRklFWF9EUlZfSU5GT19TSVpFX01BWCk7DQo+ID4gLQ0KPiA+
IC0JaWYgKCFkcnZfaW5mb19kdW1wKQ0KPiA+IC0JCXJldHVybiAwOw0KPiA+IC0NCj4gPiAtCXAg
PSAoY2hhciAqKShkcnZfaW5mb19kdW1wKTsNCj4gPiArCXAgPSBhZGFwdGVyLT5kZXZkdW1wX2Rh
dGE7DQo+ID4gKwlzdHJjcHkocCwgIj09PT09PT09U3RhcnQgZHVtcCBkcml2ZXJpbmZvPT09PT09
PT1cbiIpOw0KPiA+ICsJcCArPSBzdHJsZW4oIj09PT09PT09U3RhcnQgZHVtcCBkcml2ZXJpbmZv
PT09PT09PT1cbiIpOw0KPiA+ICAJcCArPSBzcHJpbnRmKHAsICJkcml2ZXJfbmFtZSA9ICIgIlwi
bXdpZmlleFwiXG4iKTsNCj4gPg0KPiA+ICAJbXdpZmlleF9kcnZfZ2V0X2RyaXZlcl92ZXJzaW9u
KGFkYXB0ZXIsIGRydl92ZXJzaW9uLCBAQCAtMTE1NiwyMQ0KPiA+ICsxMTY4LDE4IEBAIGludCBt
d2lmaWV4X2Rydl9pbmZvX2R1bXAoc3RydWN0IG13aWZpZXhfYWRhcHRlciAqYWRhcHRlciwNCj4g
dm9pZCAqKmRydl9pbmZvKQ0KPiA+ICAJCWtmcmVlKGRlYnVnX2luZm8pOw0KPiA+ICAJfQ0KPiA+
DQo+ID4gKwlzdHJjcHkocCwgIlxuPT09PT09PT1FbmQgZHVtcD09PT09PT09XG4iKTsNCj4gPiAr
CXAgKz0gc3RybGVuKCJcbj09PT09PT09RW5kIGR1bXA9PT09PT09PVxuIik7DQo+ID4gIAltd2lm
aWV4X2RiZyhhZGFwdGVyLCBNU0csICI9PT1td2lmaWV4IGRyaXZlcmluZm8gZHVtcCBlbmQ9PT1c
biIpOw0KPiA+IC0JKmRydl9pbmZvID0gZHJ2X2luZm9fZHVtcDsNCj4gPiAtCXJldHVybiBwIC0g
ZHJ2X2luZm9fZHVtcDsNCj4gPiArCWFkYXB0ZXItPmRldmR1bXBfbGVuID0gcCAtIGFkYXB0ZXIt
PmRldmR1bXBfZGF0YTsNCj4gPiAgfQ0KPiA+ICBFWFBPUlRfU1lNQk9MX0dQTChtd2lmaWV4X2Ry
dl9pbmZvX2R1bXApOw0KPiA+DQo+ID4gLXZvaWQgbXdpZmlleF91cGxvYWRfZGV2aWNlX2R1bXAo
c3RydWN0IG13aWZpZXhfYWRhcHRlciAqYWRhcHRlciwgdm9pZA0KPiAqZHJ2X2luZm8sDQo+ID4g
LQkJCQlpbnQgZHJ2X2luZm9fc2l6ZSkNCj4gPiArdm9pZCBtd2lmaWV4X3ByZXBhcmVfZndfZHVt
cF9pbmZvKHN0cnVjdCBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIpDQo+ID4gIHsNCj4gPiAtCXU4
IGlkeCwgKmR1bXBfZGF0YSwgKmZ3X2R1bXBfcHRyOw0KPiA+IC0JdTMyIGR1bXBfbGVuOw0KPiA+
IC0NCj4gPiAtCWR1bXBfbGVuID0gKHN0cmxlbigiPT09PT09PT1TdGFydCBkdW1wIGRyaXZlcmlu
Zm89PT09PT09PVxuIikgKw0KPiA+IC0JCSAgICAgICBkcnZfaW5mb19zaXplICsNCj4gPiAtCQkg
ICAgICAgc3RybGVuKCJcbj09PT09PT09RW5kIGR1bXA9PT09PT09PVxuIikpOw0KPiA+ICsJdTgg
aWR4Ow0KPiA+ICsJY2hhciAqZndfZHVtcF9wdHI7DQo+ID4gKwl1MzIgZHVtcF9sZW4gPSAwOw0K
PiA+DQo+ID4gIAlmb3IgKGlkeCA9IDA7IGlkeCA8IGFkYXB0ZXItPm51bV9tZW1fdHlwZXM7IGlk
eCsrKSB7DQo+ID4gIAkJc3RydWN0IG1lbW9yeV90eXBlX21hcHBpbmcgKmVudHJ5ID0gQEAgLTEx
ODUsMjQgKzExOTQsMjQgQEANCj4gdm9pZA0KPiA+IG13aWZpZXhfdXBsb2FkX2RldmljZV9kdW1w
KHN0cnVjdCBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIsIHZvaWQNCj4gKmRydl9pbmZvLA0KPiA+
ICAJCX0NCj4gPiAgCX0NCj4gPg0KPiA+IC0JZHVtcF9kYXRhID0gdnphbGxvYyhkdW1wX2xlbiAr
IDEpOw0KPiA+IC0JaWYgKCFkdW1wX2RhdGEpDQo+ID4gLQkJZ290byBkb25lOw0KPiA+IC0NCj4g
PiAtCWZ3X2R1bXBfcHRyID0gZHVtcF9kYXRhOw0KPiA+ICsJaWYgKGR1bXBfbGVuICsgMSArIGFk
YXB0ZXItPmRldmR1bXBfbGVuID4gTVdJRklFWF9GV19EVU1QX1NJWkUpIHsNCj4gPiArCQkvKiBS
ZWFsbG9jIGluIGNhc2UgYnVmZmVyIG92ZXJmbG93ICovDQo+ID4gKwkJZndfZHVtcF9wdHIgPSB2
emFsbG9jKGR1bXBfbGVuICsgMSArIGFkYXB0ZXItPmRldmR1bXBfbGVuKTsNCj4gPiArCQltd2lm
aWV4X2RiZyhhZGFwdGVyLCBNU0csICJSZWFsbG9jIGRldmljZSBkdW1wIGRhdGEuIik7DQo+ID4g
KwkJaWYgKCFmd19kdW1wX3B0cikgew0KPiA+ICsJCQl2ZnJlZShhZGFwdGVyLT5kZXZkdW1wX2Rh
dGEpOw0KPiA+ICsJCQltd2lmaWV4X2RiZyhhZGFwdGVyLCBFUlJPUiwNCj4gPiArCQkJCSAgICAi
dnphbGxvYyBkZXZkdW1wIGRhdGEgZmFpbHVyZSFcbiIpOw0KPiA+ICsJCQlyZXR1cm47DQo+ID4g
KwkJfQ0KPiA+DQo+ID4gLQkvKiBEdW1wIGFsbCB0aGUgbWVtb3J5IGRhdGEgaW50byBzaW5nbGUg
ZmlsZSwgYSB1c2Vyc3BhY2Ugc2NyaXB0IHdpbGwNCj4gPiAtCSAqIGJlIHVzZWQgdG8gc3BsaXQg
YWxsIHRoZSBtZW1vcnkgZGF0YSB0byBtdWx0aXBsZSBmaWxlcw0KPiA+IC0JICovDQo+ID4gLQlt
d2lmaWV4X2RiZyhhZGFwdGVyLCBNU0csDQo+ID4gLQkJICAgICI9PSBtd2lmaWV4IGR1bXAgaW5m
b3JtYXRpb24gdG8gL3N5cy9jbGFzcy9kZXZjb3JlZHVtcA0KPiBzdGFydCIpOw0KPiA+ICsJCW1l
bW1vdmUoZndfZHVtcF9wdHIsIGFkYXB0ZXItPmRldmR1bXBfZGF0YSwNCj4gPiArCQkJYWRhcHRl
ci0+ZGV2ZHVtcF9sZW4pOw0KPiA+ICsJCXZmcmVlKGFkYXB0ZXItPmRldmR1bXBfZGF0YSk7DQo+
ID4gKwkJYWRhcHRlci0+ZGV2ZHVtcF9kYXRhID0gZndfZHVtcF9wdHI7DQo+ID4gKwl9DQo+ID4N
Cj4gPiAtCXN0cmNweShmd19kdW1wX3B0ciwgIj09PT09PT09U3RhcnQgZHVtcCBkcml2ZXJpbmZv
PT09PT09PT1cbiIpOw0KPiA+IC0JZndfZHVtcF9wdHIgKz0gc3RybGVuKCI9PT09PT09PVN0YXJ0
IGR1bXAgZHJpdmVyaW5mbz09PT09PT09XG4iKTsNCj4gPiAtCW1lbWNweShmd19kdW1wX3B0ciwg
ZHJ2X2luZm8sIGRydl9pbmZvX3NpemUpOw0KPiA+IC0JZndfZHVtcF9wdHIgKz0gZHJ2X2luZm9f
c2l6ZTsNCj4gPiAtCXN0cmNweShmd19kdW1wX3B0ciwgIlxuPT09PT09PT1FbmQgZHVtcD09PT09
PT09XG4iKTsNCj4gPiAtCWZ3X2R1bXBfcHRyICs9IHN0cmxlbigiXG49PT09PT09PUVuZCBkdW1w
PT09PT09PT1cbiIpOw0KPiA+ICsJZndfZHVtcF9wdHIgPSBhZGFwdGVyLT5kZXZkdW1wX2RhdGEg
KyBhZGFwdGVyLT5kZXZkdW1wX2xlbjsNCj4gPg0KPiA+ICAJZm9yIChpZHggPSAwOyBpZHggPCBh
ZGFwdGVyLT5udW1fbWVtX3R5cGVzOyBpZHgrKykgew0KPiA+ICAJCXN0cnVjdCBtZW1vcnlfdHlw
ZV9tYXBwaW5nICplbnRyeSA9IEBAIC0xMjI5LDExICsxMjM4LDggQEANCj4gdm9pZA0KPiA+IG13
aWZpZXhfdXBsb2FkX2RldmljZV9kdW1wKHN0cnVjdCBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIs
IHZvaWQNCj4gKmRydl9pbmZvLA0KPiA+ICAJLyogZGV2aWNlIGR1bXAgZGF0YSB3aWxsIGJlIGZy
ZWUgaW4gZGV2aWNlIGNvcmVkdW1wIHJlbGVhc2UgZnVuY3Rpb24NCj4gPiAgCSAqIGFmdGVyIDUg
bWluDQo+ID4gIAkgKi8NCj4gPiAtCWRldl9jb3JlZHVtcHYoYWRhcHRlci0+ZGV2LCBkdW1wX2Rh
dGEsIGR1bXBfbGVuLCBHRlBfS0VSTkVMKTsNCj4gPiAtCW13aWZpZXhfZGJnKGFkYXB0ZXIsIE1T
RywNCj4gPiAtCQkgICAgIj09IG13aWZpZXggZHVtcCBpbmZvcm1hdGlvbiB0byAvc3lzL2NsYXNz
L2RldmNvcmVkdW1wIGVuZCIpOw0KPiA+ICsJYWRhcHRlci0+ZGV2ZHVtcF9sZW4gPSBmd19kdW1w
X3B0ciAtIGFkYXB0ZXItPmRldmR1bXBfZGF0YTsNCj4gPg0KPiA+IC1kb25lOg0KPiA+ICAJZm9y
IChpZHggPSAwOyBpZHggPCBhZGFwdGVyLT5udW1fbWVtX3R5cGVzOyBpZHgrKykgew0KPiA+ICAJ
CXN0cnVjdCBtZW1vcnlfdHlwZV9tYXBwaW5nICplbnRyeSA9DQo+ID4gIAkJCSZhZGFwdGVyLT5t
ZW1fdHlwZV9tYXBwaW5nX3RibFtpZHhdOw0KPiA+IEBAIC0xMjQyLDEwICsxMjQ4LDggQEAgdm9p
ZCBtd2lmaWV4X3VwbG9hZF9kZXZpY2VfZHVtcChzdHJ1Y3QNCj4gbXdpZmlleF9hZGFwdGVyICph
ZGFwdGVyLCB2b2lkICpkcnZfaW5mbywNCj4gPiAgCQllbnRyeS0+bWVtX3B0ciA9IE5VTEw7DQo+
ID4gIAkJZW50cnktPm1lbV9zaXplID0gMDsNCj4gPiAgCX0NCj4gPiAtDQo+ID4gLQl2ZnJlZShk
cnZfaW5mbyk7DQo+ID4gIH0NCj4gPiAtRVhQT1JUX1NZTUJPTF9HUEwobXdpZmlleF91cGxvYWRf
ZGV2aWNlX2R1bXApOw0KPiA+ICtFWFBPUlRfU1lNQk9MX0dQTChtd2lmaWV4X3ByZXBhcmVfZndf
ZHVtcF9pbmZvKTsNCj4gPg0KPiA+ICAvKg0KPiA+ICAgKiBDRkc4MDIuMTEgbmV0d29yayBkZXZp
Y2UgaGFuZGxlciBmb3Igc3RhdGlzdGljcyByZXRyaWV2YWwuDQo+ID4gZGlmZiAtLWdpdCBhL2Ry
aXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmgNCj4gPiBiL2RyaXZlcnMv
bmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmgNCj4gPiBpbmRleCAwYWFhZTA4Li5l
MzA4YjhhIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdp
ZmlleC9tYWluLmgNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZp
ZXgvbWFpbi5oDQo+ID4gQEAgLTk0LDYgKzk0LDggQEAgZW51bSB7DQo+ID4NCj4gPiAgI2RlZmlu
ZSBNQVhfRVZFTlRfU0laRSAgICAgICAgICAgICAgICAgIDIwNDgNCj4gPg0KPiA+ICsjZGVmaW5l
IE1XSUZJRVhfRldfRFVNUF9TSVpFICAgICAgICgyICogMTAyNCAqIDEwMjQpDQo+ID4gKw0KPiA+
ICAjZGVmaW5lIEFSUF9GSUxURVJfTUFYX0JVRl9TSVpFICAgICAgICAgNjgNCj4gPg0KPiA+ICAj
ZGVmaW5lIE1XSUZJRVhfS0VZX0JVRkZFUl9TSVpFCQkJMTYNCj4gPiBAQCAtMTAzMyw2ICsxMDM1
LDkgQEAgc3RydWN0IG13aWZpZXhfYWRhcHRlciB7DQo+ID4gIAlib29sIHdha2VfYnlfd2lmaTsN
Cj4gPiAgCS8qIEFnZ3JlZ2F0aW9uIHBhcmFtZXRlcnMqLw0KPiA+ICAJc3RydWN0IGJ1c19hZ2dy
X3BhcmFtcyBidXNfYWdncjsNCj4gPiArCS8qIERldmljZSBkdW1wIGRhdGEvbGVuZ3RoICovDQo+
ID4gKwljaGFyICpkZXZkdW1wX2RhdGE7DQo+IA0KPiBTaG91bGQgYmUgJ3ZvaWQgKicuDQoNCk9r
Lg0KDQo+IA0KPiA+ICsJaW50IGRldmR1bXBfbGVuOw0KPiANCj4gSSByZWFsbHkgcmVhbGx5IGRv
bid0IGxpa2UgeW91IHN0aWNraW5nIHlldCBhbm90aGVyIHRyYW5zaWVudCBwaWVjZSBvZiBkYXRh
IGhlcmUuDQo+IElJVUMsIHlvdSdyZSBqdXN0IGFkbWl0dGluZyB0aGF0IChhZnRlciB0aGUgZmly
c3QgZHVtcCkgeW91J3JlIGdvaW5nIHRvIHdhc3RlDQo+IDJNQisgb2YgbWVtb3J5IGZvcmV2ZXI/
IFBsZWFzZSB0cnkgaGFyZGVyIHRoYW4gdGhhdC4NCj4gDQoNClNvcnJ5LCB0aGUgZGV2ZHVtcF9s
ZW4gc2hvdWxkIGJlIHJlc2V0IGR1cmluZyBzb2Z0d2FyZSBpbml0aXphdGlvbi4NCg0KPiA+ICB9
Ow0KPiA+DQo+ID4gIHZvaWQgbXdpZmlleF9wcm9jZXNzX3R4X3F1ZXVlKHN0cnVjdCBtd2lmaWV4
X2FkYXB0ZXIgKmFkYXB0ZXIpOyBAQA0KPiA+IC0xNjU0LDkgKzE2NTksOSBAQCB2b2lkIG13aWZp
ZXhfaGlzdF9kYXRhX2FkZChzdHJ1Y3QgbXdpZmlleF9wcml2YXRlDQo+ID4gKnByaXYsDQo+ID4g
IHU4IG13aWZpZXhfYWRqdXN0X2RhdGFfcmF0ZShzdHJ1Y3QgbXdpZmlleF9wcml2YXRlICpwcml2
LA0KPiA+ICAJCQkgICAgdTggcnhfcmF0ZSwgdTggaHRfaW5mbyk7DQo+ID4NCj4gPiAtaW50IG13
aWZpZXhfZHJ2X2luZm9fZHVtcChzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVyLCB2b2lk
DQo+ID4gKipkcnZfaW5mbyk7IC12b2lkIG13aWZpZXhfdXBsb2FkX2RldmljZV9kdW1wKHN0cnVj
dCBtd2lmaWV4X2FkYXB0ZXINCj4gKmFkYXB0ZXIsIHZvaWQgKmRydl9pbmZvLA0KPiA+IC0JCQkJ
aW50IGRydl9pbmZvX3NpemUpOw0KPiA+ICt2b2lkIG13aWZpZXhfZHJ2X2luZm9fZHVtcChzdHJ1
Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVyKTsgdm9pZA0KPiA+ICttd2lmaWV4X3ByZXBhcmVf
ZndfZHVtcF9pbmZvKHN0cnVjdCBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIpOyB2b2lkDQo+ID4g
K213aWZpZXhfdXBsb2FkX2RldmljZV9kdW1wKHVuc2lnbmVkIGxvbmcgZnVuY3Rpb25fY29udGV4
dCk7DQo+ID4gIHZvaWQgKm13aWZpZXhfYWxsb2NfZG1hX2FsaWduX2J1ZihpbnQgcnhfbGVuLCBn
ZnBfdCBmbGFncyk7ICB2b2lkDQo+ID4gbXdpZmlleF9xdWV1ZV9tYWluX3dvcmsoc3RydWN0IG13
aWZpZXhfYWRhcHRlciAqYWRhcHRlcik7ICBpbnQNCj4gPiBtd2lmaWV4X2dldF93YWtldXBfcmVh
c29uKHN0cnVjdCBtd2lmaWV4X3ByaXZhdGUgKnByaXYsIHUxNiBhY3Rpb24sDQo+ID4gZGlmZiAt
LWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9wY2llLmMNCj4gPiBi
L2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9wY2llLmMNCj4gPiBpbmRleCBj
ZDMxNDk0Li5kYmM1OTQ0IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21h
cnZlbGwvbXdpZmlleC9wY2llLmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2
ZWxsL213aWZpZXgvcGNpZS5jDQo+ID4gQEAgLTI3NjksMTIgKzI3NjksMTcgQEAgc3RhdGljIHZv
aWQgbXdpZmlleF9wY2llX2Z3X2R1bXAoc3RydWN0DQo+ID4gbXdpZmlleF9hZGFwdGVyICphZGFw
dGVyKQ0KPiA+DQo+ID4gIHN0YXRpYyB2b2lkIG13aWZpZXhfcGNpZV9kZXZpY2VfZHVtcF93b3Jr
KHN0cnVjdCBtd2lmaWV4X2FkYXB0ZXINCj4gPiAqYWRhcHRlcikgIHsNCj4gPiAtCWludCBkcnZf
aW5mb19zaXplOw0KPiA+IC0Jdm9pZCAqZHJ2X2luZm87DQo+ID4gKwlhZGFwdGVyLT5kZXZkdW1w
X2RhdGEgPSB2emFsbG9jKE1XSUZJRVhfRldfRFVNUF9TSVpFKTsNCj4gPiArCWlmICghYWRhcHRl
ci0+ZGV2ZHVtcF9kYXRhKSB7DQo+ID4gKwkJbXdpZmlleF9kYmcoYWRhcHRlciwgRVJST1IsDQo+
ID4gKwkJCSAgICAidnphbGxvYyBkZXZkdW1wIGRhdGEgZmFpbHVyZSFcbiIpOw0KPiA+ICsJCXJl
dHVybjsNCj4gPiArCX0NCj4gPg0KPiA+IC0JZHJ2X2luZm9fc2l6ZSA9IG13aWZpZXhfZHJ2X2lu
Zm9fZHVtcChhZGFwdGVyLCAmZHJ2X2luZm8pOw0KPiA+ICsJbXdpZmlleF9kcnZfaW5mb19kdW1w
KGFkYXB0ZXIpOw0KPiA+ICAJbXdpZmlleF9wY2llX2Z3X2R1bXAoYWRhcHRlcik7DQo+ID4gLQlt
d2lmaWV4X3VwbG9hZF9kZXZpY2VfZHVtcChhZGFwdGVyLCBkcnZfaW5mbywgZHJ2X2luZm9fc2l6
ZSk7DQo+ID4gKwltd2lmaWV4X3ByZXBhcmVfZndfZHVtcF9pbmZvKGFkYXB0ZXIpOw0KPiA+ICsJ
bXdpZmlleF91cGxvYWRfZGV2aWNlX2R1bXAoKHVuc2lnbmVkIGxvbmcpYWRhcHRlcik7DQo+IA0K
PiBIb3cgZGlkIHlvdSBtYW5hZ2UgdG8gbWFrZSA0IHNlcGFyYXRlIGZ1bmN0aW9uIGNhbGxzIGlu
dG8gNSBzZXBhcmF0ZSBmdW5jdGlvbg0KPiBjYWxscyBhbmQgMSBtZW1vcnkgYWxsb2NhdGlvbj8g
SSdtIHByZXR0eSBzdXJlIHlvdSdyZSBnb2luZyB0aGUgd3JvbmcgZGlyZWN0aW9uDQo+IG9uIHRo
aXMgcmVmYWN0b3JpbmcuDQo+IA0KDQpUaGUgdXNiIGZpcm13YXJlIGR1bXAgbWVjaGFuaXNtIGlz
IGRpZmZlcmVudCBmcm9tIGN1cnJlbnQgcGNpZS9zZGlvIGltcGxlbWVudGF0aW9uLCB0aGUgY29u
dGV4dCBpcyB1cGxvYWRlZCBpbiBtdWx0aXBsZSBGV19EVU1QX0lORk8oMHg3MykgZXZlbnQuDQpV
cG9uIHJlY2VpdmluZyBlYWNoIGV2ZW50LCBuZWVkIHBhc3RlIHRoZSBjb250ZXh0IHRvIGVuZCBv
ZiBwcmV2aW91cyBjb2xsZWN0ZWQgZXZlbnQgZHVtcHMuDQoNClRodXMgd2UgbmVlZCBhZGFwdGVy
LT5kZXZkdW1wX2RhdGEvZGV2ZHVtcF9sZW4gdG8gcmVwcmVzZW50IHRoZSBjdXJyZW50IGxvY2F0
aW9uIG9mIGV4aXN0IGR1bXAgbWVtb3J5Lg0KDQpUaGVyZWZvcmUgd2UgY2FuIHVzZSBhIHVuaWZp
ZWQgd2F5IGZvciBhbGwgaW50ZXJmYWNlcywgYW5kIHNpbXBsaWZ5IHRoZSBleGlzdCBQQ0lFL1NE
SU8gZHVtcCBmdW5jdGlvbiwgd2UgZG8gbm90IG5lZWQgdG8gYWxsb2NhdGUgImRydl9pbmZvIiBu
b3cuDQoNCkFsc28sIHRoZXJlIGlzIG5vIG1lbW9yeSByZWdpb24gdGFibGUgZm9yIFVTQiBpbnRl
cmZhY2UsIHNvIHRyeSB0byBzcGxpdCBjdXJyZW50IG13aWZpZXhfdXBsb2FkX2RldmljZV9kdW1w
IGZ1bmN0aW9uIHRvDQooMSkgbXdpZmlleF9wcmVwYXJlX2Z3X2R1bXA6ICAgICBjb3B5IHRoZSBk
dW1wIG9mIGVhY2ggbWVtb3J5IHJlZ2lvbiB0byBhZGFwdGVyLT5kZXZkdW1wX2RhdGEsICAgdGhp
cyBpcyB1c2VkIGluIFNESU8gYW5kIFBDSUUNCigyKSBtd2lmaWV4X3VwbG9hZF9kZXZpY2VfZHVt
cAkJY2FsbCBkZXZjb3JlZHVtcCBBUEkgdG8gdXBsb2FkIHRvIHN5c2ZzCSwJCXRoaXMgaXMgdXNl
ZCBpbiBTRElPL1BDSUUgYW5kIFVTQg0KDQpTb3JyeSBmb3IgdGhlIGxhdGVyIHJlc3BvbnNlLCBw
bGVhc2UgbGV0IHVzIGtub3cgeW91ciBzdWdnZXN0aW9ucyBpZiB0aGVyZSBhcmUgYW55IGlzc3Vl
cy4NCg0KPiBCcmlhbg0KPiANCj4gPiAgfQ0KPiA+DQo+ID4gIHN0YXRpYyB2b2lkIG13aWZpZXhf
cGNpZV9jYXJkX3Jlc2V0X3dvcmsoc3RydWN0IG13aWZpZXhfYWRhcHRlcg0KPiA+ICphZGFwdGVy
KSBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3NkaW8u
Yw0KPiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3NkaW8uYw0KPiA+
IGluZGV4IGZkNTE4M2MuLjgwMTAxMDkgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2ly
ZWxlc3MvbWFydmVsbC9td2lmaWV4L3NkaW8uYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVs
ZXNzL21hcnZlbGwvbXdpZmlleC9zZGlvLmMNCj4gPiBAQCAtMjUwNSwxNSArMjUwNSwyMSBAQCBz
dGF0aWMgdm9pZA0KPiA+IG13aWZpZXhfc2Rpb19nZW5lcmljX2Z3X2R1bXAoc3RydWN0IG13aWZp
ZXhfYWRhcHRlciAqYWRhcHRlcikgIHN0YXRpYw0KPiA+IHZvaWQgbXdpZmlleF9zZGlvX2Rldmlj
ZV9kdW1wX3dvcmsoc3RydWN0IG13aWZpZXhfYWRhcHRlciAqYWRhcHRlcikgIHsNCj4gPiAgCXN0
cnVjdCBzZGlvX21tY19jYXJkICpjYXJkID0gYWRhcHRlci0+Y2FyZDsNCj4gPiAtCWludCBkcnZf
aW5mb19zaXplOw0KPiA+IC0Jdm9pZCAqZHJ2X2luZm87DQo+ID4NCj4gPiAtCWRydl9pbmZvX3Np
emUgPSBtd2lmaWV4X2Rydl9pbmZvX2R1bXAoYWRhcHRlciwgJmRydl9pbmZvKTsNCj4gPiArCWFk
YXB0ZXItPmRldmR1bXBfZGF0YSA9IHZ6YWxsb2MoTVdJRklFWF9GV19EVU1QX1NJWkUpOw0KPiA+
ICsJaWYgKCFhZGFwdGVyLT5kZXZkdW1wX2RhdGEpIHsNCj4gPiArCQltd2lmaWV4X2RiZyhhZGFw
dGVyLCBFUlJPUiwNCj4gPiArCQkJICAgICJ2emFsbG9jIGRldmR1bXAgZGF0YSBmYWlsdXJlIVxu
Iik7DQo+ID4gKwkJcmV0dXJuOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCW13aWZpZXhfZHJ2X2lu
Zm9fZHVtcChhZGFwdGVyKTsNCj4gPiAgCWlmIChjYXJkLT5md19kdW1wX2VuaCkNCj4gPiAgCQlt
d2lmaWV4X3NkaW9fZ2VuZXJpY19md19kdW1wKGFkYXB0ZXIpOw0KPiA+ICAJZWxzZQ0KPiA+ICAJ
CW13aWZpZXhfc2Rpb19md19kdW1wKGFkYXB0ZXIpOw0KPiA+IC0JbXdpZmlleF91cGxvYWRfZGV2
aWNlX2R1bXAoYWRhcHRlciwgZHJ2X2luZm8sIGRydl9pbmZvX3NpemUpOw0KPiA+ICsJbXdpZmll
eF9wcmVwYXJlX2Z3X2R1bXBfaW5mbyhhZGFwdGVyKTsNCj4gPiArCW13aWZpZXhfdXBsb2FkX2Rl
dmljZV9kdW1wKCh1bnNpZ25lZCBsb25nKWFkYXB0ZXIpOw0KPiA+ICB9DQo+ID4NCj4gPiAgc3Rh
dGljIHZvaWQgbXdpZmlleF9zZGlvX3dvcmsoc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQ0KPiA+
IC0tDQo+ID4gMS45LjENCj4gPg0K
SGkgQnJpYW4sDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQnJpYW4g
Tm9ycmlzIFttYWlsdG86YnJpYW5ub3JyaXNAY2hyb21pdW0ub3JnXQ0KPiBTZW50OiAyMDE3xOo4
1MIxNcjVIDc6NDkNCj4gVG86IFhpbm1pbmcgSHUgPGh1eGlubWluZzgyMEBnbWFpbC5jb20+DQo+
IENjOiBMaW51eCBXaXJlbGVzcyA8bGludXgtd2lyZWxlc3NAdmdlci5rZXJuZWwub3JnPjsgS2Fs
bGUgVmFsbw0KPiA8a3ZhbG9AY29kZWF1cm9yYS5vcmc+OyBEbWl0cnkgVG9yb2tob3YgPGR0b3JA
Z29vZ2xlLmNvbT47DQo+IHJhamF0amFAZ29vZ2xlLmNvbTsgWmhpeXVhbiBZYW5nIDx5YW5nenlA
bWFydmVsbC5jb20+OyBUaW0gU29uZw0KPiA8c29uZ3Rhb0BtYXJ2ZWxsLmNvbT47IENhdGh5IEx1
byA8Y2x1b0BtYXJ2ZWxsLmNvbT47IEdhbmFwYXRoaSBCaGF0DQo+IDxnYmhhdEBtYXJ2ZWxsLmNv
bT47IFhpbm1pbmcgSHUgPGh1eG1AbWFydmVsbC5jb20+DQo+IFN1YmplY3Q6IFtFWFRdIFJlOiBb
UEFUQ0ggMy8zXSBtd2lmaWV4OiBkZWJ1Z2ZzOiB0cmlnZ2VyIGRldmljZSBkdW1wIGZvciB1c2IN
Cj4gaW50ZXJmYWNlDQo+IA0KPiBFeHRlcm5hbCBFbWFpbA0KPiANCj4gLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0K
PiBIaSwNCj4gDQo+IE9uIE1vbiwgQXVnIDE0LCAyMDE3IGF0IDEyOjE5OjAzUE0gKzAwMDAsIFhp
bm1pbmcgSHUgd3JvdGU6DQo+ID4gRnJvbTogWGlubWluZyBIdSA8aHV4bUBtYXJ2ZWxsLmNvbT4N
Cj4gPg0KPiA+IFRoaXMgcGF0Y2ggZXh0ZW5kIGRldmljZV9kdW1wIGRlYnVnZnMgZnVuY3Rpb24g
dG8gbWFrZSBpdCB3b3JrcyBmb3INCj4gPiB1c2IgaW50ZXJmYWNlLg0KPiA+DQo+ID4gU2lnbmVk
LW9mZi1ieTogWGlubWluZyBIdSA8aHV4bUBtYXJ2ZWxsLmNvbT4NCj4gPiBTaWduZWQtb2ZmLWJ5
OiBDYXRoeSBMdW8gPGNsdW9AbWFydmVsbC5jb20+DQo+ID4gU2lnbmVkLW9mZi1ieTogR2FuYXBh
dGhpIEJoYXQgPGdiaGF0QG1hcnZlbGwuY29tPg0KPiA+IC0tLQ0KPiA+ICBkcml2ZXJzL25ldC93
aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvY21kZXZ0LmMgIHwgMTEgKysrKysrKy0tLS0NCj4gPiBk
cml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvZGVidWdmcy5jIHwgIDkgKysrKyst
LS0tDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9mdy5oICAgICAg
fCAgMSArDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9zdGFfY21k
LmMgfCAgNCArKysrDQo+ID4gIDQgZmlsZXMgY2hhbmdlZCwgMTcgaW5zZXJ0aW9ucygrKSwgOCBk
ZWxldGlvbnMoLSkNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9t
YXJ2ZWxsL213aWZpZXgvY21kZXZ0LmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZl
bGwvbXdpZmlleC9jbWRldnQuYw0KPiA+IGluZGV4IDBlZGM1ZDYuLmIxNmRkNmEgMTAwNjQ0DQo+
ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L2NtZGV2dC5jDQo+
ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L2NtZGV2dC5jDQo+
ID4gQEAgLTI5MCwxMyArMjkwLDE2IEBAIHN0YXRpYyBpbnQgbXdpZmlleF9kbmxkX2NtZF90b19m
dyhzdHJ1Y3QNCj4gbXdpZmlleF9wcml2YXRlICpwcml2LA0KPiA+ICAJYWRhcHRlci0+ZGJnLmxh
c3RfY21kX2FjdFthZGFwdGVyLT5kYmcubGFzdF9jbWRfaW5kZXhdID0NCj4gPiAgCQkJZ2V0X3Vu
YWxpZ25lZF9sZTE2KCh1OCAqKWhvc3RfY21kICsgU19EU19HRU4pOw0KPiA+DQo+ID4gKwkvKiBT
ZXR1cCB0aGUgdGltZXIgYWZ0ZXIgdHJhbnNtaXQgY29tbWFuZCwgZXhjZXB0IHRoYXQgc3BlY2lm
aWMNCj4gPiArCSAqIGNvbW1hbmQgbWlnaHQgbm90IGhhdmUgY29tbWFuZCByZXNwb25zZS4NCj4g
PiArCSAqLw0KPiA+ICsJaWYgKGNtZF9jb2RlICE9IEhvc3RDbWRfQ01EX0ZXX0RVTVBfRVZFTlQp
DQo+ID4gKwkJbW9kX3RpbWVyKCZhZGFwdGVyLT5jbWRfdGltZXIsDQo+ID4gKwkJCSAgamlmZmll
cyArIG1zZWNzX3RvX2ppZmZpZXMoTVdJRklFWF9USU1FUl8xMFMpKTsNCj4gPiArDQo+ID4gIAkv
KiBDbGVhciBCU1NfTk9fQklUUyBmcm9tIEhvc3RDbWQgKi8NCj4gPiAgCWNtZF9jb2RlICY9IEhv
c3RDbWRfQ01EX0lEX01BU0s7DQo+ID4NCj4gPiAtCS8qIFNldHVwIHRoZSB0aW1lciBhZnRlciB0
cmFuc21pdCBjb21tYW5kICovDQo+ID4gLQltb2RfdGltZXIoJmFkYXB0ZXItPmNtZF90aW1lciwN
Cj4gPiAtCQkgIGppZmZpZXMgKyBtc2Vjc190b19qaWZmaWVzKE1XSUZJRVhfVElNRVJfMTBTKSk7
DQo+ID4gLQ0KPiA+ICAJcmV0dXJuIDA7DQo+ID4gIH0NCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9k
cml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvZGVidWdmcy5jDQo+ID4gYi9kcml2
ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvZGVidWdmcy5jDQo+ID4gaW5kZXggNmY0
MjM5Yi4uNWQ0NzZkZSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2
ZWxsL213aWZpZXgvZGVidWdmcy5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFy
dmVsbC9td2lmaWV4L2RlYnVnZnMuYw0KPiA+IEBAIC0xNjgsMTAgKzE2OCwxMSBAQA0KPiA+ICB7
DQo+ID4gIAlzdHJ1Y3QgbXdpZmlleF9wcml2YXRlICpwcml2ID0gZmlsZS0+cHJpdmF0ZV9kYXRh
Ow0KPiA+DQo+ID4gLQlpZiAoIXByaXYtPmFkYXB0ZXItPmlmX29wcy5kZXZpY2VfZHVtcCkNCj4g
PiAtCQlyZXR1cm4gLUVJTzsNCj4gPiAtDQo+ID4gLQlwcml2LT5hZGFwdGVyLT5pZl9vcHMuZGV2
aWNlX2R1bXAocHJpdi0+YWRhcHRlcik7DQo+ID4gKwlpZiAocHJpdi0+YWRhcHRlci0+aWZhY2Vf
dHlwZSA9PSBNV0lGSUVYX1VTQikNCj4gPiArCQltd2lmaWV4X3NlbmRfY21kKHByaXYsIEhvc3RD
bWRfQ01EX0ZXX0RVTVBfRVZFTlQsDQo+ID4gKwkJCQkgSG9zdENtZF9BQ1RfR0VOX1NFVCwgMCwg
TlVMTCwgdHJ1ZSk7DQo+IA0KPiBXaHkgY291bGRuJ3QgeW91IGp1c3QgaW1wbGVtZW50IHRoZSBk
ZXZpY2VfZHVtcCgpIGNhbGxiYWNrPw0KDQpDdXJyZW50bHkgbXdpZmlleF9zZW5kX2NtZCBmdW5j
dGlvbiBpcyBub3QgZXhwb3J0ZWQgdG8gZXh0ZXJuYWwgbW9kdWxlcywgaXQgaXMgZGVzaWduZWQg
Zm9yIG1vZHVsZSBtd2lmaWV4IGludGVybmFsIHVzZS4NCg0KSWYgd2UgZXhwb3J0IG13aWZpZXhf
c2VuZF9jbWQsIGFuZCBjYWxsIGl0IGluIG13aWZpZXhfdXNiLiBUaGVyZSB3aWxsIGJlIGEgbG9v
cCwNCg0KLkRldmljZV9kdW1wIChtb2R1bGUgbXdpZmlleF91c2IpICAtLT4gIG13aWZpZXhfc2Vu
ZF9jbWQobW9kdWxlIG13aWZpZXgpICAtLT4gLmhvc3RfdG9fY2FyZCAobW9kdWxlIG13aWZpZXhf
dXNiKQ0KDQpUaGlzIHNlZW1zIG5vdCBhbiBlbGVnYW50IGRlc2lnbiwgcmlnaHQ/DQoNCg0KUmVn
YXJkcywNClNpbW9uDQo+IA0KPiA+ICsJZWxzZQ0KPiA+ICsJCXByaXYtPmFkYXB0ZXItPmlmX29w
cy5kZXZpY2VfZHVtcChwcml2LT5hZGFwdGVyKTsNCj4gPg0KPiA+ICAJcmV0dXJuIDA7DQo+ID4g
IH0NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4
L2Z3LmgNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9mdy5oDQo+
ID4gaW5kZXggNjEwYTNlYS4uMmQzYTY0NCAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93
aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvZncuaA0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVs
ZXNzL21hcnZlbGwvbXdpZmlleC9mdy5oDQo+ID4gQEAgLTM5OCw2ICszOTgsNyBAQCBlbnVtIE1X
SUZJRVhfODAyXzExX1BSSVZBQ1lfRklMVEVSIHsNCj4gPiAgI2RlZmluZSBIb3N0Q21kX0NNRF9U
RExTX0NPTkZJRyAgICAgICAgICAgICAgICAgICAgICAgMHgwMTAwDQo+ID4gICNkZWZpbmUgSG9z
dENtZF9DTURfTUNfUE9MSUNZICAgICAgICAgICAgICAgICAgICAgICAgIDB4MDEyMQ0KPiA+ICAj
ZGVmaW5lIEhvc3RDbWRfQ01EX1RETFNfT1BFUiAgICAgICAgICAgICAgICAgICAgICAgICAweDAx
MjINCj4gPiArI2RlZmluZSBIb3N0Q21kX0NNRF9GV19EVU1QX0VWRU5UCQkgICAgICAweDAxMjUN
Cj4gPiAgI2RlZmluZSBIb3N0Q21kX0NNRF9TRElPX1NQX1JYX0FHR1JfQ0ZHICAgICAgICAgICAg
ICAgMHgwMjIzDQo+ID4gICNkZWZpbmUgSG9zdENtZF9DTURfQ0hBTl9SRUdJT05fQ0ZHCQkgICAg
ICAweDAyNDINCj4gPiAgI2RlZmluZSBIb3N0Q21kX0NNRF9QQUNLRVRfQUdHUl9DVFJMCQkgICAg
ICAweDAyNTENCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9t
d2lmaWV4L3N0YV9jbWQuYw0KPiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lm
aWV4L3N0YV9jbWQuYw0KPiA+IGluZGV4IGZiMDkwMTQuLjIxMWU0N2QgMTAwNjQ0DQo+ID4gLS0t
IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3N0YV9jbWQuYw0KPiA+ICsr
KyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9zdGFfY21kLmMNCj4gPiBA
QCAtMjIwNiw2ICsyMjA2LDEwIEBAIGludCBtd2lmaWV4X3N0YV9wcmVwYXJlX2NtZChzdHJ1Y3QN
Cj4gbXdpZmlleF9wcml2YXRlICpwcml2LCB1aW50MTZfdCBjbWRfbm8sDQo+ID4gIAljYXNlIEhv
c3RDbWRfQ01EX0NIQU5fUkVHSU9OX0NGRzoNCj4gPiAgCQlyZXQgPSBtd2lmaWV4X2NtZF9jaGFu
X3JlZ2lvbl9jZmcocHJpdiwgY21kX3B0ciwgY21kX2FjdGlvbik7DQo+ID4gIAkJYnJlYWs7DQo+
ID4gKwljYXNlIEhvc3RDbWRfQ01EX0ZXX0RVTVBfRVZFTlQ6DQo+ID4gKwkJY21kX3B0ci0+Y29t
bWFuZCA9IGNwdV90b19sZTE2KGNtZF9ubyk7DQo+ID4gKwkJY21kX3B0ci0+c2l6ZSA9IGNwdV90
b19sZTE2KFNfRFNfR0VOKTsNCj4gPiArCQlicmVhazsNCj4gPiAgCWRlZmF1bHQ6DQo+ID4gIAkJ
bXdpZmlleF9kYmcocHJpdi0+YWRhcHRlciwgRVJST1IsDQo+ID4gIAkJCSAgICAiUFJFUF9DTUQ6
IHVua25vd24gY21kLSAlI3hcbiIsIGNtZF9ubyk7DQo+ID4gLS0NCj4gPiAxLjkuMQ0KPiA+DQo=
SGkgQnJpYW4sDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQnJpYW4g
Tm9ycmlzIFttYWlsdG86YnJpYW5ub3JyaXNAY2hyb21pdW0ub3JnXQ0KPiBTZW50OiAyMDE3xOo4
1MIxNcjVIDg6MDENCj4gVG86IFhpbm1pbmcgSHUgPGh1eGlubWluZzgyMEBnbWFpbC5jb20+DQo+
IENjOiBMaW51eCBXaXJlbGVzcyA8bGludXgtd2lyZWxlc3NAdmdlci5rZXJuZWwub3JnPjsgS2Fs
bGUgVmFsbw0KPiA8a3ZhbG9AY29kZWF1cm9yYS5vcmc+OyBEbWl0cnkgVG9yb2tob3YgPGR0b3JA
Z29vZ2xlLmNvbT47DQo+IHJhamF0amFAZ29vZ2xlLmNvbTsgWmhpeXVhbiBZYW5nIDx5YW5nenlA
bWFydmVsbC5jb20+OyBUaW0gU29uZw0KPiA8c29uZ3Rhb0BtYXJ2ZWxsLmNvbT47IENhdGh5IEx1
byA8Y2x1b0BtYXJ2ZWxsLmNvbT47IEdhbmFwYXRoaSBCaGF0DQo+IDxnYmhhdEBtYXJ2ZWxsLmNv
bT47IFhpbm1pbmcgSHUgPGh1eG1AbWFydmVsbC5jb20+DQo+IFN1YmplY3Q6IFtFWFRdIFJlOiBb
UEFUQ0ggMi8zXSBtd2lmaWV4OiBkZXZpY2UgZHVtcCBzdXBwb3J0IGZvciB1c2IgaW50ZXJmYWNl
DQo+IA0KPiBFeHRlcm5hbCBFbWFpbA0KPiANCj4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KPiBIaSwNCj4gDQo+
IE9uIE1vbiwgQXVnIDE0LCAyMDE3IGF0IDEyOjE5OjAyUE0gKzAwMDAsIFhpbm1pbmcgSHUgd3Jv
dGU6DQo+ID4gRnJvbTogWGlubWluZyBIdSA8aHV4bUBtYXJ2ZWxsLmNvbT4NCj4gPg0KPiA+IEZp
cm13YXJlIGR1bXAgb24gdXNiIGludGVyZmFjZSBpcyBkaWZmZXJlbnQgd2l0aCBjdXJyZW50IHNk
aW8vcGNpZQ0KPiA+IGNoaXBzZXQsIHdoaWNoIGlzIGJhc2VkIG9uIHJlZ2lzdGVyIG9wZXJhdGlv
bi4NCj4gPg0KPiA+IFdoZW4gZmlybXdhcmUgaGFuZyBvbiB1c2IgaW50ZXJmYWNlLCBjb250ZXh0
IGR1bXAgd2lsbCBiZSB1cGxvYWQgdG8NCj4gPiBob3N0IHVzaW5nIDB4NzMgZmlybXdhcmUgZGVi
dWcgZXZlbnQuDQo+ID4NCj4gPiBUaGlzIHBhdGNoIHN0b3JlIGR1bXAgZGF0YSBmcm9tIGRlYnVn
IGV2ZW50IGFuZCBzZW5kIHRvIHVzZXJzcGFjZQ0KPiA+IHVzaW5nIGRldmljZSBjb3JlZHVtcCBB
UEkuDQo+ID4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBYaW5taW5nIEh1IDxodXhtQG1hcnZlbGwuY29t
Pg0KPiA+IFNpZ25lZC1vZmYtYnk6IENhdGh5IEx1byA8Y2x1b0BtYXJ2ZWxsLmNvbT4NCj4gPiBT
aWduZWQtb2ZmLWJ5OiBHYW5hcGF0aGkgQmhhdCA8Z2JoYXRAbWFydmVsbC5jb20+DQo+ID4gLS0t
DQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9mdy5oICAgICAgICB8
ICAxICsNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L2luaXQuYyAg
ICAgIHwgIDMgKysNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21h
aW4uaCAgICAgIHwgIDIgKysNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lm
aWV4L3N0YV9ldmVudC5jIHwgMzkNCj4gPiArKysrKysrKysrKysrKysrKysrKysrKysNCj4gPiAg
NCBmaWxlcyBjaGFuZ2VkLCA0NSBpbnNlcnRpb25zKCspDQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEv
ZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L2Z3LmgNCj4gPiBiL2RyaXZlcnMv
bmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9mdy5oDQo+ID4gaW5kZXggOWU3NTUyMi4uNjEw
YTNlYSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZp
ZXgvZncuaA0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9m
dy5oDQo+ID4gQEAgLTU2OCw2ICs1NjgsNyBAQCBlbnVtIG13aWZpZXhfY2hhbm5lbF9mbGFncyB7
DQo+ID4gICNkZWZpbmUgRVZFTlRfQkdfU0NBTl9TVE9QUEVEICAgICAgICAgICAweDAwMDAwMDY1
DQo+ID4gICNkZWZpbmUgRVZFTlRfUkVNQUlOX09OX0NIQU5fRVhQSVJFRCAgICAweDAwMDAwMDVm
DQo+ID4gICNkZWZpbmUgRVZFTlRfTVVMVElfQ0hBTl9JTkZPICAgICAgICAgICAweDAwMDAwMDZh
DQo+ID4gKyNkZWZpbmUgRVZFTlRfRldfRFVNUF9JTkZPCQkweDAwMDAwMDczDQo+ID4gICNkZWZp
bmUgRVZFTlRfVFhfU1RBVFVTX1JFUE9SVAkJMHgwMDAwMDA3NA0KPiA+ICAjZGVmaW5lIEVWRU5U
X0JUX0NPRVhfV0xBTl9QQVJBX0NIQU5HRQkwWDAwMDAwMDc2DQo+ID4NCj4gPiBkaWZmIC0tZ2l0
IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L2luaXQuYw0KPiA+IGIvZHJp
dmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L2luaXQuYw0KPiA+IGluZGV4IGUxMTkx
OWQuLjM4OWQ3MjUgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVs
bC9td2lmaWV4L2luaXQuYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwv
bXdpZmlleC9pbml0LmMNCj4gPiBAQCAtMzE1LDYgKzMxNSw4IEBAIHN0YXRpYyB2b2lkIG13aWZp
ZXhfaW5pdF9hZGFwdGVyKHN0cnVjdA0KPiBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIpDQo+ID4g
IAlhZGFwdGVyLT5hY3RpdmVfc2Nhbl90cmlnZ2VyZWQgPSBmYWxzZTsNCj4gPiAgCXNldHVwX3Rp
bWVyKCZhZGFwdGVyLT53YWtldXBfdGltZXIsIHdha2V1cF90aW1lcl9mbiwNCj4gPiAgCQkgICAg
KHVuc2lnbmVkIGxvbmcpYWRhcHRlcik7DQo+ID4gKwlzZXR1cF90aW1lcigmYWRhcHRlci0+ZGV2
ZHVtcF90aW1lciwgbXdpZmlleF91cGxvYWRfZGV2aWNlX2R1bXAsDQo+ID4gKwkJICAgICh1bnNp
Z25lZCBsb25nKWFkYXB0ZXIpOw0KPiA+ICB9DQo+ID4NCj4gPiAgLyoNCj4gPiBAQCAtMzk3LDYg
KzM5OSw3IEBAIHN0YXRpYyB2b2lkIG13aWZpZXhfaW52YWxpZGF0ZV9saXN0cyhzdHJ1Y3QNCj4g
PiBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIpICBtd2lmaWV4X2FkYXB0ZXJfY2xlYW51cChzdHJ1
Y3QNCj4gPiBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIpICB7DQo+ID4gIAlkZWxfdGltZXIoJmFk
YXB0ZXItPndha2V1cF90aW1lcik7DQo+ID4gKwlkZWxfdGltZXJfc3luYygmYWRhcHRlci0+ZGV2
ZHVtcF90aW1lcik7DQo+ID4gIAltd2lmaWV4X2NhbmNlbF9hbGxfcGVuZGluZ19jbWQoYWRhcHRl
cik7DQo+ID4gIAl3YWtlX3VwX2ludGVycnVwdGlibGUoJmFkYXB0ZXItPmNtZF93YWl0X3Eud2Fp
dCk7DQo+ID4gIAl3YWtlX3VwX2ludGVycnVwdGlibGUoJmFkYXB0ZXItPmhzX2FjdGl2YXRlX3dh
aXRfcSk7DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdp
ZmlleC9tYWluLmgNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9t
YWluLmgNCj4gPiBpbmRleCBlMzA4YjhhLi42YjAwMjk0IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZl
cnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmgNCj4gPiArKysgYi9kcml2ZXJz
L25ldC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5oDQo+ID4gQEAgLTEwMzgsNiArMTAz
OCw3IEBAIHN0cnVjdCBtd2lmaWV4X2FkYXB0ZXIgew0KPiA+ICAJLyogRGV2aWNlIGR1bXAgZGF0
YS9sZW5ndGggKi8NCj4gPiAgCWNoYXIgKmRldmR1bXBfZGF0YTsNCj4gPiAgCWludCBkZXZkdW1w
X2xlbjsNCj4gPiArCXN0cnVjdCB0aW1lcl9saXN0IGRldmR1bXBfdGltZXI7DQo+ID4gIH07DQo+
ID4NCj4gPiAgdm9pZCBtd2lmaWV4X3Byb2Nlc3NfdHhfcXVldWUoc3RydWN0IG13aWZpZXhfYWRh
cHRlciAqYWRhcHRlcik7IEBADQo+ID4gLTE2ODAsNiArMTY4MSw3IEBAIHZvaWQgbXdpZmlleF9w
cm9jZXNzX211bHRpX2NoYW5fZXZlbnQoc3RydWN0DQo+ID4gbXdpZmlleF9wcml2YXRlICpwcml2
LCAgdm9pZCBtd2lmaWV4X211bHRpX2NoYW5fcmVzeW5jKHN0cnVjdA0KPiA+IG13aWZpZXhfYWRh
cHRlciAqYWRhcHRlcik7ICBpbnQgbXdpZmlleF9zZXRfbWFjX2FkZHJlc3Moc3RydWN0DQo+IG13
aWZpZXhfcHJpdmF0ZSAqcHJpdiwNCj4gPiAgCQkJICAgIHN0cnVjdCBuZXRfZGV2aWNlICpkZXYp
Ow0KPiA+ICt2b2lkIG13aWZpZXhfZGV2ZHVtcF90bW9fZnVuYyh1bnNpZ25lZCBsb25nIGZ1bmN0
aW9uX2NvbnRleHQpOw0KPiA+DQo+ID4gICNpZmRlZiBDT05GSUdfREVCVUdfRlMNCj4gPiAgdm9p
ZCBtd2lmaWV4X2RlYnVnZnNfaW5pdCh2b2lkKTsNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9u
ZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3N0YV9ldmVudC5jDQo+ID4gYi9kcml2ZXJzL25l
dC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvc3RhX2V2ZW50LmMNCj4gPiBpbmRleCA4MzlkZjhh
Li5iY2YyZmEyIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwv
bXdpZmlleC9zdGFfZXZlbnQuYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZl
bGwvbXdpZmlleC9zdGFfZXZlbnQuYw0KPiA+IEBAIC01ODYsNiArNTg2LDQwIEBAIHZvaWQNCj4g
bXdpZmlleF9idF9jb2V4X3dsYW5fcGFyYW1fdXBkYXRlX2V2ZW50KHN0cnVjdCBtd2lmaWV4X3By
aXZhdGUgKnByaXYsDQo+ID4gIAkJYWRhcHRlci0+Y29leF9yeF93aW5fc2l6ZSk7DQo+ID4gIH0N
Cj4gPg0KPiA+ICtzdGF0aWMgdm9pZA0KPiA+ICttd2lmaWV4X2Z3X2R1bXBfaW5mb19ldmVudChz
dHJ1Y3QgbXdpZmlleF9wcml2YXRlICpwcml2LA0KPiA+ICsJCQkgICBzdHJ1Y3Qgc2tfYnVmZiAq
ZXZlbnRfc2tiKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVy
ID0gcHJpdi0+YWRhcHRlcjsNCj4gPiArDQo+ID4gKwlpZiAoYWRhcHRlci0+aWZhY2VfdHlwZSAh
PSBNV0lGSUVYX1VTQikgew0KPiA+ICsJCW13aWZpZXhfZGJnKGFkYXB0ZXIsIE1TRywNCj4gPiAr
CQkJICAgICJldmVudCBpcyBub3Qgb24gdXNiIGludGVyZmFjZSwgaWdub3JlIGl0XG4iKTsNCj4g
PiArCQlyZXR1cm47DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJaWYgKCFhZGFwdGVyLT5kZXZkdW1w
X2RhdGEpIHsNCj4gPiArCQkvKiBXaGVuIHJlY2VpdmUgdGhlIGZpcnN0IGV2ZW50LCBhbGxvY2F0
ZSBkZXZpY2UgZHVtcA0KPiA+ICsJCSAqIGJ1ZmZlciwgZHVtcCBkcml2ZXIgaW5mby4NCj4gPiAr
CQkgKi8NCj4gPiArCQlhZGFwdGVyLT5kZXZkdW1wX2RhdGEgPSB2emFsbG9jKE1XSUZJRVhfRldf
RFVNUF9TSVpFKTsNCj4gDQo+IERvZXMgdGhpcyBldmVyIGdldCBmcmVlZD8NCg0KU3VyZSwgaXQg
d2lsbCBiZSBmcmVlZCBieSBkZXZjb3JlZHVtcCBmcmFtZXdvcmssIDVtaW5zIGFmdGVyIGRyaXZl
ciBjYWxsIGRldl9jb3JlZHVtcA0KDQo+IA0KPiA+ICsJCWlmICghYWRhcHRlci0+ZGV2ZHVtcF9k
YXRhKSB7DQo+ID4gKwkJCW13aWZpZXhfZGJnKGFkYXB0ZXIsIEVSUk9SLA0KPiA+ICsJCQkJICAg
ICJ2emFsbG9jIGRldmR1bXAgZGF0YSBmYWlsdXJlIVxuIik7DQo+ID4gKwkJCXJldHVybjsNCj4g
PiArCQl9DQo+ID4gKw0KPiA+ICsJCW13aWZpZXhfZHJ2X2luZm9fZHVtcChhZGFwdGVyKTsNCj4g
PiArCX0NCj4gPiArDQo+ID4gKwltZW1tb3ZlKGFkYXB0ZXItPmRldmR1bXBfZGF0YSArIGFkYXB0
ZXItPmRldmR1bXBfbGVuLA0KPiA+ICsJCWFkYXB0ZXItPmV2ZW50X2JvZHksIGV2ZW50X3NrYi0+
bGVuIC0NCj4gTVdJRklFWF9FVkVOVF9IRUFERVJfTEVOKTsNCj4gPiArCWFkYXB0ZXItPmRldmR1
bXBfbGVuICs9IChldmVudF9za2ItPmxlbiAtDQo+IE1XSUZJRVhfRVZFTlRfSEVBREVSX0xFTik7
DQo+IA0KPiBBcmUgeW91IGdvaW5nIHRvIHRyeSB0byBjaGVjayBmb3Igb3ZlcmZsb3c/DQoNClRo
YW5rcyBmb3IgdGhlIHBvaW50LCB3aWxsIGFkZCB0aGUgY2hlY2sgaW4gVjIuDQoNCj4gDQo+ID4g
KwkvKiBJZiBubyBwcm9jZWVkZWQgZXZlbnQgYXJyaXZlIGluIDEwcywgdXBsb2FkIGRldmljZSBk
dW1wIGRhdGEqLw0KPiANCj4gWW91IG1pc3NlZCBhIHNwYWNlIGF0IHRoZSBlbmQgb2YgdGhlIGNv
bW1lbnQuIFNob3VsZCBiZToNCj4gDQo+IAkvKiBJZiBubyBwcm9jZWVkZWQgZXZlbnQgYXJyaXZl
IGluIDEwcywgdXBsb2FkIGRldmljZSBkdW1wIGRhdGEuICovDQo+IA0KPiBBbHNvLCBpcyB0aGF0
IHJlYWxseSB0aGUgb25seSB3YXkgdG8gc2lnbmFsIHRoYXQgdGhlIGZpcm13YXJlIGR1bXAgaGFz
DQo+IGNvbXBsZXRlZD8gQnkgdGltaW5nIG91dD8gVGhhdCBzZWVtcyBsaWtlIGEgdmVyeSBiYWQg
ZGVzaWduLiBDYW4geW91DQo+IGltcGxlbWVudCBhbiAiZW5kIG9mIHRyYW5zbWlzc2lvbiIgc2ln
bmFsPw0KDQpHb29kIHN1Z2dlc3Rpb24sICBMYXRlc3QgZmlybXdhcmUgd2lsbCBzZXQgdGhlIHNp
Z25hbCBpbiB0aGUgbGFzdCBGV19EVU1QX0lORk8gZXZlbnQsIHdpbGwgYXBwbHkgaXQgaW4gVjIu
DQoNCkluIGNhc2UgdGhlICJlbmQgb2YgdHJhbnNtaXNzaW9uIiBldmVudCBsb3N0IGluIHNvbWUg
Y29ybmVsIGNhc2UsIHdlIHdvdWxkIGxpa2UgdG8gYWRkIGEgMTBzIHRpbWVyIHRvIHRyaWdnZXIg
dGhlIGR1bXAgdXBsb2FkIHRvIHVzZXJzcGFjZS4NCg0KUmVnYXJkcywNClNpbW9uDQoNCj4gDQo+
IEJyaWFuDQo+IA0KPiA+ICsJbW9kX3RpbWVyKCZhZGFwdGVyLT5kZXZkdW1wX3RpbWVyLA0KPiA+
ICsJCSAgamlmZmllcyArIG1zZWNzX3RvX2ppZmZpZXMoTVdJRklFWF9USU1FUl8xMFMpKTsNCj4g
PiArfQ0KPiA+ICsNCj4gPiAgLyoNCj4gPiAgICogVGhpcyBmdW5jdGlvbiBoYW5kbGVzIGV2ZW50
cyBnZW5lcmF0ZWQgYnkgZmlybXdhcmUuDQo+ID4gICAqDQo+ID4gQEAgLTYzOCw2ICs2NzIsNyBA
QCB2b2lkDQo+IG13aWZpZXhfYnRfY29leF93bGFuX3BhcmFtX3VwZGF0ZV9ldmVudChzdHJ1Y3Qg
bXdpZmlleF9wcml2YXRlICpwcml2LA0KPiA+ICAgKiAgICAgIC0gRVZFTlRfREVMQkENCj4gPiAg
ICogICAgICAtIEVWRU5UX0JBX1NUUkVBTV9USUVNT1VUDQo+ID4gICAqICAgICAgLSBFVkVOVF9B
TVNEVV9BR0dSX0NUUkwNCj4gPiArICogICAgICAtIEVWRU5UX0ZXX0RVTVBfSU5GTw0KPiA+ICAg
Ki8NCj4gPiAgaW50IG13aWZpZXhfcHJvY2Vzc19zdGFfZXZlbnQoc3RydWN0IG13aWZpZXhfcHJp
dmF0ZSAqcHJpdikgIHsgQEANCj4gPiAtMTAwOSw2ICsxMDQ0LDEwIEBAIGludCBtd2lmaWV4X3By
b2Nlc3Nfc3RhX2V2ZW50KHN0cnVjdA0KPiBtd2lmaWV4X3ByaXZhdGUgKnByaXYpDQo+ID4gIAkJ
CQkJICAgIGFkYXB0ZXItPmV2ZW50X3NrYi0+bGVuIC0NCj4gPiAgCQkJCQkgICAgc2l6ZW9mKGV2
ZW50Y2F1c2UpKTsNCj4gPiAgCQlicmVhazsNCj4gPiArCWNhc2UgRVZFTlRfRldfRFVNUF9JTkZP
Og0KPiA+ICsJCW13aWZpZXhfZGJnKGFkYXB0ZXIsIEVWRU5ULCAiZXZlbnQ6IGZpcm13YXJlIGRl
YnVnIGluZm9cbiIpOw0KPiA+ICsJCW13aWZpZXhfZndfZHVtcF9pbmZvX2V2ZW50KHByaXYsIGFk
YXB0ZXItPmV2ZW50X3NrYik7DQo+ID4gKwkJYnJlYWs7DQo+ID4gIAkvKiBEZWJ1Z2dpbmcgZXZl
bnQ7IG5vdCB1c2VkLCBidXQgbGV0J3Mgbm90IHByaW50IGFuIEVSUk9SIGZvciBpdC4gKi8NCj4g
PiAgCWNhc2UgRVZFTlRfVU5LTk9XTl9ERUJVRzoNCj4gPiAgCQltd2lmaWV4X2RiZyhhZGFwdGVy
LCBFVkVOVCwgImV2ZW50OiBkZWJ1Z1xuIik7DQo+ID4gLS0NCj4gPiAxLjkuMQ0KPiA+DQo=
Hi Simon,
On Wed, Nov 15, 2017 at 11:31:05AM +0000, Xinming Hu wrote:
> > -----Original Message-----
> > From: Brian Norris [mailto:[email protected]]
> >
> > On Mon, Aug 14, 2017 at 12:19:03PM +0000, Xinming Hu wrote:
> > > diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c
> > > b/drivers/net/wireless/marvell/mwifiex/debugfs.c
> > > index 6f4239b..5d476de 100644
> > > --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
> > > +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
> > > @@ -168,10 +168,11 @@
> > > {
> > > struct mwifiex_private *priv = file->private_data;
> > >
> > > - if (!priv->adapter->if_ops.device_dump)
> > > - return -EIO;
> > > -
> > > - priv->adapter->if_ops.device_dump(priv->adapter);
> > > + if (priv->adapter->iface_type == MWIFIEX_USB)
> > > + mwifiex_send_cmd(priv, HostCmd_CMD_FW_DUMP_EVENT,
> > > + HostCmd_ACT_GEN_SET, 0, NULL, true);
> >
> > Why couldn't you just implement the device_dump() callback?
>
> Currently mwifiex_send_cmd function is not exported to external modules, it is designed for module mwifiex internal use.
If you really don't want to export mwifiex_send_cmd(), you can export
some other wrapper which does the logic for you. The point is that
there's a well defined point for determining how to dump the firmware
based on which interface you're using. You should use it.
> If we export mwifiex_send_cmd, and call it in mwifiex_usb. There will be a loop,
So? There are all sorts of interdependencies between mwifiex.ko and
mwifiex_usb.ko (or in your words, "loops").
> .Device_dump (module mwifiex_usb) --> mwifiex_send_cmd(module mwifiex) --> .host_to_card (module mwifiex_usb)
>
> This seems not an elegant design, right?
No less elegant than scattering:
if (!USB)
driver->this();
else
that();
all over the place.
> Regards,
> Simon
> >
> > > + else
> > > + priv->adapter->if_ops.device_dump(priv->adapter);
> > >
> > > return 0;
> > > }
Brian
On Fri, Dec 01, 2017 at 08:36:01AM +0000, Xinming Hu wrote:
> Thanks for the suggestion, it sounds better than exporting
> mwifiex_send_cmd() directly.
> In addition to used as debugfs tirgger, the "defined point"
> if_ops.device_dump is only used in command timeout context.
> For sdio/pcie interface, register operation will be made to trigger
> firmware dump and get dump context under specific algorithm.
> For usb interface, however, this is not needed, since firmware will
> automatically send dump event to host without any trigger, and what's
> more , host is also not able to issue command in the situation.
>
> So per my understand, here we only need provide a simple way to
> trigger , instead of a totally functional complete dump entry point.
> Suppose if we make the command trigger a part of if_ops->device_dump,
> then we also need add check for "MWIFIEX_USB" in mwifiex_cmd_tmo_func.
Ah, I see. Your explanation makes some more sense then. It would be nice
if you could include some of this in
(a) the commit message
(b) the entry point in debugfs.c, where you trigger this
Something along the lines of "For command timeouts, USB firmware will
automatically emit firmware dump events, so we don't implement
device_dump(). For user-initiated dumps, we trigger it ourselves."
> it also looks inelegant, and what we did looks weird, they are
> (1) export a new kernel symbol, the wrapper of mwifiex_send_command
> (2) add usb if_ops->device_dump, it send the command in mwifiex_usb, instead of in mwifiex itself.
> (3) bypass above "if_ops->device_dump" in mwifiex_cmd_tmo_func, which is the mainly user case.
No, I'm not sure that solution would be much better. Your existing
solution with additional comments is probably fine.
> I am not sure whether there is a better way on this, perhaps we need a
> trade-off on different solutions, please let us know if you have more
> suggestions.
>
> Thanks & Regards,
> SImon
Brian
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQnJpYW4gTm9ycmlzIFtt
YWlsdG86YnJpYW5ub3JyaXNAY2hyb21pdW0ub3JnXQ0KPiBTZW50OiAyMDE3xOoxMtTCMsjVIDk6
NDUNCj4gVG86IFhpbm1pbmcgSHUgPGh1eG1AbWFydmVsbC5jb20+DQo+IENjOiBYaW5taW5nIEh1
IDxodXhpbm1pbmc4MjBAZ21haWwuY29tPjsgTGludXggV2lyZWxlc3MNCj4gPGxpbnV4LXdpcmVs
ZXNzQHZnZXIua2VybmVsLm9yZz47IEthbGxlIFZhbG8gPGt2YWxvQGNvZGVhdXJvcmEub3JnPjsg
RG1pdHJ5DQo+IFRvcm9raG92IDxkdG9yQGdvb2dsZS5jb20+OyByYWphdGphQGdvb2dsZS5jb207
IFpoaXl1YW4gWWFuZw0KPiA8eWFuZ3p5QG1hcnZlbGwuY29tPjsgVGltIFNvbmcgPHNvbmd0YW9A
bWFydmVsbC5jb20+OyBDYXRoeSBMdW8NCj4gPGNsdW9AbWFydmVsbC5jb20+OyBHYW5hcGF0aGkg
QmhhdCA8Z2JoYXRAbWFydmVsbC5jb20+OyBKYW1lcyBDYW8NCj4gPGpjYW9AbWFydmVsbC5jb20+
DQo+IFN1YmplY3Q6IFtFWFRdIFJlOiBSZTogUmU6IFtQQVRDSCAzLzNdIG13aWZpZXg6IGRlYnVn
ZnM6IHRyaWdnZXIgZGV2aWNlIGR1bXANCj4gZm9yIHVzYiBpbnRlcmZhY2UNCj4gDQo+IEV4dGVy
bmFsIEVtYWlsDQo+IA0KPiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQo+IE9uIEZyaSwgRGVjIDAxLCAyMDE3IGF0
IDA4OjM2OjAxQU0gKzAwMDAsIFhpbm1pbmcgSHUgd3JvdGU6DQo+ID4gVGhhbmtzIGZvciB0aGUg
c3VnZ2VzdGlvbiwgaXQgc291bmRzIGJldHRlciB0aGFuIGV4cG9ydGluZw0KPiA+IG13aWZpZXhf
c2VuZF9jbWQoKSBkaXJlY3RseS4NCj4gPiBJbiBhZGRpdGlvbiB0byB1c2VkIGFzIGRlYnVnZnMg
dGlyZ2dlciwgdGhlICJkZWZpbmVkIHBvaW50Ig0KPiA+IGlmX29wcy5kZXZpY2VfZHVtcCBpcyBv
bmx5IHVzZWQgaW4gY29tbWFuZCB0aW1lb3V0IGNvbnRleHQuDQo+ID4gRm9yIHNkaW8vcGNpZSBp
bnRlcmZhY2UsIHJlZ2lzdGVyIG9wZXJhdGlvbiB3aWxsIGJlIG1hZGUgdG8gdHJpZ2dlcg0KPiA+
IGZpcm13YXJlIGR1bXAgYW5kIGdldCBkdW1wIGNvbnRleHQgdW5kZXIgc3BlY2lmaWMgYWxnb3Jp
dGhtLg0KPiA+IEZvciB1c2IgaW50ZXJmYWNlLCBob3dldmVyLCAgdGhpcyBpcyBub3QgbmVlZGVk
LCBzaW5jZSBmaXJtd2FyZSB3aWxsDQo+ID4gYXV0b21hdGljYWxseSBzZW5kIGR1bXAgZXZlbnQg
dG8gaG9zdCB3aXRob3V0IGFueSB0cmlnZ2VyLCBhbmQgd2hhdCdzDQo+ID4gbW9yZSAsIGhvc3Qg
aXMgYWxzbyBub3QgYWJsZSB0byBpc3N1ZSBjb21tYW5kIGluIHRoZSBzaXR1YXRpb24uDQo+ID4N
Cj4gPiBTbyBwZXIgbXkgdW5kZXJzdGFuZCwgIGhlcmUgd2Ugb25seSBuZWVkIHByb3ZpZGUgYSBz
aW1wbGUgd2F5IHRvDQo+ID4gdHJpZ2dlciAsIGluc3RlYWQgb2YgYSB0b3RhbGx5IGZ1bmN0aW9u
YWwgY29tcGxldGUgZHVtcCBlbnRyeSBwb2ludC4NCj4gPiBTdXBwb3NlIGlmIHdlIG1ha2UgdGhl
IGNvbW1hbmQgdHJpZ2dlciBhIHBhcnQgb2YgaWZfb3BzLT5kZXZpY2VfZHVtcCwNCj4gPiB0aGVu
IHdlIGFsc28gbmVlZCBhZGQgY2hlY2sgZm9yICJNV0lGSUVYX1VTQiIgaW4gbXdpZmlleF9jbWRf
dG1vX2Z1bmMuDQo+IA0KPiBBaCwgSSBzZWUuIFlvdXIgZXhwbGFuYXRpb24gbWFrZXMgc29tZSBt
b3JlIHNlbnNlIHRoZW4uIEl0IHdvdWxkIGJlIG5pY2UgaWYNCj4geW91IGNvdWxkIGluY2x1ZGUg
c29tZSBvZiB0aGlzIGluDQo+IChhKSB0aGUgY29tbWl0IG1lc3NhZ2UNCj4gKGIpIHRoZSBlbnRy
eSBwb2ludCBpbiBkZWJ1Z2ZzLmMsIHdoZXJlIHlvdSB0cmlnZ2VyIHRoaXMNCj4gDQo+IFNvbWV0
aGluZyBhbG9uZyB0aGUgbGluZXMgb2YgIkZvciBjb21tYW5kIHRpbWVvdXRzLCBVU0IgZmlybXdh
cmUgd2lsbA0KPiBhdXRvbWF0aWNhbGx5IGVtaXQgZmlybXdhcmUgZHVtcCBldmVudHMsIHNvIHdl
IGRvbid0IGltcGxlbWVudA0KPiBkZXZpY2VfZHVtcCgpLiBGb3IgdXNlci1pbml0aWF0ZWQgZHVt
cHMsIHdlIHRyaWdnZXIgaXQgb3Vyc2VsdmVzLiINCj4gDQoNCk9rYXksIFRoYW5rcyENCg0KUmVn
YXJkcywNClNpbW9uDQoNCj4gPiBpdCBhbHNvIGxvb2tzIGluZWxlZ2FudCwgYW5kIHdoYXQgd2Ug
ZGlkIGxvb2tzIHdlaXJkLCB0aGV5IGFyZQ0KPiA+ICgxKSBleHBvcnQgYSBuZXcgIGtlcm5lbCBz
eW1ib2wsICB0aGUgd3JhcHBlciBvZiBtd2lmaWV4X3NlbmRfY29tbWFuZA0KPiA+ICgyKSBhZGQg
dXNiIGlmX29wcy0+ZGV2aWNlX2R1bXAsIGl0ICBzZW5kIHRoZSBjb21tYW5kIGluIG13aWZpZXhf
dXNiLA0KPiBpbnN0ZWFkIG9mIGluIG13aWZpZXggaXRzZWxmLg0KPiA+ICgzKSBieXBhc3MgYWJv
dmUgImlmX29wcy0+ZGV2aWNlX2R1bXAiIGluIG13aWZpZXhfY21kX3Rtb19mdW5jLCB3aGljaCBp
cw0KPiB0aGUgbWFpbmx5IHVzZXIgY2FzZS4NCj4gDQo+IE5vLCBJJ20gbm90IHN1cmUgdGhhdCBz
b2x1dGlvbiB3b3VsZCBiZSBtdWNoIGJldHRlci4gWW91ciBleGlzdGluZyBzb2x1dGlvbiB3aXRo
DQo+IGFkZGl0aW9uYWwgY29tbWVudHMgaXMgcHJvYmFibHkgZmluZS4NCj4gDQo+ID4gSSBhbSBu
b3Qgc3VyZSB3aGV0aGVyIHRoZXJlIGlzIGEgYmV0dGVyIHdheSBvbiB0aGlzLCBwZXJoYXBzIHdl
IG5lZWQgYQ0KPiA+IHRyYWRlLW9mZiBvbiBkaWZmZXJlbnQgc29sdXRpb25zLCBwbGVhc2UgbGV0
IHVzIGtub3cgaWYgeW91IGhhdmUgbW9yZQ0KPiA+IHN1Z2dlc3Rpb25zLg0KPiA+DQo+ID4gVGhh
bmtzICYgUmVnYXJkcywNCj4gPiBTSW1vbg0KPiANCj4gQnJpYW4NCg==