Esempio n. 1
0
static int __nfp_resource_entry_init(struct nfp_cpp *cpp, int entry,
				     const struct nfp_resource_entry_region
				     *region,
				     struct nfp_cpp_mutex **resource_mutex)
{
	struct nfp_cpp_mutex *mutex;
	int target, entries;
	size_t size;
	u32 cpp_id;
	u32 key;
	int err;
	u64 base;

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

	if (entry >= entries)
		return -EINVAL;

	base += sizeof(struct nfp_resource_entry) * entry;

	if (entry == 0)
		key = NFP_RESOURCE_TABLE_KEY;
	else
		key = crc32_posix(region->name, 8);

	err = nfp_cpp_mutex_init(cpp, target, base, key);
	if (err < 0)
		return err;

	/* We already own the initialized lock */
	mutex = nfp_cpp_mutex_alloc(cpp, target, base, key);
	if (!mutex)
		return -ENOMEM;

	/* Mutex Owner and Key are already set */
	cpp_id = NFP_CPP_ID(target, 4, 0);  /* Atomic write */

	err = nfp_cpp_write(cpp, cpp_id, base +
			offsetof(struct nfp_resource_entry, region),
			region, sizeof(*region));
	if (err < 0) {
		/* Try to unlock in the face of adversity */
		nfp_cpp_mutex_unlock(mutex);
		nfp_cpp_mutex_free(mutex);
		return err;
	}

	if (resource_mutex) {
		*resource_mutex = mutex;
	} else {
		nfp_cpp_mutex_unlock(mutex);
		nfp_cpp_mutex_free(mutex);
	}

	return 0;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
static int
hwinfo_db_validate(struct nfp_cpp *cpp, struct nfp_hwinfo *db, u32 len)
{
	u32 size, crc;

	size = le32_to_cpu(db->size);
	if (size > len) {
		nfp_err(cpp, "Unsupported hwinfo size %u > %u\n", size, len);
		return -EINVAL;
	}

	size -= sizeof(u32);
	crc = crc32_posix(db, size);
	if (crc != get_unaligned_le32(db->start + size)) {
		nfp_err(cpp, "Corrupt hwinfo table (CRC mismatch), calculated 0x%x, expected 0x%x\n",
			crc, get_unaligned_le32(db->start + size));

		return -EINVAL;
	}

	return hwinfo_db_walk(cpp, db, size);
}
Esempio n. 4
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;
}
Esempio n. 5
0
/**
 * nfp_cpp_resource_add() - Construct a new NFP Resource entry
 * @cpp:		NFP CPP handle
 * @name:		Name of the resource
 * @cpp_id:		NFP CPP ID of the resource
 * @address:		NFP CPP address of the resource
 * @size:		Size, in bytes, of the resource area
 * @resource_mutex:	Location to place the resource's mutex
 *
 * NOTE: If resource_mutex is NULL, the mutex of the resource is
 * implictly unlocked.
 *
 * Return: 0, or -ERRNO
 */
int nfp_cpp_resource_add(struct nfp_cpp *cpp, const char *name,
			 u32 cpp_id, u64 address, u64 size,
			 struct nfp_cpp_mutex **resource_mutex)
{
	int target, err, i, entries, minfree;
	u64 base;
	u32 key;
	struct nfp_resource_entry_region region = {
		.cpp_action = NFP_CPP_ID_ACTION_of(cpp_id),
		.cpp_token  = NFP_CPP_ID_TOKEN_of(cpp_id),
		.cpp_target = NFP_CPP_ID_TARGET_of(cpp_id),
		.page_offset = (u32)(address >> 8),
		.page_size  = (u32)(size >> 8),
	};
	struct nfp_cpp_mutex *mutex;
	u32 tmp;

	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 free entry, or a duplicate */
	minfree = 0;
	key = crc32_posix(name, 8);
	for (i = 1; i < entries; i++) {
		u64 addr = base + sizeof(struct nfp_resource_entry) * i;

		err = nfp_cpp_readl(cpp, cpp_id, addr +
				offsetof(struct nfp_resource_entry, mutex.key),
				&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 == key) {
			/* Duplicate key! */
			nfp_cpp_mutex_unlock(mutex);
			nfp_cpp_mutex_free(mutex);
			return -EEXIST;
		}

		if (tmp == 0 && minfree == 0)
			minfree = i;
	}

	/* No available space in the table! */
	if (minfree == 0)
		return -ENOSPC;

	err = __nfp_resource_entry_init(cpp, minfree, &region, resource_mutex);
	nfp_cpp_mutex_unlock(mutex);
	nfp_cpp_mutex_free(mutex);

	return err;
}