1 /* 2 * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifndef _HTC_INTERNAL_H_ 20 #define _HTC_INTERNAL_H_ 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif /* __cplusplus */ 25 26 #include "htc_api.h" 27 #include "htc_packet.h" 28 #include <hif.h> 29 #include <htc.h> 30 #include <qdf_atomic.h> 31 #include <qdf_event.h> 32 #include <qdf_lock.h> 33 #include <qdf_nbuf.h> 34 #include <qdf_timer.h> 35 #include <qdf_types.h> 36 37 /* HTC operational parameters */ 38 #define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ 39 #define HTC_TARGET_DEBUG_INTR_MASK 0x01 40 #define HTC_TARGET_CREDIT_INTR_MASK 0xF0 41 #define HTC_MIN_MSG_PER_BUNDLE 2 42 43 #if defined(HIF_USB) 44 45 #define HTC_MAX_MSG_PER_BUNDLE_RX 11 46 #if defined(CFG_HTC_MAX_MSG_PER_BUNDLE_TX) 47 #define HTC_MAX_MSG_PER_BUNDLE_TX CFG_HTC_MAX_MSG_PER_BUNDLE_TX 48 #else 49 #define HTC_MAX_MSG_PER_BUNDLE_TX 8 50 #endif /* CFG_HTC_MAX_MSG_PER_BUNDLE_TX */ 51 #else 52 #define HTC_MAX_MSG_PER_BUNDLE_RX 64 53 #define HTC_MAX_MSG_PER_BUNDLE 16 54 #define HTC_MAX_MSG_PER_BUNDLE_TX 32 55 #endif 56 57 #ifdef HIF_SDIO 58 #define UPDATE_ALT_CREDIT(tar, val) (tar->AltDataCreditSize = (uint16_t) val) 59 #else 60 #define UPDATE_ALT_CREDIT(tar, val) /* no-op */ 61 #endif 62 63 /* 64 * HTC_MAX_TX_BUNDLE_SEND_LIMIT - 65 * This value is in units of tx frame fragments. 66 * It needs to be at least as large as the maximum number of tx frames in a 67 * HTC download bundle times the average number of fragments in each such frame 68 * (In certain operating systems, such as Linux, we expect to only have 69 * a single fragment per frame anyway.) 70 */ 71 #define HTC_MAX_TX_BUNDLE_SEND_LIMIT 255 72 73 #define HTC_PACKET_CONTAINER_ALLOCATION 32 74 #define NUM_CONTROL_TX_BUFFERS 2 75 #define HTC_CONTROL_BUFFER_SIZE (HTC_MAX_CONTROL_MESSAGE_LENGTH + \ 76 HTC_HDR_LENGTH) 77 #define HTC_CONTROL_BUFFER_ALIGN 32 78 #define HTC_TARGET_RESPONSE_POLL_MS 10 79 #if !defined(A_SIMOS_DEVHOST) 80 #define HTC_TARGET_MAX_RESPONSE_POLL 200 /* actual HW */ 81 #else 82 #define HTC_TARGET_MAX_RESPONSE_POLL 600 /* host + target simulation */ 83 #endif 84 85 #define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL 86 87 #ifndef HTC_CREDIT_HISTORY_MAX 88 #define HTC_CREDIT_HISTORY_MAX 1024 89 #endif 90 91 #define HTC_IS_EPPING_ENABLED(_x) ((_x) == QDF_GLOBAL_EPPING_MODE) 92 93 enum htc_credit_exchange_type { 94 HTC_REQUEST_CREDIT, 95 HTC_PROCESS_CREDIT_REPORT, 96 HTC_SUSPEND_ACK, 97 HTC_SUSPEND_NACK, 98 HTC_INITIAL_WAKE_UP, 99 }; 100 101 static inline const char* 102 htc_credit_exchange_type_str(enum htc_credit_exchange_type type) 103 { 104 switch (type) { 105 case HTC_REQUEST_CREDIT: 106 return "HTC_REQUEST_CREDIT"; 107 case HTC_PROCESS_CREDIT_REPORT: 108 return "HTC_PROCESS_CREDIT_REPORT"; 109 case HTC_SUSPEND_ACK: 110 return "HTC_SUSPEND_ACK"; 111 case HTC_SUSPEND_NACK: 112 return "HTC_SUSPEND_NACK"; 113 case HTC_INITIAL_WAKE_UP: 114 return "HTC_INITIAL_WAKE_UP"; 115 default: 116 return "Unknown htc_credit_exchange_type"; 117 } 118 } 119 120 typedef struct _HTC_ENDPOINT { 121 HTC_ENDPOINT_ID Id; 122 123 /* service ID this endpoint is bound to 124 * non-zero value means this endpoint is in use 125 */ 126 HTC_SERVICE_ID service_id; 127 128 /* callbacks associated with this endpoint */ 129 struct htc_ep_callbacks EpCallBacks; 130 /* HTC frame buffer TX queue */ 131 HTC_PACKET_QUEUE TxQueue; 132 /* max depth of the TX queue before calling driver's full handler */ 133 int MaxTxQueueDepth; 134 /* max length of endpoint message */ 135 int MaxMsgLength; 136 uint8_t UL_PipeID; 137 uint8_t DL_PipeID; 138 /* Need to call HIF to get tx completion callbacks? */ 139 int ul_is_polled; 140 qdf_timer_t ul_poll_timer; 141 int ul_poll_timer_active; 142 int ul_outstanding_cnt; 143 uint32_t htc_send_cnt; 144 uint32_t htc_comp_cnt; 145 /* Need to call HIF to fetch rx? (Not currently supported.) */ 146 int dl_is_polled; 147 /* not currently supported */ 148 /* qdf_timer_t dl_poll_timer; */ 149 150 /* lookup queue to match netbufs to htc packets */ 151 HTC_PACKET_QUEUE TxLookupQueue; 152 /* temporary hold queue for back compatibility */ 153 HTC_PACKET_QUEUE RxBufferHoldQueue; 154 /* TX seq no (helpful) for debugging */ 155 uint8_t SeqNo; 156 /* serialization */ 157 qdf_atomic_t TxProcessCount; 158 struct _HTC_TARGET *target; 159 /* TX credits available on this endpoint */ 160 int TxCredits; 161 /* size in bytes of each credit (set by HTC) */ 162 int TxCreditSize; 163 /* credits required per max message (precalculated) */ 164 int TxCreditsPerMaxMsg; 165 #ifdef HTC_EP_STAT_PROFILING 166 /* endpoint statistics */ 167 struct htc_endpoint_stats endpoint_stats; 168 #endif 169 bool TxCreditFlowEnabled; 170 bool async_update; /* packets can be queued asynchronously */ 171 qdf_spinlock_t lookup_queue_lock; 172 173 /* number of consecutive requeue attempts used for print */ 174 uint32_t num_requeues_warn; 175 /* total number of requeue attempts */ 176 uint32_t total_num_requeues; 177 178 } HTC_ENDPOINT; 179 180 #ifdef HTC_EP_STAT_PROFILING 181 #define INC_HTC_EP_STAT(p, stat, count) ((p)->endpoint_stats.stat += (count)) 182 #else 183 #define INC_HTC_EP_STAT(p, stat, count) 184 #endif 185 186 struct htc_service_tx_credit_allocation { 187 uint16_t service_id; 188 uint8_t CreditAllocation; 189 }; 190 191 #define HTC_MAX_SERVICE_ALLOC_ENTRIES 8 192 193 /* Error codes for HTC layer packet stats*/ 194 enum ol_ath_htc_pkt_ecodes { 195 /* error- get packet at head of HTC_PACKET_Q */ 196 GET_HTC_PKT_Q_FAIL = 0, 197 HTC_PKT_Q_EMPTY, 198 HTC_SEND_Q_EMPTY 199 }; 200 /* our HTC target state */ 201 typedef struct _HTC_TARGET { 202 struct hif_opaque_softc *hif_dev; 203 HTC_ENDPOINT endpoint[ENDPOINT_MAX]; 204 qdf_spinlock_t HTCLock; 205 qdf_spinlock_t HTCRxLock; 206 qdf_spinlock_t HTCTxLock; 207 uint32_t HTCStateFlags; 208 void *host_handle; 209 struct htc_init_info HTCInitInfo; 210 HTC_PACKET *pHTCPacketStructPool; /* pool of HTC packets */ 211 HTC_PACKET_QUEUE ControlBufferTXFreeList; 212 uint8_t CtrlResponseBuffer[HTC_MAX_CONTROL_MESSAGE_LENGTH]; 213 int CtrlResponseLength; 214 qdf_event_t ctrl_response_valid; 215 bool CtrlResponseProcessing; 216 int TotalTransmitCredits; 217 struct htc_service_tx_credit_allocation 218 ServiceTxAllocTable[HTC_MAX_SERVICE_ALLOC_ENTRIES]; 219 int TargetCreditSize; 220 #ifdef RX_SG_SUPPORT 221 qdf_nbuf_queue_t RxSgQueue; 222 bool IsRxSgInprogress; 223 uint32_t CurRxSgTotalLen; /* current total length */ 224 uint32_t ExpRxSgTotalLen; /* expected total length */ 225 #endif 226 qdf_device_t osdev; 227 struct ol_ath_htc_stats htc_pkt_stats; 228 HTC_PACKET *pBundleFreeList; 229 uint32_t ce_send_cnt; 230 uint32_t TX_comp_cnt; 231 uint8_t MaxMsgsPerHTCBundle; 232 qdf_work_t queue_kicker; 233 234 #ifdef HIF_SDIO 235 uint16_t AltDataCreditSize; 236 #endif 237 uint32_t avail_tx_credits; 238 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) 239 uint32_t rx_bundle_stats[HTC_MAX_MSG_PER_BUNDLE_RX]; 240 uint32_t tx_bundle_stats[HTC_MAX_MSG_PER_BUNDLE_TX]; 241 #endif 242 243 uint32_t con_mode; 244 245 /* 246 * This flag is from the mboxping tool. It indicates that we cannot 247 * drop it. Besides, nodrop pkts have higher priority than normal pkts. 248 */ 249 A_BOOL is_nodrop_pkt; 250 251 /* 252 * Number of WMI endpoints used. 253 * Default value is 1. But it should be overidden after htc_create to 254 * reflect the actual count. 255 */ 256 uint8_t wmi_ep_count; 257 /* Flag to indicate whether htc header length check is required */ 258 bool htc_hdr_length_check; 259 260 /* flag to enable packet send debug */ 261 bool htc_pkt_dbg; 262 263 #ifdef FEATURE_RUNTIME_PM 264 /* Runtime count for H2T msg with response */ 265 qdf_atomic_t htc_runtime_cnt; 266 #endif 267 } HTC_TARGET; 268 269 270 #ifdef RX_SG_SUPPORT 271 #define RESET_RX_SG_CONFIG(_target) \ 272 do { \ 273 _target->ExpRxSgTotalLen = 0; \ 274 _target->CurRxSgTotalLen = 0; \ 275 _target->IsRxSgInprogress = false; \ 276 } while (0) 277 #endif 278 279 #define HTC_STATE_STOPPING (1 << 0) 280 #define HTC_STOPPING(t) ((t)->HTCStateFlags & HTC_STATE_STOPPING) 281 #define LOCK_HTC(t) qdf_spin_lock_bh(&(t)->HTCLock) 282 #define UNLOCK_HTC(t) qdf_spin_unlock_bh(&(t)->HTCLock) 283 #define LOCK_HTC_RX(t) qdf_spin_lock_bh(&(t)->HTCRxLock) 284 #define UNLOCK_HTC_RX(t) qdf_spin_unlock_bh(&(t)->HTCRxLock) 285 #define LOCK_HTC_TX(t) qdf_spin_lock_bh(&(t)->HTCTxLock) 286 #define UNLOCK_HTC_TX(t) qdf_spin_unlock_bh(&(t)->HTCTxLock) 287 #define LOCK_HTC_EP_TX_LOOKUP(t) qdf_spin_lock_bh(&(t)->lookup_queue_lock) 288 #define UNLOCK_HTC_EP_TX_LOOKUP(t) qdf_spin_unlock_bh(&(t)->lookup_queue_lock) 289 290 #define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd)) 291 292 #define IS_TX_CREDIT_FLOW_ENABLED(ep) ((ep)->TxCreditFlowEnabled) 293 294 #define HTC_POLL_CLEANUP_PERIOD_MS 10 /* milliseconds */ 295 296 /* Macro to Increment the HTC_PACKET_ERRORS for Tx.*/ 297 #define OL_ATH_HTC_PKT_ERROR_COUNT_INCR(_target, _ecode) \ 298 do { \ 299 if (_ecode == GET_HTC_PKT_Q_FAIL) \ 300 (_target->htc_pkt_stats.htc_get_pkt_q_fail_count) += 1; \ 301 if (_ecode == HTC_PKT_Q_EMPTY) \ 302 (_target->htc_pkt_stats.htc_pkt_q_empty_count) += 1; \ 303 if (_ecode == HTC_SEND_Q_EMPTY) \ 304 (_target->htc_pkt_stats.htc_send_q_empty_count) += 1; \ 305 } while (0) 306 /* internal HTC functions */ 307 308 QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf, 309 uint8_t pipeID); 310 QDF_STATUS htc_tx_completion_handler(void *Context, qdf_nbuf_t netbuf, 311 unsigned int transferID, 312 uint32_t toeplitz_hash_result); 313 314 HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target); 315 void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket); 316 317 HTC_PACKET *allocate_htc_packet_container(HTC_TARGET *target); 318 void free_htc_packet_container(HTC_TARGET *target, HTC_PACKET *pPacket); 319 void htc_flush_rx_hold_queue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint); 320 void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, 321 HTC_TX_TAG Tag); 322 323 /** 324 * htc_flush_endpoint_txlookupQ() - Flush EP's lookup queue 325 * @target: HTC target 326 * @endpoint_id: EP ID 327 * @call_ep_callback: whether to call EP tx completion callback 328 * 329 * Return: void 330 */ 331 void htc_flush_endpoint_txlookupQ(HTC_TARGET *target, 332 HTC_ENDPOINT_ID endpoint_id, 333 bool call_ep_callback); 334 335 void htc_recv_init(HTC_TARGET *target); 336 QDF_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target); 337 void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket); 338 HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target); 339 uint8_t htc_get_credit_allocation(HTC_TARGET *target, uint16_t service_id); 340 void htc_tx_resource_avail_handler(void *context, uint8_t pipeID); 341 void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket); 342 void htc_process_credit_rpt(HTC_TARGET *target, 343 HTC_CREDIT_REPORT *pRpt, 344 int NumEntries, HTC_ENDPOINT_ID FromEndpoint); 345 void htc_fw_event_handler(void *context, QDF_STATUS status); 346 void htc_send_complete_check_cleanup(void *context); 347 #ifdef FEATURE_RUNTIME_PM 348 void htc_kick_queues(void *context); 349 #endif 350 351 static inline void htc_send_complete_poll_timer_stop(HTC_ENDPOINT * 352 pEndpoint) { 353 LOCK_HTC_TX(pEndpoint->target); 354 if (pEndpoint->ul_poll_timer_active) { 355 /* qdf_timer_stop(&pEndpoint->ul_poll_timer); */ 356 pEndpoint->ul_poll_timer_active = 0; 357 } 358 UNLOCK_HTC_TX(pEndpoint->target); 359 } 360 361 static inline void htc_send_complete_poll_timer_start(HTC_ENDPOINT * 362 pEndpoint) { 363 LOCK_HTC_TX(pEndpoint->target); 364 if (pEndpoint->ul_outstanding_cnt 365 && !pEndpoint->ul_poll_timer_active) { 366 /* qdf_timer_start( 367 * &pEndpoint->ul_poll_timer, HTC_POLL_CLEANUP_PERIOD_MS); 368 */ 369 pEndpoint->ul_poll_timer_active = 1; 370 } 371 UNLOCK_HTC_TX(pEndpoint->target); 372 } 373 374 static inline void 375 htc_send_complete_check(HTC_ENDPOINT *pEndpoint, int force) { 376 /* 377 * Stop the polling-cleanup timer that will result in a later call to 378 * this function. It may get started again below, if there are still 379 * outsending sends. 380 */ 381 htc_send_complete_poll_timer_stop(pEndpoint); 382 /* 383 * Check whether HIF has any prior sends that have finished, 384 * have not had the post-processing done. 385 */ 386 hif_send_complete_check(pEndpoint->target->hif_dev, 387 pEndpoint->UL_PipeID, force); 388 /* 389 * If there are still outstanding sends after polling, start a timer 390 * to check again a little later. 391 */ 392 htc_send_complete_poll_timer_start(pEndpoint); 393 } 394 395 #ifdef __cplusplus 396 } 397 #endif 398 399 #ifndef DEBUG_BUNDLE 400 #define DEBUG_BUNDLE 0 401 #endif 402 403 #if defined(HIF_SDIO) || defined(HIF_USB) 404 #ifndef ENABLE_BUNDLE_TX 405 #define ENABLE_BUNDLE_TX 1 406 #endif 407 408 #ifndef ENABLE_BUNDLE_RX 409 #define ENABLE_BUNDLE_RX 1 410 #endif 411 #endif /*defined(HIF_SDIO) || defined(HIF_USB)*/ 412 413 #if defined ENABLE_BUNDLE_TX 414 #define HTC_TX_BUNDLE_ENABLED(target) (target->MaxMsgsPerHTCBundle > 1) 415 #else 416 #define HTC_TX_BUNDLE_ENABLED(target) 0 417 #endif 418 419 #if defined ENABLE_BUNDLE_RX 420 #define HTC_RX_BUNDLE_ENABLED(target) (target->MaxMsgsPerHTCBundle > 1) 421 #else 422 #define HTC_RX_BUNDLE_ENABLED(target) 0 423 #endif 424 425 #define HTC_ENABLE_BUNDLE(target) (target->MaxMsgsPerHTCBundle > 1) 426 427 #endif /* !_HTC_HOST_INTERNAL_H_ */ 428