예제 #1
0
파일: rpmem_fip.c 프로젝트: janekmi/nvml
/*
 * rpmem_fip_persist_gpspm -- (internal) perform persist operation for GPSPM
 */
static int
rpmem_fip_persist_gpspm(struct rpmem_fip *fip, size_t offset,
	size_t len, unsigned lane)
{
	int ret;
	struct rpmem_fip_plane_gpspm *lanep = &fip->lanes.gpspm[lane];

	ret = rpmem_fip_lane_wait(&lanep->lane, FI_SEND);
	if (unlikely(ret)) {
		RPMEM_LOG(ERR, "waiting for SEND buffer");
		return ret;
	}

	RPMEM_ASSERT(!rpmem_fip_lane_busy(&lanep->lane));

	rpmem_fip_lane_begin(&lanep->lane, FI_SEND | FI_RECV);

	void *laddr = (void *)((uintptr_t)fip->laddr + offset);
	uint64_t raddr = fip->raddr + offset;
	struct rpmem_msg_persist *msg;
	struct rpmem_fip_plane_gpspm *gpspm = (void *)lanep;

	/* WRITE for requested memory region */
	ret = rpmem_fip_writemsg(fip->ep, &gpspm->write, laddr, len, raddr);
	if (unlikely(ret)) {
		RPMEM_FI_ERR((int)ret, "RMA write");
		return ret;
	}

	/* SEND persist message */
	msg = rpmem_fip_msg_get_pmsg(&gpspm->send);
	msg->lane = lane;
	msg->addr = raddr;
	msg->size = len;

	ret = rpmem_fip_sendmsg(fip->ep, &gpspm->send);
	if (unlikely(ret)) {
		RPMEM_FI_ERR(ret, "MSG send");
		return ret;
	}

	/* wait for persist operation completion */
	ret = rpmem_fip_lane_wait(&lanep->lane, FI_RECV);
	if (unlikely(ret)) {
		RPMEM_LOG(ERR, "persist operation failed");
		return ret;
	}

	return ret;
}
예제 #2
0
파일: rpmem_fip.c 프로젝트: janekmi/nvml
/*
 * rpmem_fip_read -- perform read operation
 */
int
rpmem_fip_read(struct rpmem_fip *fip, void *buff, size_t len, size_t off)
{
	RPMEM_ASSERT(!rpmem_fip_lane_busy(&fip->rd_lane.lane));

	int ret = 0;
	size_t rd = 0;
	uint8_t *cbuff = buff;
	while (rd < len) {
		rpmem_fip_lane_begin(&fip->rd_lane.lane, FI_READ);

		size_t rd_len = len - rd < RPMEM_RD_BUFF_SIZE ?
				len - rd : RPMEM_RD_BUFF_SIZE;
		size_t rd_off = off + rd;
		uint64_t raddr = fip->raddr + rd_off;

		ret = rpmem_fip_readmsg(fip->ep, &fip->rd_lane.read,
				fip->rd_buff, rd_len, raddr);

		ret = rpmem_fip_lane_wait(&fip->rd_lane.lane, FI_READ);
		if (ret)
			return ret;

		memcpy(&cbuff[rd], fip->rd_buff, rd_len);

		rd += rd_len;
	}

	return ret;
}
예제 #3
0
파일: rpmem_fip.c 프로젝트: mslusarz/nvml
/*
 * rpmem_fip_read -- perform read operation
 */
