Ejemplo n.º 1
0
static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
{
	int i;
	u64 cur_admin_val;
	ib_sa_comp_mask comp_mask = 0;

	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status
		= MLX4_GUID_INFO_STATUS_IDLE;
	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].method
		= MLX4_GUID_INFO_RECORD_SET;

	/* calculate the comp_mask for that record.*/
	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
		cur_admin_val =
			*(u64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
			all_rec_per_port[index].all_recs[GUID_REC_SIZE * i];
		/*
		check the admin value: if it's for delete (~00LL) or
		it is the first guid of the first record (hw guid) or
		the records is not in ownership of the sysadmin and the sm doesn't
		need to assign GUIDs, then don't put it up for assignment.
		*/
		if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val ||
		    (!index && !i) ||
		    MLX4_GUID_NONE_ASSIGN == dev->sriov.alias_guid.
		    ports_guid[port - 1].all_rec_per_port[index].ownership)
			continue;
		comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
	}
	dev->sriov.alias_guid.ports_guid[port - 1].
		all_rec_per_port[index].guid_indexes = comp_mask;
}
Ejemplo n.º 2
0
Archivo: sysfs.c Proyecto: 7799/linux
/* store_admin_alias_guid stores the (new) administratively assigned value of that GUID.
 * Values in buf parameter string:
 *	0			- requests opensm to assign a value.
 *	0xffffffffffffffff	- delete this entry.
 *	other			- guid value assigned by the administrator.
 */
static ssize_t store_admin_alias_guid(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t count)
{
	int record_num;/*0-15*/
	int guid_index_in_rec; /*0 - 7*/
	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
	struct mlx4_ib_dev *mdev = port->dev;
	u64 sysadmin_ag_val;

	record_num = mlx4_ib_iov_dentry->entry_num / 8;
	guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8;
	if (0 == record_num && 0 == guid_index_in_rec) {
		pr_err("GUID 0 block 0 is RO\n");
		return count;
	}
	sscanf(buf, "%llx", &sysadmin_ag_val);
	*(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1].
		all_rec_per_port[record_num].
		all_recs[GUID_REC_SIZE * guid_index_in_rec] =
			cpu_to_be64(sysadmin_ag_val);

	/* Change the state to be pending for update */
	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status
		= MLX4_GUID_INFO_STATUS_IDLE ;

	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method
		= MLX4_GUID_INFO_RECORD_SET;

	switch (sysadmin_ag_val) {
	case MLX4_GUID_FOR_DELETE_VAL:
		mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method
			= MLX4_GUID_INFO_RECORD_DELETE;
		mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
			= MLX4_GUID_SYSADMIN_ASSIGN;
		break;
	/* The sysadmin requests the SM to re-assign */
	case MLX4_NOT_SET_GUID:
		mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
			= MLX4_GUID_DRIVER_ASSIGN;
		break;
	/* The sysadmin requests a specific value.*/
	default:
		mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
			= MLX4_GUID_SYSADMIN_ASSIGN;
		break;
	}

	/* set the record index */
	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes
		= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec);

	mlx4_ib_init_alias_guid_work(mdev, port->num - 1);

	return count;
}
Ejemplo n.º 3
0
/* store_admin_alias_guid stores the (new) administratively assigned value of that GUID.
 * Values in buf parameter string:
 *	0			- requests opensm to assign a value.
 *	0xffffffffffffffff	- delete this entry.
 *	other			- guid value assigned by the administrator.
 */
