xref: /linux/drivers/net/wireless/intel/iwlwifi/fw/dhc-utils.h (revision 1a9239bb4253f9076b5b4b2a1a4e8d7defd77a95)
1 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
2 /*
3  * Copyright (C) 2021, 2025 Intel Corporation
4  */
5 #ifndef __iwl_fw_dhc_utils_h__
6 #define __iwl_fw_dhc_utils_h__
7 
8 #include <linux/types.h>
9 #include "fw/img.h"
10 #include "api/commands.h"
11 #include "api/dhc.h"
12 
13 /**
14  * iwl_dhc_resp_status - return status of DHC response
15  * @fw: firwmware image information
16  * @pkt: response packet, must not be %NULL
17  *
18  * Returns: the status value of the DHC command or (u32)-1 if the
19  *	    response was too short.
20  */
iwl_dhc_resp_status(const struct iwl_fw * fw,struct iwl_rx_packet * pkt)21 static inline u32 iwl_dhc_resp_status(const struct iwl_fw *fw,
22 				      struct iwl_rx_packet *pkt)
23 {
24 	if (iwl_fw_lookup_notif_ver(fw, IWL_ALWAYS_LONG_GROUP,
25 				    DEBUG_HOST_COMMAND, 1) >= 2) {
26 		struct iwl_dhc_cmd_resp *resp = (void *)pkt->data;
27 
28 		if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
29 			return (u32)-1;
30 
31 		return le32_to_cpu(resp->status);
32 	} else {
33 		struct iwl_dhc_cmd_resp_v1 *resp = (void *)pkt->data;
34 
35 		if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
36 			return (u32)-1;
37 
38 		return le32_to_cpu(resp->status);
39 	}
40 }
41 
42 /**
43  * iwl_dhc_resp_data - return data pointer of DHC response
44  * @fw: firwmware image information
45  * @pkt: response packet, must not be %NULL
46  * @len: where to store the length
47  *
48  * Returns: The data pointer, or an ERR_PTR() if the data was
49  *	    not valid (too short).
50  */
iwl_dhc_resp_data(const struct iwl_fw * fw,struct iwl_rx_packet * pkt,unsigned int * len)51 static inline void *iwl_dhc_resp_data(const struct iwl_fw *fw,
52 				      struct iwl_rx_packet *pkt,
53 				      unsigned int *len)
54 {
55 	if (iwl_fw_lookup_notif_ver(fw, IWL_ALWAYS_LONG_GROUP,
56 				    DEBUG_HOST_COMMAND, 1) >= 2) {
57 		struct iwl_dhc_cmd_resp *resp = (void *)pkt->data;
58 
59 		if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
60 			return ERR_PTR(-EINVAL);
61 
62 		*len = iwl_rx_packet_payload_len(pkt) - sizeof(*resp);
63 		return (void *)&resp->data;
64 	} else {
65 		struct iwl_dhc_cmd_resp_v1 *resp = (void *)pkt->data;
66 
67 		if (iwl_rx_packet_payload_len(pkt) < sizeof(*resp))
68 			return ERR_PTR(-EINVAL);
69 
70 		*len = iwl_rx_packet_payload_len(pkt) - sizeof(*resp);
71 		return (void *)&resp->data;
72 	}
73 }
74 
75 #endif  /* __iwl_fw_dhc_utils_h__ */
76