1 /* 2 * Copyright (c) 2013-2018 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 #if defined(HIF_USB) 43 #define HTC_MAX_MSG_PER_BUNDLE_RX 11 44 #define HTC_MAX_MSG_PER_BUNDLE_TX 8 45 #else 46 #define HTC_MAX_MSG_PER_BUNDLE_RX 64 47 #define HTC_MAX_MSG_PER_BUNDLE 16 48 #define HTC_MAX_MSG_PER_BUNDLE_TX 32 49 #endif 50 51 #ifdef HIF_SDIO 52 #define UPDATE_ALT_CREDIT(tar, val) (tar->AltDataCreditSize = (uint16_t) val) 53 #else 54 #define UPDATE_ALT_CREDIT(tar, val) /* no-op */ 55 #endif 56 57 /* 58 * HTC_MAX_TX_BUNDLE_SEND_LIMIT - 59 * This value is in units of tx frame fragments. 60 * It needs to be at least as large as the maximum number of tx frames in a 61 * HTC download bundle times the average number of fragments in each such frame 62 * (In certain operating systems, such as Linux, we expect to only have 63 * a single fragment per frame anyway.) 64 */ 65 #define HTC_MAX_TX_BUNDLE_SEND_LIMIT 255 66 67 #define HTC_PACKET_CONTAINER_ALLOCATION 32 68 #define NUM_CONTROL_TX_BUFFERS 2 69 #define HTC_CONTROL_BUFFER_SIZE (HTC_MAX_CONTROL_MESSAGE_LENGTH + \ 70 HTC_HDR_LENGTH) 71 #define HTC_CONTROL_BUFFER_ALIGN 32 72 #define HTC_TARGET_RESPONSE_POLL_MS 10 73 #if !defined(A_SIMOS_DEVHOST) 74 #define HTC_TARGET_MAX_RESPONSE_POLL 200 /* actual HW */ 75 #else 76 #define HTC_TARGET_MAX_RESPONSE_POLL 600 /* host + target simulation */ 77 #endif 78 79 #define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL 80 81 #define HTC_CREDIT_HISTORY_MAX 1024 82 83 #define HTC_IS_EPPING_ENABLED(_x) ((_x) == QDF_GLOBAL_EPPING_MODE) 84 85 enum htc_credit_exchange_type { 86 HTC_REQUEST_CREDIT, 87 HTC_PROCESS_CREDIT_REPORT, 88 HTC_SUSPEND_ACK, 89 HTC_SUSPEND_NACK, 90 HTC_INITIAL_WAKE_UP, 91 }; 92 93 static inline const char* 94 htc_credit_exchange_type_str(enum htc_credit_exchange_type type) 95 { 96 switch (type) { 97 case HTC_REQUEST_CREDIT: 98 return "HTC_REQUEST_CREDIT"; 99 case HTC_PROCESS_CREDIT_REPORT: 100 return "HTC_PROCESS_CREDIT_REPORT"; 101 case HTC_SUSPEND_ACK: 102 return "HTC_SUSPEND_ACK"; 103 case HTC_SUSPEND_NACK: 104 return "HTC_SUSPEND_NACK"; 105 case HTC_INITIAL_WAKE_UP: 106 return "HTC_INITIAL_WAKE_UP"; 107 default: 108 return "Unknown htc_credit_exchange_type"; 109 } 110 } 111 112 typedef struct _HTC_ENDPOINT { 113 HTC_ENDPOINT_ID Id; 114 115 /* service ID this endpoint is bound to 116 * non-zero value means this endpoint is in use 117 */ 118 HTC_SERVICE_ID service_id; 119 120 /* callbacks associated with this endpoint */ 121 struct htc_ep_callbacks EpCallBacks; 122 /* HTC frame buffer TX queue */ 123 HTC_PACKET_QUEUE TxQueue; 124 /* max depth of the TX queue before calling driver's full handler */ 125 int MaxTxQueueDepth; 126 /* max length of endpoint message */ 127 int MaxMsgLength; 128 uint8_t UL_PipeID; 129 uint8_t DL_PipeID; 130 /* Need to call HIF to get tx completion callbacks? */ 131 int ul_is_polled; 132 qdf_timer_t ul_poll_timer; 133 int ul_poll_timer_active; 134 int ul_outstanding_cnt; 135 /* Need to call HIF to fetch rx? (Not currently supported.) */ 136 int dl_is_polled; 137 /* not currently supported */ 138 /* qdf_timer_t dl_poll_timer; */ 139 140 /* lookup queue to match netbufs to htc packets */ 141 HTC_PACKET_QUEUE TxLookupQueue; 142 /* temporary hold queue for back compatibility */ 143 HTC_PACKET_QUEUE RxBufferHoldQueue; 144 /* TX seq no (helpful) for debugging */ 145 uint8_t SeqNo; 146 /* serialization */ 147 qdf_atomic_t TxProcessCount; 148 struct _HTC_TARGET *target; 149 /* TX credits available on this endpoint */ 150 int TxCredits; 151 /* size in bytes of each credit (set by HTC) */ 152 int TxCreditSize; 153 /* credits required per max message (precalculated) */ 154 int TxCreditsPerMaxMsg; 155 #ifdef HTC_EP_STAT_PROFILING 156 /* endpoint statistics */ 157 struct htc_endpoint_stats endpoint_stats; 158 #endif 159 bool TxCreditFlowEnabled; 160 bool async_update; /* packets can be queued asynchronously */ 161 qdf_spinlock_t lookup_queue_lock; 162 } HTC_ENDPOINT; 163 164 #ifdef HTC_EP_STAT_PROFILING 165 #define INC_HTC_EP_STAT(p, stat, count) ((p)->endpoint_stats.stat += (count)) 166 #else 167 #define INC_HTC_EP_STAT(p, stat, count) 168 #endif 169 170 struct htc_service_tx_credit_allocation { 171 uint16_t service_id; 172 uint8_t CreditAllocation; 173 }; 174 175 #define HTC_MAX_SERVICE_ALLOC_ENTRIES 8 176 177 /* Error codes for HTC layer packet stats*/ 178 enum ol_ath_htc_pkt_ecodes { 179 /* error- get packet at head of HTC_PACKET_Q */ 180 GET_HTC_PKT_Q_FAIL = 0, 181 HTC_PKT_Q_EMPTY, 182 HTC_SEND_Q_EMPTY 183 }; 184 /* our HTC target state */ 185 typedef struct _HTC_TARGET { 186 struct hif_opaque_softc *hif_dev; 187 HTC_ENDPOINT endpoint[ENDPOINT_MAX]; 188 qdf_spinlock_t HTCLock; 189 qdf_spinlock_t HTCRxLock; 190 qdf_spinlock_t HTCTxLock; 191 qdf_spinlock_t HTCCreditLock; 192 uint32_t HTCStateFlags; 193 void *host_handle; 194 struct htc_init_info HTCInitInfo; 195 HTC_PACKET *pHTCPacketStructPool; /* pool of HTC packets */ 196 HTC_PACKET_QUEUE ControlBufferTXFreeList; 197 uint8_t CtrlResponseBuffer[HTC_MAX_CONTROL_MESSAGE_LENGTH]; 198 int CtrlResponseLength; 199 qdf_event_t ctrl_response_valid; 200 bool CtrlResponseProcessing; 201 int TotalTransmitCredits; 202 struct htc_service_tx_credit_allocation 203 ServiceTxAllocTable[HTC_MAX_SERVICE_ALLOC_ENTRIES]; 204 int TargetCreditSize; 205 #ifdef RX_SG_SUPPORT 206 qdf_nbuf_queue_t RxSgQueue; 207 bool IsRxSgInprogress; 208 uint32_t CurRxSgTotalLen; /* current total length */ 209 uint32_t ExpRxSgTotalLen; /* expected total length */ 210 #endif 211 qdf_device_t osdev; 212 struct ol_ath_htc_stats htc_pkt_stats; 213 HTC_PACKET *pBundleFreeList; 214 uint32_t ce_send_cnt; 215 uint32_t TX_comp_cnt; 216 uint8_t MaxMsgsPerHTCBundle; 217 qdf_work_t queue_kicker; 218 219 #ifdef HIF_SDIO 220 uint16_t AltDataCreditSize; 221 #endif 222 uint32_t avail_tx_credits; 223 #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT) 224 uint32_t rx_bundle_stats[HTC_MAX_MSG_PER_BUNDLE_RX]; 225 uint32_t tx_bundle_stats[HTC_MAX_MSG_PER_BUNDLE_TX]; 226 #endif 227 228 uint32_t con_mode; 229 230 /* 231 * This flag is from the mboxping tool. It indicates that we cannot 232 * drop it. Besides, nodrop pkts have higher priority than normal pkts. 233 */ 234 A_BOOL is_nodrop_pkt; 235 236 /* 237 * Number of WMI endpoints used. 238 * Default value is 1. But it should be overidden after htc_create to 239 * reflect the actual count. 240 */ 241 uint8_t wmi_ep_count; 242 } HTC_TARGET; 243 244 245 #ifdef RX_SG_SUPPORT 246 #define RESET_RX_SG_CONFIG(_target) \ 247 do { \ 248 _target->ExpRxSgTotalLen = 0; \ 249 _target->CurRxSgTotalLen = 0; \ 250 _target->IsRxSgInprogress = false; \ 251 } while (0) 252 #endif 253 254 #define HTC_STATE_STOPPING (1 << 0) 255 #define HTC_STOPPING(t) ((t)->HTCStateFlags & HTC_STATE_STOPPING) 256 #define LOCK_HTC(t) qdf_spin_lock_bh(&(t)->HTCLock) 257 #define UNLOCK_HTC(t) qdf_spin_unlock_bh(&(t)->HTCLock) 258 #define LOCK_HTC_RX(t) qdf_spin_lock_bh(&(t)->HTCRxLock) 259 #define UNLOCK_HTC_RX(t) qdf_spin_unlock_bh(&(t)->HTCRxLock) 260 #define LOCK_HTC_TX(t) qdf_spin_lock_bh(&(t)->HTCTxLock) 261 #define UNLOCK_HTC_TX(t) qdf_spin_unlock_bh(&(t)->HTCTxLock) 262 #define LOCK_HTC_EP_TX_LOOKUP(t) qdf_spin_lock_bh(&(t)->lookup_queue_lock) 263 #define UNLOCK_HTC_EP_TX_LOOKUP(t) qdf_spin_unlock_bh(&(t)->lookup_queue_lock) 264 265 #define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd)) 266 267 #define IS_TX_CREDIT_FLOW_ENABLED(ep) ((ep)->TxCreditFlowEnabled) 268 269 #define HTC_POLL_CLEANUP_PERIOD_MS 10 /* milliseconds */ 270 271 /* Macro to Increment the HTC_PACKET_ERRORS for Tx.*/ 272 #define OL_ATH_HTC_PKT_ERROR_COUNT_INCR(_target, _ecode) \ 273 do { \ 274 if (_ecode == GET_HTC_PKT_Q_FAIL) \ 275 (_target->htc_pkt_stats.htc_get_pkt_q_fail_count) += 1; \ 276 if (_ecode == HTC_PKT_Q_EMPTY) \ 277 (_target->htc_pkt_stats.htc_pkt_q_empty_count) += 1; \ 278 if (_ecode == HTC_SEND_Q_EMPTY) \ 279 (_target->htc_pkt_stats.htc_send_q_empty_count) += 1; \ 280 } while (0) 281 /* internal HTC functions */ 282 283 QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf, 284 uint8_t pipeID); 285 QDF_STATUS htc_tx_completion_handler(void *Context, qdf_nbuf_t netbuf, 286 unsigned int transferID, 287 uint32_t toeplitz_hash_result); 288 289 HTC_PACKET *allocate_htc_bundle_packet(HTC_TARGET *target); 290 void free_htc_bundle_packet(HTC_TARGET *target, HTC_PACKET *pPacket); 291 292 HTC_PACKET *allocate_htc_packet_container(HTC_TARGET *target); 293 void free_htc_packet_container(HTC_TARGET *target, HTC_PACKET *pPacket); 294 void htc_flush_rx_hold_queue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint); 295 void htc_flush_endpoint_tx(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, 296 HTC_TX_TAG Tag); 297 void htc_recv_init(HTC_TARGET *target); 298 QDF_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target); 299 void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket); 300 HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target); 301 uint8_t htc_get_credit_allocation(HTC_TARGET *target, uint16_t service_id); 302 void htc_tx_resource_avail_handler(void *context, uint8_t pipeID); 303 void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket); 304 void htc_process_credit_rpt(HTC_TARGET *target, 305 HTC_CREDIT_REPORT *pRpt, 306 int NumEntries, HTC_ENDPOINT_ID FromEndpoint); 307 void htc_fw_event_handler(void *context, QDF_STATUS status); 308 void htc_send_complete_check_cleanup(void *context); 309 #ifdef FEATURE_RUNTIME_PM 310 void htc_kick_queues(void *context); 311 #endif 312 313 static inline void htc_send_complete_poll_timer_stop(HTC_ENDPOINT * 314 pEndpoint) { 315 LOCK_HTC_TX(pEndpoint->target); 316 if (pEndpoint->ul_poll_timer_active) { 317 /* qdf_timer_stop(&pEndpoint->ul_poll_timer); */ 318 pEndpoint->ul_poll_timer_active = 0; 319 } 320 UNLOCK_HTC_TX(pEndpoint->target); 321 } 322 323 static inline void htc_send_complete_poll_timer_start(HTC_ENDPOINT * 324 pEndpoint) { 325 LOCK_HTC_TX(pEndpoint->target); 326 if (pEndpoint->ul_outstanding_cnt 327 && !pEndpoint->ul_poll_timer_active) { 328 /* qdf_timer_start( 329 * &pEndpoint->ul_poll_timer, HTC_POLL_CLEANUP_PERIOD_MS); 330 */ 331 pEndpoint->ul_poll_timer_active = 1; 332 } 333 UNLOCK_HTC_TX(pEndpoint->target); 334 } 335 336 static inline void 337 htc_send_complete_check(HTC_ENDPOINT *pEndpoint, int force) { 338 /* 339 * Stop the polling-cleanup timer that will result in a later call to 340 * this function. It may get started again below, if there are still 341 * outsending sends. 342 */ 343 htc_send_complete_poll_timer_stop(pEndpoint); 344 /* 345 * Check whether HIF has any prior sends that have finished, 346 * have not had the post-processing done. 347 */ 348 hif_send_complete_check(pEndpoint->target->hif_dev, 349 pEndpoint->UL_PipeID, force); 350 /* 351 * If there are still outstanding sends after polling, start a timer 352 * to check again a little later. 353 */ 354 htc_send_complete_poll_timer_start(pEndpoint); 355 } 356 357 #ifdef __cplusplus 358 } 359 #endif 360 361 #ifndef DEBUG_BUNDLE 362 #define DEBUG_BUNDLE 0 363 #endif 364 365 #if defined(HIF_SDIO) || defined(HIF_USB) 366 #ifndef ENABLE_BUNDLE_TX 367 #define ENABLE_BUNDLE_TX 1 368 #endif 369 370 #ifndef ENABLE_BUNDLE_RX 371 #define ENABLE_BUNDLE_RX 1 372 #endif 373 #endif /*defined(HIF_SDIO) || defined(HIF_USB)*/ 374 375 #if defined ENABLE_BUNDLE_TX 376 #define HTC_TX_BUNDLE_ENABLED(target) (target->MaxMsgsPerHTCBundle > 1) 377 #else 378 #define HTC_TX_BUNDLE_ENABLED(target) 0 379 #endif 380 381 #if defined ENABLE_BUNDLE_RX 382 #define HTC_RX_BUNDLE_ENABLED(target) (target->MaxMsgsPerHTCBundle > 1) 383 #else 384 #define HTC_RX_BUNDLE_ENABLED(target) 0 385 #endif 386 387 #define HTC_ENABLE_BUNDLE(target) (target->MaxMsgsPerHTCBundle > 1) 388 389 #endif /* !_HTC_HOST_INTERNAL_H_ */ 390