int
rpmem_fip_read(struct rpmem_fip *fip, void *buff, size_t len, size_t off)
{
	RPMEM_ASSERT(!rpmem_fip_lane_busy(&fip->rd_lane.lane));

	int ret;
	size_t rd = 0;
	uint8_t *cbuff = buff;
	while (rd < len) {
		rpmem_fip_lane_begin(&fip->rd_lane.lane, FI_READ);

		size_t rd_len = len - rd < RPMEM_RD_BUFF_SIZE ?
				len - rd : RPMEM_RD_BUFF_SIZE;
		size_t rd_off = off + rd;
		uint64_t raddr = fip->raddr + rd_off;

		ret = rpmem_fip_readmsg(fip->ep, &fip->rd_lane.read,
				fip->rd_buff, rd_len, raddr);
		VALGRIND_DO_MAKE_MEM_DEFINED(fip->rd_buff, rd_len);

		ret = rpmem_fip_lane_wait(&fip->rd_lane.lane, FI_READ);
		if (ret) {
			ERR("error when processing read request");
			errno = ret;
			return -1;
		}

		memcpy(&cbuff[rd], fip->rd_buff, rd_len);

		rd += rd_len;
	}

	return 0;
}
예제 #4
0
파일: rpmemd_fip.c 프로젝트: astroynao/nvml
/*
 * rpmemd_fip_worker -- worker callback which processes persist
 * operation in GPSPM
 */
static int
rpmemd_fip_worker(void *arg, void *data)
{
	struct rpmemd_fip *fip = arg;
	struct rpmemd_fip_lane *lanep = data;

	int ret = 0;

	/* wait until last SEND message has been processed */
	rpmem_fip_lane_wait(&lanep->lane, FI_SEND);

	/*
	 * Get persist message and persist message response from appropriate
	 * buffers. The persist message is in lane's RECV buffer and the
	 * persist response message in lane's SEND buffer.
	 */
	struct rpmem_msg_persist *pmsg = rpmem_fip_msg_get_pmsg(&lanep->recv);
	struct rpmem_msg_persist_resp *pres =
		rpmem_fip_msg_get_pres(&lanep->send);

	/* verify persist message */
	ret = rpmemd_fip_check_pmsg(fip, pmsg);
	if (unlikely(ret))
		goto err;

	/* return back the lane id */
	pres->lane = pmsg->lane;

	/*
	 * Perform the persist operation.
	 *
	 * XXX
	 *
	 * Maybe the persist could be divided into flush + drain.
	 * We could issue flush operation, do some other work like
	 * posting RECV buffer and then call drain. Need to consider this.
	 */
	fip->persist((void *)pmsg->addr, pmsg->size);

	/* post lane's RECV buffer */
	ret = rpmemd_fip_gpspm_post_msg(fip, &lanep->recv);
	if (unlikely(ret))
		goto err;

	/* initialize lane for waiting for SEND completion */
	rpmem_fip_lane_begin(&lanep->lane, FI_SEND);

	/* post lane's SEND buffer */
	ret = rpmemd_fip_gpspm_post_resp(fip, &lanep->send);
	if (unlikely(ret))
		goto err;
err:
	return ret;
}
예제 #5
0
파일: rpmem_fip.c 프로젝트: janekmi/nvml
/*
 * rpmem_fip_persist_apm -- (internal) perform persist operation for APM
 */
static int
rpmem_fip_persist_apm(struct rpmem_fip *fip, size_t offset,
	size_t len, unsigned lane)
{
	struct rpmem_fip_plane_apm *lanep = &fip->lanes.apm[lane];

	RPMEM_ASSERT(!rpmem_fip_lane_busy(&lanep->lane));

	rpmem_fip_lane_begin(&lanep->lane, FI_READ);

	int ret;
	void *laddr = (void *)((uintptr_t)fip->laddr + offset);
	uint64_t raddr = fip->raddr + offset;

	/* WRITE for requested memory region */
	ret = rpmem_fip_writemsg(fip->ep, &lanep->write, laddr, len, raddr);
	if (unlikely(ret)) {
		RPMEM_FI_ERR(ret, "RMA write");
		return ret;
	}

	/* READ to read-after-write buffer */
	ret = rpmem_fip_readmsg(fip->ep, &lanep->read, &fip->raw_buff,
			sizeof(fip->raw_buff), raddr);
	if (unlikely(ret)) {
		RPMEM_FI_ERR(ret, "RMA read");
		return ret;
	}

	/* wait for READ completion */
	ret = rpmem_fip_lane_wait(&lanep->lane, FI_READ);
	if (unlikely(ret)) {
		RPMEM_LOG(ERR, "waiting for READ completion failed");
		return ret;
	}

	return ret;
}