FILE
ctdaio.c
File preview with syntax highlighting.
linux-6.19.14/sound/pci/ctxfi/ctdaio.c
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 21struct daio_usage { 22 unsigned short data; 23}; 24 25struct daio_rsc_idx { 26 unsigned short left; 27 unsigned short right; 28}; 29 30static 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 41static 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 53static 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 61static int daio_index(const struct rsc *rsc) 62{ 63 return rsc->conj; 64} 65 66static void daio_out_next_conj(struct rsc *rsc) 67{ 68 rsc->conj += 2; 69} 70 71static void daio_in_next_conj_20k1(struct rsc *rsc) 72{ 73 rsc->conj += 0x200; 74} 75 76static void daio_in_next_conj_20k2(struct rsc *rsc) 77{ 78 rsc->conj += 0x100; 79} 80 81static 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 88static 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 95static 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 102static 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 141static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc); 142 143static 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 149static 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 155static 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 165static 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 = kcalloc(daio->rscl.msr, sizeof(*entry), GFP_KERNEL); 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 194static 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 = kcalloc(daio->rscr.msr, sizeof(*entry), GFP_KERNEL); 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 223static 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 238static int dao_clear_left_input(struct dao *dao) 239{ 240 return dao_clear_input(dao, 0, dao->daio.rscl.msr); 241} 242 243static 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 249static 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 260static 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 267static 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 274static 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 285static 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 291static 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 297static 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 307static 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 316static 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 363error1: 364 rsc_uninit(&daio->rscl); 365 return err; 366} 367 368static int daio_rsc_uninit(struct daio *daio) 369{ 370 rsc_uninit(&daio->rscl); 371 rsc_uninit(&daio->rscr); 372 373 return 0; 374} 375 376static 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 417error2: 418 kfree(dao->imappers); 419 dao->imappers = NULL; 420error1: 421 daio_rsc_uninit(&dao->daio); 422 return err; 423} 424 425static 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 444static 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 457static 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 493error1: 494 daio_rsc_uninit(&dai->daio); 495 return err; 496} 497 498static 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 506static 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 516static 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 523static 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 574error: 575 scoped_guard(spinlock_irqsave, &mgr->mgr_lock) { 576 daio_mgr_put_rsc(&mgr->mgr, desc->type); 577 } 578 return err; 579} 580 581static 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 601static 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 615static 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 629static 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 642static 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 653static 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 668static 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 676int 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(sizeof(*daio_mgr), GFP_KERNEL); 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(sizeof(*entry), GFP_KERNEL); 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 723error2: 724 rsc_mgr_uninit(&daio_mgr->mgr); 725error1: 726 kfree(daio_mgr); 727 return err; 728} 729 730int 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
~/
Read-only file preview.