[Bluetooth] Use work queue to trigger URB submission
[pandora-kernel.git] / fs / dlm / lowcomms.c
index 09b0124..867f93d 100644 (file)
@@ -55,9 +55,9 @@
 #include "config.h"
 #include "midcomms.h"
 
-static struct sockaddr_storage *local_addr[DLM_MAX_ADDR_COUNT];
-static int                     local_count;
-static int                     local_nodeid;
+static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT];
+static int                     dlm_local_count;
+static int                     dlm_local_nodeid;
 
 /* One of these per connected node */
 
@@ -153,14 +153,14 @@ static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
        struct sockaddr_storage addr;
        int error;
 
-       if (!local_count)
+       if (!dlm_local_count)
                return -1;
 
        error = dlm_nodeid_to_addr(nodeid, &addr);
        if (error)
                return error;
 
-       if (local_addr[0]->ss_family == AF_INET) {
+       if (dlm_local_addr[0]->ss_family == AF_INET) {
                struct sockaddr_in *in4  = (struct sockaddr_in *) &addr;
                struct sockaddr_in *ret4 = (struct sockaddr_in *) retaddr;
                ret4->sin_addr.s_addr = in4->sin_addr.s_addr;
@@ -174,7 +174,7 @@ static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
        return 0;
 }
 
-static struct nodeinfo *nodeid2nodeinfo(int nodeid, int alloc)
+static struct nodeinfo *nodeid2nodeinfo(int nodeid, gfp_t alloc)
 {
        struct nodeinfo *ni;
        int r;
@@ -260,21 +260,21 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
        struct sockaddr_in *local4_addr;
        struct sockaddr_in6 *local6_addr;
 
-       if (!local_count)
+       if (!dlm_local_count)
                return;
 
        if (!port) {
-               if (local_addr[0]->ss_family == AF_INET) {
-                       local4_addr = (struct sockaddr_in *)local_addr[0];
+               if (dlm_local_addr[0]->ss_family == AF_INET) {
+                       local4_addr = (struct sockaddr_in *)dlm_local_addr[0];
                        port = be16_to_cpu(local4_addr->sin_port);
                } else {
-                       local6_addr = (struct sockaddr_in6 *)local_addr[0];
+                       local6_addr = (struct sockaddr_in6 *)dlm_local_addr[0];
                        port = be16_to_cpu(local6_addr->sin6_port);
                }
        }
 
-       saddr->ss_family = local_addr[0]->ss_family;
-       if (local_addr[0]->ss_family == AF_INET) {
+       saddr->ss_family = dlm_local_addr[0]->ss_family;
+       if (dlm_local_addr[0]->ss_family == AF_INET) {
                struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr;
                in4_addr->sin_port = cpu_to_be16(port);
                memset(&in4_addr->sin_zero, 0, sizeof(in4_addr->sin_zero));
@@ -548,7 +548,7 @@ static int receive_from_sock(void)
        }
        len = iov[0].iov_len + iov[1].iov_len;
 
-       r = ret = kernel_recvmsg(sctp_con.sock, &msg, iov, 1, len,
+       r = ret = kernel_recvmsg(sctp_con.sock, &msg, iov, msg.msg_iovlen, len,
                                 MSG_NOSIGNAL | MSG_DONTWAIT);
        if (ret <= 0)
                goto out_close;
@@ -636,7 +636,7 @@ static void init_local(void)
        struct sockaddr_storage sas, *addr;
        int i;
 
-       local_nodeid = dlm_our_nodeid();
+       dlm_local_nodeid = dlm_our_nodeid();
 
        for (i = 0; i < DLM_MAX_ADDR_COUNT - 1; i++) {
                if (dlm_our_addr(&sas, i))
@@ -646,7 +646,7 @@ static void init_local(void)
                if (!addr)
                        break;
                memcpy(addr, &sas, sizeof(*addr));
-               local_addr[local_count++] = addr;
+               dlm_local_addr[dlm_local_count++] = addr;
        }
 }
 
@@ -659,15 +659,15 @@ static int init_sock(void)
        struct sctp_event_subscribe subscribe;
        int result = -EINVAL, num = 1, i, addr_len;
 
-       if (!local_count) {
+       if (!dlm_local_count) {
                init_local();
-               if (!local_count) {
+               if (!dlm_local_count) {
                        log_print("no local IP address has been set");
                        goto out;
                }
        }
 
-       result = sock_create_kern(local_addr[0]->ss_family, SOCK_SEQPACKET,
+       result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_SEQPACKET,
                                  IPPROTO_SCTP, &sock);
        if (result < 0) {
                log_print("Can't create comms socket, check SCTP is loaded");
@@ -700,8 +700,8 @@ static int init_sock(void)
        sctp_con.sock->sk->sk_data_ready = lowcomms_data_ready;
 
        /* Bind to all interfaces. */
-       for (i = 0; i < local_count; i++) {
-               memcpy(&localaddr, local_addr[i], sizeof(localaddr));
+       for (i = 0; i < dlm_local_count; i++) {
+               memcpy(&localaddr, dlm_local_addr[i], sizeof(localaddr));
                make_sockaddr(&localaddr, dlm_config.tcp_port, &addr_len);
 
                result = add_bind_addr(&localaddr, addr_len, num);
@@ -726,7 +726,7 @@ static int init_sock(void)
 }
 
 
-static struct writequeue_entry *new_writequeue_entry(int allocation)
+static struct writequeue_entry *new_writequeue_entry(gfp_t allocation)
 {
        struct writequeue_entry *entry;
 
@@ -748,7 +748,7 @@ static struct writequeue_entry *new_writequeue_entry(int allocation)
        return entry;
 }
 
-void *dlm_lowcomms_get_buffer(int nodeid, int len, int allocation, char **ppc)
+void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
 {
        struct writequeue_entry *e;
        int offset = 0;
@@ -879,7 +879,7 @@ static void initiate_association(int nodeid)
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
        sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
        memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
-       sinfo->sinfo_ppid = cpu_to_le32(local_nodeid);
+       sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid);
 
        outmessage.msg_controllen = cmsg->cmsg_len;
        ret = kernel_sendmsg(sctp_con.sock, &outmessage, iov, 1, 1);
@@ -924,7 +924,7 @@ static int send_to_sock(struct nodeinfo *ni)
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
        sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
        memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
-       sinfo->sinfo_ppid = cpu_to_le32(local_nodeid);
+       sinfo->sinfo_ppid = cpu_to_le32(dlm_local_nodeid);
        sinfo->sinfo_assoc_id = ni->assoc_id;
        outmsg.msg_controllen = cmsg->cmsg_len;
 
@@ -934,11 +934,11 @@ static int send_to_sock(struct nodeinfo *ni)
                        break;
                e = list_entry(ni->writequeue.next, struct writequeue_entry,
                               list);
-               kmap(e->page);
                len = e->len;
                offset = e->offset;
                BUG_ON(len == 0 && e->users == 0);
                spin_unlock(&ni->writequeue_lock);
+               kmap(e->page);
 
                ret = 0;
                if (len) {
@@ -1063,6 +1063,27 @@ static void dealloc_nodeinfo(void)
        }
 }
 
+int dlm_lowcomms_close(int nodeid)
+{
+       struct nodeinfo *ni;
+
+       ni = nodeid2nodeinfo(nodeid, 0);
+       if (!ni)
+               return -1;
+
+       spin_lock(&ni->lock);
+       if (ni->assoc_id) {
+               ni->assoc_id = 0;
+               /* Don't send shutdown here, sctp will just queue it
+                  till the node comes back up! */
+       }
+       spin_unlock(&ni->lock);
+
+       clean_one_writequeue(ni);
+       clear_bit(NI_INIT_PENDING, &ni->flags);
+       return 0;
+}
+
 static int write_list_empty(void)
 {
        int status;
@@ -1169,10 +1190,6 @@ int dlm_lowcomms_start(void)
 {
        int error;
 
-       spin_lock_init(&write_nodes_lock);
-       INIT_LIST_HEAD(&write_nodes);
-       init_rwsem(&nodeinfo_lock);
-
        error = init_sock();
        if (error)
                goto fail_sock;
@@ -1203,6 +1220,9 @@ void dlm_lowcomms_stop(void)
 int dlm_lowcomms_init(void)
 {
        init_waitqueue_head(&lowcomms_recv_wait);
+       spin_lock_init(&write_nodes_lock);
+       INIT_LIST_HEAD(&write_nodes);
+       init_rwsem(&nodeinfo_lock);
        return 0;
 }
 
@@ -1210,9 +1230,9 @@ void dlm_lowcomms_exit(void)
 {
        int i;
 
-       for (i = 0; i < local_count; i++)
-               kfree(local_addr[i]);
-       local_count = 0;
-       local_nodeid = 0;
+       for (i = 0; i < dlm_local_count; i++)
+               kfree(dlm_local_addr[i]);
+       dlm_local_count = 0;
+       dlm_local_nodeid = 0;
 }