/* * 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; }
/* * 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; }