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