コード例 #1
0
ファイル: nfp_hwinfo.c プロジェクト: SantoshShilimkar/linux
static struct nfp_hwinfo *
hwinfo_try_fetch(struct nfp_cpp *cpp, size_t *cpp_size)
{
	struct nfp_hwinfo *header;
	struct nfp_resource *res;
	u64 cpp_addr;
	u32 cpp_id;
	int err;
	u8 *db;

	res = nfp_resource_acquire(cpp, NFP_RESOURCE_NFP_HWINFO);
	if (!IS_ERR(res)) {
		cpp_id = nfp_resource_cpp_id(res);
		cpp_addr = nfp_resource_address(res);
		*cpp_size = nfp_resource_size(res);

		nfp_resource_release(res);

		if (*cpp_size < HWINFO_SIZE_MIN)
			return NULL;
	} else if (PTR_ERR(res) == -ENOENT) {
		/* Try getting the HWInfo table from the 'classic' location */
		cpp_id = NFP_CPP_ISLAND_ID(NFP_CPP_TARGET_MU,
					   NFP_CPP_ACTION_RW, 0, 1);
		cpp_addr = 0x30000;
		*cpp_size = 0x0e000;
	} else {
		return NULL;
	}

	db = kmalloc(*cpp_size + 1, GFP_KERNEL);
	if (!db)
		return NULL;

	err = nfp_cpp_read(cpp, cpp_id, cpp_addr, db, *cpp_size);
	if (err != *cpp_size)
		goto exit_free;

	header = (void *)db;
	if (nfp_hwinfo_is_updating(header))
		goto exit_free;

	if (le32_to_cpu(header->version) != NFP_HWINFO_VERSION_2) {
		nfp_err(cpp, "Unknown HWInfo version: 0x%08x\n",
			le32_to_cpu(header->version));
		goto exit_free;
	}

	/* NULL-terminate for safety */
	db[*cpp_size] = '\0';

	return (void *)db;
exit_free:
	kfree(db);
	return NULL;
}
コード例 #2
0
ファイル: nfp_nffw.c プロジェクト: DrenfongWong/dpdk
/*
 * nfp_nffw_info_open() - Acquire the lock on the NFFW table
 * @cpp:	NFP CPP handle
 *
 * Return: 0, or -ERRNO
 */
struct nfp_nffw_info *
nfp_nffw_info_open(struct nfp_cpp *cpp)
{
	struct nfp_nffw_info_data *fwinf;
	struct nfp_nffw_info *state;
	uint32_t info_ver;
	int err;

	state = malloc(sizeof(*state));
	if (!state)
		return NULL;

	memset(state, 0, sizeof(*state));

	state->res = nfp_resource_acquire(cpp, NFP_RESOURCE_NFP_NFFW);
	if (!state->res)
		goto err_free;

	fwinf = &state->fwinf;

	if (sizeof(*fwinf) > nfp_resource_size(state->res))
		goto err_release;

	err = nfp_cpp_read(cpp, nfp_resource_cpp_id(state->res),
			   nfp_resource_address(state->res),
			   fwinf, sizeof(*fwinf));
	if (err < (int)sizeof(*fwinf))
		goto err_release;

	if (!nffw_res_flg_init_get(fwinf))
		goto err_release;

	info_ver = nffw_res_info_version_get(fwinf);
	if (info_ver > NFFW_INFO_VERSION_CURRENT)
		goto err_release;

	state->cpp = cpp;
	return state;

err_release:
	nfp_resource_release(state->res);
err_free:
	free(state);
	return NULL;
}
コード例 #3
0
ファイル: nfp_resource.c プロジェクト: AshishNamdev/linux
static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res)
{
	char name_pad[NFP_RESOURCE_ENTRY_NAME_SZ] = {};
	struct nfp_resource_entry entry;
	u32 cpp_id, key;
	int ret, i;

	cpp_id = NFP_CPP_ID(NFP_RESOURCE_TBL_TARGET, 3, 0);  /* Atomic read */

	strncpy(name_pad, res->name, sizeof(name_pad));

	/* Search for a matching entry */
	key = NFP_RESOURCE_TBL_KEY;
	if (memcmp(name_pad, NFP_RESOURCE_TBL_NAME "\0\0\0\0\0\0\0\0", 8))
		key = crc32_posix(name_pad, sizeof(name_pad));

	for (i = 0; i < NFP_RESOURCE_TBL_ENTRIES; i++) {
		u64 addr = NFP_RESOURCE_TBL_BASE +
			sizeof(struct nfp_resource_entry) * i;

		ret = nfp_cpp_read(cpp, cpp_id, addr, &entry, sizeof(entry));
		if (ret != sizeof(entry))
			return -EIO;

		if (entry.mutex.key != key)
			continue;

		/* Found key! */
		res->mutex =
			nfp_cpp_mutex_alloc(cpp,
					    NFP_RESOURCE_TBL_TARGET, addr, key);
		res->cpp_id = NFP_CPP_ID(entry.region.cpp_target,
					 entry.region.cpp_action,
					 entry.region.cpp_token);
		res->addr = (u64)entry.region.page_offset << 8;
		res->size = (u64)entry.region.page_size << 8;

		return 0;
	}

	return -ENOENT;
}
コード例 #4
0
ファイル: nfp_net_ethtool.c プロジェクト: AshishNamdev/linux
/* Other debug dumps
 */
