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