1*5113495bSYour Name /*
2*5113495bSYour Name * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3*5113495bSYour Name *
4*5113495bSYour Name * Permission to use, copy, modify, and/or distribute this software for
5*5113495bSYour Name * any purpose with or without fee is hereby granted, provided that the
6*5113495bSYour Name * above copyright notice and this permission notice appear in all
7*5113495bSYour Name * copies.
8*5113495bSYour Name *
9*5113495bSYour Name * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10*5113495bSYour Name * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11*5113495bSYour Name * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12*5113495bSYour Name * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13*5113495bSYour Name * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14*5113495bSYour Name * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15*5113495bSYour Name * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*5113495bSYour Name * PERFORMANCE OF THIS SOFTWARE.
17*5113495bSYour Name */
18*5113495bSYour Name
19*5113495bSYour Name #include <htt.h>
20*5113495bSYour Name #include "dp_types.h"
21*5113495bSYour Name #include "dp_internal.h"
22*5113495bSYour Name #include "dp_rh_htt.h"
23*5113495bSYour Name #include "dp_rh_rx.h"
24*5113495bSYour Name #include "qdf_mem.h"
25*5113495bSYour Name #include "cdp_txrx_cmn_struct.h"
26*5113495bSYour Name #include "dp_tx_desc.h"
27*5113495bSYour Name #include "dp_rh.h"
28*5113495bSYour Name
29*5113495bSYour Name #define HTT_MSG_BUF_SIZE(msg_bytes) \
30*5113495bSYour Name ((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
31*5113495bSYour Name
32*5113495bSYour Name #define HTT_T2H_MSG_BUF_REINIT(_buf, dev) \
33*5113495bSYour Name do { \
34*5113495bSYour Name qdf_nbuf_push_head(_buf, (HTC_HEADER_LEN) + \
35*5113495bSYour Name HTC_HDR_ALIGNMENT_PADDING); \
36*5113495bSYour Name qdf_nbuf_init_fast((_buf)); \
37*5113495bSYour Name qdf_mem_dma_sync_single_for_device(dev, \
38*5113495bSYour Name (QDF_NBUF_CB_PADDR(_buf)), \
39*5113495bSYour Name (skb_end_pointer(_buf) - \
40*5113495bSYour Name (_buf)->data), \
41*5113495bSYour Name PCI_DMA_FROMDEVICE); \
42*5113495bSYour Name } while (0)
43*5113495bSYour Name
44*5113495bSYour Name /**
45*5113495bSYour Name * dp_htt_flow_pool_map_handler_rh() - HTT_T2H_MSG_TYPE_FLOW_POOL_MAP handler
46*5113495bSYour Name * @soc: Handle to DP Soc structure
47*5113495bSYour Name * @flow_id: flow id
48*5113495bSYour Name * @flow_type: flow type
49*5113495bSYour Name * @flow_pool_id: pool id
50*5113495bSYour Name * @flow_pool_size: pool size
51*5113495bSYour Name *
52*5113495bSYour Name * Return: QDF_STATUS_SUCCESS - success, others - failure
53*5113495bSYour Name */
54*5113495bSYour Name static QDF_STATUS
dp_htt_flow_pool_map_handler_rh(struct dp_soc * soc,uint8_t flow_id,uint8_t flow_type,uint8_t flow_pool_id,uint32_t flow_pool_size)55*5113495bSYour Name dp_htt_flow_pool_map_handler_rh(struct dp_soc *soc, uint8_t flow_id,
56*5113495bSYour Name uint8_t flow_type, uint8_t flow_pool_id,
57*5113495bSYour Name uint32_t flow_pool_size)
58*5113495bSYour Name {
59*5113495bSYour Name struct dp_vdev *vdev;
60*5113495bSYour Name struct dp_pdev *pdev;
61*5113495bSYour Name QDF_STATUS status;
62*5113495bSYour Name
63*5113495bSYour Name if (flow_pool_id >= MAX_TXDESC_POOLS) {
64*5113495bSYour Name dp_err("invalid flow_pool_id %d", flow_pool_id);
65*5113495bSYour Name return QDF_STATUS_E_INVAL;
66*5113495bSYour Name }
67*5113495bSYour Name
68*5113495bSYour Name vdev = dp_vdev_get_ref_by_id(soc, flow_id, DP_MOD_ID_HTT);
69*5113495bSYour Name if (vdev) {
70*5113495bSYour Name pdev = vdev->pdev;
71*5113495bSYour Name dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT);
72*5113495bSYour Name } else {
73*5113495bSYour Name pdev = soc->pdev_list[0];
74*5113495bSYour Name }
75*5113495bSYour Name
76*5113495bSYour Name status = dp_tx_flow_pool_map_handler(pdev, flow_id, flow_type,
77*5113495bSYour Name flow_pool_id, flow_pool_size);
78*5113495bSYour Name if (QDF_IS_STATUS_ERROR(status)) {
79*5113495bSYour Name dp_err("failed to create tx flow pool %d", flow_pool_id);
80*5113495bSYour Name goto err_out;
81*5113495bSYour Name }
82*5113495bSYour Name
83*5113495bSYour Name return QDF_STATUS_SUCCESS;
84*5113495bSYour Name
85*5113495bSYour Name err_out:
86*5113495bSYour Name /* TODO: is assert needed ? */
87*5113495bSYour Name qdf_assert_always(0);
88*5113495bSYour Name return status;
89*5113495bSYour Name }
90*5113495bSYour Name
91*5113495bSYour Name /**
92*5113495bSYour Name * dp_htt_flow_pool_unmap_handler_rh() - HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP handler
93*5113495bSYour Name * @soc: Handle to DP Soc structure
94*5113495bSYour Name * @flow_id: flow id
95*5113495bSYour Name * @flow_type: flow type
96*5113495bSYour Name * @flow_pool_id: pool id
97*5113495bSYour Name *
98*5113495bSYour Name * Return: none
99*5113495bSYour Name */
100*5113495bSYour Name static void
dp_htt_flow_pool_unmap_handler_rh(struct dp_soc * soc,uint8_t flow_id,uint8_t flow_type,uint8_t flow_pool_id)101*5113495bSYour Name dp_htt_flow_pool_unmap_handler_rh(struct dp_soc *soc, uint8_t flow_id,
102*5113495bSYour Name uint8_t flow_type, uint8_t flow_pool_id)
103*5113495bSYour Name {
104*5113495bSYour Name struct dp_vdev *vdev;
105*5113495bSYour Name struct dp_pdev *pdev;
106*5113495bSYour Name
107*5113495bSYour Name if (flow_pool_id >= MAX_TXDESC_POOLS) {
108*5113495bSYour Name dp_err("invalid flow_pool_id %d", flow_pool_id);
109*5113495bSYour Name return;
110*5113495bSYour Name }
111*5113495bSYour Name
112*5113495bSYour Name vdev = dp_vdev_get_ref_by_id(soc, flow_id, DP_MOD_ID_HTT);
113*5113495bSYour Name if (vdev) {
114*5113495bSYour Name pdev = vdev->pdev;
115*5113495bSYour Name dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT);
116*5113495bSYour Name } else {
117*5113495bSYour Name pdev = soc->pdev_list[0];
118*5113495bSYour Name }
119*5113495bSYour Name
120*5113495bSYour Name dp_tx_flow_pool_unmap_handler(pdev, flow_id, flow_type,
121*5113495bSYour Name flow_pool_id);
122*5113495bSYour Name }
123*5113495bSYour Name
124*5113495bSYour Name /*
125*5113495bSYour Name * dp_htt_h2t_send_complete_free_netbuf() - Free completed buffer
126*5113495bSYour Name * @soc: SOC handle
127*5113495bSYour Name * @status: Completion status
128*5113495bSYour Name * @netbuf: HTT buffer
129*5113495bSYour Name */
130*5113495bSYour Name static void
dp_htt_h2t_send_complete_free_netbuf(void * soc,A_STATUS status,qdf_nbuf_t netbuf)131*5113495bSYour Name dp_htt_h2t_send_complete_free_netbuf(
132*5113495bSYour Name void *soc, A_STATUS status, qdf_nbuf_t netbuf)
133*5113495bSYour Name {
134*5113495bSYour Name qdf_nbuf_free(netbuf);
135*5113495bSYour Name }
136*5113495bSYour Name
dp_htt_h2t_rx_ring_rfs_cfg(struct htt_soc * soc)137*5113495bSYour Name QDF_STATUS dp_htt_h2t_rx_ring_rfs_cfg(struct htt_soc *soc)
138*5113495bSYour Name {
139*5113495bSYour Name struct dp_htt_htc_pkt *pkt;
140*5113495bSYour Name qdf_nbuf_t msg;
141*5113495bSYour Name uint32_t *msg_word;
142*5113495bSYour Name QDF_STATUS status;
143*5113495bSYour Name uint8_t *htt_logger_bufp;
144*5113495bSYour Name
145*5113495bSYour Name /*
146*5113495bSYour Name * TODO check do we need ini support in Evros
147*5113495bSYour Name * Receive flow steering configuration,
148*5113495bSYour Name * disable gEnableFlowSteering(=0) in ini if
149*5113495bSYour Name * FW doesn't support it
150*5113495bSYour Name */
151*5113495bSYour Name
152*5113495bSYour Name /* reserve room for the HTC header */
153*5113495bSYour Name msg = qdf_nbuf_alloc(soc->osdev,
154*5113495bSYour Name HTT_MSG_BUF_SIZE(HTT_RFS_CFG_REQ_BYTES),
155*5113495bSYour Name HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4,
156*5113495bSYour Name true);
157*5113495bSYour Name if (!msg) {
158*5113495bSYour Name dp_err("htt_msg alloc failed for RFS config");
159*5113495bSYour Name return QDF_STATUS_E_NOMEM;
160*5113495bSYour Name }
161*5113495bSYour Name /*
162*5113495bSYour Name * Set the length of the message.
163*5113495bSYour Name * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
164*5113495bSYour Name * separately during the below call to qdf_nbuf_push_head.
165*5113495bSYour Name * The contribution from the HTC header is added separately inside HTC.
166*5113495bSYour Name */
167*5113495bSYour Name qdf_nbuf_put_tail(msg, HTT_RFS_CFG_REQ_BYTES);
168*5113495bSYour Name
169*5113495bSYour Name /* fill in the message contents */
170*5113495bSYour Name msg_word = (uint32_t *)qdf_nbuf_data(msg);
171*5113495bSYour Name
172*5113495bSYour Name /* rewind beyond alignment pad to get to the HTC header reserved area */
173*5113495bSYour Name qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
174*5113495bSYour Name
175*5113495bSYour Name /* word 0 */
176*5113495bSYour Name *msg_word = 0;
177*5113495bSYour Name htt_logger_bufp = (uint8_t *)msg_word;
178*5113495bSYour Name HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RFS_CONFIG);
179*5113495bSYour Name HTT_RX_RFS_CONFIG_SET(*msg_word, 1);
180*5113495bSYour Name
181*5113495bSYour Name /*
182*5113495bSYour Name * TODO value should be obtained from ini maxMSDUsPerRxInd
183*5113495bSYour Name * currently this ini is legacy ol and available only from cds
184*5113495bSYour Name * make this ini common to HL and evros DP
185*5113495bSYour Name */
186*5113495bSYour Name *msg_word |= ((32 & 0xff) << 16);
187*5113495bSYour Name
188*5113495bSYour Name dp_htt_info("RFS sent to F.W: 0x%08x", *msg_word);
189*5113495bSYour Name
190*5113495bSYour Name /*start*/
191*5113495bSYour Name pkt = htt_htc_pkt_alloc(soc);
192*5113495bSYour Name if (!pkt) {
193*5113495bSYour Name qdf_nbuf_free(msg);
194*5113495bSYour Name return QDF_STATUS_E_NOMEM;
195*5113495bSYour Name }
196*5113495bSYour Name
197*5113495bSYour Name pkt->soc_ctxt = NULL; /* not used during send-done callback */
198*5113495bSYour Name SET_HTC_PACKET_INFO_TX(
199*5113495bSYour Name &pkt->htc_pkt,
200*5113495bSYour Name dp_htt_h2t_send_complete_free_netbuf,
201*5113495bSYour Name qdf_nbuf_data(msg),
202*5113495bSYour Name qdf_nbuf_len(msg),
203*5113495bSYour Name soc->htc_endpoint,
204*5113495bSYour Name HTC_TX_PACKET_TAG_RUNTIME_PUT); /* tag for no FW response msg */
205*5113495bSYour Name
206*5113495bSYour Name SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
207*5113495bSYour Name status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_RFS_CONFIG,
208*5113495bSYour Name htt_logger_bufp);
209*5113495bSYour Name
210*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
211*5113495bSYour Name qdf_nbuf_free(msg);
212*5113495bSYour Name htt_htc_pkt_free(soc, pkt);
213*5113495bSYour Name }
214*5113495bSYour Name
215*5113495bSYour Name return status;
216*5113495bSYour Name }
217*5113495bSYour Name
218*5113495bSYour Name static void
dp_htt_rx_addba_handler_rh(struct dp_soc * soc,uint16_t peer_id,uint8_t tid,uint16_t win_sz)219*5113495bSYour Name dp_htt_rx_addba_handler_rh(struct dp_soc *soc, uint16_t peer_id,
220*5113495bSYour Name uint8_t tid, uint16_t win_sz)
221*5113495bSYour Name {
222*5113495bSYour Name }
223*5113495bSYour Name
224*5113495bSYour Name static QDF_STATUS
dp_htt_rx_delba_ind_handler_rh(void * soc_handle,uint16_t peer_id,uint8_t tid,uint16_t win_sz)225*5113495bSYour Name dp_htt_rx_delba_ind_handler_rh(void *soc_handle, uint16_t peer_id,
226*5113495bSYour Name uint8_t tid, uint16_t win_sz)
227*5113495bSYour Name {
228*5113495bSYour Name return QDF_STATUS_SUCCESS;
229*5113495bSYour Name }
230*5113495bSYour Name
231*5113495bSYour Name /**
232*5113495bSYour Name * dp_htt_t2h_msg_handler_fast() - Fastpath specific message handler
233*5113495bSYour Name * @context: HTT context
234*5113495bSYour Name * @cmpl_msdus: netbuf completions
235*5113495bSYour Name * @num_cmpls: number of completions to be handled
236*5113495bSYour Name *
237*5113495bSYour Name * Return: None
238*5113495bSYour Name */
239*5113495bSYour Name static void
dp_htt_t2h_msg_handler_fast(void * context,qdf_nbuf_t * cmpl_msdus,uint32_t num_cmpls)240*5113495bSYour Name dp_htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus,
241*5113495bSYour Name uint32_t num_cmpls)
242*5113495bSYour Name {
243*5113495bSYour Name struct htt_soc *soc = (struct htt_soc *)context;
244*5113495bSYour Name qdf_nbuf_t htt_t2h_msg;
245*5113495bSYour Name uint32_t *msg_word;
246*5113495bSYour Name uint32_t i;
247*5113495bSYour Name enum htt_t2h_msg_type msg_type;
248*5113495bSYour Name uint32_t msg_len;
249*5113495bSYour Name
250*5113495bSYour Name for (i = 0; i < num_cmpls; i++) {
251*5113495bSYour Name htt_t2h_msg = cmpl_msdus[i];
252*5113495bSYour Name msg_len = qdf_nbuf_len(htt_t2h_msg);
253*5113495bSYour Name
254*5113495bSYour Name /*
255*5113495bSYour Name * Move the data pointer to point to HTT header
256*5113495bSYour Name * past the HTC header + HTC header alignment padding
257*5113495bSYour Name */
258*5113495bSYour Name qdf_nbuf_pull_head(htt_t2h_msg, HTC_HEADER_LEN +
259*5113495bSYour Name HTC_HDR_ALIGNMENT_PADDING);
260*5113495bSYour Name
261*5113495bSYour Name msg_word = (uint32_t *)qdf_nbuf_data(htt_t2h_msg);
262*5113495bSYour Name msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word);
263*5113495bSYour Name
264*5113495bSYour Name switch (msg_type) {
265*5113495bSYour Name case HTT_T2H_MSG_TYPE_RX_DATA_IND:
266*5113495bSYour Name {
267*5113495bSYour Name uint16_t vdev_id, msdu_cnt;
268*5113495bSYour Name uint16_t peer_id, frag_ind;
269*5113495bSYour Name
270*5113495bSYour Name peer_id = HTT_RX_DATA_IND_PEER_ID_GET(*msg_word);
271*5113495bSYour Name frag_ind = HTT_RX_DATA_IND_FRAG_GET(*(msg_word + 1));
272*5113495bSYour Name vdev_id = HTT_RX_DATA_IND_VDEV_ID_GET(*msg_word);
273*5113495bSYour Name
274*5113495bSYour Name if (qdf_unlikely(frag_ind)) {
275*5113495bSYour Name dp_rx_frag_indication_handler(soc->dp_soc,
276*5113495bSYour Name htt_t2h_msg,
277*5113495bSYour Name vdev_id, peer_id);
278*5113495bSYour Name break;
279*5113495bSYour Name }
280*5113495bSYour Name
281*5113495bSYour Name msdu_cnt =
282*5113495bSYour Name HTT_RX_DATA_IND_MSDU_CNT_GET(*(msg_word + 1));
283*5113495bSYour Name dp_rx_data_indication_handler(soc->dp_soc, htt_t2h_msg,
284*5113495bSYour Name vdev_id, peer_id,
285*5113495bSYour Name msdu_cnt);
286*5113495bSYour Name break;
287*5113495bSYour Name }
288*5113495bSYour Name case HTT_T2H_MSG_TYPE_SOFT_UMAC_TX_COMPL_IND:
289*5113495bSYour Name {
290*5113495bSYour Name uint32_t num_msdus;
291*5113495bSYour Name
292*5113495bSYour Name num_msdus = HTT_SOFT_UMAC_TX_COMP_IND_MSDU_COUNT_GET(*msg_word);
293*5113495bSYour Name
294*5113495bSYour Name if ((num_msdus * HTT_TX_MSDU_INFO_SIZE +
295*5113495bSYour Name HTT_SOFT_UMAC_TX_COMPL_IND_SIZE) > msg_len) {
296*5113495bSYour Name dp_htt_err("Invalid msdu count in tx compl indication %d", num_msdus);
297*5113495bSYour Name break;
298*5113495bSYour Name }
299*5113495bSYour Name
300*5113495bSYour Name dp_tx_compl_handler_rh(soc->dp_soc, htt_t2h_msg);
301*5113495bSYour Name break;
302*5113495bSYour Name }
303*5113495bSYour Name case HTT_T2H_MSG_TYPE_RX_PN_IND:
304*5113495bSYour Name {
305*5113495bSYour Name /* TODO check and add PN IND handling */
306*5113495bSYour Name break;
307*5113495bSYour Name }
308*5113495bSYour Name case HTT_T2H_MSG_TYPE_RX_ADDBA:
309*5113495bSYour Name {
310*5113495bSYour Name uint16_t peer_id;
311*5113495bSYour Name uint8_t tid;
312*5113495bSYour Name uint16_t win_sz;
313*5113495bSYour Name
314*5113495bSYour Name /*
315*5113495bSYour Name * Update REO Queue Desc with new values
316*5113495bSYour Name */
317*5113495bSYour Name peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word);
318*5113495bSYour Name tid = HTT_RX_ADDBA_TID_GET(*msg_word);
319*5113495bSYour Name win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word);
320*5113495bSYour Name
321*5113495bSYour Name /*
322*5113495bSYour Name * Window size needs to be incremented by 1
323*5113495bSYour Name * since fw needs to represent a value of 256
324*5113495bSYour Name * using just 8 bits
325*5113495bSYour Name */
326*5113495bSYour Name dp_htt_rx_addba_handler_rh(soc->dp_soc, peer_id,
327*5113495bSYour Name tid, win_sz + 1);
328*5113495bSYour Name break;
329*5113495bSYour Name }
330*5113495bSYour Name case HTT_T2H_MSG_TYPE_RX_DELBA:
331*5113495bSYour Name {
332*5113495bSYour Name uint16_t peer_id;
333*5113495bSYour Name uint8_t tid;
334*5113495bSYour Name uint8_t win_sz;
335*5113495bSYour Name QDF_STATUS status;
336*5113495bSYour Name
337*5113495bSYour Name peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word);
338*5113495bSYour Name tid = HTT_RX_DELBA_TID_GET(*msg_word);
339*5113495bSYour Name win_sz = HTT_RX_DELBA_WIN_SIZE_GET(*msg_word);
340*5113495bSYour Name
341*5113495bSYour Name status = dp_htt_rx_delba_ind_handler_rh(soc->dp_soc,
342*5113495bSYour Name peer_id, tid,
343*5113495bSYour Name win_sz);
344*5113495bSYour Name
345*5113495bSYour Name dp_htt_info("DELBA PeerID %d BAW %d TID %d stat %d",
346*5113495bSYour Name peer_id, win_sz, tid, status);
347*5113495bSYour Name break;
348*5113495bSYour Name }
349*5113495bSYour Name case HTT_T2H_MSG_TYPE_PPDU_STATS_IND:
350*5113495bSYour Name {
351*5113495bSYour Name qdf_nbuf_t nbuf_copy;
352*5113495bSYour Name HTC_PACKET htc_pkt = {0};
353*5113495bSYour Name
354*5113495bSYour Name nbuf_copy = qdf_nbuf_copy(htt_t2h_msg);
355*5113495bSYour Name if (qdf_unlikely(!nbuf_copy)) {
356*5113495bSYour Name dp_htt_err("NBUF copy failed for PPDU stats msg");
357*5113495bSYour Name break;
358*5113495bSYour Name }
359*5113495bSYour Name htc_pkt.Status = QDF_STATUS_SUCCESS;
360*5113495bSYour Name htc_pkt.pPktContext = (void *)nbuf_copy;
361*5113495bSYour Name dp_htt_t2h_msg_handler(context, &htc_pkt);
362*5113495bSYour Name break;
363*5113495bSYour Name }
364*5113495bSYour Name case HTT_T2H_MSG_TYPE_FLOW_POOL_MAP:
365*5113495bSYour Name {
366*5113495bSYour Name uint8_t num_flows;
367*5113495bSYour Name struct htt_flow_pool_map_payload_t *pool_map;
368*5113495bSYour Name
369*5113495bSYour Name num_flows = HTT_FLOW_POOL_MAP_NUM_FLOWS_GET(*msg_word);
370*5113495bSYour Name
371*5113495bSYour Name if (((HTT_FLOW_POOL_MAP_PAYLOAD_SZ /
372*5113495bSYour Name HTT_FLOW_POOL_MAP_HEADER_SZ) * num_flows + 1) * sizeof(*msg_word) > msg_len) {
373*5113495bSYour Name dp_htt_err("Invalid flow count in flow pool map message");
374*5113495bSYour Name WARN_ON(1);
375*5113495bSYour Name break;
376*5113495bSYour Name }
377*5113495bSYour Name
378*5113495bSYour Name msg_word++;
379*5113495bSYour Name
380*5113495bSYour Name while (num_flows) {
381*5113495bSYour Name pool_map = (struct htt_flow_pool_map_payload_t *)msg_word;
382*5113495bSYour Name dp_htt_flow_pool_map_handler_rh(
383*5113495bSYour Name soc->dp_soc, pool_map->flow_id,
384*5113495bSYour Name pool_map->flow_type,
385*5113495bSYour Name pool_map->flow_pool_id,
386*5113495bSYour Name pool_map->flow_pool_size);
387*5113495bSYour Name
388*5113495bSYour Name msg_word += (HTT_FLOW_POOL_MAP_PAYLOAD_SZ /
389*5113495bSYour Name HTT_FLOW_POOL_MAP_HEADER_SZ);
390*5113495bSYour Name num_flows--;
391*5113495bSYour Name }
392*5113495bSYour Name
393*5113495bSYour Name break;
394*5113495bSYour Name }
395*5113495bSYour Name case HTT_T2H_MSG_TYPE_FLOW_POOL_UNMAP:
396*5113495bSYour Name {
397*5113495bSYour Name struct htt_flow_pool_unmap_t *pool_unmap;
398*5113495bSYour Name
399*5113495bSYour Name if (msg_len < sizeof(struct htt_flow_pool_unmap_t)) {
400*5113495bSYour Name dp_htt_err("Invalid length in flow pool unmap message %d", msg_len);
401*5113495bSYour Name WARN_ON(1);
402*5113495bSYour Name break;
403*5113495bSYour Name }
404*5113495bSYour Name
405*5113495bSYour Name pool_unmap = (struct htt_flow_pool_unmap_t *)msg_word;
406*5113495bSYour Name dp_htt_flow_pool_unmap_handler_rh(
407*5113495bSYour Name soc->dp_soc, pool_unmap->flow_id,
408*5113495bSYour Name pool_unmap->flow_type,
409*5113495bSYour Name pool_unmap->flow_pool_id);
410*5113495bSYour Name break;
411*5113495bSYour Name }
412*5113495bSYour Name default:
413*5113495bSYour Name {
414*5113495bSYour Name HTC_PACKET htc_pkt = {0};
415*5113495bSYour Name
416*5113495bSYour Name htc_pkt.Status = QDF_STATUS_SUCCESS;
417*5113495bSYour Name htc_pkt.pPktContext = (void *)htt_t2h_msg;
418*5113495bSYour Name /*
419*5113495bSYour Name * Increment user count to protect buffer
420*5113495bSYour Name * from generic handler free count will be
421*5113495bSYour Name * reset to 1 during MSG_BUF_REINIT
422*5113495bSYour Name */
423*5113495bSYour Name qdf_nbuf_inc_users(htt_t2h_msg);
424*5113495bSYour Name dp_htt_t2h_msg_handler(context, &htc_pkt);
425*5113495bSYour Name break;
426*5113495bSYour Name }
427*5113495bSYour Name }
428*5113495bSYour Name
429*5113495bSYour Name /* Re-initialize the indication buffer */
430*5113495bSYour Name HTT_T2H_MSG_BUF_REINIT(htt_t2h_msg, soc->osdev);
431*5113495bSYour Name qdf_nbuf_set_pktlen(htt_t2h_msg, 0);
432*5113495bSYour Name }
433*5113495bSYour Name }
434*5113495bSYour Name
435*5113495bSYour Name static QDF_STATUS
dp_htt_htc_attach(struct htt_soc * soc,uint16_t service_id)436*5113495bSYour Name dp_htt_htc_attach(struct htt_soc *soc, uint16_t service_id)
437*5113495bSYour Name {
438*5113495bSYour Name struct dp_soc_rh *rh_soc = dp_get_rh_soc_from_dp_soc(soc->dp_soc);
439*5113495bSYour Name struct htc_service_connect_req connect;
440*5113495bSYour Name struct htc_service_connect_resp response;
441*5113495bSYour Name QDF_STATUS status;
442*5113495bSYour Name
443*5113495bSYour Name qdf_mem_zero(&connect, sizeof(connect));
444*5113495bSYour Name qdf_mem_zero(&response, sizeof(response));
445*5113495bSYour Name
446*5113495bSYour Name connect.pMetaData = NULL;
447*5113495bSYour Name connect.MetaDataLength = 0;
448*5113495bSYour Name connect.EpCallbacks.pContext = soc;
449*5113495bSYour Name connect.EpCallbacks.EpTxComplete = dp_htt_h2t_send_complete;
450*5113495bSYour Name connect.EpCallbacks.EpTxCompleteMultiple = NULL;
451*5113495bSYour Name /* fastpath handler will be used instead */
452*5113495bSYour Name connect.EpCallbacks.EpRecv = NULL;
453*5113495bSYour Name
454*5113495bSYour Name /* rx buffers currently are provided by HIF, not by EpRecvRefill */
455*5113495bSYour Name connect.EpCallbacks.EpRecvRefill = NULL;
456*5113495bSYour Name /* N/A, fill is done by HIF */
457*5113495bSYour Name connect.EpCallbacks.RecvRefillWaterMark = 1;
458*5113495bSYour Name
459*5113495bSYour Name connect.EpCallbacks.EpSendFull = dp_htt_h2t_full;
460*5113495bSYour Name /*
461*5113495bSYour Name * Specify how deep to let a queue get before htc_send_pkt will
462*5113495bSYour Name * call the EpSendFull function due to excessive send queue depth.
463*5113495bSYour Name */
464*5113495bSYour Name connect.MaxSendQueueDepth = DP_HTT_MAX_SEND_QUEUE_DEPTH;
465*5113495bSYour Name
466*5113495bSYour Name /* disable flow control for HTT data message service */
467*5113495bSYour Name connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
468*5113495bSYour Name
469*5113495bSYour Name /* connect to control service */
470*5113495bSYour Name connect.service_id = service_id;
471*5113495bSYour Name
472*5113495bSYour Name status = htc_connect_service(soc->htc_soc, &connect, &response);
473*5113495bSYour Name
474*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
475*5113495bSYour Name dp_htt_err("HTC connect svc failed for id:%u", service_id);
476*5113495bSYour Name return status;
477*5113495bSYour Name }
478*5113495bSYour Name
479*5113495bSYour Name if (service_id == HTT_DATA_MSG_SVC)
480*5113495bSYour Name soc->htc_endpoint = response.Endpoint;
481*5113495bSYour Name
482*5113495bSYour Name /* Save the EP_ID of the TX pipe that to be used during TX enqueue */
483*5113495bSYour Name if (service_id == HTT_DATA2_MSG_SVC)
484*5113495bSYour Name rh_soc->tx_endpoint = response.Endpoint;
485*5113495bSYour Name
486*5113495bSYour Name return QDF_STATUS_SUCCESS;
487*5113495bSYour Name }
488*5113495bSYour Name
489*5113495bSYour Name static QDF_STATUS
dp_htt_htc_soc_attach_all(struct htt_soc * soc)490*5113495bSYour Name dp_htt_htc_soc_attach_all(struct htt_soc *soc)
491*5113495bSYour Name {
492*5113495bSYour Name struct dp_soc *dp_soc = soc->dp_soc;
493*5113495bSYour Name int svc_list[3] = {HTT_DATA_MSG_SVC, HTT_DATA2_MSG_SVC,
494*5113495bSYour Name HTT_DATA3_MSG_SVC};
495*5113495bSYour Name QDF_STATUS status;
496*5113495bSYour Name int i;
497*5113495bSYour Name
498*5113495bSYour Name for (i = 0; i < QDF_ARRAY_SIZE(svc_list); i++) {
499*5113495bSYour Name status = dp_htt_htc_attach(soc, svc_list[i]);
500*5113495bSYour Name if (QDF_IS_STATUS_ERROR(status))
501*5113495bSYour Name return status;
502*5113495bSYour Name }
503*5113495bSYour Name
504*5113495bSYour Name dp_hif_update_pipe_callback(dp_soc, (void *)soc,
505*5113495bSYour Name dp_htt_hif_t2h_hp_callback,
506*5113495bSYour Name DP_HTT_T2H_HP_PIPE);
507*5113495bSYour Name
508*5113495bSYour Name /* Register fastpath cb handlers for RX CE's */
509*5113495bSYour Name if (hif_ce_fastpath_cb_register(dp_soc->hif_handle,
510*5113495bSYour Name dp_htt_t2h_msg_handler_fast, soc)) {
511*5113495bSYour Name dp_htt_err("failed to register fastpath callback");
512*5113495bSYour Name return QDF_STATUS_E_FAILURE;
513*5113495bSYour Name }
514*5113495bSYour Name
515*5113495bSYour Name return QDF_STATUS_SUCCESS;
516*5113495bSYour Name }
517*5113495bSYour Name
518*5113495bSYour Name /*
519*5113495bSYour Name * dp_htt_soc_initialize_rh() - SOC level HTT initialization
520*5113495bSYour Name * @htt_soc: Opaque htt SOC handle
521*5113495bSYour Name * @ctrl_psoc: Opaque ctrl SOC handle
522*5113495bSYour Name * @htc_soc: SOC level HTC handle
523*5113495bSYour Name * @hal_soc: Opaque HAL SOC handle
524*5113495bSYour Name * @osdev: QDF device
525*5113495bSYour Name *
526*5113495bSYour Name * Return: HTT handle on success; NULL on failure
527*5113495bSYour Name */
528*5113495bSYour Name void *
dp_htt_soc_initialize_rh(struct htt_soc * htt_soc,struct cdp_ctrl_objmgr_psoc * ctrl_psoc,HTC_HANDLE htc_soc,hal_soc_handle_t hal_soc_hdl,qdf_device_t osdev)529*5113495bSYour Name dp_htt_soc_initialize_rh(struct htt_soc *htt_soc,
530*5113495bSYour Name struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
531*5113495bSYour Name HTC_HANDLE htc_soc,
532*5113495bSYour Name hal_soc_handle_t hal_soc_hdl, qdf_device_t osdev)
533*5113495bSYour Name {
534*5113495bSYour Name struct htt_soc *soc = (struct htt_soc *)htt_soc;
535*5113495bSYour Name
536*5113495bSYour Name soc->osdev = osdev;
537*5113495bSYour Name soc->ctrl_psoc = ctrl_psoc;
538*5113495bSYour Name soc->htc_soc = htc_soc;
539*5113495bSYour Name soc->hal_soc = hal_soc_hdl;
540*5113495bSYour Name
541*5113495bSYour Name if (dp_htt_htc_soc_attach_all(soc))
542*5113495bSYour Name goto fail2;
543*5113495bSYour Name
544*5113495bSYour Name return soc;
545*5113495bSYour Name
546*5113495bSYour Name fail2:
547*5113495bSYour Name return NULL;
548*5113495bSYour Name }
549