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