/*
 * 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.
 */

/**
 *  bfa_uf.c BFA unsolicited frame receive implementation
 */

#include <bfa.h>
#include <bfa_svc.h>
#include <bfi/bfi_uf.h>
#include <cs/bfa_debug.h>

BFA_TRC_FILE(HAL, UF);
BFA_MODULE(uf);

/*
 *****************************************************************************
 * Internal functions
 *****************************************************************************
 */
static void
__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
{
	struct bfa_uf_s   *uf = cbarg;
	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);

	if (complete)
		ufm->ufrecv(ufm->cbarg, uf);
}

static void
claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
{
	u32        uf_pb_tot_sz;

	ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
	ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
	uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
							BFA_DMA_ALIGN_SZ);

	bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
	bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;

	bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
}

static void
claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
{
	struct bfi_uf_buf_post_s *uf_bp_msg;
	struct bfi_sge_s      *sge;
	union bfi_addr_u      sga_zero = { {0} };
	u16        i;
	u16        buf_len;

	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
	uf_bp_msg = ufm->uf_buf_posts;

	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
	     i++, uf_bp_msg++) {
		bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));

		uf_bp_msg->buf_tag = i;
		buf_len = sizeof(struct bfa_uf_buf_s);
		uf_bp_msg->buf_len = bfa_os_htons(buf_len);
		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
			    bfa_lpuid(ufm->bfa));

		sge = uf_bp_msg->sge;
		sge[0].sg_len = buf_len;
		sge[0].flags = BFI_SGE_DATA_LAST;
		bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
		bfa_sge_to_be(sge);

		sge[1].sg_len = buf_len;
		sge[1].flags = BFI_SGE_PGDLEN;
		sge[1].sga = sga_zero;
		bfa_sge_to_be(&sge[1]);
	}

	/**
	 * advance pointer beyond consumed memory
	 */
	bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
}

static void
claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
{
	u16        i;
	struct bfa_uf_s   *uf;

	/*
	 * Claim block of memory for UF list
	 */
	ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);

	/*
	 * Initialize UFs and queue it in UF free queue
	 */
	for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
		bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s));
		uf->bfa = ufm->bfa;
		uf->uf_tag = i;
		uf->pb_len = sizeof(struct bfa_uf_buf_s);
		uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
		uf->buf_pa = ufm_pbs_pa(ufm, i);
		list_add_tail(&uf->qe, &ufm->uf_free_q);
	}

	/**
	 * advance memory pointer
	 */
	bfa_meminfo_kva(mi) = (u8 *) uf;
}

static void
uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
{
	claim_uf_pbs(ufm, mi);
	claim_ufs(ufm, mi);
	claim_uf_post_msgs(ufm, mi);
}

static void
bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
{
	u32        num_ufs = cfg->fwcfg.num_uf_bufs;

	/*
	 * dma-able memory for UF posted bufs
	 */
	*dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
							BFA_DMA_ALIGN_SZ);

	/*
	 * kernel Virtual memory for UFs and UF buf post msg copies
	 */
	*ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
	*ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
}

static void
bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
		  struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
{
	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);

	bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
	ufm->bfa = bfa;
	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
	INIT_LIST_HEAD(&ufm->uf_free_q);
	INIT_LIST_HEAD(&ufm->uf_posted_q);

	uf_mem_claim(ufm, meminfo);
}

static void
bfa_uf_initdone(struct bfa_s *bfa)
{
}

static void
bfa_uf_detach(struct bfa_s *bfa)
{
}

static struct bfa_uf_s *
bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
{
	struct bfa_uf_s   *uf;

	bfa_q_deq(&uf_mod->uf_free_q, &uf);
	return uf;
}

static void
bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
{
	list_add_tail(&uf->qe, &uf_mod->uf_free_q);
}

static bfa_status_t
bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
{
	struct bfi_uf_buf_post_s *uf_post_msg;

	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
	if (!uf_post_msg)
		return BFA_STATUS_FAILED;

	bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
		      sizeof(struct bfi_uf_buf_post_s));
	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);

	bfa_trc(ufm->bfa, uf->uf_tag);

	list_add_tail(&uf->qe, &ufm->uf_posted_q);
	return BFA_STATUS_OK;
}

static void
bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
{
	struct bfa_uf_s   *uf;

	while ((uf = bfa_uf_get(uf_mod)) != NULL) {
		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
			break;
	}
}

static void
uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
{
	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
	u16        uf_tag = m->buf_tag;
	struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
	struct bfa_uf_s   *uf = &ufm->uf_list[uf_tag];
	u8        *buf = &uf_buf->d[0];
	struct fchs_s         *fchs;

	m->frm_len = bfa_os_ntohs(m->frm_len);
	m->xfr_len = bfa_os_ntohs(m->xfr_len);

	fchs = (struct fchs_s *) uf_buf;

	list_del(&uf->qe);	/* dequeue from posted queue */

	uf->data_ptr = buf;
	uf->data_len = m->xfr_len;

	bfa_assert(uf->data_len >= sizeof(struct fchs_s));

	if (uf->data_len == sizeof(struct fchs_s)) {
		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
			       uf->data_len, (struct fchs_s *) buf);
	} else {
		u32        pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
				      BFA_PL_EID_RX, uf->data_len,
				      (struct fchs_s *) buf, pld_w0);
	}

	bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
}

static void
bfa_uf_stop(struct bfa_s *bfa)
{
}

static void
bfa_uf_iocdisable(struct bfa_s *bfa)
{
	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
	struct bfa_uf_s   *uf;
	struct list_head        *qe, *qen;

	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
		uf = (struct bfa_uf_s *) qe;
		list_del(&uf->qe);
		bfa_uf_put(ufm, uf);
	}
}

static void
bfa_uf_start(struct bfa_s *bfa)
{
	bfa_uf_post_all(BFA_UF_MOD(bfa));
}



/**
 *  bfa_uf_api
 */

/**
 * 		Register handler for all unsolicted recieve frames.
 *
 * @param[in]	bfa		BFA instance
 * @param[in]	ufrecv	receive handler function
 * @param[in]	cbarg	receive handler arg
 */
void
bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
{
	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);

	ufm->ufrecv = ufrecv;
	ufm->cbarg = cbarg;
}

/**
 * 		Free an unsolicited frame back to BFA.
 *
 * @param[in]		uf		unsolicited frame to be freed
 *
 * @return None
 */
void
bfa_uf_free(struct bfa_uf_s *uf)
{
	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
}



/**
 *  uf_pub BFA uf module public functions
 */

void
bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
{
	bfa_trc(bfa, msg->mhdr.msg_id);

	switch (msg->mhdr.msg_id) {
	case BFI_UF_I2H_FRM_RCVD:
		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
		break;

	default:
		bfa_trc(bfa, msg->mhdr.msg_id);
		bfa_assert(0);
	}
}


