int
mgt_commit_list(islpci_private *priv, enum oid_num_t *l, int n)
{
	int i, ret = 0;
	struct islpci_mgmtframe *response;

	for (i = 0; i < n; i++) {
		struct oid_t *t = &(isl_oid[l[i]]);
		void *data = priv->mib[l[i]];
		int j = 0;
		u32 oid = t->oid;
		BUG_ON(data == NULL);
		while (j <= t->range) {
			int r = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET,
						      oid, data, t->size,
						      &response);
			if (response) {
				r |= (response->header->operation == PIMFOR_OP_ERROR);
				islpci_mgt_release(response);
			}
			if (r)
				printk(KERN_ERR "%s: mgt_commit_list: failure. "
					"oid=%08x err=%d\n",
					priv->ndev->name, oid, r);
			ret |= r;
			j++;
			oid++;
			data += t->size;
		}
	}
	return ret;
}
int
mgt_set_varlen(islpci_private *priv, enum oid_num_t n, void *data, int extra_len)
{
	int ret = 0;
	struct islpci_mgmtframe *response;
	int response_op = PIMFOR_OP_ERROR;
	int dlen;
	u32 oid;

	BUG_ON(OID_NUM_LAST <= n);

	dlen = isl_oid[n].size;
	oid = isl_oid[n].oid;

	mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, data);

	if (islpci_get_state(priv) >= PRV_STATE_READY) {
		ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid,
					     data, dlen + extra_len, &response);
		if (!ret) {
			response_op = response->header->operation;
			islpci_mgt_release(response);
		}
		if (ret || response_op == PIMFOR_OP_ERROR)
			ret = -EIO;
	} else
		ret = -EIO;

	
	if (data)
		mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data);

	return ret;
}
int
mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data)
{
	int ret = 0;
	struct islpci_mgmtframe *response = NULL;
	int response_op = PIMFOR_OP_ERROR;
	int dlen;
	void *cache, *_data = data;
	u32 oid;

	BUG_ON(OID_NUM_LAST <= n);
	BUG_ON(extra > isl_oid[n].range);

	if (!priv->mib)
		/* memory has been freed */
		return -1;

	dlen = isl_oid[n].size;
	cache = priv->mib[n];
	cache += (cache ? extra * dlen : 0);
	oid = isl_oid[n].oid + extra;

	if (_data == NULL)
		/* we are requested to re-set a cached value */
		_data = cache;
	else
		mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, _data);
	/* If we are going to write to the cache, we don't want anyone to read
	 * it -> acquire write lock.
	 * Else we could acquire a read lock to be sure we don't bother the
	 * commit process (which takes a write lock). But I'm not sure if it's
	 * needed.
	 */
	if (cache)
		down_write(&priv->mib_sem);

	if (islpci_get_state(priv) >= PRV_STATE_READY) {
		ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid,
					     _data, dlen, &response);
		if (!ret) {
			response_op = response->header->operation;
			islpci_mgt_release(response);
		}
		if (ret || response_op == PIMFOR_OP_ERROR)
			ret = -EIO;
	} else if (!cache)
		ret = -EIO;

	if (cache) {
		if (!ret && data)
			memcpy(cache, _data, dlen);
		up_write(&priv->mib_sem);
	}

	/* re-set given data to what it was */
	if (data)
		mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data);

	return ret;
}
Exemple #4
0
int
mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data)
{
	int ret = 0;
	struct islpci_mgmtframe *response = NULL;
	int response_op = PIMFOR_OP_ERROR;
	int dlen;
	void *cache, *_data = data;
	u32 oid;

	BUG_ON(OID_NUM_LAST <= n);
	BUG_ON(extra > isl_oid[n].range);

	if (!priv->mib)
		
		return -1;

	dlen = isl_oid[n].size;
	cache = priv->mib[n];
	cache += (cache ? extra * dlen : 0);
	oid = isl_oid[n].oid + extra;

	if (_data == NULL)
		
		_data = cache;
	else
		mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, _data);
	
	if (cache)
		down_write(&priv->mib_sem);

	if (islpci_get_state(priv) >= PRV_STATE_READY) {
		ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid,
					     _data, dlen, &response);
		if (!ret) {
			response_op = response->header->operation;
			islpci_mgt_release(response);
		}
		if (ret || response_op == PIMFOR_OP_ERROR)
			ret = -EIO;
	} else if (!cache)
		ret = -EIO;

	if (cache) {
		if (!ret && data)
			memcpy(cache, _data, dlen);
		up_write(&priv->mib_sem);
	}

	
	if (data)
		mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data);

	return ret;
}
static int
mgt_update_addr(islpci_private *priv)
{
	struct islpci_mgmtframe *res;
	int ret;

	ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET,
				     isl_oid[GEN_OID_MACADDRESS].oid, NULL,
				     isl_oid[GEN_OID_MACADDRESS].size, &res);

	if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR))
		memcpy(priv->ndev->dev_addr, res->data, 6);
	else
		ret = -EIO;
	if (res)
		islpci_mgt_release(res);

	if (ret)
		printk(KERN_ERR "%s: mgt_update_addr: failure\n", priv->ndev->name);
	return ret;
}
int
mgt_get_request(islpci_private *priv, enum oid_num_t n, int extra, void *data,
		union oid_res_t *res)
{

	int ret = -EIO;
	int reslen = 0;
	struct islpci_mgmtframe *response = NULL;

	int dlen;
	void *cache, *_res = NULL;
	u32 oid;

	BUG_ON(OID_NUM_LAST <= n);
	BUG_ON(extra > isl_oid[n].range);

	res->ptr = NULL;

	if (!priv->mib)
		
		return -1;

	dlen = isl_oid[n].size;
	cache = priv->mib[n];
	cache += cache ? extra * dlen : 0;
	oid = isl_oid[n].oid + extra;
	reslen = dlen;

	if (cache)
		down_read(&priv->mib_sem);

	if (islpci_get_state(priv) >= PRV_STATE_READY) {
		ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET,
					     oid, data, dlen, &response);
		if (ret || !response ||
		    response->header->operation == PIMFOR_OP_ERROR) {
			if (response)
				islpci_mgt_release(response);
			ret = -EIO;
		}
		if (!ret) {
			_res = response->data;
			reslen = response->header->length;
		}
	} else if (cache) {
		_res = cache;
		ret = 0;
	}
	if ((isl_oid[n].flags & OID_FLAG_TYPE) == OID_TYPE_U32)
		res->u = ret ? 0 : le32_to_cpu(*(u32 *) _res);
	else {
		res->ptr = kmalloc(reslen, GFP_KERNEL);
		BUG_ON(res->ptr == NULL);
		if (ret)
			memset(res->ptr, 0, reslen);
		else {
			memcpy(res->ptr, _res, reslen);
			mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE,
				      res->ptr);
		}
	}
	if (cache)
		up_read(&priv->mib_sem);

	if (response && !ret)
		islpci_mgt_release(response);

	if (reslen > isl_oid[n].size)
		printk(KERN_DEBUG
		       "mgt_get_request(0x%x): received data length was bigger "
		       "than expected (%d > %d). Memory is probably corrupted...",
		       oid, reslen, isl_oid[n].size);

	return ret;
}