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 | |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 28 | #include "targcfg.h" |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 29 | #include "qdf_lock.h" |
| 30 | #include "qdf_status.h" |
| 31 | #include "qdf_status.h" |
| 32 | #include <qdf_atomic.h> /* qdf_atomic_read */ |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 33 | #include <targaddrs.h> |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 34 | #include "hif_io32.h" |
| 35 | #include <hif.h> |
| 36 | #include "regtable.h" |
| 37 | #define ATH_MODULE_NAME hif |
| 38 | #include <a_debug.h> |
| 39 | #include "hif_main.h" |
| 40 | #include "ce_api.h" |
Jeff Johnson | 6950fdb | 2016-10-07 13:00:59 -0700 | [diff] [blame^] | 41 | #include "ce_bmi.h" |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 42 | #include "qdf_trace.h" |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 43 | #include "hif_debug.h" |
| 44 | |
| 45 | /* Track a BMI transaction that is in progress */ |
| 46 | #ifndef BIT |
| 47 | #define BIT(n) (1 << (n)) |
| 48 | #endif |
| 49 | |
| 50 | enum { |
| 51 | BMI_REQ_SEND_DONE = BIT(0), /* the bmi tx completion */ |
| 52 | BMI_RESP_RECV_DONE = BIT(1), /* the bmi respond is received */ |
| 53 | }; |
| 54 | |
| 55 | struct BMI_transaction { |
| 56 | struct HIF_CE_state *hif_state; |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 57 | qdf_semaphore_t bmi_transaction_sem; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 58 | uint8_t *bmi_request_host; /* Req BMI msg in Host addr space */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 59 | 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] | 60 | uint32_t bmi_request_length; /* Length of BMI request */ |
| 61 | uint8_t *bmi_response_host; /* Rsp BMI msg in Host addr space */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 62 | 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] | 63 | unsigned int bmi_response_length; /* Length of received response */ |
| 64 | unsigned int bmi_timeout_ms; |
| 65 | uint32_t bmi_transaction_flags; /* flags for the transcation */ |
| 66 | }; |
| 67 | |
| 68 | /* |
| 69 | * send/recv completion functions for BMI. |
| 70 | * NB: The "net_buf" parameter is actually just a |
| 71 | * straight buffer, not an sk_buff. |
| 72 | */ |
| 73 | void hif_bmi_send_done(struct CE_handle *copyeng, void *ce_context, |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 74 | void *transfer_context, qdf_dma_addr_t data, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 75 | unsigned int nbytes, |
| 76 | unsigned int transfer_id, unsigned int sw_index, |
| 77 | unsigned int hw_index, uint32_t toeplitz_hash_result) |
| 78 | { |
| 79 | struct BMI_transaction *transaction = |
| 80 | (struct BMI_transaction *)transfer_context; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 81 | |
| 82 | #ifdef BMI_RSP_POLLING |
| 83 | /* |
| 84 | * Fix EV118783, Release a semaphore after sending |
| 85 | * no matter whether a response is been expecting now. |
| 86 | */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 87 | qdf_semaphore_release(&transaction->bmi_transaction_sem); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 88 | #else |
| 89 | /* |
| 90 | * If a response is anticipated, we'll complete the |
| 91 | * transaction if the response has been received. |
| 92 | * If no response is anticipated, complete the |
| 93 | * transaction now. |
| 94 | */ |
| 95 | transaction->bmi_transaction_flags |= BMI_REQ_SEND_DONE; |
| 96 | |
| 97 | /* resp is't needed or has already been received, |
| 98 | * never assume resp comes later then this */ |
| 99 | if (!transaction->bmi_response_CE || |
| 100 | (transaction->bmi_transaction_flags & BMI_RESP_RECV_DONE)) { |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 101 | qdf_semaphore_release(&transaction->bmi_transaction_sem); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 102 | } |
| 103 | #endif |
| 104 | } |
| 105 | |
| 106 | #ifndef BMI_RSP_POLLING |
| 107 | void hif_bmi_recv_data(struct CE_handle *copyeng, void *ce_context, |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 108 | void *transfer_context, qdf_dma_addr_t data, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 109 | unsigned int nbytes, |
| 110 | unsigned int transfer_id, unsigned int flags) |
| 111 | { |
| 112 | struct BMI_transaction *transaction = |
| 113 | (struct BMI_transaction *)transfer_context; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 114 | |
| 115 | transaction->bmi_response_length = nbytes; |
| 116 | transaction->bmi_transaction_flags |= BMI_RESP_RECV_DONE; |
| 117 | |
| 118 | /* when both send/recv are done, the sem can be released */ |
| 119 | if (transaction->bmi_transaction_flags & BMI_REQ_SEND_DONE) { |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 120 | qdf_semaphore_release(&transaction->bmi_transaction_sem); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 121 | } |
| 122 | } |
| 123 | #endif |
| 124 | |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 125 | QDF_STATUS hif_exchange_bmi_msg(struct hif_opaque_softc *hif_ctx, |
| 126 | qdf_dma_addr_t bmi_cmd_da, |
| 127 | qdf_dma_addr_t bmi_rsp_da, |
Komal Seelam | 2a5fa63 | 2016-02-15 10:33:44 +0530 | [diff] [blame] | 128 | uint8_t *bmi_request, |
| 129 | uint32_t request_length, |
| 130 | uint8_t *bmi_response, |
| 131 | uint32_t *bmi_response_lengthp, |
| 132 | uint32_t TimeoutMS) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 133 | { |
Komal Seelam | 644263d | 2016-02-22 20:45:49 +0530 | [diff] [blame] | 134 | struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); |
Komal Seelam | 02cf2f8 | 2016-02-22 20:44:25 +0530 | [diff] [blame] | 135 | struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 136 | struct HIF_CE_pipe_info *send_pipe_info = |
| 137 | &(hif_state->pipe_info[BMI_CE_NUM_TO_TARG]); |
| 138 | struct CE_handle *ce_send_hdl = send_pipe_info->ce_hdl; |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 139 | qdf_dma_addr_t CE_request, CE_response = 0; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 140 | struct BMI_transaction *transaction = NULL; |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 141 | int status = QDF_STATUS_SUCCESS; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 142 | struct HIF_CE_pipe_info *recv_pipe_info = |
| 143 | &(hif_state->pipe_info[BMI_CE_NUM_TO_HOST]); |
| 144 | struct CE_handle *ce_recv = recv_pipe_info->ce_hdl; |
| 145 | unsigned int mux_id = 0; |
| 146 | unsigned int transaction_id = 0xffff; |
| 147 | unsigned int user_flags = 0; |
| 148 | #ifdef BMI_RSP_POLLING |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 149 | qdf_dma_addr_t buf; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 150 | unsigned int completed_nbytes, id, flags; |
| 151 | int i; |
| 152 | #endif |
| 153 | |
| 154 | transaction = |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 155 | (struct BMI_transaction *)qdf_mem_malloc(sizeof(*transaction)); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 156 | if (unlikely(!transaction)) { |
| 157 | HIF_ERROR("%s: no memory", __func__); |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 158 | return QDF_STATUS_E_NOMEM; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 159 | } |
| 160 | transaction_id = (mux_id & MUX_ID_MASK) | |
| 161 | (transaction_id & TRANSACTION_ID_MASK); |
| 162 | #ifdef QCA_WIFI_3_0 |
| 163 | user_flags &= DESC_DATA_FLAG_MASK; |
| 164 | #endif |
| 165 | A_TARGET_ACCESS_LIKELY(scn); |
| 166 | |
| 167 | /* Initialize bmi_transaction_sem to block */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 168 | qdf_semaphore_init(&transaction->bmi_transaction_sem); |
| 169 | qdf_semaphore_acquire(&transaction->bmi_transaction_sem); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 170 | |
| 171 | transaction->hif_state = hif_state; |
| 172 | transaction->bmi_request_host = bmi_request; |
| 173 | transaction->bmi_request_length = request_length; |
| 174 | transaction->bmi_response_length = 0; |
| 175 | transaction->bmi_timeout_ms = TimeoutMS; |
| 176 | transaction->bmi_transaction_flags = 0; |
| 177 | |
| 178 | /* |
| 179 | * CE_request = dma_map_single(dev, |
| 180 | * (void *)bmi_request, request_length, DMA_TO_DEVICE); |
| 181 | */ |
Komal Seelam | 2a5fa63 | 2016-02-15 10:33:44 +0530 | [diff] [blame] | 182 | CE_request = bmi_cmd_da; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 183 | transaction->bmi_request_CE = CE_request; |
| 184 | |
| 185 | if (bmi_response) { |
| 186 | |
| 187 | /* |
| 188 | * CE_response = dma_map_single(dev, bmi_response, |
| 189 | * BMI_DATASZ_MAX, DMA_FROM_DEVICE); |
| 190 | */ |
Komal Seelam | 2a5fa63 | 2016-02-15 10:33:44 +0530 | [diff] [blame] | 191 | CE_response = bmi_rsp_da; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 192 | transaction->bmi_response_host = bmi_response; |
| 193 | transaction->bmi_response_CE = CE_response; |
| 194 | /* dma_cache_sync(dev, bmi_response, |
| 195 | BMI_DATASZ_MAX, DMA_FROM_DEVICE); */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 196 | qdf_mem_dma_sync_single_for_device(scn->qdf_dev, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 197 | CE_response, |
| 198 | BMI_DATASZ_MAX, |
| 199 | DMA_FROM_DEVICE); |
| 200 | ce_recv_buf_enqueue(ce_recv, transaction, |
| 201 | transaction->bmi_response_CE); |
| 202 | /* NB: see HIF_BMI_recv_done */ |
| 203 | } else { |
| 204 | transaction->bmi_response_host = NULL; |
| 205 | transaction->bmi_response_CE = 0; |
| 206 | } |
| 207 | |
| 208 | /* dma_cache_sync(dev, bmi_request, request_length, DMA_TO_DEVICE); */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 209 | qdf_mem_dma_sync_single_for_device(scn->qdf_dev, CE_request, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 210 | request_length, DMA_TO_DEVICE); |
| 211 | |
| 212 | status = |
| 213 | ce_send(ce_send_hdl, transaction, |
| 214 | CE_request, request_length, |
| 215 | transaction_id, 0, user_flags); |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 216 | ASSERT(status == QDF_STATUS_SUCCESS); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 217 | /* NB: see hif_bmi_send_done */ |
| 218 | |
| 219 | /* TBDXXX: handle timeout */ |
| 220 | |
| 221 | /* Wait for BMI request/response transaction to complete */ |
| 222 | /* Always just wait for BMI request here if |
| 223 | * BMI_RSP_POLLING is defined */ |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 224 | while (qdf_semaphore_acquire |
| 225 | (&transaction->bmi_transaction_sem)) { |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 226 | /*need some break out condition(time out?) */ |
| 227 | } |
| 228 | |
| 229 | if (bmi_response) { |
| 230 | #ifdef BMI_RSP_POLLING |
| 231 | /* Fix EV118783, do not wait a semaphore for the BMI response |
| 232 | * since the relative interruption may be lost. |
| 233 | * poll the BMI response instead. |
| 234 | */ |
| 235 | i = 0; |
| 236 | while (ce_completed_recv_next( |
| 237 | ce_recv, NULL, NULL, &buf, |
| 238 | &completed_nbytes, &id, |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 239 | &flags) != QDF_STATUS_SUCCESS) { |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 240 | if (i++ > BMI_RSP_TO_MILLISEC) { |
Houston Hoffman | c50572b | 2016-06-08 19:49:46 -0700 | [diff] [blame] | 241 | HIF_ERROR("%s:error, can't get bmi response", |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 242 | __func__); |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 243 | status = QDF_STATUS_E_BUSY; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 244 | break; |
| 245 | } |
| 246 | OS_DELAY(1000); |
| 247 | } |
| 248 | |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 249 | if ((status == QDF_STATUS_SUCCESS) && bmi_response_lengthp) |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 250 | *bmi_response_lengthp = completed_nbytes; |
| 251 | #else |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 252 | if ((status == QDF_STATUS_SUCCESS) && bmi_response_lengthp) { |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 253 | *bmi_response_lengthp = |
| 254 | transaction->bmi_response_length; |
| 255 | } |
| 256 | #endif |
| 257 | |
| 258 | } |
| 259 | |
| 260 | /* dma_unmap_single(dev, transaction->bmi_request_CE, |
| 261 | request_length, DMA_TO_DEVICE); */ |
| 262 | /* bus_unmap_single(scn->sc_osdev, |
| 263 | transaction->bmi_request_CE, |
| 264 | request_length, BUS_DMA_TODEVICE); */ |
| 265 | |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 266 | if (status != QDF_STATUS_SUCCESS) { |
| 267 | qdf_dma_addr_t unused_buffer; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 268 | unsigned int unused_nbytes; |
| 269 | unsigned int unused_id; |
| 270 | unsigned int toeplitz_hash_result; |
| 271 | |
| 272 | ce_cancel_send_next(ce_send_hdl, |
| 273 | NULL, NULL, &unused_buffer, |
| 274 | &unused_nbytes, &unused_id, |
| 275 | &toeplitz_hash_result); |
| 276 | } |
| 277 | |
| 278 | A_TARGET_ACCESS_UNLIKELY(scn); |
Chouhan, Anurag | fc06aa9 | 2016-03-03 19:05:05 +0530 | [diff] [blame] | 279 | qdf_mem_free(transaction); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 280 | return status; |
| 281 | } |