htc.h 15.8 KB
Newer Older
K
Kalle Valo 已提交
1 2
/*
 * Copyright (c) 2004-2011 Atheros Communications Inc.
3
 * Copyright (c) 2011 Qualcomm Atheros, Inc.
K
Kalle Valo 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef HTC_H
#define HTC_H

#include "common.h"

/* frame header flags */

/* send direction */
#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0)
#define HTC_FLAGS_SEND_BUNDLE        (1 << 1)

/* receive direction */
#define HTC_FLG_RX_UNUSED        (1 << 0)
#define HTC_FLG_RX_TRAILER       (1 << 1)
/* Bundle count maske and shift */
#define HTC_FLG_RX_BNDL_CNT	 (0xF0)
#define HTC_FLG_RX_BNDL_CNT_S	 4

#define HTC_HDR_LENGTH  (sizeof(struct htc_frame_hdr))
#define HTC_MAX_PAYLOAD_LENGTH   (4096 - sizeof(struct htc_frame_hdr))

/* HTC control message IDs */

#define HTC_MSG_READY_ID		1
#define HTC_MSG_CONN_SVC_ID		2
#define HTC_MSG_CONN_SVC_RESP_ID	3
#define HTC_MSG_SETUP_COMPLETE_ID	4
#define HTC_MSG_SETUP_COMPLETE_EX_ID	5

#define HTC_MAX_CTRL_MSG_LEN  256

#define HTC_VERSION_2P0  0x00
#define HTC_VERSION_2P1  0x01

#define HTC_SERVICE_META_DATA_MAX_LENGTH 128

#define HTC_CONN_FLGS_THRESH_LVL_QUAT		0x0
#define HTC_CONN_FLGS_THRESH_LVL_HALF		0x1
#define HTC_CONN_FLGS_THRESH_LVL_THREE_QUAT	0x2
#define HTC_CONN_FLGS_REDUCE_CRED_DRIB		0x4
#define HTC_CONN_FLGS_THRESH_MASK		0x3

/* connect response status codes */
#define HTC_SERVICE_SUCCESS      0
#define HTC_SERVICE_NOT_FOUND    1
#define HTC_SERVICE_FAILED       2

/* no resources (i.e. no more endpoints) */
#define HTC_SERVICE_NO_RESOURCES 3

/* specific service is not allowing any more endpoints */
#define HTC_SERVICE_NO_MORE_EP   4

/* report record IDs */
#define HTC_RECORD_NULL             0
#define HTC_RECORD_CREDITS          1
#define HTC_RECORD_LOOKAHEAD        2
#define HTC_RECORD_LOOKAHEAD_BUNDLE 3

#define HTC_SETUP_COMP_FLG_RX_BNDL_EN     (1 << 0)

#define MAKE_SERVICE_ID(group, index) \
	(int)(((int)group << 8) | (int)(index))

/* NOTE: service ID of 0x0000 is reserved and should never be used */
#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 1)
#define WMI_CONTROL_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 0)
#define WMI_DATA_BE_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 1)
#define WMI_DATA_BK_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 2)
#define WMI_DATA_VI_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 3)
#define WMI_DATA_VO_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4)
#define WMI_MAX_SERVICES  5

91 92
#define WMM_NUM_AC  4

K
Kalle Valo 已提交
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
/* reserved and used to flush ALL packets */
#define HTC_TX_PACKET_TAG_ALL          0
#define HTC_SERVICE_TX_PACKET_TAG      1
#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_SERVICE_TX_PACKET_TAG + 9)

/* more packets on this endpoint are being fetched */
#define HTC_RX_FLAGS_INDICATE_MORE_PKTS  (1 << 0)

/* TODO.. for BMI */
#define ENDPOINT1 0
/* TODO -remove me, but we have to fix BMI first */
#define HTC_MAILBOX_NUM_MAX    4

/* enable send bundle padding for this endpoint */
#define HTC_FLGS_TX_BNDL_PAD_EN	 (1 << 0)
#define HTC_EP_ACTIVE                            ((u32) (1u << 31))

