linux/drivers/net/wireless/ath/ath10k/htc.h
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2011 Atheros Communications Inc.
   3 * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
   4 *
   5 * Permission to use, copy, modify, and/or distribute this software for any
   6 * purpose with or without fee is hereby granted, provided that the above
   7 * copyright notice and this permission notice appear in all copies.
   8 *
   9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16 */
  17
  18#ifndef _HTC_H_
  19#define _HTC_H_
  20
  21#include <linux/kernel.h>
  22#include <linux/list.h>
  23#include <linux/bug.h>
  24#include <linux/skbuff.h>
  25#include <linux/timer.h>
  26
  27struct ath10k;
  28
  29/****************/
  30/* HTC protocol */
  31/****************/
  32
  33/*
  34 * HTC - host-target control protocol
  35 *
  36 * tx packets are generally <htc_hdr><payload>
  37 * rx packets are more complex: <htc_hdr><payload><trailer>
  38 *
  39 * The payload + trailer length is stored in len.
  40 * To get payload-only length one needs to payload - trailer_len.
  41 *
  42 * Trailer contains (possibly) multiple <htc_record>.
  43 * Each record is a id-len-value.
  44 *
  45 * HTC header flags, control_byte0, control_byte1
  46 * have different meaning depending whether its tx
  47 * or rx.
  48 *
  49 * Alignment: htc_hdr, payload and trailer are
  50 * 4-byte aligned.
  51 */
  52
  53enum ath10k_htc_tx_flags {
  54        ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
  55        ATH10K_HTC_FLAG_SEND_BUNDLE        = 0x02
  56};
  57
  58enum ath10k_htc_rx_flags {
  59        ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02,
  60        ATH10K_HTC_FLAG_BUNDLE_MASK     = 0xF0
  61};
  62
  63struct ath10k_htc_hdr {
  64        u8 eid; /* @enum ath10k_htc_ep_id */
  65        u8 flags; /* @enum ath10k_htc_tx_flags, ath10k_htc_rx_flags */
  66        __le16 len;
  67        union {
  68                u8 trailer_len; /* for rx */
  69                u8 control_byte0;
  70        } __packed;
  71        union {
  72                u8 seq_no; /* for tx */
  73                u8 control_byte1;
  74        } __packed;
  75        u8 pad0;
  76        u8 pad1;
  77} __packed __aligned(4);
  78
  79enum ath10k_ath10k_htc_msg_id {
  80        ATH10K_HTC_MSG_READY_ID                = 1,
  81        ATH10K_HTC_MSG_CONNECT_SERVICE_ID      = 2,
  82        ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID = 3,
  83        ATH10K_HTC_MSG_SETUP_COMPLETE_ID       = 4,
  84        ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID    = 5,
  85        ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE   = 6
  86};
  87
  88enum ath10k_htc_version {
  89        ATH10K_HTC_VERSION_2P0 = 0x00, /* 2.0 */
  90        ATH10K_HTC_VERSION_2P1 = 0x01, /* 2.1 */
  91};
  92
  93enum ath10k_htc_conn_flags {
  94        ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH    = 0x0,
  95        ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_HALF      = 0x1,
  96        ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS = 0x2,
  97        ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_UNITY         = 0x3,
  98#define ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_MASK 0x3
  99        ATH10K_HTC_CONN_FLAGS_REDUCE_CREDIT_DRIBBLE    = 1 << 2,
 100        ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL = 1 << 3
 101#define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_MASK 0xFF00
 102#define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_LSB  8
 103};
 104
 105enum ath10k_htc_conn_svc_status {
 106        ATH10K_HTC_CONN_SVC_STATUS_SUCCESS      = 0,
 107        ATH10K_HTC_CONN_SVC_STATUS_NOT_FOUND    = 1,
 108        ATH10K_HTC_CONN_SVC_STATUS_FAILED       = 2,
 109        ATH10K_HTC_CONN_SVC_STATUS_NO_RESOURCES = 3,
 110        ATH10K_HTC_CONN_SVC_STATUS_NO_MORE_EP   = 4
 111};
 112
 113struct ath10k_ath10k_htc_msg_hdr {
 114        __le16 message_id; /* @enum htc_message_id */
 115} __packed;
 116
 117struct ath10k_htc_unknown {
 118        u8 pad0;
 119        u8 pad1;
 120} __packed;
 121
 122struct ath10k_htc_ready {
 123        __le16 credit_count;
 124        __le16 credit_size;
 125        u8 max_endpoints;
 126        u8 pad0;
 127} __packed;
 128
 129struct ath10k_htc_ready_extended {
 130        struct ath10k_htc_ready base;
 131        u8 htc_version; /* @enum ath10k_htc_version */
 132        u8 max_msgs_per_htc_bundle;
 133        u8 pad0;
 134        u8 pad1;
 135} __packed;
 136
 137struct ath10k_htc_conn_svc {
 138        __le16 service_id;
 139        __le16 flags; /* @enum ath10k_htc_conn_flags */
 140        u8 pad0;
 141        u8 pad1;
 142} __packed;
 143
 144struct ath10k_htc_conn_svc_response {
 145        __le16 service_id;
 146        u8 status; /* @enum ath10k_htc_conn_svc_status */
 147        u8 eid;
 148        __le16 max_msg_size;
 149} __packed;
 150
 151struct ath10k_htc_setup_complete_extended {
 152        u8 pad0;
 153        u8 pad1;
 154        __le32 flags; /* @enum htc_setup_complete_flags */
 155        u8 max_msgs_per_bundled_recv;
 156        u8 pad2;
 157        u8 pad3;
 158        u8 pad4;
 159} __packed;
 160
 161struct ath10k_htc_msg {
 162        struct ath10k_ath10k_htc_msg_hdr hdr;
 163        union {
 164                /* host-to-target */
 165                struct ath10k_htc_conn_svc connect_service;
 166                struct ath10k_htc_ready ready;
 167                struct ath10k_htc_ready_extended ready_ext;
 168                struct ath10k_htc_unknown unknown;
 169                struct ath10k_htc_setup_complete_extended setup_complete_ext;
 170
 171                /* target-to-host */
 172                struct ath10k_htc_conn_svc_response connect_service_response;
 173        };
 174} __packed __aligned(4);
 175
 176enum ath10k_ath10k_htc_record_id {
 177        ATH10K_HTC_RECORD_NULL    = 0,
 178        ATH10K_HTC_RECORD_CREDITS = 1
 179};
 180
 181struct ath10k_ath10k_htc_record_hdr {
 182        u8 id; /* @enum ath10k_ath10k_htc_record_id */
 183        u8 len;
 184        u8 pad0;
 185        u8 pad1;
 186} __packed;
 187
 188struct ath10k_htc_credit_report {
 189        u8 eid; /* @enum ath10k_htc_ep_id */
 190        u8 credits;
 191        u8 pad0;
 192        u8 pad1;
 193} __packed;
 194
 195struct ath10k_htc_record {
 196        struct ath10k_ath10k_htc_record_hdr hdr;
 197        union {
 198                struct ath10k_htc_credit_report credit_report[0];
 199                u8 pauload[0];
 200        };
 201} __packed __aligned(4);
 202
 203/*
 204 * note: the trailer offset is dynamic depending
 205 * on payload length. this is only a struct layout draft
 206 */
 207struct ath10k_htc_frame {
 208        struct ath10k_htc_hdr hdr;
 209        union {
 210                struct ath10k_htc_msg msg;
 211                u8 payload[0];
 212        };
 213        struct ath10k_htc_record trailer[0];
 214} __packed __aligned(4);
 215
 216/*******************/
 217/* Host-side stuff */
 218/*******************/
 219
 220enum ath10k_htc_svc_gid {
 221        ATH10K_HTC_SVC_GRP_RSVD = 0,
 222        ATH10K_HTC_SVC_GRP_WMI = 1,
 223        ATH10K_HTC_SVC_GRP_NMI = 2,
 224        ATH10K_HTC_SVC_GRP_HTT = 3,
 225
 226        ATH10K_HTC_SVC_GRP_TEST = 254,
 227        ATH10K_HTC_SVC_GRP_LAST = 255,
 228};
 229
 230#define SVC(group, idx) \
 231        (int)(((int)(group) << 8) | (int)(idx))
 232
 233enum ath10k_htc_svc_id {
 234        /* NOTE: service ID of 0x0000 is reserved and should never be used */
 235        ATH10K_HTC_SVC_ID_RESERVED      = 0x0000,
 236        ATH10K_HTC_SVC_ID_UNUSED        = ATH10K_HTC_SVC_ID_RESERVED,
 237
 238        ATH10K_HTC_SVC_ID_RSVD_CTRL     = SVC(ATH10K_HTC_SVC_GRP_RSVD, 1),
 239        ATH10K_HTC_SVC_ID_WMI_CONTROL   = SVC(ATH10K_HTC_SVC_GRP_WMI, 0),
 240        ATH10K_HTC_SVC_ID_WMI_DATA_BE   = SVC(ATH10K_HTC_SVC_GRP_WMI, 1),
 241        ATH10K_HTC_SVC_ID_WMI_DATA_BK   = SVC(ATH10K_HTC_SVC_GRP_WMI, 2),
 242        ATH10K_HTC_SVC_ID_WMI_DATA_VI   = SVC(ATH10K_HTC_SVC_GRP_WMI, 3),
 243        ATH10K_HTC_SVC_ID_WMI_DATA_VO   = SVC(ATH10K_HTC_SVC_GRP_WMI, 4),
 244
 245        ATH10K_HTC_SVC_ID_NMI_CONTROL   = SVC(ATH10K_HTC_SVC_GRP_NMI, 0),
 246        ATH10K_HTC_SVC_ID_NMI_DATA      = SVC(ATH10K_HTC_SVC_GRP_NMI, 1),
 247
 248        ATH10K_HTC_SVC_ID_HTT_DATA_MSG  = SVC(ATH10K_HTC_SVC_GRP_HTT, 0),
 249
 250        /* raw stream service (i.e. flash, tcmd, calibration apps) */
 251        ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS = SVC(ATH10K_HTC_SVC_GRP_TEST, 0),
 252};
 253
 254#undef SVC
 255
 256enum ath10k_htc_ep_id {
 257        ATH10K_HTC_EP_UNUSED = -1,
 258        ATH10K_HTC_EP_0 = 0,
 259        ATH10K_HTC_EP_1 = 1,
 260        ATH10K_HTC_EP_2,
 261        ATH10K_HTC_EP_3,
 262        ATH10K_HTC_EP_4,
 263        ATH10K_HTC_EP_5,
 264        ATH10K_HTC_EP_6,
 265        ATH10K_HTC_EP_7,
 266        ATH10K_HTC_EP_8,
 267        ATH10K_HTC_EP_COUNT,
 268};
 269
 270struct ath10k_htc_ops {
 271        void (*target_send_suspend_complete)(struct ath10k *ar);
 272};
 273
 274struct ath10k_htc_ep_ops {
 275        void (*ep_tx_complete)(struct ath10k *, struct sk_buff *);
 276        void (*ep_rx_complete)(struct ath10k *, struct sk_buff *);
 277        void (*ep_tx_credits)(struct ath10k *);
 278};
 279
 280/* service connection information */
 281struct ath10k_htc_svc_conn_req {
 282        u16 service_id;
 283        struct ath10k_htc_ep_ops ep_ops;
 284        int max_send_queue_depth;
 285};
 286
 287/* service connection response information */
 288struct ath10k_htc_svc_conn_resp {
 289        u8 buffer_len;
 290        u8 actual_len;
 291        enum ath10k_htc_ep_id eid;
 292        unsigned int max_msg_len;
 293        u8 connect_resp_code;
 294};
 295
 296#define ATH10K_NUM_CONTROL_TX_BUFFERS 2
 297#define ATH10K_HTC_MAX_LEN 4096
 298#define ATH10K_HTC_MAX_CTRL_MSG_LEN 256
 299#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1 * HZ)
 300#define ATH10K_HTC_CONTROL_BUFFER_SIZE (ATH10K_HTC_MAX_CTRL_MSG_LEN + \
 301                                        sizeof(struct ath10k_htc_hdr))
 302#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1 * HZ)
 303
 304struct ath10k_htc_ep {
 305        struct ath10k_htc *htc;
 306        enum ath10k_htc_ep_id eid;
 307        enum ath10k_htc_svc_id service_id;
 308        struct ath10k_htc_ep_ops ep_ops;
 309
 310        int max_tx_queue_depth;
 311        int max_ep_message_len;
 312        u8 ul_pipe_id;
 313        u8 dl_pipe_id;
 314
 315        u8 seq_no; /* for debugging */
 316        int tx_credits;
 317        bool tx_credit_flow_enabled;
 318};
 319
 320struct ath10k_htc_svc_tx_credits {
 321        u16 service_id;
 322        u8  credit_allocation;
 323};
 324
 325struct ath10k_htc {
 326        struct ath10k *ar;
 327        struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT];
 328
 329        /* protects endpoints */
 330        spinlock_t tx_lock;
 331
 332        struct ath10k_htc_ops htc_ops;
 333
 334        u8 control_resp_buffer[ATH10K_HTC_MAX_CTRL_MSG_LEN];
 335        int control_resp_len;
 336
 337        struct completion ctl_resp;
 338
 339        int total_transmit_credits;
 340        int target_credit_size;
 341};
 342
 343int ath10k_htc_init(struct ath10k *ar);
 344int ath10k_htc_wait_target(struct ath10k_htc *htc);
 345int ath10k_htc_start(struct ath10k_htc *htc);
 346int ath10k_htc_connect_service(struct ath10k_htc *htc,
 347                               struct ath10k_htc_svc_conn_req  *conn_req,
 348                               struct ath10k_htc_svc_conn_resp *conn_resp);
 349int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
 350                    struct sk_buff *packet);
 351struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
 352void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
 353void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
 354
 355#endif
 356