cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ctdaio.c (17265B)


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