/*
 * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
 *
 * This program is free software; you may redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * 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 <linux/errno.h>
#include <linux/module.h>
#include <linux/pci.h>

#include "usnic_ib.h"
#include "vnic_resource.h"
#include "usnic_log.h"
#include "usnic_vnic.h"

struct usnic_vnic {
	struct vnic_dev			*vdev;
	struct vnic_dev_bar		bar[PCI_NUM_RESOURCES];
	struct usnic_vnic_res_chunk	chunks[USNIC_VNIC_RES_TYPE_MAX];
	spinlock_t			res_lock;
};

static enum vnic_res_type _to_vnic_res_type(enum usnic_vnic_res_type res_type)
{
#define DEFINE_USNIC_VNIC_RES_AT(usnic_vnic_res_t, vnic_res_type, desc, val) \
		vnic_res_type,
#define DEFINE_USNIC_VNIC_RES(usnic_vnic_res_t, vnic_res_type, desc) \
		vnic_res_type,
	static enum vnic_res_type usnic_vnic_type_2_vnic_type[] = {
						USNIC_VNIC_RES_TYPES};
#undef DEFINE_USNIC_VNIC_RES
#undef DEFINE_USNIC_VNIC_RES_AT

	if (res_type >= USNIC_VNIC_RES_TYPE_MAX)
		return RES_TYPE_MAX;

	return usnic_vnic_type_2_vnic_type[res_type];
}

const char *usnic_vnic_res_type_to_str(enum usnic_vnic_res_type res_type)
{
#define DEFINE_USNIC_VNIC_RES_AT(usnic_vnic_res_t, vnic_res_type, desc, val) \
		desc,
#define DEFINE_USNIC_VNIC_RES(usnic_vnic_res_t, vnic_res_type, desc) \
		desc,
	static const char * const usnic_vnic_res_type_desc[] = {
						USNIC_VNIC_RES_TYPES};
#undef DEFINE_USNIC_VNIC_RES
#undef DEFINE_USNIC_VNIC_RES_AT

	if (res_type >= USNIC_VNIC_RES_TYPE_MAX)
		return "unknown";

	return usnic_vnic_res_type_desc[res_type];

}

const char *usnic_vnic_pci_name(struct usnic_vnic *vnic)
{
	return pci_name(usnic_vnic_get_pdev(vnic));
}

int usnic_vnic_dump(struct usnic_vnic *vnic, char *buf,
			int buf_sz,
			void *hdr_obj,
			int (*printtitle)(void *, char*, int),
			int (*printcols)(char *, int),
			int (*printrow)(void *, char *, int))
{
	struct usnic_vnic_res_chunk *chunk;
	struct usnic_vnic_res *res;
	struct vnic_dev_bar *bar0;
	int i, j, offset;

	offset = 0;
	bar0 = usnic_vnic_get_bar(vnic, 0);
	offset += scnprintf(buf + offset, buf_sz - offset,
			"VF:%hu BAR0 bus_addr=%pa vaddr=0x%p size=%ld ",
			usnic_vnic_get_index(vnic),
			&bar0->bus_addr,
			bar0->vaddr, bar0->len);
	if (printtitle)
		offset += printtitle(hdr_obj, buf + offset, buf_sz - offset);
	offset += scnprintf(buf + offset, buf_sz - offset, "\n");
	offset += scnprintf(buf + offset, buf_sz - offset,
			"|RES\t|CTRL_PIN\t\t|IN_USE\t");
	if (printcols)
		offset += printcols(buf + offset, buf_sz - offset);
	offset += scnprintf(buf + offset, buf_sz - offset, "\n");

	spin_lock(&vnic->res_lock);
	for (i = 0; i < ARRAY_SIZE(vnic->chunks); i++) {
		chunk = &vnic->chunks[i];
		for (j = 0; j < chunk->cnt; j++) {
			res = chunk->res[j];
			offset += scnprintf(buf + offset, buf_sz - offset,
					"|%s[%u]\t|0x%p\t|%u\t",
					usnic_vnic_res_type_to_str(res->type),
					res->vnic_idx, res->ctrl, !!res->owner);
			if (printrow) {
				offset += printrow(res->owner, buf + offset,
							buf_sz - offset);
			}
			offset += scnprintf(buf + offset, buf_sz - offset,
						"\n");
		}
	}
	spin_unlock(&vnic->res_lock);
	return offset;
}

void usnic_vnic_res_spec_update(struct usnic_vnic_res_spec *spec,
				enum usnic_vnic_res_type trgt_type,
				u16 cnt)
{
	int i;

	for (i = 0; i < USNIC_VNIC_RES_TYPE_MAX; i++) {
		if (spec->resources[i].type == trgt_type) {
			spec->resources[i].cnt = cnt;
			return;
		}
	}

	WARN_ON(1);
}

int usnic_vnic_res_spec_satisfied(const struct usnic_vnic_res_spec *min_spec,
					struct usnic_vnic_res_spec *res_spec)
{
	int found, i, j;

	for (i = 0; i < USNIC_VNIC_RES_TYPE_MAX; i++) {
		found = 0;

		for (j = 0; j < USNIC_VNIC_RES_TYPE_MAX; j++) {
			if (res_spec->resources[i].type !=
				min_spec->resources[i].type)
				continue;
			found = 1;
			if (min_spec->resources[i].cnt >
					res_spec->resources[i].cnt)
				return -EINVAL;
			break;
		}

		if (!found)
			return -EINVAL;
	}
	return 0;
}

int usnic_vnic_spec_dump(char *buf, int buf_sz,
				struct usnic_vnic_res_spec *res_spec)
{
	enum usnic_vnic_res_type res_type;
	int res_cnt;
	int i;
	int offset = 0;

	for (i = 0; i < USNIC_VNIC_RES_TYPE_MAX; i++) {
		res_type = res_spec->resources[i].type;
		res_cnt = res_spec->resources[i].cnt;
		offset += scnprintf(buf + offset, buf_sz - offset,
				"Res: %s Cnt: %d ",
				usnic_vnic_res_type_to_str(res_type),
				res_cnt);
	}

	return offset;
}

int usnic_vnic_check_room(struct usnic_vnic *vnic,
				struct usnic_vnic_res_spec *res_spec)
{
	int i;
	enum usnic_vnic_res_type res_type;
	int res_cnt;

	for (i = 0; i < USNIC_VNIC_RES_TYPE_MAX; i++) {
		res_type = res_spec->resources[i].type;
		res_cnt = res_spec->resources[i].cnt;

		if (res_type == USNIC_VNIC_RES_TYPE_EOL)
			break;

		if (res_cnt > usnic_vnic_res_free_cnt(vnic, res_type))
			return -EBUSY;
	}

	return 0;
}

int usnic_vnic_res_cnt(struct usnic_vnic *vnic,
				enum usnic_vnic_res_type type)
{
	return vnic->chunks[type].cnt;
}

int usnic_vnic_res_free_cnt(struct usnic_vnic *vnic,
				enum usnic_vnic_res_type type)
{
	return vnic->chunks[type].free_cnt;
}

struct usnic_vnic_res_chunk *
usnic_vnic_get_resources(struct usnic_vnic *vnic, enum usnic_vnic_res_type type,
				int cnt, void *owner)
{
	struct usnic_vnic_res_chunk *src, *ret;
	struct usnic_vnic_res *res;
	int i;

	if (usnic_vnic_res_free_cnt(vnic, type) < cnt || cnt < 1 || !owner)
		return ERR_PTR(-EINVAL);

	ret = kzalloc(sizeof(*ret), GFP_ATOMIC);
	if (!ret) {
		usnic_err("Failed to allocate chunk for %s - Out of memory\n",
				usnic_vnic_pci_name(vnic));
		return ERR_PTR(-ENOMEM);
	}

	ret->res = kzalloc(sizeof(*(ret->res))*cnt, GFP_ATOMIC);
	if (!ret->res) {
		usnic_err("Failed to allocate resources for %s. Out of memory\n",
				usnic_vnic_pci_name(vnic));
		kfree(ret);
		return ERR_PTR(-ENOMEM);
	}

	spin_lock(&vnic->res_lock);
	src = &vnic->chunks[type];
	for (i = 0; i < src->cnt && ret->cnt < cnt; i++) {
		res = src->res[i];
		if (!res->owner) {
			src->free_cnt--;
			res->owner = owner;
			ret->res[ret->cnt++] = res;
		}
	}

	spin_unlock(&vnic->res_lock);
	ret->type = type;
	ret->vnic = vnic;
	WARN_ON(ret->cnt != cnt);

	return ret;
}

void usnic_vnic_put_resources(struct usnic_vnic_res_chunk *chunk)
{

	struct usnic_vnic_res *res;
	int i;
	struct usnic_vnic *vnic = chunk->vnic;

	spin_lock(&vnic->res_lock);
	while ((i = --chunk->cnt) >= 0) {
		res = chunk->res[i];
		chunk->res[i] = NULL;
		res->owner = NULL;
		vnic->chunks[res->type].free_cnt++;
	}
	spin_unlock(&vnic->res_lock);

	kfree(chunk->res);
	kfree(chunk);
}

u16 usnic_vnic_get_index(struct usnic_vnic *vnic)
{
	return usnic_vnic_get_pdev(vnic)->devfn - 1;
}

static int usnic_vnic_alloc_res_chunk(struct usnic_vnic *vnic,
					enum usnic_vnic_res_type type,
					struct usnic_vnic_res_chunk *chunk)
{
	int cnt, err, i;
	struct usnic_vnic_res *res;

	cnt = vnic_dev_get_res_count(vnic->vdev, _to_vnic_res_type(type));
	if (cnt < 1)
		return -EINVAL;

	chunk->cnt = chunk->free_cnt = cnt;
	chunk->res = kzalloc(sizeof(*(chunk->res))*cnt, GFP_KERNEL);
	if (!chunk->res)
		return -ENOMEM;

	for (i = 0; i < cnt; i++) {
		res = kzalloc(sizeof(*res), GFP_KERNEL);
		if (!res) {
			err = -ENOMEM;
			goto fail;
		}
		res->type = type;
		res->vnic_idx = i;
		res->vnic = vnic;
		res->ctrl = vnic_dev_get_res(vnic->vdev,
						_to_vnic_res_type(type), i);
		chunk->res[i] = res;
	}

	chunk->vnic = vnic;
	return 0;
fail:
	for (i--; i >= 0; i--)
		kfree(chunk->res[i]);
	kfree(chunk->res);
	return err;
}

static void usnic_vnic_free_res_chunk(struct usnic_vnic_res_chunk *chunk)
{
	int i;
	for (i = 0; i < chunk->cnt; i++)
		kfree(chunk->res[i]);
	kfree(chunk->res);
}

static int usnic_vnic_discover_resources(struct pci_dev *pdev,
						struct usnic_vnic *vnic)
{
	enum usnic_vnic_res_type res_type;
	int i;
	int err = 0;

	for (i = 0; i < ARRAY_SIZE(vnic->bar); i++) {
		if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
			continue;
		vnic->bar[i].len = pci_resource_len(pdev, i);
		vnic->bar[i].vaddr = pci_iomap(pdev, i, vnic->bar[i].len);
		if (!vnic->bar[i].vaddr) {
			usnic_err("Cannot memory-map BAR %d, aborting\n",
					i);
			err = -ENODEV;
			goto out_clean_bar;
		}
		vnic->bar[i].bus_addr = pci_resource_start(pdev, i);
	}

	vnic->vdev = vnic_dev_register(NULL, pdev, pdev, vnic->bar,
			ARRAY_SIZE(vnic->bar));
	if (!vnic->vdev) {
		usnic_err("Failed to register device %s\n",
				pci_name(pdev));
		err = -EINVAL;
		goto out_clean_bar;
	}

	for (res_type = USNIC_VNIC_RES_TYPE_EOL + 1;
			res_type < USNIC_VNIC_RES_TYPE_MAX; res_type++) {
		err = usnic_vnic_alloc_res_chunk(vnic, res_type,
						&vnic->chunks[res_type]);
		if (err) {
			usnic_err("Failed to alloc res %s with err %d\n",
					usnic_vnic_res_type_to_str(res_type),
					err);
			goto out_clean_chunks;
		}
	}

	return 0;

out_clean_chunks:
	for (res_type--; res_type > USNIC_VNIC_RES_TYPE_EOL; res_type--)
		usnic_vnic_free_res_chunk(&vnic->chunks[res_type]);
	vnic_dev_unregister(vnic->vdev);
out_clean_bar:
	for (i = 0; i < ARRAY_SIZE(vnic->bar); i++) {
		if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
			continue;
		if (!vnic->bar[i].vaddr)
			break;

		iounmap(vnic->bar[i].vaddr);
	}

	return err;
}

struct pci_dev *usnic_vnic_get_pdev(struct usnic_vnic *vnic)
{
	return vnic_dev_get_pdev(vnic->vdev);
}

struct vnic_dev_bar *usnic_vnic_get_bar(struct usnic_vnic *vnic,
				int bar_num)
{
	return (bar_num < ARRAY_SIZE(vnic->bar)) ? &vnic->bar[bar_num] : NULL;
}

static void usnic_vnic_release_resources(struct usnic_vnic *vnic)
{
	int i;
	struct pci_dev *pdev;
	enum usnic_vnic_res_type res_type;

	pdev = usnic_vnic_get_pdev(vnic);

	for (res_type = USNIC_VNIC_RES_TYPE_EOL + 1;
			res_type < USNIC_VNIC_RES_TYPE_MAX; res_type++)
		usnic_vnic_free_res_chunk(&vnic->chunks[res_type]);

	vnic_dev_unregister(vnic->vdev);

	for (i = 0; i < ARRAY_SIZE(vnic->bar); i++) {
		if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
			continue;
		iounmap(vnic->bar[i].vaddr);
	}
}

struct usnic_vnic *usnic_vnic_alloc(struct pci_dev *pdev)
{
	struct usnic_vnic *vnic;
	int err = 0;

	if (!pci_is_enabled(pdev)) {
		usnic_err("PCI dev %s is disabled\n", pci_name(pdev));
		return ERR_PTR(-EINVAL);
	}

	vnic = kzalloc(sizeof(*vnic), GFP_KERNEL);
	if (!vnic) {
		usnic_err("Failed to alloc vnic for %s - out of memory\n",
				pci_name(pdev));
		return ERR_PTR(-ENOMEM);
	}

	spin_lock_init(&vnic->res_lock);

	err = usnic_vnic_discover_resources(pdev, vnic);
	if (err) {
		usnic_err("Failed to discover %s resources with err %d\n",
				pci_name(pdev), err);
		goto out_free_vnic;
	}

	usnic_dbg("Allocated vnic for %s\n", usnic_vnic_pci_name(vnic));

	return vnic;

out_free_vnic:
	kfree(vnic);

	return ERR_PTR(err);
}

void usnic_vnic_free(struct usnic_vnic *vnic)
{
	usnic_vnic_release_resources(vnic);
	kfree(vnic);
}
