Return-path: Received: from emh06.mail.saunalahti.fi ([62.142.5.116]:60901 "EHLO emh06.mail.saunalahti.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755688Ab1GQKWz (ORCPT ); Sun, 17 Jul 2011 06:22:55 -0400 Subject: [PATCH v2 12/23] ath6kl: add htc.h To: linux-wireless@vger.kernel.org From: Kalle Valo Cc: joe@perches.com, devel@linuxdriverproject.org, gregkh@suse.de, error27@gmail.com Date: Sun, 17 Jul 2011 13:22:47 +0300 Message-ID: <20110717102247.18367.64054.stgit@localhost6.localdomain6> (sfid-20110717_124611_006806_705B2554) In-Reply-To: <20110717101844.18367.44984.stgit@localhost6.localdomain6> References: <20110717101844.18367.44984.stgit@localhost6.localdomain6> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Sender: linux-wireless-owner@vger.kernel.org List-ID: Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/htc.h | 596 +++++++++++++++++++++++++++++++++ 1 files changed, 596 insertions(+), 0 deletions(-) create mode 100644 drivers/net/wireless/ath/ath6kl/htc.h diff --git a/drivers/net/wireless/ath/ath6kl/htc.h b/drivers/net/wireless/ath/ath6kl/htc.h new file mode 100644 index 0000000..16fa7a8 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/htc.h @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * 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 + +/* 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) + +/* scatter request flags */ + +#define HTC_SCAT_REQ_FLG_PART_BNDL (1 << 0) + +#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; +}; + +enum htc_send_full_action { + HTC_SEND_FULL_KEEP = 0, + HTC_SEND_FULL_DROP = 1, +}; + +struct htc_ep_callbacks { + 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); + 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 */ + void *htc_rsvd; + + /* + * 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, +}; + +struct htc_credit_state_info { + int total_avail_credits; + int cur_free_credits; + 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; +}; + +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]; + struct list_head cred_dist_list; + struct list_head free_ctrl_txbuf; + struct list_head free_ctrl_rxbuf; + struct htc_credit_state_info *cred_dist_cntxt; + int tgt_creds; + unsigned int tgt_cred_sz; + spinlock_t htc_lock; + spinlock_t rx_lock; + spinlock_t tx_lock; + 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; + + bool tx_bndl_enable; + int rx_bndl_enable; +}; + +void *htc_create(struct ath6kl *ar); +void htc_set_credit_dist(struct htc_target *target, + struct htc_credit_state_info *cred_info, + u16 svc_pri_order[], int len); +int htc_wait_target(struct htc_target *target); +int htc_start(struct htc_target *target); +int htc_conn_service(struct htc_target *target, + struct htc_service_connect_req *req, + struct htc_service_connect_resp *resp); +int htc_tx(struct htc_target *target, struct htc_packet *packet); +void htc_stop(struct htc_target *target); +void htc_cleanup(struct htc_target *target); +void htc_flush_txep(struct htc_target *target, + enum htc_endpoint_id endpoint, u16 tag); +void htc_flush_rx_buf(struct htc_target *target); +void htc_indicate_activity_change(struct htc_target *target, + enum htc_endpoint_id endpoint, bool active); +int htc_get_rxbuf_num(struct htc_target *target, enum htc_endpoint_id endpoint); +int htc_add_rxbuf_multiple(struct htc_target *target, struct list_head *pktq); + +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