2 * OMAP STI/XTI communications interface via netlink socket.
4 * Copyright (C) 2004, 2005, 2006 Nokia Corporation
5 * Written by: Paul Mundt <paul.mundt@nokia.com>
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/netlink.h>
14 #include <linux/socket.h>
15 #include <linux/skbuff.h>
16 #include <linux/mutex.h>
18 #include <asm/arch/sti.h>
20 static struct sock *sti_sock;
21 static DEFINE_MUTEX(sti_netlink_mutex);
28 static int sti_netlink_read(int pid, int seq, void *payload, int size)
32 int ret, len = NLMSG_SPACE(size);
35 skb = alloc_skb(len, GFP_KERNEL);
40 nlh = NLMSG_PUT(skb, pid, seq, STI_READ,
41 len - (sizeof(struct nlmsghdr)));
43 memcpy(NLMSG_DATA(nlh), payload, size);
44 nlh->nlmsg_len = skb->tail - tail;
46 ret = netlink_unicast(sti_sock, skb, pid, MSG_DONTWAIT);
60 * We abuse nlmsg_type and nlmsg_flags for our purposes.
62 * The ID is encoded into the upper 8 bits of the nlmsg_type, while the
63 * channel number is encoded into the upper 8 bits of the nlmsg_flags.
65 static int sti_netlink_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
69 int size, ret = 0, len = 0;
71 data = NLMSG_DATA(nlh);
72 chan = (nlh->nlmsg_flags >> 8) & 0xff;
73 id = (nlh->nlmsg_type >> 8) & 0xff;
74 size = (int)(nlh->nlmsg_len - ((char *)data - (char *)nlh));
76 switch (nlh->nlmsg_type & 0xff) {
78 sti_channel_write_trace(size, id, data, chan);
81 data = kmalloc(size, GFP_KERNEL);
84 memset(data, 0, size);
86 len = sti_read_packet(data, size);
87 ret = sti_netlink_read(NETLINK_CB(skb).pid, nlh->nlmsg_seq,
98 static int sti_netlink_receive_skb(struct sk_buff *skb)
100 while (skb->len >= NLMSG_SPACE(0)) {
101 struct nlmsghdr *nlh;
105 nlh = (struct nlmsghdr *)skb->data;
106 if (nlh->nlmsg_len < sizeof(struct nlmsghdr) ||
107 skb->len < nlh->nlmsg_len)
110 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
114 ret = sti_netlink_receive_msg(skb, nlh);
116 netlink_ack(skb, nlh, -ret);
117 else if (nlh->nlmsg_flags & NLM_F_ACK)
118 netlink_ack(skb, nlh, 0);
126 static void sti_netlink_receive(struct sk_buff *skb)
128 if (!mutex_trylock(&sti_netlink_mutex))
131 sti_netlink_receive_skb(skb);
132 mutex_unlock(&sti_netlink_mutex);
135 static int __init sti_netlink_init(void)
137 sti_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0,
138 sti_netlink_receive, NULL,
141 printk(KERN_ERR "STI: Failed to create netlink socket\n");
148 module_init(sti_netlink_init);
150 MODULE_AUTHOR("Paul Mundt");
151 MODULE_LICENSE("GPL");
152 MODULE_DESCRIPTION("STI netlink-driven communications interface");