Esempio n. 1
0
static
psm2_error_t
am_short_reqrep(ips_scb_t *scb, struct ips_epaddr *ipsaddr,
		psm2_amarg_t *args, int nargs, uint8_t opcode,
		void *src, size_t len, int flags, int pad_bytes)
{
	int i, hdr_qwords = IPS_AM_HDR_NARGS;
	struct ips_proto *proto = ((psm2_epaddr_t)ipsaddr)->proto;
	struct ips_flow *flow = &ipsaddr->flows[proto->msgflowid];

	/* There are a limited number of bits for nargs in the header, making
	   overflow very easy.  Make sure the values match. */
	psmi_assert(nargs == scb->ips_lrh.amhdr_nargs);

	_HFI_VDBG("%s src=%p len=%d, nargs=%d\n",
		  ((opcode == OPCODE_AM_REQUEST) ||
		   (opcode == OPCODE_AM_REQUEST_NOREPLY)) ? "req" : "rep",
		  src, (int)len, nargs);

	if (nargs == 1) {	/* fastpath */
		scb->ips_lrh.data[0].u64w0 = args[0].u64w0;
		hdr_qwords--;
	} else if (nargs > 1) {
		/* Easily unrollable but leave as is in case we can increase
		 * qwords on the chip in the near future */
		for (i = 0; i < IPS_AM_HDR_NARGS; i++, hdr_qwords--)
			scb->ips_lrh.data[i].u64w0 = args[i].u64w0;

		if (nargs > IPS_AM_HDR_NARGS) {
			/* Slow case -- we don't have iovec and not enough
			 * space in the message header, so we have to copy the
			 * user's arguments even if the payload is marked ASYNC
			 */
			uintptr_t bufp = (uintptr_t) ips_scb_buffer(scb);
			size_t arg_payload_len =
			    sizeof(psm2_amarg_t) * (nargs - IPS_AM_HDR_NARGS);

			psmi_mq_mtucpy((void *)bufp,
				       &args[IPS_AM_HDR_NARGS],
				       arg_payload_len);
			bufp += arg_payload_len;
			scb->payload_size = arg_payload_len;

			if (src != NULL && len > 0) {
				psmi_mq_mtucpy((void *)bufp, src, len);
				scb->payload_size += len;
			}

			psmi_assert(pad_bytes < (1 << IPS_AM_HDR_LEN_BITS));
			scb->payload_size += pad_bytes;
			scb->ips_lrh.amhdr_len = pad_bytes;
			goto send_scb;
		}
	}

	if (len == 0) {
		scb->payload_size = 0;
		scb->ips_lrh.amhdr_len = 0;
	} else if (len <= (hdr_qwords << 3)) {
		/* Inline the payload into the header. */
		/* This path CANNOT handle length = 0 due to limited space
		   in the header.  If IPS_SEND_FLAG_AMISTINY is set, an
		   amhdr_len value of 0 means a full payload, i.e.
		   1 << IPS_AM_HDR_LEN_BITS bytes of packed payload. */
		psmi_assert(len > 0);

		psmi_mq_mtucpy(&scb->ips_lrh.
			       data[IPS_AM_HDR_NARGS - hdr_qwords], src, len);
		scb->payload_size = 0;
		psmi_assert(len <= (1 << IPS_AM_HDR_LEN_BITS));
		scb->ips_lrh.amhdr_len = len & ((1 << IPS_AM_HDR_LEN_BITS) - 1);
		scb->flags |= IPS_SEND_FLAG_AMISTINY;
	} else { /* Whatever's left requires a separate payload */
		if (ips_scb_buffer(scb) == NULL) /* Just attach the buffer */
			ips_scb_buffer(scb) = src;
		else /* May need to re-xmit user data, keep it around */
			psmi_mq_mtucpy(ips_scb_buffer(scb), src, len);

		psmi_assert(pad_bytes < (1 << IPS_AM_HDR_LEN_BITS));
		scb->payload_size = len + pad_bytes;
		scb->ips_lrh.amhdr_len = pad_bytes;
	}

send_scb:
	ips_scb_opcode(scb) = opcode;
	scb->ips_lrh.khdr.kdeth0 = ipsaddr->msgctl->am_send_seqnum++;
	ips_proto_flow_enqueue(flow, scb);
	flow->flush(flow, NULL);

	return PSM2_OK;
}
Esempio n. 2
0
/* Given the unit number, return an error, or the corresponding LID
   For now, it's used only so the MPI code can determine it's own
   LID, and which other LIDs (if any) are also assigned to this node
   Returns an int, so -1 indicates an error.  0 may indicate that
   the unit is valid, but no LID has been assigned.
   No error print because we call this for both potential
   ports without knowing if both ports exist (or are connected) */
int hfi_get_port_lid(int unit, int port)
{
	int ret;
	char *state;
	int64_t val;

	ret = hfi_sysfs_port_read(unit, port, "phys_state", &state);
	if (ret == -1) {
		if (errno == ENODEV)
			/* this is "normal" for port != 1, on single port chips */
			_HFI_VDBG
			    ("Failed to get phys_state for unit %u:%u: %s\n",
			     unit, port, strerror(errno));
		else
			_HFI_DBG
			    ("Failed to get phys_state for unit %u:%u: %s\n",
			     unit, port, strerror(errno));
	} else {
		if (strncmp(state, "5: LinkUp", 9)) {
			_HFI_DBG("Link is not Up for unit %u:%u\n", unit, port);
			ret = -1;
		}
		free(state);
	}
	/* If link is not up, we think lid not valid */
	if (ret == -1)
		return ret;

	ret = hfi_sysfs_port_read_s64(unit, port, "lid", &val, 0);
	_HFI_VDBG("hfi_get_port_lid: ret %d, unit %d port %d\n", ret, unit,
		  port);

	if (ret == -1) {
		if (errno == ENODEV)
			/* this is "normal" for port != 1, on single port chips */
			_HFI_VDBG("Failed to get LID for unit %u:%u: %s\n",
				  unit, port, strerror(errno));
		else
			_HFI_DBG("Failed to get LID for unit %u:%u: %s\n",
				 unit, port, strerror(errno));
	} else {
		ret = val;

/* disable this feature since we don't have a way to provide
   file descriptor in multiple context case. */
#if 0
		if (getenv("HFI_DIAG_LID_LOOP")) {
			/* provides diagnostic ability to run MPI, etc. even */
			/* on loopback, by claiming a different LID for each context */
			struct hfi1_ctxt_info info;
			struct hfi1_cmd cmd;
			cmd.type = HFI1_CMD_CTXT_INFO;
			cmd.cmd.ctxt_info = (uintptr_t) &info;
			if (__hfi_lastfd == -1)
				_HFI_INFO
				    ("Can't run CONTEXT_INFO for lid_loop, fd not set\n");
			else if (write(__hfi_lastfd, &cmd, sizeof(cmd)) == -1)
				_HFI_INFO("CONTEXT_INFO command failed: %s\n",
					  strerror(errno));
			else if (!info.context)
				_HFI_INFO("CONTEXT_INFO returned context 0!\n");
			else {
				_HFI_PRDBG
				    ("Using lid 0x%x, base %x, context %x\n",
				     ret + info.context, ret, info.context);
				ret += info.context;
			}
		}
#endif
	}

	return ret;
}