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>
20 static struct sock *sti_sock;
21 static DEFINE_MUTEX(sti_netlink_mutex);
28 #if defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP2)
29 static int sti_netlink_read(int pid, int seq, void *payload, int size)
33 int ret, len = NLMSG_SPACE(size);
36 skb = alloc_skb(len, GFP_KERNEL);
41 nlh = NLMSG_PUT(skb, pid, seq, STI_READ,
42 len - (sizeof(struct nlmsghdr)));
44 memcpy(NLMSG_DATA(nlh), payload, size);
45 nlh->nlmsg_len = skb->tail - tail;
47 ret = netlink_unicast(sti_sock, skb, pid, MSG_DONTWAIT);
62 * We abuse nlmsg_type and nlmsg_flags for our purposes.
64 * The ID is encoded into the upper 8 bits of the nlmsg_type, while the
65 * channel number is encoded into the upper 8 bits of the nlmsg_flags.
67 static int sti_netlink_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
74 data = NLMSG_DATA(nlh);
75 chan = (nlh->nlmsg_flags >> 8) & 0xff;
76 id = (nlh->nlmsg_type >> 8) & 0xff;
77 size = (int)(nlh->nlmsg_len - ((char *)data - (char *)nlh));
79 switch (nlh->nlmsg_type & 0xff) {
81 sti_channel_write_trace(size, id, data, chan);
83 #if defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP2)
85 data = kmalloc(size, GFP_KERNEL);
88 memset(data, 0, size);
90 len = sti_read_packet(data, size);
91 ret = sti_netlink_read(NETLINK_CB(skb).pid, nlh->nlmsg_seq,
103 static int sti_netlink_receive_skb(struct sk_buff *skb)
105 while (skb->len >= NLMSG_SPACE(0)) {
106 struct nlmsghdr *nlh;
110 nlh = (struct nlmsghdr *)skb->data;
111 if (nlh->nlmsg_len < sizeof(struct nlmsghdr) ||
112 skb->len < nlh->nlmsg_len)
115 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
119 ret = sti_netlink_receive_msg(skb, nlh);
121 netlink_ack(skb, nlh, -ret);
122 else if (nlh->nlmsg_flags & NLM_F_ACK)
123 netlink_ack(skb, nlh, 0);
131 static void sti_netlink_receive(struct sk_buff *skb)
133 if (!mutex_trylock(&sti_netlink_mutex))
136 sti_netlink_receive_skb(skb);
137 mutex_unlock(&sti_netlink_mutex);
140 static int __init sti_netlink_init(void)
142 sti_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0,
143 sti_netlink_receive, NULL,
146 printk(KERN_ERR "STI: Failed to create netlink socket\n");
153 module_init(sti_netlink_init);
155 MODULE_AUTHOR("Paul Mundt");
156 MODULE_LICENSE("GPL");
157 MODULE_DESCRIPTION("STI netlink-driven communications interface");