static int
nfp_dump_nsp_diag(struct nfp_net *nn, struct ethtool_dump *dump, void *buffer)
{
	struct nfp_resource *res;
	int ret;

	if (!nn->cpp)
		return -EOPNOTSUPP;

	dump->version = 1;
	dump->flag = NFP_DUMP_NSP_DIAG;

	res = nfp_resource_acquire(nn->cpp, NFP_RESOURCE_NSP_DIAG);
	if (IS_ERR(res))
		return PTR_ERR(res);

	if (buffer) {
		if (dump->len != nfp_resource_size(res)) {
			ret = -EINVAL;
			goto exit_release;
		}

		ret = nfp_cpp_read(nn->cpp, nfp_resource_cpp_id(res),
				   nfp_resource_address(res),
				   buffer, dump->len);
		if (ret != dump->len)
			ret = ret < 0 ? ret : -EIO;
		else
			ret = 0;
	} else {
		dump->len = nfp_resource_size(res);
		ret = 0;
	}
exit_release:
	nfp_resource_release(res);

	return ret;
}
コード例 #5
0
ファイル: nfp_mip.c プロジェクト: AlexShiLucky/linux
/* Read memory and check if it could be a valid MIP */
static int
nfp_mip_try_read(struct nfp_cpp *cpp, u32 cpp_id, u64 addr, struct nfp_mip *mip)
{
	int ret;

	ret = nfp_cpp_read(cpp, cpp_id, addr, mip, sizeof(*mip));
	if (ret != sizeof(*mip)) {
		nfp_err(cpp, "Failed to read MIP data (%d, %zu)\n",
			ret, sizeof(*mip));
		return -EIO;
	}
	if (mip->signature != NFP_MIP_SIGNATURE) {
		nfp_warn(cpp, "Incorrect MIP signature (0x%08x)\n",
			 le32_to_cpu(mip->signature));
		return -EINVAL;
	}
	if (mip->mip_version != NFP_MIP_VERSION) {
		nfp_warn(cpp, "Unsupported MIP version (%d)\n",
			 le32_to_cpu(mip->mip_version));
		return -EINVAL;
	}

	return 0;
}
コード例 #6
0
ファイル: nfp_rtsym.c プロジェクト: AshishNamdev/linux
static int nfp_rtsymtab_probe(struct nfp_cpp *cpp)
{
	const u32 dram = NFP_CPP_ID(NFP_CPP_TARGET_MU, NFP_CPP_ACTION_RW, 0) |
		NFP_ISL_EMEM0;
	u32 strtab_addr, symtab_addr, strtab_size, symtab_size;
	struct nfp_rtsym_entry *rtsymtab;
	struct nfp_rtsym_cache *cache;
	const struct nfp_mip *mip;
	int err, n, size;

	mip = nfp_mip_open(cpp);
	if (!mip)
		return -EIO;

	nfp_mip_strtab(mip, &strtab_addr, &strtab_size);
	nfp_mip_symtab(mip, &symtab_addr, &symtab_size);
	nfp_mip_close(mip);

	if (!symtab_size || !strtab_size || symtab_size % sizeof(*rtsymtab))
		return -ENXIO;

	/* Align to 64 bits */
	symtab_size = round_up(symtab_size, 8);
	strtab_size = round_up(strtab_size, 8);

	rtsymtab = kmalloc(symtab_size, GFP_KERNEL);
	if (!rtsymtab)
		return -ENOMEM;

	size = sizeof(*cache);
	size += symtab_size / sizeof(*rtsymtab) * sizeof(struct nfp_rtsym);
	size +=	strtab_size + 1;
	cache = kmalloc(size, GFP_KERNEL);
	if (!cache) {
		err = -ENOMEM;
		goto err_free_rtsym_raw;
	}

	cache->num = symtab_size / sizeof(*rtsymtab);
	cache->strtab = (void *)&cache->symtab[cache->num];

	err = nfp_cpp_read(cpp, dram, symtab_addr, rtsymtab, symtab_size);
	if (err != symtab_size)
		goto err_free_cache;

	err = nfp_cpp_read(cpp, dram, strtab_addr, cache->strtab, strtab_size);
	if (err != strtab_size)
		goto err_free_cache;
	cache->strtab[strtab_size] = '\0';

	for (n = 0; n < cache->num; n++)
		nfp_rtsym_sw_entry_init(cache, strtab_size,
					&cache->symtab[n], &rtsymtab[n]);

	kfree(rtsymtab);
	nfp_rtsym_cache_set(cpp, cache);
	return 0;

err_free_cache:
	kfree(cache);
err_free_rtsym_raw:
	kfree(rtsymtab);
	return err;
}
コード例 #7
0
static int nfp_cpp_resource_acquire(struct nfp_cpp *cpp, const char *name,
				    u32 *r_cpp, u64 *r_addr, u64 *r_size,
				    struct nfp_cpp_mutex **resource_mutex)
{
	struct nfp_resource_entry_region region;
	struct nfp_resource_entry tmp;
	struct nfp_cpp_mutex *mutex;
	int target, err, i, entries;
	u64 base;
	u32 key;
	u32 cpp_id;

