Driver uses a union for copying data to & from management firmware
when interacting with it.
Problem is that the function always copies sizeof(union) while commit
2edbff8dcb5d ("qed: Learn resources from management firmware") is casting
a union elements which is of smaller size [24-byte instead of 88-bytes].

Also, the union contains some inappropriate elements which increase its
size [should have been 32-bytes]. While this shouldn't corrupt other
PF messages to the MFW [as management firmware enforces permissions so
that each PF is allowed to write only to its own mailbox] we fix this
here as well.

Fixes: 2edbff8dcb5d ("qed: Learn resources from management firmware")
Signed-off-by: Yuval Mintz <yuval.mi...@cavium.com>
---
Hi Dave,

This fix is intended for `net-next' [as its fixing a patch not
yet in `net'].

Thanks,
Yuval
---
 drivers/net/ethernet/qlogic/qed/qed_hsi.h |  1 -
 drivers/net/ethernet/qlogic/qed/qed_mcp.c | 16 ++++++++++++----
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h 
b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index 048f9a3..f5a4ebb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -8581,7 +8581,6 @@ struct resource_info {
        struct drv_version_stc drv_version;
 
        struct lan_stats_stc lan_stats;
-       u64 reserved_stats[11];
        struct ocbb_data_stc ocbb_info;
        struct temperature_status_stc temp_info;
        struct resource_info resource;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c 
b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index d8e499e..6dd3ce4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1697,19 +1697,27 @@ int qed_mcp_get_resc_info(struct qed_hwfn *p_hwfn,
                          u32 *p_mcp_resp, u32 *p_mcp_param)
 {
        struct qed_mcp_mb_params mb_params;
-       union drv_union_data *p_union_data;
+       union drv_union_data union_data;
        int rc;
 
        memset(&mb_params, 0, sizeof(mb_params));
+       memset(&union_data, 0, sizeof(union_data));
        mb_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG;
        mb_params.param = QED_RESC_ALLOC_VERSION;
-       p_union_data = (union drv_union_data *)p_resc_info;
-       mb_params.p_data_src = p_union_data;
-       mb_params.p_data_dst = p_union_data;
+
+       /* Need to have a sufficient large struct, as the cmd_and_union
+        * is going to do memcpy from and to it.
+        */
+       memcpy(&union_data.resource, p_resc_info, sizeof(*p_resc_info));
+
+       mb_params.p_data_src = &union_data;
+       mb_params.p_data_dst = &union_data;
        rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
        if (rc)
                return rc;
 
+       /* Copy the data back */
+       memcpy(p_resc_info, &union_data.resource, sizeof(*p_resc_info));
        *p_mcp_resp = mb_params.mcp_resp;
        *p_mcp_param = mb_params.mcp_param;
 
-- 
1.9.3

Reply via email to