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