Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 1 | /* |
Komal Seelam | b3a3bdf | 2016-02-01 19:22:17 +0530 | [diff] [blame] | 2 | * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 3 | * |
| 4 | * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| 5 | * |
| 6 | * |
| 7 | * Permission to use, copy, modify, and/or distribute this software for |
| 8 | * any purpose with or without fee is hereby granted, provided that the |
| 9 | * above copyright notice and this permission notice appear in all |
| 10 | * copies. |
| 11 | * |
| 12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| 13 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| 14 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| 15 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| 16 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| 17 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| 18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 19 | * PERFORMANCE OF THIS SOFTWARE. |
| 20 | */ |
| 21 | |
| 22 | /* |
| 23 | * This file was originally distributed by Qualcomm Atheros, Inc. |
| 24 | * under proprietary terms before Copyright ownership was assigned |
| 25 | * to the Linux Foundation. |
| 26 | */ |
| 27 | |
| 28 | #include <osdep.h> |
| 29 | #include "a_types.h" |
| 30 | #include "athdefs.h" |
| 31 | #include "osapi_linux.h" |
| 32 | #include "targcfg.h" |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 33 | #include "qdf_lock.h" |
| 34 | #include "qdf_status.h" |
| 35 | #include "qdf_status.h" |
| 36 | #include <qdf_atomic.h> /* qdf_atomic_read */ |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 37 | #include <targaddrs.h> |
| 38 | #include <bmi_msg.h> |
| 39 | #include "hif_io32.h" |
| 40 | #include <hif.h> |
| 41 | #include "regtable.h" |
| 42 | #define ATH_MODULE_NAME hif |
| 43 | #include <a_debug.h> |
| 44 | #include "hif_main.h" |
| 45 | #include "ce_api.h" |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 46 | #include "qdf_trace.h" |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 47 | #ifdef CONFIG_CNSS |
| 48 | #include <net/cnss.h> |
| 49 | #else |
| 50 | #include "cnss_stub.h" |
| 51 | #endif |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 52 | #include "epping_main.h" |
| 53 | #include "hif_debug.h" |
| 54 | |
| 55 | /* Track a BMI transaction that is in progress */ |
| 56 | #ifndef BIT |
| 57 | #define BIT(n) (1 << (n)) |
| 58 | #endif |
| 59 | |
| 60 | enum { |
| 61 | BMI_REQ_SEND_DONE = BIT(0), /* the bmi tx completion */ |
| 62 | BMI_RESP_RECV_DONE = BIT(1), /* the bmi respond is received */ |
| 63 | }; |
| 64 | |
| 65 | struct BMI_transaction { |
| 66 | struct HIF_CE_state *hif_state; |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 67 | qdf_semaphore_t bmi_transaction_sem; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 68 | uint8_t *bmi_request_host; /* Req BMI msg in Host addr space */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 69 | qdf_dma_addr_t bmi_request_CE; /* Req BMI msg in CE addr space */ |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 70 | uint32_t bmi_request_length; /* Length of BMI request */ |
| 71 | uint8_t *bmi_response_host; /* Rsp BMI msg in Host addr space */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 72 | qdf_dma_addr_t bmi_response_CE; /* Rsp BMI msg in CE addr space */ |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 73 | unsigned int bmi_response_length; /* Length of received response */ |
| 74 | unsigned int bmi_timeout_ms; |
| 75 | uint32_t bmi_transaction_flags; /* flags for the transcation */ |
| 76 | }; |
| 77 | |
| 78 | /* |
| 79 | * send/recv completion functions for BMI. |
| 80 | * NB: The "net_buf" parameter is actually just a |
| 81 | * straight buffer, not an sk_buff. |
| 82 | */ |
| 83 | void hif_bmi_send_done(struct CE_handle *copyeng, void *ce_context, |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 84 | void *transfer_context, qdf_dma_addr_t data, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 85 | unsigned int nbytes, |
| 86 | unsigned int transfer_id, unsigned int sw_index, |
| 87 | unsigned int hw_index, uint32_t toeplitz_hash_result) |
| 88 | { |
| 89 | struct BMI_transaction *transaction = |
| 90 | (struct BMI_transaction *)transfer_context; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 91 | |
| 92 | #ifdef BMI_RSP_POLLING |
| 93 | /* |
| 94 | * Fix EV118783, Release a semaphore after sending |
| 95 | * no matter whether a response is been expecting now. |
| 96 | */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 97 | qdf_semaphore_release(&transaction->bmi_transaction_sem); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 98 | #else |
| 99 | /* |
| 100 | * If a response is anticipated, we'll complete the |
| 101 | * transaction if the response has been received. |
| 102 | * If no response is anticipated, complete the |
| 103 | * transaction now. |
| 104 | */ |
| 105 | transaction->bmi_transaction_flags |= BMI_REQ_SEND_DONE; |
| 106 | |
| 107 | /* resp is't needed or has already been received, |
| 108 | * never assume resp comes later then this */ |
| 109 | if (!transaction->bmi_response_CE || |
| 110 | (transaction->bmi_transaction_flags & BMI_RESP_RECV_DONE)) { |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 111 | qdf_semaphore_release(&transaction->bmi_transaction_sem); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 112 | } |
| 113 | #endif |
| 114 | } |
| 115 | |
| 116 | #ifndef BMI_RSP_POLLING |
| 117 | void hif_bmi_recv_data(struct CE_handle *copyeng, void *ce_context, |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 118 | void *transfer_context, qdf_dma_addr_t data, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 119 | unsigned int nbytes, |
| 120 | unsigned int transfer_id, unsigned int flags) |
| 121 | { |
| 122 | struct BMI_transaction *transaction = |
| 123 | (struct BMI_transaction *)transfer_context; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 124 | |
| 125 | transaction->bmi_response_length = nbytes; |
| 126 | transaction->bmi_transaction_flags |= BMI_RESP_RECV_DONE; |
| 127 | |
| 128 | /* when both send/recv are done, the sem can be released */ |
| 129 | if (transaction->bmi_transaction_flags & BMI_REQ_SEND_DONE) { |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 130 | qdf_semaphore_release(&transaction->bmi_transaction_sem); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 131 | } |
| 132 | } |
| 133 | #endif |
| 134 | |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 135 | QDF_STATUS hif_exchange_bmi_msg(struct hif_opaque_softc *hif_ctx, |
| 136 | qdf_dma_addr_t bmi_cmd_da, |
| 137 | qdf_dma_addr_t bmi_rsp_da, |
Komal Seelam | 2a5fa63 | 2016-02-15 10:33:44 +0530 | [diff] [blame] | 138 | uint8_t *bmi_request, |
| 139 | uint32_t request_length, |
| 140 | uint8_t *bmi_response, |
| 141 | uint32_t *bmi_response_lengthp, |
| 142 | uint32_t TimeoutMS) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 143 | { |
Komal Seelam | 644263d | 2016-02-22 20:45:49 +0530 | [diff] [blame] | 144 | struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); |
Komal Seelam | 02cf2f8 | 2016-02-22 20:44:25 +0530 | [diff] [blame] | 145 | struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 146 | struct HIF_CE_pipe_info *send_pipe_info = |
| 147 | &(hif_state->pipe_info[BMI_CE_NUM_TO_TARG]); |
| 148 | struct CE_handle *ce_send_hdl = send_pipe_info->ce_hdl; |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 149 | qdf_dma_addr_t CE_request, CE_response = 0; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 150 | struct BMI_transaction *transaction = NULL; |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 151 | int status = QDF_STATUS_SUCCESS; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 152 | struct HIF_CE_pipe_info *recv_pipe_info = |
| 153 | &(hif_state->pipe_info[BMI_CE_NUM_TO_HOST]); |
| 154 | struct CE_handle *ce_recv = recv_pipe_info->ce_hdl; |
| 155 | unsigned int mux_id = 0; |
| 156 | unsigned int transaction_id = 0xffff; |
| 157 | unsigned int user_flags = 0; |
| 158 | #ifdef BMI_RSP_POLLING |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 159 | qdf_dma_addr_t buf; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 160 | unsigned int completed_nbytes, id, flags; |
| 161 | int i; |
| 162 | #endif |
| 163 | |
| 164 | transaction = |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 165 | (struct BMI_transaction *)qdf_mem_malloc(sizeof(*transaction)); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 166 | if (unlikely(!transaction)) { |
| 167 | HIF_ERROR("%s: no memory", __func__); |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 168 | return QDF_STATUS_E_NOMEM; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 169 | } |
| 170 | transaction_id = (mux_id & MUX_ID_MASK) | |
| 171 | (transaction_id & TRANSACTION_ID_MASK); |
| 172 | #ifdef QCA_WIFI_3_0 |
| 173 | user_flags &= DESC_DATA_FLAG_MASK; |
| 174 | #endif |
| 175 | A_TARGET_ACCESS_LIKELY(scn); |
| 176 | |
| 177 | /* Initialize bmi_transaction_sem to block */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 178 | qdf_semaphore_init(&transaction->bmi_transaction_sem); |
| 179 | qdf_semaphore_acquire(&transaction->bmi_transaction_sem); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 180 | |
| 181 | transaction->hif_state = hif_state; |
| 182 | transaction->bmi_request_host = bmi_request; |
| 183 | transaction->bmi_request_length = request_length; |
| 184 | transaction->bmi_response_length = 0; |
| 185 | transaction->bmi_timeout_ms = TimeoutMS; |
| 186 | transaction->bmi_transaction_flags = 0; |
| 187 | |
| 188 | /* |
| 189 | * CE_request = dma_map_single(dev, |
| 190 | * (void *)bmi_request, request_length, DMA_TO_DEVICE); |
| 191 | */ |
Komal Seelam | 2a5fa63 | 2016-02-15 10:33:44 +0530 | [diff] [blame] | 192 | CE_request = bmi_cmd_da; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 193 | transaction->bmi_request_CE = CE_request; |
| 194 | |
| 195 | if (bmi_response) { |
| 196 | |
| 197 | /* |
| 198 | * CE_response = dma_map_single(dev, bmi_response, |
| 199 | * BMI_DATASZ_MAX, DMA_FROM_DEVICE); |
| 200 | */ |
Komal Seelam | 2a5fa63 | 2016-02-15 10:33:44 +0530 | [diff] [blame] | 201 | CE_response = bmi_rsp_da; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 202 | transaction->bmi_response_host = bmi_response; |
| 203 | transaction->bmi_response_CE = CE_response; |
| 204 | /* dma_cache_sync(dev, bmi_response, |
| 205 | BMI_DATASZ_MAX, DMA_FROM_DEVICE); */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 206 | qdf_mem_dma_sync_single_for_device(scn->qdf_dev, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 207 | CE_response, |
| 208 | BMI_DATASZ_MAX, |
| 209 | DMA_FROM_DEVICE); |
| 210 | ce_recv_buf_enqueue(ce_recv, transaction, |
| 211 | transaction->bmi_response_CE); |
| 212 | /* NB: see HIF_BMI_recv_done */ |
| 213 | } else { |
| 214 | transaction->bmi_response_host = NULL; |
| 215 | transaction->bmi_response_CE = 0; |
| 216 | } |
| 217 | |
| 218 | /* dma_cache_sync(dev, bmi_request, request_length, DMA_TO_DEVICE); */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 219 | qdf_mem_dma_sync_single_for_device(scn->qdf_dev, CE_request, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 220 | request_length, DMA_TO_DEVICE); |
| 221 | |
| 222 | status = |
| 223 | ce_send(ce_send_hdl, transaction, |
| 224 | CE_request, request_length, |
| 225 | transaction_id, 0, user_flags); |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 226 | ASSERT(status == QDF_STATUS_SUCCESS); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 227 | /* NB: see hif_bmi_send_done */ |
| 228 | |
| 229 | /* TBDXXX: handle timeout */ |
| 230 | |
| 231 | /* Wait for BMI request/response transaction to complete */ |
| 232 | /* Always just wait for BMI request here if |
| 233 | * BMI_RSP_POLLING is defined */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 234 | while (qdf_semaphore_acquire |
| 235 | (&transaction->bmi_transaction_sem)) { |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 236 | /*need some break out condition(time out?) */ |
| 237 | } |
| 238 | |
| 239 | if (bmi_response) { |
| 240 | #ifdef BMI_RSP_POLLING |
| 241 | /* Fix EV118783, do not wait a semaphore for the BMI response |
| 242 | * since the relative interruption may be lost. |
| 243 | * poll the BMI response instead. |
| 244 | */ |
| 245 | i = 0; |
| 246 | while (ce_completed_recv_next( |
| 247 | ce_recv, NULL, NULL, &buf, |
| 248 | &completed_nbytes, &id, |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 249 | &flags) != QDF_STATUS_SUCCESS) { |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 250 | if (i++ > BMI_RSP_TO_MILLISEC) { |
| 251 | HIF_ERROR("%s:error, can't get bmi response\n", |
| 252 | __func__); |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 253 | status = QDF_STATUS_E_BUSY; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 254 | break; |
| 255 | } |
| 256 | OS_DELAY(1000); |
| 257 | } |
| 258 | |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 259 | if ((status == QDF_STATUS_SUCCESS) && bmi_response_lengthp) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 260 | *bmi_response_lengthp = completed_nbytes; |
| 261 | #else |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 262 | if ((status == QDF_STATUS_SUCCESS) && bmi_response_lengthp) { |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 263 | *bmi_response_lengthp = |
| 264 | transaction->bmi_response_length; |
| 265 | } |
| 266 | #endif |
| 267 | |
| 268 | } |
| 269 | |
| 270 | /* dma_unmap_single(dev, transaction->bmi_request_CE, |
| 271 | request_length, DMA_TO_DEVICE); */ |
| 272 | /* bus_unmap_single(scn->sc_osdev, |
| 273 | transaction->bmi_request_CE, |
| 274 | request_length, BUS_DMA_TODEVICE); */ |
| 275 | |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 276 | if (status != QDF_STATUS_SUCCESS) { |
| 277 | qdf_dma_addr_t unused_buffer; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 278 | unsigned int unused_nbytes; |
| 279 | unsigned int unused_id; |
| 280 | unsigned int toeplitz_hash_result; |
| 281 | |
| 282 | ce_cancel_send_next(ce_send_hdl, |
| 283 | NULL, NULL, &unused_buffer, |
| 284 | &unused_nbytes, &unused_id, |
| 285 | &toeplitz_hash_result); |
| 286 | } |
| 287 | |
| 288 | A_TARGET_ACCESS_UNLIKELY(scn); |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame^] | 289 | qdf_mem_free(transaction); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 290 | return status; |
| 291 | } |