/* HTC operational parameters */
#define HTC_TARGET_RESPONSE_TIMEOUT        2000	/* in ms */
#define HTC_TARGET_DEBUG_INTR_MASK         0x01
#define HTC_TARGET_CREDIT_INTR_MASK        0xF0

#define HTC_HOST_MAX_MSG_PER_BUNDLE        8
#define HTC_MIN_HTC_MSGS_TO_BUNDLE         2

/* packet flags */

#define HTC_RX_PKT_IGNORE_LOOKAHEAD      (1 << 0)
#define HTC_RX_PKT_REFRESH_HDR           (1 << 1)
#define HTC_RX_PKT_PART_OF_BUNDLE        (1 << 2)
#define HTC_RX_PKT_NO_RECYCLE            (1 << 3)

#define NUM_CONTROL_BUFFERS     8
#define NUM_CONTROL_TX_BUFFERS  2
#define NUM_CONTROL_RX_BUFFERS  (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS)

#define HTC_RECV_WAIT_BUFFERS        (1 << 0)
#define HTC_OP_STATE_STOPPING        (1 << 0)

/*
 * The frame header length and message formats defined herein were selected
 * to accommodate optimal alignment for target processing. This reduces
 * code size and improves performance. Any changes to the header length may
 * alter the alignment and cause exceptions on the target. When adding to
 * the messagestructures insure that fields are properly aligned.
 */

/* HTC frame header
 *
 * NOTE: do not remove or re-arrange the fields, these are minimally
 * required to take advantage of 4-byte lookaheads in some hardware
 * implementations.
 */
struct htc_frame_hdr {
	u8 eid;
	u8 flags;

	/* length of data (including trailer) that follows the header */
	__le16 payld_len;

	/* end of 4-byte lookahead */

	u8 ctrl[2];
} __packed;

/* HTC ready message */
struct htc_ready_msg {
	__le16 msg_id;
	__le16 cred_cnt;
	__le16 cred_sz;
	u8 max_ep;
	u8 pad;
} __packed;

/* extended HTC ready message */
struct htc_ready_ext_msg {
	struct htc_ready_msg ver2_0_info;
	u8 htc_ver;
	u8 msg_per_htc_bndl;
} __packed;

/* connect service */
struct htc_conn_service_msg {
	__le16 msg_id;
	__le16 svc_id;
	__le16 conn_flags;
	u8 svc_meta_len;
	u8 pad;
} __packed;

/* connect response */
struct htc_conn_service_resp {
	__le16 msg_id;
	__le16 svc_id;
	u8 status;
	u8 eid;
	__le16 max_msg_sz;
	u8 svc_meta_len;
	u8 pad;
} __packed;

struct htc_setup_comp_msg {
	__le16 msg_id;
} __packed;

/* extended setup completion message */
struct htc_setup_comp_ext_msg {
	__le16 msg_id;
	__le32 flags;
	u8 msg_per_rxbndl;
	u8 Rsvd[3];
} __packed;

struct htc_record_hdr {
	u8 rec_id;
	u8 len;
} __packed;

struct htc_credit_report {
	u8 eid;
	u8 credits;
} __packed;

/*
 * NOTE: The lk_ahd array is guarded by a pre_valid
 * and Post Valid guard bytes. The pre_valid bytes must
 * equal the inverse of the post_valid byte.
 */
struct htc_lookahead_report {
	u8 pre_valid;
	u8 lk_ahd[4];
	u8 post_valid;
} __packed;

struct htc_bundle_lkahd_rpt {
	u8 lk_ahd[4];
} __packed;

/* Current service IDs */

enum htc_service_grp_ids {
	RSVD_SERVICE_GROUP = 0,
	WMI_SERVICE_GROUP = 1,

	HTC_TEST_GROUP = 254,
	HTC_SERVICE_GROUP_LAST = 255
};

/* ------ endpoint IDS ------ */

enum htc_endpoint_id {
	ENDPOINT_UNUSED = -1,
	ENDPOINT_0 = 0,
	ENDPOINT_1 = 1,
	ENDPOINT_2 = 2,
	ENDPOINT_3,
	ENDPOINT_4,
	ENDPOINT_5,
	ENDPOINT_6,
	ENDPOINT_7,
	ENDPOINT_8,
	ENDPOINT_MAX,
};

