Commit | Line | Data |
---|---|---|
e91a78c7 TK |
1 | /**************************************************************************** |
2 | * | |
3 | * Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved | |
4 | * | |
5 | * BT driver entry point | |
6 | * | |
7 | ****************************************************************************/ | |
8 | ||
9 | #include <linux/version.h> | |
10 | #include <linux/init.h> | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/types.h> | |
14 | #include <linux/fs.h> | |
15 | #include <linux/module.h> | |
16 | #include <linux/firmware.h> | |
17 | #include <linux/poll.h> | |
18 | #include <linux/slab.h> | |
19 | #include <linux/cdev.h> | |
20 | #include <linux/device.h> | |
21 | #include <linux/kthread.h> | |
22 | #include <linux/proc_fs.h> | |
23 | #include <asm/io.h> | |
24 | #include <asm/termios.h> | |
25 | #include <linux/wakelock.h> | |
26 | #include <linux/delay.h> | |
781f598d | 27 | #include <linux/seq_file.h> |
e91a78c7 TK |
28 | |
29 | #ifdef CONFIG_ARCH_EXYNOS | |
30 | #include <linux/soc/samsung/exynos-soc.h> | |
31 | #endif | |
32 | ||
33 | #include <scsc/scsc_logring.h> | |
34 | #include <scsc/kic/slsi_kic_lib.h> | |
35 | #include <scsc/kic/slsi_kic_bt.h> | |
36 | #include <scsc/kic/slsi_kic_ant.h> | |
37 | ||
38 | #include "scsc_bt_priv.h" | |
39 | #include "../scsc/scsc_mx_impl.h" | |
40 | ||
41 | #ifdef CONFIG_SCSC_LOG_COLLECTION | |
42 | #include <scsc/scsc_log_collector.h> | |
43 | #endif | |
44 | ||
45 | #define SCSC_MODDESC "SCSC MX BT Driver" | |
46 | #define SCSC_MODAUTH "Samsung Electronics Co., Ltd" | |
47 | #define SCSC_MODVERSION "-devel" | |
48 | ||
49 | #define SLSI_BT_SERVICE_CLOSE_RETRY 60 | |
50 | #define SLSI_BT_SERVICE_STOP_RECOVERY_TIMEOUT 20000 | |
51 | #define SLSI_BT_SERVICE_STOP_RECOVERY_DISABLED_TIMEOUT 2000 | |
52 | ||
53 | #define SCSC_ANT_MAX_TIMEOUT (20*HZ) | |
54 | ||
781f598d TK |
55 | static u16 bt_module_irq_mask; |
56 | ||
e91a78c7 TK |
57 | #ifdef CONFIG_SCSC_ANT |
58 | static DECLARE_WAIT_QUEUE_HEAD(ant_recovery_complete_queue); | |
59 | #endif | |
60 | ||
61 | static DEFINE_MUTEX(bt_start_mutex); | |
62 | static DEFINE_MUTEX(bt_audio_mutex); | |
63 | #ifdef CONFIG_SCSC_ANT | |
64 | static DEFINE_MUTEX(ant_start_mutex); | |
65 | #endif | |
66 | ||
67 | static u8 bt_recovery_level; | |
68 | #ifdef CONFIG_SCSC_ANT | |
69 | static u8 ant_recovery_level; | |
70 | #endif | |
71 | ||
72 | static int recovery_timeout = SLSI_BT_SERVICE_STOP_RECOVERY_TIMEOUT; | |
73 | ||
74 | struct scsc_common_service common_service; | |
75 | struct scsc_bt_service bt_service; | |
76 | #ifdef CONFIG_SCSC_ANT | |
77 | struct scsc_ant_service ant_service; | |
78 | #endif | |
79 | ||
80 | static int service_start_count; | |
81 | #ifdef CONFIG_SCSC_ANT | |
82 | static int ant_service_start_count; | |
83 | #endif | |
84 | ||
85 | static u64 bluetooth_address; | |
86 | #ifdef CONFIG_ARCH_EXYNOS | |
87 | static char bluetooth_address_fallback[] = "00:00:00:00:00:00"; | |
88 | #endif | |
89 | static u32 bt_info_trigger; | |
90 | static u32 bt_info_interrupt; | |
91 | static u32 firmware_control; | |
92 | static bool firmware_control_reset = true; | |
93 | static u32 firmware_mxlog_filter; | |
94 | static bool disable_service; | |
95 | ||
96 | /* Audio */ | |
97 | static struct device *audio_device; | |
98 | static bool audio_device_probed; | |
99 | static struct scsc_bt_audio bt_audio; | |
100 | ||
101 | module_param(bluetooth_address, ullong, S_IRUGO | S_IWUSR); | |
102 | MODULE_PARM_DESC(bluetooth_address, | |
103 | "Bluetooth address"); | |
104 | ||
105 | #ifdef CONFIG_ARCH_EXYNOS | |
106 | module_param_string(bluetooth_address_fallback, bluetooth_address_fallback, | |
107 | sizeof(bluetooth_address_fallback), 0444); | |
108 | MODULE_PARM_DESC(bluetooth_address_fallback, | |
109 | "Bluetooth address as proposed by the driver"); | |
110 | #endif | |
111 | ||
112 | module_param(service_start_count, int, S_IRUGO); | |
113 | MODULE_PARM_DESC(service_start_count, | |
114 | "Track how many times the BT service has been started"); | |
115 | #ifdef CONFIG_SCSC_ANT | |
116 | module_param(ant_service_start_count, int, 0444); | |
117 | MODULE_PARM_DESC(ant_service_start_count, | |
118 | "Track how many times the ANT service has been started"); | |
119 | #endif | |
120 | ||
121 | module_param(firmware_control, int, S_IRUGO | S_IWUSR); | |
122 | MODULE_PARM_DESC(firmware_control, "Control how the firmware behaves"); | |
123 | ||
124 | module_param(firmware_control_reset, bool, S_IRUGO | S_IWUSR); | |
125 | MODULE_PARM_DESC(firmware_control_reset, | |
126 | "Controls the resetting of the firmware_control variable"); | |
127 | ||
128 | module_param(disable_service, bool, S_IRUGO | S_IWUSR); | |
129 | MODULE_PARM_DESC(disable_service, | |
130 | "Disables service startup"); | |
131 | ||
132 | /* | |
133 | * Service event callbacks called from mx-core when things go wrong | |
134 | */ | |
135 | static u8 bt_failure_notification(struct scsc_service_client *client, struct mx_syserr_decode *err) | |
136 | { | |
137 | UNUSED(client); | |
138 | SCSC_TAG_INFO(BT_COMMON, "Error level %d\n", err->level); | |
139 | ||
140 | return err->level; | |
141 | } | |
142 | ||
143 | static bool bt_stop_on_failure(struct scsc_service_client *client, struct mx_syserr_decode *err) | |
144 | { | |
145 | UNUSED(client); | |
146 | ||
147 | SCSC_TAG_ERR(BT_COMMON, "Error level %d\n", err->level); | |
148 | ||
149 | reinit_completion(&bt_service.recovery_probe_complete); | |
150 | bt_recovery_level = err->level; | |
151 | ||
152 | atomic_inc(&bt_service.error_count); | |
153 | ||
154 | /* Zero the shared memory on error. The A-Box does not stop using this | |
155 | * memory immediately as designed. To prevent noise during recovery we zero the | |
156 | * shared memory before freeing it | |
157 | */ | |
158 | mutex_lock(&bt_audio_mutex); | |
159 | ||
160 | if (bt_service.abox_ref != 0 && bt_audio.abox_virtual) { | |
161 | memset(bt_audio.abox_virtual->abox_to_bt_streaming_if_data, 0, SCSC_BT_AUDIO_ABOX_DATA_SIZE); | |
162 | memset(bt_audio.abox_virtual->bt_to_abox_streaming_if_data, 0, SCSC_BT_AUDIO_ABOX_DATA_SIZE); | |
163 | } | |
164 | ||
165 | mutex_unlock(&bt_audio_mutex); | |
166 | ||
167 | return false; | |
168 | } | |
169 | ||
170 | static void bt_failure_reset(struct scsc_service_client *client, u8 level, u16 scsc_syserr_code) | |
171 | { | |
172 | UNUSED(client); | |
173 | UNUSED(level); | |
174 | UNUSED(scsc_syserr_code); | |
175 | ||
176 | SCSC_TAG_ERR(BT_COMMON, "\n"); | |
177 | ||
178 | wake_up(&bt_service.read_wait); | |
179 | } | |
180 | ||
181 | #ifdef CONFIG_SCSC_ANT | |
182 | static u8 ant_failure_notification(struct scsc_service_client *client, struct mx_syserr_decode *err) | |
183 | { | |
184 | UNUSED(client); | |
185 | SCSC_TAG_INFO(BT_COMMON, "Error level %d\n", err->level); | |
186 | ||
187 | return err->level; | |
188 | } | |
189 | ||
190 | static bool ant_stop_on_failure(struct scsc_service_client *client, struct mx_syserr_decode *err) | |
191 | { | |
192 | UNUSED(client); | |
193 | ||
194 | SCSC_TAG_ERR(BT_COMMON, "\n"); | |
195 | ||
196 | reinit_completion(&ant_service.recovery_probe_complete); | |
197 | ant_recovery_level = err->level; | |
198 | ||
199 | atomic_inc(&ant_service.error_count); | |
200 | ||
201 | /* Let the ANT stack call poll() to be notified about the reset asap */ | |
202 | wake_up(&ant_service.read_wait); | |
203 | ||
204 | return false; | |
205 | } | |
206 | ||
207 | static void ant_failure_reset(struct scsc_service_client *client, u8 level, u16 scsc_syserr_code) | |
208 | { | |
209 | UNUSED(client); | |
210 | UNUSED(level); | |
211 | UNUSED(scsc_syserr_code); | |
212 | ||
213 | SCSC_TAG_ERR(BT_COMMON, "\n"); | |
214 | ||
215 | wake_up(&ant_service.read_wait); | |
216 | } | |
217 | #endif | |
218 | ||
219 | static void scsc_bt_shm_irq_handler(int irqbit, void *data) | |
220 | { | |
221 | /* Clear interrupt */ | |
222 | scsc_service_mifintrbit_bit_clear(bt_service.service, irqbit); | |
223 | ||
224 | bt_info_interrupt++; | |
225 | ||
226 | wake_up(&bt_service.info_wait); | |
227 | } | |
228 | ||
229 | static struct scsc_service_client mx_bt_client = { | |
230 | .failure_notification = bt_failure_notification, | |
231 | .stop_on_failure_v2 = bt_stop_on_failure, | |
232 | .failure_reset_v2 = bt_failure_reset, | |
233 | }; | |
234 | ||
235 | #ifdef CONFIG_SCSC_ANT | |
236 | static struct scsc_service_client mx_ant_client = { | |
237 | .failure_notification = ant_failure_notification, | |
238 | .stop_on_failure_v2 = ant_stop_on_failure, | |
239 | .failure_reset_v2 = ant_failure_reset, | |
240 | }; | |
241 | #endif | |
242 | ||
243 | static void slsi_sm_bt_service_cleanup_interrupts(void) | |
244 | { | |
781f598d | 245 | u16 irq_num = 0; |
e91a78c7 TK |
246 | |
247 | SCSC_TAG_DEBUG(BT_COMMON, | |
248 | "unregister firmware information interrupts\n"); | |
249 | ||
781f598d TK |
250 | if (bt_module_irq_mask & 1 << irq_num++) |
251 | scsc_service_mifintrbit_unregister_tohost(bt_service.service, | |
252 | bt_service.bsmhcp_protocol->header.info_bg_to_ap_int_src); | |
253 | if (bt_module_irq_mask & 1 << irq_num++) | |
254 | scsc_service_mifintrbit_free_fromhost(bt_service.service, | |
255 | bt_service.bsmhcp_protocol->header.info_ap_to_bg_int_src, | |
256 | SCSC_MIFINTR_TARGET_R4); | |
257 | } | |
258 | ||
259 | static int slsi_sm_bt_service_init_interrupts(void) { | |
260 | int irq_ret; | |
261 | u16 irq_num = 0; | |
262 | ||
263 | irq_ret = scsc_service_mifintrbit_register_tohost(bt_service.service, | |
264 | scsc_bt_shm_irq_handler, NULL); | |
265 | if (irq_ret < 0) | |
266 | return irq_ret; | |
267 | ||
268 | bt_service.bsmhcp_protocol->header.info_bg_to_ap_int_src = irq_ret; | |
269 | bt_module_irq_mask |= 1 << irq_num++; | |
270 | ||
271 | irq_ret = scsc_service_mifintrbit_alloc_fromhost(bt_service.service, | |
272 | SCSC_MIFINTR_TARGET_R4); | |
273 | if (irq_ret < 0) | |
274 | return irq_ret; | |
275 | ||
276 | bt_service.bsmhcp_protocol->header.info_ap_to_bg_int_src = irq_ret; | |
277 | bt_module_irq_mask |= 1 << irq_num++; | |
278 | ||
279 | return 0; | |
e91a78c7 TK |
280 | } |
281 | ||
282 | static int slsi_sm_bt_service_cleanup_stop_service(void) | |
283 | { | |
284 | int ret; | |
285 | ||
286 | /* Stop service first, then it's safe to release shared memory | |
287 | resources */ | |
288 | ret = scsc_mx_service_stop(bt_service.service); | |
289 | ||
290 | if (ret < 0 && ret != -EPERM) { | |
291 | SCSC_TAG_ERR(BT_COMMON, | |
292 | "scsc_mx_service_stop failed err: %d\n", ret); | |
293 | ||
294 | /* Only trigger recovery if the service_stop did not fail because recovery is already in progress */ | |
295 | if (atomic_read(&bt_service.error_count) == 0 && ret != -EILSEQ) { | |
296 | scsc_mx_service_service_failed(bt_service.service, "BT service stop failed"); | |
297 | SCSC_TAG_DEBUG(BT_COMMON, | |
298 | "force service fail complete\n"); | |
299 | ||
300 | return ret; | |
301 | } | |
302 | } | |
303 | ||
304 | return 0; | |
305 | } | |
306 | ||
307 | static int slsi_bt_audio_probe(void) | |
308 | { | |
309 | phys_addr_t paddr; | |
310 | size_t size; | |
311 | ||
312 | if (audio_device == NULL || bt_audio.dev_iommu_map == NULL) { | |
313 | SCSC_TAG_ERR(BT_COMMON, "failed audio_device %p bt_audio.dev_iommu_map %p\n", | |
314 | audio_device, bt_audio.dev_iommu_map); | |
315 | return -EFAULT; | |
316 | } | |
317 | ||
318 | paddr = (phys_addr_t)bt_audio.abox_physical; | |
319 | size = PAGE_ALIGN(sizeof(*bt_audio.abox_physical)); | |
320 | ||
321 | SCSC_TAG_DEBUG(BT_COMMON, "paddr %p size %zu\n", paddr, size); | |
322 | ||
323 | return bt_audio.dev_iommu_map(audio_device, paddr, size); | |
324 | } | |
325 | ||
326 | /* Note A-Box memory should only be unmapped when A-Box driver is finished with it */ | |
327 | static void slsi_bt_audio_remove(void) | |
328 | { | |
329 | size_t size; | |
330 | ||
331 | if (audio_device == NULL || bt_audio.dev_iommu_unmap == NULL || bt_audio.abox_physical == NULL) | |
332 | return; | |
333 | ||
334 | size = PAGE_ALIGN(sizeof(*bt_audio.abox_physical)); | |
335 | bt_audio.dev_iommu_unmap(audio_device, size); | |
336 | } | |
337 | ||
338 | #ifdef CONFIG_SCSC_LOG_COLLECTION | |
339 | static int bt_hcf_collect(struct scsc_log_collector_client *collect_client, size_t size) | |
340 | { | |
341 | struct scsc_bt_hcf_collection *hcf_collect = (struct scsc_bt_hcf_collection *) collect_client->prv; | |
342 | int ret = 0; | |
343 | ||
344 | if (hcf_collect == NULL) | |
345 | return ret; | |
346 | ||
347 | SCSC_TAG_DEBUG(BT_COMMON, "Collecting BT config file\n"); | |
348 | ret = scsc_log_collector_write(hcf_collect->hcf, hcf_collect->hcf_size, 1); | |
349 | ||
350 | return ret; | |
351 | } | |
352 | ||
353 | struct scsc_log_collector_client bt_collect_hcf_client = { | |
354 | .name = "bt_hcf", | |
355 | .type = SCSC_LOG_CHUNK_BT_HCF, | |
356 | .collect_init = NULL, | |
357 | .collect = bt_hcf_collect, | |
358 | .collect_end = NULL, | |
359 | .prv = NULL, | |
360 | }; | |
361 | #endif | |
362 | ||
363 | static int slsi_sm_bt_service_cleanup(bool force_cleanup) | |
364 | { | |
365 | int ret = 0; | |
366 | ||
367 | SCSC_TAG_DEBUG(BT_COMMON, "enter\n"); | |
368 | ||
369 | if (NULL != bt_service.service) { | |
370 | SCSC_TAG_DEBUG(BT_COMMON, "stopping debugging thread (service=%p)\n", bt_service.service); | |
371 | ||
372 | /* If slsi_sm_bt_service_cleanup_stop_service fails, then let | |
373 | recovery do the rest of the deinit later. */ | |
374 | if (bt_service.service_started) { | |
375 | ret = slsi_sm_bt_service_cleanup_stop_service(); | |
376 | bt_service.service_started = false; | |
377 | ||
378 | if (ret < 0 && !force_cleanup) { | |
379 | SCSC_TAG_DEBUG(BT_COMMON, "service stop failed. Recovery has been triggered\n"); | |
380 | goto done_error; | |
381 | } | |
382 | } | |
383 | ||
384 | /* Service is stopped - ensure polling function is existed */ | |
385 | SCSC_TAG_DEBUG(BT_COMMON, "wake reader/poller thread\n"); | |
386 | wake_up_interruptible(&bt_service.read_wait); | |
387 | ||
388 | /* Unregister firmware information interrupts */ | |
781f598d | 389 | if (bt_service.bsmhcp_protocol) { |
e91a78c7 | 390 | slsi_sm_bt_service_cleanup_interrupts(); |
781f598d TK |
391 | bt_module_irq_mask = 0; |
392 | } | |
e91a78c7 TK |
393 | |
394 | /* Shut down the shared memory interface */ | |
395 | SCSC_TAG_DEBUG(BT_COMMON, | |
396 | "cleanup protocol structure and main interrupts\n"); | |
397 | scsc_bt_shm_exit(); | |
398 | ||
399 | /* Cleanup AVDTP detections */ | |
400 | SCSC_TAG_DEBUG(BT_COMMON, | |
401 | "cleanup ongoing avdtp detections\n"); | |
402 | scsc_avdtp_detect_exit(); | |
403 | ||
404 | mutex_lock(&bt_audio_mutex); | |
405 | if (audio_device) { | |
406 | bt_audio.dev = NULL; | |
407 | bt_audio.abox_virtual = NULL; | |
408 | bt_audio.abox_physical = NULL; | |
409 | } | |
410 | mutex_unlock(&bt_audio_mutex); | |
411 | ||
412 | #ifdef CONFIG_SCSC_LOG_COLLECTION | |
413 | /* Deinit HCF log collection */ | |
414 | scsc_log_collector_unregister_client(&bt_collect_hcf_client); | |
415 | bt_collect_hcf_client.prv = NULL; | |
416 | ||
417 | if (bt_service.hcf_collection.hcf) { | |
418 | /* Reset HCF pointer - memory will be freed later */ | |
419 | bt_service.hcf_collection.hcf_size = 0; | |
420 | bt_service.hcf_collection.hcf = NULL; | |
421 | } | |
422 | #endif | |
423 | ||
424 | /* Release the shared memory */ | |
425 | SCSC_TAG_DEBUG(BT_COMMON, | |
426 | "free memory allocated in the shared DRAM pool\n"); | |
427 | if (bt_service.config_ref != 0) { | |
428 | scsc_mx_service_mifram_free(bt_service.service, | |
429 | bt_service.config_ref); | |
430 | bt_service.config_ref = 0; | |
431 | } | |
432 | if (bt_service.bsmhcp_ref != 0) { | |
433 | scsc_mx_service_mifram_free(bt_service.service, | |
434 | bt_service.bsmhcp_ref); | |
435 | bt_service.bsmhcp_ref = 0; | |
436 | } | |
437 | if (bt_service.bhcs_ref != 0) { | |
438 | scsc_mx_service_mifram_free(bt_service.service, | |
439 | bt_service.bhcs_ref); | |
440 | bt_service.bhcs_ref = 0; | |
441 | } | |
442 | ||
443 | SCSC_TAG_DEBUG(BT_COMMON, "closing service...\n"); | |
444 | ||
445 | ret = scsc_mx_service_close(bt_service.service); | |
446 | ||
447 | if (ret < 0 && ret != -EPERM) { | |
448 | int retry_counter; | |
449 | ||
450 | SCSC_TAG_DEBUG(BT_COMMON, | |
451 | "scsc_mx_service_close failed\n"); | |
452 | ||
453 | /** | |
454 | * Error handling in progress - try and close again | |
455 | * later. The service close call shall remain blocked | |
456 | * until close service is successful. Will try up to | |
457 | * 30 seconds. | |
458 | */ | |
459 | for (retry_counter = 0; retry_counter < SLSI_BT_SERVICE_CLOSE_RETRY; retry_counter++) { | |
460 | msleep(500); | |
461 | ||
462 | ret = scsc_mx_service_close(bt_service.service); | |
463 | ||
464 | if (ret == 0) { | |
465 | SCSC_TAG_DEBUG(BT_COMMON, | |
466 | "scsc_mx_service_close closed after %d attempts\n", | |
467 | retry_counter + 1); | |
468 | break; | |
469 | } | |
470 | } | |
471 | ||
472 | if (retry_counter + 1 == SLSI_BT_SERVICE_CLOSE_RETRY) | |
473 | SCSC_TAG_ERR(BT_COMMON, "scsc_mx_service_close failed %d times\n", | |
474 | SLSI_BT_SERVICE_CLOSE_RETRY); | |
475 | } | |
476 | bt_service.service = NULL; | |
477 | ||
478 | SCSC_TAG_DEBUG(BT_COMMON, | |
479 | "notify the KIC subsystem of the shutdown\n"); | |
480 | slsi_kic_system_event( | |
481 | slsi_kic_system_event_category_deinitialisation, | |
482 | slsi_kic_system_events_bt_off, | |
483 | 0); | |
484 | } | |
485 | ||
486 | atomic_set(&bt_service.error_count, 0); | |
487 | ||
488 | /* Release write wake lock if held */ | |
489 | if (wake_lock_active(&bt_service.write_wake_lock)) { | |
490 | bt_service.write_wake_unlock_count++; | |
491 | wake_unlock(&bt_service.write_wake_lock); | |
492 | } | |
493 | ||
494 | SCSC_TAG_DEBUG(BT_COMMON, "complete\n"); | |
495 | return 0; | |
496 | ||
497 | done_error: | |
498 | return -EIO; | |
499 | } | |
500 | ||
501 | #ifdef CONFIG_SCSC_ANT | |
502 | static int slsi_sm_ant_service_cleanup_stop_service(void) | |
503 | { | |
504 | int ret; | |
505 | ||
506 | /* Stop service first, then it's safe to release shared memory | |
507 | * resources | |
508 | */ | |
509 | ret = scsc_mx_service_stop(ant_service.service); | |
510 | if (ret < 0 && ret != -EPERM) { | |
511 | SCSC_TAG_ERR(BT_COMMON, | |
512 | "scsc_mx_service_stop failed err: %d\n", ret); | |
513 | if (atomic_read(&ant_service.error_count) == 0 && ret != -EILSEQ) { | |
514 | scsc_mx_service_service_failed(ant_service.service, "ANT service stop failed"); | |
515 | SCSC_TAG_DEBUG(BT_COMMON, "force service fail complete\n"); | |
516 | return ret; | |
517 | } | |
518 | } | |
519 | ||
520 | return 0; | |
521 | } | |
522 | #endif | |
523 | ||
524 | #ifdef CONFIG_SCSC_ANT | |
525 | static int slsi_sm_ant_service_cleanup(bool force_cleanup) | |
526 | { | |
527 | int ret = 0; | |
528 | ||
529 | SCSC_TAG_DEBUG(BT_COMMON, "enter\n"); | |
530 | ||
531 | if (ant_service.service != NULL) { | |
532 | SCSC_TAG_DEBUG(BT_COMMON, "stopping debugging thread\n"); | |
533 | ||
534 | /* If slsi_sm_ant_service_cleanup_stop_service fails, then let | |
535 | * recovery do the rest of the deinit later. | |
536 | **/ | |
537 | if (ant_service.service_started) | |
538 | ret = slsi_sm_ant_service_cleanup_stop_service(); | |
539 | ant_service.service_started = false; | |
540 | ||
541 | if (ret < 0 && !force_cleanup) { | |
542 | SCSC_TAG_DEBUG(BT_COMMON, "service stop failed. Recovery has been triggered\n"); | |
543 | goto done_error; | |
544 | } | |
545 | ||
546 | /* Service is stopped - ensure polling function is existed */ | |
547 | SCSC_TAG_DEBUG(BT_COMMON, "wake reader/poller thread\n"); | |
548 | wake_up_interruptible(&ant_service.read_wait); | |
549 | ||
550 | /* Shut down the shared memory interface */ | |
551 | SCSC_TAG_DEBUG(BT_COMMON, | |
552 | "cleanup protocol structure and main interrupts\n"); | |
553 | scsc_ant_shm_exit(); | |
554 | ||
555 | /* Release the shared memory */ | |
556 | SCSC_TAG_DEBUG(BT_COMMON, | |
557 | "free memory allocated in the shared DRAM pool\n"); | |
558 | if (ant_service.config_ref != 0) { | |
559 | scsc_mx_service_mifram_free(ant_service.service, | |
560 | ant_service.config_ref); | |
561 | ant_service.config_ref = 0; | |
562 | } | |
563 | if (ant_service.asmhcp_ref != 0) { | |
564 | scsc_mx_service_mifram_free(ant_service.service, | |
565 | ant_service.asmhcp_ref); | |
566 | ant_service.asmhcp_ref = 0; | |
567 | } | |
568 | if (ant_service.bhcs_ref != 0) { | |
569 | scsc_mx_service_mifram_free(ant_service.service, | |
570 | ant_service.bhcs_ref); | |
571 | ant_service.bhcs_ref = 0; | |
572 | } | |
573 | ||
574 | SCSC_TAG_DEBUG(BT_COMMON, "closing ant service...\n"); | |
575 | ||
576 | ret = scsc_mx_service_close(ant_service.service); | |
577 | ||
578 | if (ret < 0 && ret != -EPERM) { | |
579 | int retry_counter; | |
580 | ||
581 | SCSC_TAG_DEBUG(BT_COMMON, | |
582 | "scsc_mx_service_close failed\n"); | |
583 | ||
584 | /** | |
585 | * Error handling in progress - try and close again | |
586 | * later. The service close call shall remain blocked | |
587 | * until close service is successful. Will try up to | |
588 | * 30 seconds. | |
589 | */ | |
590 | for (retry_counter = 0; | |
591 | retry_counter < SLSI_BT_SERVICE_CLOSE_RETRY; | |
592 | retry_counter++) { | |
593 | msleep(500); | |
594 | ret = scsc_mx_service_close(ant_service.service); | |
595 | if (ret == 0) { | |
596 | SCSC_TAG_DEBUG(BT_COMMON, | |
597 | "scsc_mx_service_close closed after %d attempts\n", | |
598 | retry_counter + 1); | |
599 | break; | |
600 | } | |
601 | } | |
602 | ||
603 | if (retry_counter + 1 == SLSI_BT_SERVICE_CLOSE_RETRY) | |
604 | SCSC_TAG_ERR(BT_COMMON, | |
605 | "scsc_mx_service_close failed %d times\n", | |
606 | SLSI_BT_SERVICE_CLOSE_RETRY); | |
607 | } | |
608 | ant_service.service = NULL; | |
609 | ||
610 | SCSC_TAG_DEBUG(BT_COMMON, | |
611 | "notify the KIC subsystem of the shutdown\n"); | |
612 | slsi_kic_system_event( | |
613 | slsi_kic_system_event_category_deinitialisation, | |
614 | slsi_kic_system_events_ant_off, | |
615 | 0); | |
616 | } | |
617 | ||
618 | atomic_set(&ant_service.error_count, 0); | |
619 | ||
620 | SCSC_TAG_DEBUG(BT_COMMON, "complete\n"); | |
621 | return 0; | |
622 | ||
623 | done_error: | |
624 | return -EIO; | |
625 | } | |
626 | #endif | |
627 | ||
628 | static int setup_bhcs(struct scsc_service *service, | |
629 | struct BHCS *bhcs, | |
630 | uint32_t protocol_ref, | |
631 | uint32_t protocol_length, | |
632 | scsc_mifram_ref *config_ref, | |
633 | scsc_mifram_ref *bhcs_ref) | |
634 | { | |
635 | int err = 0; | |
636 | unsigned char *conf_ptr; | |
637 | const struct firmware *firm = NULL; | |
60f02aba | 638 | struct device_node *chosen_node = NULL; //IKKANE-6 |
e91a78c7 TK |
639 | /* Fill the configuration information */ |
640 | bhcs->version = BHCS_VERSION; | |
641 | bhcs->bsmhcp_protocol_offset = protocol_ref; | |
642 | bhcs->bsmhcp_protocol_length = protocol_length; | |
643 | bhcs->configuration_offset = 0; | |
644 | bhcs->configuration_length = 0; | |
645 | bhcs->bluetooth_address_lap = 0; | |
646 | bhcs->bluetooth_address_uap = 0; | |
647 | bhcs->bluetooth_address_nap = 0; | |
648 | ||
649 | /* Request the configuration file */ | |
650 | SCSC_TAG_DEBUG(BT_COMMON, | |
651 | "loading configuration: " SCSC_BT_CONF "\n"); | |
652 | err = mx140_file_request_conf(common_service.maxwell_core, | |
653 | &firm, "bluetooth", SCSC_BT_CONF); | |
654 | if (err) { | |
655 | /* Not found - just silently ignore this */ | |
656 | SCSC_TAG_DEBUG(BT_COMMON, "configuration not found\n"); | |
657 | *config_ref = 0; | |
658 | } else if (firm && firm->size) { | |
659 | SCSC_TAG_DEBUG(BT_COMMON, | |
660 | "configuration size = %zu\n", firm->size); | |
661 | ||
662 | /* Allocate a region for the data */ | |
663 | err = scsc_mx_service_mifram_alloc(service, | |
664 | firm->size, | |
665 | config_ref, | |
666 | BSMHCP_ALIGNMENT); | |
667 | if (err) { | |
668 | SCSC_TAG_WARNING(BT_COMMON, "mifram alloc failed\n"); | |
669 | mx140_file_release_conf(common_service.maxwell_core, firm); | |
670 | return -EINVAL; | |
671 | } | |
672 | ||
673 | /* Map the region to a memory pointer */ | |
674 | conf_ptr = scsc_mx_service_mif_addr_to_ptr(service, | |
675 | *config_ref); | |
676 | if (conf_ptr == NULL) { | |
677 | SCSC_TAG_ERR(BT_COMMON, | |
678 | "couldn't map kmem to bhcs_ref 0x%08x\n", | |
679 | (u32)*bhcs_ref); | |
680 | mx140_file_release_conf(common_service.maxwell_core, firm); | |
681 | return -EINVAL; | |
682 | } | |
683 | ||
684 | /* Copy the configuration data to the shared memory area */ | |
685 | memcpy(conf_ptr, firm->data, firm->size); | |
686 | bhcs->configuration_offset = *config_ref; | |
687 | bhcs->configuration_length = firm->size; | |
688 | ||
689 | /* Relase the configuration information */ | |
690 | mx140_file_release_conf(common_service.maxwell_core, firm); | |
691 | firm = NULL; | |
692 | } else { | |
693 | /* Empty configuration - just silently ignore this */ | |
694 | SCSC_TAG_DEBUG(BT_COMMON, "empty configuration\n"); | |
695 | *config_ref = 0; | |
696 | ||
697 | /* Relase the configuration information */ | |
698 | mx140_file_release_conf(common_service.maxwell_core, firm); | |
699 | firm = NULL; | |
700 | } | |
701 | ||
702 | #ifdef CONFIG_ARCH_EXYNOS | |
703 | bhcs->bluetooth_address_nap = | |
704 | (exynos_soc_info.unique_id & 0x000000FFFF00) >> 8; | |
705 | bhcs->bluetooth_address_uap = | |
706 | (exynos_soc_info.unique_id & 0x0000000000FF); | |
707 | bhcs->bluetooth_address_lap = | |
708 | (exynos_soc_info.unique_id & 0xFFFFFF000000) >> 24; | |
709 | #endif | |
710 | ||
711 | if (bluetooth_address) { | |
712 | SCSC_TAG_INFO(BT_COMMON, | |
713 | "using stack supplied Bluetooth address\n"); | |
714 | bhcs->bluetooth_address_nap = | |
715 | (bluetooth_address & 0xFFFF00000000) >> 32; | |
716 | bhcs->bluetooth_address_uap = | |
717 | (bluetooth_address & 0x0000FF000000) >> 24; | |
718 | bhcs->bluetooth_address_lap = | |
719 | (bluetooth_address & 0x000000FFFFFF); | |
720 | } | |
721 | ||
722 | #ifdef SCSC_BT_ADDR | |
723 | /* Request the Bluetooth address file */ | |
724 | SCSC_TAG_DEBUG(BT_COMMON, | |
725 | "loading Bluetooth address configuration file: " | |
726 | SCSC_BT_ADDR "\n"); | |
727 | err = mx140_request_file(common_service.maxwell_core, SCSC_BT_ADDR, &firm); | |
728 | if (err) { | |
729 | /* Not found - just silently ignore this */ | |
730 | SCSC_TAG_DEBUG(BT_COMMON, "Bluetooth address not found\n"); | |
731 | } else if (firm && firm->size) { | |
732 | u32 u[SCSC_BT_ADDR_LEN]; | |
733 | ||
734 | #ifdef CONFIG_SCSC_BT_BLUEZ | |
735 | /* Convert the data into a native format */ | |
736 | if (sscanf(firm->data, "%04x %02X %06x", | |
737 | &u[0], &u[1], &u[2]) | |
738 | == SCSC_BT_ADDR_LEN) { | |
739 | bhcs->bluetooth_address_lap = u[2]; | |
740 | bhcs->bluetooth_address_uap = u[1]; | |
741 | bhcs->bluetooth_address_nap = u[0]; | |
742 | } else | |
743 | SCSC_TAG_WARNING(BT_COMMON, | |
744 | "data size incorrect = %zu\n", firm->size); | |
745 | #else | |
746 | /* Convert the data into a native format */ | |
747 | if (sscanf(firm->data, "%02X:%02X:%02X:%02X:%02X:%02X", | |
748 | &u[0], &u[1], &u[2], &u[3], &u[4], &u[5]) | |
749 | == SCSC_BT_ADDR_LEN) { | |
750 | bhcs->bluetooth_address_lap = | |
751 | (u[3] << 16) | (u[4] << 8) | u[5]; | |
752 | bhcs->bluetooth_address_uap = u[2]; | |
753 | bhcs->bluetooth_address_nap = (u[0] << 8) | u[1]; | |
754 | } else | |
755 | SCSC_TAG_WARNING(BT_COMMON, | |
756 | "data size incorrect = %zu\n", firm->size); | |
757 | #endif | |
758 | /* Relase the configuration information */ | |
759 | mx140_release_file(common_service.maxwell_core, firm); | |
760 | firm = NULL; | |
761 | } else { | |
762 | SCSC_TAG_DEBUG(BT_COMMON, "empty Bluetooth address\n"); | |
763 | mx140_release_file(common_service.maxwell_core, firm); | |
764 | firm = NULL; | |
765 | } | |
766 | #endif | |
767 | ||
60f02aba | 768 | //BEGIN IKKANE-6 |
769 | #ifdef MOTO_UTAGS_MAC | |
770 | //Moto, read MACs from bootparams | |
771 | chosen_node = of_find_node_by_name(NULL, "chosen"); | |
772 | if (!chosen_node) { | |
773 | SCSC_TAG_ERR(BT_COMMON, "%s: get chosen node read failed\n", __func__); | |
774 | } else { | |
775 | int len=0; | |
776 | const char *cmd_line = NULL; | |
777 | cmd_line = of_get_property(chosen_node, "bootargs", &len); | |
778 | if (!cmd_line || len <= 0) { | |
779 | SCSC_TAG_ERR(BT_COMMON, "%s: get bt MACs bootargs failed\n", __func__); | |
780 | } else { | |
781 | char * mac_idx = NULL; | |
782 | mac_idx = strstr(cmd_line, BT_MAC_BOOTARG); | |
783 | if (mac_idx == NULL) { | |
784 | SCSC_TAG_ERR(BT_COMMON, "%s: " BT_MAC_BOOTARG " not present in bootargs", __func__); | |
785 | } else { | |
786 | char macStr[MACSTRLEN+1] = {0}; | |
787 | u32 u[SCSC_BT_ADDR_LEN] = {0}; | |
788 | // extract MAC from boot params | |
cd3de2d8 | 789 | mac_idx += strlen(BT_MAC_BOOTARG); |
60f02aba | 790 | memcpy(macStr, mac_idx, MACSTRLEN); |
791 | sscanf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", | |
cd3de2d8 | 792 | &u[0], &u[1], &u[2], &u[3], &u[4], &u[5]); |
60f02aba | 793 | bhcs->bluetooth_address_lap = |
794 | (u[3] << 16) | (u[4] << 8) | u[5]; | |
795 | bhcs->bluetooth_address_uap = u[2]; | |
796 | bhcs->bluetooth_address_nap = (u[0] << 8) | u[1]; | |
797 | SCSC_TAG_ERR(BT_COMMON,, "BT MAC address loaded from utag: %02X:%02X:%02X:%02X:%02X:%02X\n", | |
798 | u[0], u[1], u[2], u[3], u[4], u[5]); | |
799 | } | |
800 | } | |
801 | } | |
802 | #endif | |
803 | //END IKKANE-6 | |
804 | ||
e91a78c7 TK |
805 | #ifdef CONFIG_SCSC_DEBUG |
806 | SCSC_TAG_DEBUG(BT_COMMON, "Bluetooth address: %04X:%02X:%06X\n", | |
807 | bhcs->bluetooth_address_nap, | |
808 | bhcs->bluetooth_address_uap, | |
809 | bhcs->bluetooth_address_lap); | |
810 | ||
811 | /* Always print Bluetooth Address in Kernel log */ | |
812 | printk(KERN_INFO "Bluetooth address: %04X:%02X:%06X\n", | |
813 | bhcs->bluetooth_address_nap, | |
814 | bhcs->bluetooth_address_uap, | |
815 | bhcs->bluetooth_address_lap); | |
816 | #endif /* CONFIG_SCSC_DEBUG */ | |
817 | ||
818 | return err; | |
819 | } | |
820 | ||
821 | /* Start the BT service */ | |
822 | int slsi_sm_bt_service_start(void) | |
823 | { | |
824 | int err = 0; | |
825 | struct BHCS *bhcs; | |
826 | ||
827 | ++service_start_count; | |
828 | ||
829 | /* Lock the start/stop procedures to handle multiple application | |
830 | * starting the sercice | |
831 | */ | |
832 | mutex_lock(&bt_start_mutex); | |
833 | ||
834 | if (disable_service) { | |
835 | SCSC_TAG_WARNING(BT_COMMON, "service disabled\n"); | |
836 | mutex_unlock(&bt_start_mutex); | |
837 | return -EBUSY; | |
838 | } | |
839 | ||
840 | /* Has probe been called */ | |
841 | if (bt_recovery_level != 0) { | |
842 | SCSC_TAG_WARNING(BT_COMMON, "recovery in progress\n"); | |
843 | mutex_unlock(&bt_start_mutex); | |
844 | return -EFAULT; | |
845 | } | |
846 | ||
847 | /* Has probe been called */ | |
848 | if (common_service.maxwell_core == NULL) { | |
849 | SCSC_TAG_WARNING(BT_COMMON, "service probe not arrived\n"); | |
850 | mutex_unlock(&bt_start_mutex); | |
851 | return -EFAULT; | |
852 | } | |
853 | ||
854 | /* Is this the first service to enter */ | |
855 | if (atomic_inc_return(&bt_service.service_users) > 1) { | |
856 | SCSC_TAG_WARNING(BT_COMMON, "service already opened\n"); | |
857 | ||
858 | if (!bt_service.service_started) { | |
859 | SCSC_TAG_DEBUG(BT_COMMON, "service not started, returning error\n"); | |
860 | err = -EFAULT; | |
861 | atomic_dec(&bt_service.service_users); | |
862 | } | |
863 | ||
864 | mutex_unlock(&bt_start_mutex); | |
865 | return err; | |
866 | } | |
867 | ||
868 | /* Open service - will download FW - will set MBOX0 with Starting | |
869 | * address | |
870 | */ | |
871 | SCSC_TAG_DEBUG(BT_COMMON, | |
872 | "open Bluetooth service id %d opened %d times\n", | |
873 | SCSC_SERVICE_ID_BT, service_start_count); | |
874 | wake_lock(&bt_service.service_wake_lock); | |
875 | bt_service.service = scsc_mx_service_open(common_service.maxwell_core, | |
876 | SCSC_SERVICE_ID_BT, | |
877 | &mx_bt_client, | |
878 | &err); | |
879 | if (!bt_service.service) { | |
880 | SCSC_TAG_WARNING(BT_COMMON, "service open failed %d\n", err); | |
881 | atomic_dec(&bt_service.service_users); | |
882 | wake_unlock(&bt_service.service_wake_lock); | |
883 | mutex_unlock(&bt_start_mutex); | |
884 | return -EINVAL; | |
885 | } | |
886 | ||
887 | /* Shorter completion timeout if autorecovery is disabled, as it will | |
888 | * never be signalled. | |
889 | */ | |
890 | if (mxman_recovery_disabled()) | |
891 | recovery_timeout = SLSI_BT_SERVICE_STOP_RECOVERY_DISABLED_TIMEOUT; | |
892 | else | |
893 | recovery_timeout = SLSI_BT_SERVICE_STOP_RECOVERY_TIMEOUT; | |
894 | ||
895 | /* Get shared memory region for the configuration structure from | |
896 | * the MIF | |
897 | */ | |
898 | SCSC_TAG_DEBUG(BT_COMMON, "allocate mifram regions\n"); | |
899 | err = scsc_mx_service_mifram_alloc(bt_service.service, | |
900 | sizeof(struct BHCS), | |
901 | &bt_service.bhcs_ref, | |
902 | BSMHCP_ALIGNMENT); | |
903 | if (err) { | |
904 | SCSC_TAG_WARNING(BT_COMMON, "mifram alloc failed\n"); | |
905 | err = -EINVAL; | |
906 | goto exit; | |
907 | } | |
908 | ||
909 | /* Get shared memory region for the protocol structure from the MIF */ | |
910 | err = scsc_mx_service_mifram_alloc(bt_service.service, | |
911 | sizeof(struct BSMHCP_PROTOCOL), | |
912 | &bt_service.bsmhcp_ref, | |
913 | BSMHCP_ALIGNMENT); | |
914 | if (err) { | |
915 | SCSC_TAG_WARNING(BT_COMMON, "mifram alloc failed\n"); | |
916 | err = -EINVAL; | |
917 | goto exit; | |
918 | } | |
919 | ||
920 | /* The A-Box driver must have registered before reaching this point | |
921 | * otherwise there is no audio routing | |
922 | */ | |
923 | if (audio_device != NULL) { | |
924 | /* Get shared memory region for the A-Box structure from the MIF. | |
925 | * The allocated memory is aligned to 4kB, but this is going to work | |
926 | * only if the physical start address of the 4MB region is aligned | |
927 | * to 4kB (which maybe will be always the case). | |
928 | */ | |
929 | ||
930 | /* On 9610, do not unmap previously mapped memory from IOMMU. | |
931 | * It may still be used by A-Box. | |
932 | */ | |
933 | ||
934 | err = scsc_mx_service_mif_ptr_to_addr(bt_service.service, | |
935 | scsc_mx_service_get_bt_audio_abox(bt_service.service), | |
936 | &bt_service.abox_ref); | |
937 | if (err) { | |
938 | SCSC_TAG_WARNING(BT_COMMON, "scsc_mx_service_mif_ptr_to_addr failed\n"); | |
939 | err = -EINVAL; | |
940 | goto exit; | |
941 | } | |
942 | /* irrespective of the technical definition of probe - wrt to memory allocation it has been */ | |
943 | ||
944 | bt_audio.abox_virtual = (struct scsc_bt_audio_abox *) | |
945 | scsc_mx_service_mif_addr_to_ptr( | |
946 | bt_service.service, | |
947 | bt_service.abox_ref); | |
948 | ||
949 | memset(bt_audio.abox_virtual, 0, sizeof(struct scsc_bt_audio_abox)); | |
950 | ||
951 | bt_audio.abox_virtual->magic_value = SCSC_BT_AUDIO_ABOX_MAGIC_VALUE; | |
952 | bt_audio.abox_virtual->version_major = SCSC_BT_AUDIO_ABOX_VERSION_MAJOR; | |
953 | bt_audio.abox_virtual->version_minor = SCSC_BT_AUDIO_ABOX_VERSION_MINOR; | |
954 | bt_audio.abox_virtual->abox_to_bt_streaming_if_0_size = SCSC_BT_AUDIO_ABOX_IF_0_SIZE; | |
955 | bt_audio.abox_virtual->bt_to_abox_streaming_if_0_size = SCSC_BT_AUDIO_ABOX_IF_0_SIZE; | |
956 | bt_audio.abox_virtual->abox_to_bt_streaming_if_1_size = SCSC_BT_AUDIO_ABOX_IF_1_SIZE; | |
957 | bt_audio.abox_virtual->abox_to_bt_streaming_if_1_offset = SCSC_BT_AUDIO_ABOX_IF_0_SIZE; | |
958 | bt_audio.abox_virtual->bt_to_abox_streaming_if_1_size = SCSC_BT_AUDIO_ABOX_IF_1_SIZE; | |
959 | bt_audio.abox_virtual->bt_to_abox_streaming_if_1_offset = SCSC_BT_AUDIO_ABOX_IF_0_SIZE; | |
960 | ||
961 | /* Resolve the physical address of the structure */ | |
962 | bt_audio.abox_physical = (struct scsc_bt_audio_abox *)scsc_mx_service_mif_addr_to_phys( | |
963 | bt_service.service, | |
964 | bt_service.abox_ref); | |
965 | ||
966 | ||
967 | bt_audio.dev = bt_service.dev; | |
968 | } | |
969 | ||
970 | /* Map the configuration pointer */ | |
971 | bhcs = (struct BHCS *) scsc_mx_service_mif_addr_to_ptr( | |
972 | bt_service.service, | |
973 | bt_service.bhcs_ref); | |
974 | if (bhcs == NULL) { | |
975 | SCSC_TAG_ERR(BT_COMMON, | |
976 | "couldn't map kmem to bhcs_ref 0x%08x\n", | |
977 | (u32)bt_service.bhcs_ref); | |
978 | err = -ENOMEM; | |
979 | goto exit; | |
980 | } | |
981 | ||
982 | SCSC_TAG_INFO(BT_COMMON, | |
983 | "regions (bhcs_ref=0x%08x, bsmhcp_ref=0x%08x, config_ref=0x%08x, abox_ref=0x%08x)\n", | |
984 | bt_service.bhcs_ref, | |
985 | bt_service.bsmhcp_ref, | |
986 | bt_service.config_ref, | |
987 | bt_service.abox_ref); | |
988 | SCSC_TAG_INFO(BT_COMMON, "version=%u\n", BHCS_VERSION); | |
989 | ||
990 | err = setup_bhcs(bt_service.service, | |
991 | bhcs, | |
992 | bt_service.bsmhcp_ref, | |
993 | sizeof(struct BSMHCP_PROTOCOL), | |
994 | &bt_service.config_ref, | |
995 | &bt_service.bhcs_ref); | |
996 | ||
997 | #ifdef CONFIG_SCSC_LOG_COLLECTION | |
998 | /* Save the binary BT config ref and register for | |
999 | * log collector to collect the hcf file | |
1000 | */ | |
1001 | if (bhcs->configuration_length > 0) { | |
1002 | bt_service.hcf_collection.hcf = | |
1003 | scsc_mx_service_mif_addr_to_ptr(bt_service.service, | |
1004 | bt_service.config_ref); | |
1005 | bt_service.hcf_collection.hcf_size = bhcs->configuration_length; | |
1006 | bt_collect_hcf_client.prv = &bt_service.hcf_collection; | |
1007 | scsc_log_collector_register_client(&bt_collect_hcf_client); | |
1008 | } | |
1009 | #endif | |
1010 | ||
1011 | if (err == -EINVAL) | |
1012 | goto exit; | |
1013 | ||
1014 | /* Initialise the shared-memory interface */ | |
1015 | err = scsc_bt_shm_init(); | |
1016 | if (err) { | |
1017 | SCSC_TAG_ERR(BT_COMMON, "scsc_bt_shm_init err %d\n", err); | |
1018 | err = -EINVAL; | |
1019 | goto exit; | |
1020 | } | |
1021 | ||
781f598d TK |
1022 | err = slsi_sm_bt_service_init_interrupts(); |
1023 | if (err < 0) | |
1024 | goto exit; | |
1025 | ||
e91a78c7 TK |
1026 | bt_service.bsmhcp_protocol->header.mxlog_filter = firmware_mxlog_filter; |
1027 | bt_service.bsmhcp_protocol->header.firmware_control = firmware_control; | |
1028 | bt_service.bsmhcp_protocol->header.abox_offset = bt_service.abox_ref; | |
1029 | bt_service.bsmhcp_protocol->header.abox_length = sizeof(struct scsc_bt_audio_abox); | |
1030 | ||
1031 | SCSC_TAG_DEBUG(BT_COMMON, | |
1032 | "firmware_control=0x%08x, firmware_control_reset=%u\n", | |
1033 | firmware_control, firmware_control_reset); | |
1034 | ||
1035 | if (firmware_control_reset) | |
1036 | firmware_control = 0; | |
1037 | ||
1038 | /* Start service last - after setting up shared memory resources */ | |
1039 | SCSC_TAG_DEBUG(BT_COMMON, "starting Bluetooth service\n"); | |
1040 | err = scsc_mx_service_start(bt_service.service, bt_service.bhcs_ref); | |
1041 | if (err < 0) { | |
1042 | SCSC_TAG_ERR(BT_COMMON, "scsc_mx_service_start err %d\n", err); | |
1043 | err = -EINVAL; | |
1044 | } else { | |
1045 | SCSC_TAG_DEBUG(BT_COMMON, "Bluetooth service running\n"); | |
1046 | bt_service.service_started = true; | |
1047 | slsi_kic_system_event( | |
1048 | slsi_kic_system_event_category_initialisation, | |
1049 | slsi_kic_system_events_bt_on, 0); | |
1050 | ||
1051 | mutex_lock(&bt_audio_mutex); | |
1052 | if (audio_device && !audio_device_probed) { | |
1053 | err = slsi_bt_audio_probe(); | |
1054 | ||
1055 | audio_device_probed = true; | |
1056 | } | |
1057 | mutex_unlock(&bt_audio_mutex); | |
1058 | } | |
1059 | ||
1060 | if (bt_service.bsmhcp_protocol->header.firmware_features & | |
1061 | BSMHCP_FEATURE_M4_INTERRUPTS) | |
1062 | SCSC_TAG_DEBUG(BT_COMMON, "features enabled: M4_INTERRUPTS\n"); | |
1063 | ||
1064 | exit: | |
1065 | if (err < 0) { | |
1066 | if (slsi_sm_bt_service_cleanup(true) == 0) | |
1067 | atomic_dec(&bt_service.service_users); | |
1068 | } | |
1069 | ||
1070 | wake_unlock(&bt_service.service_wake_lock); | |
1071 | mutex_unlock(&bt_start_mutex); | |
1072 | return err; | |
1073 | } | |
1074 | ||
1075 | #ifdef CONFIG_SCSC_ANT | |
1076 | /* Start the ANT service */ | |
1077 | int slsi_sm_ant_service_start(void) | |
1078 | { | |
1079 | int err = 0; | |
1080 | struct BHCS *bhcs; | |
1081 | ||
1082 | ++ant_service_start_count; | |
1083 | ||
1084 | /* Lock the start/stop procedures to handle multiple application | |
1085 | * starting the sercice | |
1086 | */ | |
1087 | mutex_lock(&ant_start_mutex); | |
1088 | ||
1089 | if (disable_service) { | |
1090 | SCSC_TAG_WARNING(BT_COMMON, "service disabled\n"); | |
1091 | mutex_unlock(&ant_start_mutex); | |
1092 | return -EBUSY; | |
1093 | } | |
1094 | ||
1095 | /* Has probe been called */ | |
1096 | if (common_service.maxwell_core == NULL) { | |
1097 | SCSC_TAG_WARNING(BT_COMMON, "service probe not arrived\n"); | |
1098 | mutex_unlock(&ant_start_mutex); | |
1099 | return -EFAULT; | |
1100 | } | |
1101 | ||
1102 | /* Is this the first service to enter */ | |
1103 | if (atomic_inc_return(&ant_service.service_users) > 1) { | |
1104 | SCSC_TAG_WARNING(BT_COMMON, "service already opened\n"); | |
1105 | ||
1106 | if (!ant_service.service_started) { | |
1107 | SCSC_TAG_DEBUG(BT_COMMON, "service not started, returning error\n"); | |
1108 | err = -EFAULT; | |
1109 | atomic_dec(&bt_service.service_users); | |
1110 | } | |
1111 | ||
1112 | mutex_unlock(&ant_start_mutex); | |
1113 | return err; | |
1114 | } | |
1115 | ||
1116 | /* Open service - will download FW - will set MBOX0 with Starting | |
1117 | * address | |
1118 | */ | |
1119 | SCSC_TAG_DEBUG(BT_COMMON, | |
1120 | "open ANT service id %d opened %d times\n", | |
1121 | SCSC_SERVICE_ID_ANT, ant_service_start_count); | |
1122 | ||
1123 | wake_lock(&ant_service.service_wake_lock); | |
1124 | ant_service.service = scsc_mx_service_open(common_service.maxwell_core, | |
1125 | SCSC_SERVICE_ID_ANT, | |
1126 | &mx_ant_client, | |
1127 | &err); | |
1128 | if (!ant_service.service) { | |
1129 | SCSC_TAG_WARNING(BT_COMMON, "ant service open failed %d\n", err); | |
1130 | if (err < 0) { | |
1131 | atomic_dec(&ant_service.service_users); | |
1132 | wake_unlock(&ant_service.service_wake_lock); | |
1133 | mutex_unlock(&ant_start_mutex); | |
1134 | return -EINVAL; | |
1135 | } | |
1136 | } | |
1137 | ||
1138 | /* Shorter completion timeout if autorecovery is disabled, as it will | |
1139 | * never be signalled. | |
1140 | */ | |
1141 | if (mxman_recovery_disabled()) | |
1142 | recovery_timeout = SLSI_BT_SERVICE_STOP_RECOVERY_DISABLED_TIMEOUT; | |
1143 | else | |
1144 | recovery_timeout = SLSI_BT_SERVICE_STOP_RECOVERY_TIMEOUT; | |
1145 | ||
1146 | ||
1147 | /* Get shared memory region for the configuration structure from | |
1148 | * the MIF | |
1149 | */ | |
1150 | SCSC_TAG_DEBUG(BT_COMMON, "allocate mifram regions\n"); | |
1151 | err = scsc_mx_service_mifram_alloc(ant_service.service, | |
1152 | sizeof(struct BHCS), | |
1153 | &ant_service.bhcs_ref, | |
1154 | BSMHCP_ALIGNMENT); | |
1155 | if (err) { | |
1156 | SCSC_TAG_WARNING(BT_COMMON, "mifram alloc failed\n"); | |
1157 | err = -EINVAL; | |
1158 | goto exit; | |
1159 | } | |
1160 | ||
1161 | /* Get shared memory region for the protocol structure from the MIF */ | |
1162 | err = scsc_mx_service_mifram_alloc(ant_service.service, | |
1163 | sizeof(struct ASMHCP_PROTOCOL), | |
1164 | &ant_service.asmhcp_ref, | |
1165 | BSMHCP_ALIGNMENT); | |
1166 | if (err) { | |
1167 | SCSC_TAG_WARNING(BT_COMMON, "mifram alloc failed\n"); | |
1168 | err = -EINVAL; | |
1169 | goto exit; | |
1170 | } | |
1171 | ||
1172 | /* Map the configuration pointer */ | |
1173 | bhcs = (struct BHCS *) scsc_mx_service_mif_addr_to_ptr( | |
1174 | ant_service.service, | |
1175 | ant_service.bhcs_ref); | |
1176 | if (bhcs == NULL) { | |
1177 | SCSC_TAG_ERR(BT_COMMON, | |
1178 | "couldn't map kmem to bhcs_ref 0x%08x\n", | |
1179 | (u32)ant_service.bhcs_ref); | |
1180 | err = -ENOMEM; | |
1181 | goto exit; | |
1182 | } | |
1183 | ||
1184 | SCSC_TAG_INFO(BT_COMMON, | |
1185 | "regions (bhcs_ref=0x%08x, bsmhcp_ref=0x%08x, config_ref=0x%08x)\n", | |
1186 | ant_service.bhcs_ref, | |
1187 | ant_service.asmhcp_ref, | |
1188 | ant_service.config_ref); | |
1189 | SCSC_TAG_INFO(BT_COMMON, "version=%u\n", BHCS_VERSION); | |
1190 | ||
1191 | err = setup_bhcs(ant_service.service, | |
1192 | bhcs, | |
1193 | ant_service.asmhcp_ref, | |
1194 | sizeof(struct ASMHCP_PROTOCOL), | |
1195 | &ant_service.config_ref, | |
1196 | &ant_service.bhcs_ref); | |
1197 | ||
1198 | if (err == -EINVAL) | |
1199 | goto exit; | |
1200 | ||
1201 | /* Initialise the shared-memory interface */ | |
1202 | err = scsc_ant_shm_init(); | |
1203 | if (err) { | |
1204 | SCSC_TAG_ERR(BT_COMMON, "scsc_ant_shm_init err %d\n", err); | |
1205 | err = -EINVAL; | |
1206 | goto exit; | |
1207 | } | |
1208 | ||
1209 | ant_service.asmhcp_protocol->header.mxlog_filter = firmware_mxlog_filter; | |
1210 | ant_service.asmhcp_protocol->header.firmware_control = firmware_control; | |
1211 | ||
1212 | SCSC_TAG_DEBUG(BT_COMMON, | |
1213 | "firmware_control=0x%08x, firmware_control_reset=%u\n", | |
1214 | firmware_control, firmware_control_reset); | |
1215 | ||
1216 | if (firmware_control_reset) | |
1217 | firmware_control = 0; | |
1218 | ||
1219 | /* Start service last - after setting up shared memory resources */ | |
1220 | SCSC_TAG_DEBUG(BT_COMMON, "starting ANT service\n"); | |
1221 | err = scsc_mx_service_start(ant_service.service, ant_service.bhcs_ref); | |
1222 | if (err < 0) { | |
1223 | SCSC_TAG_ERR(BT_COMMON, "scsc_mx_service_start err %d\n", err); | |
1224 | err = -EINVAL; | |
1225 | } else { | |
1226 | SCSC_TAG_DEBUG(BT_COMMON, "Ant service running\n"); | |
1227 | ant_service.service_started = true; | |
1228 | slsi_kic_system_event( | |
1229 | slsi_kic_system_event_category_initialisation, | |
1230 | slsi_kic_system_events_ant_on, 0); | |
1231 | } | |
1232 | ||
1233 | exit: | |
1234 | if (err < 0) { | |
1235 | if (slsi_sm_ant_service_cleanup(true) == 0) | |
1236 | atomic_dec(&ant_service.service_users); | |
1237 | } | |
1238 | ||
1239 | wake_unlock(&ant_service.service_wake_lock); | |
1240 | mutex_unlock(&ant_start_mutex); | |
1241 | return err; | |
1242 | } | |
1243 | #endif | |
1244 | ||
1245 | /* Stop the BT service */ | |
1246 | static int slsi_sm_bt_service_stop(bool force_cleanup) | |
1247 | { | |
1248 | SCSC_TAG_INFO(BT_COMMON, "bt service users %u\n", atomic_read(&bt_service.service_users)); | |
1249 | ||
1250 | if (1 < atomic_read(&bt_service.service_users)) { | |
1251 | atomic_dec(&bt_service.service_users); | |
1252 | } else if (1 == atomic_read(&bt_service.service_users)) { | |
1253 | if (slsi_sm_bt_service_cleanup(force_cleanup) == 0) | |
1254 | atomic_dec(&bt_service.service_users); | |
1255 | else | |
1256 | return -EIO; | |
1257 | } | |
1258 | ||
1259 | return 0; | |
1260 | } | |
1261 | ||
1262 | #ifdef CONFIG_SCSC_ANT | |
1263 | /* Stop the ANT service */ | |
1264 | static int slsi_sm_ant_service_stop(bool force_cleanup) | |
1265 | { | |
1266 | SCSC_TAG_INFO(BT_COMMON, "ant service users %u\n", atomic_read(&ant_service.service_users)); | |
1267 | ||
1268 | if (atomic_read(&ant_service.service_users) > 1) { | |
1269 | atomic_dec(&ant_service.service_users); | |
1270 | } else if (atomic_read(&ant_service.service_users) == 1) { | |
1271 | if (slsi_sm_ant_service_cleanup(force_cleanup) == 0) | |
1272 | atomic_dec(&ant_service.service_users); | |
1273 | else | |
1274 | return -EIO; | |
1275 | } | |
1276 | ||
1277 | return 0; | |
1278 | } | |
1279 | #endif | |
1280 | ||
1281 | static int scsc_bt_h4_open(struct inode *inode, struct file *file) | |
1282 | { | |
1283 | int ret = 0; | |
1284 | ||
1285 | SCSC_TAG_INFO(BT_COMMON, "(h4_users=%u)\n", bt_service.h4_users ? 1 : 0); | |
1286 | ||
1287 | if (!bt_service.h4_users) { | |
1288 | ret = slsi_sm_bt_service_start(); | |
1289 | if (0 == ret) | |
1290 | bt_service.h4_users = true; | |
1291 | } else { | |
1292 | ret = -EBUSY; | |
1293 | } | |
1294 | ||
1295 | return ret; | |
1296 | } | |
1297 | ||
1298 | static int scsc_bt_h4_release(struct inode *inode, struct file *file) | |
1299 | { | |
1300 | SCSC_TAG_INFO(BT_COMMON, "\n"); | |
1301 | ||
1302 | mutex_lock(&bt_start_mutex); | |
1303 | wake_lock(&bt_service.service_wake_lock); | |
1304 | if (bt_recovery_level != MX_SYSERR_LEVEL_7) { | |
1305 | if (slsi_sm_bt_service_stop(false) == -EIO) | |
1306 | goto recovery; | |
1307 | ||
1308 | /* Clear all control structures */ | |
1309 | bt_service.read_offset = 0; | |
1310 | bt_service.read_operation = 0; | |
1311 | bt_service.read_index = 0; | |
1312 | bt_service.h4_write_offset = 0; | |
1313 | ||
1314 | /* The recovery flag can be set in case of crossing release and | |
1315 | * recovery signaling. It's safe to check the flag here since | |
1316 | * the bt_start_mutex guarantees that the remove/probe callbacks | |
1317 | * will be called after the mutex is released. Jump to the | |
1318 | * normal recovery path. | |
1319 | */ | |
1320 | if (bt_recovery_level == MX_SYSERR_LEVEL_7) | |
1321 | goto recovery; | |
1322 | else | |
1323 | bt_recovery_level = 0; | |
1324 | ||
1325 | wake_unlock(&bt_service.service_wake_lock); | |
1326 | bt_service.h4_users = false; | |
1327 | mutex_unlock(&bt_start_mutex); | |
1328 | } else { | |
1329 | int ret; | |
1330 | recovery: | |
1331 | complete_all(&bt_service.recovery_release_complete); | |
1332 | wake_unlock(&bt_service.service_wake_lock); | |
1333 | mutex_unlock(&bt_start_mutex); | |
1334 | ||
1335 | ret = wait_for_completion_timeout(&bt_service.recovery_probe_complete, | |
1336 | msecs_to_jiffies(recovery_timeout)); | |
1337 | if (ret == 0) | |
1338 | SCSC_TAG_INFO(BT_COMMON, "recovery_probe_complete timeout\n"); | |
1339 | ||
1340 | bt_service.h4_users = false; | |
1341 | } | |
1342 | ||
1343 | return 0; | |
1344 | } | |
1345 | ||
1346 | #ifdef CONFIG_SCSC_ANT | |
1347 | static int scsc_ant_release(struct inode *inode, struct file *file) | |
1348 | { | |
1349 | SCSC_TAG_INFO(BT_COMMON, "\n"); | |
1350 | ||
1351 | mutex_lock(&ant_start_mutex); | |
1352 | wake_lock(&ant_service.service_wake_lock); | |
1353 | if (ant_recovery_level != MX_SYSERR_LEVEL_7) { | |
1354 | if (slsi_sm_ant_service_stop(false) == -EIO) | |
1355 | goto recovery; | |
1356 | ||
1357 | /* Clear all control structures */ | |
1358 | ant_service.read_offset = 0; | |
1359 | ant_service.read_operation = 0; | |
1360 | ant_service.read_index = 0; | |
1361 | ant_service.ant_write_offset = 0; | |
1362 | ||
1363 | ant_service.ant_users = false; | |
1364 | ||
1365 | /* The recovery flag can be set in case of crossing release and | |
1366 | * recovery signaling. It's safe to check the flag here since | |
1367 | * the bt_start_mutex guarantees that the remove/probe callbacks | |
1368 | * will be called after the mutex is released. Jump to the | |
1369 | * normal recovery path. | |
1370 | */ | |
1371 | if (ant_recovery_level == MX_SYSERR_LEVEL_7) | |
1372 | goto recovery; | |
1373 | else | |
1374 | ant_recovery_level = 0; | |
1375 | ||
1376 | wake_unlock(&ant_service.service_wake_lock); | |
1377 | ant_service.ant_users = false; | |
1378 | mutex_unlock(&ant_start_mutex); | |
1379 | } else { | |
1380 | int ret; | |
1381 | recovery: | |
1382 | complete_all(&ant_service.recovery_release_complete); | |
1383 | wake_unlock(&ant_service.service_wake_lock); | |
1384 | mutex_unlock(&ant_start_mutex); | |
1385 | ||
1386 | ret = wait_for_completion_timeout(&ant_service.recovery_probe_complete, | |
1387 | msecs_to_jiffies(recovery_timeout)); | |
1388 | if (ret == 0) | |
1389 | SCSC_TAG_INFO(BT_COMMON, "recovery_probe_complete timeout\n"); | |
1390 | ||
1391 | ant_service.ant_users = false; | |
1392 | } | |
1393 | ||
1394 | return 0; | |
1395 | } | |
1396 | #endif | |
1397 | ||
1398 | #ifdef CONFIG_SCSC_ANT | |
1399 | static int scsc_ant_open(struct inode *inode, struct file *file) | |
1400 | { | |
1401 | int ret = 0; | |
1402 | ||
1403 | SCSC_TAG_INFO(BT_COMMON, "(ant_users=%u)\n", ant_service.ant_users ? 1 : 0); | |
1404 | ||
1405 | if (ant_recovery_level != 0) { | |
1406 | SCSC_TAG_WARNING(BT_COMMON, "recovery in progress\n"); | |
1407 | wait_event_interruptible_timeout(ant_recovery_complete_queue, | |
1408 | ant_recovery_level == 0, | |
1409 | SCSC_ANT_MAX_TIMEOUT); | |
1410 | if (ant_recovery_level != 0) { | |
1411 | SCSC_TAG_WARNING(BT_COMMON, "recovery timeout, aborting\n"); | |
1412 | return -EFAULT; | |
1413 | } | |
1414 | } | |
1415 | if (!ant_service.ant_users) { | |
1416 | ret = slsi_sm_ant_service_start(); | |
1417 | if (ret == 0) | |
1418 | ant_service.ant_users = true; | |
1419 | } else { | |
1420 | ret = -EBUSY; | |
1421 | } | |
1422 | ||
1423 | return ret; | |
1424 | } | |
1425 | #endif | |
1426 | ||
1427 | static long scsc_default_ioctl(struct file *file, | |
1428 | unsigned int cmd, | |
1429 | unsigned long arg) | |
1430 | { | |
1431 | UNUSED(file); | |
1432 | UNUSED(cmd); | |
1433 | UNUSED(arg); | |
1434 | ||
1435 | switch (cmd) { | |
1436 | case TCGETS: | |
1437 | SCSC_TAG_DEBUG(BT_COMMON, "TCGETS (arg=%lu)\n", arg); | |
1438 | break; | |
1439 | case TCSETS: | |
1440 | SCSC_TAG_DEBUG(BT_COMMON, "TCSETS (arg=%lu)\n", arg); | |
1441 | break; | |
1442 | default: | |
1443 | SCSC_TAG_DEBUG(BT_COMMON, | |
1444 | "trapped ioctl in virtual tty device, cmd %d arg %lu\n", | |
1445 | cmd, arg); | |
1446 | break; | |
1447 | } | |
1448 | ||
1449 | return 0; | |
1450 | } | |
1451 | ||
1452 | static int scsc_bt_trigger_recovery(void *priv, | |
1453 | enum slsi_kic_test_recovery_type type) | |
1454 | { | |
1455 | int err = 0; | |
1456 | ||
1457 | SCSC_TAG_INFO(BT_COMMON, "forcing panic\n"); | |
1458 | ||
1459 | mutex_lock(&bt_start_mutex); | |
1460 | ||
1461 | if (0 < atomic_read(&bt_service.service_users) && | |
1462 | bt_service.bsmhcp_protocol) { | |
1463 | SCSC_TAG_INFO(BT_COMMON, "trashing magic value\n"); | |
1464 | ||
1465 | if (slsi_kic_test_recovery_type_service_stop_panic == type) | |
1466 | bt_service.bsmhcp_protocol->header.firmware_control = | |
1467 | BSMHCP_CONTROL_STOP_PANIC; | |
1468 | else if (slsi_kic_test_recovery_type_service_start_panic == | |
1469 | type) | |
1470 | firmware_control = BSMHCP_CONTROL_START_PANIC; | |
1471 | else | |
1472 | bt_service.bsmhcp_protocol->header.magic_value = 0; | |
1473 | ||
1474 | scsc_service_mifintrbit_bit_set(bt_service.service, | |
1475 | bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, | |
1476 | SCSC_MIFINTR_TARGET_R4); | |
1477 | } else { | |
1478 | if (slsi_kic_test_recovery_type_service_stop_panic == type) | |
1479 | firmware_control = BSMHCP_CONTROL_STOP_PANIC; | |
1480 | else if (slsi_kic_test_recovery_type_service_start_panic == | |
1481 | type) | |
1482 | firmware_control = BSMHCP_CONTROL_START_PANIC; | |
1483 | else | |
1484 | err = -EFAULT; | |
1485 | } | |
1486 | ||
1487 | mutex_unlock(&bt_start_mutex); | |
1488 | ||
1489 | return err; | |
1490 | } | |
1491 | ||
1492 | #ifdef CONFIG_SCSC_ANT | |
1493 | static int scsc_ant_trigger_recovery(void *priv, | |
1494 | enum slsi_kic_test_recovery_type type) | |
1495 | { | |
1496 | int err = 0; | |
1497 | ||
1498 | SCSC_TAG_INFO(BT_COMMON, "forcing panic\n"); | |
1499 | ||
1500 | mutex_lock(&ant_start_mutex); | |
1501 | ||
1502 | if (atomic_read(&ant_service.service_users) > 0 && | |
1503 | ant_service.asmhcp_protocol) { | |
1504 | SCSC_TAG_INFO(BT_COMMON, "trashing magic value\n"); | |
1505 | ||
1506 | if (slsi_kic_test_recovery_type_service_stop_panic == type) | |
1507 | ant_service.asmhcp_protocol->header.firmware_control = | |
1508 | BSMHCP_CONTROL_STOP_PANIC; | |
1509 | else if (slsi_kic_test_recovery_type_service_start_panic == | |
1510 | type) | |
1511 | firmware_control = BSMHCP_CONTROL_START_PANIC; | |
1512 | else | |
1513 | ant_service.asmhcp_protocol->header.magic_value = 0; | |
1514 | ||
1515 | scsc_service_mifintrbit_bit_set(ant_service.service, | |
1516 | ant_service.asmhcp_protocol->header.ap_to_bg_int_src, | |
1517 | SCSC_MIFINTR_TARGET_R4); | |
1518 | } else { | |
1519 | if (slsi_kic_test_recovery_type_service_stop_panic == type) | |
1520 | firmware_control = BSMHCP_CONTROL_STOP_PANIC; | |
1521 | else if (slsi_kic_test_recovery_type_service_start_panic == | |
1522 | type) | |
1523 | firmware_control = BSMHCP_CONTROL_START_PANIC; | |
1524 | else | |
1525 | err = -EFAULT; | |
1526 | } | |
1527 | ||
1528 | mutex_unlock(&ant_start_mutex); | |
1529 | ||
1530 | return err; | |
1531 | } | |
1532 | #endif | |
1533 | ||
1534 | static const struct file_operations scsc_bt_shm_fops = { | |
1535 | .owner = THIS_MODULE, | |
1536 | .open = scsc_bt_h4_open, | |
1537 | .release = scsc_bt_h4_release, | |
1538 | .read = scsc_bt_shm_h4_read, | |
1539 | .write = scsc_bt_shm_h4_write, | |
1540 | .poll = scsc_bt_shm_h4_poll, | |
1541 | .unlocked_ioctl = scsc_default_ioctl, | |
1542 | }; | |
1543 | ||
1544 | #ifdef CONFIG_SCSC_ANT | |
1545 | static const struct file_operations scsc_ant_shm_fops = { | |
1546 | .owner = THIS_MODULE, | |
1547 | .open = scsc_ant_open, | |
1548 | .release = scsc_ant_release, | |
1549 | .read = scsc_shm_ant_read, | |
1550 | .write = scsc_shm_ant_write, | |
1551 | .poll = scsc_shm_ant_poll, | |
1552 | }; | |
1553 | #endif | |
1554 | ||
1555 | static struct slsi_kic_bt_ops scsc_bt_kic_ops = { | |
1556 | .trigger_recovery = scsc_bt_trigger_recovery | |
1557 | }; | |
1558 | ||
1559 | #ifdef CONFIG_SCSC_ANT | |
1560 | static struct slsi_kic_ant_ops scsc_ant_kic_ops = { | |
1561 | .trigger_recovery = scsc_ant_trigger_recovery | |
1562 | }; | |
1563 | #endif | |
1564 | ||
1565 | /* A new MX instance is available */ | |
1566 | void slsi_bt_service_probe(struct scsc_mx_module_client *module_client, | |
1567 | struct scsc_mx *mx, | |
1568 | enum scsc_module_client_reason reason) | |
1569 | { | |
1570 | /* Note: mx identifies the instance */ | |
1571 | SCSC_TAG_INFO(BT_COMMON, | |
1572 | "BT service probe (%s %p)\n", module_client->name, mx); | |
1573 | ||
1574 | mutex_lock(&bt_start_mutex); | |
1575 | if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && bt_recovery_level == 0) { | |
1576 | SCSC_TAG_INFO(BT_COMMON, | |
1577 | "BT service probe recovery, but no recovery in progress\n"); | |
1578 | goto done; | |
1579 | } | |
1580 | ||
1581 | bt_service.dev = scsc_mx_get_device(mx); | |
1582 | common_service.maxwell_core = mx; | |
1583 | ||
1584 | get_device(bt_service.dev); | |
1585 | ||
1586 | if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && bt_recovery_level != 0) { | |
1587 | complete_all(&bt_service.recovery_probe_complete); | |
1588 | bt_recovery_level = 0; | |
1589 | } | |
1590 | ||
1591 | slsi_bt_notify_probe(bt_service.dev, | |
1592 | &scsc_bt_shm_fops, | |
1593 | &bt_service.error_count, | |
1594 | &bt_service.read_wait); | |
1595 | ||
1596 | done: | |
1597 | mutex_unlock(&bt_start_mutex); | |
1598 | } | |
1599 | ||
1600 | /* The MX instance is now unavailable */ | |
1601 | static void slsi_bt_service_remove(struct scsc_mx_module_client *module_client, | |
1602 | struct scsc_mx *mx, | |
1603 | enum scsc_module_client_reason reason) | |
1604 | { | |
1605 | SCSC_TAG_INFO(BT_COMMON, | |
1606 | "BT service remove (%s %p)\n", module_client->name, mx); | |
1607 | ||
1608 | mutex_lock(&bt_start_mutex); | |
1609 | if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && bt_recovery_level == 0) { | |
1610 | SCSC_TAG_INFO(BT_COMMON, | |
1611 | "BT service remove recovery, but no recovery in progress\n"); | |
1612 | goto done; | |
1613 | } | |
1614 | ||
1615 | if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && bt_recovery_level != 0) { | |
1616 | bool h4_users = bt_service.h4_users; | |
1617 | ||
1618 | mutex_unlock(&bt_start_mutex); | |
1619 | ||
1620 | /* Wait forever for recovery_release_complete, as it will | |
1621 | * arrive even if autorecovery is disabled. | |
1622 | */ | |
1623 | SCSC_TAG_INFO(BT_COMMON, "wait for recovery_release_complete\n"); | |
1624 | ||
1625 | /* only wait for recovery_release_complete if service has a user */ | |
1626 | if (h4_users) | |
1627 | wait_for_completion(&bt_service.recovery_release_complete); | |
1628 | ||
1629 | reinit_completion(&bt_service.recovery_release_complete); | |
1630 | ||
1631 | mutex_lock(&bt_start_mutex); | |
1632 | if (slsi_sm_bt_service_stop(true) == -EIO) | |
1633 | SCSC_TAG_INFO(BT_COMMON, "Service stop or close failed during recovery.\n"); | |
1634 | ||
1635 | /* Clear all control structures */ | |
1636 | bt_service.read_offset = 0; | |
1637 | bt_service.read_operation = 0; | |
1638 | bt_service.read_index = 0; | |
1639 | bt_service.h4_write_offset = 0; | |
1640 | } | |
1641 | ||
1642 | slsi_bt_notify_remove(); | |
1643 | put_device(bt_service.dev); | |
1644 | common_service.maxwell_core = NULL; | |
1645 | ||
1646 | done: | |
1647 | mutex_unlock(&bt_start_mutex); | |
1648 | ||
1649 | SCSC_TAG_INFO(BT_COMMON, | |
1650 | "BT service remove complete (%s %p)\n", module_client->name, mx); | |
1651 | } | |
1652 | ||
1653 | /* BT service driver registration interface */ | |
1654 | static struct scsc_mx_module_client bt_driver = { | |
1655 | .name = "BT driver", | |
1656 | .probe = slsi_bt_service_probe, | |
1657 | .remove = slsi_bt_service_remove, | |
1658 | }; | |
1659 | ||
1660 | #ifdef CONFIG_SCSC_ANT | |
1661 | /* A new MX instance is available */ | |
1662 | void slsi_ant_service_probe(struct scsc_mx_module_client *module_client, | |
1663 | struct scsc_mx *mx, | |
1664 | enum scsc_module_client_reason reason) | |
1665 | { | |
1666 | /* Note: mx identifies the instance */ | |
1667 | SCSC_TAG_INFO(BT_COMMON, | |
1668 | "ANT service probe (%s %p)\n", module_client->name, mx); | |
1669 | ||
1670 | mutex_lock(&ant_start_mutex); | |
1671 | if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && ant_recovery_level == 0) { | |
1672 | SCSC_TAG_INFO(BT_COMMON, | |
1673 | "ANT service probe recovery, but no recovery in progress\n"); | |
1674 | goto done; | |
1675 | } | |
1676 | ||
1677 | ant_service.dev = scsc_mx_get_device(mx); | |
1678 | common_service.maxwell_core = mx; | |
1679 | ||
1680 | get_device(ant_service.dev); | |
1681 | ||
1682 | if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && ant_recovery_level != 0) { | |
1683 | complete_all(&ant_service.recovery_probe_complete); | |
1684 | ant_recovery_level = 0; | |
1685 | } | |
1686 | ||
1687 | done: | |
1688 | mutex_unlock(&ant_start_mutex); | |
1689 | wake_up_interruptible(&ant_recovery_complete_queue); | |
1690 | } | |
1691 | #endif | |
1692 | ||
1693 | #ifdef CONFIG_SCSC_ANT | |
1694 | /* The MX instance is now unavailable */ | |
1695 | static void slsi_ant_service_remove(struct scsc_mx_module_client *module_client, | |
1696 | struct scsc_mx *mx, | |
1697 | enum scsc_module_client_reason reason) | |
1698 | { | |
1699 | SCSC_TAG_INFO(BT_COMMON, | |
1700 | "ANT service remove (%s %p)\n", module_client->name, mx); | |
1701 | ||
1702 | mutex_lock(&ant_start_mutex); | |
1703 | if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && ant_recovery_level == 0) { | |
1704 | SCSC_TAG_INFO(BT_COMMON, | |
1705 | "ANT service remove recovery, but no recovery in progress\n"); | |
1706 | goto done; | |
1707 | } | |
1708 | ||
1709 | if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && ant_recovery_level != 0) { | |
1710 | int ret; | |
1711 | bool ant_users = ant_service.ant_users; | |
1712 | ||
1713 | mutex_unlock(&ant_start_mutex); | |
1714 | ||
1715 | /* Wait full duration for recovery_release_complete, as it will | |
1716 | * arrive even if autorecovery is disabled. | |
1717 | */ | |
1718 | if (ant_users) | |
1719 | ret = wait_for_completion_timeout(&ant_service.recovery_release_complete, | |
1720 | msecs_to_jiffies(SLSI_BT_SERVICE_STOP_RECOVERY_TIMEOUT)); | |
1721 | reinit_completion(&ant_service.recovery_release_complete); | |
1722 | if (ret == 0) | |
1723 | SCSC_TAG_INFO(BT_COMMON, "recovery_release_complete timeout\n"); | |
1724 | ||
1725 | mutex_lock(&ant_start_mutex); | |
1726 | if (slsi_sm_ant_service_stop(true) == -EIO) | |
1727 | SCSC_TAG_INFO(BT_COMMON, "Service stop or close failed during recovery.\n"); | |
1728 | ||
1729 | ant_service.ant_users = false; | |
1730 | ||
1731 | /* Clear all control structures */ | |
1732 | ant_service.read_offset = 0; | |
1733 | ant_service.read_operation = 0; | |
1734 | ant_service.read_index = 0; | |
1735 | ant_service.ant_write_offset = 0; | |
1736 | } | |
1737 | ||
1738 | put_device(ant_service.dev); | |
1739 | common_service.maxwell_core = NULL; | |
1740 | ||
1741 | done: | |
1742 | mutex_unlock(&ant_start_mutex); | |
1743 | ||
1744 | SCSC_TAG_INFO(BT_COMMON, | |
1745 | "ANT service remove complete (%s %p)\n", module_client->name, mx); | |
1746 | } | |
1747 | #endif | |
1748 | ||
1749 | #ifdef CONFIG_SCSC_ANT | |
1750 | /* ANT service driver registration interface */ | |
1751 | static struct scsc_mx_module_client ant_driver = { | |
1752 | .name = "ANT driver", | |
1753 | .probe = slsi_ant_service_probe, | |
1754 | .remove = slsi_ant_service_remove, | |
1755 | }; | |
1756 | #endif | |
1757 | ||
1758 | static void slsi_bt_service_proc_show_firmware(struct seq_file *m) | |
1759 | { | |
1760 | struct BSMHCP_FW_INFO *info = | |
1761 | &bt_service.bsmhcp_protocol->information; | |
1762 | int res; | |
1763 | u32 index; | |
1764 | u32 user_defined_count = info->user_defined_count; | |
1765 | ||
1766 | bt_info_trigger++; | |
1767 | ||
1768 | scsc_service_mifintrbit_bit_set(bt_service.service, | |
1769 | bt_service.bsmhcp_protocol->header.info_ap_to_bg_int_src, | |
1770 | SCSC_MIFINTR_TARGET_R4); | |
1771 | ||
1772 | res = wait_event_interruptible_timeout(bt_service.info_wait, | |
1773 | bt_info_trigger == bt_info_interrupt, | |
1774 | 2*HZ); | |
1775 | ||
1776 | seq_printf(m, " r4_from_ap_interrupt_count = %u\n", | |
1777 | info->r4_from_ap_interrupt_count); | |
1778 | seq_printf(m, " m4_from_ap_interrupt_count = %u\n", | |
1779 | info->m4_from_ap_interrupt_count); | |
1780 | seq_printf(m, " r4_to_ap_interrupt_count = %u\n", | |
1781 | info->r4_to_ap_interrupt_count); | |
1782 | seq_printf(m, " m4_to_ap_interrupt_count = %u\n\n", | |
1783 | info->m4_to_ap_interrupt_count); | |
1784 | seq_printf(m, " bt_deep_sleep_time_total = %u\n", | |
1785 | info->bt_deep_sleep_time_total); | |
1786 | seq_printf(m, " bt_deep_sleep_wakeup_duration = %u\n\n", | |
1787 | info->bt_deep_sleep_wakeup_duration); | |
1788 | seq_printf(m, " sched_n_messages = %u\n\n", | |
1789 | info->sched_n_messages); | |
1790 | seq_printf(m, " user_defined_count = %u\n\n", | |
1791 | info->user_defined_count); | |
1792 | ||
1793 | if (user_defined_count > BSMHCP_FW_INFO_USER_DEFINED_COUNT) | |
1794 | user_defined_count = BSMHCP_FW_INFO_USER_DEFINED_COUNT; | |
1795 | ||
1796 | for (index = 0; index < user_defined_count; index++) | |
1797 | seq_printf(m, " user%02u = 0x%08x (%u)\n", | |
1798 | index, info->user_defined[index], info->user_defined[index]); | |
1799 | ||
1800 | if (user_defined_count) | |
1801 | seq_puts(m, "\n"); | |
1802 | ||
1803 | seq_printf(m, " bt_info_trigger = %u\n", | |
1804 | bt_info_trigger); | |
1805 | seq_printf(m, " bt_info_interrupt = %u\n\n", | |
1806 | bt_info_interrupt); | |
1807 | seq_printf(m, " result = %d\n", res); | |
1808 | } | |
1809 | ||
1810 | static int slsi_bt_service_proc_show(struct seq_file *m, void *v) | |
1811 | { | |
1812 | char allocated_text[BSMHCP_DATA_BUFFER_TX_ACL_SIZE + 1]; | |
1813 | char processed_text[BSMHCP_TRANSFER_RING_EVT_SIZE + 1]; | |
1814 | size_t index; | |
1815 | struct scsc_bt_avdtp_detect_hci_connection *cur = bt_service.avdtp_detect.connections; | |
1816 | ||
1817 | seq_puts(m, "Driver statistics:\n"); | |
1818 | seq_printf(m, " write_wake_lock_count = %zu\n", | |
1819 | bt_service.write_wake_lock_count); | |
1820 | seq_printf(m, " write_wake_unlock_count = %zu\n\n", | |
1821 | bt_service.write_wake_unlock_count); | |
1822 | ||
1823 | seq_printf(m, " mailbox_hci_evt_read = %u\n", | |
1824 | bt_service.mailbox_hci_evt_read); | |
1825 | seq_printf(m, " mailbox_hci_evt_write = %u\n", | |
1826 | bt_service.mailbox_hci_evt_write); | |
1827 | seq_printf(m, " mailbox_acl_rx_read = %u\n", | |
1828 | bt_service.mailbox_acl_rx_read); | |
1829 | seq_printf(m, " mailbox_acl_rx_write = %u\n", | |
1830 | bt_service.mailbox_acl_rx_write); | |
1831 | seq_printf(m, " mailbox_acl_free_read = %u\n", | |
1832 | bt_service.mailbox_acl_free_read); | |
1833 | seq_printf(m, " mailbox_acl_free_read_scan = %u\n", | |
1834 | bt_service.mailbox_acl_free_read_scan); | |
1835 | seq_printf(m, " mailbox_acl_free_write = %u\n", | |
1836 | bt_service.mailbox_acl_free_write); | |
1837 | ||
1838 | seq_printf(m, " hci_event_paused = %u\n", | |
1839 | bt_service.hci_event_paused); | |
1840 | seq_printf(m, " acldata_paused = %u\n\n", | |
1841 | bt_service.acldata_paused); | |
1842 | ||
1843 | seq_printf(m, " interrupt_count = %zu\n", | |
1844 | bt_service.interrupt_count); | |
1845 | seq_printf(m, " interrupt_read_count = %zu\n", | |
1846 | bt_service.interrupt_read_count); | |
1847 | seq_printf(m, " interrupt_write_count = %zu\n", | |
1848 | bt_service.interrupt_write_count); | |
1849 | ||
1850 | for (index = 0; index < BSMHCP_DATA_BUFFER_TX_ACL_SIZE; index++) | |
1851 | allocated_text[index] = bt_service.allocated[index] ? '1' : '0'; | |
1852 | allocated_text[BSMHCP_DATA_BUFFER_TX_ACL_SIZE] = 0; | |
1853 | ||
1854 | for (index = 0; index < BSMHCP_TRANSFER_RING_EVT_SIZE; index++) | |
1855 | processed_text[index] = bt_service.processed[index] ? '1' : '0'; | |
1856 | processed_text[BSMHCP_DATA_BUFFER_TX_ACL_SIZE] = 0; | |
1857 | ||
1858 | seq_printf(m, " allocated_count = %u\n", | |
1859 | bt_service.allocated_count); | |
1860 | seq_printf(m, " freed_count = %u\n", | |
1861 | bt_service.freed_count); | |
1862 | seq_printf(m, " allocated = %s\n", | |
1863 | allocated_text); | |
1864 | seq_printf(m, " processed = %s\n\n", | |
1865 | processed_text); | |
1866 | ||
1867 | while (cur) { | |
1868 | seq_printf(m, " avdtp_hci_connection_handle = %u\n\n", | |
1869 | cur->hci_connection_handle); | |
1870 | seq_printf(m, " avdtp_signaling_src_cid = %u\n", | |
1871 | cur->signal.src_cid); | |
1872 | seq_printf(m, " avdtp_signaling_dst_cid = %u\n", | |
1873 | cur->signal.dst_cid); | |
1874 | seq_printf(m, " avdtp_streaming_src_cid = %u\n", | |
1875 | cur->stream.src_cid); | |
1876 | seq_printf(m, " avdtp_streaming_dst_cid = %u\n", | |
1877 | cur->stream.dst_cid); | |
1878 | cur = cur->next; | |
1879 | } | |
1880 | seq_puts(m, "Firmware statistics:\n"); | |
1881 | ||
1882 | mutex_lock(&bt_start_mutex); | |
1883 | ||
1884 | if (NULL != bt_service.service) { | |
1885 | if (bt_service.bsmhcp_protocol->header.firmware_features & | |
1886 | BSMHCP_FEATURE_FW_INFORMATION) { | |
1887 | slsi_bt_service_proc_show_firmware(m); | |
1888 | } else | |
1889 | seq_puts(m, | |
1890 | " Firmware does not provide this information\n"); | |
1891 | } else | |
1892 | seq_puts(m, | |
1893 | " Error: bluetooth service is currently disabled\n"); | |
1894 | ||
1895 | mutex_unlock(&bt_start_mutex); | |
1896 | ||
1897 | return 0; | |
1898 | } | |
1899 | ||
1900 | static int slsi_bt_service_proc_open(struct inode *inode, struct file *file) | |
1901 | { | |
1902 | return single_open(file, slsi_bt_service_proc_show, NULL); | |
1903 | } | |
1904 | ||
1905 | static const struct file_operations scsc_bt_procfs_fops = { | |
1906 | .owner = THIS_MODULE, | |
1907 | .open = slsi_bt_service_proc_open, | |
1908 | .read = seq_read, | |
1909 | .llseek = seq_lseek, | |
1910 | .release = single_release, | |
1911 | }; | |
1912 | ||
1913 | static int scsc_mxlog_filter_set_param_cb(const char *buffer, | |
1914 | const struct kernel_param *kp) | |
1915 | { | |
1916 | int ret; | |
1917 | u32 value; | |
1918 | ||
1919 | ret = kstrtou32(buffer, 0, &value); | |
1920 | if (!ret) { | |
1921 | firmware_mxlog_filter = value; | |
1922 | ||
1923 | mutex_lock(&bt_start_mutex); | |
1924 | if (bt_service.service) { | |
1925 | bt_service.bsmhcp_protocol->header.mxlog_filter = | |
1926 | firmware_mxlog_filter; | |
1927 | ||
1928 | /* Trigger the interrupt in the mailbox */ | |
1929 | scsc_service_mifintrbit_bit_set(bt_service.service, | |
1930 | bt_service.bsmhcp_protocol->header.ap_to_bg_int_src, | |
1931 | SCSC_MIFINTR_TARGET_R4); | |
1932 | } | |
1933 | mutex_unlock(&bt_start_mutex); | |
1934 | } | |
1935 | ||
1936 | return ret; | |
1937 | } | |
1938 | ||
1939 | static int scsc_mxlog_filter_get_param_cb(char *buffer, | |
1940 | const struct kernel_param *kp) | |
1941 | { | |
1942 | return sprintf(buffer, "filter=0x%08x\n", firmware_mxlog_filter); | |
1943 | } | |
1944 | ||
1945 | static struct kernel_param_ops scsc_mxlog_filter_ops = { | |
1946 | .set = scsc_mxlog_filter_set_param_cb, | |
1947 | .get = scsc_mxlog_filter_get_param_cb, | |
1948 | }; | |
1949 | ||
1950 | module_param_cb(mxlog_filter, &scsc_mxlog_filter_ops, NULL, S_IRUGO | S_IWUSR); | |
1951 | MODULE_PARM_DESC(mxlog_filter, | |
1952 | "Set the filter for MX log in the Bluetooth firmware"); | |
1953 | ||
1954 | static int scsc_force_crash_set_param_cb(const char *buffer, | |
1955 | const struct kernel_param *kp) | |
1956 | { | |
1957 | int ret; | |
1958 | u32 value; | |
1959 | ||
1960 | ret = kstrtou32(buffer, 0, &value); | |
1961 | if (!ret && value == 0xDEADDEAD) { | |
1962 | mutex_lock(&bt_start_mutex); | |
1963 | if (bt_service.service) { | |
1964 | atomic_inc(&bt_service.error_count); | |
1965 | wake_up(&bt_service.read_wait); | |
1966 | } | |
1967 | mutex_unlock(&bt_start_mutex); | |
1968 | } | |
1969 | ||
1970 | return ret; | |
1971 | } | |
1972 | ||
1973 | static struct kernel_param_ops scsc_force_crash_ops = { | |
1974 | .set = scsc_force_crash_set_param_cb, | |
1975 | .get = NULL, | |
1976 | }; | |
1977 | ||
1978 | module_param_cb(force_crash, &scsc_force_crash_ops, NULL, S_IRUGO | S_IWUSR); | |
1979 | MODULE_PARM_DESC(force_crash, | |
1980 | "Forces a crash of the Bluetooth driver"); | |
1981 | ||
1982 | ||
1983 | phys_addr_t scsc_bt_audio_get_paddr_buf(bool tx) | |
1984 | { | |
1985 | if (bt_audio.abox_physical) { | |
1986 | struct scsc_bt_audio_abox *abox_physical; | |
1987 | void *ptr; | |
1988 | ||
1989 | abox_physical = bt_audio.abox_physical; | |
1990 | if (tx) | |
1991 | ptr = abox_physical->bt_to_abox_streaming_if_data; | |
1992 | else | |
1993 | ptr = abox_physical->abox_to_bt_streaming_if_data; | |
1994 | ||
1995 | return (phys_addr_t)ptr; | |
1996 | } else | |
1997 | return 0; | |
1998 | } | |
1999 | EXPORT_SYMBOL(scsc_bt_audio_get_paddr_buf); | |
2000 | ||
2001 | unsigned int scsc_bt_audio_get_rate(int id) | |
2002 | { | |
2003 | if (!bt_audio.abox_virtual) | |
2004 | return 0; | |
2005 | ||
2006 | switch (id) { | |
2007 | case 0: | |
2008 | return bt_audio.abox_virtual->streaming_if_0_sample_rate; | |
2009 | case 1: | |
2010 | return bt_audio.abox_virtual->streaming_if_1_sample_rate; | |
2011 | default: | |
2012 | return 0; | |
2013 | } | |
2014 | } | |
2015 | EXPORT_SYMBOL(scsc_bt_audio_get_rate); | |
2016 | ||
2017 | int scsc_bt_audio_register(struct device *dev, | |
2018 | int (*dev_iommu_map)(struct device *, phys_addr_t, size_t), | |
2019 | void (*dev_iommu_unmap)(struct device *, size_t)) | |
2020 | { | |
2021 | int ret = 0; | |
2022 | ||
2023 | mutex_lock(&bt_audio_mutex); | |
2024 | ||
2025 | if (audio_device != NULL || dev == NULL || | |
2026 | dev_iommu_map == NULL || dev_iommu_unmap == NULL) { | |
2027 | SCSC_TAG_ERR(BT_COMMON, | |
2028 | "failed audio_device %p dev %p dev_iommu_map %p dev_iommu_unmap %p\n", | |
2029 | audio_device, dev, dev_iommu_map, dev_iommu_unmap); | |
2030 | ret = -EINVAL; | |
2031 | } else { | |
2032 | audio_device = dev; | |
2033 | bt_audio.dev_iommu_map = dev_iommu_map; | |
2034 | bt_audio.dev_iommu_unmap = dev_iommu_unmap; | |
2035 | } | |
2036 | ||
2037 | mutex_unlock(&bt_audio_mutex); | |
2038 | ||
2039 | return ret; | |
2040 | } | |
2041 | EXPORT_SYMBOL(scsc_bt_audio_register); | |
2042 | ||
2043 | int scsc_bt_audio_unregister(struct device *dev) | |
2044 | { | |
2045 | int ret = 0; | |
2046 | ||
2047 | mutex_lock(&bt_audio_mutex); | |
2048 | ||
2049 | if (audio_device != NULL && dev == audio_device) { | |
2050 | ||
2051 | /* Unmap ringbuffer IOMMU now that A-Box is finished with it, | |
2052 | * but for safety don't allow this if BT is running. | |
2053 | * | |
2054 | * In practice, A-Box driver only unregisters if platform | |
2055 | * driver unloads at shutdown, so it would be safe to leave the | |
2056 | * memmory mapped. | |
2057 | */ | |
2058 | if (atomic_read(&bt_service.service_users) == 0 && audio_device_probed) | |
2059 | slsi_bt_audio_remove(); | |
2060 | ||
2061 | bt_audio.dev = NULL; | |
2062 | bt_audio.abox_virtual = NULL; | |
2063 | bt_audio.abox_physical = NULL; | |
2064 | bt_audio.dev_iommu_map = NULL; | |
2065 | bt_audio.dev_iommu_unmap = NULL; | |
2066 | audio_device = NULL; | |
2067 | audio_device_probed = false; | |
2068 | } else | |
2069 | ret = -EINVAL; | |
2070 | ||
2071 | mutex_unlock(&bt_audio_mutex); | |
2072 | ||
2073 | return ret; | |
2074 | } | |
2075 | EXPORT_SYMBOL(scsc_bt_audio_unregister); | |
2076 | ||
2077 | /******* Module entry/exit point ********/ | |
2078 | static int __init scsc_bt_module_init(void) | |
2079 | { | |
2080 | int ret; | |
2081 | struct proc_dir_entry *procfs_dir; | |
2082 | ||
2083 | SCSC_TAG_INFO(BT_COMMON, "%s %s (C) %s\n", | |
2084 | SCSC_MODDESC, SCSC_MODVERSION, SCSC_MODAUTH); | |
781f598d | 2085 | bt_module_irq_mask = 0; |
e91a78c7 TK |
2086 | bt_recovery_level = 0; |
2087 | #ifdef CONFIG_SCSC_ANT | |
2088 | ant_recovery_level = 0; | |
2089 | #endif | |
2090 | ||
2091 | memset(&bt_service, 0, sizeof(bt_service)); | |
2092 | #ifdef CONFIG_SCSC_ANT | |
2093 | memset(&ant_service, 0, sizeof(ant_service)); | |
2094 | #endif | |
2095 | ||
2096 | init_waitqueue_head(&bt_service.read_wait); | |
2097 | init_waitqueue_head(&bt_service.info_wait); | |
2098 | ||
2099 | wake_lock_init(&bt_service.read_wake_lock, | |
2100 | WAKE_LOCK_SUSPEND, | |
2101 | "bt_read_wake_lock"); | |
2102 | wake_lock_init(&bt_service.write_wake_lock, | |
2103 | WAKE_LOCK_SUSPEND, | |
2104 | "bt_write_wake_lock"); | |
2105 | wake_lock_init(&bt_service.service_wake_lock, | |
2106 | WAKE_LOCK_SUSPEND, | |
2107 | "bt_service_wake_lock"); | |
2108 | ||
2109 | #ifdef CONFIG_SCSC_ANT | |
2110 | init_waitqueue_head(&ant_service.read_wait); | |
2111 | ||
2112 | wake_lock_init(&ant_service.read_wake_lock, | |
2113 | WAKE_LOCK_SUSPEND, | |
2114 | "ant_read_wake_lock"); | |
2115 | wake_lock_init(&ant_service.write_wake_lock, | |
2116 | WAKE_LOCK_SUSPEND, | |
2117 | "ant_write_wake_lock"); | |
2118 | wake_lock_init(&ant_service.service_wake_lock, | |
2119 | WAKE_LOCK_SUSPEND, | |
2120 | "ant_service_wake_lock"); | |
2121 | #endif | |
2122 | ||
2123 | procfs_dir = proc_mkdir("driver/scsc_bt", NULL); | |
2124 | if (NULL != procfs_dir) { | |
2125 | proc_create_data("stats", S_IRUSR | S_IRGRP, | |
2126 | procfs_dir, &scsc_bt_procfs_fops, NULL); | |
2127 | } | |
2128 | ||
2129 | ret = alloc_chrdev_region(&bt_service.device, 0, | |
2130 | SCSC_TTY_MINORS, "scsc_char"); | |
2131 | if (ret) { | |
2132 | SCSC_TAG_ERR(BT_COMMON, "error alloc_chrdev_region %d\n", ret); | |
2133 | return ret; | |
2134 | } | |
2135 | ||
2136 | common_service.class = class_create(THIS_MODULE, "scsc_char"); | |
2137 | if (IS_ERR(common_service.class)) { | |
2138 | ret = PTR_ERR(common_service.class); | |
2139 | goto error; | |
2140 | } | |
2141 | ||
2142 | cdev_init(&bt_service.h4_cdev, &scsc_bt_shm_fops); | |
2143 | ret = cdev_add(&bt_service.h4_cdev, | |
2144 | MKDEV(MAJOR(bt_service.device), MINOR(0)), 1); | |
2145 | if (ret) { | |
2146 | SCSC_TAG_ERR(BT_COMMON, | |
2147 | "cdev_add failed for device %s\n", | |
2148 | SCSC_H4_DEVICE_NAME); | |
2149 | bt_service.h4_cdev.dev = 0; | |
2150 | goto error; | |
2151 | } | |
2152 | ||
2153 | bt_service.h4_device = device_create(common_service.class, | |
2154 | NULL, | |
2155 | bt_service.h4_cdev.dev, | |
2156 | NULL, | |
2157 | SCSC_H4_DEVICE_NAME); | |
2158 | if (bt_service.h4_device == NULL) { | |
2159 | cdev_del(&bt_service.h4_cdev); | |
2160 | ret = -EFAULT; | |
2161 | goto error; | |
2162 | } | |
2163 | ||
2164 | init_completion(&bt_service.recovery_probe_complete); | |
2165 | init_completion(&bt_service.recovery_release_complete); | |
2166 | ||
2167 | #ifdef CONFIG_SCSC_ANT | |
2168 | ret = alloc_chrdev_region(&ant_service.device, 0, | |
2169 | SCSC_TTY_MINORS, "scsc_ant_char"); | |
2170 | if (ret) { | |
2171 | SCSC_TAG_ERR(BT_COMMON, "error alloc_chrdev_region %d\n", ret); | |
2172 | return ret; | |
2173 | } | |
2174 | ||
2175 | cdev_init(&ant_service.ant_cdev, &scsc_ant_shm_fops); | |
2176 | ret = cdev_add(&ant_service.ant_cdev, | |
2177 | MKDEV(MAJOR(ant_service.device), MINOR(0)), 1); | |
2178 | if (ret) { | |
2179 | SCSC_TAG_ERR(BT_COMMON, | |
2180 | "cdev_add failed for device %s\n", | |
2181 | SCSC_ANT_DEVICE_NAME); | |
2182 | ant_service.ant_cdev.dev = 0; | |
2183 | goto error; | |
2184 | } | |
2185 | ||
2186 | ant_service.ant_device = device_create(common_service.class, | |
2187 | NULL, | |
2188 | ant_service.ant_cdev.dev, | |
2189 | NULL, | |
2190 | SCSC_ANT_DEVICE_NAME); | |
2191 | if (ant_service.ant_device == NULL) { | |
2192 | cdev_del(&ant_service.ant_cdev); | |
2193 | ret = -EFAULT; | |
2194 | goto error; | |
2195 | } | |
2196 | ||
2197 | init_completion(&ant_service.recovery_probe_complete); | |
2198 | init_completion(&ant_service.recovery_release_complete); | |
2199 | #endif | |
2200 | ||
2201 | /* Register KIC interface */ | |
2202 | slsi_kic_bt_ops_register(NULL, &scsc_bt_kic_ops); | |
2203 | ||
2204 | /* Register with MX manager */ | |
2205 | scsc_mx_module_register_client_module(&bt_driver); | |
2206 | ||
2207 | #ifdef CONFIG_SCSC_ANT | |
2208 | /* Register KIC interface */ | |
2209 | slsi_kic_ant_ops_register(NULL, &scsc_ant_kic_ops); | |
2210 | SCSC_TAG_DEBUG(BT_COMMON, "Register the KIC interface, %p\n", | |
2211 | &scsc_ant_kic_ops); | |
2212 | ||
2213 | /* Register with MX manager */ | |
2214 | scsc_mx_module_register_client_module(&ant_driver); | |
2215 | #endif | |
2216 | ||
2217 | SCSC_TAG_DEBUG(BT_COMMON, "dev=%u class=%p\n", | |
2218 | bt_service.device, common_service.class); | |
2219 | ||
2220 | spin_lock_init(&bt_service.avdtp_detect.lock); | |
2221 | spin_lock_init(&bt_service.avdtp_detect.fw_write_lock); | |
2222 | ||
60f02aba | 2223 | //BEGIN IKKANE-6 |
2224 | #ifdef MOTO_UTAGS_MAC | |
2225 | sprintf(bluetooth_address_fallback, "F0:D7:AA:%02X:%02X:%02X", | |
2226 | (exynos_soc_info.unique_id & 0xFF0000000000) >> 40, | |
2227 | (exynos_soc_info.unique_id & 0x00FF00000000) >> 32, | |
2228 | (exynos_soc_info.unique_id & 0x0000FF000000) >> 24); | |
2229 | #elif CONFIG_ARCH_EXYNOS | |
e91a78c7 | 2230 | sprintf(bluetooth_address_fallback, "%02X:%02X:%02X:%02X:%02X:%02X", |
60f02aba | 2231 | (exynos_soc_info.unique_id & 0x000000FF0000) >> 16, |
2232 | (exynos_soc_info.unique_id & 0x00000000FF00) >> 8, | |
2233 | (exynos_soc_info.unique_id & 0x0000000000FF) >> 0, | |
2234 | (exynos_soc_info.unique_id & 0xFF0000000000) >> 40, | |
2235 | (exynos_soc_info.unique_id & 0x00FF00000000) >> 32, | |
2236 | (exynos_soc_info.unique_id & 0x0000FF000000) >> 24); | |
e91a78c7 | 2237 | #endif |
60f02aba | 2238 | //END IKKANE-6 |
e91a78c7 TK |
2239 | |
2240 | #ifdef CONFIG_SCSC_ANT | |
2241 | SCSC_TAG_DEBUG(BT_COMMON, "dev=%u class=%p\n", | |
2242 | ant_service.device, common_service.class); | |
2243 | #endif | |
2244 | ||
2245 | return 0; | |
2246 | ||
2247 | error: | |
2248 | SCSC_TAG_ERR(BT_COMMON, "error class_create bt device\n"); | |
2249 | unregister_chrdev_region(bt_service.device, SCSC_TTY_MINORS); | |
2250 | ||
2251 | #ifdef CONFIG_SCSC_ANT | |
2252 | SCSC_TAG_ERR(BT_COMMON, "error class_create ant device\n"); | |
2253 | unregister_chrdev_region(ant_service.device, SCSC_TTY_MINORS); | |
2254 | #endif | |
2255 | ||
2256 | return ret; | |
2257 | } | |
2258 | ||
2259 | ||
2260 | static void __exit scsc_bt_module_exit(void) | |
2261 | { | |
2262 | SCSC_TAG_INFO(BT_COMMON, "\n"); | |
2263 | ||
2264 | wake_lock_destroy(&bt_service.write_wake_lock); | |
2265 | wake_lock_destroy(&bt_service.read_wake_lock); | |
2266 | wake_lock_destroy(&bt_service.service_wake_lock); | |
2267 | complete_all(&bt_service.recovery_probe_complete); | |
2268 | complete_all(&bt_service.recovery_release_complete); | |
2269 | ||
2270 | #ifdef CONFIG_SCSC_ANT | |
2271 | wake_lock_destroy(&ant_service.write_wake_lock); | |
2272 | wake_lock_destroy(&ant_service.read_wake_lock); | |
2273 | wake_lock_destroy(&ant_service.service_wake_lock); | |
2274 | complete_all(&ant_service.recovery_probe_complete); | |
2275 | complete_all(&ant_service.recovery_release_complete); | |
2276 | #endif | |
2277 | ||
2278 | slsi_kic_bt_ops_unregister(&scsc_bt_kic_ops); | |
2279 | ||
2280 | /* Register with MX manager */ | |
2281 | scsc_mx_module_unregister_client_module(&bt_driver); | |
2282 | ||
2283 | if (bt_service.h4_device) { | |
2284 | device_destroy(common_service.class, bt_service.h4_cdev.dev); | |
2285 | bt_service.h4_device = NULL; | |
2286 | } | |
2287 | ||
2288 | cdev_del(&bt_service.h4_cdev); | |
2289 | ||
2290 | unregister_chrdev_region(bt_service.device, SCSC_TTY_MINORS); | |
2291 | ||
2292 | #ifdef CONFIG_SCSC_ANT | |
2293 | slsi_kic_ant_ops_unregister(&scsc_ant_kic_ops); | |
2294 | ||
2295 | /* Register with MX manager */ | |
2296 | scsc_mx_module_unregister_client_module(&ant_driver); | |
2297 | ||
2298 | if (ant_service.ant_device) { | |
2299 | device_destroy(common_service.class, ant_service.ant_cdev.dev); | |
2300 | ant_service.ant_device = NULL; | |
2301 | } | |
2302 | ||
2303 | cdev_del(&ant_service.ant_cdev); | |
2304 | ||
2305 | unregister_chrdev_region(ant_service.device, SCSC_TTY_MINORS); | |
2306 | #endif | |
2307 | ||
2308 | SCSC_TAG_INFO(BT_COMMON, "exit, module unloaded\n"); | |
2309 | } | |
2310 | ||
2311 | module_init(scsc_bt_module_init); | |
2312 | module_exit(scsc_bt_module_exit); | |
2313 | ||
2314 | MODULE_DESCRIPTION(SCSC_MODDESC); | |
2315 | MODULE_AUTHOR(SCSC_MODAUTH); | |
2316 | MODULE_LICENSE("GPL"); | |
2317 | MODULE_VERSION(SCSC_MODVERSION); |