Commit fdd9fd5c authored by Sudeep Dutt's avatar Sudeep Dutt Committed by Greg Kroah-Hartman

misc: mic: SCIF messaging and node enumeration APIs

SCIF messaging APIs which allow sending messages between the SCIF
endpoints via a byte stream based ring buffer which has been
optimized to avoid reads across PCIe. The SCIF messaging APIs
are typically used for short < 1024 byte messages for best
performance while the RDMA APIs which will be submitted in a future
patch series is recommended for larger transfers. The node
enumeration API enables a user to query for the number of nodes
online in the SCIF network and their node ids.
Reviewed-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: default avatarNikhil Rao <nikhil.rao@intel.com>
Signed-off-by: default avatarSudeep Dutt <sudeep.dutt@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 76371c7c
This diff is collapsed.
......@@ -319,3 +319,35 @@ void scif_discnt_ack(struct scif_dev *scifdev, struct scifmsg *msg)
spin_unlock(&ep->lock);
complete(&ep->discon);
}
/**
* scif_clientsend() - Respond to SCIF_CLIENT_SEND interrupt message
* @msg: Interrupt message
*
* Remote side is confirming send or receive interrupt handling is complete.
*/
void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg)
{
struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
spin_lock(&ep->lock);
if (SCIFEP_CONNECTED == ep->state)
wake_up_interruptible(&ep->recvwq);
spin_unlock(&ep->lock);
}
/**
* scif_clientrcvd() - Respond to SCIF_CLIENT_RCVD interrupt message
* @msg: Interrupt message
*
* Remote side is confirming send or receive interrupt handling is complete.
*/
void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg)
{
struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
spin_lock(&ep->lock);
if (SCIFEP_CONNECTED == ep->state)
wake_up_interruptible(&ep->sendwq);
spin_unlock(&ep->lock);
}
......@@ -144,6 +144,8 @@ int scif_rsrv_port(u16 port);
void scif_get_port(u16 port);
int scif_get_new_port(void);
void scif_put_port(u16 port);
int scif_user_send(scif_epd_t epd, void __user *msg, int len, int flags);
int scif_user_recv(scif_epd_t epd, void __user *msg, int len, int flags);
void scif_cnctreq(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_cnctgnt(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_cnctgnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
......@@ -151,6 +153,8 @@ void scif_cnctgnt_nack(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_cnctrej(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_discnct(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_discnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg);
int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block);
int __scif_flush(scif_epd_t epd);
#endif /* SCIF_EPD_H */
......@@ -69,6 +69,7 @@ static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
struct scif_endpt *priv = f->private_data;
void __user *argp = (void __user *)arg;
int err = 0;
struct scifioctl_msg request;
bool non_block = false;
non_block = !!(f->f_flags & O_NONBLOCK);
......@@ -197,6 +198,98 @@ static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
f->private_data = newep;
return 0;
}
case SCIF_SEND:
{
struct scif_endpt *priv = f->private_data;
if (copy_from_user(&request, argp,
sizeof(struct scifioctl_msg))) {
err = -EFAULT;
goto send_err;
}
err = scif_user_send(priv, (void __user *)request.msg,
request.len, request.flags);
if (err < 0)
goto send_err;
if (copy_to_user(&
((struct scifioctl_msg __user *)argp)->out_len,
&err, sizeof(err))) {
err = -EFAULT;
goto send_err;
}
err = 0;
send_err:
scif_err_debug(err, "scif_send");
return err;
}
case SCIF_RECV:
{
struct scif_endpt *priv = f->private_data;
if (copy_from_user(&request, argp,
sizeof(struct scifioctl_msg))) {
err = -EFAULT;
goto recv_err;
}
err = scif_user_recv(priv, (void __user *)request.msg,
request.len, request.flags);
if (err < 0)
goto recv_err;
if (copy_to_user(&
((struct scifioctl_msg __user *)argp)->out_len,
&err, sizeof(err))) {
err = -EFAULT;
goto recv_err;
}
err = 0;
recv_err:
scif_err_debug(err, "scif_recv");
return err;
}
case SCIF_GET_NODEIDS:
{
struct scifioctl_node_ids node_ids;
int entries;
u16 *nodes;
void __user *unodes, *uself;
u16 self;
if (copy_from_user(&node_ids, argp, sizeof(node_ids))) {
err = -EFAULT;
goto getnodes_err2;
}
entries = min_t(int, scif_info.maxid, node_ids.len);
nodes = kmalloc_array(entries, sizeof(u16), GFP_KERNEL);
if (entries && !nodes) {
err = -ENOMEM;
goto getnodes_err2;
}
node_ids.len = scif_get_node_ids(nodes, entries, &self);
unodes = (void __user *)node_ids.nodes;
if (copy_to_user(unodes, nodes, sizeof(u16) * entries)) {
err = -EFAULT;
goto getnodes_err1;
}
uself = (void __user *)node_ids.self;
if (copy_to_user(uself, &self, sizeof(u16))) {
err = -EFAULT;
goto getnodes_err1;
}
if (copy_to_user(argp, &node_ids, sizeof(node_ids))) {
err = -EFAULT;
goto getnodes_err1;
}
getnodes_err1:
kfree(nodes);
getnodes_err2:
return err;
}
}
return -EINVAL;
}
......
......@@ -218,3 +218,20 @@ void scif_disconnect_node(u32 node_id, bool mgmt_initiated)
(atomic_read(&scifdev->disconn_rescnt) == 1),
SCIF_NODE_ALIVE_TIMEOUT);
}
void scif_get_node_info(void)
{
struct scifmsg msg;
DECLARE_COMPLETION_ONSTACK(node_info);
msg.uop = SCIF_GET_NODE_INFO;
msg.src.node = scif_info.nodeid;
msg.dst.node = SCIF_MGMT_NODE;
msg.payload[3] = (u64)&node_info;
if ((scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], &msg)))
return;
/* Wait for a response with SCIF_GET_NODE_INFO */
wait_for_completion(&node_info);
}
......@@ -570,7 +570,10 @@ static char *message_types[] = {"BAD",
"CNCT_GNTNACK",
"CNCT_REJ",
"DISCNCT",
"DISCNT_ACK"};
"DISCNT_ACK",
"CLIENT_SENT",
"CLIENT_RCVD",
"SCIF_GET_NODE_INFO"};
static void
scif_display_message(struct scif_dev *scifdev, struct scifmsg *msg,
......@@ -951,6 +954,34 @@ scif_node_remove_ack(struct scif_dev *scifdev, struct scifmsg *msg)
wake_up(&sdev->disconn_wq);
}
/**
* scif_get_node_info: Respond to SCIF_GET_NODE_INFO interrupt message
* @msg: Interrupt message
*
* Retrieve node info i.e maxid and total from the mgmt node.
*/
static __always_inline void
scif_get_node_info_resp(struct scif_dev *scifdev, struct scifmsg *msg)
{
if (scif_is_mgmt_node()) {
swap(msg->dst.node, msg->src.node);
mutex_lock(&scif_info.conflock);
msg->payload[1] = scif_info.maxid;
msg->payload[2] = scif_info.total;
mutex_unlock(&scif_info.conflock);
scif_nodeqp_send(scifdev, msg);
} else {
struct completion *node_info =
(struct completion *)msg->payload[3];
mutex_lock(&scif_info.conflock);
scif_info.maxid = msg->payload[1];
scif_info.total = msg->payload[2];
complete_all(node_info);
mutex_unlock(&scif_info.conflock);
}
}
static void
scif_msg_unknown(struct scif_dev *scifdev, struct scifmsg *msg)
{
......@@ -978,6 +1009,9 @@ static void (*scif_intr_func[SCIF_MAX_MSG + 1])
scif_cnctrej, /* SCIF_CNCT_REJ */
scif_discnct, /* SCIF_DISCNCT */
scif_discnt_ack, /* SCIF_DISCNT_ACK */
scif_clientsend, /* SCIF_CLIENT_SENT */
scif_clientrcvd, /* SCIF_CLIENT_RCVD */
scif_get_node_info_resp,/* SCIF_GET_NODE_INFO */
};
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment