Linux Audio

Check our new training course

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