예제 #1
0
/**
 * nfp_reset_soft() - Perform a soft reset of the NFP
 * @nfp:	NFP Device handle
 *
 * Return: 0, or -ERRNO
 */
int nfp_reset_soft(struct nfp_device *nfp)
{
	struct nfp_cpp *cpp = nfp_device_cpp(nfp);
	struct nfp_cpp_area *area;
	struct nfp_resource *res;
	u32 model;
	int i, err;

	model = nfp_cpp_model(cpp);

	/* Claim the nfp.nffw resource page */
	res = nfp_resource_acquire(nfp, NFP_RESOURCE_NFP_NFFW);
	if (IS_ERR(res)) {
		nfp_err(nfp, "Can't aquire %s resource\n",
			NFP_RESOURCE_NFP_NFFW);
		return -EBUSY;
	}

	if (NFP_CPP_MODEL_IS_3200(model))
		err = nfp3200_reset_soft(nfp);
	else if (NFP_CPP_MODEL_IS_6000(model))
		err = nfp6000_reset_soft(nfp);
	else
		err = -EINVAL;

	if (err < 0)
		goto exit;

	/* Clear all NFP NFFW page */
	area = nfp_cpp_area_alloc_acquire(cpp, nfp_resource_cpp_id(res),
					  nfp_resource_address(res),
					  nfp_resource_size(res));
	if (!area) {
		nfp_err(nfp, "Can't acquire area for %s resource\n",
			NFP_RESOURCE_NFP_NFFW);
		err = -ENOMEM;
		goto exit;
	}

	for (i = 0; i < nfp_resource_size(res); i += 8) {
		err = nfp_cpp_area_writeq(area, i, 0);
		if (err < 0)
			break;
	}
	nfp_cpp_area_release_free(area);

	if (err < 0) {
		nfp_err(nfp, "Can't erase area of %s resource\n",
			NFP_RESOURCE_NFP_NFFW);
		goto exit;
	}

	err = 0;

exit:
	nfp_resource_release(res);

	return err;
}
예제 #2
0
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;
}
예제 #3
0
/* 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;
}
예제 #4
0
/*
 * 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;
}