summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/htc_hst.h
blob: ea50ab032d205fa92c62aba023e540b64a4ee3ad (plain)
1
2
3
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
91
92
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
/*
 * Copyright (c) 2010 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_HST_H
#define HTC_HST_H

struct ath9k_htc_priv;
struct htc_target;
struct ath9k_htc_tx_ctl;

enum ath9k_hif_transports {
	ATH9K_HIF_USB,
};

struct ath9k_htc_hif {
	struct list_head list;
	const enum ath9k_hif_transports transport;
	const char *name;

	u8 control_dl_pipe;
	u8 control_ul_pipe;

	void (*start) (void *hif_handle, u8 pipe);
	void (*stop) (void *hif_handle, u8 pipe);
	int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf,
		     struct ath9k_htc_tx_ctl *tx_ctl);
};

enum htc_endpoint_id {
	ENDPOINT_UNUSED = -1,
	ENDPOINT0 = 0,
	ENDPOINT1 = 1,
	ENDPOINT2 = 2,
	ENDPOINT3 = 3,
	ENDPOINT4 = 4,
	ENDPOINT5 = 5,
	ENDPOINT6 = 6,
	ENDPOINT7 = 7,
	ENDPOINT8 = 8,
	ENDPOINT_MAX = 22
};

/* Htc frame hdr flags */
#define HTC_FLAGS_RECV_TRAILER (1 << 1)

struct htc_frame_hdr {
	u8 endpoint_id;
	u8 flags;
	__be16 payload_len;
	u8 control[4];
} __packed;

struct htc_ready_msg {
	__be16 message_id;
	__be16 credits;
	__be16 credit_size;
	u8 max_endpoints;
	u8 pad;
} __packed;

struct htc_config_pipe_msg {
	__be16 message_id;
	u8 pipe_id;
	u8 credits;
} __packed;

struct htc_packet {
	void *pktcontext;
	u8 *buf;
	u8 *buf_payload;
	u32 buflen;
	u32 payload_len;

	int endpoint;
	int status;

	void *context;
	u32 reserved;
};

struct htc_ep_callbacks {
	void *priv;
	void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok);
	void (*rx) (void *, struct sk_buff *, enum htc_endpoint_id);
};

#define HTC_TX_QUEUE_SIZE 256

struct htc_txq {
	struct sk_buff *buf[HTC_TX_QUEUE_SIZE];
	u32 txqdepth;
	u16 txbuf_cnt;
	u16 txq_head;
	u16 txq_tail;
};

struct htc_endpoint {
	u16 service_id;

	struct htc_ep_callbacks ep_callbacks;
	struct htc_txq htc_txq;
	u32 max_txqdepth;
	int max_msglen;

	u8 ul_pipeid;
	u8 dl_pipeid;
};

#define HTC_MAX_CONTROL_MESSAGE_LENGTH 255
#define HTC_CONTROL_BUFFER_SIZE	\
	(HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr))

#define NUM_CONTROL_BUFFERS 8
#define HST_ENDPOINT_MAX 8

struct htc_control_buf {
	struct htc_packet htc_pkt;
	u8 buf[HTC_CONTROL_BUFFER_SIZE];
};

#define HTC_OP_START_WAIT           BIT(0)
#define HTC_OP_CONFIG_PIPE_CREDITS  BIT(1)

struct htc_target {
	void *hif_dev;
	struct ath9k_htc_priv *drv_priv;
	struct device *dev;
	struct ath9k_htc_hif *hif;
	struct htc_endpoint endpoint[HST_ENDPOINT_MAX];
	struct completion target_wait;
	struct completion cmd_wait;
	struct list_head list;
	enum htc_endpoint_id conn_rsp_epid;
	u16 credits;
	u16 credit_size;
	u8 htc_flags;
};

enum htc_msg_id {
	HTC_MSG_READY_ID = 1,
	HTC_MSG_CONNECT_SERVICE_ID,
	HTC_MSG_CONNECT_SERVICE_RESPONSE_ID,
	HTC_MSG_SETUP_COMPLETE_ID,
	HTC_MSG_CONFIG_PIPE_ID,
	HTC_MSG_CONFIG_PIPE_RESPONSE_ID,
};

struct htc_service_connreq {
	u16 service_id;
	u16 con_flags;
	u32 max_send_qdepth;
	struct htc_ep_callbacks ep_callbacks;
};

/* Current service IDs */

enum htc_service_group_ids{
	RSVD_SERVICE_GROUP = 0,
	WMI_SERVICE_GROUP = 1,

	HTC_SERVICE_GROUP_LAST = 255
};

#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 HTC_LOOPBACK_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 2)

#define WMI_CONTROL_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 0)
#define WMI_BEACON_SVC	  MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 1)
#define WMI_CAB_SVC	  MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 2)
#define WMI_UAPSD_SVC	  MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 3)
#define WMI_MGMT_SVC	  MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4)
#define WMI_DATA_VO_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 5)
#define WMI_DATA_VI_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 6)
#define WMI_DATA_BE_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 7)
#define WMI_DATA_BK_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 8)

struct htc_conn_svc_msg {
	__be16 msg_id;
	__be16 service_id;
	__be16 con_flags;
	u8 dl_pipeid;
	u8 ul_pipeid;
	u8 svc_meta_len;
	u8 pad;
} __packed;

/* connect response status codes */
#define HTC_SERVICE_SUCCESS      0
#define HTC_SERVICE_NOT_FOUND    1
#define HTC_SERVICE_FAILED       2
#define HTC_SERVICE_NO_RESOURCES 3
#define HTC_SERVICE_NO_MORE_EP   4

struct htc_conn_svc_rspmsg {
	__be16 msg_id;
	__be16 service_id;
	u8 status;
	u8 endpoint_id;
	__be16 max_msg_len;
	u8 svc_meta_len;
	u8 pad;
} __packed;

struct htc_comp_msg {
	__be16 msg_id;
} __packed;

int htc_init(struct htc_target *target);
int htc_connect_service(struct htc_target *target,
			  struct htc_service_connreq *service_connreq,
			  enum htc_endpoint_id *conn_rsp_eid);
int htc_send(struct htc_target *target, struct sk_buff *skb,
	     enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl);
void htc_stop(struct htc_target *target);
void htc_start(struct htc_target *target);

void ath9k_htc_rx_msg(struct htc_target *htc_handle,
		      struct sk_buff *skb, u32 len, u8 pipe_id);
void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
			       struct sk_buff *skb, bool txok);

struct htc_target *ath9k_htc_hw_alloc(void *hif_handle);
void ath9k_htc_hw_free(struct htc_target *htc);
int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target,
		      void *hif_handle, struct device *dev, u16 devid,
		      enum ath9k_hif_transports transport);
void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug);

#endif /* HTC_HST_H */