linux/drivers/net/wireless/ath/ath10k/htc.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: ISC */
   2/*
   3 * Copyright (c) 2005-2011 Atheros Communications Inc.
   4 * Copyright (c) 2011-2016 Qualcomm Atheros, Inc.
   5 */
   6
   7#ifndef _HTC_H_
   8#define _HTC_H_
   9
  10#include <linux/kernel.h>
  11#include <linux/list.h>
  12#include <linux/bug.h>
  13#include <linux/skbuff.h>
  14#include <linux/timer.h>
  15#include <linux/bitfield.h>
  16
  17struct ath10k;
  18
  19/****************/
  20/* HTC protocol */
  21/****************/
  22
  23/*
  24 * HTC - host-target control protocol
  25 *
  26 * tx packets are generally <htc_hdr><payload>
  27 * rx packets are more complex: <htc_hdr><payload><trailer>
  28 *
  29 * The payload + trailer length is stored in len.
  30 * To get payload-only length one needs to payload - trailer_len.
  31 *
  32 * Trailer contains (possibly) multiple <htc_record>.
  33 * Each record is a id-len-value.
  34 *
  35 * HTC header flags, control_byte0, control_byte1
  36 * have different meaning depending whether its tx
  37 * or rx.
  38 *
  39 * Alignment: htc_hdr, payload and trailer are
  40 * 4-byte aligned.
  41 */
  42
  43#define HTC_HOST_MAX_MSG_PER_RX_BUNDLE        32
  44
  45enum ath10k_htc_tx_flags {
  46        ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
  47        ATH10K_HTC_FLAG_SEND_BUNDLE        = 0x02
  48};
  49
  50enum ath10k_htc_rx_flags {
  51        ATH10K_HTC_FLAGS_RECV_1MORE_BLOCK = 0x01,
  52        ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02,
  53};
  54
  55#define ATH10K_HTC_FLAG_BUNDLE_MASK GENMASK(7, 4)
  56
  57/* bits 2-3 are for extra bundle count bits 4-5 */
  58#define ATH10K_HTC_BUNDLE_EXTRA_MASK GENMASK(3, 2)
  59#define ATH10K_HTC_BUNDLE_EXTRA_SHIFT 4
  60
  61static inline unsigned int ath10k_htc_get_bundle_count(u8 max_msgs, u8 flags)
  62{
  63        unsigned int count, extra_count = 0;
  64
  65        count = FIELD_GET(ATH10K_HTC_FLAG_BUNDLE_MASK, flags);
  66
  67        if (max_msgs > 16)
  68                extra_count = FIELD_GET(ATH10K_HTC_BUNDLE_EXTRA_MASK, flags) <<
  69                        ATH10K_HTC_BUNDLE_EXTRA_SHIFT;
  70
  71        return count + extra_count;
  72}
  73
  74struct ath10k_htc_hdr {
  75        u8 eid; /* @enum ath10k_htc_ep_id */
  76        u8 flags; /* @enum ath10k_htc_tx_flags, ath10k_htc_rx_flags */
  77        __le16 len;
  78        union {
  79                u8 trailer_len; /* for rx */
  80                u8 control_byte0;
  81        } __packed;
  82        union {
  83                u8 seq_no; /* for tx */
  84                u8 control_byte1;
  85        } __packed;
  86        union {
  87                __le16 pad_len;
  88                struct {
  89                        u8 pad0;
  90                        u8 pad1;
  91                } __packed;
  92        } __packed;
  93
  94} __packed __aligned(4);
  95
  96enum ath10k_ath10k_htc_msg_id {
  97        ATH10K_HTC_MSG_READY_ID                = 1,
  98        ATH10K_HTC_MSG_CONNECT_SERVICE_ID      = 2,
  99        ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID = 3,
 100        ATH10K_HTC_MSG_SETUP_COMPLETE_ID       = 4,
 101        ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID    = 5,
 102        ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE   = 6
 103};
 104
 105enum ath10k_htc_version {
 106        ATH10K_HTC_VERSION_2P0 = 0x00, /* 2.0 */
 107        ATH10K_HTC_VERSION_2P1 = 0x01, /* 2.1 */
 108};
 109
 110enum ath10k_htc_conn_flags {
 111        ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH    = 0x0,
 112        ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_HALF      = 0x1,
 113        ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS = 0x2,
 114        ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_UNITY         = 0x3,
 115#define ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_MASK 0x3
 116        ATH10K_HTC_CONN_FLAGS_REDUCE_CREDIT_DRIBBLE    = 1 << 2,
 117        ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL = 1 << 3
 118#define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_MASK 0xFF00
 119#define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_LSB  8
 120};
 121
 122#define ATH10K_HTC_MSG_READY_EXT_ALT_DATA_MASK 0xFFF
 123
 124enum ath10k_htc_conn_svc_status {
 125        ATH10K_HTC_CONN_SVC_STATUS_SUCCESS      = 0,
 126        ATH10K_HTC_CONN_SVC_STATUS_NOT_FOUND    = 1,
 127        ATH10K_HTC_CONN_SVC_STATUS_FAILED       = 2,
 128        ATH10K_HTC_CONN_SVC_STATUS_NO_RESOURCES = 3,
 129        ATH10K_HTC_CONN_SVC_STATUS_NO_MORE_EP   = 4
 130};
 131
 132#define ATH10K_MAX_MSG_PER_HTC_TX_BUNDLE        32
 133#define ATH10K_MIN_MSG_PER_HTC_TX_BUNDLE        2
 134#define ATH10K_MIN_CREDIT_PER_HTC_TX_BUNDLE     2
 135
 136enum ath10k_htc_setup_complete_flags {
 137        ATH10K_HTC_SETUP_COMPLETE_FLAGS_RX_BNDL_EN = 1
 138};
 139
 140struct ath10k_ath10k_htc_msg_hdr {
 141        __le16 message_id; /* @enum htc_message_id */
 142} __packed;
 143
 144struct ath10k_htc_unknown {
 145        u8 pad0;
 146        u8 pad1;
 147} __packed;
 148
 149struct ath10k_htc_ready {
 150        __le16 credit_count;
 151        __le16 credit_size;
 152        u8 max_endpoints;
 153        u8 pad0;
 154} __packed;
 155
 156struct ath10k_htc_ready_extended {
 157        struct ath10k_htc_ready base;
 158        u8 htc_version; /* @enum ath10k_htc_version */
 159        u8 max_msgs_per_htc_bundle;
 160        union {
 161                __le16 reserved;
 162                struct {
 163                        u8 pad0;
 164                        u8 pad1;
 165                } __packed;
 166        } __packed;
 167
 168} __packed;
 169
 170struct ath10k_htc_conn_svc {
 171        __le16 service_id;
 172        __le16 flags; /* @enum ath10k_htc_conn_flags */
 173        u8 pad0;
 174        u8 pad1;
 175} __packed;
 176
 177struct ath10k_htc_conn_svc_response {
 178        __le16 service_id;
 179        u8 status; /* @enum ath10k_htc_conn_svc_status */
 180        u8 eid;
 181        __le16 max_msg_size;
 182} __packed;
 183
 184struct ath10k_htc_setup_complete_extended {
 185        u8 pad0;
 186        u8 pad1;
 187        __le32 flags; /* @enum htc_setup_complete_flags */
 188        u8 max_msgs_per_bundled_recv;
 189        u8 pad2;
 190        u8 pad3;
 191        u8 pad4;
 192} __packed;
 193
 194struct ath10k_htc_msg {
 195        struct ath10k_ath10k_htc_msg_hdr hdr;
 196        union {
 197                /* host-to-target */
 198                struct ath10k_htc_conn_svc connect_service;
 199                struct ath10k_htc_ready ready;
 200                struct ath10k_htc_ready_extended ready_ext;
 201                struct ath10k_htc_unknown unknown;
 202                struct ath10k_htc_setup_complete_extended setup_complete_ext;
 203
 204                /* target-to-host */
 205                struct ath10k_htc_conn_svc_response connect_service_response;
 206        };
 207} __packed __aligned(4);
 208
 209enum ath10k_ath10k_htc_record_id {
 210        ATH10K_HTC_RECORD_NULL             = 0,
 211        ATH10K_HTC_RECORD_CREDITS          = 1,
 212        ATH10K_HTC_RECORD_LOOKAHEAD        = 2,
 213        ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE = 3,
 214};
 215
 216struct ath10k_ath10k_htc_record_hdr {
 217        u8 id; /* @enum ath10k_ath10k_htc_record_id */
 218        u8 len;
 219        u8 pad0;
 220        u8 pad1;
 221} __packed;
 222
 223struct ath10k_htc_credit_report {
 224        u8 eid; /* @enum ath10k_htc_ep_id */
 225        u8 credits;
 226        u8 pad0;
 227        u8 pad1;
 228} __packed;
 229
 230struct ath10k_htc_lookahead_report {
 231        u8 pre_valid;
 232        u8 pad0;
 233        u8 pad1;
 234        u8 pad2;
 235        u8 lookahead[4];
 236        u8 post_valid;
 237        u8 pad3;
 238        u8 pad4;
 239        u8 pad5;
 240} __packed;
 241
 242struct ath10k_htc_lookahead_bundle {
 243        u8 lookahead[4];
 244} __packed;
 245
 246struct ath10k_htc_record {
 247        struct ath10k_ath10k_htc_record_hdr hdr;
 248        union {
 249                struct ath10k_htc_credit_report credit_report[0];
 250                struct ath10k_htc_lookahead_report lookahead_report[0];
 251                struct ath10k_htc_lookahead_bundle lookahead_bundle[0];
 252                u8 pauload[0];
 253        };
 254} __packed __aligned(4);
 255
 256/*
 257 * note: the trailer offset is dynamic depending
 258 * on payload length. this is only a struct layout draft
 259 */
 260struct ath10k_htc_frame {
 261        struct ath10k_htc_hdr hdr;
 262        union {
 263                struct ath10k_htc_msg msg;
 264                u8 payload[0];
 265        };
 266        struct ath10k_htc_record trailer[0];
 267} __packed __aligned(4);
 268
 269/*******************/
 270/* Host-side stuff */
 271/*******************/
 272
 273enum ath10k_htc_svc_gid {
 274        ATH10K_HTC_SVC_GRP_RSVD = 0,
 275        ATH10K_HTC_SVC_GRP_WMI = 1,
 276        ATH10K_HTC_SVC_GRP_NMI = 2,
 277        ATH10K_HTC_SVC_GRP_HTT = 3,
 278        ATH10K_LOG_SERVICE_GROUP = 6,
 279
 280        ATH10K_HTC_SVC_GRP_TEST = 254,
 281        ATH10K_HTC_SVC_GRP_LAST = 255,
 282};
 283
 284#define SVC(group, idx) \
 285        (int)(((int)(group) << 8) | (int)(idx))
 286
 287enum ath10k_htc_svc_id {
 288        /* NOTE: service ID of 0x0000 is reserved and should never be used */
 289        ATH10K_HTC_SVC_ID_RESERVED      = 0x0000,
 290        ATH10K_HTC_SVC_ID_UNUSED        = ATH10K_HTC_SVC_ID_RESERVED,
 291
 292        ATH10K_HTC_SVC_ID_RSVD_CTRL     = SVC(ATH10K_HTC_SVC_GRP_RSVD, 1),
 293        ATH10K_HTC_SVC_ID_WMI_CONTROL   = SVC(ATH10K_HTC_SVC_GRP_WMI, 0),
 294        ATH10K_HTC_SVC_ID_WMI_DATA_BE   = SVC(ATH10K_HTC_SVC_GRP_WMI, 1),
 295        ATH10K_HTC_SVC_ID_WMI_DATA_BK   = SVC(ATH10K_HTC_SVC_GRP_WMI, 2),
 296        ATH10K_HTC_SVC_ID_WMI_DATA_VI   = SVC(ATH10K_HTC_SVC_GRP_WMI, 3),
 297        ATH10K_HTC_SVC_ID_WMI_DATA_VO   = SVC(ATH10K_HTC_SVC_GRP_WMI, 4),
 298
 299        ATH10K_HTC_SVC_ID_NMI_CONTROL   = SVC(ATH10K_HTC_SVC_GRP_NMI, 0),
 300        ATH10K_HTC_SVC_ID_NMI_DATA      = SVC(ATH10K_HTC_SVC_GRP_NMI, 1),
 301
 302        ATH10K_HTC_SVC_ID_HTT_DATA_MSG  = SVC(ATH10K_HTC_SVC_GRP_HTT, 0),
 303
 304        ATH10K_HTC_SVC_ID_HTT_DATA2_MSG = SVC(ATH10K_HTC_SVC_GRP_HTT, 1),
 305        ATH10K_HTC_SVC_ID_HTT_DATA3_MSG = SVC(ATH10K_HTC_SVC_GRP_HTT, 2),
 306        ATH10K_HTC_SVC_ID_HTT_LOG_MSG = SVC(ATH10K_LOG_SERVICE_GROUP, 0),
 307        /* raw stream service (i.e. flash, tcmd, calibration apps) */
 308        ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS = SVC(ATH10K_HTC_SVC_GRP_TEST, 0),
 309};
 310
 311#undef SVC
 312
 313enum ath10k_htc_ep_id {
 314        ATH10K_HTC_EP_UNUSED = -1,
 315        ATH10K_HTC_EP_0 = 0,
 316        ATH10K_HTC_EP_1 = 1,
 317        ATH10K_HTC_EP_2,
 318        ATH10K_HTC_EP_3,
 319        ATH10K_HTC_EP_4,
 320        ATH10K_HTC_EP_5,
 321        ATH10K_HTC_EP_6,
 322        ATH10K_HTC_EP_7,
 323        ATH10K_HTC_EP_8,
 324        ATH10K_HTC_EP_COUNT,
 325};
 326
 327struct ath10k_htc_ops {
 328        void (*target_send_suspend_complete)(struct ath10k *ar);
 329};
 330
 331struct ath10k_htc_ep_ops {
 332        void (*ep_tx_complete)(struct ath10k *, struct sk_buff *);
 333        void (*ep_rx_complete)(struct ath10k *, struct sk_buff *);
 334        void (*ep_tx_credits)(struct ath10k *);
 335};
 336
 337/* service connection information */
 338struct ath10k_htc_svc_conn_req {
 339        u16 service_id;
 340        struct ath10k_htc_ep_ops ep_ops;
 341        int max_send_queue_depth;
 342};
 343
 344/* service connection response information */
 345struct ath10k_htc_svc_conn_resp {
 346        u8 buffer_len;
 347        u8 actual_len;
 348        enum ath10k_htc_ep_id eid;
 349        unsigned int max_msg_len;
 350        u8 connect_resp_code;
 351};
 352
 353#define ATH10K_NUM_CONTROL_TX_BUFFERS 2
 354#define ATH10K_HTC_MAX_LEN 4096
 355#define ATH10K_HTC_MAX_CTRL_MSG_LEN 256
 356#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1 * HZ)
 357#define ATH10K_HTC_CONTROL_BUFFER_SIZE (ATH10K_HTC_MAX_CTRL_MSG_LEN + \
 358                                        sizeof(struct ath10k_htc_hdr))
 359#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1 * HZ)
 360
 361struct ath10k_htc_ep {
 362        struct ath10k_htc *htc;
 363        enum ath10k_htc_ep_id eid;
 364        enum ath10k_htc_svc_id service_id;
 365        struct ath10k_htc_ep_ops ep_ops;
 366
 367        int max_tx_queue_depth;
 368        int max_ep_message_len;
 369        u8 ul_pipe_id;
 370        u8 dl_pipe_id;
 371
 372        u8 seq_no; /* for debugging */
 373        int tx_credits;
 374        int tx_credit_size;
 375        bool tx_credit_flow_enabled;
 376        bool bundle_tx;
 377        struct sk_buff_head tx_req_head;
 378        struct sk_buff_head tx_complete_head;
 379
 380};
 381
 382struct ath10k_htc_svc_tx_credits {
 383        u16 service_id;
 384        u8  credit_allocation;
 385};
 386
 387struct ath10k_htc {
 388        struct ath10k *ar;
 389        struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT];
 390
 391        /* protects endpoints */
 392        spinlock_t tx_lock;
 393
 394        struct ath10k_htc_ops htc_ops;
 395
 396        u8 control_resp_buffer[ATH10K_HTC_MAX_CTRL_MSG_LEN];
 397        int control_resp_len;
 398
 399        struct completion ctl_resp;
 400
 401        int total_transmit_credits;
 402        int target_credit_size;
 403        u8 max_msgs_per_htc_bundle;
 404        int alt_data_credit_size;
 405};
 406
 407int ath10k_htc_init(struct ath10k *ar);
 408int ath10k_htc_wait_target(struct ath10k_htc *htc);
 409void ath10k_htc_setup_tx_req(struct ath10k_htc_ep *ep);
 410int ath10k_htc_start(struct ath10k_htc *htc);
 411int ath10k_htc_connect_service(struct ath10k_htc *htc,
 412                               struct ath10k_htc_svc_conn_req  *conn_req,
 413                               struct ath10k_htc_svc_conn_resp *conn_resp);
 414void ath10k_htc_change_tx_credit_flow(struct ath10k_htc *htc,
 415                                      enum ath10k_htc_ep_id eid,
 416                                      bool enable);
 417int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
 418                    struct sk_buff *packet);
 419void ath10k_htc_stop_hl(struct ath10k *ar);
 420
 421int ath10k_htc_send_hl(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
 422                       struct sk_buff *packet);
 423struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
 424void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
 425void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
 426void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
 427                                     struct sk_buff *skb);
 428int ath10k_htc_process_trailer(struct ath10k_htc *htc,
 429                               u8 *buffer,
 430                               int length,
 431                               enum ath10k_htc_ep_id src_eid,
 432                               void *next_lookaheads,
 433                               int *next_lookaheads_len);
 434
 435#endif
 436