int fi_bgq_cq_open()

in prov/bgq/src/fi_bgq_cq.c [416:596]


int fi_bgq_cq_open(struct fid_domain *dom,
		struct fi_cq_attr *attr,
		struct fid_cq **cq, void *context)
{
	int ret;
	struct fi_bgq_cq *bgq_cq;
	int lock_required;

	if (!attr) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_CQ,
				"no attr supplied\n");
		errno = FI_EINVAL;
		return -errno;
	}
	ret = fi_bgq_fid_check(&dom->fid, FI_CLASS_DOMAIN, "domain");
	if (ret)
		return ret;

	bgq_cq = calloc(1, sizeof(*bgq_cq));
	if (!bgq_cq) {
		errno = FI_ENOMEM;
		goto err;
	}

	bgq_cq->cq_fid.fid.fclass = FI_CLASS_CQ;
	bgq_cq->cq_fid.fid.context= context;
	bgq_cq->cq_fid.fid.ops    = &fi_bgq_fi_ops;

	bgq_cq->size = attr->size ? attr->size : FI_BGQ_DEFAULT_CQ_DEPTH;

	bgq_cq->domain = (struct fi_bgq_domain *) dom;

	bgq_cq->format = attr->format ? attr->format : FI_CQ_FORMAT_CONTEXT;

	bgq_cq->pending_head = NULL;
	bgq_cq->pending_tail = NULL;
	bgq_cq->completed_head = NULL;
	bgq_cq->completed_tail = NULL;
	bgq_cq->err_head = NULL;
	bgq_cq->err_tail = NULL;

	switch (bgq_cq->domain->threading) {
	case FI_THREAD_ENDPOINT:
	case FI_THREAD_DOMAIN:
	case FI_THREAD_COMPLETION:
		lock_required = 0;
		break;
	case FI_THREAD_FID:
	case FI_THREAD_UNSPEC:
	case FI_THREAD_SAFE:
		lock_required = 1;
		break;
	default:
		errno = FI_EINVAL;
	goto err;
	}

	if (lock_required == 0 &&
			bgq_cq->format == FI_CQ_FORMAT_UNSPEC) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_UNSPEC, 0);
	} else if (lock_required == 0 &&
			bgq_cq->format == FI_CQ_FORMAT_CONTEXT) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_CONTEXT, 0);
	} else if (lock_required == 0 &&
			bgq_cq->format == FI_CQ_FORMAT_MSG) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_MSG, 0);
	} else if (lock_required == 0 &&
			bgq_cq->format == FI_CQ_FORMAT_DATA) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_DATA, 0);
	} else if (lock_required == 0 &&
			bgq_cq->format == FI_CQ_FORMAT_TAGGED) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_TAGGED, 0);
	} else if (lock_required == 1 &&
			bgq_cq->format == FI_CQ_FORMAT_UNSPEC) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_UNSPEC, 1);
	} else if (lock_required == 1 &&
			bgq_cq->format == FI_CQ_FORMAT_CONTEXT) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_CONTEXT, 1);
	} else if (lock_required == 1 &&
			bgq_cq->format == FI_CQ_FORMAT_MSG) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_MSG, 1);
	} else if (lock_required == 1 &&
			bgq_cq->format == FI_CQ_FORMAT_DATA) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_DATA, 1);
	} else if (lock_required == 1 &&
			bgq_cq->format == FI_CQ_FORMAT_TAGGED) {
		bgq_cq->cq_fid.ops =
			&FI_BGQ_CQ_OPS_STRUCT_NAME(FI_CQ_FORMAT_TAGGED, 1);

	} else {
		bgq_cq->cq_fid.ops =
			&fi_bgq_ops_cq_default;
	}

	/* initialize the 'local completion' direct-put descriptor model */
	{
		MUHWI_Descriptor_t * desc = &bgq_cq->local_completion_model;
		MUSPI_DescriptorZeroOut(desc);

		desc->Half_Word0.Prefetch_Only = MUHWI_DESCRIPTOR_PRE_FETCH_ONLY_NO;
		desc->Half_Word1.Interrupt = MUHWI_DESCRIPTOR_DO_NOT_INTERRUPT_ON_PACKET_ARRIVAL;
		desc->Pa_Payload = 0;				/* specified at injection time */
		desc->Message_Length = sizeof(uint64_t);
		desc->Torus_FIFO_Map =
			MUHWI_DESCRIPTOR_TORUS_FIFO_MAP_LOCAL0 |
			MUHWI_DESCRIPTOR_TORUS_FIFO_MAP_LOCAL1;
		desc->PacketHeader.NetworkHeader.pt2pt.Data_Packet_Type = MUHWI_PT2PT_DATA_PACKET_TYPE;
		desc->PacketHeader.NetworkHeader.pt2pt.Hints = 
			MUHWI_PACKET_HINT_A_NONE |
			MUHWI_PACKET_HINT_B_NONE |
			MUHWI_PACKET_HINT_C_NONE |
			MUHWI_PACKET_HINT_D_NONE;
		desc->PacketHeader.NetworkHeader.pt2pt.Byte2.Byte2 = 0;

		desc->PacketHeader.NetworkHeader.pt2pt.Byte3.Byte3 =
			MUHWI_PACKET_VIRTUAL_CHANNEL_DETERMINISTIC;

		desc->PacketHeader.NetworkHeader.pt2pt.Destination.Destination.Destination = 0;	/* not used for local transfers */

		desc->PacketHeader.NetworkHeader.pt2pt.Byte8.Byte8 = MUHWI_PACKET_TYPE_PUT;
		desc->PacketHeader.NetworkHeader.pt2pt.Byte8.Size = 16;
		desc->PacketHeader.messageUnitHeader.Packet_Types.Direct_Put.Rec_Payload_Base_Address_Id = FI_BGQ_MU_BAT_ID_COUNTER;
		desc->PacketHeader.messageUnitHeader.Packet_Types.Direct_Put.Pacing = MUHWI_PACKET_DIRECT_PUT_IS_NOT_PACED;
		desc->PacketHeader.messageUnitHeader.Packet_Types.Direct_Put.Put_Offset_MSB = 0;
		desc->PacketHeader.messageUnitHeader.Packet_Types.Direct_Put.Put_Offset_LSB = 0;
		desc->PacketHeader.messageUnitHeader.Packet_Types.Direct_Put.Unused1 = 0;
		desc->PacketHeader.messageUnitHeader.Packet_Types.Direct_Put.Rec_Counter_Base_Address_Id = FI_BGQ_MU_BAT_ID_COUNTER;
		desc->PacketHeader.messageUnitHeader.Packet_Types.Direct_Put.Valid_Bytes_In_Payload = 0;
		desc->PacketHeader.messageUnitHeader.Packet_Types.Direct_Put.Unused2 = 0;
		desc->PacketHeader.messageUnitHeader.Packet_Types.Direct_Put.Counter_Offset = 0;
	}

	/* allocate the 'std' and 'err' l2atomic fifos */
	{
		struct fi_cq_bgq_l2atomic_data * memptr = NULL;
		size_t bytes = sizeof(struct fi_cq_bgq_l2atomic_data) +
			sizeof(uint64_t) * bgq_cq->size;
		if (posix_memalign((void **)&memptr, 32, bytes)) {
			errno = FI_ENOMEM;
			goto err;
		}
		memset((void*)memptr, 0, bytes);
		bgq_cq->fifo_memptr = (void*)memptr;

		l2atomic_fifo_initialize(&bgq_cq->err_consumer,
			&bgq_cq->err_producer,
			&memptr->err_fifo_data, FI_BGQ_L2ATOMIC_ERR_FIFO_DATA_SIZE);
		l2atomic_fifo_initialize(&bgq_cq->std_consumer,
			&bgq_cq->std_producer,
			&memptr->std_fifo_data, bgq_cq->size);
	};

	bgq_cq->ep_bind_count = 0;
	bgq_cq->progress.ep_count = 0;
	unsigned i;
	for (i=0; i<64; ++i) {		/* TODO - check this array size */
		bgq_cq->ep[i] = NULL;
		bgq_cq->progress.ep[i] = NULL;
	}


	fi_bgq_ref_init(&bgq_cq->domain->fabric->node, &bgq_cq->ref_cnt, "completion queue");
	fi_bgq_ref_inc(&bgq_cq->domain->ref_cnt, "domain");

	*cq = &bgq_cq->cq_fid;

	return 0;
err:
	if(bgq_cq)
		free(bgq_cq);
	return -errno;
}