xref: /linux/drivers/hid/intel-ish-hid/ishtp/init.c (revision d53b8e36925256097a08d7cb749198d85cbf9b2b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Initialization protocol for ISHTP driver
4  *
5  * Copyright (c) 2003-2016, Intel Corporation.
6  */
7 
8 #include <linux/devm-helpers.h>
9 #include <linux/export.h>
10 #include <linux/slab.h>
11 #include <linux/sched.h>
12 #include "ishtp-dev.h"
13 #include "hbm.h"
14 #include "client.h"
15 #include "loader.h"
16 
17 /**
18  * ishtp_dev_state_str() -Convert to string format
19  * @state: state to convert
20  *
21  * Convert state to string for prints
22  *
23  * Return: character pointer to converted string
24  */
25 const char *ishtp_dev_state_str(int state)
26 {
27 	switch (state) {
28 	case ISHTP_DEV_INITIALIZING:
29 		return	"INITIALIZING";
30 	case ISHTP_DEV_INIT_CLIENTS:
31 		return	"INIT_CLIENTS";
32 	case ISHTP_DEV_ENABLED:
33 		return	"ENABLED";
34 	case ISHTP_DEV_RESETTING:
35 		return	"RESETTING";
36 	case ISHTP_DEV_DISABLED:
37 		return	"DISABLED";
38 	case ISHTP_DEV_POWER_DOWN:
39 		return	"POWER_DOWN";
40 	case ISHTP_DEV_POWER_UP:
41 		return	"POWER_UP";
42 	default:
43 		return "unknown";
44 	}
45 }
46 
47 /**
48  * ishtp_device_init() - ishtp device init
49  * @dev: ISHTP device instance
50  *
51  * After ISHTP device is alloacted, this function is used to initialize
52  * each field which includes spin lock, work struct and lists
53  */
54 void ishtp_device_init(struct ishtp_device *dev)
55 {
56 	int ret;
57 
58 	dev->dev_state = ISHTP_DEV_INITIALIZING;
59 	INIT_LIST_HEAD(&dev->cl_list);
60 	INIT_LIST_HEAD(&dev->device_list);
61 	dev->rd_msg_fifo_head = 0;
62 	dev->rd_msg_fifo_tail = 0;
63 	spin_lock_init(&dev->rd_msg_spinlock);
64 
65 	init_waitqueue_head(&dev->wait_hbm_recvd_msg);
66 	init_waitqueue_head(&dev->wait_loader_recvd_msg);
67 	spin_lock_init(&dev->read_list_spinlock);
68 	spin_lock_init(&dev->device_lock);
69 	spin_lock_init(&dev->device_list_lock);
70 	spin_lock_init(&dev->cl_list_lock);
71 	spin_lock_init(&dev->fw_clients_lock);
72 	INIT_WORK(&dev->bh_hbm_work, bh_hbm_work_fn);
73 
74 	bitmap_zero(dev->host_clients_map, ISHTP_CLIENTS_MAX);
75 	dev->open_handle_count = 0;
76 
77 	/*
78 	 * Reserving client ID 0 for ISHTP Bus Message communications
79 	 */
80 	bitmap_set(dev->host_clients_map, 0, 1);
81 
82 	INIT_LIST_HEAD(&dev->read_list.list);
83 
84 	ret = devm_work_autocancel(dev->devc, &dev->work_fw_loader, ishtp_loader_work);
85 	if (ret)
86 		dev_err_probe(dev->devc, ret, "Failed to initialise FW loader work\n");
87 }
88 EXPORT_SYMBOL(ishtp_device_init);
89 
90 /**
91  * ishtp_start() - Start ISH processing
92  * @dev: ISHTP device instance
93  *
94  * Start ISHTP processing by sending query subscriber message
95  *
96  * Return: 0 on success else -ENODEV
97  */
98 int ishtp_start(struct ishtp_device *dev)
99 {
100 	if (ishtp_hbm_start_wait(dev)) {
101 		dev_err(dev->devc, "HBM haven't started");
102 		goto err;
103 	}
104 
105 	/* suspend & resume notification - send QUERY_SUBSCRIBERS msg */
106 	ishtp_query_subscribers(dev);
107 
108 	return 0;
109 err:
110 	dev_err(dev->devc, "link layer initialization failed.\n");
111 	dev->dev_state = ISHTP_DEV_DISABLED;
112 	return -ENODEV;
113 }
114 EXPORT_SYMBOL(ishtp_start);
115