struct htc_tx_packet_info {
	u16 tag;
	int cred_used;
	u8 flags;
	int seqno;
};

struct htc_rx_packet_info {
	u32 exp_hdr;
	u32 rx_flags;
	u32 indicat_flags;
};

struct htc_target;

/* wrapper around endpoint-specific packets */
struct htc_packet {
	struct list_head list;

	/* caller's per packet specific context */
	void *pkt_cntxt;

	/*
	 * the true buffer start , the caller can store the real
	 * buffer start here.  In receive callbacks, the HTC layer
	 * sets buf to the start of the payload past the header.
	 * This field allows the caller to reset buf when it recycles
	 * receive packets back to HTC.
	 */
	u8 *buf_start;

	/*
	 * Pointer to the start of the buffer. In the transmit
	 * direction this points to the start of the payload. In the
	 * receive direction, however, the buffer when queued up
	 * points to the start of the HTC header but when returned
	 * to the caller points to the start of the payload
	 */
	u8 *buf;
	u32 buf_len;

	/* actual length of payload */
	u32 act_len;

	/* endpoint that this packet was sent/recv'd from */
	enum htc_endpoint_id endpoint;

	/* completion status */

	int status;
	union {
		struct htc_tx_packet_info tx;
		struct htc_rx_packet_info rx;
	} info;

	void (*completion) (struct htc_target *, struct htc_packet *);
	struct htc_target *context;
314 315 316 317 318 319 320 321

	/*
	 * optimization for network-oriented data, the HTC packet
	 * can pass the network buffer corresponding to the HTC packet
	 * lower layers may optimized the transfer knowing this is
	 * a network buffer
	 */
	struct sk_buff *skb;
K
Kalle Valo 已提交
322 323 324 325 326 327 328 329
};

enum htc_send_full_action {
	HTC_SEND_FULL_KEEP = 0,
	HTC_SEND_FULL_DROP = 1,
};

struct htc_ep_callbacks {
330
	void (*tx_complete) (struct htc_target *, struct htc_packet *);
K
Kalle Valo 已提交
331 332 333 334 335 336
	void (*rx) (struct htc_target *, struct htc_packet *);
	void (*rx_refill) (struct htc_target *, enum htc_endpoint_id endpoint);
	enum htc_send_full_action (*tx_full) (struct htc_target *,
					      struct htc_packet *);
	struct htc_packet *(*rx_allocthresh) (struct htc_target *,
					      enum htc_endpoint_id, int);
337
	void (*tx_comp_multi) (struct htc_target *, struct list_head *);
K
Kalle Valo 已提交
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
	int rx_alloc_thresh;
	int rx_refill_thresh;
};

/* service connection information */
struct htc_service_connect_req {
	u16 svc_id;
	u16 conn_flags;
	struct htc_ep_callbacks ep_cb;
	int max_txq_depth;
	u32 flags;
	unsigned int max_rxmsg_sz;
};

/* service connection response information */
struct htc_service_connect_resp {
	u8 buf_len;
	u8 act_len;
	enum htc_endpoint_id endpoint;
	unsigned int len_max;
	u8 resp_code;
};

/* endpoint distributionstructure */
struct htc_endpoint_credit_dist {
	struct list_head list;

	/* Service ID (set by HTC) */
	u16 svc_id;

	/* endpoint for this distributionstruct (set by HTC) */
	enum htc_endpoint_id endpoint;

	u32 dist_flags;

	/*
	 * credits for normal operation, anything above this
	 * indicates the endpoint is over-subscribed.
	 */
	int cred_norm;

	/* floor for credit distribution */
	int cred_min;

	int cred_assngd;

	/* current credits available */
	int credits;

	/*
	 * pending credits to distribute on this endpoint, this
	 * is set by HTC when credit reports arrive.  The credit
	 * distribution functions sets this to zero when it distributes
	 * the credits.
	 */
	int cred_to_dist;

