1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Greybus Firmware Management Protocol Driver.
4  *
5  * Copyright 2016 Google Inc.
6  * Copyright 2016 Linaro Ltd.
7  */
8 
9 #include <linux/cdev.h>
10 #include <linux/completion.h>
11 #include <linux/firmware.h>
12 #include <linux/fs.h>
13 #include <linux/idr.h>
14 #include <linux/ioctl.h>
15 #include <linux/uaccess.h>
16 #include <linux/greybus.h>
17 
18 #include "firmware.h"
19 #include "greybus_firmware.h"
20 
21 #define FW_MGMT_TIMEOUT_MS		1000
22 
23 struct fw_mgmt {
24 	struct device		*parent;
25 	struct gb_connection	*connection;
26 	struct kref		kref;
27 	struct list_head	node;
28 
29 	/* Common id-map for interface and backend firmware requests */
30 	struct ida		id_map;
31 	struct mutex		mutex;
32 	struct completion	completion;
33 	struct cdev		cdev;
34 	struct device		*class_device;
35 	dev_t			dev_num;
36 	unsigned int		timeout_jiffies;
37 	bool			disabled; /* connection getting disabled */
38 
39 	/* Interface Firmware specific fields */
40 	bool			mode_switch_started;
41 	bool			intf_fw_loaded;
42 	u8			intf_fw_request_id;
43 	u8			intf_fw_status;
44 	u16			intf_fw_major;
45 	u16			intf_fw_minor;
46 
47 	/* Backend Firmware specific fields */
48 	u8			backend_fw_request_id;
49 	u8			backend_fw_status;
50 };
51 
52 /*
53  * Number of minor devices this driver supports.
54  * There will be exactly one required per Interface.
55  */
56 #define NUM_MINORS		U8_MAX
57 
58 static const struct class fw_mgmt_class = {
59 	.name = "gb_fw_mgmt",
60 };
61 
62 static dev_t fw_mgmt_dev_num;
63 static DEFINE_IDA(fw_mgmt_minors_map);
64 static LIST_HEAD(fw_mgmt_list);
65 static DEFINE_MUTEX(list_mutex);
66 
fw_mgmt_kref_release(struct kref * kref)67 static void fw_mgmt_kref_release(struct kref *kref)
68 {
69 	struct fw_mgmt *fw_mgmt = container_of(kref, struct fw_mgmt, kref);
70 
71 	ida_destroy(&fw_mgmt->id_map);
72 	kfree(fw_mgmt);
73 }
74 
75 /*
76  * All users of fw_mgmt take a reference (from within list_mutex lock), before
77  * they get a pointer to play with. And the structure will be freed only after
78  * the last user has put the reference to it.
79  */
put_fw_mgmt(struct fw_mgmt * fw_mgmt)80 static void put_fw_mgmt(struct fw_mgmt *fw_mgmt)
81 {
82 	kref_put(&fw_mgmt->kref, fw_mgmt_kref_release);
83 }
84 
85 /* Caller must call put_fw_mgmt() after using struct fw_mgmt */
get_fw_mgmt(struct cdev * cdev)86 static struct fw_mgmt *get_fw_mgmt(struct cdev *cdev)
87 {
88 	struct fw_mgmt *fw_mgmt;
89 
90 	mutex_lock(&list_mutex);
91 
92 	list_for_each_entry(fw_mgmt, &fw_mgmt_list, node) {
93 		if (&fw_mgmt->cdev == cdev) {
94 			kref_get(&fw_mgmt->kref);
95 			goto unlock;
96 		}
97 	}
98 
99 	fw_mgmt = NULL;
100 
101 unlock:
102 	mutex_unlock(&list_mutex);
103 
104 	return fw_mgmt;
105 }
106 
fw_mgmt_interface_fw_version_operation(struct fw_mgmt * fw_mgmt,struct fw_mgmt_ioc_get_intf_version * fw_info)107 static int fw_mgmt_interface_fw_version_operation(struct fw_mgmt *fw_mgmt,
108 						  struct fw_mgmt_ioc_get_intf_version *fw_info)
109 {
110 	struct gb_connection *connection = fw_mgmt->connection;
111 	struct gb_fw_mgmt_interface_fw_version_response response;
112 	int ret;
113 
114 	ret = gb_operation_sync(connection,
115 				GB_FW_MGMT_TYPE_INTERFACE_FW_VERSION, NULL, 0,
116 				&response, sizeof(response));
117 	if (ret) {
118 		dev_err(fw_mgmt->parent,
119 			"failed to get interface firmware version (%d)\n", ret);
120 		return ret;
121 	}
122 
123 	fw_info->major = le16_to_cpu(response.major);
124 	fw_info->minor = le16_to_cpu(response.minor);
125 
126 	strncpy(fw_info->firmware_tag, response.firmware_tag,
127 		GB_FIRMWARE_TAG_MAX_SIZE);
128 
129 	/*
130 	 * The firmware-tag should be NULL terminated, otherwise throw error but
131 	 * don't fail.
132 	 */
133 	if (fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') {
134 		dev_err(fw_mgmt->parent,
135 			"fw-version: firmware-tag is not NULL terminated\n");
136 		fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] = '\0';
137 	}
138 
139 	return 0;
140 }
141 
fw_mgmt_load_and_validate_operation(struct fw_mgmt * fw_mgmt,u8 load_method,const char * tag)142 static int fw_mgmt_load_and_validate_operation(struct fw_mgmt *fw_mgmt,
143 					       u8 load_method, const char *tag)
144 {
145 	struct gb_fw_mgmt_load_and_validate_fw_request request;
146 	int ret;
147 
148 	if (load_method != GB_FW_LOAD_METHOD_UNIPRO &&
149 	    load_method != GB_FW_LOAD_METHOD_INTERNAL) {
150 		dev_err(fw_mgmt->parent,
151 			"invalid load-method (%d)\n", load_method);
152 		return -EINVAL;
153 	}
154 
155 	request.load_method = load_method;
156 	strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_SIZE);
157 
158 	/*
159 	 * The firmware-tag should be NULL terminated, otherwise throw error and
160 	 * fail.
161 	 */
162 	if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') {
163 		dev_err(fw_mgmt->parent, "load-and-validate: firmware-tag is not NULL terminated\n");
164 		return -EINVAL;
165 	}
166 
167 	/* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */
168 	ret = ida_simple_get(&fw_mgmt->id_map, 1, 256, GFP_KERNEL);
169 	if (ret < 0) {
170 		dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n",
171 			ret);
172 		return ret;
173 	}
174 
175 	fw_mgmt->intf_fw_request_id = ret;
176 	fw_mgmt->intf_fw_loaded = false;
177 	request.request_id = ret;
178 
179 	ret = gb_operation_sync(fw_mgmt->connection,
180 				GB_FW_MGMT_TYPE_LOAD_AND_VALIDATE_FW, &request,
181 				sizeof(request), NULL, 0);
182 	if (ret) {
183 		ida_simple_remove(&fw_mgmt->id_map,
184 				  fw_mgmt->intf_fw_request_id);
185 		fw_mgmt->intf_fw_request_id = 0;
186 		dev_err(fw_mgmt->parent,
187 			"load and validate firmware request failed (%d)\n",
188 			ret);
189 		return ret;
190 	}
191 
192 	return 0;
193 }
194 
fw_mgmt_interface_fw_loaded_operation(struct gb_operation * op)195 static int fw_mgmt_interface_fw_loaded_operation(struct gb_operation *op)
196 {
197 	struct gb_connection *connection = op->connection;
198 	struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection);
199 	struct gb_fw_mgmt_loaded_fw_request *request;
200 
201 	/* No pending load and validate request ? */
202 	if (!fw_mgmt->intf_fw_request_id) {
203 		dev_err(fw_mgmt->parent,
204 			"unexpected firmware loaded request received\n");
205 		return -ENODEV;
206 	}
207 
208 	if (op->request->payload_size != sizeof(*request)) {
209 		dev_err(fw_mgmt->parent, "illegal size of firmware loaded request (%zu != %zu)\n",
210 			op->request->payload_size, sizeof(*request));
211 		return -EINVAL;
212 	}
213 
214 	request = op->request->payload;
215 
216 	/* Invalid request-id ? */
217 	if (request->request_id != fw_mgmt->intf_fw_request_id) {
218 		dev_err(fw_mgmt->parent, "invalid request id for firmware loaded request (%02u != %02u)\n",
219 			fw_mgmt->intf_fw_request_id, request->request_id);
220 		return -ENODEV;
221 	}
222 
223 	ida_simple_remove(&fw_mgmt->id_map, fw_mgmt->intf_fw_request_id);
224 	fw_mgmt->intf_fw_request_id = 0;
225 	fw_mgmt->intf_fw_status = request->status;
226 	fw_mgmt->intf_fw_major = le16_to_cpu(request->major);
227 	fw_mgmt->intf_fw_minor = le16_to_cpu(request->minor);
228 
229 	if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_FAILED)
230 		dev_err(fw_mgmt->parent,
231 			"failed to load interface firmware, status:%02x\n",
232 			fw_mgmt->intf_fw_status);
233 	else if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_VALIDATION_FAILED)
234 		dev_err(fw_mgmt->parent,
235 			"failed to validate interface firmware, status:%02x\n",
236 			fw_mgmt->intf_fw_status);
237 	else
238 		fw_mgmt->intf_fw_loaded = true;
239 
240 	complete(&fw_mgmt->completion);
241 
242 	return 0;
243 }
244 
fw_mgmt_backend_fw_version_operation(struct fw_mgmt * fw_mgmt,struct fw_mgmt_ioc_get_backend_version * fw_info)245 static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt,
246 						struct fw_mgmt_ioc_get_backend_version *fw_info)
247 {
248 	struct gb_connection *connection = fw_mgmt->connection;
249 	struct gb_fw_mgmt_backend_fw_version_request request;
250 	struct gb_fw_mgmt_backend_fw_version_response response;
251 	int ret;
252 
253 	strncpy(request.firmware_tag, fw_info->firmware_tag,
254 		GB_FIRMWARE_TAG_MAX_SIZE);
255 
256 	/*
257 	 * The firmware-tag should be NULL terminated, otherwise throw error and
258 	 * fail.
259 	 */
260 	if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') {
261 		dev_err(fw_mgmt->parent, "backend-version: firmware-tag is not NULL terminated\n");
262 		return -EINVAL;
263 	}
264 
265 	ret = gb_operation_sync(connection,
266 				GB_FW_MGMT_TYPE_BACKEND_FW_VERSION, &request,
267 				sizeof(request), &response, sizeof(response));
268 	if (ret) {
269 		dev_err(fw_mgmt->parent, "failed to get version of %s backend firmware (%d)\n",
270 			fw_info->firmware_tag, ret);
271 		return ret;
272 	}
273 
274 	fw_info->status = response.status;
275 
276 	/* Reset version as that should be non-zero only for success case */
277 	fw_info->major = 0;
278 	fw_info->minor = 0;
279 
280 	switch (fw_info->status) {
281 	case GB_FW_BACKEND_VERSION_STATUS_SUCCESS:
282 		fw_info->major = le16_to_cpu(response.major);
283 		fw_info->minor = le16_to_cpu(response.minor);
284 		break;
285 	case GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE:
286 	case GB_FW_BACKEND_VERSION_STATUS_RETRY:
287 		break;
288 	case GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED:
289 		dev_err(fw_mgmt->parent,
290 			"Firmware with tag %s is not supported by Interface\n",
291 			fw_info->firmware_tag);
292 		break;
293 	default:
294 		dev_err(fw_mgmt->parent, "Invalid status received: %u\n",
295 			fw_info->status);
296 	}
297 
298 	return 0;
299 }
300 
fw_mgmt_backend_fw_update_operation(struct fw_mgmt * fw_mgmt,char * tag)301 static int fw_mgmt_backend_fw_update_operation(struct fw_mgmt *fw_mgmt,
302 					       char *tag)
303 {
304 	struct gb_fw_mgmt_backend_fw_update_request request;
305 	int ret;
306 
307 	strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_SIZE);
308 
309 	/*
310 	 * The firmware-tag should be NULL terminated, otherwise throw error and
311 	 * fail.
312 	 */
313 	if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') {
314 		dev_err(fw_mgmt->parent, "backend-update: firmware-tag is not NULL terminated\n");
315 		return -EINVAL;
316 	}
317 
318 	/* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */
319 	ret = ida_simple_get(&fw_mgmt->id_map, 1, 256, GFP_KERNEL);
320 	if (ret < 0) {
321 		dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n",
322 			ret);
323 		return ret;
324 	}
325 
326 	fw_mgmt->backend_fw_request_id = ret;
327 	request.request_id = ret;
328 
329 	ret = gb_operation_sync(fw_mgmt->connection,
330 				GB_FW_MGMT_TYPE_BACKEND_FW_UPDATE, &request,
331 				sizeof(request), NULL, 0);
332 	if (ret) {
333 		ida_simple_remove(&fw_mgmt->id_map,
334 				  fw_mgmt->backend_fw_request_id);
335 		fw_mgmt->backend_fw_request_id = 0;
336 		dev_err(fw_mgmt->parent,
337 			"backend %s firmware update request failed (%d)\n", tag,
338 			ret);
339 		return ret;
340 	}
341 
342 	return 0;
343 }
344 
fw_mgmt_backend_fw_updated_operation(struct gb_operation * op)345 static int fw_mgmt_backend_fw_updated_operation(struct gb_operation *op)
346 {
347 	struct gb_connection *connection = op->connection;
348 	struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection);
349 	struct gb_fw_mgmt_backend_fw_updated_request *request;
350 
351 	/* No pending load and validate request ? */
352 	if (!fw_mgmt->backend_fw_request_id) {
353 		dev_err(fw_mgmt->parent, "unexpected backend firmware updated request received\n");
354 		return -ENODEV;
355 	}
356 
357 	if (op->request->payload_size != sizeof(*request)) {
358 		dev_err(fw_mgmt->parent, "illegal size of backend firmware updated request (%zu != %zu)\n",
359 			op->request->payload_size, sizeof(*request));
360 		return -EINVAL;
361 	}
362 
363 	request = op->request->payload;
364 
365 	/* Invalid request-id ? */
366 	if (request->request_id != fw_mgmt->backend_fw_request_id) {
367 		dev_err(fw_mgmt->parent, "invalid request id for backend firmware updated request (%02u != %02u)\n",
368 			fw_mgmt->backend_fw_request_id, request->request_id);
369 		return -ENODEV;
370 	}
371 
372 	ida_simple_remove(&fw_mgmt->id_map, fw_mgmt->backend_fw_request_id);
373 	fw_mgmt->backend_fw_request_id = 0;
374 	fw_mgmt->backend_fw_status = request->status;
375 
376 	if ((fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_SUCCESS) &&
377 	    (fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_RETRY))
378 		dev_err(fw_mgmt->parent,
379 			"failed to load backend firmware: %02x\n",
380 			fw_mgmt->backend_fw_status);
381 
382 	complete(&fw_mgmt->completion);
383 
384 	return 0;
385 }
386 
387 /* Char device fops */
388 
fw_mgmt_open(struct inode * inode,struct file * file)389 static int fw_mgmt_open(struct inode *inode, struct file *file)
390 {
391 	struct fw_mgmt *fw_mgmt = get_fw_mgmt(inode->i_cdev);
392 
393 	/* fw_mgmt structure can't get freed until file descriptor is closed */
394 	if (fw_mgmt) {
395 		file->private_data = fw_mgmt;
396 		return 0;
397 	}
398 
399 	return -ENODEV;
400 }
401 
fw_mgmt_release(struct inode * inode,struct file * file)402 static int fw_mgmt_release(struct inode *inode, struct file *file)
403 {
404 	struct fw_mgmt *fw_mgmt = file->private_data;
405 
406 	put_fw_mgmt(fw_mgmt);
407 	return 0;
408 }
409 
fw_mgmt_ioctl(struct fw_mgmt * fw_mgmt,unsigned int cmd,void __user * buf)410 static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd,
411 			 void __user *buf)
412 {
413 	struct fw_mgmt_ioc_get_intf_version intf_fw_info;
414 	struct fw_mgmt_ioc_get_backend_version backend_fw_info;
415 	struct fw_mgmt_ioc_intf_load_and_validate intf_load;
416 	struct fw_mgmt_ioc_backend_fw_update backend_update;
417 	unsigned int timeout;
418 	int ret;
419 
420 	/* Reject any operations after mode-switch has started */
421 	if (fw_mgmt->mode_switch_started)
422 		return -EBUSY;
423 
424 	switch (cmd) {
425 	case FW_MGMT_IOC_GET_INTF_FW:
426 		ret = fw_mgmt_interface_fw_version_operation(fw_mgmt,
427 							     &intf_fw_info);
428 		if (ret)
429 			return ret;
430 
431 		if (copy_to_user(buf, &intf_fw_info, sizeof(intf_fw_info)))
432 			return -EFAULT;
433 
434 		return 0;
435 	case FW_MGMT_IOC_GET_BACKEND_FW:
436 		if (copy_from_user(&backend_fw_info, buf,
437 				   sizeof(backend_fw_info)))
438 			return -EFAULT;
439 
440 		ret = fw_mgmt_backend_fw_version_operation(fw_mgmt,
441 							   &backend_fw_info);
442 		if (ret)
443 			return ret;
444 
445 		if (copy_to_user(buf, &backend_fw_info,
446 				 sizeof(backend_fw_info)))
447 			return -EFAULT;
448 
449 		return 0;
450 	case FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE:
451 		if (copy_from_user(&intf_load, buf, sizeof(intf_load)))
452 			return -EFAULT;
453 
454 		ret = fw_mgmt_load_and_validate_operation(fw_mgmt,
455 				intf_load.load_method, intf_load.firmware_tag);
456 		if (ret)
457 			return ret;
458 
459 		if (!wait_for_completion_timeout(&fw_mgmt->completion,
460 						 fw_mgmt->timeout_jiffies)) {
461 			dev_err(fw_mgmt->parent, "timed out waiting for firmware load and validation to finish\n");
462 			return -ETIMEDOUT;
463 		}
464 
465 		intf_load.status = fw_mgmt->intf_fw_status;
466 		intf_load.major = fw_mgmt->intf_fw_major;
467 		intf_load.minor = fw_mgmt->intf_fw_minor;
468 
469 		if (copy_to_user(buf, &intf_load, sizeof(intf_load)))
470 			return -EFAULT;
471 
472 		return 0;
473 	case FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE:
474 		if (copy_from_user(&backend_update, buf,
475 				   sizeof(backend_update)))
476 			return -EFAULT;
477 
478 		ret = fw_mgmt_backend_fw_update_operation(fw_mgmt,
479 							  backend_update.firmware_tag);
480 		if (ret)
481 			return ret;
482 
483 		if (!wait_for_completion_timeout(&fw_mgmt->completion,
484 						 fw_mgmt->timeout_jiffies)) {
485 			dev_err(fw_mgmt->parent, "timed out waiting for backend firmware update to finish\n");
486 			return -ETIMEDOUT;
487 		}
488 
489 		backend_update.status = fw_mgmt->backend_fw_status;
490 
491 		if (copy_to_user(buf, &backend_update, sizeof(backend_update)))
492 			return -EFAULT;
493 
494 		return 0;
495 	case FW_MGMT_IOC_SET_TIMEOUT_MS:
496 		if (get_user(timeout, (unsigned int __user *)buf))
497 			return -EFAULT;
498 
499 		if (!timeout) {
500 			dev_err(fw_mgmt->parent, "timeout can't be zero\n");
501 			return -EINVAL;
502 		}
503 
504 		fw_mgmt->timeout_jiffies = msecs_to_jiffies(timeout);
505 
506 		return 0;
507 	case FW_MGMT_IOC_MODE_SWITCH:
508 		if (!fw_mgmt->intf_fw_loaded) {
509 			dev_err(fw_mgmt->parent,
510 				"Firmware not loaded for mode-switch\n");
511 			return -EPERM;
512 		}
513 
514 		/*
515 		 * Disallow new ioctls as the fw-core bundle driver is going to
516 		 * get disconnected soon and the character device will get
517 		 * removed.
518 		 */
519 		fw_mgmt->mode_switch_started = true;
520 
521 		ret = gb_interface_request_mode_switch(fw_mgmt->connection->intf);
522 		if (ret) {
523 			dev_err(fw_mgmt->parent, "Mode-switch failed: %d\n",
524 				ret);
525 			fw_mgmt->mode_switch_started = false;
526 			return ret;
527 		}
528 
529 		return 0;
530 	default:
531 		return -ENOTTY;
532 	}
533 }
534 
fw_mgmt_ioctl_unlocked(struct file * file,unsigned int cmd,unsigned long arg)535 static long fw_mgmt_ioctl_unlocked(struct file *file, unsigned int cmd,
536 				   unsigned long arg)
537 {
538 	struct fw_mgmt *fw_mgmt = file->private_data;
539 	struct gb_bundle *bundle = fw_mgmt->connection->bundle;
540 	int ret = -ENODEV;
541 
542 	/*
543 	 * Serialize ioctls.
544 	 *
545 	 * We don't want the user to do few operations in parallel. For example,
546 	 * updating Interface firmware in parallel for the same Interface. There
547 	 * is no need to do things in parallel for speed and we can avoid having
548 	 * complicated code for now.
549 	 *
550 	 * This is also used to protect ->disabled, which is used to check if
551 	 * the connection is getting disconnected, so that we don't start any
552 	 * new operations.
553 	 */
554 	mutex_lock(&fw_mgmt->mutex);
555 	if (!fw_mgmt->disabled) {
556 		ret = gb_pm_runtime_get_sync(bundle);
557 		if (!ret) {
558 			ret = fw_mgmt_ioctl(fw_mgmt, cmd, (void __user *)arg);
559 			gb_pm_runtime_put_autosuspend(bundle);
560 		}
561 	}
562 	mutex_unlock(&fw_mgmt->mutex);
563 
564 	return ret;
565 }
566 
567 static const struct file_operations fw_mgmt_fops = {
568 	.owner		= THIS_MODULE,
569 	.open		= fw_mgmt_open,
570 	.release	= fw_mgmt_release,
571 	.unlocked_ioctl	= fw_mgmt_ioctl_unlocked,
572 };
573 
gb_fw_mgmt_request_handler(struct gb_operation * op)574 int gb_fw_mgmt_request_handler(struct gb_operation *op)
575 {
576 	u8 type = op->type;
577 
578 	switch (type) {
579 	case GB_FW_MGMT_TYPE_LOADED_FW:
580 		return fw_mgmt_interface_fw_loaded_operation(op);
581 	case GB_FW_MGMT_TYPE_BACKEND_FW_UPDATED:
582 		return fw_mgmt_backend_fw_updated_operation(op);
583 	default:
584 		dev_err(&op->connection->bundle->dev,
585 			"unsupported request: %u\n", type);
586 		return -EINVAL;
587 	}
588 }
589 
gb_fw_mgmt_connection_init(struct gb_connection * connection)590 int gb_fw_mgmt_connection_init(struct gb_connection *connection)
591 {
592 	struct fw_mgmt *fw_mgmt;
593 	int ret, minor;
594 
595 	if (!connection)
596 		return 0;
597 
598 	fw_mgmt = kzalloc(sizeof(*fw_mgmt), GFP_KERNEL);
599 	if (!fw_mgmt)
600 		return -ENOMEM;
601 
602 	fw_mgmt->parent = &connection->bundle->dev;
603 	fw_mgmt->timeout_jiffies = msecs_to_jiffies(FW_MGMT_TIMEOUT_MS);
604 	fw_mgmt->connection = connection;
605 
606 	gb_connection_set_data(connection, fw_mgmt);
607 	init_completion(&fw_mgmt->completion);
608 	ida_init(&fw_mgmt->id_map);
609 	mutex_init(&fw_mgmt->mutex);
610 	kref_init(&fw_mgmt->kref);
611 
612 	mutex_lock(&list_mutex);
613 	list_add(&fw_mgmt->node, &fw_mgmt_list);
614 	mutex_unlock(&list_mutex);
615 
616 	ret = gb_connection_enable(connection);
617 	if (ret)
618 		goto err_list_del;
619 
620 	minor = ida_simple_get(&fw_mgmt_minors_map, 0, NUM_MINORS, GFP_KERNEL);
621 	if (minor < 0) {
622 		ret = minor;
623 		goto err_connection_disable;
624 	}
625 
626 	/* Add a char device to allow userspace to interact with fw-mgmt */
627 	fw_mgmt->dev_num = MKDEV(MAJOR(fw_mgmt_dev_num), minor);
628 	cdev_init(&fw_mgmt->cdev, &fw_mgmt_fops);
629 
630 	ret = cdev_add(&fw_mgmt->cdev, fw_mgmt->dev_num, 1);
631 	if (ret)
632 		goto err_remove_ida;
633 
634 	/* Add a soft link to the previously added char-dev within the bundle */
635 	fw_mgmt->class_device = device_create(&fw_mgmt_class, fw_mgmt->parent,
636 					      fw_mgmt->dev_num, NULL,
637 					      "gb-fw-mgmt-%d", minor);
638 	if (IS_ERR(fw_mgmt->class_device)) {
639 		ret = PTR_ERR(fw_mgmt->class_device);
640 		goto err_del_cdev;
641 	}
642 
643 	return 0;
644 
645 err_del_cdev:
646 	cdev_del(&fw_mgmt->cdev);
647 err_remove_ida:
648 	ida_simple_remove(&fw_mgmt_minors_map, minor);
649 err_connection_disable:
650 	gb_connection_disable(connection);
651 err_list_del:
652 	mutex_lock(&list_mutex);
653 	list_del(&fw_mgmt->node);
654 	mutex_unlock(&list_mutex);
655 
656 	put_fw_mgmt(fw_mgmt);
657 
658 	return ret;
659 }
660 
gb_fw_mgmt_connection_exit(struct gb_connection * connection)661 void gb_fw_mgmt_connection_exit(struct gb_connection *connection)
662 {
663 	struct fw_mgmt *fw_mgmt;
664 
665 	if (!connection)
666 		return;
667 
668 	fw_mgmt = gb_connection_get_data(connection);
669 
670 	device_destroy(&fw_mgmt_class, fw_mgmt->dev_num);
671 	cdev_del(&fw_mgmt->cdev);
672 	ida_simple_remove(&fw_mgmt_minors_map, MINOR(fw_mgmt->dev_num));
673 
674 	/*
675 	 * Disallow any new ioctl operations on the char device and wait for
676 	 * existing ones to finish.
677 	 */
678 	mutex_lock(&fw_mgmt->mutex);
679 	fw_mgmt->disabled = true;
680 	mutex_unlock(&fw_mgmt->mutex);
681 
682 	/* All pending greybus operations should have finished by now */
683 	gb_connection_disable(fw_mgmt->connection);
684 
685 	/* Disallow new users to get access to the fw_mgmt structure */
686 	mutex_lock(&list_mutex);
687 	list_del(&fw_mgmt->node);
688 	mutex_unlock(&list_mutex);
689 
690 	/*
691 	 * All current users of fw_mgmt would have taken a reference to it by
692 	 * now, we can drop our reference and wait the last user will get
693 	 * fw_mgmt freed.
694 	 */
695 	put_fw_mgmt(fw_mgmt);
696 }
697 
fw_mgmt_init(void)698 int fw_mgmt_init(void)
699 {
700 	int ret;
701 
702 	ret = class_register(&fw_mgmt_class);
703 	if (ret)
704 		return ret;
705 
706 	ret = alloc_chrdev_region(&fw_mgmt_dev_num, 0, NUM_MINORS,
707 				  "gb_fw_mgmt");
708 	if (ret)
709 		goto err_remove_class;
710 
711 	return 0;
712 
713 err_remove_class:
714 	class_unregister(&fw_mgmt_class);
715 	return ret;
716 }
717 
fw_mgmt_exit(void)718 void fw_mgmt_exit(void)
719 {
720 	unregister_chrdev_region(fw_mgmt_dev_num, NUM_MINORS);
721 	class_unregister(&fw_mgmt_class);
722 	ida_destroy(&fw_mgmt_minors_map);
723 }
724