0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/cdev.h>
0010 #include <linux/completion.h>
0011 #include <linux/firmware.h>
0012 #include <linux/fs.h>
0013 #include <linux/idr.h>
0014 #include <linux/ioctl.h>
0015 #include <linux/uaccess.h>
0016 #include <linux/greybus.h>
0017
0018 #include "firmware.h"
0019 #include "greybus_firmware.h"
0020
0021 #define FW_MGMT_TIMEOUT_MS 1000
0022
0023 struct fw_mgmt {
0024 struct device *parent;
0025 struct gb_connection *connection;
0026 struct kref kref;
0027 struct list_head node;
0028
0029
0030 struct ida id_map;
0031 struct mutex mutex;
0032 struct completion completion;
0033 struct cdev cdev;
0034 struct device *class_device;
0035 dev_t dev_num;
0036 unsigned int timeout_jiffies;
0037 bool disabled;
0038
0039
0040 bool mode_switch_started;
0041 bool intf_fw_loaded;
0042 u8 intf_fw_request_id;
0043 u8 intf_fw_status;
0044 u16 intf_fw_major;
0045 u16 intf_fw_minor;
0046
0047
0048 u8 backend_fw_request_id;
0049 u8 backend_fw_status;
0050 };
0051
0052
0053
0054
0055
0056 #define NUM_MINORS U8_MAX
0057
0058 static struct class *fw_mgmt_class;
0059 static dev_t fw_mgmt_dev_num;
0060 static DEFINE_IDA(fw_mgmt_minors_map);
0061 static LIST_HEAD(fw_mgmt_list);
0062 static DEFINE_MUTEX(list_mutex);
0063
0064 static void fw_mgmt_kref_release(struct kref *kref)
0065 {
0066 struct fw_mgmt *fw_mgmt = container_of(kref, struct fw_mgmt, kref);
0067
0068 ida_destroy(&fw_mgmt->id_map);
0069 kfree(fw_mgmt);
0070 }
0071
0072
0073
0074
0075
0076
0077 static void put_fw_mgmt(struct fw_mgmt *fw_mgmt)
0078 {
0079 kref_put(&fw_mgmt->kref, fw_mgmt_kref_release);
0080 }
0081
0082
0083 static struct fw_mgmt *get_fw_mgmt(struct cdev *cdev)
0084 {
0085 struct fw_mgmt *fw_mgmt;
0086
0087 mutex_lock(&list_mutex);
0088
0089 list_for_each_entry(fw_mgmt, &fw_mgmt_list, node) {
0090 if (&fw_mgmt->cdev == cdev) {
0091 kref_get(&fw_mgmt->kref);
0092 goto unlock;
0093 }
0094 }
0095
0096 fw_mgmt = NULL;
0097
0098 unlock:
0099 mutex_unlock(&list_mutex);
0100
0101 return fw_mgmt;
0102 }
0103
0104 static int fw_mgmt_interface_fw_version_operation(struct fw_mgmt *fw_mgmt,
0105 struct fw_mgmt_ioc_get_intf_version *fw_info)
0106 {
0107 struct gb_connection *connection = fw_mgmt->connection;
0108 struct gb_fw_mgmt_interface_fw_version_response response;
0109 int ret;
0110
0111 ret = gb_operation_sync(connection,
0112 GB_FW_MGMT_TYPE_INTERFACE_FW_VERSION, NULL, 0,
0113 &response, sizeof(response));
0114 if (ret) {
0115 dev_err(fw_mgmt->parent,
0116 "failed to get interface firmware version (%d)\n", ret);
0117 return ret;
0118 }
0119
0120 fw_info->major = le16_to_cpu(response.major);
0121 fw_info->minor = le16_to_cpu(response.minor);
0122
0123 strncpy(fw_info->firmware_tag, response.firmware_tag,
0124 GB_FIRMWARE_TAG_MAX_SIZE);
0125
0126
0127
0128
0129
0130 if (fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') {
0131 dev_err(fw_mgmt->parent,
0132 "fw-version: firmware-tag is not NULL terminated\n");
0133 fw_info->firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] = '\0';
0134 }
0135
0136 return 0;
0137 }
0138
0139 static int fw_mgmt_load_and_validate_operation(struct fw_mgmt *fw_mgmt,
0140 u8 load_method, const char *tag)
0141 {
0142 struct gb_fw_mgmt_load_and_validate_fw_request request;
0143 int ret;
0144
0145 if (load_method != GB_FW_LOAD_METHOD_UNIPRO &&
0146 load_method != GB_FW_LOAD_METHOD_INTERNAL) {
0147 dev_err(fw_mgmt->parent,
0148 "invalid load-method (%d)\n", load_method);
0149 return -EINVAL;
0150 }
0151
0152 request.load_method = load_method;
0153 strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_SIZE);
0154
0155
0156
0157
0158
0159 if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') {
0160 dev_err(fw_mgmt->parent, "load-and-validate: firmware-tag is not NULL terminated\n");
0161 return -EINVAL;
0162 }
0163
0164
0165 ret = ida_simple_get(&fw_mgmt->id_map, 1, 256, GFP_KERNEL);
0166 if (ret < 0) {
0167 dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n",
0168 ret);
0169 return ret;
0170 }
0171
0172 fw_mgmt->intf_fw_request_id = ret;
0173 fw_mgmt->intf_fw_loaded = false;
0174 request.request_id = ret;
0175
0176 ret = gb_operation_sync(fw_mgmt->connection,
0177 GB_FW_MGMT_TYPE_LOAD_AND_VALIDATE_FW, &request,
0178 sizeof(request), NULL, 0);
0179 if (ret) {
0180 ida_simple_remove(&fw_mgmt->id_map,
0181 fw_mgmt->intf_fw_request_id);
0182 fw_mgmt->intf_fw_request_id = 0;
0183 dev_err(fw_mgmt->parent,
0184 "load and validate firmware request failed (%d)\n",
0185 ret);
0186 return ret;
0187 }
0188
0189 return 0;
0190 }
0191
0192 static int fw_mgmt_interface_fw_loaded_operation(struct gb_operation *op)
0193 {
0194 struct gb_connection *connection = op->connection;
0195 struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection);
0196 struct gb_fw_mgmt_loaded_fw_request *request;
0197
0198
0199 if (!fw_mgmt->intf_fw_request_id) {
0200 dev_err(fw_mgmt->parent,
0201 "unexpected firmware loaded request received\n");
0202 return -ENODEV;
0203 }
0204
0205 if (op->request->payload_size != sizeof(*request)) {
0206 dev_err(fw_mgmt->parent, "illegal size of firmware loaded request (%zu != %zu)\n",
0207 op->request->payload_size, sizeof(*request));
0208 return -EINVAL;
0209 }
0210
0211 request = op->request->payload;
0212
0213
0214 if (request->request_id != fw_mgmt->intf_fw_request_id) {
0215 dev_err(fw_mgmt->parent, "invalid request id for firmware loaded request (%02u != %02u)\n",
0216 fw_mgmt->intf_fw_request_id, request->request_id);
0217 return -ENODEV;
0218 }
0219
0220 ida_simple_remove(&fw_mgmt->id_map, fw_mgmt->intf_fw_request_id);
0221 fw_mgmt->intf_fw_request_id = 0;
0222 fw_mgmt->intf_fw_status = request->status;
0223 fw_mgmt->intf_fw_major = le16_to_cpu(request->major);
0224 fw_mgmt->intf_fw_minor = le16_to_cpu(request->minor);
0225
0226 if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_FAILED)
0227 dev_err(fw_mgmt->parent,
0228 "failed to load interface firmware, status:%02x\n",
0229 fw_mgmt->intf_fw_status);
0230 else if (fw_mgmt->intf_fw_status == GB_FW_LOAD_STATUS_VALIDATION_FAILED)
0231 dev_err(fw_mgmt->parent,
0232 "failed to validate interface firmware, status:%02x\n",
0233 fw_mgmt->intf_fw_status);
0234 else
0235 fw_mgmt->intf_fw_loaded = true;
0236
0237 complete(&fw_mgmt->completion);
0238
0239 return 0;
0240 }
0241
0242 static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt,
0243 struct fw_mgmt_ioc_get_backend_version *fw_info)
0244 {
0245 struct gb_connection *connection = fw_mgmt->connection;
0246 struct gb_fw_mgmt_backend_fw_version_request request;
0247 struct gb_fw_mgmt_backend_fw_version_response response;
0248 int ret;
0249
0250 strncpy(request.firmware_tag, fw_info->firmware_tag,
0251 GB_FIRMWARE_TAG_MAX_SIZE);
0252
0253
0254
0255
0256
0257 if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') {
0258 dev_err(fw_mgmt->parent, "backend-version: firmware-tag is not NULL terminated\n");
0259 return -EINVAL;
0260 }
0261
0262 ret = gb_operation_sync(connection,
0263 GB_FW_MGMT_TYPE_BACKEND_FW_VERSION, &request,
0264 sizeof(request), &response, sizeof(response));
0265 if (ret) {
0266 dev_err(fw_mgmt->parent, "failed to get version of %s backend firmware (%d)\n",
0267 fw_info->firmware_tag, ret);
0268 return ret;
0269 }
0270
0271 fw_info->status = response.status;
0272
0273
0274 fw_info->major = 0;
0275 fw_info->minor = 0;
0276
0277 switch (fw_info->status) {
0278 case GB_FW_BACKEND_VERSION_STATUS_SUCCESS:
0279 fw_info->major = le16_to_cpu(response.major);
0280 fw_info->minor = le16_to_cpu(response.minor);
0281 break;
0282 case GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE:
0283 case GB_FW_BACKEND_VERSION_STATUS_RETRY:
0284 break;
0285 case GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED:
0286 dev_err(fw_mgmt->parent,
0287 "Firmware with tag %s is not supported by Interface\n",
0288 fw_info->firmware_tag);
0289 break;
0290 default:
0291 dev_err(fw_mgmt->parent, "Invalid status received: %u\n",
0292 fw_info->status);
0293 }
0294
0295 return 0;
0296 }
0297
0298 static int fw_mgmt_backend_fw_update_operation(struct fw_mgmt *fw_mgmt,
0299 char *tag)
0300 {
0301 struct gb_fw_mgmt_backend_fw_update_request request;
0302 int ret;
0303
0304 strncpy(request.firmware_tag, tag, GB_FIRMWARE_TAG_MAX_SIZE);
0305
0306
0307
0308
0309
0310 if (request.firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE - 1] != '\0') {
0311 dev_err(fw_mgmt->parent, "backend-update: firmware-tag is not NULL terminated\n");
0312 return -EINVAL;
0313 }
0314
0315
0316 ret = ida_simple_get(&fw_mgmt->id_map, 1, 256, GFP_KERNEL);
0317 if (ret < 0) {
0318 dev_err(fw_mgmt->parent, "failed to allocate request id (%d)\n",
0319 ret);
0320 return ret;
0321 }
0322
0323 fw_mgmt->backend_fw_request_id = ret;
0324 request.request_id = ret;
0325
0326 ret = gb_operation_sync(fw_mgmt->connection,
0327 GB_FW_MGMT_TYPE_BACKEND_FW_UPDATE, &request,
0328 sizeof(request), NULL, 0);
0329 if (ret) {
0330 ida_simple_remove(&fw_mgmt->id_map,
0331 fw_mgmt->backend_fw_request_id);
0332 fw_mgmt->backend_fw_request_id = 0;
0333 dev_err(fw_mgmt->parent,
0334 "backend %s firmware update request failed (%d)\n", tag,
0335 ret);
0336 return ret;
0337 }
0338
0339 return 0;
0340 }
0341
0342 static int fw_mgmt_backend_fw_updated_operation(struct gb_operation *op)
0343 {
0344 struct gb_connection *connection = op->connection;
0345 struct fw_mgmt *fw_mgmt = gb_connection_get_data(connection);
0346 struct gb_fw_mgmt_backend_fw_updated_request *request;
0347
0348
0349 if (!fw_mgmt->backend_fw_request_id) {
0350 dev_err(fw_mgmt->parent, "unexpected backend firmware updated request received\n");
0351 return -ENODEV;
0352 }
0353
0354 if (op->request->payload_size != sizeof(*request)) {
0355 dev_err(fw_mgmt->parent, "illegal size of backend firmware updated request (%zu != %zu)\n",
0356 op->request->payload_size, sizeof(*request));
0357 return -EINVAL;
0358 }
0359
0360 request = op->request->payload;
0361
0362
0363 if (request->request_id != fw_mgmt->backend_fw_request_id) {
0364 dev_err(fw_mgmt->parent, "invalid request id for backend firmware updated request (%02u != %02u)\n",
0365 fw_mgmt->backend_fw_request_id, request->request_id);
0366 return -ENODEV;
0367 }
0368
0369 ida_simple_remove(&fw_mgmt->id_map, fw_mgmt->backend_fw_request_id);
0370 fw_mgmt->backend_fw_request_id = 0;
0371 fw_mgmt->backend_fw_status = request->status;
0372
0373 if ((fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_SUCCESS) &&
0374 (fw_mgmt->backend_fw_status != GB_FW_BACKEND_FW_STATUS_RETRY))
0375 dev_err(fw_mgmt->parent,
0376 "failed to load backend firmware: %02x\n",
0377 fw_mgmt->backend_fw_status);
0378
0379 complete(&fw_mgmt->completion);
0380
0381 return 0;
0382 }
0383
0384
0385
0386 static int fw_mgmt_open(struct inode *inode, struct file *file)
0387 {
0388 struct fw_mgmt *fw_mgmt = get_fw_mgmt(inode->i_cdev);
0389
0390
0391 if (fw_mgmt) {
0392 file->private_data = fw_mgmt;
0393 return 0;
0394 }
0395
0396 return -ENODEV;
0397 }
0398
0399 static int fw_mgmt_release(struct inode *inode, struct file *file)
0400 {
0401 struct fw_mgmt *fw_mgmt = file->private_data;
0402
0403 put_fw_mgmt(fw_mgmt);
0404 return 0;
0405 }
0406
0407 static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd,
0408 void __user *buf)
0409 {
0410 struct fw_mgmt_ioc_get_intf_version intf_fw_info;
0411 struct fw_mgmt_ioc_get_backend_version backend_fw_info;
0412 struct fw_mgmt_ioc_intf_load_and_validate intf_load;
0413 struct fw_mgmt_ioc_backend_fw_update backend_update;
0414 unsigned int timeout;
0415 int ret;
0416
0417
0418 if (fw_mgmt->mode_switch_started)
0419 return -EBUSY;
0420
0421 switch (cmd) {
0422 case FW_MGMT_IOC_GET_INTF_FW:
0423 ret = fw_mgmt_interface_fw_version_operation(fw_mgmt,
0424 &intf_fw_info);
0425 if (ret)
0426 return ret;
0427
0428 if (copy_to_user(buf, &intf_fw_info, sizeof(intf_fw_info)))
0429 return -EFAULT;
0430
0431 return 0;
0432 case FW_MGMT_IOC_GET_BACKEND_FW:
0433 if (copy_from_user(&backend_fw_info, buf,
0434 sizeof(backend_fw_info)))
0435 return -EFAULT;
0436
0437 ret = fw_mgmt_backend_fw_version_operation(fw_mgmt,
0438 &backend_fw_info);
0439 if (ret)
0440 return ret;
0441
0442 if (copy_to_user(buf, &backend_fw_info,
0443 sizeof(backend_fw_info)))
0444 return -EFAULT;
0445
0446 return 0;
0447 case FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE:
0448 if (copy_from_user(&intf_load, buf, sizeof(intf_load)))
0449 return -EFAULT;
0450
0451 ret = fw_mgmt_load_and_validate_operation(fw_mgmt,
0452 intf_load.load_method, intf_load.firmware_tag);
0453 if (ret)
0454 return ret;
0455
0456 if (!wait_for_completion_timeout(&fw_mgmt->completion,
0457 fw_mgmt->timeout_jiffies)) {
0458 dev_err(fw_mgmt->parent, "timed out waiting for firmware load and validation to finish\n");
0459 return -ETIMEDOUT;
0460 }
0461
0462 intf_load.status = fw_mgmt->intf_fw_status;
0463 intf_load.major = fw_mgmt->intf_fw_major;
0464 intf_load.minor = fw_mgmt->intf_fw_minor;
0465
0466 if (copy_to_user(buf, &intf_load, sizeof(intf_load)))
0467 return -EFAULT;
0468
0469 return 0;
0470 case FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE:
0471 if (copy_from_user(&backend_update, buf,
0472 sizeof(backend_update)))
0473 return -EFAULT;
0474
0475 ret = fw_mgmt_backend_fw_update_operation(fw_mgmt,
0476 backend_update.firmware_tag);
0477 if (ret)
0478 return ret;
0479
0480 if (!wait_for_completion_timeout(&fw_mgmt->completion,
0481 fw_mgmt->timeout_jiffies)) {
0482 dev_err(fw_mgmt->parent, "timed out waiting for backend firmware update to finish\n");
0483 return -ETIMEDOUT;
0484 }
0485
0486 backend_update.status = fw_mgmt->backend_fw_status;
0487
0488 if (copy_to_user(buf, &backend_update, sizeof(backend_update)))
0489 return -EFAULT;
0490
0491 return 0;
0492 case FW_MGMT_IOC_SET_TIMEOUT_MS:
0493 if (get_user(timeout, (unsigned int __user *)buf))
0494 return -EFAULT;
0495
0496 if (!timeout) {
0497 dev_err(fw_mgmt->parent, "timeout can't be zero\n");
0498 return -EINVAL;
0499 }
0500
0501 fw_mgmt->timeout_jiffies = msecs_to_jiffies(timeout);
0502
0503 return 0;
0504 case FW_MGMT_IOC_MODE_SWITCH:
0505 if (!fw_mgmt->intf_fw_loaded) {
0506 dev_err(fw_mgmt->parent,
0507 "Firmware not loaded for mode-switch\n");
0508 return -EPERM;
0509 }
0510
0511
0512
0513
0514
0515
0516 fw_mgmt->mode_switch_started = true;
0517
0518 ret = gb_interface_request_mode_switch(fw_mgmt->connection->intf);
0519 if (ret) {
0520 dev_err(fw_mgmt->parent, "Mode-switch failed: %d\n",
0521 ret);
0522 fw_mgmt->mode_switch_started = false;
0523 return ret;
0524 }
0525
0526 return 0;
0527 default:
0528 return -ENOTTY;
0529 }
0530 }
0531
0532 static long fw_mgmt_ioctl_unlocked(struct file *file, unsigned int cmd,
0533 unsigned long arg)
0534 {
0535 struct fw_mgmt *fw_mgmt = file->private_data;
0536 struct gb_bundle *bundle = fw_mgmt->connection->bundle;
0537 int ret = -ENODEV;
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551 mutex_lock(&fw_mgmt->mutex);
0552 if (!fw_mgmt->disabled) {
0553 ret = gb_pm_runtime_get_sync(bundle);
0554 if (!ret) {
0555 ret = fw_mgmt_ioctl(fw_mgmt, cmd, (void __user *)arg);
0556 gb_pm_runtime_put_autosuspend(bundle);
0557 }
0558 }
0559 mutex_unlock(&fw_mgmt->mutex);
0560
0561 return ret;
0562 }
0563
0564 static const struct file_operations fw_mgmt_fops = {
0565 .owner = THIS_MODULE,
0566 .open = fw_mgmt_open,
0567 .release = fw_mgmt_release,
0568 .unlocked_ioctl = fw_mgmt_ioctl_unlocked,
0569 };
0570
0571 int gb_fw_mgmt_request_handler(struct gb_operation *op)
0572 {
0573 u8 type = op->type;
0574
0575 switch (type) {
0576 case GB_FW_MGMT_TYPE_LOADED_FW:
0577 return fw_mgmt_interface_fw_loaded_operation(op);
0578 case GB_FW_MGMT_TYPE_BACKEND_FW_UPDATED:
0579 return fw_mgmt_backend_fw_updated_operation(op);
0580 default:
0581 dev_err(&op->connection->bundle->dev,
0582 "unsupported request: %u\n", type);
0583 return -EINVAL;
0584 }
0585 }
0586
0587 int gb_fw_mgmt_connection_init(struct gb_connection *connection)
0588 {
0589 struct fw_mgmt *fw_mgmt;
0590 int ret, minor;
0591
0592 if (!connection)
0593 return 0;
0594
0595 fw_mgmt = kzalloc(sizeof(*fw_mgmt), GFP_KERNEL);
0596 if (!fw_mgmt)
0597 return -ENOMEM;
0598
0599 fw_mgmt->parent = &connection->bundle->dev;
0600 fw_mgmt->timeout_jiffies = msecs_to_jiffies(FW_MGMT_TIMEOUT_MS);
0601 fw_mgmt->connection = connection;
0602
0603 gb_connection_set_data(connection, fw_mgmt);
0604 init_completion(&fw_mgmt->completion);
0605 ida_init(&fw_mgmt->id_map);
0606 mutex_init(&fw_mgmt->mutex);
0607 kref_init(&fw_mgmt->kref);
0608
0609 mutex_lock(&list_mutex);
0610 list_add(&fw_mgmt->node, &fw_mgmt_list);
0611 mutex_unlock(&list_mutex);
0612
0613 ret = gb_connection_enable(connection);
0614 if (ret)
0615 goto err_list_del;
0616
0617 minor = ida_simple_get(&fw_mgmt_minors_map, 0, NUM_MINORS, GFP_KERNEL);
0618 if (minor < 0) {
0619 ret = minor;
0620 goto err_connection_disable;
0621 }
0622
0623
0624 fw_mgmt->dev_num = MKDEV(MAJOR(fw_mgmt_dev_num), minor);
0625 cdev_init(&fw_mgmt->cdev, &fw_mgmt_fops);
0626
0627 ret = cdev_add(&fw_mgmt->cdev, fw_mgmt->dev_num, 1);
0628 if (ret)
0629 goto err_remove_ida;
0630
0631
0632 fw_mgmt->class_device = device_create(fw_mgmt_class, fw_mgmt->parent,
0633 fw_mgmt->dev_num, NULL,
0634 "gb-fw-mgmt-%d", minor);
0635 if (IS_ERR(fw_mgmt->class_device)) {
0636 ret = PTR_ERR(fw_mgmt->class_device);
0637 goto err_del_cdev;
0638 }
0639
0640 return 0;
0641
0642 err_del_cdev:
0643 cdev_del(&fw_mgmt->cdev);
0644 err_remove_ida:
0645 ida_simple_remove(&fw_mgmt_minors_map, minor);
0646 err_connection_disable:
0647 gb_connection_disable(connection);
0648 err_list_del:
0649 mutex_lock(&list_mutex);
0650 list_del(&fw_mgmt->node);
0651 mutex_unlock(&list_mutex);
0652
0653 put_fw_mgmt(fw_mgmt);
0654
0655 return ret;
0656 }
0657
0658 void gb_fw_mgmt_connection_exit(struct gb_connection *connection)
0659 {
0660 struct fw_mgmt *fw_mgmt;
0661
0662 if (!connection)
0663 return;
0664
0665 fw_mgmt = gb_connection_get_data(connection);
0666
0667 device_destroy(fw_mgmt_class, fw_mgmt->dev_num);
0668 cdev_del(&fw_mgmt->cdev);
0669 ida_simple_remove(&fw_mgmt_minors_map, MINOR(fw_mgmt->dev_num));
0670
0671
0672
0673
0674
0675 mutex_lock(&fw_mgmt->mutex);
0676 fw_mgmt->disabled = true;
0677 mutex_unlock(&fw_mgmt->mutex);
0678
0679
0680 gb_connection_disable(fw_mgmt->connection);
0681
0682
0683 mutex_lock(&list_mutex);
0684 list_del(&fw_mgmt->node);
0685 mutex_unlock(&list_mutex);
0686
0687
0688
0689
0690
0691
0692 put_fw_mgmt(fw_mgmt);
0693 }
0694
0695 int fw_mgmt_init(void)
0696 {
0697 int ret;
0698
0699 fw_mgmt_class = class_create(THIS_MODULE, "gb_fw_mgmt");
0700 if (IS_ERR(fw_mgmt_class))
0701 return PTR_ERR(fw_mgmt_class);
0702
0703 ret = alloc_chrdev_region(&fw_mgmt_dev_num, 0, NUM_MINORS,
0704 "gb_fw_mgmt");
0705 if (ret)
0706 goto err_remove_class;
0707
0708 return 0;
0709
0710 err_remove_class:
0711 class_destroy(fw_mgmt_class);
0712 return ret;
0713 }
0714
0715 void fw_mgmt_exit(void)
0716 {
0717 unregister_chrdev_region(fw_mgmt_dev_num, NUM_MINORS);
0718 class_destroy(fw_mgmt_class);
0719 ida_destroy(&fw_mgmt_minors_map);
0720 }