ozproto.c revision ae35f26644d1af10bfc96c5dffc5103c84a9b3c4
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> 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> 256e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_CF_CONN_SUCCESS 1 271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_CF_CONN_FAILURE 2 281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_DO_STOP 1 301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_DO_SLEEP 2 311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_MAX_TIMER_POOL_SIZE 16 331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystruct oz_binding { 351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct packet_type ptype; 361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly char name[OZ_MAX_BINDING_LEN]; 378a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare struct list_head link; 381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly}; 391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 404e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 416b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil * External variable 426b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil */ 436b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil 446b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra PatilDEFINE_SPINLOCK(g_polling_lock); 456b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil/* 461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Static external variables. 471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic LIST_HEAD(g_pd_list); 498a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujarestatic LIST_HEAD(g_binding); 501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic DEFINE_SPINLOCK(g_binding_lock); 511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic struct sk_buff_head g_rx_queue; 521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u8 g_session_id; 531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u16 g_apps = 0x1; 541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic int g_processing_rx; 556e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 564e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u8 oz_get_new_session_id(u8 exclude) 601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (++g_session_id == 0) 621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_session_id = 1; 631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (g_session_id == exclude) { 641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (++g_session_id == 0) 651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_session_id = 1; 661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return g_session_id; 681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 696e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 704e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_send_conn_rsp(struct oz_pd *pd, u8 status) 741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct sk_buff *skb; 761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct net_device *dev = pd->net_dev; 771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_hdr *oz_hdr; 781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt *elt; 791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_connect_rsp *body; 8018f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int sz = sizeof(struct oz_hdr) + sizeof(struct oz_elt) + 821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly sizeof(struct oz_elt_connect_rsp); 836b790d0fae3a6e80af6b0e71cbb39a38b822230aGreg Kroah-Hartman skb = alloc_skb(sz + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); 8441ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (skb == NULL) 851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_reset_network_header(skb); 881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, sz); 891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = (struct oz_elt *)(oz_hdr+1); 901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body = (struct oz_elt_connect_rsp *)(elt+1); 911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb->dev = dev; 921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Fill in device header */ 941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev->dev_addr, skb->len) < 0) { 96e79f864d5902a70c1b90f700628cb34756cd8c4aGreg Kroah-Hartman kfree_skb(skb); 971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT); 1001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr->last_pkt_num = 0; 1011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly put_unaligned(0, &oz_hdr->pkt_num); 1021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->type = OZ_ELT_CONNECT_RSP; 1031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->length = sizeof(struct oz_elt_connect_rsp); 1041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memset(body, 0, sizeof(struct oz_elt_connect_rsp)); 1051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->status = status; 1061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (status == 0) { 1071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->mode = pd->mode; 1081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->session_id = pd->session_id; 1091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly put_unaligned(cpu_to_le16(pd->total_apps), &body->apps); 1101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 111f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "TX: OZ_ELT_CONNECT_RSP %d", status); 1121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_queue_xmit(skb); 1131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 1141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1156e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1164e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void pd_set_keepalive(struct oz_pd *pd, u8 kalive) 1201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly unsigned long keep_alive = kalive & OZ_KALIVE_VALUE_MASK; 1221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 1231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (kalive & OZ_KALIVE_TYPE_MASK) { 1241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_SPECIAL: 1258fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive * 1000*60*60*24*20; 1261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_SECS: 1288fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000; 1291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_MINS: 1318fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000*60; 1321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_HOURS: 1348fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000*60*60; 1351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly default: 1378fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = 0; 1381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1398fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_dbg(ON, "Keepalive = %lu mSec\n", pd->keep_alive); 1401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1416e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1424e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1458fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarestatic void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer) 1461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (presleep) 1488fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->presleep = presleep*100; 1491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly else 1508fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->presleep = OZ_PRESLEEP_TOUT; 1518fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (start_timer) { 1528fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock(&g_polling_lock); 1538fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); 1548fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock(&g_polling_lock); 1558fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare } 1568fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_dbg(ON, "Presleep time = %lu mSec\n", pd->presleep); 1571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1586e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1594e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, 163dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const u8 *pd_addr, struct net_device *net_dev) 1641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 1661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_connect_req *body = 1671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_connect_req *)(elt+1); 1681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 rsp_status = OZ_STATUS_SUCCESS; 1691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 stop_needed = 0; 1701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 new_apps = g_apps; 17141ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct net_device *old_net_dev = NULL; 17241ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *free_pd = NULL; 17318f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 1741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (cur_pd) { 1751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = cur_pd; 1761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 1771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 17841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *pd2 = NULL; 1791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 1801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_pd_alloc(pd_addr); 18141ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (pd == NULL) 18241ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 1838fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare getnstimeofday(&pd->last_rx_timestamp); 1841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 1851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 1861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd2 = container_of(e, struct oz_pd, link); 18793dc5e429b4d8ac8d683b61052592812e9353f9fdingtianhong if (ether_addr_equal(pd2->mac_addr, pd_addr)) { 1881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly free_pd = pd; 1891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = pd2; 1901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd != pd2) 1941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_add_tail(&pd->link, &g_pd_list); 1951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 19641ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (pd == NULL) { 1971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 19841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 1991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->net_dev != net_dev) { 2011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly old_net_dev = pd->net_dev; 2021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_hold(net_dev); 2031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->net_dev = net_dev; 2041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 205f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Host vendor: %d\n", body->host_vendor); 2061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_tx_size = OZ_MAX_TX_SIZE; 2071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->mode = body->mode; 2081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->pd_info = body->pd_info; 2091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->mode & OZ_F_ISOC_NO_ELTS) { 2101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->ms_per_isoc = body->ms_per_isoc; 2111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (!pd->ms_per_isoc) 2121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->ms_per_isoc = 4; 21386d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare 21486d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare switch (body->ms_isoc_latency & OZ_LATENCY_MASK) { 21586d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare case OZ_ONE_MS_LATENCY: 21686d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = (body->ms_isoc_latency & 21786d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare ~OZ_LATENCY_MASK) / pd->ms_per_isoc; 21886d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare break; 21986d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare case OZ_TEN_MS_LATENCY: 22086d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = ((body->ms_isoc_latency & 22186d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc; 22286d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare break; 22386d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare default: 22486d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC; 22586d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare } 2261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (body->max_len_div16) 2281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_tx_size = ((u16)body->max_len_div16)<<4; 229f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n", 230f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->max_tx_size, pd->ms_per_isoc); 2311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_stream_buffering = 3*1024; 2328fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->pulse_period = OZ_QUANTUM; 2338fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd_set_presleep(pd, body->presleep, 0); 2341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_set_keepalive(pd, body->keep_alive); 2351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 2361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= le16_to_cpu(get_unaligned(&body->apps)); 2371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((new_apps & 0x1) && (body->session_id)) { 2381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id) { 2391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id != body->session_id) { 2401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_SESSION_MISMATCH; 2411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly goto done; 2421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= ~0x1; /* Resume not permitted */ 2451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->session_id = 2461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_get_new_session_id(body->session_id); 2471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id && !body->session_id) { 2501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_SESSION_TEARDOWN; 2511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly stop_needed = 1; 2521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= ~0x1; /* Resume not permitted */ 2541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->session_id = 2551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_get_new_session_id(body->session_id); 2561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellydone: 2591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (rsp_status == OZ_STATUS_SUCCESS) { 2601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 start_apps = new_apps & ~pd->total_apps & ~0x1; 2611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 stop_apps = pd->total_apps & ~new_apps & ~0x1; 2621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 resume_apps = new_apps & pd->paused_apps & ~0x1; 2631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 2641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_set_state(pd, OZ_PD_S_CONNECTED); 265f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n", 266f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches new_apps, pd->total_apps, pd->paused_apps); 2671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (start_apps) { 2681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_services_start(pd, start_apps, 0)) 2691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_TOO_MANY_PDS; 2701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (resume_apps) 2721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_services_start(pd, resume_apps, 1)) 2731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_TOO_MANY_PDS; 2741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (stop_apps) 2751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_services_stop(pd, stop_apps, 0); 2761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_request_heartbeat(pd); 2771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 2791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_send_conn_rsp(pd, rsp_status); 2811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (rsp_status != OZ_STATUS_SUCCESS) { 2821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (stop_needed) 2831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 2841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 28541ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe pd = NULL; 2861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (old_net_dev) 2881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(old_net_dev); 2891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (free_pd) 2901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_destroy(free_pd); 2911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return pd; 2921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 2936e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 2944e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 2951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 2961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 2971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index, 298dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const u8 *report, u8 len) 2991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 3001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_farewell *f; 3011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_farewell *f2; 3021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int found = 0; 30318f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 304b2271b5bdf1fd8b7d5442e2452e9242b88c56e8fRupesh Gujare f = kmalloc(sizeof(struct oz_farewell) + len, GFP_ATOMIC); 3051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (!f) 3061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 3071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly f->ep_num = ep_num; 3081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly f->index = index; 309b50c460a6c03284f7e1b4cfe9266df0f9169ad24Rupesh Gujare f->len = len; 3101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memcpy(f->report, report, len); 311f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: Adding farewell report\n"); 3121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock(&g_polling_lock); 3131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each_entry(f2, &pd->farewell_list, link) { 3141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((f2->ep_num == ep_num) && (f2->index == index)) { 3151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly found = 1; 3161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_del(&f2->link); 3171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 3181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_add_tail(&f->link, &pd->farewell_list); 3211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock(&g_polling_lock); 3221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (found) 3231ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(f2); 3241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 3256e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 3264e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 3271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 3281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 3291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_rx_frame(struct sk_buff *skb) 3301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 3311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 *mac_hdr; 3321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 *src_addr; 3331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt *elt; 3341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int length; 33541ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *pd = NULL; 3361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); 3378fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct timespec current_time; 3381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int dup = 0; 3391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u32 pkt_num; 3401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 341f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n", 342f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control); 3431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly mac_hdr = skb_mac_header(skb); 3442dce674891c1d2708715fecaad222362db53f815Matina Maria Trompouki src_addr = &mac_hdr[ETH_ALEN]; 3451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length = skb->len; 3461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Check the version field */ 3481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_get_prot_ver(oz_hdr->control) != OZ_PROTOCOL_VERSION) { 349f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Incorrect protocol version: %d\n", 350f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_get_prot_ver(oz_hdr->control)); 3511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly goto done; 3521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pkt_num = le32_to_cpu(get_unaligned(&oz_hdr->pkt_num)); 3551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_pd_find(src_addr); 3571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) { 3588fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (!(pd->state & OZ_PD_S_CONNECTED)) 3598fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_pd_set_state(pd, OZ_PD_S_CONNECTED); 3608fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare getnstimeofday(¤t_time); 3618fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) || 3628fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare (pd->presleep < MSEC_PER_SEC)) { 3638fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); 3648fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->last_rx_timestamp = current_time; 3658fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare } 3661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pkt_num != pd->last_rx_pkt_num) { 3671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->last_rx_pkt_num = pkt_num; 3681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 3691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dup = 1; 370f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Duplicate frame\n"); 3711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) { 375f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(RX_FRAMES, "Received TRIGGER Frame\n"); 3761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->last_sent_frame = &pd->tx_queue; 3771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_hdr->control & OZ_F_ACK) { 3781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Retire completed frames */ 3791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_retire_tx_frames(pd, oz_hdr->last_pkt_num); 3801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((oz_hdr->control & OZ_F_ACK_REQUESTED) && 3821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (pd->state == OZ_PD_S_CONNECTED)) { 3831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int backlog = pd->nb_queued_frames; 3841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->trigger_pkt_num = pkt_num; 3851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Send queued frames */ 3861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_send_queued_frames(pd, backlog); 3871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length -= sizeof(struct oz_hdr); 3911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = (struct oz_elt *)((u8 *)oz_hdr + sizeof(struct oz_hdr)); 3921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (length >= sizeof(struct oz_elt)) { 3941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length -= sizeof(struct oz_elt) + elt->length; 3951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (length < 0) 3961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 3971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (elt->type) { 3981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_CONNECT_REQ: 399f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_CONNECT_REQ\n"); 4001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_connect_req(pd, elt, src_addr, skb->dev); 4011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_DISCONNECT: 403f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_DISCONNECT\n"); 4041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) 4051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_sleep(pd); 4061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_UPDATE_PARAM_REQ: { 4081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_update_param *body = 4091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_update_param *)(elt + 1); 410f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_UPDATE_PARAM_REQ\n"); 4111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && (pd->state & OZ_PD_S_CONNECTED)) { 4121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock(&g_polling_lock); 4131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_set_keepalive(pd, body->keepalive); 4148fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd_set_presleep(pd, body->presleep, 1); 4151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock(&g_polling_lock); 4161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_FAREWELL_REQ: { 4201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_farewell *body = 4211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_farewell *)(elt + 1); 422f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_FAREWELL_REQ\n"); 4231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_add_farewell(pd, body->ep_num, 4241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->index, body->report, 4251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->length + 1 - sizeof(*body)); 4261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_APP_DATA: 4291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && (pd->state & OZ_PD_S_CONNECTED)) { 4301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_app_hdr *app_hdr = 4311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_app_hdr *)(elt+1); 4321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (dup) 4331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_handle_app_elt(pd, app_hdr->app_id, elt); 4351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly default: 438f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: Unknown elt %02x\n", elt->type); 4391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = oz_next_elt(elt); 4411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellydone: 4431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) 4441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 4451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly consume_skb(skb); 4461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 4476e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 4484e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 4491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 4501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_protocol_term(void) 4521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 4538a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare struct oz_binding *b, *t; 4548a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare 4551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Walk the list of bindings and remove each one. 4561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 4588a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_for_each_entry_safe(b, t, &g_binding, link) { 4598a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_del(&b->link); 4601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 4611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_remove_pack(&b->ptype); 4621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (b->ptype.dev) 4631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(b->ptype.dev); 4641ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(b); 4651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 4661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 4681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Walk the list of PDs and stop each one. This causes the PD to be 4691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * removed from the list so we can just pull each one from the head 4701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * of the list. 4711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 4731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (!list_empty(&g_pd_list)) { 4741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd = 4751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_first_entry(&g_pd_list, struct oz_pd, link); 4761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_get(pd); 4771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 4781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 4791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 4801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 4811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 483f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Protocol stopped\n"); 4841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 4856e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 4864e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 4871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq 4881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4898fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_pd_heartbeat_handler(unsigned long data) 4901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 4918fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd = (struct oz_pd *)data; 4928fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare u16 apps = 0; 49318f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 4948fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 4958fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (pd->state & OZ_PD_S_CONNECTED) 4968fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare apps = pd->total_apps; 4978fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 4988fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (apps) 4998fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_pd_heartbeat(pd, apps); 500b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_put(pd); 5018fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare} 5026e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5034e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5048fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: softirq 5058fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare */ 5068fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_pd_timeout_handler(unsigned long data) 5078fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare{ 5088fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare int type; 5098fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd = (struct oz_pd *)data; 5108fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5118fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 5128fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare type = pd->timeout_type; 5138fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 5141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (type) { 5151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_TIMER_TOUT: 5161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_sleep(pd); 5171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 5181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_TIMER_STOP: 5191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 5201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 5211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 522b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_put(pd); 5231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5246e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5254e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5268fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: Interrupt 5271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5288fd070077410b26847ef6f5856850df417e7b83eRupesh Gujareenum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer) 5291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 5318fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5328fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd = container_of(timer, struct oz_pd, heartbeat); 5338fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_forward_now(timer, ktime_set(pd->pulse_period / 5348fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (pd->pulse_period % MSEC_PER_SEC) * NSEC_PER_MSEC)); 535b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_get(pd); 5368fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_schedule(&pd->heartbeat_tasklet); 5378fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare return HRTIMER_RESTART; 5381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5396e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5404e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5418fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: Interrupt 5421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5438fd070077410b26847ef6f5856850df417e7b83eRupesh Gujareenum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer) 5441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5458fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd; 5468fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5478fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd = container_of(timer, struct oz_pd, timeout); 548b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_get(pd); 5498fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_schedule(&pd->timeout_tasklet); 5508fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare return HRTIMER_NORESTART; 5511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5526e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5534e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5568fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time) 5571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5588fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 5598fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare switch (type) { 5608fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_TOUT: 5618fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_STOP: 5628fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (hrtimer_active(&pd->timeout)) { 5638fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_set_expires(&pd->timeout, ktime_set(due_time / 5648fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5658fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC)); 5668fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL); 5671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 5688fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start(&pd->timeout, ktime_set(due_time / 5698fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5708fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC), HRTIMER_MODE_REL); 5711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5728fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->timeout_type = type; 5738fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare break; 5748fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_HEARTBEAT: 5758fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (!hrtimer_active(&pd->heartbeat)) 5768fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start(&pd->heartbeat, ktime_set(due_time / 5778fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5788fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC), HRTIMER_MODE_REL); 5798fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare break; 5801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5818fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 5821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5836e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5844e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_pd_request_heartbeat(struct oz_pd *pd) 5881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5898fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_HEARTBEAT, pd->pulse_period > 0 ? 5908fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->pulse_period : OZ_QUANTUM); 5911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5926e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5934e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 596dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewestruct oz_pd *oz_pd_find(const u8 *mac_addr) 5971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 5991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 60018f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 6011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 6021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 6031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = container_of(e, struct oz_pd, link); 60493dc5e429b4d8ac8d683b61052592812e9353f9fdingtianhong if (ether_addr_equal(pd->mac_addr, mac_addr)) { 6051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly atomic_inc(&pd->ref_count); 6061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 6071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return pd; 6081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 61141ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 6121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6136e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6144e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_app_enable(int app_id, int enable) 6181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (app_id <= OZ_APPID_MAX) { 6201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 6211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (enable) 6221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_apps |= (1<<app_id); 6231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly else 6241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_apps &= ~(1<<app_id); 6251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 6261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6286e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6294e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq 6311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev, 6331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct packet_type *pt, struct net_device *orig_dev) 6341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb = skb_share_check(skb, GFP_ATOMIC); 63641ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (skb == NULL) 6371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 6381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_rx_queue.lock); 6391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (g_processing_rx) { 6401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* We already hold the lock so use __ variant. 6411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly __skb_queue_head(&g_rx_queue, skb); 6431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 6451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_processing_rx = 1; 6461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly do { 6471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 6481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_rx_frame(skb); 6501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_rx_queue.lock); 6511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (skb_queue_empty(&g_rx_queue)) { 6521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_processing_rx = 0; 6531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 6551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* We already hold the lock so use __ variant. 6571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb = __skb_dequeue(&g_rx_queue); 6591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } while (1); 6601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 6621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6636e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6644e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 66783e4817fc3a2092ac1545999705b799bea855bcbRupesh Gujarevoid oz_binding_add(const char *net_dev) 6681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_binding *binding; 6701ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman 671e4b41af14d7dc683ecd84a10fed8ea38b94f0f28Salym Senyonga binding = kzalloc(sizeof(struct oz_binding), GFP_KERNEL); 672a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga if (!binding) 673a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga return; 674a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga 675c632824ef26bb27e51518242650bf4195a33ae63Jérôme Pinot binding->ptype.type = htons(OZ_ETHERTYPE); 676a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga binding->ptype.func = oz_pkt_recv; 677a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga if (net_dev && *net_dev) { 678a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN); 679a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga oz_dbg(ON, "Adding binding: %s\n", net_dev); 680a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga binding->ptype.dev = dev_get_by_name(&init_net, net_dev); 681a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga if (binding->ptype.dev == NULL) { 682a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga oz_dbg(ON, "Netdev %s not found\n", net_dev); 683a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga kfree(binding); 684a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga return; 6851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 687a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga dev_add_pack(&binding->ptype); 688a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga spin_lock_bh(&g_binding_lock); 689a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga list_add_tail(&binding->link, &g_binding); 690a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga spin_unlock_bh(&g_binding_lock); 6911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6926e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6934e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void pd_stop_all_for_device(struct net_device *net_dev) 6971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head h; 6991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 7001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *n; 70118f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 7021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly INIT_LIST_HEAD(&h); 7031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 7041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each_entry_safe(pd, n, &g_pd_list, link) { 7051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->net_dev == net_dev) { 7061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_move(&pd->link, &h); 7071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_get(pd); 7081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 7111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (!list_empty(&h)) { 7121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = list_first_entry(&h, struct oz_pd, link); 7131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 7141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 7151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7176e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7184e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 72183e4817fc3a2092ac1545999705b799bea855bcbRupesh Gujarevoid oz_binding_remove(const char *net_dev) 7221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 72341ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_binding *binding; 7248a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare int found = 0; 7258a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare 726f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Removing binding: %s\n", net_dev); 7271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 7288a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_for_each_entry(binding, &g_binding, link) { 7294d6c9e57027940b6b492abac4c1b67710e38f366Rupesh Gujare if (strncmp(binding->name, net_dev, OZ_MAX_BINDING_LEN) == 0) { 730f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Binding '%s' found\n", net_dev); 7318a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare found = 1; 7321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 7331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 7368a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare if (found) { 7371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_remove_pack(&binding->ptype); 7381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (binding->ptype.dev) { 7391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(binding->ptype.dev); 7401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_stop_all_for_device(binding->ptype.dev); 7411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7428a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_del(&binding->link); 7431ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(binding); 7441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7466e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7474e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic char *oz_get_next_device_name(char *s, char *dname, int max_size) 7511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*s == ',') 7531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly s++; 7541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*s && (*s != ',') && max_size > 1) { 7551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly *dname++ = *s++; 7561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly max_size--; 7571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly *dname = 0; 7591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return s; 7601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7616e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7624e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyint oz_protocol_init(char *devs) 7661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_queue_head_init(&g_rx_queue); 76801c48ad3ea7f976ab9e02dca642c52f7cf1256b9Daeseok Youn if (devs[0] == '*') { 76941ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe oz_binding_add(NULL); 7701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 7711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly char d[32]; 7721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*devs) { 7731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly devs = oz_get_next_device_name(devs, d, sizeof(d)); 7741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (d[0]) 7751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_binding_add(d); 7761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 7791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7806e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7814e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyint oz_get_pd_list(struct oz_mac_addr *addr, int max_count) 7851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 7871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 7881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int count = 0; 78918f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 7901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 7911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 7921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (count >= max_count) 7931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 7941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = container_of(e, struct oz_pd, link); 795ae35f26644d1af10bfc96c5dffc5103c84a9b3c4Anil Belur ether_addr_copy((u8 *)&addr[count++], pd->mac_addr); 7961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 7981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return count; 7991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 8006e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 801