]>
Commit | Line | Data |
---|---|---|
1af447de MM |
1 | /* |
2 | * Espressif Systems Wireless LAN device driver | |
3 | * | |
d7215282 | 4 | * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD |
1af447de | 5 | * |
d7215282 | 6 | * SPDX-License-Identifier: GPL-2.0-only |
1af447de | 7 | */ |
057d3956 | 8 | #include "utils.h" |
6d417020 | 9 | #include <linux/mutex.h> |
6968597b MM |
10 | #include <linux/mmc/sdio.h> |
11 | #include <linux/mmc/sdio_func.h> | |
12 | #include <linux/mmc/sdio_ids.h> | |
13 | #include <linux/mmc/card.h> | |
14 | #include <linux/mmc/host.h> | |
15 | #include "esp_if.h" | |
16 | #include "esp_sdio_api.h" | |
17 | #include "esp_api.h" | |
71d37aa1 | 18 | #include "esp_bt_api.h" |
6968597b | 19 | #include <linux/kthread.h> |
5bd53032 | 20 | #include <linux/printk.h> |
bf3d6cb6 | 21 | #include "esp_stats.h" |
1294f8ac | 22 | #include "include/esp_kernel_port.h" |
6968597b | 23 | |
19b47858 | 24 | #define MAX_WRITE_RETRIES 2 |
8e29337c MM |
25 | #define TX_MAX_PENDING_COUNT 200 |
26 | #define TX_RESUME_THRESHOLD (TX_MAX_PENDING_COUNT/5) | |
03e9f879 | 27 | |
6968597b MM |
28 | #define CHECK_SDIO_RW_ERROR(ret) do { \ |
29 | if (ret) \ | |
30 | printk(KERN_ERR "%s: CMD53 read/write error at %d\n", __func__, __LINE__); \ | |
31 | } while (0); | |
32 | ||
422f3570 | 33 | struct esp_sdio_context sdio_context; |
03e9f879 | 34 | static atomic_t tx_pending; |
4848e879 | 35 | static atomic_t queue_items[MAX_PRIORITY_QUEUES]; |
c88030e0 MM |
36 | |
37 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS | |
6968597b | 38 | struct task_struct *monitor_thread; |
c88030e0 | 39 | #endif |
03e9f879 | 40 | struct task_struct *tx_thread; |
6968597b | 41 | |
3fef9acf MM |
42 | volatile u8 host_sleep = 0; |
43 | ||
422f3570 | 44 | static int init_context(struct esp_sdio_context *context); |
6968597b | 45 | static struct sk_buff * read_packet(struct esp_adapter *adapter); |
03e9f879 | 46 | static int write_packet(struct esp_adapter *adapter, struct sk_buff *skb); |
6968597b MM |
47 | /*int deinit_context(struct esp_adapter *adapter);*/ |
48 | ||
422f3570 | 49 | static const struct sdio_device_id esp_devices[] = { |
6968597b MM |
50 | { SDIO_DEVICE(ESP_VENDOR_ID, ESP_DEVICE_ID_1) }, |
51 | { SDIO_DEVICE(ESP_VENDOR_ID, ESP_DEVICE_ID_2) }, | |
52 | {} | |
53 | }; | |
54 | ||
422f3570 | 55 | static void esp_process_interrupt(struct esp_sdio_context *context, u32 int_status) |
6968597b MM |
56 | { |
57 | if (!context) { | |
58 | return; | |
59 | } | |
60 | ||
61 | if (int_status & ESP_SLAVE_RX_NEW_PACKET_INT) { | |
422f3570 | 62 | esp_process_new_packet_intr(context->adapter); |
6968597b | 63 | } |
6968597b MM |
64 | } |
65 | ||
422f3570 | 66 | static void esp_handle_isr(struct sdio_func *func) |
6968597b | 67 | { |
422f3570 | 68 | struct esp_sdio_context *context = NULL; |
5bd53032 | 69 | u32 *int_status; |
6968597b MM |
70 | int ret; |
71 | ||
72 | if (!func) { | |
73 | return; | |
74 | } | |
75 | ||
3fef9acf MM |
76 | if (host_sleep) |
77 | return; | |
78 | ||
6968597b MM |
79 | context = sdio_get_drvdata(func); |
80 | ||
81 | if (!context) { | |
82 | return; | |
83 | } | |
84 | ||
5bd53032 MM |
85 | int_status = kmalloc(sizeof(u32), GFP_ATOMIC); |
86 | ||
87 | if (!int_status) { | |
88 | return; | |
89 | } | |
90 | ||
6968597b | 91 | /* Read interrupt status register */ |
422f3570 | 92 | ret = esp_read_reg(context, ESP_SLAVE_INT_ST_REG, |
5bd53032 | 93 | (u8 *) int_status, sizeof(* int_status), ACQUIRE_LOCK); |
6968597b MM |
94 | CHECK_SDIO_RW_ERROR(ret); |
95 | ||
5bd53032 | 96 | esp_process_interrupt(context, *int_status); |
6968597b MM |
97 | |
98 | /* Clear interrupt status */ | |
422f3570 | 99 | ret = esp_write_reg(context, ESP_SLAVE_INT_CLR_REG, |
5bd53032 | 100 | (u8 *) int_status, sizeof(* int_status), ACQUIRE_LOCK); |
6968597b | 101 | CHECK_SDIO_RW_ERROR(ret); |
5bd53032 MM |
102 | |
103 | kfree(int_status); | |
6968597b MM |
104 | } |
105 | ||
422f3570 | 106 | int generate_slave_intr(struct esp_sdio_context *context, u8 data) |
6968597b | 107 | { |
5bd53032 MM |
108 | u8 *val; |
109 | int ret = 0; | |
110 | ||
6968597b MM |
111 | if (!context) |
112 | return -EINVAL; | |
113 | ||
5bd53032 MM |
114 | val = kmalloc(sizeof(u8), GFP_KERNEL); |
115 | ||
116 | if (!val) { | |
117 | return -ENOMEM; | |
118 | } | |
119 | ||
120 | *val = data; | |
121 | ||
122 | ret = esp_write_reg(context, ESP_SLAVE_SCRATCH_REG_7, val, | |
123 | sizeof(*val), ACQUIRE_LOCK); | |
124 | ||
125 | kfree(val); | |
126 | ||
127 | return ret; | |
6968597b MM |
128 | } |
129 | ||
130 | static void deinit_sdio_func(struct sdio_func *func) | |
131 | { | |
132 | sdio_claim_host(func); | |
133 | /* Release IRQ */ | |
134 | sdio_release_irq(func); | |
135 | /* Disable sdio function */ | |
136 | sdio_disable_func(func); | |
137 | sdio_release_host(func); | |
71d37aa1 | 138 | sdio_set_drvdata(func, NULL); |
6968597b MM |
139 | } |
140 | ||
422f3570 | 141 | static int esp_slave_get_tx_buffer_num(struct esp_sdio_context *context, u32 *tx_num, u8 is_lock_needed) |
6968597b | 142 | { |
5bd53032 MM |
143 | u32 *len = NULL; |
144 | int ret = 0; | |
6968597b | 145 | |
5bd53032 | 146 | len = kmalloc(sizeof(u32), GFP_KERNEL); |
6968597b | 147 | |
5bd53032 MM |
148 | if (!len) { |
149 | return -ENOMEM; | |
150 | } | |
151 | ||
152 | ret = esp_read_reg(context, ESP_SLAVE_TOKEN_RDATA, (u8*) len, sizeof(*len), is_lock_needed); | |
153 | ||
154 | if (ret) { | |
155 | kfree(len); | |
156 | return ret; | |
157 | } | |
6968597b | 158 | |
5bd53032 MM |
159 | *len = (*len >> 16) & ESP_TX_BUFFER_MASK; |
160 | *len = (*len + ESP_TX_BUFFER_MAX - context->tx_buffer_count) % ESP_TX_BUFFER_MAX; | |
6968597b | 161 | |
5bd53032 | 162 | *tx_num = *len; |
6968597b | 163 | |
5bd53032 MM |
164 | kfree(len); |
165 | return ret; | |
6968597b MM |
166 | } |
167 | ||
422f3570 | 168 | static int esp_get_len_from_slave(struct esp_sdio_context *context, u32 *rx_size, u8 is_lock_needed) |
6968597b | 169 | { |
5bd53032 MM |
170 | u32 *len; |
171 | u32 temp; | |
172 | int ret = 0; | |
6968597b | 173 | |
5bd53032 | 174 | len = kmalloc(sizeof(u32), GFP_KERNEL); |
6968597b | 175 | |
5bd53032 MM |
176 | if (!len) { |
177 | return -ENOMEM; | |
178 | } | |
179 | ||
180 | ret = esp_read_reg(context, ESP_SLAVE_PACKET_LEN_REG, | |
181 | (u8 *) len, sizeof(*len), is_lock_needed); | |
6968597b | 182 | |
5bd53032 MM |
183 | if (ret) { |
184 | kfree (len); | |
185 | return ret; | |
186 | } | |
6968597b | 187 | |
5bd53032 | 188 | *len &= ESP_SLAVE_LEN_MASK; |
6968597b | 189 | |
5bd53032 MM |
190 | if (*len >= context->rx_byte_count) |
191 | *len = (*len + ESP_RX_BYTE_MAX - context->rx_byte_count) % ESP_RX_BYTE_MAX; | |
192 | else { | |
193 | /* Handle a case of roll over */ | |
194 | temp = ESP_RX_BYTE_MAX - context->rx_byte_count; | |
195 | *len = temp + *len; | |
6968597b | 196 | |
5bd53032 MM |
197 | if (*len > ESP_RX_BUFFER_SIZE) { |
198 | printk(KERN_INFO "%s: Len from slave[%d] exceeds max [%d]\n", | |
199 | __func__, *len, ESP_RX_BUFFER_SIZE); | |
200 | } | |
201 | } | |
202 | *rx_size = *len; | |
203 | ||
204 | kfree (len); | |
205 | return 0; | |
6968597b MM |
206 | } |
207 | ||
208 | ||
774e9b2e | 209 | #if 0 |
422f3570 | 210 | static void flush_sdio(struct esp_sdio_context *context) |
6968597b MM |
211 | { |
212 | struct sk_buff *skb; | |
213 | ||
214 | if (!context || !context->adapter) | |
215 | return; | |
216 | ||
217 | while (1) { | |
218 | skb = read_packet(context->adapter); | |
219 | ||
220 | if (!skb) { | |
221 | break; | |
222 | } | |
223 | ||
224 | if (skb->len) | |
1af447de | 225 | printk (KERN_INFO "%s: Flushed %d bytes\n", __func__, skb->len); |
6968597b | 226 | dev_kfree_skb(skb); |
774e9b2e | 227 | skb = NULL; |
6968597b MM |
228 | } |
229 | } | |
774e9b2e | 230 | #endif |
6968597b | 231 | |
422f3570 | 232 | static void esp_remove(struct sdio_func *func) |
6968597b | 233 | { |
422f3570 | 234 | struct esp_sdio_context *context; |
4848e879 | 235 | uint8_t prio_q_idx = 0; |
6968597b MM |
236 | context = sdio_get_drvdata(func); |
237 | ||
c88030e0 | 238 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS |
6968597b MM |
239 | if (monitor_thread) |
240 | kthread_stop(monitor_thread); | |
c88030e0 | 241 | #endif |
774e9b2e MM |
242 | if (context) { |
243 | context->state = ESP_CONTEXT_INIT; | |
244 | for (prio_q_idx=0; prio_q_idx<MAX_PRIORITY_QUEUES; prio_q_idx++) | |
245 | skb_queue_purge(&(sdio_context.tx_q[prio_q_idx])); | |
246 | } | |
6968597b | 247 | |
03e9f879 YM |
248 | if (tx_thread) |
249 | kthread_stop(tx_thread); | |
250 | ||
6968597b | 251 | if (context) { |
f0597120 | 252 | generate_slave_intr(context, BIT(ESP_CLOSE_DATA_PATH)); |
6968597b MM |
253 | msleep(100); |
254 | ||
774e9b2e | 255 | context->state = ESP_CONTEXT_DISABLED; |
6968597b MM |
256 | |
257 | if (context->adapter) { | |
422f3570 | 258 | esp_remove_card(context->adapter); |
71d37aa1 MM |
259 | |
260 | if (context->adapter->hcidev) { | |
261 | esp_deinit_bt(context->adapter); | |
262 | } | |
4848e879 | 263 | } |
71d37aa1 | 264 | |
774e9b2e MM |
265 | |
266 | if (context->func) { | |
267 | deinit_sdio_func(context->func); | |
268 | context->func = NULL; | |
269 | } | |
422f3570 | 270 | memset(context, 0, sizeof(struct esp_sdio_context)); |
6968597b | 271 | } |
6968597b MM |
272 | } |
273 | ||
274 | static struct esp_if_ops if_ops = { | |
275 | .read = read_packet, | |
276 | .write = write_packet, | |
277 | }; | |
278 | ||
3fef9acf | 279 | static int get_firmware_data(struct esp_sdio_context *context) |
6968597b | 280 | { |
5bd53032 | 281 | u32 *val; |
3fef9acf | 282 | int ret = 0; |
6968597b | 283 | |
5bd53032 MM |
284 | val = kmalloc(sizeof(u32), GFP_KERNEL); |
285 | ||
286 | if (!val) { | |
287 | return -ENOMEM; | |
288 | } | |
289 | ||
6968597b | 290 | /* Initialize rx_byte_count */ |
422f3570 | 291 | ret = esp_read_reg(context, ESP_SLAVE_PACKET_LEN_REG, |
5bd53032 MM |
292 | (u8 *) val, sizeof(* val), ACQUIRE_LOCK); |
293 | if (ret) { | |
294 | kfree(val); | |
6968597b | 295 | return ret; |
5bd53032 | 296 | } |
6968597b | 297 | |
3fef9acf | 298 | printk(KERN_INFO "Rx Pre ====== %d\n", context->rx_byte_count); |
5bd53032 | 299 | context->rx_byte_count = *val & ESP_SLAVE_LEN_MASK; |
3fef9acf | 300 | printk(KERN_INFO "Rx Pos ====== %d\n", context->rx_byte_count); |
6968597b MM |
301 | |
302 | /* Initialize tx_buffer_count */ | |
5bd53032 MM |
303 | ret = esp_read_reg(context, ESP_SLAVE_TOKEN_RDATA, (u8 *) val, |
304 | sizeof(* val), ACQUIRE_LOCK); | |
6968597b | 305 | |
5bd53032 MM |
306 | if (ret) { |
307 | kfree(val); | |
6968597b | 308 | return ret; |
5bd53032 | 309 | } |
6968597b | 310 | |
5bd53032 | 311 | *val = ((*val >> 16) & ESP_TX_BUFFER_MASK); |
3fef9acf | 312 | printk(KERN_INFO "Tx Pre ====== %d\n", context->tx_buffer_count); |
6968597b | 313 | |
5bd53032 MM |
314 | if (*val >= ESP_MAX_BUF_CNT) |
315 | context->tx_buffer_count = (*val) - ESP_MAX_BUF_CNT; | |
6968597b MM |
316 | else |
317 | context->tx_buffer_count = 0; | |
3fef9acf MM |
318 | printk(KERN_INFO "Tx Pos ====== %d\n", context->tx_buffer_count); |
319 | ||
320 | kfree(val); | |
321 | return ret; | |
322 | } | |
323 | ||
324 | static int init_context(struct esp_sdio_context *context) | |
325 | { | |
326 | int ret = 0; | |
3fef9acf MM |
327 | uint8_t prio_q_idx = 0; |
328 | ||
329 | if (!context) { | |
330 | return -EINVAL; | |
331 | } | |
332 | ||
333 | ret = get_firmware_data(context); | |
334 | if(ret) | |
335 | return ret; | |
6968597b | 336 | |
422f3570 | 337 | context->adapter = esp_get_adapter(); |
6968597b | 338 | |
03e9f879 | 339 | if (unlikely(!context->adapter)) |
6968597b MM |
340 | printk (KERN_ERR "%s: Failed to get adapter\n", __func__); |
341 | ||
4848e879 YM |
342 | for (prio_q_idx=0; prio_q_idx<MAX_PRIORITY_QUEUES; prio_q_idx++) { |
343 | skb_queue_head_init(&(sdio_context.tx_q[prio_q_idx])); | |
344 | atomic_set(&queue_items[prio_q_idx], 0); | |
345 | } | |
03e9f879 | 346 | |
062be972 MM |
347 | context->adapter->if_type = ESP_IF_TYPE_SDIO; |
348 | ||
6968597b MM |
349 | return ret; |
350 | } | |
351 | ||
352 | static struct sk_buff * read_packet(struct esp_adapter *adapter) | |
353 | { | |
354 | u32 len_from_slave, data_left, len_to_read, size, num_blocks; | |
355 | int ret = 0; | |
356 | struct sk_buff *skb; | |
357 | u8 *pos; | |
422f3570 | 358 | struct esp_sdio_context *context; |
6968597b MM |
359 | |
360 | if (!adapter || !adapter->if_context) { | |
1af447de | 361 | printk (KERN_ERR "%s: INVALID args\n", __func__); |
6968597b MM |
362 | return NULL; |
363 | } | |
364 | ||
365 | context = adapter->if_context; | |
366 | ||
774e9b2e MM |
367 | if(!context || (context->state != ESP_CONTEXT_READY) || !context->func) { |
368 | printk(KERN_ERR "Invalid context/state\n"); | |
369 | return NULL; | |
370 | } | |
371 | ||
6caed1bd | 372 | sdio_claim_host(context->func); |
6968597b | 373 | |
6caed1bd | 374 | data_left = len_to_read = len_from_slave = num_blocks = 0; |
6d417020 | 375 | |
6968597b | 376 | /* Read length */ |
422f3570 | 377 | ret = esp_get_len_from_slave(context, &len_from_slave, LOCK_ALREADY_ACQUIRED); |
6968597b | 378 | |
6968597b | 379 | if (ret || !len_from_slave) { |
6caed1bd | 380 | sdio_release_host(context->func); |
6968597b MM |
381 | return NULL; |
382 | } | |
383 | ||
384 | size = ESP_BLOCK_SIZE * 4; | |
385 | ||
386 | if (len_from_slave > size) { | |
467101a5 | 387 | printk(KERN_INFO "Rx large packet: %d\n", len_from_slave); |
6968597b MM |
388 | } |
389 | ||
422f3570 | 390 | skb = esp_alloc_skb(len_from_slave); |
6968597b MM |
391 | |
392 | if (!skb) { | |
393 | printk (KERN_ERR "%s: SKB alloc failed\n", __func__); | |
6caed1bd | 394 | sdio_release_host(context->func); |
6968597b MM |
395 | return NULL; |
396 | } | |
397 | ||
398 | skb_put(skb, len_from_slave); | |
399 | pos = skb->data; | |
400 | ||
401 | data_left = len_from_slave; | |
402 | ||
403 | do { | |
404 | num_blocks = data_left/ESP_BLOCK_SIZE; | |
405 | ||
406 | #if 0 | |
407 | if (!context->rx_byte_count) { | |
408 | start_time = ktime_get_ns(); | |
409 | } | |
410 | #endif | |
411 | ||
412 | if (num_blocks) { | |
413 | len_to_read = num_blocks * ESP_BLOCK_SIZE; | |
422f3570 | 414 | ret = esp_read_block(context, |
6968597b | 415 | ESP_SLAVE_CMD53_END_ADDR - len_to_read, |
c88030e0 | 416 | pos, len_to_read, LOCK_ALREADY_ACQUIRED); |
6968597b MM |
417 | } else { |
418 | len_to_read = data_left; | |
419 | /* 4 byte aligned length */ | |
422f3570 | 420 | ret = esp_read_block(context, |
6968597b | 421 | ESP_SLAVE_CMD53_END_ADDR - len_to_read, |
c88030e0 | 422 | pos, (len_to_read + 3) & (~3), LOCK_ALREADY_ACQUIRED); |
6968597b MM |
423 | } |
424 | ||
425 | if (ret) { | |
5bd53032 | 426 | printk (KERN_ERR "%s: Failed to read data - %d [%u - %d]\n", __func__, ret, num_blocks, len_to_read); |
6968597b | 427 | dev_kfree_skb(skb); |
774e9b2e | 428 | skb = NULL; |
6caed1bd | 429 | sdio_release_host(context->func); |
6968597b MM |
430 | return NULL; |
431 | } | |
432 | ||
433 | data_left -= len_to_read; | |
434 | pos += len_to_read; | |
435 | context->rx_byte_count += len_to_read; | |
436 | context->rx_byte_count = context->rx_byte_count % ESP_RX_BYTE_MAX; | |
437 | ||
438 | } while (data_left > 0); | |
439 | ||
6caed1bd | 440 | sdio_release_host(context->func); |
6d417020 | 441 | |
6968597b MM |
442 | return skb; |
443 | } | |
444 | ||
03e9f879 | 445 | static int write_packet(struct esp_adapter *adapter, struct sk_buff *skb) |
6968597b | 446 | { |
774e9b2e | 447 | u32 max_pkt_size = ESP_RX_BUFFER_SIZE - sizeof(struct esp_payload_header); |
4848e879 | 448 | struct esp_payload_header *payload_header = (struct esp_payload_header *) skb->data; |
774e9b2e MM |
449 | struct esp_skb_cb * cb = NULL; |
450 | uint8_t prio = PRIO_Q_LOW; | |
03e9f879 YM |
451 | |
452 | if (!adapter || !adapter->if_context || !skb || !skb->data || !skb->len) { | |
453 | printk(KERN_ERR "%s: Invalid args\n", __func__); | |
774e9b2e | 454 | if(skb) { |
03e9f879 | 455 | dev_kfree_skb(skb); |
774e9b2e MM |
456 | skb = NULL; |
457 | } | |
6968597b | 458 | |
6968597b MM |
459 | return -EINVAL; |
460 | } | |
461 | ||
03e9f879 YM |
462 | if (skb->len > max_pkt_size) { |
463 | printk(KERN_ERR "%s: Drop pkt of len[%u] > max SDIO transport len[%u]\n", | |
464 | __func__, skb->len, max_pkt_size); | |
465 | dev_kfree_skb(skb); | |
774e9b2e | 466 | skb = NULL; |
03e9f879 YM |
467 | return -EPERM; |
468 | } | |
469 | ||
774e9b2e MM |
470 | cb = (struct esp_skb_cb *)skb->cb; |
471 | if (cb && cb->priv && (atomic_read(&tx_pending) >= TX_MAX_PENDING_COUNT)) { | |
472 | esp_tx_pause(cb->priv); | |
03e9f879 | 473 | dev_kfree_skb(skb); |
774e9b2e MM |
474 | skb = NULL; |
475 | /* printk(KERN_ERR "%s: TX Pause busy", __func__);*/ | |
03e9f879 YM |
476 | return -EBUSY; |
477 | } | |
478 | ||
03e9f879 YM |
479 | /* Enqueue SKB in tx_q */ |
480 | atomic_inc(&tx_pending); | |
481 | ||
4848e879 | 482 | /* Notify to process queue */ |
774e9b2e MM |
483 | if (payload_header->if_type == ESP_INTERNAL_IF) |
484 | prio = PRIO_Q_HIGH; | |
485 | else if (payload_header->if_type == ESP_HCI_IF) | |
486 | prio = PRIO_Q_MID; | |
487 | else | |
488 | prio = PRIO_Q_LOW; | |
489 | ||
490 | atomic_inc(&queue_items[prio]); | |
491 | skb_queue_tail(&(sdio_context.tx_q[prio]), skb); | |
03e9f879 YM |
492 | |
493 | return 0; | |
494 | } | |
495 | ||
bf3d6cb6 SR |
496 | static int is_sdio_write_buffer_available(u32 buf_needed) |
497 | { | |
498 | #define BUFFER_AVAILABLE 1 | |
499 | #define BUFFER_UNAVAILABLE 0 | |
500 | ||
501 | int ret = 0; | |
502 | static u32 buf_available = 0; | |
503 | struct esp_sdio_context *context = &sdio_context; | |
504 | u8 retry = MAX_WRITE_RETRIES; | |
505 | ||
506 | /*If buffer needed are less than buffer available | |
507 | then only read for available buffer number from slave*/ | |
508 | if (buf_available < buf_needed) { | |
509 | while (retry) { | |
510 | ret = esp_slave_get_tx_buffer_num(context, &buf_available, ACQUIRE_LOCK); | |
511 | ||
512 | if (buf_available < buf_needed) { | |
513 | ||
514 | /* Release SDIO and retry after delay*/ | |
515 | retry--; | |
516 | usleep_range(10,50); | |
517 | continue; | |
518 | } | |
519 | ||
520 | break; | |
521 | } | |
522 | } | |
523 | ||
524 | if (buf_available >= buf_needed) | |
525 | buf_available -= buf_needed; | |
526 | ||
527 | if (!retry) { | |
528 | /* No buffer available at slave */ | |
529 | return BUFFER_UNAVAILABLE; | |
530 | } | |
531 | ||
532 | return BUFFER_AVAILABLE; | |
533 | } | |
534 | ||
03e9f879 YM |
535 | static int tx_process(void *data) |
536 | { | |
537 | int ret = 0; | |
538 | u32 block_cnt = 0; | |
bf3d6cb6 | 539 | u32 buf_needed = 0; |
03e9f879 YM |
540 | u8 *pos = NULL; |
541 | u32 data_left, len_to_send, pad; | |
542 | struct sk_buff *tx_skb = NULL; | |
543 | struct esp_adapter *adapter = (struct esp_adapter *) data; | |
544 | struct esp_sdio_context *context = NULL; | |
774e9b2e | 545 | struct esp_skb_cb * cb = NULL; |
19b47858 | 546 | u8 retry; |
03e9f879 | 547 | |
6968597b MM |
548 | context = adapter->if_context; |
549 | ||
03e9f879 | 550 | while (!kthread_should_stop()) { |
6caed1bd | 551 | |
03e9f879 YM |
552 | if (context->state != ESP_CONTEXT_READY) { |
553 | msleep(10); | |
774e9b2e | 554 | printk(KERN_ERR "%s: not ready", __func__); |
03e9f879 YM |
555 | continue; |
556 | } | |
6968597b | 557 | |
3fef9acf MM |
558 | if (host_sleep) { |
559 | /* TODO: Use wait_event_interruptible_timeout */ | |
560 | msleep(100); | |
561 | continue; | |
562 | } | |
563 | ||
774e9b2e MM |
564 | if (atomic_read(&queue_items[PRIO_Q_HIGH]) > 0) { |
565 | tx_skb = skb_dequeue(&(context->tx_q[PRIO_Q_HIGH])); | |
4848e879 YM |
566 | if (!tx_skb) { |
567 | continue; | |
568 | } | |
774e9b2e MM |
569 | atomic_dec(&queue_items[PRIO_Q_HIGH]); |
570 | } else if (atomic_read(&queue_items[PRIO_Q_MID]) > 0) { | |
571 | tx_skb = skb_dequeue(&(context->tx_q[PRIO_Q_MID])); | |
4848e879 YM |
572 | if (!tx_skb) { |
573 | continue; | |
574 | } | |
774e9b2e MM |
575 | atomic_dec(&queue_items[PRIO_Q_MID]); |
576 | } else if (atomic_read(&queue_items[PRIO_Q_LOW]) > 0) { | |
577 | tx_skb = skb_dequeue(&(context->tx_q[PRIO_Q_LOW])); | |
4848e879 YM |
578 | if (!tx_skb) { |
579 | continue; | |
580 | } | |
774e9b2e | 581 | atomic_dec(&queue_items[PRIO_Q_LOW]); |
4848e879 | 582 | } else { |
774e9b2e MM |
583 | #if 0 |
584 | printk(KERN_ERR "%s: not ready 2 [%d %d]\n", __func__, | |
585 | atomic_read(&queue_items[PRIO_Q_OTHERS]), | |
586 | atomic_read(&queue_items[PRIO_Q_SERIAL])); | |
587 | #endif | |
4848e879 | 588 | msleep(1); |
03e9f879 YM |
589 | continue; |
590 | } | |
6968597b | 591 | |
8e29337c MM |
592 | if (atomic_read(&tx_pending)) |
593 | atomic_dec(&tx_pending); | |
594 | ||
19b47858 | 595 | retry = MAX_WRITE_RETRIES; |
6968597b | 596 | |
03e9f879 | 597 | /* resume network tx queue if bearable load */ |
774e9b2e MM |
598 | cb = (struct esp_skb_cb *)tx_skb->cb; |
599 | if (cb && cb->priv && atomic_read(&tx_pending) < TX_RESUME_THRESHOLD) { | |
600 | esp_tx_resume(cb->priv); | |
bf3d6cb6 SR |
601 | #if TEST_RAW_TP |
602 | esp_raw_tp_queue_resume(); | |
603 | #endif | |
03e9f879 | 604 | } |
6968597b | 605 | |
03e9f879 | 606 | buf_needed = (tx_skb->len + ESP_RX_BUFFER_SIZE - 1) / ESP_RX_BUFFER_SIZE; |
6968597b | 607 | |
bf3d6cb6 SR |
608 | /*If SDIO slave buffer is available to write then only write data |
609 | else wait till buffer is available*/ | |
610 | ret = is_sdio_write_buffer_available(buf_needed); | |
611 | if(!ret) { | |
03e9f879 YM |
612 | dev_kfree_skb(tx_skb); |
613 | continue; | |
6968597b | 614 | } |
6968597b | 615 | |
03e9f879 YM |
616 | pos = tx_skb->data; |
617 | data_left = len_to_send = 0; | |
6968597b | 618 | |
03e9f879 YM |
619 | data_left = tx_skb->len; |
620 | pad = ESP_BLOCK_SIZE - (data_left % ESP_BLOCK_SIZE); | |
621 | data_left += pad; | |
6968597b | 622 | |
6caed1bd | 623 | |
03e9f879 YM |
624 | do { |
625 | block_cnt = data_left / ESP_BLOCK_SIZE; | |
626 | len_to_send = data_left; | |
627 | ret = esp_write_block(context, ESP_SLAVE_CMD53_END_ADDR - len_to_send, | |
bf3d6cb6 | 628 | pos, (len_to_send + 3) & (~3), ACQUIRE_LOCK); |
03e9f879 YM |
629 | |
630 | if (ret) { | |
5bd53032 | 631 | printk (KERN_ERR "%s: Failed to send data: %d %d %d\n", __func__, ret, len_to_send, data_left); |
03e9f879 YM |
632 | break; |
633 | } | |
634 | ||
03e9f879 YM |
635 | data_left -= len_to_send; |
636 | pos += len_to_send; | |
637 | } while (data_left); | |
638 | ||
639 | if (ret) { | |
640 | /* drop the packet */ | |
641 | dev_kfree_skb(tx_skb); | |
642 | continue; | |
643 | } | |
644 | ||
645 | context->tx_buffer_count += buf_needed; | |
646 | context->tx_buffer_count = context->tx_buffer_count % ESP_TX_BUFFER_MAX; | |
647 | ||
03e9f879 | 648 | dev_kfree_skb(tx_skb); |
774e9b2e | 649 | tx_skb = NULL; |
03e9f879 YM |
650 | } |
651 | ||
652 | do_exit(0); | |
6968597b MM |
653 | return 0; |
654 | } | |
655 | ||
422f3570 | 656 | static struct esp_sdio_context * init_sdio_func(struct sdio_func *func) |
6968597b | 657 | { |
422f3570 | 658 | struct esp_sdio_context *context = NULL; |
6968597b MM |
659 | int ret = 0; |
660 | ||
661 | if (!func) | |
662 | return NULL; | |
663 | ||
6968597b MM |
664 | context = &sdio_context; |
665 | ||
666 | context->func = func; | |
667 | ||
668 | sdio_claim_host(func); | |
669 | ||
670 | /* Enable Function */ | |
671 | ret = sdio_enable_func(func); | |
672 | if (ret) { | |
673 | return NULL; | |
674 | } | |
675 | ||
676 | /* Register IRQ */ | |
422f3570 | 677 | ret = sdio_claim_irq(func, esp_handle_isr); |
6968597b MM |
678 | if (ret) { |
679 | sdio_disable_func(func); | |
680 | return NULL; | |
681 | } | |
682 | ||
683 | /* Set private data */ | |
684 | sdio_set_drvdata(func, context); | |
685 | ||
686 | context->state = ESP_CONTEXT_INIT; | |
687 | ||
688 | sdio_release_host(func); | |
689 | ||
690 | return context; | |
691 | } | |
692 | ||
c88030e0 | 693 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS |
6968597b MM |
694 | static int monitor_process(void *data) |
695 | { | |
6caed1bd | 696 | u32 val, intr, len_reg, rdata, old_len = 0; |
422f3570 | 697 | struct esp_sdio_context *context = (struct esp_sdio_context *) data; |
6d417020 | 698 | struct sk_buff *skb; |
6968597b MM |
699 | |
700 | while (!kthread_should_stop()) { | |
6caed1bd | 701 | msleep(5000); |
6968597b MM |
702 | |
703 | val = intr = len_reg = rdata = 0; | |
704 | ||
422f3570 | 705 | esp_read_reg(context, ESP_SLAVE_PACKET_LEN_REG, |
c88030e0 | 706 | (u8 *) &val, sizeof(val), ACQUIRE_LOCK); |
6968597b MM |
707 | |
708 | len_reg = val & ESP_SLAVE_LEN_MASK; | |
709 | ||
710 | val = 0; | |
422f3570 | 711 | esp_read_reg(context, ESP_SLAVE_TOKEN_RDATA, (u8 *) &val, |
c88030e0 | 712 | sizeof(val), ACQUIRE_LOCK); |
6968597b MM |
713 | |
714 | rdata = ((val >> 16) & ESP_TX_BUFFER_MASK); | |
715 | ||
422f3570 | 716 | esp_read_reg(context, ESP_SLAVE_INT_ST_REG, |
c88030e0 | 717 | (u8 *) &intr, sizeof(intr), ACQUIRE_LOCK); |
6968597b MM |
718 | |
719 | ||
720 | if (len_reg > context->rx_byte_count) { | |
6caed1bd MM |
721 | if (old_len && (context->rx_byte_count == old_len)) { |
722 | printk (KERN_DEBUG "Monitor thread ----> [%d - %d] [%d - %d] %d\n", | |
723 | len_reg, context->rx_byte_count, | |
6968597b MM |
724 | rdata, context->tx_buffer_count, intr); |
725 | ||
6d417020 MM |
726 | skb = read_packet(context->adapter); |
727 | ||
728 | if (!skb) | |
729 | continue; | |
730 | ||
731 | if (skb->len) | |
6caed1bd | 732 | printk (KERN_DEBUG "%s: Flushed %d bytes\n", __func__, skb->len); |
6968597b | 733 | |
6d417020 MM |
734 | /* drop the packet */ |
735 | dev_kfree_skb(skb); | |
774e9b2e | 736 | skb = NULL; |
6968597b MM |
737 | } |
738 | } | |
739 | ||
740 | old_len = context->rx_byte_count; | |
741 | } | |
742 | ||
743 | do_exit(0); | |
744 | return 0; | |
745 | } | |
c88030e0 | 746 | #endif |
1af447de | 747 | |
422f3570 | 748 | static int esp_probe(struct sdio_func *func, |
6968597b MM |
749 | const struct sdio_device_id *id) |
750 | { | |
422f3570 | 751 | struct esp_sdio_context *context = NULL; |
6968597b MM |
752 | int ret = 0; |
753 | ||
754 | if (func->num != 1) { | |
755 | return -EINVAL; | |
756 | } | |
757 | ||
71d37aa1 MM |
758 | printk(KERN_INFO "%s: ESP network device detected\n", __func__); |
759 | ||
6968597b MM |
760 | context = init_sdio_func(func); |
761 | ||
762 | if (!context) { | |
763 | return -ENOMEM; | |
764 | } | |
765 | ||
774e9b2e | 766 | context->state = ESP_CONTEXT_READY; |
03e9f879 | 767 | atomic_set(&tx_pending, 0); |
6968597b MM |
768 | ret = init_context(context); |
769 | if (ret) { | |
770 | deinit_sdio_func(func); | |
771 | return ret; | |
772 | } | |
773 | ||
03e9f879 YM |
774 | tx_thread = kthread_run(tx_process, context->adapter, "esp32_TX"); |
775 | ||
776 | if (!tx_thread) | |
777 | printk (KERN_ERR "Failed to create esp32_sdio TX thread\n"); | |
778 | ||
774e9b2e MM |
779 | context->adapter->dev = &func->dev; |
780 | generate_slave_intr(context, BIT(ESP_OPEN_DATA_PATH)); | |
5bd53032 | 781 | |
6968597b | 782 | |
c88030e0 | 783 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS |
6968597b MM |
784 | monitor_thread = kthread_run(monitor_process, context, "Monitor process"); |
785 | ||
786 | if (!monitor_thread) | |
787 | printk (KERN_ERR "Failed to create monitor thread\n"); | |
c88030e0 | 788 | #endif |
1af447de | 789 | |
6968597b MM |
790 | return ret; |
791 | } | |
792 | ||
3fef9acf MM |
793 | static int esp_suspend(struct device *dev) |
794 | { | |
5a47b073 | 795 | struct sdio_func *func = NULL; |
3fef9acf MM |
796 | struct esp_sdio_context *context = NULL; |
797 | ||
5a47b073 MM |
798 | if (!dev) { |
799 | printk(KERN_INFO "Failed to inform ESP that host is suspending\n"); | |
800 | return -1; | |
801 | } | |
802 | ||
803 | func = dev_to_sdio_func(dev); | |
804 | ||
3fef9acf MM |
805 | printk(KERN_INFO "----> Host Suspend\n"); |
806 | msleep(1000); | |
807 | ||
808 | context = sdio_get_drvdata(func); | |
809 | ||
810 | if (!context) { | |
5a47b073 | 811 | printk(KERN_INFO "Failed to inform ESP that host is suspending\n"); |
3fef9acf MM |
812 | return -1; |
813 | } | |
814 | ||
815 | host_sleep = 1; | |
816 | ||
817 | generate_slave_intr(context, BIT(ESP_POWER_SAVE_ON)); | |
818 | msleep(10); | |
819 | ||
820 | sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | |
821 | #if 0 | |
822 | /* Enale OOB IRQ and host wake up */ | |
823 | enable_irq(SDIO_OOB_IRQ); | |
824 | enable_irq_wake(SDIO_OOB_IRQ); | |
825 | #endif | |
826 | return 0; | |
827 | } | |
828 | ||
829 | static int esp_resume(struct device *dev) | |
830 | { | |
5a47b073 | 831 | struct sdio_func *func = NULL; |
3fef9acf MM |
832 | struct esp_sdio_context *context = NULL; |
833 | ||
5a47b073 MM |
834 | if (!dev) { |
835 | printk(KERN_INFO "Failed to inform ESP that host is awake\n"); | |
836 | return -1; | |
837 | } | |
838 | ||
839 | func = dev_to_sdio_func(dev); | |
840 | ||
3fef9acf MM |
841 | printk(KERN_INFO "-----> Host Awake\n"); |
842 | #if 0 | |
843 | /* Host woke up.. Disable OOB IRQ */ | |
844 | disable_irq_wake(SDIO_OOB_IRQ); | |
845 | disable_irq(SDIO_OOB_IRQ); | |
846 | #endif | |
847 | ||
848 | ||
849 | context = sdio_get_drvdata(func); | |
850 | ||
851 | if (!context) { | |
5a47b073 | 852 | printk(KERN_INFO "Failed to inform ESP that host is awake\n"); |
3fef9acf MM |
853 | return -1; |
854 | } | |
855 | ||
856 | /* generate_slave_intr(context, BIT(ESP_RESET));*/ | |
857 | get_firmware_data(context); | |
858 | msleep(100); | |
859 | generate_slave_intr(context, BIT(ESP_POWER_SAVE_OFF)); | |
860 | host_sleep = 0; | |
861 | return 0; | |
862 | } | |
863 | ||
864 | static const struct dev_pm_ops esp_pm_ops = { | |
5a47b073 MM |
865 | .suspend = esp_suspend, |
866 | .resume = esp_resume, | |
3fef9acf MM |
867 | }; |
868 | ||
6968597b MM |
869 | /* SDIO driver structure to be registered with kernel */ |
870 | static struct sdio_driver esp_sdio_driver = { | |
422f3570 MM |
871 | .name = "esp_sdio", |
872 | .id_table = esp_devices, | |
873 | .probe = esp_probe, | |
874 | .remove = esp_remove, | |
3fef9acf MM |
875 | .drv = { |
876 | .owner = THIS_MODULE, | |
877 | .pm = &esp_pm_ops, | |
878 | } | |
879 | ||
6968597b MM |
880 | }; |
881 | ||
422f3570 | 882 | int esp_init_interface_layer(struct esp_adapter *adapter) |
6968597b MM |
883 | { |
884 | if (!adapter) | |
885 | return -EINVAL; | |
886 | ||
887 | adapter->if_context = &sdio_context; | |
888 | adapter->if_ops = &if_ops; | |
889 | sdio_context.adapter = adapter; | |
890 | ||
891 | return sdio_register_driver(&esp_sdio_driver); | |
892 | } | |
893 | ||
774e9b2e | 894 | void process_event_esp_bootup(struct esp_adapter *adapter, u8 *evt_buf, u8 len) |
42f570e1 YM |
895 | { |
896 | u8 len_left = len, tag_len; | |
897 | u8 *pos; | |
774e9b2e MM |
898 | struct esp_sdio_context *context = &sdio_context; |
899 | ||
900 | if (!adapter) | |
901 | return; | |
42f570e1 YM |
902 | |
903 | if (!evt_buf) | |
904 | return; | |
905 | ||
906 | pos = evt_buf; | |
907 | ||
908 | while (len_left) { | |
909 | tag_len = *(pos + 1); | |
774e9b2e | 910 | |
42f570e1 | 911 | printk(KERN_INFO "EVENT: %d\n", *pos); |
774e9b2e MM |
912 | |
913 | if (*pos == ESP_BOOTUP_CAPABILITY) { | |
914 | ||
915 | adapter->capabilities = *(pos + 2); | |
916 | process_capabilities(adapter); | |
42f570e1 | 917 | print_capabilities(*(pos + 2)); |
774e9b2e MM |
918 | |
919 | } else if (*pos == ESP_BOOTUP_FIRMWARE_CHIP_ID){ | |
920 | ||
5a47b073 | 921 | printk(KERN_INFO "ESP chipset detected [%s]\n", |
774e9b2e MM |
922 | *(pos+2)==ESP_FIRMWARE_CHIP_ESP32 ? "esp32": |
923 | *(pos+2)==ESP_FIRMWARE_CHIP_ESP32S2 ? "esp32-s2" : | |
924 | *(pos+2)==ESP_FIRMWARE_CHIP_ESP32C3 ? "esp32-c3" : | |
925 | *(pos+2)==ESP_FIRMWARE_CHIP_ESP32S3 ? "esp32-s3" : | |
926 | "unknown"); | |
927 | ||
928 | if (*(pos+2)!=ESP_FIRMWARE_CHIP_ESP32) | |
929 | printk(KERN_ERR "SDIO is only supported with ESP32\n"); | |
930 | ||
bf3d6cb6 SR |
931 | } else if (*pos == ESP_BOOTUP_TEST_RAW_TP) { |
932 | process_test_capabilities(*(pos + 2)); | |
933 | ||
774e9b2e MM |
934 | } else if (*pos == ESP_BOOTUP_FW_DATA) { |
935 | ||
936 | if (tag_len != sizeof(struct fw_data)) | |
937 | printk(KERN_INFO "Length not matching to firmware data size\n"); | |
938 | else | |
939 | if (process_fw_data((struct fw_data*)(pos + 2))) | |
940 | if (context->func) { | |
941 | generate_slave_intr(context, BIT(ESP_CLOSE_DATA_PATH)); | |
942 | return; | |
943 | } | |
944 | ||
42f570e1 YM |
945 | } else { |
946 | printk (KERN_WARNING "Unsupported tag in event"); | |
947 | } | |
774e9b2e | 948 | |
42f570e1 YM |
949 | pos += (tag_len+2); |
950 | len_left -= (tag_len+2); | |
951 | } | |
774e9b2e MM |
952 | |
953 | if (esp_add_card(adapter)) { | |
954 | printk(KERN_ERR "network iterface init failed\n"); | |
955 | generate_slave_intr(context, BIT(ESP_CLOSE_DATA_PATH)); | |
956 | } | |
42f570e1 YM |
957 | } |
958 | ||
422f3570 | 959 | void esp_deinit_interface_layer(void) |
6968597b MM |
960 | { |
961 | sdio_unregister_driver(&esp_sdio_driver); | |
962 | } |