ozproto.c revision 50222db4b03ac8f3259c6d39bbd585ed3358f70f
11619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/* ----------------------------------------------------------------------------- 21619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Copyright (c) 2011 Ozmo Inc 31619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Released under the GNU General Public License Version 2 (GPLv2). 41619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * ----------------------------------------------------------------------------- 51619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 605f608f237dcc3c4e5188d054d9918cbfd2916c2Joe Perches 71619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/module.h> 81619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/timer.h> 91619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/sched.h> 101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/netdevice.h> 1193dc5e429b4d8ac8d683b61052592812e9353f9fdingtianhong#include <linux/etherdevice.h> 121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/errno.h> 131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/ieee80211.h> 142b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger#include <linux/slab.h> 15f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches#include "ozdbg.h" 161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozprotocol.h" 171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozeltbuf.h" 181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozpd.h" 191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozproto.h" 201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozusbsvc.h" 2105f608f237dcc3c4e5188d054d9918cbfd2916c2Joe Perches 221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozappif.h" 231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <asm/unaligned.h> 241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/uaccess.h> 251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <net/psnap.h> 266e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_CF_CONN_SUCCESS 1 281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_CF_CONN_FAILURE 2 291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_DO_STOP 1 311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_DO_SLEEP 2 321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystruct oz_binding { 341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct packet_type ptype; 351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly char name[OZ_MAX_BINDING_LEN]; 368a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare struct list_head link; 371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly}; 381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 394e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 406b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil * External variable 416b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil */ 426b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil 436b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra PatilDEFINE_SPINLOCK(g_polling_lock); 446b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil/* 451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Static external variables. 461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic LIST_HEAD(g_pd_list); 488a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujarestatic LIST_HEAD(g_binding); 491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic DEFINE_SPINLOCK(g_binding_lock); 501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic struct sk_buff_head g_rx_queue; 511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u8 g_session_id; 521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u16 g_apps = 0x1; 531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic int g_processing_rx; 546e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 552b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaegerstruct kmem_cache *oz_elt_info_cache; 5650222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaegerstruct kmem_cache *oz_tx_frame_cache; 572b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger 584e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u8 oz_get_new_session_id(u8 exclude) 621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (++g_session_id == 0) 641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_session_id = 1; 651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (g_session_id == exclude) { 661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (++g_session_id == 0) 671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_session_id = 1; 681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return g_session_id; 701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 716e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 724e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_send_conn_rsp(struct oz_pd *pd, u8 status) 761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct sk_buff *skb; 781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct net_device *dev = pd->net_dev; 791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_hdr *oz_hdr; 801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt *elt; 811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_connect_rsp *body; 8218f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int sz = sizeof(struct oz_hdr) + sizeof(struct oz_elt) + 841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly sizeof(struct oz_elt_connect_rsp); 856b790d0fae3a6e80af6b0e71cbb39a38b822230aGreg Kroah-Hartman skb = alloc_skb(sz + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); 8641ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (skb == NULL) 871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_reset_network_header(skb); 901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, sz); 911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = (struct oz_elt *)(oz_hdr+1); 921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body = (struct oz_elt_connect_rsp *)(elt+1); 931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb->dev = dev; 941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Fill in device header */ 961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev->dev_addr, skb->len) < 0) { 98e79f864d5902a70c1b90f700628cb34756cd8c4aGreg Kroah-Hartman kfree_skb(skb); 991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 1001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT); 1021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr->last_pkt_num = 0; 1031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly put_unaligned(0, &oz_hdr->pkt_num); 1041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->type = OZ_ELT_CONNECT_RSP; 1051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->length = sizeof(struct oz_elt_connect_rsp); 1061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memset(body, 0, sizeof(struct oz_elt_connect_rsp)); 1071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->status = status; 1081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (status == 0) { 1091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->mode = pd->mode; 1101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->session_id = pd->session_id; 1111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly put_unaligned(cpu_to_le16(pd->total_apps), &body->apps); 1121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 113f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "TX: OZ_ELT_CONNECT_RSP %d", status); 1141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_queue_xmit(skb); 1151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 1161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1176e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1184e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void pd_set_keepalive(struct oz_pd *pd, u8 kalive) 1221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly unsigned long keep_alive = kalive & OZ_KALIVE_VALUE_MASK; 1241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 1251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (kalive & OZ_KALIVE_TYPE_MASK) { 1261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_SPECIAL: 1278fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive * 1000*60*60*24*20; 1281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_SECS: 1308fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000; 1311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_MINS: 1338fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000*60; 1341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_HOURS: 1368fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000*60*60; 1371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly default: 1398fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = 0; 1401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1418fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_dbg(ON, "Keepalive = %lu mSec\n", pd->keep_alive); 1421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1436e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1444e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1478fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarestatic void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer) 1481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (presleep) 1508fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->presleep = presleep*100; 1511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly else 1528fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->presleep = OZ_PRESLEEP_TOUT; 1538fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (start_timer) { 1548fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock(&g_polling_lock); 1558fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); 1568fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock(&g_polling_lock); 1578fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare } 1588fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_dbg(ON, "Presleep time = %lu mSec\n", pd->presleep); 1591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1606e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1614e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, 165dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const u8 *pd_addr, struct net_device *net_dev) 1661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 1681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_connect_req *body = 1691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_connect_req *)(elt+1); 1701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 rsp_status = OZ_STATUS_SUCCESS; 1711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 stop_needed = 0; 1721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 new_apps = g_apps; 17341ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct net_device *old_net_dev = NULL; 17441ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *free_pd = NULL; 17518f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 1761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (cur_pd) { 1771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = cur_pd; 1781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 1791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 18041ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *pd2 = NULL; 1811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 1821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_pd_alloc(pd_addr); 18341ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (pd == NULL) 18441ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 1858fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare getnstimeofday(&pd->last_rx_timestamp); 1861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 1871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 1881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd2 = container_of(e, struct oz_pd, link); 18993dc5e429b4d8ac8d683b61052592812e9353f9fdingtianhong if (ether_addr_equal(pd2->mac_addr, pd_addr)) { 1901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly free_pd = pd; 1911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = pd2; 1921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd != pd2) 1961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_add_tail(&pd->link, &g_pd_list); 1971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 19841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (pd == NULL) { 1991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 20041ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 2011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->net_dev != net_dev) { 2031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly old_net_dev = pd->net_dev; 2041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_hold(net_dev); 2051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->net_dev = net_dev; 2061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 207f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Host vendor: %d\n", body->host_vendor); 2081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_tx_size = OZ_MAX_TX_SIZE; 2091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->mode = body->mode; 2101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->pd_info = body->pd_info; 2111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->mode & OZ_F_ISOC_NO_ELTS) { 2121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->ms_per_isoc = body->ms_per_isoc; 2131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (!pd->ms_per_isoc) 2141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->ms_per_isoc = 4; 21586d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare 21686d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare switch (body->ms_isoc_latency & OZ_LATENCY_MASK) { 21786d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare case OZ_ONE_MS_LATENCY: 21886d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = (body->ms_isoc_latency & 21986d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare ~OZ_LATENCY_MASK) / pd->ms_per_isoc; 22086d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare break; 22186d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare case OZ_TEN_MS_LATENCY: 22286d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = ((body->ms_isoc_latency & 22386d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc; 22486d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare break; 22586d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare default: 22686d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC; 22786d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare } 2281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (body->max_len_div16) 2301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_tx_size = ((u16)body->max_len_div16)<<4; 231f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n", 232f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->max_tx_size, pd->ms_per_isoc); 2331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_stream_buffering = 3*1024; 2348fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->pulse_period = OZ_QUANTUM; 2358fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd_set_presleep(pd, body->presleep, 0); 2361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_set_keepalive(pd, body->keep_alive); 2371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 2381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= le16_to_cpu(get_unaligned(&body->apps)); 2391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((new_apps & 0x1) && (body->session_id)) { 2401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id) { 2411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id != body->session_id) { 2421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_SESSION_MISMATCH; 2431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly goto done; 2441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= ~0x1; /* Resume not permitted */ 2471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->session_id = 2481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_get_new_session_id(body->session_id); 2491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id && !body->session_id) { 2521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_SESSION_TEARDOWN; 2531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly stop_needed = 1; 2541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= ~0x1; /* Resume not permitted */ 2561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->session_id = 2571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_get_new_session_id(body->session_id); 2581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellydone: 2611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (rsp_status == OZ_STATUS_SUCCESS) { 2621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 start_apps = new_apps & ~pd->total_apps & ~0x1; 2631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 stop_apps = pd->total_apps & ~new_apps & ~0x1; 2641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 resume_apps = new_apps & pd->paused_apps & ~0x1; 2651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 2661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_set_state(pd, OZ_PD_S_CONNECTED); 267f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n", 268f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches new_apps, pd->total_apps, pd->paused_apps); 2691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (start_apps) { 2701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_services_start(pd, start_apps, 0)) 2711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_TOO_MANY_PDS; 2721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (resume_apps) 2741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_services_start(pd, resume_apps, 1)) 2751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_TOO_MANY_PDS; 2761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (stop_apps) 2771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_services_stop(pd, stop_apps, 0); 2781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_request_heartbeat(pd); 2791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 2811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_send_conn_rsp(pd, rsp_status); 2831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (rsp_status != OZ_STATUS_SUCCESS) { 2841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (stop_needed) 2851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 2861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 28741ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe pd = NULL; 2881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (old_net_dev) 2901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(old_net_dev); 2911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (free_pd) 2921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_destroy(free_pd); 2931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return pd; 2941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 2956e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 2964e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 2971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 2981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 2991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index, 300dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const u8 *report, u8 len) 3011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 3021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_farewell *f; 3031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_farewell *f2; 3041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int found = 0; 30518f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 306b2271b5bdf1fd8b7d5442e2452e9242b88c56e8fRupesh Gujare f = kmalloc(sizeof(struct oz_farewell) + len, GFP_ATOMIC); 3071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (!f) 3081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 3091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly f->ep_num = ep_num; 3101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly f->index = index; 311b50c460a6c03284f7e1b4cfe9266df0f9169ad24Rupesh Gujare f->len = len; 3121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memcpy(f->report, report, len); 313f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: Adding farewell report\n"); 3141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock(&g_polling_lock); 3151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each_entry(f2, &pd->farewell_list, link) { 3161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((f2->ep_num == ep_num) && (f2->index == index)) { 3171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly found = 1; 3181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_del(&f2->link); 3191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 3201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_add_tail(&f->link, &pd->farewell_list); 3231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock(&g_polling_lock); 3241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (found) 3251ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(f2); 3261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 3276e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 3284e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 3291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 3301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 3311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_rx_frame(struct sk_buff *skb) 3321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 3331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 *mac_hdr; 3341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 *src_addr; 3351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt *elt; 3361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int length; 33741ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *pd = NULL; 3381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); 3398fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct timespec current_time; 3401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int dup = 0; 3411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u32 pkt_num; 3421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 343f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n", 344f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control); 3451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly mac_hdr = skb_mac_header(skb); 3462dce674891c1d2708715fecaad222362db53f815Matina Maria Trompouki src_addr = &mac_hdr[ETH_ALEN]; 3471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length = skb->len; 3481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Check the version field */ 3501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_get_prot_ver(oz_hdr->control) != OZ_PROTOCOL_VERSION) { 351f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Incorrect protocol version: %d\n", 352f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_get_prot_ver(oz_hdr->control)); 3531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly goto done; 3541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pkt_num = le32_to_cpu(get_unaligned(&oz_hdr->pkt_num)); 3571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_pd_find(src_addr); 3591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) { 3608fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (!(pd->state & OZ_PD_S_CONNECTED)) 3618fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_pd_set_state(pd, OZ_PD_S_CONNECTED); 3628fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare getnstimeofday(¤t_time); 3638fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) || 3648fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare (pd->presleep < MSEC_PER_SEC)) { 3658fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); 3668fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->last_rx_timestamp = current_time; 3678fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare } 3681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pkt_num != pd->last_rx_pkt_num) { 3691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->last_rx_pkt_num = pkt_num; 3701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 3711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dup = 1; 372f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Duplicate frame\n"); 3731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) { 377f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(RX_FRAMES, "Received TRIGGER Frame\n"); 3781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->last_sent_frame = &pd->tx_queue; 3791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_hdr->control & OZ_F_ACK) { 3801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Retire completed frames */ 3811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_retire_tx_frames(pd, oz_hdr->last_pkt_num); 3821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((oz_hdr->control & OZ_F_ACK_REQUESTED) && 3841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (pd->state == OZ_PD_S_CONNECTED)) { 3851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int backlog = pd->nb_queued_frames; 3861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->trigger_pkt_num = pkt_num; 3871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Send queued frames */ 3881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_send_queued_frames(pd, backlog); 3891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length -= sizeof(struct oz_hdr); 3931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = (struct oz_elt *)((u8 *)oz_hdr + sizeof(struct oz_hdr)); 3941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (length >= sizeof(struct oz_elt)) { 3961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length -= sizeof(struct oz_elt) + elt->length; 3971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (length < 0) 3981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 3991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (elt->type) { 4001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_CONNECT_REQ: 401f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_CONNECT_REQ\n"); 4021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_connect_req(pd, elt, src_addr, skb->dev); 4031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_DISCONNECT: 405f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_DISCONNECT\n"); 4061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) 4071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_sleep(pd); 4081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_UPDATE_PARAM_REQ: { 4101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_update_param *body = 4111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_update_param *)(elt + 1); 412f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_UPDATE_PARAM_REQ\n"); 4131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && (pd->state & OZ_PD_S_CONNECTED)) { 4141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock(&g_polling_lock); 4151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_set_keepalive(pd, body->keepalive); 4168fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd_set_presleep(pd, body->presleep, 1); 4171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock(&g_polling_lock); 4181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_FAREWELL_REQ: { 4221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_farewell *body = 4231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_farewell *)(elt + 1); 424f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_FAREWELL_REQ\n"); 4251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_add_farewell(pd, body->ep_num, 4261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->index, body->report, 4271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->length + 1 - sizeof(*body)); 4281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_APP_DATA: 4311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && (pd->state & OZ_PD_S_CONNECTED)) { 4321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_app_hdr *app_hdr = 4331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_app_hdr *)(elt+1); 4341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (dup) 4351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_handle_app_elt(pd, app_hdr->app_id, elt); 4371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly default: 440f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: Unknown elt %02x\n", elt->type); 4411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = oz_next_elt(elt); 4431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellydone: 4451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) 4461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 4471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly consume_skb(skb); 4481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 4496e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 4504e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 4511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 4521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_protocol_term(void) 4541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 4558a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare struct oz_binding *b, *t; 4568a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare 4571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Walk the list of bindings and remove each one. 4581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 4608a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_for_each_entry_safe(b, t, &g_binding, link) { 4618a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_del(&b->link); 4621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 4631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_remove_pack(&b->ptype); 4641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (b->ptype.dev) 4651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(b->ptype.dev); 4661ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(b); 4671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 4681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 4701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Walk the list of PDs and stop each one. This causes the PD to be 4711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * removed from the list so we can just pull each one from the head 4721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * of the list. 4731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 4751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (!list_empty(&g_pd_list)) { 4761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd = 4771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_first_entry(&g_pd_list, struct oz_pd, link); 4781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_get(pd); 4791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 4801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 4811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 4821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 4831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 485f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Protocol stopped\n"); 4862b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger 48750222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger kmem_cache_destroy(oz_tx_frame_cache); 4882b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger kmem_cache_destroy(oz_elt_info_cache); 4891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 4906e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 4914e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 4921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq 4931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4948fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_pd_heartbeat_handler(unsigned long data) 4951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 4968fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd = (struct oz_pd *)data; 4978fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare u16 apps = 0; 49818f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 4998fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 5008fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (pd->state & OZ_PD_S_CONNECTED) 5018fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare apps = pd->total_apps; 5028fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 5038fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (apps) 5048fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_pd_heartbeat(pd, apps); 505b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_put(pd); 5068fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare} 5076e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5084e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5098fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: softirq 5108fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare */ 5118fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_pd_timeout_handler(unsigned long data) 5128fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare{ 5138fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare int type; 5148fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd = (struct oz_pd *)data; 5158fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5168fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 5178fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare type = pd->timeout_type; 5188fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 5191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (type) { 5201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_TIMER_TOUT: 5211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_sleep(pd); 5221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 5231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_TIMER_STOP: 5241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 5251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 5261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 527b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_put(pd); 5281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5296e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5304e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5318fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: Interrupt 5321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5338fd070077410b26847ef6f5856850df417e7b83eRupesh Gujareenum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer) 5341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 5368fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5378fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd = container_of(timer, struct oz_pd, heartbeat); 5388fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_forward_now(timer, ktime_set(pd->pulse_period / 5398fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (pd->pulse_period % MSEC_PER_SEC) * NSEC_PER_MSEC)); 540b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_get(pd); 5418fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_schedule(&pd->heartbeat_tasklet); 5428fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare return HRTIMER_RESTART; 5431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5446e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5454e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5468fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: Interrupt 5471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5488fd070077410b26847ef6f5856850df417e7b83eRupesh Gujareenum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer) 5491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5508fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd; 5518fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5528fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd = container_of(timer, struct oz_pd, timeout); 553b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_get(pd); 5548fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_schedule(&pd->timeout_tasklet); 5558fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare return HRTIMER_NORESTART; 5561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5576e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5584e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5618fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time) 5621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5638fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 5648fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare switch (type) { 5658fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_TOUT: 5668fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_STOP: 5678fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (hrtimer_active(&pd->timeout)) { 5688fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_set_expires(&pd->timeout, ktime_set(due_time / 5698fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5708fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC)); 5718fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL); 5721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 5738fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start(&pd->timeout, ktime_set(due_time / 5748fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5758fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC), HRTIMER_MODE_REL); 5761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5778fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->timeout_type = type; 5788fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare break; 5798fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_HEARTBEAT: 5808fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (!hrtimer_active(&pd->heartbeat)) 5818fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start(&pd->heartbeat, ktime_set(due_time / 5828fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5838fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC), HRTIMER_MODE_REL); 5848fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare break; 5851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5868fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 5871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5886e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5894e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_pd_request_heartbeat(struct oz_pd *pd) 5931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5948fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_HEARTBEAT, pd->pulse_period > 0 ? 5958fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->pulse_period : OZ_QUANTUM); 5961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5976e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5984e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 6001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 601dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewestruct oz_pd *oz_pd_find(const u8 *mac_addr) 6021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 6041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 60518f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 6061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 6071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 6081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = container_of(e, struct oz_pd, link); 60993dc5e429b4d8ac8d683b61052592812e9353f9fdingtianhong if (ether_addr_equal(pd->mac_addr, mac_addr)) { 6101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly atomic_inc(&pd->ref_count); 6111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 6121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return pd; 6131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 61641ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 6171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6186e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6194e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_app_enable(int app_id, int enable) 6231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 624a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger if (app_id < OZ_NB_APPS) { 6251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 6261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (enable) 6271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_apps |= (1<<app_id); 6281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly else 6291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_apps &= ~(1<<app_id); 6301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 6311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6336e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6344e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq 6361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev, 6381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct packet_type *pt, struct net_device *orig_dev) 6391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb = skb_share_check(skb, GFP_ATOMIC); 64141ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (skb == NULL) 6421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 6431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_rx_queue.lock); 6441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (g_processing_rx) { 6451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* We already hold the lock so use __ variant. 6461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly __skb_queue_head(&g_rx_queue, skb); 6481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 6501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_processing_rx = 1; 6511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly do { 6521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 6531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_rx_frame(skb); 6551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_rx_queue.lock); 6561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (skb_queue_empty(&g_rx_queue)) { 6571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_processing_rx = 0; 6581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 6601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* We already hold the lock so use __ variant. 6621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb = __skb_dequeue(&g_rx_queue); 6641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } while (1); 6651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 6671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6686e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6694e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 67283e4817fc3a2092ac1545999705b799bea855bcbRupesh Gujarevoid oz_binding_add(const char *net_dev) 6731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_binding *binding; 6751ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman 676e4b41af14d7dc683ecd84a10fed8ea38b94f0f28Salym Senyonga binding = kzalloc(sizeof(struct oz_binding), GFP_KERNEL); 677a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga if (!binding) 678a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga return; 679a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga 680c632824ef26bb27e51518242650bf4195a33ae63Jérôme Pinot binding->ptype.type = htons(OZ_ETHERTYPE); 681a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga binding->ptype.func = oz_pkt_recv; 682a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga if (net_dev && *net_dev) { 683a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN); 684a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga oz_dbg(ON, "Adding binding: %s\n", net_dev); 685a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga binding->ptype.dev = dev_get_by_name(&init_net, net_dev); 686a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga if (binding->ptype.dev == NULL) { 687a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga oz_dbg(ON, "Netdev %s not found\n", net_dev); 688a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga kfree(binding); 689a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga return; 6901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 692a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga dev_add_pack(&binding->ptype); 693a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga spin_lock_bh(&g_binding_lock); 694a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga list_add_tail(&binding->link, &g_binding); 695a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga spin_unlock_bh(&g_binding_lock); 6961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6976e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6984e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void pd_stop_all_for_device(struct net_device *net_dev) 7021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head h; 7041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 7051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *n; 70618f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 7071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly INIT_LIST_HEAD(&h); 7081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 7091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each_entry_safe(pd, n, &g_pd_list, link) { 7101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->net_dev == net_dev) { 7111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_move(&pd->link, &h); 7121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_get(pd); 7131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 7161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (!list_empty(&h)) { 7171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = list_first_entry(&h, struct oz_pd, link); 7181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 7191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 7201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7226e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7234e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 72683e4817fc3a2092ac1545999705b799bea855bcbRupesh Gujarevoid oz_binding_remove(const char *net_dev) 7271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 72841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_binding *binding; 7298a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare int found = 0; 7308a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare 731f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Removing binding: %s\n", net_dev); 7321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 7338a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_for_each_entry(binding, &g_binding, link) { 7344d6c9e57027940b6b492abac4c1b67710e38f366Rupesh Gujare if (strncmp(binding->name, net_dev, OZ_MAX_BINDING_LEN) == 0) { 735f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Binding '%s' found\n", net_dev); 7368a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare found = 1; 7371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 7381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 7418a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare if (found) { 7421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_remove_pack(&binding->ptype); 7431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (binding->ptype.dev) { 7441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(binding->ptype.dev); 7451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_stop_all_for_device(binding->ptype.dev); 7461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7478a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_del(&binding->link); 7481ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(binding); 7491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7516e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7524e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic char *oz_get_next_device_name(char *s, char *dname, int max_size) 7561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*s == ',') 7581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly s++; 7591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*s && (*s != ',') && max_size > 1) { 7601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly *dname++ = *s++; 7611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly max_size--; 7621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly *dname = 0; 7641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return s; 7651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7666e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7674e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyint oz_protocol_init(char *devs) 7711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7722b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger oz_elt_info_cache = KMEM_CACHE(oz_elt_info, 0); 7732b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger if (!oz_elt_info_cache) 7742b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger return -ENOMEM; 7752b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger 77650222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger oz_tx_frame_cache = KMEM_CACHE(oz_tx_frame, 0); 77750222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger if (!oz_tx_frame_cache) { 77850222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger kmem_cache_destroy(oz_elt_info_cache); 77950222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger return -ENOMEM; 78050222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger } 78150222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger 7821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_queue_head_init(&g_rx_queue); 78301c48ad3ea7f976ab9e02dca642c52f7cf1256b9Daeseok Youn if (devs[0] == '*') { 78441ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe oz_binding_add(NULL); 7851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 7861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly char d[32]; 7871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*devs) { 7881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly devs = oz_get_next_device_name(devs, d, sizeof(d)); 7891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (d[0]) 7901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_binding_add(d); 7911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 7941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7956e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7964e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyint oz_get_pd_list(struct oz_mac_addr *addr, int max_count) 8001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 8011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 8021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 8031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int count = 0; 80418f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 8051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 8061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 8071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (count >= max_count) 8081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 8091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = container_of(e, struct oz_pd, link); 810ae35f26644d1af10bfc96c5dffc5103c84a9b3c4Anil Belur ether_addr_copy((u8 *)&addr[count++], pd->mac_addr); 8111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 8121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 8131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return count; 8141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 8156e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 816