1 /*
2  * Copyright (c) 2017 Red Hat, Inc
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published by
6  * the Free Software Foundation.
7  */
8 
9 #define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
10 
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/libps2.h>
14 #include <linux/i2c.h>
15 #include <linux/serio.h>
16 #include <linux/slab.h>
17 #include <linux/workqueue.h>
18 #include "psmouse.h"
19 
20 struct psmouse_smbus_dev {
21 	struct i2c_board_info board;
22 	struct psmouse *psmouse;
23 	struct i2c_client *client;
24 	struct list_head node;
25 	bool dead;
26 };
27 
28 static LIST_HEAD(psmouse_smbus_list);
29 static DEFINE_MUTEX(psmouse_smbus_mutex);
30 
31 static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter)
32 {
33 	struct psmouse_smbus_dev *smbdev;
34 
35 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY))
36 		return;
37 
38 	mutex_lock(&psmouse_smbus_mutex);
39 
40 	list_for_each_entry(smbdev, &psmouse_smbus_list, node) {
41 		if (smbdev->dead)
42 			continue;
43 
44 		if (smbdev->client)
45 			continue;
46 
47 		/*
48 		 * Here would be a good place to check if device is actually
49 		 * present, but it seems that SMBus will not respond unless we
50 		 * fully reset PS/2 connection.  So cross our fingers, and try
51 		 * to switch over, hopefully our system will not have too many
52 		 * "host notify" I2C adapters.
53 		 */
54 		psmouse_dbg(smbdev->psmouse,
55 			    "SMBus candidate adapter appeared, triggering rescan\n");
56 		serio_rescan(smbdev->psmouse->ps2dev.serio);
57 	}
58 
59 	mutex_unlock(&psmouse_smbus_mutex);
60 }
61 
62 static void psmouse_smbus_detach_i2c_client(struct i2c_client *client)
63 {
64 	struct psmouse_smbus_dev *smbdev, *tmp;
65 
66 	mutex_lock(&psmouse_smbus_mutex);
67 
68 	list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
69 		if (smbdev->client != client)
70 			continue;
71 
72 		kfree(client->dev.platform_data);
73 		client->dev.platform_data = NULL;
74 
75 		if (!smbdev->dead) {
76 			psmouse_dbg(smbdev->psmouse,
77 				    "Marking SMBus companion %s as gone\n",
78 				    dev_name(&smbdev->client->dev));
79 			smbdev->dead = true;
80 			serio_rescan(smbdev->psmouse->ps2dev.serio);
81 		} else {
82 			list_del(&smbdev->node);
83 			kfree(smbdev);
84 		}
85 	}
86 
87 	mutex_unlock(&psmouse_smbus_mutex);
88 }
89 
90 static int psmouse_smbus_notifier_call(struct notifier_block *nb,
91 				       unsigned long action, void *data)
92 {
93 	struct device *dev = data;
94 
95 	switch (action) {
96 	case BUS_NOTIFY_ADD_DEVICE:
97 		if (dev->type == &i2c_adapter_type)
98 			psmouse_smbus_check_adapter(to_i2c_adapter(dev));
99 		break;
100 
101 	case BUS_NOTIFY_REMOVED_DEVICE:
102 		if (dev->type == &i2c_client_type)
103 			psmouse_smbus_detach_i2c_client(to_i2c_client(dev));
104 		break;
105 	}
106 
107 	return 0;
108 }
109 
110 static struct notifier_block psmouse_smbus_notifier = {
111 	.notifier_call = psmouse_smbus_notifier_call,
112 };
113 
114 static psmouse_ret_t psmouse_smbus_process_byte(struct psmouse *psmouse)
115 {
116 	return PSMOUSE_FULL_PACKET;
117 }
118 
119 static int psmouse_smbus_reconnect(struct psmouse *psmouse)
120 {
121 	psmouse_deactivate(psmouse);
122 
123 	return 0;
124 }
125 
126 struct psmouse_smbus_removal_work {
127 	struct work_struct work;
128 	struct i2c_client *client;
129 };
130 
131 static void psmouse_smbus_remove_i2c_device(struct work_struct *work)
132 {
133 	struct psmouse_smbus_removal_work *rwork =
134 		container_of(work, struct psmouse_smbus_removal_work, work);
135 
136 	dev_dbg(&rwork->client->dev, "destroying SMBus companion device\n");
137 	i2c_unregister_device(rwork->client);
138 
139 	kfree(rwork);
140 }
141 
142 /*
143  * This schedules removal of SMBus companion device. We have to do
144  * it in a separate tread to avoid deadlocking on psmouse_mutex in
145  * case the device has a trackstick (which is also driven by psmouse).
146  *
147  * Note that this may be racing with i2c adapter removal, but we
148  * can't do anything about that: i2c automatically destroys clients
149  * attached to an adapter that is being removed. This has to be
150  * fixed in i2c core.
151  */
152 static void psmouse_smbus_schedule_remove(struct i2c_client *client)
153 {
154 	struct psmouse_smbus_removal_work *rwork;
155 
156 	rwork = kzalloc(sizeof(*rwork), GFP_KERNEL);
157 	if (rwork) {
158 		INIT_WORK(&rwork->work, psmouse_smbus_remove_i2c_device);
159 		rwork->client = client;
160 
161 		schedule_work(&rwork->work);
162 	}
163 }
164 
165 static void psmouse_smbus_disconnect(struct psmouse *psmouse)
166 {
167 	struct psmouse_smbus_dev *smbdev = psmouse->private;
168 
169 	mutex_lock(&psmouse_smbus_mutex);
170 
171 	if (smbdev->dead) {
172 		list_del(&smbdev->node);
173 		kfree(smbdev);
174 	} else {
175 		smbdev->dead = true;
176 		psmouse_dbg(smbdev->psmouse,
177 			    "posting removal request for SMBus companion %s\n",
178 			    dev_name(&smbdev->client->dev));
179 		psmouse_smbus_schedule_remove(smbdev->client);
180 	}
181 
182 	mutex_unlock(&psmouse_smbus_mutex);
183 
184 	psmouse->private = NULL;
185 }
186 
187 static int psmouse_smbus_create_companion(struct device *dev, void *data)
188 {
189 	struct psmouse_smbus_dev *smbdev = data;
190 	unsigned short addr_list[] = { smbdev->board.addr, I2C_CLIENT_END };
191 	struct i2c_adapter *adapter;
192 
193 	adapter = i2c_verify_adapter(dev);
194 	if (!adapter)
195 		return 0;
196 
197 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY))
198 		return 0;
199 
200 	smbdev->client = i2c_new_probed_device(adapter, &smbdev->board,
201 					       addr_list, NULL);
202 	if (!smbdev->client)
203 		return 0;
204 
205 	/* We have our(?) device, stop iterating i2c bus. */
206 	return 1;
207 }
208 
209 void psmouse_smbus_cleanup(struct psmouse *psmouse)
210 {
211 	struct psmouse_smbus_dev *smbdev, *tmp;
212 
213 	mutex_lock(&psmouse_smbus_mutex);
214 
215 	list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
216 		if (psmouse == smbdev->psmouse) {
217 			list_del(&smbdev->node);
218 			kfree(smbdev);
219 		}
220 	}
221 
222 	mutex_unlock(&psmouse_smbus_mutex);
223 }
224 
225 int psmouse_smbus_init(struct psmouse *psmouse,
226 		       const struct i2c_board_info *board,
227 		       const void *pdata, size_t pdata_size,
228 		       bool leave_breadcrumbs)
229 {
230 	struct psmouse_smbus_dev *smbdev;
231 	int error;
232 
233 	smbdev = kzalloc(sizeof(*smbdev), GFP_KERNEL);
234 	if (!smbdev)
235 		return -ENOMEM;
236 
237 	smbdev->psmouse = psmouse;
238 	smbdev->board = *board;
239 
240 	smbdev->board.platform_data = kmemdup(pdata, pdata_size, GFP_KERNEL);
241 	if (!smbdev->board.platform_data) {
242 		kfree(smbdev);
243 		return -ENOMEM;
244 	}
245 
246 	psmouse->private = smbdev;
247 	psmouse->protocol_handler = psmouse_smbus_process_byte;
248 	psmouse->reconnect = psmouse_smbus_reconnect;
249 	psmouse->fast_reconnect = psmouse_smbus_reconnect;
250 	psmouse->disconnect = psmouse_smbus_disconnect;
251 	psmouse->resync_time = 0;
252 
253 	psmouse_deactivate(psmouse);
254 
255 	mutex_lock(&psmouse_smbus_mutex);
256 	list_add_tail(&smbdev->node, &psmouse_smbus_list);
257 	mutex_unlock(&psmouse_smbus_mutex);
258 
259 	/* Bind to already existing adapters right away */
260 	error = i2c_for_each_dev(smbdev, psmouse_smbus_create_companion);
261 
262 	if (smbdev->client) {
263 		/* We have our companion device */
264 		return 0;
265 	}
266 
267 	/*
268 	 * If we did not create i2c device we will not need platform
269 	 * data even if we are leaving breadcrumbs.
270 	 */
271 	kfree(smbdev->board.platform_data);
272 	smbdev->board.platform_data = NULL;
273 
274 	if (error < 0 || !leave_breadcrumbs) {
275 		mutex_lock(&psmouse_smbus_mutex);
276 		list_del(&smbdev->node);
277 		mutex_unlock(&psmouse_smbus_mutex);
278 
279 		kfree(smbdev);
280 	}
281 
282 	return error < 0 ? error : -EAGAIN;
283 }
284 
285 int __init psmouse_smbus_module_init(void)
286 {
287 	int error;
288 
289 	error = bus_register_notifier(&i2c_bus_type, &psmouse_smbus_notifier);
290 	if (error) {
291 		pr_err("failed to register i2c bus notifier: %d\n", error);
292 		return error;
293 	}
294 
295 	return 0;
296 }
297 
298 void psmouse_smbus_module_exit(void)
299 {
300 	bus_unregister_notifier(&i2c_bus_type, &psmouse_smbus_notifier);
301 	flush_scheduled_work();
302 }
303