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]>
---
v2: Addressed below review comments from Brian Norris
a) use new API timer_setup/from_timer.
b) reset devdump_len during initization
v4: Same as v2,v3
---
drivers/net/wireless/marvell/mwifiex/init.c | 1 +
drivers/net/wireless/marvell/mwifiex/main.c | 87 +++++++++++++++--------------
drivers/net/wireless/marvell/mwifiex/main.h | 11 +++-
drivers/net/wireless/marvell/mwifiex/pcie.c | 13 +++--
drivers/net/wireless/marvell/mwifiex/sdio.c | 14 +++--
5 files changed, 72 insertions(+), 54 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index e1aa860..b0d3d68 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -314,6 +314,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
adapter->active_scan_triggered = false;
timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
+ adapter->devdump_len = 0;
}
/*
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index a96bd7e..f7d0299 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1051,9 +1051,23 @@ 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(struct mwifiex_adapter *adapter)
{
- void *p;
+ /* 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\n");
+ dev_coredumpv(adapter->dev, adapter->devdump_data, adapter->devdump_len,
+ GFP_KERNEL);
+ mwifiex_dbg(adapter, MSG,
+ "== mwifiex dump information to /sys/class/devcoredump end\n");
+}
+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;
@@ -1061,17 +1075,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,
@@ -1155,21 +1164,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 - (char *)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 =
@@ -1184,24 +1190,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.\n");
+ 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 = (char *)adapter->devdump_data + adapter->devdump_len;
for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
@@ -1228,11 +1234,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 - (char *)adapter->devdump_data;
-done:
for (idx = 0; idx < adapter->num_mem_types; idx++) {
struct memory_type_mapping *entry =
&adapter->mem_type_mapping_tbl[idx];
@@ -1241,10 +1244,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 154c079..8b6241a 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
@@ -1032,6 +1034,9 @@ struct mwifiex_adapter {
bool wake_by_wifi;
/* Aggregation parameters*/
struct bus_aggr_params bus_aggr;
+ /* Device dump data/length */
+ void *devdump_data;
+ int devdump_len;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1656,9 +1661,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(struct mwifiex_adapter *adapter);
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..f666cb2 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(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..a828801 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(adapter);
}
static void mwifiex_sdio_work(struct work_struct *work)
--
1.9.1
Hi,
On Mon, Dec 04, 2017 at 08:18:42PM +0800, Xinming Hu wrote:
> This patch refactor current device dump code to make it generic
> for subsequent implementation on usb interface.
I still think you're making the spaghetti worse. I only have a few
specific suggestions for improving your spaghetti code at the moment,
but I'm still sure you could do better.
> Signed-off-by: Xinming Hu <[email protected]>
> Signed-off-by: Cathy Luo <[email protected]>
> Signed-off-by: Ganapathi Bhat <[email protected]>
> ---
> v2: Addressed below review comments from Brian Norris
> a) use new API timer_setup/from_timer.
> b) reset devdump_len during initization
> v4: Same as v2,v3
> ---
> drivers/net/wireless/marvell/mwifiex/init.c | 1 +
> drivers/net/wireless/marvell/mwifiex/main.c | 87 +++++++++++++++--------------
> drivers/net/wireless/marvell/mwifiex/main.h | 11 +++-
> drivers/net/wireless/marvell/mwifiex/pcie.c | 13 +++--
> drivers/net/wireless/marvell/mwifiex/sdio.c | 14 +++--
> 5 files changed, 72 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
> index e1aa860..b0d3d68 100644
> --- a/drivers/net/wireless/marvell/mwifiex/init.c
> +++ b/drivers/net/wireless/marvell/mwifiex/init.c
> @@ -314,6 +314,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
> adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM;
> adapter->active_scan_triggered = false;
> timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
> + adapter->devdump_len = 0;
> }
>
> /*
> diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
> index a96bd7e..f7d0299 100644
> --- a/drivers/net/wireless/marvell/mwifiex/main.c
> +++ b/drivers/net/wireless/marvell/mwifiex/main.c
> @@ -1051,9 +1051,23 @@ 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(struct mwifiex_adapter *adapter)
> {
> - void *p;
> + /* 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\n");
> + dev_coredumpv(adapter->dev, adapter->devdump_data, adapter->devdump_len,
> + GFP_KERNEL);
Seems like you should reset adapter->devdump_data and ->devdump_len
here, so you don't accidentally reuse it? (You're expecting
dev_coredumpv() to free the buffer, no?)
> + mwifiex_dbg(adapter, MSG,
> + "== mwifiex dump information to /sys/class/devcoredump end\n");
> +}
> +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;
> @@ -1061,17 +1075,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,
> @@ -1155,21 +1164,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 - (char *)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 =
> @@ -1184,24 +1190,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.\n");
> + 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 = (char *)adapter->devdump_data + adapter->devdump_len;
>
> for (idx = 0; idx < adapter->num_mem_types; idx++) {
> struct memory_type_mapping *entry =
> @@ -1228,11 +1234,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
> */
^^ This comment is a bit out of place now. The data is not dumped until
we call mwifiex_upload_device_dump(), and so we don't guarantee anyone
will actually free it for us until then
> - 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 - (char *)adapter->devdump_data;
>
> -done:
> for (idx = 0; idx < adapter->num_mem_types; idx++) {
> struct memory_type_mapping *entry =
> &adapter->mem_type_mapping_tbl[idx];
> @@ -1241,10 +1244,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 154c079..8b6241a 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
> @@ -1032,6 +1034,9 @@ struct mwifiex_adapter {
> bool wake_by_wifi;
> /* Aggregation parameters*/
> struct bus_aggr_params bus_aggr;
> + /* Device dump data/length */
> + void *devdump_data;
> + int devdump_len;
> };
>
> void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
> @@ -1656,9 +1661,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(struct mwifiex_adapter *adapter);
> 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..f666cb2 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);
I'm still not sure why you need 3 different callers to allocate the same
size buffer. It seems like this should all be done in the core.
Brian
> + 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(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..a828801 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(adapter);
> }
>
> static void mwifiex_sdio_work(struct work_struct *work)
> --
> 1.9.1
>
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]>
---
v2: Addressed below review comments from Brian Norris
a) Check for overflow introduced by invalid event.
b) Use end of transmission signal to recognize last event.
v4: Same as v2,v3
---
drivers/net/wireless/marvell/mwifiex/fw.h | 10 ++++
drivers/net/wireless/marvell/mwifiex/init.c | 9 ++++
drivers/net/wireless/marvell/mwifiex/main.h | 2 +
drivers/net/wireless/marvell/mwifiex/sta_event.c | 61 ++++++++++++++++++++++++
4 files changed, 82 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 13cd58e9..4d5e686 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -56,6 +56,15 @@ struct mwifiex_fw_data {
u8 data[1];
} __packed;
+struct mwifiex_fw_dump_header {
+ __le16 seq_num;
+ __le16 reserved;
+ __le16 type;
+ __le16 len;
+} __packed;
+
+#define FW_DUMP_INFO_ENDED 0x0002
+
#define MWIFIEX_FW_DNLD_CMD_1 0x1
#define MWIFIEX_FW_DNLD_CMD_5 0x5
#define MWIFIEX_FW_DNLD_CMD_6 0x6
@@ -570,6 +579,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 b0d3d68..d239e92 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -64,6 +64,13 @@ static void wakeup_timer_fn(struct timer_list *t)
adapter->if_ops.card_reset(adapter);
}
+static void fw_dump_timer_fn(struct timer_list *t)
+{
+ struct mwifiex_adapter *adapter = from_timer(adapter, t, devdump_timer);
+
+ mwifiex_upload_device_dump(adapter);
+}
+
/*
* This function initializes the private structure and sets default
* values to the members.
@@ -315,6 +322,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->active_scan_triggered = false;
timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
adapter->devdump_len = 0;
+ timer_setup(&adapter->devdump_timer, fw_dump_timer_fn, 0);
}
/*
@@ -397,6 +405,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 8b6241a..6b5539b 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -1037,6 +1037,7 @@ struct mwifiex_adapter {
/* Device dump data/length */
void *devdump_data;
int devdump_len;
+ struct timer_list devdump_timer;
};
void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1682,6 +1683,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 d8db412..93dfb76 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -584,6 +584,62 @@ 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;
+ struct mwifiex_fw_dump_header *fw_dump_hdr =
+ (void *)adapter->event_body;
+
+ 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);
+
+ /* If no proceeded event arrive in 10s, upload device
+ * dump data, this will be useful if the end of
+ * transmission event get lost, in this cornel case,
+ * user would still get partial of the dump.
+ */
+ mod_timer(&adapter->devdump_timer,
+ jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
+ }
+
+ /* Overflow check */
+ if (adapter->devdump_len + event_skb->len >= MWIFIEX_FW_DUMP_SIZE)
+ goto upload_dump;
+
+ memmove(adapter->devdump_data + adapter->devdump_len,
+ adapter->event_skb->data, event_skb->len);
+ adapter->devdump_len += event_skb->len;
+
+ if (le16_to_cpu(fw_dump_hdr->type == FW_DUMP_INFO_ENDED)) {
+ mwifiex_dbg(adapter, MSG,
+ "receive end of transmission flag event!\n");
+ goto upload_dump;
+ }
+ return;
+
+upload_dump:
+ del_timer_sync(&adapter->devdump_timer);
+ mwifiex_upload_device_dump(adapter);
+}
+
/*
* This function handles events generated by firmware.
*
@@ -636,6 +692,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)
{
@@ -1007,6 +1064,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
This patch extend device_dump debugfs function to make it
works for usb interface.
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 by issue firmware
dump event command to firmware, as there is no command
response, do not start 10s timer.
Signed-off-by: Xinming Hu <[email protected]>
Signed-off-by: Cathy Luo <[email protected]>
---
v2: Same as v1
v3: Add more comments Regards the different dump mechanism
between usb and other interfaces.(Brian Norris)
v4: Same as v3
---
drivers/net/wireless/marvell/mwifiex/cmdevt.c | 11 +++++++----
drivers/net/wireless/marvell/mwifiex/debugfs.c | 13 +++++++++----
drivers/net/wireless/marvell/mwifiex/fw.h | 1 +
drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 4 ++++
4 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index dcc529e..8746600 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..db2872d 100644
--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@ -168,10 +168,15 @@
{
struct mwifiex_private *priv = file->private_data;
- if (!priv->adapter->if_ops.device_dump)
- return -EIO;
-
- priv->adapter->if_ops.device_dump(priv->adapter);
+ /* 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.
+ */
+ 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 4d5e686..9c2cdef 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -409,6 +409,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
SGkgQnJpYW4sDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQnJpYW4g
Tm9ycmlzIFttYWlsdG86YnJpYW5ub3JyaXNAY2hyb21pdW0ub3JnXQ0KPiBTZW50OiAyMDE3xOox
MtTCNsjVIDI6MjYNCj4gVG86IFhpbm1pbmcgSHUgPGh1eG1AbWFydmVsbC5jb20+DQo+IENjOiBM
aW51eCBXaXJlbGVzcyA8bGludXgtd2lyZWxlc3NAdmdlci5rZXJuZWwub3JnPjsgS2FsbGUgVmFs
bw0KPiA8a3ZhbG9AY29kZWF1cm9yYS5vcmc+OyBEbWl0cnkgVG9yb2tob3YgPGR0b3JAZ29vZ2xl
LmNvbT47DQo+IHJhamF0amFAZ29vZ2xlLmNvbTsgWmhpeXVhbiBZYW5nIDx5YW5nenlAbWFydmVs
bC5jb20+OyBUaW0gU29uZw0KPiA8c29uZ3Rhb0BtYXJ2ZWxsLmNvbT47IENhdGh5IEx1byA8Y2x1
b0BtYXJ2ZWxsLmNvbT47IEphbWVzIENhbw0KPiA8amNhb0BtYXJ2ZWxsLmNvbT47IEdhbmFwYXRo
aSBCaGF0IDxnYmhhdEBtYXJ2ZWxsLmNvbT47IEVsbGllIFJlZXZlcw0KPiA8ZWxsaWVyZXZ2ZXNA
Z21haWwuY29tPg0KPiBTdWJqZWN0OiBbRVhUXSBSZTogW1BBVENIIHY0IDEvM10gbXdpZmlleDog
cmVmYWN0b3IgZGV2aWNlIGR1bXAgY29kZSB0byBtYWtlIGl0DQo+IGdlbmVyaWMgZm9yIHVzYiBp
bnRlcmZhY2UNCj4gDQo+IEV4dGVybmFsIEVtYWlsDQo+IA0KPiAtLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQo+IEhp
LA0KPiANCj4gT24gTW9uLCBEZWMgMDQsIDIwMTcgYXQgMDg6MTg6NDJQTSArMDgwMCwgWGlubWlu
ZyBIdSB3cm90ZToNCj4gPiBUaGlzIHBhdGNoIHJlZmFjdG9yIGN1cnJlbnQgZGV2aWNlIGR1bXAg
Y29kZSB0byBtYWtlIGl0IGdlbmVyaWMgZm9yDQo+ID4gc3Vic2VxdWVudCBpbXBsZW1lbnRhdGlv
biBvbiB1c2IgaW50ZXJmYWNlLg0KPiANCj4gSSBzdGlsbCB0aGluayB5b3UncmUgbWFraW5nIHRo
ZSBzcGFnaGV0dGkgd29yc2UuIEkgb25seSBoYXZlIGEgZmV3IHNwZWNpZmljDQo+IHN1Z2dlc3Rp
b25zIGZvciBpbXByb3ZpbmcgeW91ciBzcGFnaGV0dGkgY29kZSBhdCB0aGUgbW9tZW50LCBidXQg
SSdtIHN0aWxsIHN1cmUNCj4geW91IGNvdWxkIGRvIGJldHRlci4NCj4gDQpPaywgVGhhbmtzLg0K
DQo+ID4gU2lnbmVkLW9mZi1ieTogWGlubWluZyBIdSA8aHV4bUBtYXJ2ZWxsLmNvbT4NCj4gPiBT
aWduZWQtb2ZmLWJ5OiBDYXRoeSBMdW8gPGNsdW9AbWFydmVsbC5jb20+DQo+ID4gU2lnbmVkLW9m
Zi1ieTogR2FuYXBhdGhpIEJoYXQgPGdiaGF0QG1hcnZlbGwuY29tPg0KPiA+IC0tLQ0KPiA+IHYy
OiBBZGRyZXNzZWQgYmVsb3cgcmV2aWV3IGNvbW1lbnRzIGZyb20gQnJpYW4gTm9ycmlzDQo+ID4g
ICAgIGEpIHVzZSBuZXcgQVBJIHRpbWVyX3NldHVwL2Zyb21fdGltZXIuDQo+ID4gICAgIGIpIHJl
c2V0IGRldmR1bXBfbGVuIGR1cmluZyBpbml0aXphdGlvbg0KPiA+IHY0OiBTYW1lIGFzIHYyLHYz
DQo+ID4gLS0tDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9pbml0
LmMgfCAgMSArDQo+ID4gZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21haW4u
YyB8IDg3DQo+ID4gKysrKysrKysrKysrKysrLS0tLS0tLS0tLS0tLS0NCj4gPiBkcml2ZXJzL25l
dC93aXJlbGVzcy9tYXJ2ZWxsL213aWZpZXgvbWFpbi5oIHwgMTEgKysrLQ0KPiA+IGRyaXZlcnMv
bmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9wY2llLmMgfCAxMyArKystLQ0KPiA+IGRyaXZl
cnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9zZGlvLmMgfCAxNCArKystLQ0KPiA+ICA1
IGZpbGVzIGNoYW5nZWQsIDcyIGluc2VydGlvbnMoKyksIDU0IGRlbGV0aW9ucygtKQ0KPiA+DQo+
ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9pbml0
LmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9pbml0LmMNCj4g
PiBpbmRleCBlMWFhODYwLi5iMGQzZDY4IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dp
cmVsZXNzL21hcnZlbGwvbXdpZmlleC9pbml0LmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJl
bGVzcy9tYXJ2ZWxsL213aWZpZXgvaW5pdC5jDQo+ID4gQEAgLTMxNCw2ICszMTQsNyBAQCBzdGF0
aWMgdm9pZCBtd2lmaWV4X2luaXRfYWRhcHRlcihzdHJ1Y3QNCj4gbXdpZmlleF9hZGFwdGVyICph
ZGFwdGVyKQ0KPiA+ICAJYWRhcHRlci0+aWZhY2VfbGltaXQucDJwX2ludGYgPSBNV0lGSUVYX01B
WF9QMlBfTlVNOw0KPiA+ICAJYWRhcHRlci0+YWN0aXZlX3NjYW5fdHJpZ2dlcmVkID0gZmFsc2U7
DQo+ID4gIAl0aW1lcl9zZXR1cCgmYWRhcHRlci0+d2FrZXVwX3RpbWVyLCB3YWtldXBfdGltZXJf
Zm4sIDApOw0KPiA+ICsJYWRhcHRlci0+ZGV2ZHVtcF9sZW4gPSAwOw0KPiA+ICB9DQo+ID4NCj4g
PiAgLyoNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lm
aWV4L21haW4uYw0KPiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21h
aW4uYw0KPiA+IGluZGV4IGE5NmJkN2UuLmY3ZDAyOTkgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVy
cy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21haW4uYw0KPiA+ICsrKyBiL2RyaXZlcnMv
bmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmMNCj4gPiBAQCAtMTA1MSw5ICsxMDUx
LDIzIEBAIHZvaWQgbXdpZmlleF9tdWx0aV9jaGFuX3Jlc3luYyhzdHJ1Y3QNCj4gPiBtd2lmaWV4
X2FkYXB0ZXIgKmFkYXB0ZXIpICB9DQo+ID4gRVhQT1JUX1NZTUJPTF9HUEwobXdpZmlleF9tdWx0
aV9jaGFuX3Jlc3luYyk7DQo+ID4NCj4gPiAtaW50IG13aWZpZXhfZHJ2X2luZm9fZHVtcChzdHJ1
Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVyLCB2b2lkDQo+ID4gKipkcnZfaW5mbykNCj4gPiAr
dm9pZCBtd2lmaWV4X3VwbG9hZF9kZXZpY2VfZHVtcChzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyICph
ZGFwdGVyKQ0KPiA+ICB7DQo+ID4gLQl2b2lkICpwOw0KPiA+ICsJLyogRHVtcCBhbGwgdGhlIG1l
bW9yeSBkYXRhIGludG8gc2luZ2xlIGZpbGUsIGEgdXNlcnNwYWNlIHNjcmlwdCB3aWxsDQo+ID4g
KwkgKiBiZSB1c2VkIHRvIHNwbGl0IGFsbCB0aGUgbWVtb3J5IGRhdGEgdG8gbXVsdGlwbGUgZmls
ZXMNCj4gPiArCSAqLw0KPiA+ICsJbXdpZmlleF9kYmcoYWRhcHRlciwgTVNHLA0KPiA+ICsJCSAg
ICAiPT0gbXdpZmlleCBkdW1wIGluZm9ybWF0aW9uIHRvIC9zeXMvY2xhc3MvZGV2Y29yZWR1bXAN
Cj4gc3RhcnRcbiIpOw0KPiA+ICsJZGV2X2NvcmVkdW1wdihhZGFwdGVyLT5kZXYsIGFkYXB0ZXIt
PmRldmR1bXBfZGF0YSwNCj4gYWRhcHRlci0+ZGV2ZHVtcF9sZW4sDQo+ID4gKwkJICAgICAgR0ZQ
X0tFUk5FTCk7DQo+IA0KPiBTZWVtcyBsaWtlIHlvdSBzaG91bGQgcmVzZXQgYWRhcHRlci0+ZGV2
ZHVtcF9kYXRhIGFuZCAtPmRldmR1bXBfbGVuIGhlcmUsDQo+IHNvIHlvdSBkb24ndCBhY2NpZGVu
dGFsbHkgcmV1c2UgaXQ/IChZb3UncmUgZXhwZWN0aW5nDQo+IGRldl9jb3JlZHVtcHYoKSB0byBm
cmVlIHRoZSBidWZmZXIsIG5vPykNCj4gDQoNCk9oLCB5ZXMsIEkgd2FzIGV4cGVjdCBkZXZfY29y
ZWR1bXB2IHRvIGZyZWUgdGhlIGJ1ZmZlciwgdGhlIGRldl9jb3JlZHVtcCBmcmFtZXdvcmsgd2ls
bCBmcmVlIGR1bXAgZGF0YSBhZnRlciA1IG1pbnV0ZXMuDQpXaGF0J3MgbW9yZSwgSWYgdGhlcmUg
aXMgbmV3IGNvcmVkdW1wIGluIDUgbWludXRlcywgdGhlIG5ldyBkdW1wIGRhdGEgd2lsbCBiZSBk
aXNjYXJkIGFuZCBmcmVlLg0KQ29uc2lkZXIgYmVsb3cgc2VxdWVuY2UgaGFwcGVucyBpbiBjb21t
YW5kIHRpbWVvdXQgY29udGV4dDoNCk13aWZpZXhfY21kX3Rtb19mdW5jDQooMSkgIC0tPiAgIGZp
cm13YXJlIGR1bXAgMSAtLT4gICAgZGV2Y29yZWR1bXAgMQ0KKDIpICAtLT4gIGNhcmRfcmVzZXQg
LS0+IGluaXQgc29mdHdhcmUNCgkJCQlDb21tYW5kIHRpbWVvdXQgaGFwcGVucyBhZ2FpbglpbiA1
IG1pbnV0ZXMgLS0+ICBmaXJtd2FyZSBkdW1wIDIgIC0tPiAgIGRldmNvcmVkdW1wIDINCg0KSGVy
ZSwgaWYgd2UgZnJlZSBhZGFwdGVyLT4gZGV2ZHVtcF9kYXRhLCBhbmQgIHRoZW4gdXNlciBjYXQg
ZGV2Y29yZWR1bXAxLCB3aWxsIGNyYXNoIHRoZSBrZXJuZWwNCg0KDQpJIHRoaW5rLCBoZXJlLCBS
ZWdhcmRzICJyZXNldCBhZGFwdGVyLT5kZXZkdW1wX2RhdGEiLCB5b3UgbWVhbiBhZGFwdGVyLT5k
ZXZkdW1wX2RhdGEgPSBOVUxMLCANCkJ1dCBub3QgZnJlZSBpdCwgcmlnaHQgPw0KDQoNCj4gPiAr
CW13aWZpZXhfZGJnKGFkYXB0ZXIsIE1TRywNCj4gPiArCQkgICAgIj09IG13aWZpZXggZHVtcCBp
bmZvcm1hdGlvbiB0byAvc3lzL2NsYXNzL2RldmNvcmVkdW1wDQo+IGVuZFxuIik7DQo+ID4gK30g
RVhQT1JUX1NZTUJPTF9HUEwobXdpZmlleF91cGxvYWRfZGV2aWNlX2R1bXApOw0KPiA+ICsNCj4g
PiArdm9pZCBtd2lmaWV4X2Rydl9pbmZvX2R1bXAoc3RydWN0IG13aWZpZXhfYWRhcHRlciAqYWRh
cHRlcikgew0KPiA+ICsJY2hhciAqcDsNCj4gPiAgCWNoYXIgZHJ2X3ZlcnNpb25bNjRdOw0KPiA+
ICAJc3RydWN0IHVzYl9jYXJkX3JlYyAqY2FyZHA7DQo+ID4gIAlzdHJ1Y3Qgc2Rpb19tbWNfY2Fy
ZCAqc2Rpb19jYXJkOw0KPiA+IEBAIC0xMDYxLDE3ICsxMDc1LDEyIEBAIGludCBtd2lmaWV4X2Ry
dl9pbmZvX2R1bXAoc3RydWN0DQo+IG13aWZpZXhfYWRhcHRlciAqYWRhcHRlciwgdm9pZCAqKmRy
dl9pbmZvKQ0KPiA+ICAJaW50IGksIGlkeDsNCj4gPiAgCXN0cnVjdCBuZXRkZXZfcXVldWUgKnR4
cTsNCj4gPiAgCXN0cnVjdCBtd2lmaWV4X2RlYnVnX2luZm8gKmRlYnVnX2luZm87DQo+ID4gLQl2
b2lkICpkcnZfaW5mb19kdW1wOw0KPiA+DQo+ID4gIAltd2lmaWV4X2RiZyhhZGFwdGVyLCBNU0cs
ICI9PT1td2lmaWV4IGRyaXZlcmluZm8gZHVtcCBzdGFydD09PVxuIik7DQo+ID4NCj4gPiAtCS8q
IG1lbW9yeSBhbGxvY2F0ZSBoZXJlIHNob3VsZCBiZSBmcmVlIGluIG13aWZpZXhfdXBsb2FkX2Rl
dmljZV9kdW1wKi8NCj4gPiAtCWRydl9pbmZvX2R1bXAgPSB2emFsbG9jKE1XSUZJRVhfRFJWX0lO
Rk9fU0laRV9NQVgpOw0KPiA+IC0NCj4gPiAtCWlmICghZHJ2X2luZm9fZHVtcCkNCj4gPiAtCQly
ZXR1cm4gMDsNCj4gPiAtDQo+ID4gLQlwID0gKGNoYXIgKikoZHJ2X2luZm9fZHVtcCk7DQo+ID4g
KwlwID0gYWRhcHRlci0+ZGV2ZHVtcF9kYXRhOw0KPiA+ICsJc3RyY3B5KHAsICI9PT09PT09PVN0
YXJ0IGR1bXAgZHJpdmVyaW5mbz09PT09PT09XG4iKTsNCj4gPiArCXAgKz0gc3RybGVuKCI9PT09
PT09PVN0YXJ0IGR1bXAgZHJpdmVyaW5mbz09PT09PT09XG4iKTsNCj4gPiAgCXAgKz0gc3ByaW50
ZihwLCAiZHJpdmVyX25hbWUgPSAiICJcIm13aWZpZXhcIlxuIik7DQo+ID4NCj4gPiAgCW13aWZp
ZXhfZHJ2X2dldF9kcml2ZXJfdmVyc2lvbihhZGFwdGVyLCBkcnZfdmVyc2lvbiwgQEAgLTExNTUs
MjENCj4gPiArMTE2NCwxOCBAQCBpbnQgbXdpZmlleF9kcnZfaW5mb19kdW1wKHN0cnVjdCBtd2lm
aWV4X2FkYXB0ZXIgKmFkYXB0ZXIsDQo+IHZvaWQgKipkcnZfaW5mbykNCj4gPiAgCQlrZnJlZShk
ZWJ1Z19pbmZvKTsNCj4gPiAgCX0NCj4gPg0KPiA+ICsJc3RyY3B5KHAsICJcbj09PT09PT09RW5k
IGR1bXA9PT09PT09PVxuIik7DQo+ID4gKwlwICs9IHN0cmxlbigiXG49PT09PT09PUVuZCBkdW1w
PT09PT09PT1cbiIpOw0KPiA+ICAJbXdpZmlleF9kYmcoYWRhcHRlciwgTVNHLCAiPT09bXdpZmll
eCBkcml2ZXJpbmZvIGR1bXAgZW5kPT09XG4iKTsNCj4gPiAtCSpkcnZfaW5mbyA9IGRydl9pbmZv
X2R1bXA7DQo+ID4gLQlyZXR1cm4gcCAtIGRydl9pbmZvX2R1bXA7DQo+ID4gKwlhZGFwdGVyLT5k
ZXZkdW1wX2xlbiA9IHAgLSAoY2hhciAqKWFkYXB0ZXItPmRldmR1bXBfZGF0YTsNCj4gPiAgfQ0K
PiA+ICBFWFBPUlRfU1lNQk9MX0dQTChtd2lmaWV4X2Rydl9pbmZvX2R1bXApOw0KPiA+DQo+ID4g
LXZvaWQgbXdpZmlleF91cGxvYWRfZGV2aWNlX2R1bXAoc3RydWN0IG13aWZpZXhfYWRhcHRlciAq
YWRhcHRlciwgdm9pZA0KPiAqZHJ2X2luZm8sDQo+ID4gLQkJCQlpbnQgZHJ2X2luZm9fc2l6ZSkN
Cj4gPiArdm9pZCBtd2lmaWV4X3ByZXBhcmVfZndfZHVtcF9pbmZvKHN0cnVjdCBtd2lmaWV4X2Fk
YXB0ZXIgKmFkYXB0ZXIpDQo+ID4gIHsNCj4gPiAtCXU4IGlkeCwgKmR1bXBfZGF0YSwgKmZ3X2R1
bXBfcHRyOw0KPiA+IC0JdTMyIGR1bXBfbGVuOw0KPiA+IC0NCj4gPiAtCWR1bXBfbGVuID0gKHN0
cmxlbigiPT09PT09PT1TdGFydCBkdW1wIGRyaXZlcmluZm89PT09PT09PVxuIikgKw0KPiA+IC0J
CSAgICAgICBkcnZfaW5mb19zaXplICsNCj4gPiAtCQkgICAgICAgc3RybGVuKCJcbj09PT09PT09
RW5kIGR1bXA9PT09PT09PVxuIikpOw0KPiA+ICsJdTggaWR4Ow0KPiA+ICsJY2hhciAqZndfZHVt
cF9wdHI7DQo+ID4gKwl1MzIgZHVtcF9sZW4gPSAwOw0KPiA+DQo+ID4gIAlmb3IgKGlkeCA9IDA7
IGlkeCA8IGFkYXB0ZXItPm51bV9tZW1fdHlwZXM7IGlkeCsrKSB7DQo+ID4gIAkJc3RydWN0IG1l
bW9yeV90eXBlX21hcHBpbmcgKmVudHJ5ID0gQEAgLTExODQsMjQgKzExOTAsMjQgQEANCj4gdm9p
ZA0KPiA+IG13aWZpZXhfdXBsb2FkX2RldmljZV9kdW1wKHN0cnVjdCBtd2lmaWV4X2FkYXB0ZXIg
KmFkYXB0ZXIsIHZvaWQNCj4gKmRydl9pbmZvLA0KPiA+ICAJCX0NCj4gPiAgCX0NCj4gPg0KPiA+
IC0JZHVtcF9kYXRhID0gdnphbGxvYyhkdW1wX2xlbiArIDEpOw0KPiA+IC0JaWYgKCFkdW1wX2Rh
dGEpDQo+ID4gLQkJZ290byBkb25lOw0KPiA+IC0NCj4gPiAtCWZ3X2R1bXBfcHRyID0gZHVtcF9k
YXRhOw0KPiA+ICsJaWYgKGR1bXBfbGVuICsgMSArIGFkYXB0ZXItPmRldmR1bXBfbGVuID4gTVdJ
RklFWF9GV19EVU1QX1NJWkUpIHsNCj4gPiArCQkvKiBSZWFsbG9jIGluIGNhc2UgYnVmZmVyIG92
ZXJmbG93ICovDQo+ID4gKwkJZndfZHVtcF9wdHIgPSB2emFsbG9jKGR1bXBfbGVuICsgMSArIGFk
YXB0ZXItPmRldmR1bXBfbGVuKTsNCj4gPiArCQltd2lmaWV4X2RiZyhhZGFwdGVyLCBNU0csICJS
ZWFsbG9jIGRldmljZSBkdW1wIGRhdGEuXG4iKTsNCj4gPiArCQlpZiAoIWZ3X2R1bXBfcHRyKSB7
DQo+ID4gKwkJCXZmcmVlKGFkYXB0ZXItPmRldmR1bXBfZGF0YSk7DQo+ID4gKwkJCW13aWZpZXhf
ZGJnKGFkYXB0ZXIsIEVSUk9SLA0KPiA+ICsJCQkJICAgICJ2emFsbG9jIGRldmR1bXAgZGF0YSBm
YWlsdXJlIVxuIik7DQo+ID4gKwkJCXJldHVybjsNCj4gPiArCQl9DQo+ID4NCj4gPiAtCS8qIER1
bXAgYWxsIHRoZSBtZW1vcnkgZGF0YSBpbnRvIHNpbmdsZSBmaWxlLCBhIHVzZXJzcGFjZSBzY3Jp
cHQgd2lsbA0KPiA+IC0JICogYmUgdXNlZCB0byBzcGxpdCBhbGwgdGhlIG1lbW9yeSBkYXRhIHRv
IG11bHRpcGxlIGZpbGVzDQo+ID4gLQkgKi8NCj4gPiAtCW13aWZpZXhfZGJnKGFkYXB0ZXIsIE1T
RywNCj4gPiAtCQkgICAgIj09IG13aWZpZXggZHVtcCBpbmZvcm1hdGlvbiB0byAvc3lzL2NsYXNz
L2RldmNvcmVkdW1wDQo+IHN0YXJ0Iik7DQo+ID4gKwkJbWVtbW92ZShmd19kdW1wX3B0ciwgYWRh
cHRlci0+ZGV2ZHVtcF9kYXRhLA0KPiA+ICsJCQlhZGFwdGVyLT5kZXZkdW1wX2xlbik7DQo+ID4g
KwkJdmZyZWUoYWRhcHRlci0+ZGV2ZHVtcF9kYXRhKTsNCj4gPiArCQlhZGFwdGVyLT5kZXZkdW1w
X2RhdGEgPSBmd19kdW1wX3B0cjsNCj4gPiArCX0NCj4gPg0KPiA+IC0Jc3RyY3B5KGZ3X2R1bXBf
cHRyLCAiPT09PT09PT1TdGFydCBkdW1wIGRyaXZlcmluZm89PT09PT09PVxuIik7DQo+ID4gLQlm
d19kdW1wX3B0ciArPSBzdHJsZW4oIj09PT09PT09U3RhcnQgZHVtcCBkcml2ZXJpbmZvPT09PT09
PT1cbiIpOw0KPiA+IC0JbWVtY3B5KGZ3X2R1bXBfcHRyLCBkcnZfaW5mbywgZHJ2X2luZm9fc2l6
ZSk7DQo+ID4gLQlmd19kdW1wX3B0ciArPSBkcnZfaW5mb19zaXplOw0KPiA+IC0Jc3RyY3B5KGZ3
X2R1bXBfcHRyLCAiXG49PT09PT09PUVuZCBkdW1wPT09PT09PT1cbiIpOw0KPiA+IC0JZndfZHVt
cF9wdHIgKz0gc3RybGVuKCJcbj09PT09PT09RW5kIGR1bXA9PT09PT09PVxuIik7DQo+ID4gKwlm
d19kdW1wX3B0ciA9IChjaGFyICopYWRhcHRlci0+ZGV2ZHVtcF9kYXRhICsNCj4gYWRhcHRlci0+
ZGV2ZHVtcF9sZW47DQo+ID4NCj4gPiAgCWZvciAoaWR4ID0gMDsgaWR4IDwgYWRhcHRlci0+bnVt
X21lbV90eXBlczsgaWR4KyspIHsNCj4gPiAgCQlzdHJ1Y3QgbWVtb3J5X3R5cGVfbWFwcGluZyAq
ZW50cnkgPSBAQCAtMTIyOCwxMSArMTIzNCw4IEBADQo+IHZvaWQNCj4gPiBtd2lmaWV4X3VwbG9h
ZF9kZXZpY2VfZHVtcChzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVyLCB2b2lkDQo+ICpk
cnZfaW5mbywNCj4gPiAgCS8qIGRldmljZSBkdW1wIGRhdGEgd2lsbCBiZSBmcmVlIGluIGRldmlj
ZSBjb3JlZHVtcCByZWxlYXNlIGZ1bmN0aW9uDQo+ID4gIAkgKiBhZnRlciA1IG1pbg0KPiA+ICAJ
ICovDQo+IA0KPiBeXiBUaGlzIGNvbW1lbnQgaXMgYSBiaXQgb3V0IG9mIHBsYWNlIG5vdy4gVGhl
IGRhdGEgaXMgbm90IGR1bXBlZCB1bnRpbCB3ZSBjYWxsDQo+IG13aWZpZXhfdXBsb2FkX2Rldmlj
ZV9kdW1wKCksIGFuZCBzbyB3ZSBkb24ndCBndWFyYW50ZWUgYW55b25lIHdpbGwNCj4gYWN0dWFs
bHkgZnJlZSBpdCBmb3IgdXMgdW50aWwgdGhlbg0KPiANCg0KT2suDQoNCj4gPiAtCWRldl9jb3Jl
ZHVtcHYoYWRhcHRlci0+ZGV2LCBkdW1wX2RhdGEsIGR1bXBfbGVuLCBHRlBfS0VSTkVMKTsNCj4g
PiAtCW13aWZpZXhfZGJnKGFkYXB0ZXIsIE1TRywNCj4gPiAtCQkgICAgIj09IG13aWZpZXggZHVt
cCBpbmZvcm1hdGlvbiB0byAvc3lzL2NsYXNzL2RldmNvcmVkdW1wIGVuZCIpOw0KPiA+ICsJYWRh
cHRlci0+ZGV2ZHVtcF9sZW4gPSBmd19kdW1wX3B0ciAtIChjaGFyICopYWRhcHRlci0+ZGV2ZHVt
cF9kYXRhOw0KPiA+DQo+ID4gLWRvbmU6DQo+ID4gIAlmb3IgKGlkeCA9IDA7IGlkeCA8IGFkYXB0
ZXItPm51bV9tZW1fdHlwZXM7IGlkeCsrKSB7DQo+ID4gIAkJc3RydWN0IG1lbW9yeV90eXBlX21h
cHBpbmcgKmVudHJ5ID0NCj4gPiAgCQkJJmFkYXB0ZXItPm1lbV90eXBlX21hcHBpbmdfdGJsW2lk
eF07DQo+ID4gQEAgLTEyNDEsMTAgKzEyNDQsOCBAQCB2b2lkIG13aWZpZXhfdXBsb2FkX2Rldmlj
ZV9kdW1wKHN0cnVjdA0KPiBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIsIHZvaWQgKmRydl9pbmZv
LA0KPiA+ICAJCWVudHJ5LT5tZW1fcHRyID0gTlVMTDsNCj4gPiAgCQllbnRyeS0+bWVtX3NpemUg
PSAwOw0KPiA+ICAJfQ0KPiA+IC0NCj4gPiAtCXZmcmVlKGRydl9pbmZvKTsNCj4gPiAgfQ0KPiA+
IC1FWFBPUlRfU1lNQk9MX0dQTChtd2lmaWV4X3VwbG9hZF9kZXZpY2VfZHVtcCk7DQo+ID4gK0VY
UE9SVF9TWU1CT0xfR1BMKG13aWZpZXhfcHJlcGFyZV9md19kdW1wX2luZm8pOw0KPiA+DQo+ID4g
IC8qDQo+ID4gICAqIENGRzgwMi4xMSBuZXR3b3JrIGRldmljZSBoYW5kbGVyIGZvciBzdGF0aXN0
aWNzIHJldHJpZXZhbC4NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFy
dmVsbC9td2lmaWV4L21haW4uaA0KPiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9t
d2lmaWV4L21haW4uaA0KPiA+IGluZGV4IDE1NGMwNzkuLjhiNjI0MWEgMTAwNjQ0DQo+ID4gLS0t
IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L21haW4uaA0KPiA+ICsrKyBi
L2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9tYWluLmgNCj4gPiBAQCAtOTQs
NiArOTQsOCBAQCBlbnVtIHsNCj4gPg0KPiA+ICAjZGVmaW5lIE1BWF9FVkVOVF9TSVpFICAgICAg
ICAgICAgICAgICAgMjA0OA0KPiA+DQo+ID4gKyNkZWZpbmUgTVdJRklFWF9GV19EVU1QX1NJWkUg
ICAgICAgKDIgKiAxMDI0ICogMTAyNCkNCj4gPiArDQo+ID4gICNkZWZpbmUgQVJQX0ZJTFRFUl9N
QVhfQlVGX1NJWkUgICAgICAgICA2OA0KPiA+DQo+ID4gICNkZWZpbmUgTVdJRklFWF9LRVlfQlVG
RkVSX1NJWkUJCQkxNg0KPiA+IEBAIC0xMDMyLDYgKzEwMzQsOSBAQCBzdHJ1Y3QgbXdpZmlleF9h
ZGFwdGVyIHsNCj4gPiAgCWJvb2wgd2FrZV9ieV93aWZpOw0KPiA+ICAJLyogQWdncmVnYXRpb24g
cGFyYW1ldGVycyovDQo+ID4gIAlzdHJ1Y3QgYnVzX2FnZ3JfcGFyYW1zIGJ1c19hZ2dyOw0KPiA+
ICsJLyogRGV2aWNlIGR1bXAgZGF0YS9sZW5ndGggKi8NCj4gPiArCXZvaWQgKmRldmR1bXBfZGF0
YTsNCj4gPiArCWludCBkZXZkdW1wX2xlbjsNCj4gPiAgfTsNCj4gPg0KPiA+ICB2b2lkIG13aWZp
ZXhfcHJvY2Vzc190eF9xdWV1ZShzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVyKTsgQEAN
Cj4gPiAtMTY1Niw5ICsxNjYxLDkgQEAgdm9pZCBtd2lmaWV4X2hpc3RfZGF0YV9hZGQoc3RydWN0
IG13aWZpZXhfcHJpdmF0ZQ0KPiA+ICpwcml2LA0KPiA+ICB1OCBtd2lmaWV4X2FkanVzdF9kYXRh
X3JhdGUoc3RydWN0IG13aWZpZXhfcHJpdmF0ZSAqcHJpdiwNCj4gPiAgCQkJICAgIHU4IHJ4X3Jh
dGUsIHU4IGh0X2luZm8pOw0KPiA+DQo+ID4gLWludCBtd2lmaWV4X2Rydl9pbmZvX2R1bXAoc3Ry
dWN0IG13aWZpZXhfYWRhcHRlciAqYWRhcHRlciwgdm9pZA0KPiA+ICoqZHJ2X2luZm8pOyAtdm9p
ZCBtd2lmaWV4X3VwbG9hZF9kZXZpY2VfZHVtcChzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyDQo+ICph
ZGFwdGVyLCB2b2lkICpkcnZfaW5mbywNCj4gPiAtCQkJCWludCBkcnZfaW5mb19zaXplKTsNCj4g
PiArdm9pZCBtd2lmaWV4X2Rydl9pbmZvX2R1bXAoc3RydWN0IG13aWZpZXhfYWRhcHRlciAqYWRh
cHRlcik7IHZvaWQNCj4gPiArbXdpZmlleF9wcmVwYXJlX2Z3X2R1bXBfaW5mbyhzdHJ1Y3QgbXdp
ZmlleF9hZGFwdGVyICphZGFwdGVyKTsgdm9pZA0KPiA+ICttd2lmaWV4X3VwbG9hZF9kZXZpY2Vf
ZHVtcChzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVyKTsNCj4gPiAgdm9pZCAqbXdpZmll
eF9hbGxvY19kbWFfYWxpZ25fYnVmKGludCByeF9sZW4sIGdmcF90IGZsYWdzKTsgIHZvaWQNCj4g
PiBtd2lmaWV4X3F1ZXVlX21haW5fd29yayhzdHJ1Y3QgbXdpZmlleF9hZGFwdGVyICphZGFwdGVy
KTsgIGludA0KPiA+IG13aWZpZXhfZ2V0X3dha2V1cF9yZWFzb24oc3RydWN0IG13aWZpZXhfcHJp
dmF0ZSAqcHJpdiwgdTE2IGFjdGlvbiwNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2ly
ZWxlc3MvbWFydmVsbC9td2lmaWV4L3BjaWUuYw0KPiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3Mv
bWFydmVsbC9td2lmaWV4L3BjaWUuYw0KPiA+IGluZGV4IGNkMzE0OTQuLmY2NjZjYjIgMTAwNjQ0
DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3BjaWUuYw0K
PiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdpZmlleC9wY2llLmMNCj4g
PiBAQCAtMjc2OSwxMiArMjc2OSwxNyBAQCBzdGF0aWMgdm9pZCBtd2lmaWV4X3BjaWVfZndfZHVt
cChzdHJ1Y3QNCj4gPiBtd2lmaWV4X2FkYXB0ZXIgKmFkYXB0ZXIpDQo+ID4NCj4gPiAgc3RhdGlj
IHZvaWQgbXdpZmlleF9wY2llX2RldmljZV9kdW1wX3dvcmsoc3RydWN0IG13aWZpZXhfYWRhcHRl
cg0KPiA+ICphZGFwdGVyKSAgew0KPiA+IC0JaW50IGRydl9pbmZvX3NpemU7DQo+ID4gLQl2b2lk
ICpkcnZfaW5mbzsNCj4gPiArCWFkYXB0ZXItPmRldmR1bXBfZGF0YSA9IHZ6YWxsb2MoTVdJRklF
WF9GV19EVU1QX1NJWkUpOw0KPiANCj4gSSdtIHN0aWxsIG5vdCBzdXJlIHdoeSB5b3UgbmVlZCAz
IGRpZmZlcmVudCBjYWxsZXJzIHRvIGFsbG9jYXRlIHRoZSBzYW1lIHNpemUNCj4gYnVmZmVyLiBJ
dCBzZWVtcyBsaWtlIHRoaXMgc2hvdWxkIGFsbCBiZSBkb25lIGluIHRoZSBjb3JlLg0KPiANCg0K
SSBoYWQgdGhvdWdodCBvZiBwdXQgbWVtb3J5IGFsbG9jYXRpb24gYW5kIGRydl9pbmZvX2R1bXAg
aW50byAxIGZ1bmN0aW9uICwgYW5kIGxldCBpdCBjYWxsZWQgaW4gZGV2aWNlX2R1bXAuDQpCdXQg
aXQgbG9va3MgcXVpdGUgc3RyYW5nZS4NCkNvbnNpZGVyIHRoZSBkaWZmZXJlbnQgaW1wbGVtZW50
YXRpb24gb24gdXNiLCBsZXQgdGhlc2Ugc3ViIGZ1bmN0aW9ucyB3b3JrcyBpbiBhIGxvb3NlIGNv
dXBsaW5nIHdheSBzZWVtcyBiZXR0ZXIgdG8gcmV1c2UgdGhhbiBhICJjb3JlIiBhcmNoaXRlY3R1
cmUuDQoNClBsZWFzZSBsZXQgdXMga25vdyBpZiB5b3UgaGF2ZSBtb3JlIHN1Z2dlc3Rpb25zIHRv
IGVuaGFuY2UgdGhpcyBwYXJ0DQoNClRoYW5rcyAmIFJlZ2FyZHMsDQpTaW1vbg0KDQo+IEJyaWFu
DQo+IA0KPiA+ICsJaWYgKCFhZGFwdGVyLT5kZXZkdW1wX2RhdGEpIHsNCj4gPiArCQltd2lmaWV4
X2RiZyhhZGFwdGVyLCBFUlJPUiwNCj4gPiArCQkJICAgICJ2emFsbG9jIGRldmR1bXAgZGF0YSBm
YWlsdXJlIVxuIik7DQo+ID4gKwkJcmV0dXJuOw0KPiA+ICsJfQ0KPiA+DQo+ID4gLQlkcnZfaW5m
b19zaXplID0gbXdpZmlleF9kcnZfaW5mb19kdW1wKGFkYXB0ZXIsICZkcnZfaW5mbyk7DQo+ID4g
Kwltd2lmaWV4X2Rydl9pbmZvX2R1bXAoYWRhcHRlcik7DQo+ID4gIAltd2lmaWV4X3BjaWVfZndf
ZHVtcChhZGFwdGVyKTsNCj4gPiAtCW13aWZpZXhfdXBsb2FkX2RldmljZV9kdW1wKGFkYXB0ZXIs
IGRydl9pbmZvLCBkcnZfaW5mb19zaXplKTsNCj4gPiArCW13aWZpZXhfcHJlcGFyZV9md19kdW1w
X2luZm8oYWRhcHRlcik7DQo+ID4gKwltd2lmaWV4X3VwbG9hZF9kZXZpY2VfZHVtcChhZGFwdGVy
KTsNCj4gPiAgfQ0KPiA+DQo+ID4gIHN0YXRpYyB2b2lkIG13aWZpZXhfcGNpZV9jYXJkX3Jlc2V0
X3dvcmsoc3RydWN0IG13aWZpZXhfYWRhcHRlcg0KPiA+ICphZGFwdGVyKSBkaWZmIC0tZ2l0IGEv
ZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3NkaW8uYw0KPiA+IGIvZHJpdmVy
cy9uZXQvd2lyZWxlc3MvbWFydmVsbC9td2lmaWV4L3NkaW8uYw0KPiA+IGluZGV4IGZkNTE4M2Mu
LmE4Mjg4MDEgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbWFydmVsbC9t
d2lmaWV4L3NkaW8uYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL21hcnZlbGwvbXdp
ZmlleC9zZGlvLmMNCj4gPiBAQCAtMjUwNSwxNSArMjUwNSwyMSBAQCBzdGF0aWMgdm9pZA0KPiA+
IG13aWZpZXhfc2Rpb19nZW5lcmljX2Z3X2R1bXAoc3RydWN0IG13aWZpZXhfYWRhcHRlciAqYWRh
cHRlcikgIHN0YXRpYw0KPiA+IHZvaWQgbXdpZmlleF9zZGlvX2RldmljZV9kdW1wX3dvcmsoc3Ry
dWN0IG13aWZpZXhfYWRhcHRlciAqYWRhcHRlcikgIHsNCj4gPiAgCXN0cnVjdCBzZGlvX21tY19j
YXJkICpjYXJkID0gYWRhcHRlci0+Y2FyZDsNCj4gPiAtCWludCBkcnZfaW5mb19zaXplOw0KPiA+
IC0Jdm9pZCAqZHJ2X2luZm87DQo+ID4NCj4gPiAtCWRydl9pbmZvX3NpemUgPSBtd2lmaWV4X2Ry
dl9pbmZvX2R1bXAoYWRhcHRlciwgJmRydl9pbmZvKTsNCj4gPiArCWFkYXB0ZXItPmRldmR1bXBf
ZGF0YSA9IHZ6YWxsb2MoTVdJRklFWF9GV19EVU1QX1NJWkUpOw0KPiA+ICsJaWYgKCFhZGFwdGVy
LT5kZXZkdW1wX2RhdGEpIHsNCj4gPiArCQltd2lmaWV4X2RiZyhhZGFwdGVyLCBFUlJPUiwNCj4g
PiArCQkJICAgICJ2emFsbG9jIGRldmR1bXAgZGF0YSBmYWlsdXJlIVxuIik7DQo+ID4gKwkJcmV0
dXJuOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCW13aWZpZXhfZHJ2X2luZm9fZHVtcChhZGFwdGVy
KTsNCj4gPiAgCWlmIChjYXJkLT5md19kdW1wX2VuaCkNCj4gPiAgCQltd2lmaWV4X3NkaW9fZ2Vu
ZXJpY19md19kdW1wKGFkYXB0ZXIpOw0KPiA+ICAJZWxzZQ0KPiA+ICAJCW13aWZpZXhfc2Rpb19m
d19kdW1wKGFkYXB0ZXIpOw0KPiA+IC0JbXdpZmlleF91cGxvYWRfZGV2aWNlX2R1bXAoYWRhcHRl
ciwgZHJ2X2luZm8sIGRydl9pbmZvX3NpemUpOw0KPiA+ICsJbXdpZmlleF9wcmVwYXJlX2Z3X2R1
bXBfaW5mbyhhZGFwdGVyKTsNCj4gPiArCW13aWZpZXhfdXBsb2FkX2RldmljZV9kdW1wKGFkYXB0
ZXIpOw0KPiA+ICB9DQo+ID4NCj4gPiAgc3RhdGljIHZvaWQgbXdpZmlleF9zZGlvX3dvcmsoc3Ry
dWN0IHdvcmtfc3RydWN0ICp3b3JrKQ0KPiA+IC0tDQo+ID4gMS45LjENCj4gPg0K