	for (i = 0; i < sizeof(region.name); i++) {
		if (*name != 0)
			region.name[i] = *(name++);
		else
			region.name[i] = 0;
	}

	entries = nfp_cpp_resource_table(cpp, &target, &base, NULL);
	if (entries < 0)
		return entries;

	cpp_id = NFP_CPP_ID(target, 3, 0);  /* Atomic read */

	key = NFP_RESOURCE_TABLE_KEY;
	mutex = nfp_cpp_mutex_alloc(cpp, target, base, key);
	if (!mutex)
		return -ENOMEM;

	/* Wait for the lock.. */
	err = nfp_cpp_mutex_lock(mutex);
	if (err < 0) {
		nfp_cpp_mutex_free(mutex);
		return err;
	}

	/* Search for a matching entry */
	if (memcmp(region.name,
		   NFP_RESOURCE_TABLE_NAME "\0\0\0\0\0\0\0\0", 8) != 0)
		key = crc32_posix(&region.name[0], sizeof(region.name));
	for (i = 0; i < entries; i++) {
		u64 addr = base + sizeof(struct nfp_resource_entry) * i;

		err = nfp_cpp_read(cpp, cpp_id, addr, &tmp, sizeof(tmp));
		if (err < 0) {
			/* Unlikely to work if the read failed,
			 * but we should at least try... */
			nfp_cpp_mutex_unlock(mutex);
			nfp_cpp_mutex_free(mutex);
			return err;
		}

		if (tmp.mutex.key == key) {
			/* Found key! */
			if (resource_mutex)
				*resource_mutex = nfp_cpp_mutex_alloc(cpp,
							target, addr, key);

			if (r_cpp)
				*r_cpp = NFP_CPP_ID(tmp.region.cpp_target,
						tmp.region.cpp_action,
						tmp.region.cpp_token);

			if (r_addr)
				*r_addr = (u64)tmp.region.page_offset << 8;

			if (r_size)
				*r_size = (u64)tmp.region.page_size << 8;

			nfp_cpp_mutex_unlock(mutex);
			nfp_cpp_mutex_free(mutex);

			return 0;
		}
	}

	nfp_cpp_mutex_unlock(mutex);
	nfp_cpp_mutex_free(mutex);

	return -ENOENT;
}