	/*
	 * the number of credits that the current pending TX packet needs
	 * to transmit. This is set by HTC when endpoint needs credits in
	 * order to transmit.
	 */
	int seek_cred;

	/* size in bytes of each credit */
	int cred_sz;

	/* credits required for a maximum sized messages */
	int cred_per_msg;

	/* reserved for HTC use */
409
	struct htc_endpoint *htc_ep;
K
Kalle Valo 已提交
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429

	/*
	 * current depth of TX queue , i.e. messages waiting for credits
	 * This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE
	 * or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint
	 * that has non-zero credits to recover.
	 */
	int txq_depth;
};

/*
 * credit distibution code that is passed into the distrbution function,
 * there are mandatory and optional codes that must be handled
 */
enum htc_credit_dist_reason {
	HTC_CREDIT_DIST_SEND_COMPLETE = 0,
	HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1,
	HTC_CREDIT_DIST_SEEK_CREDITS,
};

430
struct ath6kl_htc_credit_info {
K
Kalle Valo 已提交
431 432
	int total_avail_credits;
	int cur_free_credits;
433 434

	/* list of lowest priority endpoints */
K
Kalle Valo 已提交
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
	struct list_head lowestpri_ep_dist;
};

/* endpoint statistics */
struct htc_endpoint_stats {
	/*
	 * number of times the host set the credit-low flag in a send
	 * message on this endpoint
	 */
	u32 cred_low_indicate;

	u32 tx_issued;
	u32 tx_pkt_bundled;
	u32 tx_bundles;
	u32 tx_dropped;

	/* running count of total credit reports received for this endpoint */
	u32 tx_cred_rpt;

	/* credit reports received from this endpoint's RX packets */
	u32 cred_rpt_from_rx;

	/* credit reports received from RX packets of other endpoints */
	u32 cred_rpt_from_other;

	/* credit reports received from endpoint 0 RX packets */
	u32 cred_rpt_ep0;

	/* count of credits received via Rx packets on this endpoint */
	u32 cred_from_rx;

	/* count of credits received via another endpoint */
	u32 cred_from_other;

	/* count of credits received via another endpoint */
	u32 cred_from_ep0;

	/* count of consummed credits */
	u32 cred_cosumd;

	/* count of credits returned */
	u32 cred_retnd;

	u32 rx_pkts;

	/* count of lookahead records found in Rx msg */
	u32 rx_lkahds;

	/* count of recv packets received in a bundle */
	u32 rx_bundl;

	/* count of number of bundled lookaheads */
	u32 rx_bundle_lkahd;

	/* count of the number of bundle indications from the HTC header */
	u32 rx_bundle_from_hdr;

	/* the number of times the recv allocation threshold was hit */
	u32 rx_alloc_thresh_hit;

	/* total number of bytes */
	u32 rxalloc_thresh_byte;
};

struct htc_endpoint {
	enum htc_endpoint_id eid;
	u16 svc_id;
	struct list_head txq;
	struct list_head rx_bufq;
	struct htc_endpoint_credit_dist cred_dist;
	struct htc_ep_callbacks ep_cb;
	int max_txq_depth;
	int len_max;
	int tx_proc_cnt;
	int rx_proc_cnt;
	struct htc_target *target;
	u8 seqno;
	u32 conn_flags;
	struct htc_endpoint_stats ep_st;
514
	u16 tx_drop_packet_threshold;
K
Kalle Valo 已提交
515 516 517 518 519 520 521 522 523 524 525 526
};

struct htc_control_buffer {
	struct htc_packet packet;
	u8 *buf;
};

struct ath6kl_device;

/* our HTC target state */
struct htc_target {
	struct htc_endpoint endpoint[ENDPOINT_MAX];
527 528

	/* contains struct htc_endpoint_credit_dist */
K
Kalle Valo 已提交
529
	struct list_head cred_dist_list;
530

K
Kalle Valo 已提交
531 532
	struct list_head free_ctrl_txbuf;
	struct list_head free_ctrl_rxbuf;
533
	struct ath6kl_htc_credit_info *credit_info;
K
Kalle Valo 已提交
534 535
	int tgt_creds;
	unsigned int tgt_cred_sz;
K
Kalle Valo 已提交
536 537