static ssize_t store_admin_alias_guid(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t count)
{
	int record_num;/*0-15*/
	int guid_index_in_rec; /*0 - 7*/
	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
	struct mlx4_ib_dev *mdev = port->dev;
	unsigned long long sysadmin_ag_val;
	unsigned long flags;

	record_num = mlx4_ib_iov_dentry->entry_num / 8;
	guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8;
	if (0 == record_num && 0 == guid_index_in_rec) {
		pr_err("GUID 0 block 0 is RO\n");
		return count;
	}
	spin_lock_irqsave(&mdev->sriov.alias_guid.ag_work_lock, flags);
	sscanf(buf, "%llx", &sysadmin_ag_val);
	*(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1].
		all_rec_per_port[record_num].
		all_recs[GUID_REC_SIZE * guid_index_in_rec] =
			cpu_to_be64(sysadmin_ag_val);

	/* Change the state to be pending for update */
	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status
		= MLX4_GUID_INFO_STATUS_IDLE ;
	mlx4_set_admin_guid(mdev->dev, cpu_to_be64(sysadmin_ag_val),
			    mlx4_ib_iov_dentry->entry_num,
			    port->num);

	/* set the record index */
	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes
		|= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec);

	spin_unlock_irqrestore(&mdev->sriov.alias_guid.ag_work_lock, flags);
	mlx4_ib_init_alias_guid_work(mdev, port->num - 1);

	return count;
}
Ejemplo n.º 4
0
static void aliasguid_query_handler(int status,
				    struct ib_sa_guidinfo_rec *guid_rec,
				    void *context)
{
	struct mlx4_ib_dev *dev;
	struct mlx4_alias_guid_work_context *cb_ctx = context;
	u8 port_index ;
	int i;
	struct mlx4_sriov_alias_guid_info_rec_det *rec;
	unsigned long flags, flags1;

	if (!context)
		return;

	dev = cb_ctx->dev;
	port_index = cb_ctx->port - 1;
	rec = &dev->sriov.alias_guid.ports_guid[port_index].
		all_rec_per_port[cb_ctx->block_num];

	if (status) {
		rec->status = MLX4_GUID_INFO_STATUS_IDLE;
		pr_debug("(port: %d) failed: status = %d\n",
			 cb_ctx->port, status);
		goto out;
	}

	if (guid_rec->block_num != cb_ctx->block_num) {
		pr_err("block num mismatch: %d != %d\n",
		       cb_ctx->block_num, guid_rec->block_num);
		goto out;
	}

	pr_debug("lid/port: %d/%d, block_num: %d\n",
		 be16_to_cpu(guid_rec->lid), cb_ctx->port,
		 guid_rec->block_num);

	rec = &dev->sriov.alias_guid.ports_guid[port_index].
		all_rec_per_port[guid_rec->block_num];

	rec->status = MLX4_GUID_INFO_STATUS_SET;
	rec->method = MLX4_GUID_INFO_RECORD_SET;

	for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
		__be64 tmp_cur_ag;
		tmp_cur_ag = *(__be64 *)&guid_rec->guid_info_list[i * GUID_REC_SIZE];
		/* check if the SM didn't assign one of the records.
		 * if it didn't, if it was not sysadmin request:
		 * ask the SM to give a new GUID, (instead of the driver request).
		 */
		if (tmp_cur_ag == MLX4_NOT_SET_GUID) {
			mlx4_ib_warn(&dev->ib_dev, "%s:Record num %d in "
				     "block_num: %d was declined by SM, "
				     "ownership by %d (0 = driver, 1=sysAdmin,"
				     " 2=None)\n", __func__, i,
				     guid_rec->block_num, rec->ownership);
			if (rec->ownership == MLX4_GUID_DRIVER_ASSIGN) {
				/* if it is driver assign, asks for new GUID from SM*/
				*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
					MLX4_NOT_SET_GUID;

				/* Mark the record as not assigned, and let it
				 * be sent again in the next work sched.*/
				rec->status = MLX4_GUID_INFO_STATUS_IDLE;
				rec->guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
			}
		} else {
		       /* properly assigned record. */
		       /* We save the GUID we just got from the SM in the
			* admin_guid in order to be persistent, and in the
			* request from the sm the process will ask for the same GUID */
			if (rec->ownership == MLX4_GUID_SYSADMIN_ASSIGN &&
			    tmp_cur_ag != *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE]) {
				/* the sysadmin assignment failed.*/
				mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
					     " admin guid after SysAdmin "
					     "configuration. "
					     "Record num %d in block_num:%d "
					     "was declined by SM, "
					     "new val(0x%llx) was kept\n",
					      __func__, i,
					     guid_rec->block_num,
					     be64_to_cpu(*(__be64 *) &
							 rec->all_recs[i * GUID_REC_SIZE]));
			} else {
				memcpy(&rec->all_recs[i * GUID_REC_SIZE],
				       &guid_rec->guid_info_list[i * GUID_REC_SIZE],
				       GUID_REC_SIZE);
			}
		}
	}
	/*
	The func is call here to close the cases when the
	sm doesn't send smp, so in the sa response the driver
	notifies the slave.
	*/
	mlx4_ib_notify_slaves_on_guid_change(dev, guid_rec->block_num,
					     cb_ctx->port,
					     guid_rec->guid_info_list);
out:
	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
	if (!dev->sriov.is_going_down)
		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq,
				   &dev->sriov.alias_guid.ports_guid[port_index].
				   alias_guid_work, 0);
	if (cb_ctx->sa_query) {
		list_del(&cb_ctx->list);
		kfree(cb_ctx);
	} else
		complete(&cb_ctx->done);
	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
}