1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 4 * 5 * @File ctdaio.c 6 * 7 * @Brief 8 * This file contains the implementation of Digital Audio Input Output 9 * resource management object. 10 * 11 * @Author Liu Chun 12 * @Date May 23 2008 13 */ 14 15 #include "ctdaio.h" 16 #include "cthardware.h" 17 #include "ctimap.h" 18 #include <linux/slab.h> 19 #include <linux/kernel.h> 20 21 struct daio_usage { 22 unsigned short data; 23 }; 24 25 struct daio_rsc_idx { 26 unsigned short left; 27 unsigned short right; 28 }; 29 30 static const struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = { 31 [LINEO1] = {.left = 0x00, .right = 0x01}, 32 [LINEO2] = {.left = 0x18, .right = 0x19}, 33 [LINEO3] = {.left = 0x08, .right = 0x09}, 34 [LINEO4] = {.left = 0x10, .right = 0x11}, 35 [LINEIM] = {.left = 0x1b5, .right = 0x1bd}, 36 [SPDIFOO] = {.left = 0x20, .right = 0x21}, 37 [SPDIFIO] = {.left = 0x15, .right = 0x1d}, 38 [SPDIFI1] = {.left = 0x95, .right = 0x9d}, 39 }; 40 41 static const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { 42 [LINEO1] = {.left = 0x40, .right = 0x41}, 43 [LINEO2] = {.left = 0x60, .right = 0x61}, 44 [LINEO3] = {.left = 0x50, .right = 0x51}, 45 [LINEO4] = {.left = 0x70, .right = 0x71}, 46 [LINEIM] = {.left = 0x45, .right = 0xc5}, 47 [MIC] = {.left = 0x55, .right = 0xd5}, 48 [RCA] = {.left = 0x30, .right = 0x31}, 49 [SPDIFOO] = {.left = 0x00, .right = 0x01}, 50 [SPDIFIO] = {.left = 0x05, .right = 0x85}, 51 }; 52 53 static void daio_master(struct rsc *rsc) 54 { 55 /* Actually, this is not the resource index of DAIO. 56 * For DAO, it is the input mapper index. And, for DAI, 57 * it is the output time-slot index. */ 58 rsc->conj = rsc->idx; 59 } 60 61 static int daio_index(const struct rsc *rsc) 62 { 63 return rsc->conj; 64 } 65 66 static void daio_out_next_conj(struct rsc *rsc) 67 { 68 rsc->conj += 2; 69 } 70 71 static void daio_in_next_conj_20k1(struct rsc *rsc) 72 { 73 rsc->conj += 0x200; 74 } 75 76 static void daio_in_next_conj_20k2(struct rsc *rsc) 77 { 78 rsc->conj += 0x100; 79 } 80 81 static const struct rsc_ops daio_out_rsc_ops = { 82 .master = daio_master, 83 .next_conj = daio_out_next_conj, 84 .index = daio_index, 85 .output_slot = NULL, 86 }; 87 88 static const struct rsc_ops daio_in_rsc_ops_20k1 = { 89 .master = daio_master, 90 .next_conj = daio_in_next_conj_20k1, 91 .index = NULL, 92 .output_slot = daio_index, 93 }; 94 95 static const struct rsc_ops daio_in_rsc_ops_20k2 = { 96 .master = daio_master, 97 .next_conj = daio_in_next_conj_20k2, 98 .index = NULL, 99 .output_slot = daio_index, 100 }; 101 102 static int daio_device_index(enum DAIOTYP type, struct hw *hw) 103 { 104 switch (hw->chip_type) { 105 case ATC20K1: 106 switch (type) { 107 case SPDIFOO: return 0; 108 case SPDIFIO: return 0; 109 case SPDIFI1: return 1; 110 case LINEO1: return 4; 111 case LINEO2: return 7; 112 case LINEO3: return 5; 113 case LINEO4: return 6; 114 case LINEIM: return 7; 115 default: 116 pr_err("ctxfi: Invalid type %d for hw20k1\n", type); 117 return -EINVAL; 118 } 119 case ATC20K2: 120 switch (type) { 121 case SPDIFOO: return 0; 122 case SPDIFIO: return 0; 123 case SPDIFI1: return 1; 124 case LINEO1: return 4; 125 case LINEO2: return 7; 126 case LINEO3: return 5; 127 case LINEO4: return 6; 128 case LINEIM: return 4; 129 case MIC: return 5; 130 case RCA: return 3; 131 default: 132 pr_err("ctxfi: Invalid type %d for hw20k2\n", type); 133 return -EINVAL; 134 } 135 default: 136 pr_err("ctxfi: Invalid chip type %d\n", hw->chip_type); 137 return -EINVAL; 138 } 139 } 140 141 static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc); 142 143 static int dao_spdif_get_spos(struct dao *dao, unsigned int *spos) 144 { 145 dao->hw->dao_get_spos(dao->ctrl_blk, spos); 146 return 0; 147 } 148 149 static int dao_spdif_set_spos(struct dao *dao, unsigned int spos) 150 { 151 dao->hw->dao_set_spos(dao->ctrl_blk, spos); 152 return 0; 153 } 154 155 static int dao_commit_write(struct dao *dao) 156 { 157 int idx = daio_device_index(dao->daio.type, dao->hw); 158 159 if (idx < 0) 160 return idx; 161 dao->hw->dao_commit_write(dao->hw, idx, dao->ctrl_blk); 162 return 0; 163 } 164 165 static int dao_set_left_input(struct dao *dao, struct rsc *input) 166 { 167 struct imapper *entry; 168 struct daio *daio = &dao->daio; 169 int i; 170 171 entry = kzalloc_objs(*entry, daio->rscl.msr); 172 if (!entry) 173 return -ENOMEM; 174 175 dao->ops->clear_left_input(dao); 176 /* Program master and conjugate resources */ 177 input->ops->master(input); 178 daio->rscl.ops->master(&daio->rscl); 179 for (i = 0; i < daio->rscl.msr; i++, entry++) { 180 entry->slot = input->ops->output_slot(input); 181 entry->user = entry->addr = daio->rscl.ops->index(&daio->rscl); 182 dao->mgr->imap_add(dao->mgr, entry); 183 dao->imappers[i] = entry; 184 185 input->ops->next_conj(input); 186 daio->rscl.ops->next_conj(&daio->rscl); 187 } 188 input->ops->master(input); 189 daio->rscl.ops->master(&daio->rscl); 190 191 return 0; 192 } 193 194 static int dao_set_right_input(struct dao *dao, struct rsc *input) 195 { 196 struct imapper *entry; 197 struct daio *daio = &dao->daio; 198 int i; 199 200 entry = kzalloc_objs(*entry, daio->rscr.msr); 201 if (!entry) 202 return -ENOMEM; 203 204 dao->ops->clear_right_input(dao); 205 /* Program master and conjugate resources */ 206 input->ops->master(input); 207 daio->rscr.ops->master(&daio->rscr); 208 for (i = 0; i < daio->rscr.msr; i++, entry++) { 209 entry->slot = input->ops->output_slot(input); 210 entry->user = entry->addr = daio->rscr.ops->index(&daio->rscr); 211 dao->mgr->imap_add(dao->mgr, entry); 212 dao->imappers[daio->rscl.msr + i] = entry; 213 214 input->ops->next_conj(input); 215 daio->rscr.ops->next_conj(&daio->rscr); 216 } 217 input->ops->master(input); 218 daio->rscr.ops->master(&daio->rscr); 219 220 return 0; 221 } 222 223 static int dao_clear_input(struct dao *dao, unsigned int start, unsigned int end) 224 { 225 unsigned int i; 226 227 if (!dao->imappers[start]) 228 return 0; 229 for (i = start; i < end; i++) { 230 dao->mgr->imap_delete(dao->mgr, dao->imappers[i]); 231 dao->imappers[i] = NULL; 232 } 233 234 return 0; 235 } 236 237 238 static int dao_clear_left_input(struct dao *dao) 239 { 240 return dao_clear_input(dao, 0, dao->daio.rscl.msr); 241 } 242 243 static int dao_clear_right_input(struct dao *dao) 244 { 245 return dao_clear_input(dao, dao->daio.rscl.msr, 246 dao->daio.rscl.msr + dao->daio.rscr.msr); 247 } 248 249 static const struct dao_rsc_ops dao_ops = { 250 .set_spos = dao_spdif_set_spos, 251 .commit_write = dao_commit_write, 252 .get_spos = dao_spdif_get_spos, 253 .reinit = dao_rsc_reinit, 254 .set_left_input = dao_set_left_input, 255 .set_right_input = dao_set_right_input, 256 .clear_left_input = dao_clear_left_input, 257 .clear_right_input = dao_clear_right_input, 258 }; 259 260 static int dai_set_srt_srcl(struct dai *dai, struct rsc *src) 261 { 262 src->ops->master(src); 263 dai->hw->dai_srt_set_srcm(dai->ctrl_blk, src->ops->index(src)); 264 return 0; 265 } 266 267 static int dai_set_srt_srcr(struct dai *dai, struct rsc *src) 268 { 269 src->ops->master(src); 270 dai->hw->dai_srt_set_srco(dai->ctrl_blk, src->ops->index(src)); 271 return 0; 272 } 273 274 static int dai_set_srt_msr(struct dai *dai, unsigned int msr) 275 { 276 unsigned int rsr; 277 278 for (rsr = 0; msr > 1; msr >>= 1) 279 rsr++; 280 281 dai->hw->dai_srt_set_rsr(dai->ctrl_blk, rsr); 282 return 0; 283 } 284 285 static int dai_set_enb_src(struct dai *dai, unsigned int enb) 286 { 287 dai->hw->dai_srt_set_ec(dai->ctrl_blk, enb); 288 return 0; 289 } 290 291 static int dai_set_enb_srt(struct dai *dai, unsigned int enb) 292 { 293 dai->hw->dai_srt_set_et(dai->ctrl_blk, enb); 294 return 0; 295 } 296 297 static int dai_commit_write(struct dai *dai) 298 { 299 int idx = daio_device_index(dai->daio.type, dai->hw); 300 301 if (idx < 0) 302 return idx; 303 dai->hw->dai_commit_write(dai->hw, idx, dai->ctrl_blk); 304 return 0; 305 } 306 307 static const struct dai_rsc_ops dai_ops = { 308 .set_srt_srcl = dai_set_srt_srcl, 309 .set_srt_srcr = dai_set_srt_srcr, 310 .set_srt_msr = dai_set_srt_msr, 311 .set_enb_src = dai_set_enb_src, 312 .set_enb_srt = dai_set_enb_srt, 313 .commit_write = dai_commit_write, 314 }; 315 316 static int daio_rsc_init(struct daio *daio, 317 const struct daio_desc *desc, 318 struct hw *hw) 319 { 320 int err; 321 unsigned int idx_l, idx_r; 322 323 switch (hw->chip_type) { 324 case ATC20K1: 325 idx_l = idx_20k1[desc->type].left; 326 idx_r = idx_20k1[desc->type].right; 327 break; 328 case ATC20K2: 329 idx_l = idx_20k2[desc->type].left; 330 idx_r = idx_20k2[desc->type].right; 331 break; 332 default: 333 return -EINVAL; 334 } 335 err = rsc_init(&daio->rscl, idx_l, DAIO, desc->msr, hw); 336 if (err) 337 return err; 338 339 err = rsc_init(&daio->rscr, idx_r, DAIO, desc->msr, hw); 340 if (err) 341 goto error1; 342 343 /* Set daio->rscl/r->ops to daio specific ones */ 344 if (desc->output) { 345 daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops; 346 } else { 347 switch (hw->chip_type) { 348 case ATC20K1: 349 daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1; 350 break; 351 case ATC20K2: 352 daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k2; 353 break; 354 default: 355 break; 356 } 357 } 358 daio->type = desc->type; 359 daio->output = desc->output; 360 361 return 0; 362 363 error1: 364 rsc_uninit(&daio->rscl); 365 return err; 366 } 367 368 static int daio_rsc_uninit(struct daio *daio) 369 { 370 rsc_uninit(&daio->rscl); 371 rsc_uninit(&daio->rscr); 372 373 return 0; 374 } 375 376 static int dao_rsc_init(struct dao *dao, 377 const struct daio_desc *desc, 378 struct daio_mgr *mgr) 379 { 380 struct hw *hw = mgr->mgr.hw; 381 unsigned int conf; 382 int idx, err; 383 384 err = daio_rsc_init(&dao->daio, desc, mgr->mgr.hw); 385 if (err) 386 return err; 387 388 dao->imappers = kzalloc(array3_size(sizeof(void *), desc->msr, 2), 389 GFP_KERNEL); 390 if (!dao->imappers) { 391 err = -ENOMEM; 392 goto error1; 393 } 394 dao->ops = &dao_ops; 395 dao->mgr = mgr; 396 dao->hw = hw; 397 err = hw->dao_get_ctrl_blk(&dao->ctrl_blk); 398 if (err) 399 goto error2; 400 401 idx = daio_device_index(dao->daio.type, hw); 402 if (idx < 0) { 403 err = idx; 404 goto error2; 405 } 406 407 hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, idx); 408 hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); 409 410 conf = (desc->msr & 0x7) | (desc->passthru << 3); 411 hw->daio_mgr_dao_init(hw, mgr->mgr.ctrl_blk, idx, conf); 412 hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, idx); 413 hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); 414 415 return 0; 416 417 error2: 418 kfree(dao->imappers); 419 dao->imappers = NULL; 420 error1: 421 daio_rsc_uninit(&dao->daio); 422 return err; 423 } 424 425 static int dao_rsc_uninit(struct dao *dao) 426 { 427 if (dao->imappers) { 428 if (dao->imappers[0]) 429 dao_clear_left_input(dao); 430 431 if (dao->imappers[dao->daio.rscl.msr]) 432 dao_clear_right_input(dao); 433 434 kfree(dao->imappers); 435 dao->imappers = NULL; 436 } 437 dao->hw->dao_put_ctrl_blk(dao->ctrl_blk); 438 dao->hw = dao->ctrl_blk = NULL; 439 daio_rsc_uninit(&dao->daio); 440 441 return 0; 442 } 443 444 static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc) 445 { 446 struct daio_mgr *mgr = dao->mgr; 447 struct daio_desc dsc = {0}; 448 449 dsc.type = dao->daio.type; 450 dsc.msr = desc->msr; 451 dsc.passthru = desc->passthru; 452 dsc.output = dao->daio.output; 453 dao_rsc_uninit(dao); 454 return dao_rsc_init(dao, &dsc, mgr); 455 } 456 457 static int dai_rsc_init(struct dai *dai, 458 const struct daio_desc *desc, 459 struct daio_mgr *mgr) 460 { 461 int idx, err; 462 struct hw *hw = mgr->mgr.hw; 463 unsigned int rsr, msr; 464 465 err = daio_rsc_init(&dai->daio, desc, mgr->mgr.hw); 466 if (err) 467 return err; 468 469 dai->ops = &dai_ops; 470 dai->hw = mgr->mgr.hw; 471 err = hw->dai_get_ctrl_blk(&dai->ctrl_blk); 472 if (err) 473 goto error1; 474 475 idx = daio_device_index(dai->daio.type, dai->hw); 476 if (idx < 0) { 477 err = idx; 478 goto error1; 479 } 480 481 for (rsr = 0, msr = desc->msr; msr > 1; msr >>= 1) 482 rsr++; 483 484 hw->dai_srt_set_rsr(dai->ctrl_blk, rsr); 485 hw->dai_srt_set_drat(dai->ctrl_blk, 0); 486 /* default to disabling control of a SRC */ 487 hw->dai_srt_set_ec(dai->ctrl_blk, 0); 488 hw->dai_srt_set_et(dai->ctrl_blk, 0); /* default to disabling SRT */ 489 hw->dai_commit_write(hw, idx, dai->ctrl_blk); 490 491 return 0; 492 493 error1: 494 daio_rsc_uninit(&dai->daio); 495 return err; 496 } 497 498 static int dai_rsc_uninit(struct dai *dai) 499 { 500 dai->hw->dai_put_ctrl_blk(dai->ctrl_blk); 501 dai->hw = dai->ctrl_blk = NULL; 502 daio_rsc_uninit(&dai->daio); 503 return 0; 504 } 505 506 static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) 507 { 508 if (((struct daio_usage *)mgr->rscs)->data & (0x1 << type)) 509 return -ENOENT; 510 511 ((struct daio_usage *)mgr->rscs)->data |= (0x1 << type); 512 513 return 0; 514 } 515 516 static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) 517 { 518 ((struct daio_usage *)mgr->rscs)->data &= ~(0x1 << type); 519 520 return 0; 521 } 522 523 static int get_daio_rsc(struct daio_mgr *mgr, 524 const struct daio_desc *desc, 525 struct daio **rdaio) 526 { 527 int err; 528 529 *rdaio = NULL; 530 531 /* Check whether there are sufficient daio resources to meet request. */ 532 scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { 533 err = daio_mgr_get_rsc(&mgr->mgr, desc->type); 534 } 535 if (err) { 536 dev_err(mgr->card->dev, 537 "Can't meet DAIO resource request!\n"); 538 return err; 539 } 540 541 err = -ENOMEM; 542 /* Allocate mem for daio resource */ 543 if (desc->output) { 544 struct dao *dao = kzalloc(sizeof(*dao), GFP_KERNEL); 545 if (!dao) 546 goto error; 547 548 err = dao_rsc_init(dao, desc, mgr); 549 if (err) { 550 kfree(dao); 551 goto error; 552 } 553 554 *rdaio = &dao->daio; 555 } else { 556 struct dai *dai = kzalloc(sizeof(*dai), GFP_KERNEL); 557 if (!dai) 558 goto error; 559 560 err = dai_rsc_init(dai, desc, mgr); 561 if (err) { 562 kfree(dai); 563 goto error; 564 } 565 566 *rdaio = &dai->daio; 567 } 568 569 mgr->daio_enable(mgr, *rdaio); 570 mgr->commit_write(mgr); 571 572 return 0; 573 574 error: 575 scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { 576 daio_mgr_put_rsc(&mgr->mgr, desc->type); 577 } 578 return err; 579 } 580 581 static int put_daio_rsc(struct daio_mgr *mgr, struct daio *daio) 582 { 583 mgr->daio_disable(mgr, daio); 584 mgr->commit_write(mgr); 585 586 scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { 587 daio_mgr_put_rsc(&mgr->mgr, daio->type); 588 } 589 590 if (daio->output) { 591 dao_rsc_uninit(container_of(daio, struct dao, daio)); 592 kfree(container_of(daio, struct dao, daio)); 593 } else { 594 dai_rsc_uninit(container_of(daio, struct dai, daio)); 595 kfree(container_of(daio, struct dai, daio)); 596 } 597 598 return 0; 599 } 600 601 static int daio_mgr_enb_daio(struct daio_mgr *mgr, struct daio *daio) 602 { 603 struct hw *hw = mgr->mgr.hw; 604 int idx = daio_device_index(daio->type, hw); 605 606 if (idx < 0) 607 return idx; 608 if (daio->output) 609 hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, idx); 610 else 611 hw->daio_mgr_enb_dai(mgr->mgr.ctrl_blk, idx); 612 return 0; 613 } 614 615 static int daio_mgr_dsb_daio(struct daio_mgr *mgr, struct daio *daio) 616 { 617 struct hw *hw = mgr->mgr.hw; 618 int idx = daio_device_index(daio->type, hw); 619 620 if (idx < 0) 621 return idx; 622 if (daio->output) 623 hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, idx); 624 else 625 hw->daio_mgr_dsb_dai(mgr->mgr.ctrl_blk, idx); 626 return 0; 627 } 628 629 static int daio_map_op(void *data, struct imapper *entry) 630 { 631 struct rsc_mgr *mgr = &((struct daio_mgr *)data)->mgr; 632 struct hw *hw = mgr->hw; 633 634 hw->daio_mgr_set_imaparc(mgr->ctrl_blk, entry->slot); 635 hw->daio_mgr_set_imapnxt(mgr->ctrl_blk, entry->next); 636 hw->daio_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr); 637 hw->daio_mgr_commit_write(mgr->hw, mgr->ctrl_blk); 638 639 return 0; 640 } 641 642 static int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry) 643 { 644 guard(spinlock_irqsave)(&mgr->imap_lock); 645 if (!entry->addr && mgr->init_imap_added) { 646 input_mapper_delete(&mgr->imappers, mgr->init_imap, 647 daio_map_op, mgr); 648 mgr->init_imap_added = 0; 649 } 650 return input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr); 651 } 652 653 static int daio_imap_delete(struct daio_mgr *mgr, struct imapper *entry) 654 { 655 int err; 656 657 guard(spinlock_irqsave)(&mgr->imap_lock); 658 err = input_mapper_delete(&mgr->imappers, entry, daio_map_op, mgr); 659 if (list_empty(&mgr->imappers)) { 660 input_mapper_add(&mgr->imappers, mgr->init_imap, 661 daio_map_op, mgr); 662 mgr->init_imap_added = 1; 663 } 664 665 return err; 666 } 667 668 static int daio_mgr_commit_write(struct daio_mgr *mgr) 669 { 670 struct hw *hw = mgr->mgr.hw; 671 672 hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); 673 return 0; 674 } 675 676 int daio_mgr_create(struct hw *hw, void **rdaio_mgr) 677 { 678 int err, i; 679 struct daio_mgr *daio_mgr; 680 struct imapper *entry; 681 682 *rdaio_mgr = NULL; 683 daio_mgr = kzalloc_obj(*daio_mgr); 684 if (!daio_mgr) 685 return -ENOMEM; 686 687 err = rsc_mgr_init(&daio_mgr->mgr, DAIO, NUM_DAIOTYP, hw); 688 if (err) 689 goto error1; 690 691 spin_lock_init(&daio_mgr->mgr_lock); 692 spin_lock_init(&daio_mgr->imap_lock); 693 INIT_LIST_HEAD(&daio_mgr->imappers); 694 entry = kzalloc_obj(*entry); 695 if (!entry) { 696 err = -ENOMEM; 697 goto error2; 698 } 699 entry->slot = entry->addr = entry->next = entry->user = 0; 700 list_add(&entry->list, &daio_mgr->imappers); 701 daio_mgr->init_imap = entry; 702 daio_mgr->init_imap_added = 1; 703 704 daio_mgr->get_daio = get_daio_rsc; 705 daio_mgr->put_daio = put_daio_rsc; 706 daio_mgr->daio_enable = daio_mgr_enb_daio; 707 daio_mgr->daio_disable = daio_mgr_dsb_daio; 708 daio_mgr->imap_add = daio_imap_add; 709 daio_mgr->imap_delete = daio_imap_delete; 710 daio_mgr->commit_write = daio_mgr_commit_write; 711 daio_mgr->card = hw->card; 712 713 for (i = 0; i < 8; i++) { 714 hw->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i); 715 hw->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i); 716 } 717 hw->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk); 718 719 *rdaio_mgr = daio_mgr; 720 721 return 0; 722 723 error2: 724 rsc_mgr_uninit(&daio_mgr->mgr); 725 error1: 726 kfree(daio_mgr); 727 return err; 728 } 729 730 int daio_mgr_destroy(void *ptr) 731 { 732 struct daio_mgr *daio_mgr = ptr; 733 734 /* free daio input mapper list */ 735 scoped_guard(spinlock_irqsave, &daio_mgr->imap_lock) { 736 free_input_mapper_list(&daio_mgr->imappers); 737 } 738 739 rsc_mgr_uninit(&daio_mgr->mgr); 740 kfree(daio_mgr); 741 742 return 0; 743 } 744 745