ozproto.c revision 8fd070077410b26847ef6f5856850df417e7b83e
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/init.h> 81619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/module.h> 91619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/timer.h> 101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/sched.h> 111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/netdevice.h> 121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/errno.h> 131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/ieee80211.h> 14f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches#include "ozdbg.h" 151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozprotocol.h" 161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozeltbuf.h" 171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozpd.h" 181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozproto.h" 191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozusbsvc.h" 2005f608f237dcc3c4e5188d054d9918cbfd2916c2Joe Perches 211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozappif.h" 221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <asm/unaligned.h> 231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/uaccess.h> 241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <net/psnap.h> 251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 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 Kelly#define OZ_MAX_TIMER_POOL_SIZE 16 341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystruct oz_binding { 381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct packet_type ptype; 391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly char name[OZ_MAX_BINDING_LEN]; 401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_binding *next; 411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly}; 421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Static external variables. 451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic DEFINE_SPINLOCK(g_polling_lock); 471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic LIST_HEAD(g_pd_list); 481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic struct oz_binding *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; 541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u8 oz_get_new_session_id(u8 exclude) 581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (++g_session_id == 0) 601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_session_id = 1; 611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (g_session_id == exclude) { 621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (++g_session_id == 0) 631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_session_id = 1; 641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return g_session_id; 661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_send_conn_rsp(struct oz_pd *pd, u8 status) 711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct sk_buff *skb; 731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct net_device *dev = pd->net_dev; 741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_hdr *oz_hdr; 751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt *elt; 761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_connect_rsp *body; 771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int sz = sizeof(struct oz_hdr) + sizeof(struct oz_elt) + 781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly sizeof(struct oz_elt_connect_rsp); 796b790d0fae3a6e80af6b0e71cbb39a38b822230aGreg Kroah-Hartman skb = alloc_skb(sz + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); 8041ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (skb == NULL) 811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_reset_network_header(skb); 841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, sz); 851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = (struct oz_elt *)(oz_hdr+1); 861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body = (struct oz_elt_connect_rsp *)(elt+1); 871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb->dev = dev; 881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Fill in device header */ 901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev->dev_addr, skb->len) < 0) { 92e79f864d5902a70c1b90f700628cb34756cd8c4aGreg Kroah-Hartman kfree_skb(skb); 931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT); 961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr->last_pkt_num = 0; 971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly put_unaligned(0, &oz_hdr->pkt_num); 981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->type = OZ_ELT_CONNECT_RSP; 991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->length = sizeof(struct oz_elt_connect_rsp); 1001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memset(body, 0, sizeof(struct oz_elt_connect_rsp)); 1011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->status = status; 1021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (status == 0) { 1031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->mode = pd->mode; 1041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->session_id = pd->session_id; 1051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly put_unaligned(cpu_to_le16(pd->total_apps), &body->apps); 1061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 107f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "TX: OZ_ELT_CONNECT_RSP %d", status); 1081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_queue_xmit(skb); 1091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 1101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 1121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void pd_set_keepalive(struct oz_pd *pd, u8 kalive) 1151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly unsigned long keep_alive = kalive & OZ_KALIVE_VALUE_MASK; 1171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 1181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (kalive & OZ_KALIVE_TYPE_MASK) { 1191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_SPECIAL: 1208fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive * 1000*60*60*24*20; 1211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_SECS: 1238fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000; 1241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_MINS: 1268fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000*60; 1271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_HOURS: 1298fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000*60*60; 1301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly default: 1328fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = 0; 1331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1348fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_dbg(ON, "Keepalive = %lu mSec\n", pd->keep_alive); 1351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 1371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1398fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarestatic void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer) 1401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (presleep) 1428fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->presleep = presleep*100; 1431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly else 1448fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->presleep = OZ_PRESLEEP_TOUT; 1458fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (start_timer) { 1468fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock(&g_polling_lock); 1478fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); 1488fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock(&g_polling_lock); 1498fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare } 1508fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_dbg(ON, "Presleep time = %lu mSec\n", pd->presleep); 1511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 1531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, 156dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const u8 *pd_addr, struct net_device *net_dev) 1571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 1591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_connect_req *body = 1601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_connect_req *)(elt+1); 1611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 rsp_status = OZ_STATUS_SUCCESS; 1621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 stop_needed = 0; 1631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 new_apps = g_apps; 16441ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct net_device *old_net_dev = NULL; 16541ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *free_pd = NULL; 1661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (cur_pd) { 1671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = cur_pd; 1681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 1691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 17041ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *pd2 = NULL; 1711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 1721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_pd_alloc(pd_addr); 17341ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (pd == NULL) 17441ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 1758fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare getnstimeofday(&pd->last_rx_timestamp); 1761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 1771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 1781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd2 = container_of(e, struct oz_pd, link); 1791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (memcmp(pd2->mac_addr, pd_addr, ETH_ALEN) == 0) { 1801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly free_pd = pd; 1811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = pd2; 1821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd != pd2) 1861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_add_tail(&pd->link, &g_pd_list); 1871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 18841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (pd == NULL) { 1891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 19041ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 1911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->net_dev != net_dev) { 1931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly old_net_dev = pd->net_dev; 1941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_hold(net_dev); 1951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->net_dev = net_dev; 1961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 197f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Host vendor: %d\n", body->host_vendor); 1981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_tx_size = OZ_MAX_TX_SIZE; 1991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->mode = body->mode; 2001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->pd_info = body->pd_info; 2011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->mode & OZ_F_ISOC_NO_ELTS) { 2021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->ms_per_isoc = body->ms_per_isoc; 2031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (!pd->ms_per_isoc) 2041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->ms_per_isoc = 4; 20586d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare 20686d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare switch (body->ms_isoc_latency & OZ_LATENCY_MASK) { 20786d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare case OZ_ONE_MS_LATENCY: 20886d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = (body->ms_isoc_latency & 20986d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare ~OZ_LATENCY_MASK) / pd->ms_per_isoc; 21086d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare break; 21186d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare case OZ_TEN_MS_LATENCY: 21286d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = ((body->ms_isoc_latency & 21386d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc; 21486d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare break; 21586d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare default: 21686d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC; 21786d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare } 2181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (body->max_len_div16) 2201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_tx_size = ((u16)body->max_len_div16)<<4; 221f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n", 222f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->max_tx_size, pd->ms_per_isoc); 2231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_stream_buffering = 3*1024; 2248fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->pulse_period = OZ_QUANTUM; 2258fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd_set_presleep(pd, body->presleep, 0); 2261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_set_keepalive(pd, body->keep_alive); 2271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 2281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= le16_to_cpu(get_unaligned(&body->apps)); 2291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((new_apps & 0x1) && (body->session_id)) { 2301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id) { 2311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id != body->session_id) { 2321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_SESSION_MISMATCH; 2331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly goto done; 2341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= ~0x1; /* Resume not permitted */ 2371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->session_id = 2381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_get_new_session_id(body->session_id); 2391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id && !body->session_id) { 2421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_SESSION_TEARDOWN; 2431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly stop_needed = 1; 2441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= ~0x1; /* Resume not permitted */ 2461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->session_id = 2471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_get_new_session_id(body->session_id); 2481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellydone: 2511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (rsp_status == OZ_STATUS_SUCCESS) { 2521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 start_apps = new_apps & ~pd->total_apps & ~0x1; 2531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 stop_apps = pd->total_apps & ~new_apps & ~0x1; 2541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 resume_apps = new_apps & pd->paused_apps & ~0x1; 2551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 2561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_set_state(pd, OZ_PD_S_CONNECTED); 257f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n", 258f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches new_apps, pd->total_apps, pd->paused_apps); 2591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (start_apps) { 2601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_services_start(pd, start_apps, 0)) 2611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_TOO_MANY_PDS; 2621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (resume_apps) 2641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_services_start(pd, resume_apps, 1)) 2651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_TOO_MANY_PDS; 2661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (stop_apps) 2671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_services_stop(pd, stop_apps, 0); 2681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_request_heartbeat(pd); 2691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 2711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_send_conn_rsp(pd, rsp_status); 2731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (rsp_status != OZ_STATUS_SUCCESS) { 2741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (stop_needed) 2751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 2761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 27741ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe pd = NULL; 2781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (old_net_dev) 2801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(old_net_dev); 2811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (free_pd) 2821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_destroy(free_pd); 2831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return pd; 2841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 2851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 2861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 2871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 2881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index, 289dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const u8 *report, u8 len) 2901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 2911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_farewell *f; 2921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_farewell *f2; 2931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int found = 0; 2941ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman f = kmalloc(sizeof(struct oz_farewell) + len - 1, GFP_ATOMIC); 2951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (!f) 2961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 2971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly f->ep_num = ep_num; 2981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly f->index = index; 2991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memcpy(f->report, report, len); 300f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: Adding farewell report\n"); 3011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock(&g_polling_lock); 3021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each_entry(f2, &pd->farewell_list, link) { 3031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((f2->ep_num == ep_num) && (f2->index == index)) { 3041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly found = 1; 3051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_del(&f2->link); 3061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 3071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_add_tail(&f->link, &pd->farewell_list); 3101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock(&g_polling_lock); 3111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (found) 3121ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(f2); 3131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 3141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 3151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 3161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 3171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_rx_frame(struct sk_buff *skb) 3181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 3191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 *mac_hdr; 3201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 *src_addr; 3211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt *elt; 3221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int length; 32341ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *pd = NULL; 3241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); 3258fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct timespec current_time; 3261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int dup = 0; 3271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u32 pkt_num; 3281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 329f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n", 330f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control); 3311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly mac_hdr = skb_mac_header(skb); 3321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly src_addr = &mac_hdr[ETH_ALEN] ; 3331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length = skb->len; 3341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Check the version field */ 3361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_get_prot_ver(oz_hdr->control) != OZ_PROTOCOL_VERSION) { 337f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Incorrect protocol version: %d\n", 338f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_get_prot_ver(oz_hdr->control)); 3391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly goto done; 3401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pkt_num = le32_to_cpu(get_unaligned(&oz_hdr->pkt_num)); 3431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_pd_find(src_addr); 3451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) { 3468fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (!(pd->state & OZ_PD_S_CONNECTED)) 3478fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_pd_set_state(pd, OZ_PD_S_CONNECTED); 3488fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare getnstimeofday(¤t_time); 3498fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) || 3508fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare (pd->presleep < MSEC_PER_SEC)) { 3518fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); 3528fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->last_rx_timestamp = current_time; 3538fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare } 3541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pkt_num != pd->last_rx_pkt_num) { 3551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->last_rx_pkt_num = pkt_num; 3561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 3571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dup = 1; 358f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Duplicate frame\n"); 3591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) { 363f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(RX_FRAMES, "Received TRIGGER Frame\n"); 3641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->last_sent_frame = &pd->tx_queue; 3651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_hdr->control & OZ_F_ACK) { 3661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Retire completed frames */ 3671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_retire_tx_frames(pd, oz_hdr->last_pkt_num); 3681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((oz_hdr->control & OZ_F_ACK_REQUESTED) && 3701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (pd->state == OZ_PD_S_CONNECTED)) { 3711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int backlog = pd->nb_queued_frames; 3721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->trigger_pkt_num = pkt_num; 3731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Send queued frames */ 3741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_send_queued_frames(pd, backlog); 3751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length -= sizeof(struct oz_hdr); 3791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = (struct oz_elt *)((u8 *)oz_hdr + sizeof(struct oz_hdr)); 3801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (length >= sizeof(struct oz_elt)) { 3821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length -= sizeof(struct oz_elt) + elt->length; 3831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (length < 0) 3841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 3851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (elt->type) { 3861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_CONNECT_REQ: 387f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_CONNECT_REQ\n"); 3881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_connect_req(pd, elt, src_addr, skb->dev); 3891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 3901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_DISCONNECT: 391f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_DISCONNECT\n"); 3921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) 3931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_sleep(pd); 3941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 3951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_UPDATE_PARAM_REQ: { 3961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_update_param *body = 3971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_update_param *)(elt + 1); 398f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_UPDATE_PARAM_REQ\n"); 3991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && (pd->state & OZ_PD_S_CONNECTED)) { 4001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock(&g_polling_lock); 4011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_set_keepalive(pd, body->keepalive); 4028fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd_set_presleep(pd, body->presleep, 1); 4031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock(&g_polling_lock); 4041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_FAREWELL_REQ: { 4081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_farewell *body = 4091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_farewell *)(elt + 1); 410f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_FAREWELL_REQ\n"); 4111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_add_farewell(pd, body->ep_num, 4121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->index, body->report, 4131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->length + 1 - sizeof(*body)); 4141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_APP_DATA: 4171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && (pd->state & OZ_PD_S_CONNECTED)) { 4181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_app_hdr *app_hdr = 4191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_app_hdr *)(elt+1); 4201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (dup) 4211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_handle_app_elt(pd, app_hdr->app_id, elt); 4231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly default: 426f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: Unknown elt %02x\n", elt->type); 4271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = oz_next_elt(elt); 4291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellydone: 4311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) 4321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 4331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly consume_skb(skb); 4341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 4351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 4361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 4371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_protocol_term(void) 4391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 4401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Walk the list of bindings and remove each one. 4411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 4431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (g_binding) { 4441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_binding *b = g_binding; 4451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_binding = b->next; 4461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 4471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_remove_pack(&b->ptype); 4481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (b->ptype.dev) 4491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(b->ptype.dev); 4501ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(b); 4511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 4521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 4541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Walk the list of PDs and stop each one. This causes the PD to be 4551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * removed from the list so we can just pull each one from the head 4561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * of the list. 4571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 4591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (!list_empty(&g_pd_list)) { 4601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd = 4611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_first_entry(&g_pd_list, struct oz_pd, link); 4621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_get(pd); 4631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 4641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 4651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 4661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 4671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 469f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Protocol stopped\n"); 4701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 4711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 4721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq 4731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4748fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_pd_heartbeat_handler(unsigned long data) 4751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 4768fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd = (struct oz_pd *)data; 4778fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare u16 apps = 0; 4788fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 4798fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (pd->state & OZ_PD_S_CONNECTED) 4808fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare apps = pd->total_apps; 4818fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 4828fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (apps) 4838fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_pd_heartbeat(pd, apps); 4848fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 4858fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare} 4868fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare/*------------------------------------------------------------------------------ 4878fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: softirq 4888fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare */ 4898fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_pd_timeout_handler(unsigned long data) 4908fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare{ 4918fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare int type; 4928fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd = (struct oz_pd *)data; 4938fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 4948fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 4958fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare type = pd->timeout_type; 4968fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 4971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (type) { 4981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_TIMER_TOUT: 4991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_sleep(pd); 5001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 5011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_TIMER_STOP: 5021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 5031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 5041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 5078fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: Interrupt 5081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5098fd070077410b26847ef6f5856850df417e7b83eRupesh Gujareenum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer) 5101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 5128fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5138fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd = container_of(timer, struct oz_pd, heartbeat); 5148fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_forward_now(timer, ktime_set(pd->pulse_period / 5158fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (pd->pulse_period % MSEC_PER_SEC) * NSEC_PER_MSEC)); 5168fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_schedule(&pd->heartbeat_tasklet); 5178fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare return HRTIMER_RESTART; 5181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 5208fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: Interrupt 5211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5228fd070077410b26847ef6f5856850df417e7b83eRupesh Gujareenum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer) 5231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5248fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd; 5258fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5268fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd = container_of(timer, struct oz_pd, timeout); 5278fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_schedule(&pd->timeout_tasklet); 5288fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare return HRTIMER_NORESTART; 5291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 5311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5338fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time) 5341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5358fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 5368fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare switch (type) { 5378fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_TOUT: 5388fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_STOP: 5398fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (hrtimer_active(&pd->timeout)) { 5408fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_set_expires(&pd->timeout, ktime_set(due_time / 5418fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5428fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC)); 5438fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL); 5441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 5458fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start(&pd->timeout, ktime_set(due_time / 5468fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5478fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC), HRTIMER_MODE_REL); 5481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5498fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->timeout_type = type; 5508fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare break; 5518fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_HEARTBEAT: 5528fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (!hrtimer_active(&pd->heartbeat)) 5538fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start(&pd->heartbeat, ktime_set(due_time / 5548fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5558fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC), HRTIMER_MODE_REL); 5568fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare break; 5571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5588fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 5591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 5611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_pd_request_heartbeat(struct oz_pd *pd) 5641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5658fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_HEARTBEAT, pd->pulse_period > 0 ? 5668fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->pulse_period : OZ_QUANTUM); 5671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 5691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 571dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewestruct oz_pd *oz_pd_find(const u8 *mac_addr) 5721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 5741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 5751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 5761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 5771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = container_of(e, struct oz_pd, link); 5781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (memcmp(pd->mac_addr, mac_addr, ETH_ALEN) == 0) { 5791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly atomic_inc(&pd->ref_count); 5801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 5811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return pd; 5821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 58541ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 5861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 5881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 5891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_app_enable(int app_id, int enable) 5911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (app_id <= OZ_APPID_MAX) { 5931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 5941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (enable) 5951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_apps |= (1<<app_id); 5961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly else 5971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_apps &= ~(1<<app_id); 5981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 5991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 6021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq 6031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev, 6051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct packet_type *pt, struct net_device *orig_dev) 6061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb = skb_share_check(skb, GFP_ATOMIC); 60841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (skb == NULL) 6091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 6101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_rx_queue.lock); 6111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (g_processing_rx) { 6121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* We already hold the lock so use __ variant. 6131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly __skb_queue_head(&g_rx_queue, skb); 6151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 6171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_processing_rx = 1; 6181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly do { 6191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 6201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_rx_frame(skb); 6221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_rx_queue.lock); 6231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (skb_queue_empty(&g_rx_queue)) { 6241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_processing_rx = 0; 6251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 6271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* We already hold the lock so use __ variant. 6291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb = __skb_dequeue(&g_rx_queue); 6311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } while (1); 6321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 6341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 6361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_binding_add(char *net_dev) 6391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_binding *binding; 6411ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman 642fec9f24b6269dc5fb4b1212a970c089461ec7ff2Rupesh Gujare binding = kmalloc(sizeof(struct oz_binding), GFP_KERNEL); 6431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (binding) { 6441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly binding->ptype.type = __constant_htons(OZ_ETHERTYPE); 6451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly binding->ptype.func = oz_pkt_recv; 6461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN); 6471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (net_dev && *net_dev) { 648f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Adding binding: %s\n", net_dev); 6491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly binding->ptype.dev = 6501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_get_by_name(&init_net, net_dev); 65141ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (binding->ptype.dev == NULL) { 652f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Netdev %s not found\n", net_dev); 6531ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(binding); 65441ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe binding = NULL; 6551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 657f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Binding to all netcards\n"); 65841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe binding->ptype.dev = NULL; 6591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (binding) { 6611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_add_pack(&binding->ptype); 6621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 6631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly binding->next = g_binding; 6641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_binding = binding; 6651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 6661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 6701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic int compare_binding_name(char *s1, char *s2) 6731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int i; 6751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly for (i = 0; i < OZ_MAX_BINDING_LEN; i++) { 6761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (*s1 != *s2) 6771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 6781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (!*s1++) 6791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 1; 6801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly s2++; 6811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 1; 6831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 6851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void pd_stop_all_for_device(struct net_device *net_dev) 6881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head h; 6901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 6911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *n; 6921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly INIT_LIST_HEAD(&h); 6931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 6941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each_entry_safe(pd, n, &g_pd_list, link) { 6951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->net_dev == net_dev) { 6961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_move(&pd->link, &h); 6971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_get(pd); 6981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 7011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (!list_empty(&h)) { 7021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = list_first_entry(&h, struct oz_pd, link); 7031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 7041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 7051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 7081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_binding_remove(char *net_dev) 7111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 71241ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_binding *binding; 7131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_binding **link; 714f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Removing binding: %s\n", net_dev); 7151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 7161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly binding = g_binding; 7171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly link = &g_binding; 7181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (binding) { 7191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (compare_binding_name(binding->name, net_dev)) { 720f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Binding '%s' found\n", net_dev); 7211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly *link = binding->next; 7221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 7231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 7241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly link = &binding; 7251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly binding = binding->next; 7261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 7291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (binding) { 7301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_remove_pack(&binding->ptype); 7311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (binding->ptype.dev) { 7321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(binding->ptype.dev); 7331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_stop_all_for_device(binding->ptype.dev); 7341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7351ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(binding); 7361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 7391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic char *oz_get_next_device_name(char *s, char *dname, int max_size) 7421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*s == ',') 7441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly s++; 7451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*s && (*s != ',') && max_size > 1) { 7461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly *dname++ = *s++; 7471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly max_size--; 7481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly *dname = 0; 7501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return s; 7511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 7531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyint oz_protocol_init(char *devs) 7561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_queue_head_init(&g_rx_queue); 7581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (devs && (devs[0] == '*')) { 75941ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe oz_binding_add(NULL); 7601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 7611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly char d[32]; 7621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*devs) { 7631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly devs = oz_get_next_device_name(devs, d, sizeof(d)); 7641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (d[0]) 7651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_binding_add(d); 7661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 7691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 7711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyint oz_get_pd_list(struct oz_mac_addr *addr, int max_count) 7741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 7761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 7771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int count = 0; 7781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 7791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 7801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (count >= max_count) 7811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 7821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = container_of(e, struct oz_pd, link); 7831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memcpy(&addr[count++], pd->mac_addr, ETH_ALEN); 7841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 7861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return count; 7871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 7891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly*/ 7901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_polling_lock_bh(void) 7911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 7931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/*------------------------------------------------------------------------------ 7951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly*/ 7961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_polling_unlock_bh(void) 7971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 7991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 800