/* * struct s10_svc_buf * buf: virtual address of buf provided by service layer * lock: locked if buffer is in use
*/ struct s10_svc_buf { char *buf; unsignedlong lock;
};
ret = stratix10_svc_send(chan, &msg);
dev_dbg(dev, "stratix10_svc_send returned status %d\n", ret);
return ret;
}
/* * Free buffers allocated from the service layer's pool that are not in use. * Return true when all buffers are freed.
*/ staticbool s10_free_buffers(struct fpga_manager *mgr)
{ struct s10_priv *priv = mgr->priv;
uint num_free = 0;
uint i;
for (i = 0; i < NUM_SVC_BUFS; i++) { if (!priv->svc_bufs[i].buf) {
num_free++; continue;
}
/* * Returns count of how many buffers are not in use.
*/ static uint s10_free_buffer_count(struct fpga_manager *mgr)
{ struct s10_priv *priv = mgr->priv;
uint num_free = 0;
uint i;
for (i = 0; i < NUM_SVC_BUFS; i++) if (!priv->svc_bufs[i].buf)
num_free++;
return num_free;
}
/* * s10_unlock_bufs * Given the returned buffer address, match that address to our buffer struct * and unlock that buffer. This marks it as available to be refilled and sent * (or freed). * priv: private data * kaddr: kernel address of buffer that was returned from service layer
*/ staticvoid s10_unlock_bufs(struct s10_priv *priv, void *kaddr)
{
uint i;
if (!kaddr) return;
for (i = 0; i < NUM_SVC_BUFS; i++) if (priv->svc_bufs[i].buf == kaddr) {
clear_bit_unlock(SVC_BUF_LOCK,
&priv->svc_bufs[i].lock); return;
}
WARN(1, "Unknown buffer returned from service layer %p\n", kaddr);
}
/* * s10_receive_callback - callback for service layer to use to provide client * (this driver) messages received through the mailbox. * client: service layer client struct * data: message from service layer
*/ staticvoid s10_receive_callback(struct stratix10_svc_client *client, struct stratix10_svc_cb_data *data)
{ struct s10_priv *priv = client->priv;
u32 status; int i;
/* * Here we set status bits as we receive them. Elsewhere, we always use * test_and_clear_bit() to check status in priv->status
*/ for (i = 0; i <= SVC_STATUS_ERROR; i++) if (status & (1 << i))
set_bit(i, &priv->status);
reinit_completion(&priv->status_return_completion);
ret = s10_svc_send_msg(priv, COMMAND_RECONFIG,
&ctype, sizeof(ctype)); if (ret < 0) goto init_done;
ret = wait_for_completion_timeout(
&priv->status_return_completion, S10_RECONFIG_TIMEOUT); if (!ret) {
dev_err(dev, "timeout waiting for RECONFIG_REQUEST\n");
ret = -ETIMEDOUT; goto init_done;
}
ret = 0; if (!test_and_clear_bit(SVC_STATUS_OK, &priv->status)) {
ret = -ETIMEDOUT; goto init_done;
}
/* Allocate buffers from the service layer's pool. */ for (i = 0; i < NUM_SVC_BUFS; i++) {
kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE); if (IS_ERR(kbuf)) {
s10_free_buffers(mgr);
ret = PTR_ERR(kbuf); goto init_done;
}
/* * s10_send_buf - send a buffer to the service layer queue * mgr: fpga manager struct * buf: fpga image buffer * count: size of buf in bytes * Returns # of bytes transferred or -ENOBUFS if the all the buffers are in use * or if the service queue is full. Never returns 0.
*/ staticint s10_send_buf(struct fpga_manager *mgr, constchar *buf, size_t count)
{ struct s10_priv *priv = mgr->priv; struct device *dev = priv->client.dev; void *svc_buf;
size_t xfer_sz; int ret;
uint i;
/* get/lock a buffer that that's not being used */ for (i = 0; i < NUM_SVC_BUFS; i++) if (!test_and_set_bit_lock(SVC_BUF_LOCK,
&priv->svc_bufs[i].lock)) break;
svc_buf = priv->svc_bufs[i].buf;
memcpy(svc_buf, buf, xfer_sz);
ret = s10_svc_send_msg(priv, COMMAND_RECONFIG_DATA_SUBMIT,
svc_buf, xfer_sz); if (ret < 0) {
dev_err(dev, "Error while sending data to service layer (%d)", ret);
clear_bit_unlock(SVC_BUF_LOCK, &priv->svc_bufs[i].lock); return ret;
}
return xfer_sz;
}
/* * Send an FPGA image to privileged layers to write to the FPGA. When done * sending, free all service layer buffers we allocated in write_init.
*/ staticint s10_ops_write(struct fpga_manager *mgr, constchar *buf,
size_t count)
{ struct s10_priv *priv = mgr->priv; struct device *dev = priv->client.dev; long wait_status; int sent = 0; int ret = 0;
/* * Loop waiting for buffers to be returned. When a buffer is returned, * reuse it to send more data or free if if all data has been sent.
*/ while (count > 0 || s10_free_buffer_count(mgr) != NUM_SVC_BUFS) {
reinit_completion(&priv->status_return_completion);
if (count > 0) {
sent = s10_send_buf(mgr, buf, count); if (sent < 0) continue;
ret = s10_svc_send_msg(
priv, COMMAND_RECONFIG_DATA_CLAIM,
NULL, 0); if (ret < 0) break;
}
/* * If callback hasn't already happened, wait for buffers to be * returned from service layer
*/
wait_status = 1; /* not timed out */ if (!priv->status)
wait_status = wait_for_completion_timeout(
&priv->status_return_completion,
S10_BUFFER_TIMEOUT);
if (test_and_clear_bit(SVC_STATUS_BUFFER_DONE, &priv->status) ||
test_and_clear_bit(SVC_STATUS_BUFFER_SUBMITTED,
&priv->status)) {
ret = 0; continue;
}
if (test_and_clear_bit(SVC_STATUS_ERROR, &priv->status)) {
dev_err(dev, "ERROR - giving up - SVC_STATUS_ERROR\n");
ret = -EFAULT; break;
}
if (!wait_status) {
dev_err(dev, "timeout waiting for svc layer buffers\n");
ret = -ETIMEDOUT; break;
}
}
if (!s10_free_buffers(mgr))
dev_err(dev, "%s not all buffers were freed\n", __func__);
do {
reinit_completion(&priv->status_return_completion);
ret = s10_svc_send_msg(priv, COMMAND_RECONFIG_STATUS, NULL, 0); if (ret < 0) break;
ret = wait_for_completion_timeout(
&priv->status_return_completion, timeout); if (!ret) {
dev_err(dev, "timeout waiting for RECONFIG_COMPLETED\n");
ret = -ETIMEDOUT; break;
} /* Not error or timeout, so ret is # of jiffies until timeout */
timeout = ret;
ret = 0;
if (test_and_clear_bit(SVC_STATUS_COMPLETED, &priv->status)) break;
if (test_and_clear_bit(SVC_STATUS_ERROR, &priv->status)) {
dev_err(dev, "ERROR - giving up - SVC_STATUS_ERROR\n");
ret = -EFAULT; break;
}
} while (1);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.