/*
 * This file is part of the Chelsio T4/T5/T6 Ethernet driver for Linux.
 *
 * Copyright (c) 2017 Chelsio Communications, Inc. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "cxgb4.h"
#include "smt.h"
#include "t4_msg.h"
#include "t4fw_api.h"
#include "t4_regs.h"
#include "t4_values.h"

struct smt_data *t4_init_smt(void)
{
	unsigned int smt_size;
	struct smt_data *s;
	int i;

	smt_size = SMT_SIZE;

	s = kvzalloc(struct_size(s, smtab, smt_size), GFP_KERNEL);
	if (!s)
		return NULL;
	s->smt_size = smt_size;
	rwlock_init(&s->lock);
	for (i = 0; i < s->smt_size; ++i) {
		s->smtab[i].idx = i;
		s->smtab[i].state = SMT_STATE_UNUSED;
		eth_zero_addr(s->smtab[i].src_mac);
		spin_lock_init(&s->smtab[i].lock);
		s->smtab[i].refcnt = 0;
	}
	return s;
}

static struct smt_entry *find_or_alloc_smte(struct smt_data *s, u8 *smac)
{
	struct smt_entry *first_free = NULL;
	struct smt_entry *e, *end;

	for (e = &s->smtab[0], end = &s->smtab[s->smt_size]; e != end; ++e) {
		if (e->refcnt == 0) {
			if (!first_free)
				first_free = e;
		} else {
			if (e->state == SMT_STATE_SWITCHING) {
				/* This entry is actually in use. See if we can
				 * re-use it ?
				 */
				if (memcmp(e->src_mac, smac, ETH_ALEN) == 0)
					goto found_reuse;
			}
		}
	}

	if (first_free) {
		e = first_free;
		goto found;
	}
	return NULL;

found:
	e->state = SMT_STATE_UNUSED;

found_reuse:
	return e;
}

static void t4_smte_free(struct smt_entry *e)
{
	if (e->refcnt == 0) {  /* hasn't been recycled */
		e->state = SMT_STATE_UNUSED;
	}
}

/**
 * cxgb4_smt_release - Release SMT entry
 * @e: smt entry to release
 *
 * Releases ref count and frees up an smt entry from SMT table
 */
void cxgb4_smt_release(struct smt_entry *e)
{
	spin_lock_bh(&e->lock);
	if ((--e->refcnt) == 0)
		t4_smte_free(e);
	spin_unlock_bh(&e->lock);
}
EXPORT_SYMBOL(cxgb4_smt_release);

void do_smt_write_rpl(struct adapter *adap, const struct cpl_smt_write_rpl *rpl)
{
	unsigned int smtidx = TID_TID_G(GET_TID(rpl));
	struct smt_data *s = adap->smt;

	if (unlikely(rpl->status != CPL_ERR_NONE)) {
		struct smt_entry *e = &s->smtab[smtidx];

		dev_err(adap->pdev_dev,
			"Unexpected SMT_WRITE_RPL status %u for entry %u\n",
			rpl->status, smtidx);
		spin_lock(&e->lock);
		e->state = SMT_STATE_ERROR;
		spin_unlock(&e->lock);
		return;
	}
}

static int write_smt_entry(struct adapter *adapter, struct smt_entry *e)
{
	struct cpl_t6_smt_write_req *t6req;
	struct smt_data *s = adapter->smt;
	struct cpl_smt_write_req *req;
	struct sk_buff *skb;
	int size;
	u8 row;

	if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5) {
		size = sizeof(*req);
		skb = alloc_skb(size, GFP_ATOMIC);
		if (!skb)
			return -ENOMEM;
		/* Source MAC Table (SMT) contains 256 SMAC entries
		 * organized in 128 rows of 2 entries each.
		 */
		req = (struct cpl_smt_write_req *)__skb_put(skb, size);
		INIT_TP_WR(req, 0);

		/* Each row contains an SMAC pair.
		 * LSB selects the SMAC entry within a row
		 */
		row = (e->idx >> 1);
		if (e->idx & 1) {
			req->pfvf1 = 0x0;
			memcpy(req->src_mac1, e->src_mac, ETH_ALEN);

			/* fill pfvf0/src_mac0 with entry
			 * at prev index from smt-tab.
			 */
			req->pfvf0 = 0x0;
			memcpy(req->src_mac0, s->smtab[e->idx - 1].src_mac,
			       ETH_ALEN);
		} else {
			req->pfvf0 = 0x0;
			memcpy(req->src_mac0, e->src_mac, ETH_ALEN);

			/* fill pfvf1/src_mac1 with entry
			 * at next index from smt-tab
			 */
			req->pfvf1 = 0x0;
			memcpy(req->src_mac1, s->smtab[e->idx + 1].src_mac,
			       ETH_ALEN);
		}
	} else {
		size = sizeof(*t6req);
		skb = alloc_skb(size, GFP_ATOMIC);
		if (!skb)
			return -ENOMEM;
		/* Source MAC Table (SMT) contains 256 SMAC entries */
		t6req = (struct cpl_t6_smt_write_req *)__skb_put(skb, size);
		INIT_TP_WR(t6req, 0);
		req = (struct cpl_smt_write_req *)t6req;

		/* fill pfvf0/src_mac0 from smt-tab */
		req->pfvf0 = 0x0;
		memcpy(req->src_mac0, s->smtab[e->idx].src_mac, ETH_ALEN);
		row = e->idx;
	}

	OPCODE_TID(req) =
		htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, e->idx |
				    TID_QID_V(adapter->sge.fw_evtq.abs_id)));
	req->params = htonl(SMTW_NORPL_V(0) |
			    SMTW_IDX_V(row) |
			    SMTW_OVLAN_IDX_V(0));
	t4_mgmt_tx(adapter, skb);
	return 0;
}

static struct smt_entry *t4_smt_alloc_switching(struct adapter *adap, u16 pfvf,
						u8 *smac)
{
	struct smt_data *s = adap->smt;
	struct smt_entry *e;

	write_lock_bh(&s->lock);
	e = find_or_alloc_smte(s, smac);
	if (e) {
		spin_lock(&e->lock);
		if (!e->refcnt) {
			e->refcnt = 1;
			e->state = SMT_STATE_SWITCHING;
			e->pfvf = pfvf;
			memcpy(e->src_mac, smac, ETH_ALEN);
			write_smt_entry(adap, e);
		} else {
			++e->refcnt;
		}
		spin_unlock(&e->lock);
	}
	write_unlock_bh(&s->lock);
	return e;
}

/**
 * cxgb4_smt_alloc_switching - Allocates an SMT entry for switch filters.
 * @dev: net_device pointer
 * @smac: MAC address to add to SMT
 * Returns pointer to the SMT entry created
 *
 * Allocates an SMT entry to be used by switching rule of a filter.
 */
struct smt_entry *cxgb4_smt_alloc_switching(struct net_device *dev, u8 *smac)
{
	struct adapter *adap = netdev2adap(dev);

	return t4_smt_alloc_switching(adap, 0x0, smac);
}
EXPORT_SYMBOL(cxgb4_smt_alloc_switching);
