devices/rtdmnet.c : abuse RTDM api to allow sendmsg and recvmsg to be called indirectly from userland cobalt process ioctl, while rtdm_socket is created from a kernel thread.
--- a/devices/rtdmnet.c Sun Oct 07 17:05:42 2018 +0200
+++ b/devices/rtdmnet.c Mon Oct 08 23:16:34 2018 +0200
@@ -80,6 +80,7 @@
struct net_device *netdev;
struct rtnet_device *used_netdev;
int socket;
+ struct rtdm_fd *rtdm_fd;
ec_device_t *ecdev;
uint8_t *rx_buf;
// struct sockaddr_ll dest_addr;
@@ -195,6 +196,7 @@
ecdev_withdraw(dev->ecdev);
}
if (!(dev->socket < 0)) {
+ rtdm_fd_put(dev->rtdm_fd);
rtdm_close(dev->socket);
dev->socket = -1;
}
@@ -228,6 +230,24 @@
printk(" rtdm_socket() = %d!\n", dev->socket);
return dev->socket;
}
+
+ /* HACK :
+ When this is called, process is 'kernel', i.e.
+ cobalt_ppd_get(0) == &cobalt_kernel_ppd
+
+ This makes a problem later when recvmsg or sendmsg is indirectly called
+ from application's cobalt thread through RTDM IOCTL. From such thread,
+ RTDM can't resolv socket's 'ufd' that rtdm_socket just returned.
+
+ To keep a usable file descriptor for that socket, even when calling
+ from cobalt thread (i.e. if (cobalt_ppd_get(0) != &cobalt_kernel_ppd))
+ we resolve it here in advance */
+ dev->rtdm_fd = rtdm_fd_get(dev->socket,0);
+ if (IS_ERR(dev->rtdm_fd)){
+ printk(" rtdm_fd_get() = %d!\n", ret);
+ ret = PTR_ERR(dev->rtdm_fd);
+ goto out_err;
+ }
printk(KERN_ERR PFX "Binding socket to interface %i (%s).\n",
desc->ifindex, desc->name);
@@ -240,12 +260,17 @@
sizeof(struct sockaddr_ll));
if (ret < 0) {
printk(" rtdm_bind() = %d!\n", ret);
- rtdm_close(dev->socket);
- dev->socket = -1;
- return ret;
+ goto out_err;
}
return 0;
+
+out_err:
+ rtdm_fd_put(dev->rtdm_fd);
+ rtdm_close(dev->socket);
+ dev->socket = -1;
+ return ret;
+
}
/*****************************************************************************/
@@ -351,7 +376,8 @@
msg.msg_iovlen = 1;
if (rtdm_in_rt_context())
- ret = rtdm_sendmsg(dev->socket, &msg, 0);
+ /* HACK : call fd ops directly as in rtdm's fd.c */
+ ret = dev->rtdm_fd->ops->sendmsg_rt(dev->rtdm_fd, &msg, 0);
else
ret = nrt_rtdm_sendmsg(dev->socket, &msg);
@@ -406,9 +432,10 @@
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
- if (rtdm_in_rt_context())
- ret = rtdm_recvmsg(dev->socket, &msg, MSG_DONTWAIT);
- else
+ if (rtdm_in_rt_context()){
+ /* HACK : call fd ops directly as in rtdm's fd.c */
+ ret = dev->rtdm_fd->ops->recvmsg_rt(dev->rtdm_fd, &msg, MSG_DONTWAIT);
+ }else
ret = nrt_rtdm_recvmsg(dev->socket, &msg);
if (ret > 0) {