/*
 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
 * All rights reserved
 * www.brocade.com
 *
 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License (GPL) Version 2 as
 * published by the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

#include <bfa.h>

BFA_TRC_FILE(HAL, SGPG);
BFA_MODULE(sgpg);

/**
 *  bfa_sgpg_mod BFA SGPG Mode module
 */

/**
 * Compute and return memory needed by FCP(im) module.
 */
static void
bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
		u32 *dm_len)
{
	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;

	*km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
	*dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
}


static void
bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
		    struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
{
	struct bfa_sgpg_mod_s	*mod = BFA_SGPG_MOD(bfa);
	int				i;
	struct bfa_sgpg_s		*hsgpg;
	struct bfi_sgpg_s 	*sgpg;
	u64		align_len;

	union {
		u64        pa;
		union bfi_addr_u      addr;
	} sgpg_pa;

	INIT_LIST_HEAD(&mod->sgpg_q);
	INIT_LIST_HEAD(&mod->sgpg_wait_q);

	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);

	mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
	mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
	align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
	mod->sgpg_arr_pa += align_len;
	mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
						align_len);
	mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
						align_len);

	hsgpg = mod->hsgpg_arr;
	sgpg = mod->sgpg_arr;
	sgpg_pa.pa = mod->sgpg_arr_pa;
	mod->free_sgpgs = mod->num_sgpgs;

	bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));

	for (i = 0; i < mod->num_sgpgs; i++) {
		bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
		bfa_os_memset(sgpg, 0, sizeof(*sgpg));

		hsgpg->sgpg = sgpg;
		hsgpg->sgpg_pa = sgpg_pa.addr;
		list_add_tail(&hsgpg->qe, &mod->sgpg_q);

		hsgpg++;
		sgpg++;
		sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
	}

	bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
	bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
	bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
}

static void
bfa_sgpg_initdone(struct bfa_s *bfa)
{
}

static void
bfa_sgpg_detach(struct bfa_s *bfa)
{
}

static void
bfa_sgpg_start(struct bfa_s *bfa)
{
}

static void
bfa_sgpg_stop(struct bfa_s *bfa)
{
}

static void
bfa_sgpg_iocdisable(struct bfa_s *bfa)
{
}



/**
 *  bfa_sgpg_public BFA SGPG public functions
 */

bfa_status_t
bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
{
	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
	struct bfa_sgpg_s *hsgpg;
	int             i;

	bfa_trc_fp(bfa, nsgpgs);

	if (mod->free_sgpgs < nsgpgs)
		return BFA_STATUS_ENOMEM;

	for (i = 0; i < nsgpgs; i++) {
		bfa_q_deq(&mod->sgpg_q, &hsgpg);
		bfa_assert(hsgpg);
		list_add_tail(&hsgpg->qe, sgpg_q);
	}

	mod->free_sgpgs -= nsgpgs;
	return BFA_STATUS_OK;
}

void
bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
{
	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
	struct bfa_sgpg_wqe_s *wqe;

	bfa_trc_fp(bfa, nsgpg);

	mod->free_sgpgs += nsgpg;
	bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);

	list_splice_tail_init(sgpg_q, &mod->sgpg_q);

	if (list_empty(&mod->sgpg_wait_q))
		return;

	/**
	 * satisfy as many waiting requests as possible
	 */
	do {
		wqe = bfa_q_first(&mod->sgpg_wait_q);
		if (mod->free_sgpgs < wqe->nsgpg)
			nsgpg = mod->free_sgpgs;
		else
			nsgpg = wqe->nsgpg;
		bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
		wqe->nsgpg -= nsgpg;
		if (wqe->nsgpg == 0) {
			list_del(&wqe->qe);
			wqe->cbfn(wqe->cbarg);
		}
	} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
}

void
bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
{
	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);

	bfa_assert(nsgpg > 0);
	bfa_assert(nsgpg > mod->free_sgpgs);

	wqe->nsgpg_total = wqe->nsgpg = nsgpg;

	/**
	 * allocate any left to this one first
	 */
	if (mod->free_sgpgs) {
		/**
		 * no one else is waiting for SGPG
		 */
		bfa_assert(list_empty(&mod->sgpg_wait_q));
		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
		wqe->nsgpg -= mod->free_sgpgs;
		mod->free_sgpgs = 0;
	}

	list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
}

void
bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
{
	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);

	bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
	list_del(&wqe->qe);

	if (wqe->nsgpg_total != wqe->nsgpg)
		bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
				   wqe->nsgpg_total - wqe->nsgpg);
}

void
bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
		   void *cbarg)
{
	INIT_LIST_HEAD(&wqe->sgpg_q);
	wqe->cbfn = cbfn;
	wqe->cbarg = cbarg;
}


