1 /* 2 * Copyright (c) 2004-2011 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #ifndef HTC_H 18 #define HTC_H 19 20 #include "common.h" 21 22 /* frame header flags */ 23 24 /* send direction */ 25 #define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0) 26 #define HTC_FLAGS_SEND_BUNDLE (1 << 1) 27 28 /* receive direction */ 29 #define HTC_FLG_RX_UNUSED (1 << 0) 30 #define HTC_FLG_RX_TRAILER (1 << 1) 31 /* Bundle count maske and shift */ 32 #define HTC_FLG_RX_BNDL_CNT (0xF0) 33 #define HTC_FLG_RX_BNDL_CNT_S 4 34 35 #define HTC_HDR_LENGTH (sizeof(struct htc_frame_hdr)) 36 #define HTC_MAX_PAYLOAD_LENGTH (4096 - sizeof(struct htc_frame_hdr)) 37 38 /* HTC control message IDs */ 39 40 #define HTC_MSG_READY_ID 1 41 #define HTC_MSG_CONN_SVC_ID 2 42 #define HTC_MSG_CONN_SVC_RESP_ID 3 43 #define HTC_MSG_SETUP_COMPLETE_ID 4 44 #define HTC_MSG_SETUP_COMPLETE_EX_ID 5 45 46 #define HTC_MAX_CTRL_MSG_LEN 256 47 48 #define HTC_VERSION_2P0 0x00 49 #define HTC_VERSION_2P1 0x01 50 51 #define HTC_SERVICE_META_DATA_MAX_LENGTH 128 52 53 #define HTC_CONN_FLGS_THRESH_LVL_QUAT 0x0 54 #define HTC_CONN_FLGS_THRESH_LVL_HALF 0x1 55 #define HTC_CONN_FLGS_THRESH_LVL_THREE_QUAT 0x2 56 #define HTC_CONN_FLGS_REDUCE_CRED_DRIB 0x4 57 #define HTC_CONN_FLGS_THRESH_MASK 0x3 58 59 /* connect response status codes */ 60 #define HTC_SERVICE_SUCCESS 0 61 #define HTC_SERVICE_NOT_FOUND 1 62 #define HTC_SERVICE_FAILED 2 63 64 /* no resources (i.e. no more endpoints) */ 65 #define HTC_SERVICE_NO_RESOURCES 3 66 67 /* specific service is not allowing any more endpoints */ 68 #define HTC_SERVICE_NO_MORE_EP 4 69 70 /* report record IDs */ 71 #define HTC_RECORD_NULL 0 72 #define HTC_RECORD_CREDITS 1 73 #define HTC_RECORD_LOOKAHEAD 2 74 #define HTC_RECORD_LOOKAHEAD_BUNDLE 3 75 76 #define HTC_SETUP_COMP_FLG_RX_BNDL_EN (1 << 0) 77 78 #define MAKE_SERVICE_ID(group, index) \ 79 (int)(((int)group << 8) | (int)(index)) 80 81 /* NOTE: service ID of 0x0000 is reserved and should never be used */ 82 #define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 1) 83 #define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 0) 84 #define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 1) 85 #define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 2) 86 #define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 3) 87 #define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4) 88 #define WMI_MAX_SERVICES 5 89 90 /* reserved and used to flush ALL packets */ 91 #define HTC_TX_PACKET_TAG_ALL 0 92 #define HTC_SERVICE_TX_PACKET_TAG 1 93 #define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_SERVICE_TX_PACKET_TAG + 9) 94 95 /* more packets on this endpoint are being fetched */ 96 #define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0) 97 98 /* TODO.. for BMI */ 99 #define ENDPOINT1 0 100 /* TODO -remove me, but we have to fix BMI first */ 101 #define HTC_MAILBOX_NUM_MAX 4 102 103 /* enable send bundle padding for this endpoint */ 104 #define HTC_FLGS_TX_BNDL_PAD_EN (1 << 0) 105 #define HTC_EP_ACTIVE ((u32) (1u << 31)) 106 107 /* HTC operational parameters */ 108 #define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ 109 #define HTC_TARGET_DEBUG_INTR_MASK 0x01 110 #define HTC_TARGET_CREDIT_INTR_MASK 0xF0 111 112 #define HTC_HOST_MAX_MSG_PER_BUNDLE 8 113 #define HTC_MIN_HTC_MSGS_TO_BUNDLE 2 114 115 /* packet flags */ 116 117 #define HTC_RX_PKT_IGNORE_LOOKAHEAD (1 << 0) 118 #define HTC_RX_PKT_REFRESH_HDR (1 << 1) 119 #define HTC_RX_PKT_PART_OF_BUNDLE (1 << 2) 120 #define HTC_RX_PKT_NO_RECYCLE (1 << 3) 121 122 #define NUM_CONTROL_BUFFERS 8 123 #define NUM_CONTROL_TX_BUFFERS 2 124 #define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS) 125 126 #define HTC_RECV_WAIT_BUFFERS (1 << 0) 127 #define HTC_OP_STATE_STOPPING (1 << 0) 128 129 /* 130 * The frame header length and message formats defined herein were selected 131 * to accommodate optimal alignment for target processing. This reduces 132 * code size and improves performance. Any changes to the header length may 133 * alter the alignment and cause exceptions on the target. When adding to 134 * the messagestructures insure that fields are properly aligned. 135 */ 136 137 /* HTC frame header 138 * 139 * NOTE: do not remove or re-arrange the fields, these are minimally 140 * required to take advantage of 4-byte lookaheads in some hardware 141 * implementations. 142 */ 143 struct htc_frame_hdr { 144 u8 eid; 145 u8 flags; 146 147 /* length of data (including trailer) that follows the header */ 148 __le16 payld_len; 149 150 /* end of 4-byte lookahead */ 151 152 u8 ctrl[2]; 153 } __packed; 154 155 /* HTC ready message */ 156 struct htc_ready_msg { 157 __le16 msg_id; 158 __le16 cred_cnt; 159 __le16 cred_sz; 160 u8 max_ep; 161 u8 pad; 162 } __packed; 163 164 /* extended HTC ready message */ 165 struct htc_ready_ext_msg { 166 struct htc_ready_msg ver2_0_info; 167 u8 htc_ver; 168 u8 msg_per_htc_bndl; 169 } __packed; 170 171 /* connect service */ 172 struct htc_conn_service_msg { 173 __le16 msg_id; 174 __le16 svc_id; 175 __le16 conn_flags; 176 u8 svc_meta_len; 177 u8 pad; 178 } __packed; 179 180 /* connect response */ 181 struct htc_conn_service_resp { 182 __le16 msg_id; 183 __le16 svc_id; 184 u8 status; 185 u8 eid; 186 __le16 max_msg_sz; 187 u8 svc_meta_len; 188 u8 pad; 189 } __packed; 190 191 struct htc_setup_comp_msg { 192 __le16 msg_id; 193 } __packed; 194 195 /* extended setup completion message */ 196 struct htc_setup_comp_ext_msg { 197 __le16 msg_id; 198 __le32 flags; 199 u8 msg_per_rxbndl; 200 u8 Rsvd[3]; 201 } __packed; 202 203 struct htc_record_hdr { 204 u8 rec_id; 205 u8 len; 206 } __packed; 207 208 struct htc_credit_report { 209 u8 eid; 210 u8 credits; 211 } __packed; 212 213 /* 214 * NOTE: The lk_ahd array is guarded by a pre_valid 215 * and Post Valid guard bytes. The pre_valid bytes must 216 * equal the inverse of the post_valid byte. 217 */ 218 struct htc_lookahead_report { 219 u8 pre_valid; 220 u8 lk_ahd[4]; 221 u8 post_valid; 222 } __packed; 223 224 struct htc_bundle_lkahd_rpt { 225 u8 lk_ahd[4]; 226 } __packed; 227 228 /* Current service IDs */ 229 230 enum htc_service_grp_ids { 231 RSVD_SERVICE_GROUP = 0, 232 WMI_SERVICE_GROUP = 1, 233 234 HTC_TEST_GROUP = 254, 235 HTC_SERVICE_GROUP_LAST = 255 236 }; 237 238 /* ------ endpoint IDS ------ */ 239 240 enum htc_endpoint_id { 241 ENDPOINT_UNUSED = -1, 242 ENDPOINT_0 = 0, 243 ENDPOINT_1 = 1, 244 ENDPOINT_2 = 2, 245 ENDPOINT_3, 246 ENDPOINT_4, 247 ENDPOINT_5, 248 ENDPOINT_6, 249 ENDPOINT_7, 250 ENDPOINT_8, 251 ENDPOINT_MAX, 252 }; 253 254 struct htc_tx_packet_info { 255 u16 tag; 256 int cred_used; 257 u8 flags; 258 int seqno; 259 }; 260 261 struct htc_rx_packet_info { 262 u32 exp_hdr; 263 u32 rx_flags; 264 u32 indicat_flags; 265 }; 266 267 struct htc_target; 268 269 /* wrapper around endpoint-specific packets */ 270 struct htc_packet { 271 struct list_head list; 272 273 /* caller's per packet specific context */ 274 void *pkt_cntxt; 275 276 /* 277 * the true buffer start , the caller can store the real 278 * buffer start here. In receive callbacks, the HTC layer 279 * sets buf to the start of the payload past the header. 280 * This field allows the caller to reset buf when it recycles 281 * receive packets back to HTC. 282 */ 283 u8 *buf_start; 284 285 /* 286 * Pointer to the start of the buffer. In the transmit 287 * direction this points to the start of the payload. In the 288 * receive direction, however, the buffer when queued up 289 * points to the start of the HTC header but when returned 290 * to the caller points to the start of the payload 291 */ 292 u8 *buf; 293 u32 buf_len; 294 295 /* actual length of payload */ 296 u32 act_len; 297 298 /* endpoint that this packet was sent/recv'd from */ 299 enum htc_endpoint_id endpoint; 300 301 /* completion status */ 302 303 int status; 304 union { 305 struct htc_tx_packet_info tx; 306 struct htc_rx_packet_info rx; 307 } info; 308 309 void (*completion) (struct htc_target *, struct htc_packet *); 310 struct htc_target *context; 311 }; 312 313 enum htc_send_full_action { 314 HTC_SEND_FULL_KEEP = 0, 315 HTC_SEND_FULL_DROP = 1, 316 }; 317 318 struct htc_ep_callbacks { 319 void (*rx) (struct htc_target *, struct htc_packet *); 320 void (*rx_refill) (struct htc_target *, enum htc_endpoint_id endpoint); 321 enum htc_send_full_action (*tx_full) (struct htc_target *, 322 struct htc_packet *); 323 struct htc_packet *(*rx_allocthresh) (struct htc_target *, 324 enum htc_endpoint_id, int); 325 int rx_alloc_thresh; 326 int rx_refill_thresh; 327 }; 328 329 /* service connection information */ 330 struct htc_service_connect_req { 331 u16 svc_id; 332 u16 conn_flags; 333 struct htc_ep_callbacks ep_cb; 334 int max_txq_depth; 335 u32 flags; 336 unsigned int max_rxmsg_sz; 337 }; 338 339 /* service connection response information */ 340 struct htc_service_connect_resp { 341 u8 buf_len; 342 u8 act_len; 343 enum htc_endpoint_id endpoint; 344 unsigned int len_max; 345 u8 resp_code; 346 }; 347 348 /* endpoint distributionstructure */ 349 struct htc_endpoint_credit_dist { 350 struct list_head list; 351 352 /* Service ID (set by HTC) */ 353 u16 svc_id; 354 355 /* endpoint for this distributionstruct (set by HTC) */ 356 enum htc_endpoint_id endpoint; 357 358 u32 dist_flags; 359 360 /* 361 * credits for normal operation, anything above this 362 * indicates the endpoint is over-subscribed. 363 */ 364 int cred_norm; 365 366 /* floor for credit distribution */ 367 int cred_min; 368 369 int cred_assngd; 370 371 /* current credits available */ 372 int credits; 373 374 /* 375 * pending credits to distribute on this endpoint, this 376 * is set by HTC when credit reports arrive. The credit 377 * distribution functions sets this to zero when it distributes 378 * the credits. 379 */ 380 int cred_to_dist; 381 382 /* 383 * the number of credits that the current pending TX packet needs 384 * to transmit. This is set by HTC when endpoint needs credits in 385 * order to transmit. 386 */ 387 int seek_cred; 388 389 /* size in bytes of each credit */ 390 int cred_sz; 391 392 /* credits required for a maximum sized messages */ 393 int cred_per_msg; 394 395 /* reserved for HTC use */ 396 struct htc_endpoint *htc_ep; 397 398 /* 399 * current depth of TX queue , i.e. messages waiting for credits 400 * This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE 401 * or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint 402 * that has non-zero credits to recover. 403 */ 404 int txq_depth; 405 }; 406 407 /* 408 * credit distibution code that is passed into the distrbution function, 409 * there are mandatory and optional codes that must be handled 410 */ 411 enum htc_credit_dist_reason { 412 HTC_CREDIT_DIST_SEND_COMPLETE = 0, 413 HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, 414 HTC_CREDIT_DIST_SEEK_CREDITS, 415 }; 416 417 struct ath6kl_htc_credit_info { 418 int total_avail_credits; 419 int cur_free_credits; 420 421 /* list of lowest priority endpoints */ 422 struct list_head lowestpri_ep_dist; 423 }; 424 425 /* endpoint statistics */ 426 struct htc_endpoint_stats { 427 /* 428 * number of times the host set the credit-low flag in a send 429 * message on this endpoint 430 */ 431 u32 cred_low_indicate; 432 433 u32 tx_issued; 434 u32 tx_pkt_bundled; 435 u32 tx_bundles; 436 u32 tx_dropped; 437 438 /* running count of total credit reports received for this endpoint */ 439 u32 tx_cred_rpt; 440 441 /* credit reports received from this endpoint's RX packets */ 442 u32 cred_rpt_from_rx; 443 444 /* credit reports received from RX packets of other endpoints */ 445 u32 cred_rpt_from_other; 446 447 /* credit reports received from endpoint 0 RX packets */ 448 u32 cred_rpt_ep0; 449 450 /* count of credits received via Rx packets on this endpoint */ 451 u32 cred_from_rx; 452 453 /* count of credits received via another endpoint */ 454 u32 cred_from_other; 455 456 /* count of credits received via another endpoint */ 457 u32 cred_from_ep0; 458 459 /* count of consummed credits */ 460 u32 cred_cosumd; 461 462 /* count of credits returned */ 463 u32 cred_retnd; 464 465 u32 rx_pkts; 466 467 /* count of lookahead records found in Rx msg */ 468 u32 rx_lkahds; 469 470 /* count of recv packets received in a bundle */ 471 u32 rx_bundl; 472 473 /* count of number of bundled lookaheads */ 474 u32 rx_bundle_lkahd; 475 476 /* count of the number of bundle indications from the HTC header */ 477 u32 rx_bundle_from_hdr; 478 479 /* the number of times the recv allocation threshold was hit */ 480 u32 rx_alloc_thresh_hit; 481 482 /* total number of bytes */ 483 u32 rxalloc_thresh_byte; 484 }; 485 486 struct htc_endpoint { 487 enum htc_endpoint_id eid; 488 u16 svc_id; 489 struct list_head txq; 490 struct list_head rx_bufq; 491 struct htc_endpoint_credit_dist cred_dist; 492 struct htc_ep_callbacks ep_cb; 493 int max_txq_depth; 494 int len_max; 495 int tx_proc_cnt; 496 int rx_proc_cnt; 497 struct htc_target *target; 498 u8 seqno; 499 u32 conn_flags; 500 struct htc_endpoint_stats ep_st; 501 }; 502 503 struct htc_control_buffer { 504 struct htc_packet packet; 505 u8 *buf; 506 }; 507 508 struct ath6kl_device; 509 510 /* our HTC target state */ 511 struct htc_target { 512 struct htc_endpoint endpoint[ENDPOINT_MAX]; 513 514 /* contains struct htc_endpoint_credit_dist */ 515 struct list_head cred_dist_list; 516 517 struct list_head free_ctrl_txbuf; 518 struct list_head free_ctrl_rxbuf; 519 struct ath6kl_htc_credit_info *credit_info; 520 int tgt_creds; 521 unsigned int tgt_cred_sz; 522 spinlock_t htc_lock; 523 spinlock_t rx_lock; 524 spinlock_t tx_lock; 525 struct ath6kl_device *dev; 526 u32 htc_flags; 527 u32 rx_st_flags; 528 enum htc_endpoint_id ep_waiting; 529 u8 htc_tgt_ver; 530 531 /* max messages per bundle for HTC */ 532 int msg_per_bndl_max; 533 534 bool tx_bndl_enable; 535 int rx_bndl_enable; 536 int max_rx_bndl_sz; 537 int max_tx_bndl_sz; 538 539 u32 block_sz; 540 u32 block_mask; 541 542 int max_scat_entries; 543 int max_xfer_szper_scatreq; 544 545 int chk_irq_status_cnt; 546 }; 547 548 void *ath6kl_htc_create(struct ath6kl *ar); 549 void ath6kl_htc_set_credit_dist(struct htc_target *target, 550 struct ath6kl_htc_credit_info *cred_info, 551 u16 svc_pri_order[], int len); 552 int ath6kl_htc_wait_target(struct htc_target *target); 553 int ath6kl_htc_start(struct htc_target *target); 554 int ath6kl_htc_conn_service(struct htc_target *target, 555 struct htc_service_connect_req *req, 556 struct htc_service_connect_resp *resp); 557 int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet); 558 void ath6kl_htc_stop(struct htc_target *target); 559 void ath6kl_htc_cleanup(struct htc_target *target); 560 void ath6kl_htc_flush_txep(struct htc_target *target, 561 enum htc_endpoint_id endpoint, u16 tag); 562 void ath6kl_htc_flush_rx_buf(struct htc_target *target); 563 void ath6kl_htc_indicate_activity_change(struct htc_target *target, 564 enum htc_endpoint_id endpoint, 565 bool active); 566 int ath6kl_htc_get_rxbuf_num(struct htc_target *target, 567 enum htc_endpoint_id endpoint); 568 int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, 569 struct list_head *pktq); 570 int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, 571 u32 msg_look_ahead, int *n_pkts); 572 573 static inline void set_htc_pkt_info(struct htc_packet *packet, void *context, 574 u8 *buf, unsigned int len, 575 enum htc_endpoint_id eid, u16 tag) 576 { 577 packet->pkt_cntxt = context; 578 packet->buf = buf; 579 packet->act_len = len; 580 packet->endpoint = eid; 581 packet->info.tx.tag = tag; 582 } 583 584 static inline void htc_rxpkt_reset(struct htc_packet *packet) 585 { 586 packet->buf = packet->buf_start; 587 packet->act_len = 0; 588 } 589 590 static inline void set_htc_rxpkt_info(struct htc_packet *packet, void *context, 591 u8 *buf, unsigned long len, 592 enum htc_endpoint_id eid) 593 { 594 packet->pkt_cntxt = context; 595 packet->buf = buf; 596 packet->buf_start = buf; 597 packet->buf_len = len; 598 packet->endpoint = eid; 599 } 600 601 static inline int get_queue_depth(struct list_head *queue) 602 { 603 struct list_head *tmp_list; 604 int depth = 0; 605 606 list_for_each(tmp_list, queue) 607 depth++; 608 609 return depth; 610 } 611 612 #endif 613