	/* protects free_ctrl_txbuf and free_ctrl_rxbuf */
K
Kalle Valo 已提交
538
	spinlock_t htc_lock;
K
Kalle Valo 已提交
539 540

	/* FIXME: does this protext rx_bufq and endpoint structures or what? */
K
Kalle Valo 已提交
541
	spinlock_t rx_lock;
K
Kalle Valo 已提交
542 543

	/* protects endpoint->txq */
K
Kalle Valo 已提交
544
	spinlock_t tx_lock;
K
Kalle Valo 已提交
545

K
Kalle Valo 已提交
546 547 548 549 550 551 552 553 554
	struct ath6kl_device *dev;
	u32 htc_flags;
	u32 rx_st_flags;
	enum htc_endpoint_id ep_waiting;
	u8 htc_tgt_ver;

	/* max messages per bundle for HTC */
	int msg_per_bndl_max;

555
	u32 tx_bndl_mask;
K
Kalle Valo 已提交
556
	int rx_bndl_enable;
557 558
	int max_rx_bndl_sz;
	int max_tx_bndl_sz;
559 560 561

	u32 block_sz;
	u32 block_mask;
562 563 564

	int max_scat_entries;
	int max_xfer_szper_scatreq;
565 566

	int chk_irq_status_cnt;
567 568 569

	/* counts the number of Tx without bundling continously per AC */
	u32 ac_tx_count[WMM_NUM_AC];
K
Kalle Valo 已提交
570 571
};

572 573
void *ath6kl_htc_create(struct ath6kl *ar);
void ath6kl_htc_set_credit_dist(struct htc_target *target,
574
				struct ath6kl_htc_credit_info *cred_info,
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
				u16 svc_pri_order[], int len);
int ath6kl_htc_wait_target(struct htc_target *target);
int ath6kl_htc_start(struct htc_target *target);
int ath6kl_htc_conn_service(struct htc_target *target,
			    struct htc_service_connect_req *req,
			    struct htc_service_connect_resp *resp);
int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet);
void ath6kl_htc_stop(struct htc_target *target);
void ath6kl_htc_cleanup(struct htc_target *target);
void ath6kl_htc_flush_txep(struct htc_target *target,
			   enum htc_endpoint_id endpoint, u16 tag);
void ath6kl_htc_flush_rx_buf(struct htc_target *target);
void ath6kl_htc_indicate_activity_change(struct htc_target *target,
					 enum htc_endpoint_id endpoint,
					 bool active);
int ath6kl_htc_get_rxbuf_num(struct htc_target *target,
			     enum htc_endpoint_id endpoint);
int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
				  struct list_head *pktq);
int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
595
				     u32 msg_look_ahead, int *n_pkts);
K
Kalle Valo 已提交
596

597
int ath6kl_credit_setup(struct htc_target *htc_target,
598
			struct ath6kl_htc_credit_info *cred_info);
599

K
Kalle Valo 已提交
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
static inline void set_htc_pkt_info(struct htc_packet *packet, void *context,
				    u8 *buf, unsigned int len,
				    enum htc_endpoint_id eid, u16 tag)
{
	packet->pkt_cntxt = context;
	packet->buf = buf;
	packet->act_len = len;
	packet->endpoint = eid;
	packet->info.tx.tag = tag;
}

static inline void htc_rxpkt_reset(struct htc_packet *packet)
{
	packet->buf = packet->buf_start;
	packet->act_len = 0;
}

static inline void set_htc_rxpkt_info(struct htc_packet *packet, void *context,
				      u8 *buf, unsigned long len,
				      enum htc_endpoint_id eid)
{
	packet->pkt_cntxt = context;
	packet->buf = buf;
	packet->buf_start = buf;
	packet->buf_len = len;
	packet->endpoint = eid;
}

static inline int get_queue_depth(struct list_head *queue)
{
	struct list_head *tmp_list;
	int depth = 0;

	list_for_each(tmp_list, queue)
	    depth++;

	return depth;
}

#endif