11619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly/* ----------------------------------------------------------------------------- 21619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Copyright (c) 2011 Ozmo Inc 31619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Released under the GNU General Public License Version 2 (GPLv2). 41619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * ----------------------------------------------------------------------------- 51619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 605f608f237dcc3c4e5188d054d9918cbfd2916c2Joe Perches 71619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/module.h> 81619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/timer.h> 91619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/sched.h> 101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/netdevice.h> 1193dc5e429b4d8ac8d683b61052592812e9353f9fdingtianhong#include <linux/etherdevice.h> 121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/errno.h> 131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/ieee80211.h> 142b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger#include <linux/slab.h> 15f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches#include "ozdbg.h" 161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozprotocol.h" 171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozeltbuf.h" 181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozpd.h" 191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozproto.h" 201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozusbsvc.h" 2105f608f237dcc3c4e5188d054d9918cbfd2916c2Joe Perches 221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include "ozappif.h" 231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <asm/unaligned.h> 241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <linux/uaccess.h> 251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#include <net/psnap.h> 266e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_CF_CONN_SUCCESS 1 281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_CF_CONN_FAILURE 2 291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_DO_STOP 1 311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly#define OZ_DO_SLEEP 2 321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystruct oz_binding { 341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct packet_type ptype; 351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly char name[OZ_MAX_BINDING_LEN]; 368a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare struct list_head link; 371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly}; 381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 394e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 406b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil * External variable 416b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil */ 426b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil 436b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra PatilDEFINE_SPINLOCK(g_polling_lock); 446b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil/* 451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Static external variables. 461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic LIST_HEAD(g_pd_list); 488a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujarestatic LIST_HEAD(g_binding); 491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic DEFINE_SPINLOCK(g_binding_lock); 501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic struct sk_buff_head g_rx_queue; 511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u8 g_session_id; 521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u16 g_apps = 0x1; 531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic int g_processing_rx; 546e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 552b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaegerstruct kmem_cache *oz_elt_info_cache; 5650222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaegerstruct kmem_cache *oz_tx_frame_cache; 572b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger 584e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic u8 oz_get_new_session_id(u8 exclude) 621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (++g_session_id == 0) 641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_session_id = 1; 651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (g_session_id == exclude) { 661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (++g_session_id == 0) 671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_session_id = 1; 681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return g_session_id; 701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 716e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 724e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_send_conn_rsp(struct oz_pd *pd, u8 status) 761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct sk_buff *skb; 781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct net_device *dev = pd->net_dev; 791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_hdr *oz_hdr; 801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt *elt; 811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_connect_rsp *body; 8218f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int sz = sizeof(struct oz_hdr) + sizeof(struct oz_elt) + 841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly sizeof(struct oz_elt_connect_rsp); 856b790d0fae3a6e80af6b0e71cbb39a38b822230aGreg Kroah-Hartman skb = alloc_skb(sz + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); 8641ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (skb == NULL) 871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_reset_network_header(skb); 901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, sz); 911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = (struct oz_elt *)(oz_hdr+1); 921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body = (struct oz_elt_connect_rsp *)(elt+1); 931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb->dev = dev; 941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Fill in device header */ 961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev->dev_addr, skb->len) < 0) { 98e79f864d5902a70c1b90f700628cb34756cd8c4aGreg Kroah-Hartman kfree_skb(skb); 991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 1001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT); 1021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_hdr->last_pkt_num = 0; 1031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly put_unaligned(0, &oz_hdr->pkt_num); 1041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->type = OZ_ELT_CONNECT_RSP; 1051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->length = sizeof(struct oz_elt_connect_rsp); 1061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memset(body, 0, sizeof(struct oz_elt_connect_rsp)); 1071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->status = status; 1081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (status == 0) { 1091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->mode = pd->mode; 1101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->session_id = pd->session_id; 1111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly put_unaligned(cpu_to_le16(pd->total_apps), &body->apps); 1121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 113f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "TX: OZ_ELT_CONNECT_RSP %d", status); 1141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_queue_xmit(skb); 1151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1166e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1174e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void pd_set_keepalive(struct oz_pd *pd, u8 kalive) 1211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly unsigned long keep_alive = kalive & OZ_KALIVE_VALUE_MASK; 1231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 1241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (kalive & OZ_KALIVE_TYPE_MASK) { 1251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_SPECIAL: 1268fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive * 1000*60*60*24*20; 1271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_SECS: 1298fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000; 1301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_MINS: 1328fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000*60; 1331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_KALIVE_HOURS: 1358fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = keep_alive*1000*60*60; 1361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly default: 1388fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->keep_alive = 0; 1391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1408fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_dbg(ON, "Keepalive = %lu mSec\n", pd->keep_alive); 1411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1426e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1434e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1468fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarestatic void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer) 1471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (presleep) 1498fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->presleep = presleep*100; 1501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly else 1518fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->presleep = OZ_PRESLEEP_TOUT; 1528fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (start_timer) { 1538fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock(&g_polling_lock); 1548fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); 1558fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock(&g_polling_lock); 1568fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare } 1578fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_dbg(ON, "Presleep time = %lu mSec\n", pd->presleep); 1581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 1596e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1604e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 1621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 1631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, 164dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const u8 *pd_addr, struct net_device *net_dev) 1651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 1661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 1671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_connect_req *body = 1681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_connect_req *)(elt+1); 1691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 rsp_status = OZ_STATUS_SUCCESS; 1701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 stop_needed = 0; 1711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 new_apps = g_apps; 17241ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct net_device *old_net_dev = NULL; 17341ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *free_pd = NULL; 17418f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 1751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (cur_pd) { 1761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = cur_pd; 1771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 1781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 17941ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *pd2 = NULL; 1801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct list_head *e; 181ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 1821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_pd_alloc(pd_addr); 18341ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (pd == NULL) 18441ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 1858fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare getnstimeofday(&pd->last_rx_timestamp); 1861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 1871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each(e, &g_pd_list) { 188a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger pd2 = list_entry(e, struct oz_pd, link); 18993dc5e429b4d8ac8d683b61052592812e9353f9fdingtianhong if (ether_addr_equal(pd2->mac_addr, pd_addr)) { 1901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly free_pd = pd; 1911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = pd2; 1921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 1931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 1951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd != pd2) 1961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_add_tail(&pd->link, &g_pd_list); 1971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 19841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (pd == NULL) { 1991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 20041ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 2011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->net_dev != net_dev) { 2031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly old_net_dev = pd->net_dev; 2041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_hold(net_dev); 2051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->net_dev = net_dev; 2061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 207f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Host vendor: %d\n", body->host_vendor); 2081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_tx_size = OZ_MAX_TX_SIZE; 2091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->mode = body->mode; 2101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->pd_info = body->pd_info; 2111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->mode & OZ_F_ISOC_NO_ELTS) { 2121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->ms_per_isoc = body->ms_per_isoc; 2131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (!pd->ms_per_isoc) 2141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->ms_per_isoc = 4; 21586d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare 21686d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare switch (body->ms_isoc_latency & OZ_LATENCY_MASK) { 21786d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare case OZ_ONE_MS_LATENCY: 21886d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = (body->ms_isoc_latency & 21986d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare ~OZ_LATENCY_MASK) / pd->ms_per_isoc; 22086d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare break; 22186d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare case OZ_TEN_MS_LATENCY: 22286d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = ((body->ms_isoc_latency & 22386d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc; 22486d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare break; 22586d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare default: 22686d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC; 22786d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare } 2281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (body->max_len_div16) 2301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_tx_size = ((u16)body->max_len_div16)<<4; 231f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n", 232f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->max_tx_size, pd->ms_per_isoc); 2331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->max_stream_buffering = 3*1024; 2348fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->pulse_period = OZ_QUANTUM; 2358fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd_set_presleep(pd, body->presleep, 0); 2361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_set_keepalive(pd, body->keep_alive); 2371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 2381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= le16_to_cpu(get_unaligned(&body->apps)); 2391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((new_apps & 0x1) && (body->session_id)) { 2401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id) { 2411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id != body->session_id) { 2421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_SESSION_MISMATCH; 2431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly goto done; 2441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= ~0x1; /* Resume not permitted */ 2471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->session_id = 2481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_get_new_session_id(body->session_id); 2491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->session_id && !body->session_id) { 2521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_SESSION_TEARDOWN; 2531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly stop_needed = 1; 2541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly new_apps &= ~0x1; /* Resume not permitted */ 2561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->session_id = 2571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_get_new_session_id(body->session_id); 2581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellydone: 2611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (rsp_status == OZ_STATUS_SUCCESS) { 2621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 start_apps = new_apps & ~pd->total_apps & ~0x1; 2631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 stop_apps = pd->total_apps & ~new_apps & ~0x1; 2641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u16 resume_apps = new_apps & pd->paused_apps & ~0x1; 265ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 2661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 2671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_set_state(pd, OZ_PD_S_CONNECTED); 268f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n", 269f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches new_apps, pd->total_apps, pd->paused_apps); 2701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (start_apps) { 2711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_services_start(pd, start_apps, 0)) 2721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_TOO_MANY_PDS; 2731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (resume_apps) 2751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_services_start(pd, resume_apps, 1)) 2761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly rsp_status = OZ_STATUS_TOO_MANY_PDS; 2771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (stop_apps) 2781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_services_stop(pd, stop_apps, 0); 2791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_request_heartbeat(pd); 2801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 2811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 2821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_send_conn_rsp(pd, rsp_status); 2841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (rsp_status != OZ_STATUS_SUCCESS) { 2851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (stop_needed) 2861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 2871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 28841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe pd = NULL; 2891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 2901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (old_net_dev) 2911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(old_net_dev); 2921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (free_pd) 2931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_destroy(free_pd); 2941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return pd; 2951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 2966e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 2974e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 2981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 2991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 3001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index, 301dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const u8 *report, u8 len) 3021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 3031619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_farewell *f; 3041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_farewell *f2; 3051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int found = 0; 30618f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 307b2271b5bdf1fd8b7d5442e2452e9242b88c56e8fRupesh Gujare f = kmalloc(sizeof(struct oz_farewell) + len, GFP_ATOMIC); 3081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (!f) 3091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return; 3101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly f->ep_num = ep_num; 3111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly f->index = index; 312b50c460a6c03284f7e1b4cfe9266df0f9169ad24Rupesh Gujare f->len = len; 3131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly memcpy(f->report, report, len); 314f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: Adding farewell report\n"); 3151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock(&g_polling_lock); 3161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each_entry(f2, &pd->farewell_list, link) { 3171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((f2->ep_num == ep_num) && (f2->index == index)) { 3181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly found = 1; 3191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_del(&f2->link); 3201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 3211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_add_tail(&f->link, &pd->farewell_list); 3241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock(&g_polling_lock); 3251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (found) 3261ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(f2); 3271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 3286e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 3294e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 3301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq-serialized 3311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 3321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void oz_rx_frame(struct sk_buff *skb) 3331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 3341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 *mac_hdr; 3351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u8 *src_addr; 3361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt *elt; 3371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int length; 33841ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_pd *pd = NULL; 3391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); 3408fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct timespec current_time; 3411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int dup = 0; 3421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly u32 pkt_num; 3431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 344f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n", 345f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control); 3461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly mac_hdr = skb_mac_header(skb); 3472dce674891c1d2708715fecaad222362db53f815Matina Maria Trompouki src_addr = &mac_hdr[ETH_ALEN]; 3481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length = skb->len; 3491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Check the version field */ 3511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_get_prot_ver(oz_hdr->control) != OZ_PROTOCOL_VERSION) { 352f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Incorrect protocol version: %d\n", 353f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_get_prot_ver(oz_hdr->control)); 3541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly goto done; 3551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pkt_num = le32_to_cpu(get_unaligned(&oz_hdr->pkt_num)); 3581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_pd_find(src_addr); 3601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) { 3618fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (!(pd->state & OZ_PD_S_CONNECTED)) 3628fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_pd_set_state(pd, OZ_PD_S_CONNECTED); 3638fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare getnstimeofday(¤t_time); 3648fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) || 3658fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare (pd->presleep < MSEC_PER_SEC)) { 3668fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); 3678fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->last_rx_timestamp = current_time; 3688fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare } 3691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pkt_num != pd->last_rx_pkt_num) { 3701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->last_rx_pkt_num = pkt_num; 3711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 3721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dup = 1; 373f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Duplicate frame\n"); 3741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) { 378f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(RX_FRAMES, "Received TRIGGER Frame\n"); 3791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->last_sent_frame = &pd->tx_queue; 3801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (oz_hdr->control & OZ_F_ACK) { 3811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Retire completed frames */ 3821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_retire_tx_frames(pd, oz_hdr->last_pkt_num); 3831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if ((oz_hdr->control & OZ_F_ACK_REQUESTED) && 3851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (pd->state == OZ_PD_S_CONNECTED)) { 3861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int backlog = pd->nb_queued_frames; 387ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 3881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd->trigger_pkt_num = pkt_num; 3891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Send queued frames */ 3901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_send_queued_frames(pd, backlog); 3911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 3931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length -= sizeof(struct oz_hdr); 3951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = (struct oz_elt *)((u8 *)oz_hdr + sizeof(struct oz_hdr)); 3961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 3971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (length >= sizeof(struct oz_elt)) { 3981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly length -= sizeof(struct oz_elt) + elt->length; 3991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (length < 0) 4001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (elt->type) { 4021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_CONNECT_REQ: 403f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_CONNECT_REQ\n"); 4041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = oz_connect_req(pd, elt, src_addr, skb->dev); 4051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_DISCONNECT: 407f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_DISCONNECT\n"); 4081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) 4091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_sleep(pd); 4101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_UPDATE_PARAM_REQ: { 4121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_update_param *body = 4131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_update_param *)(elt + 1); 414f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_UPDATE_PARAM_REQ\n"); 4151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && (pd->state & OZ_PD_S_CONNECTED)) { 4161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock(&g_polling_lock); 4171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_set_keepalive(pd, body->keepalive); 4188fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd_set_presleep(pd, body->presleep, 1); 4191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock(&g_polling_lock); 4201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_FAREWELL_REQ: { 4241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_elt_farewell *body = 4251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_elt_farewell *)(elt + 1); 426f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: OZ_ELT_FAREWELL_REQ\n"); 4271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_add_farewell(pd, body->ep_num, 4281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly body->index, body->report, 4291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt->length + 1 - sizeof(*body)); 4301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_ELT_APP_DATA: 4331619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd && (pd->state & OZ_PD_S_CONNECTED)) { 4341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_app_hdr *app_hdr = 4351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly (struct oz_app_hdr *)(elt+1); 4361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (dup) 4371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_handle_app_elt(pd, app_hdr->app_id, elt); 4391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 4411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly default: 442f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "RX: Unknown elt %02x\n", elt->type); 4431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly elt = oz_next_elt(elt); 4451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellydone: 4471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd) 4481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 4491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly consume_skb(skb); 4501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 4516e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 4524e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 4531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 4541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_protocol_term(void) 4561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 4578a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare struct oz_binding *b, *t; 4588a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare 4591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Walk the list of bindings and remove each one. 4601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 4628a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_for_each_entry_safe(b, t, &g_binding, link) { 4638a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_del(&b->link); 4641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 4651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_remove_pack(&b->ptype); 4661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (b->ptype.dev) 4671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(b->ptype.dev); 4681ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(b); 4691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 4701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 4721619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* Walk the list of PDs and stop each one. This causes the PD to be 4731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * removed from the list so we can just pull each one from the head 4741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * of the list. 4751619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4761619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 4771619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (!list_empty(&g_pd_list)) { 4781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd = 4791619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_first_entry(&g_pd_list, struct oz_pd, link); 4801619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_get(pd); 4811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 4821619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 4831619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 4841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 4851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 4861619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 487f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Protocol stopped\n"); 4882b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger 48950222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger kmem_cache_destroy(oz_tx_frame_cache); 4902b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger kmem_cache_destroy(oz_elt_info_cache); 4911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 4926e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 4934e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 4941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq 4951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 4968fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_pd_heartbeat_handler(unsigned long data) 4971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 4988fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd = (struct oz_pd *)data; 4998fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare u16 apps = 0; 50018f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 5018fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 5028fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (pd->state & OZ_PD_S_CONNECTED) 5038fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare apps = pd->total_apps; 5048fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 5058fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (apps) 5068fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_pd_heartbeat(pd, apps); 507b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_put(pd); 5088fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare} 5096e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5104e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5118fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: softirq 5128fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare */ 5138fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_pd_timeout_handler(unsigned long data) 5148fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare{ 5158fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare int type; 5168fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd = (struct oz_pd *)data; 5178fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5188fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 5198fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare type = pd->timeout_type; 5208fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 5211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly switch (type) { 5221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_TIMER_TOUT: 5231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_sleep(pd); 5241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 5251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly case OZ_TIMER_STOP: 5261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 5271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 5281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 529b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_put(pd); 5301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5316e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5324e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5338fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: Interrupt 5341619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5358fd070077410b26847ef6f5856850df417e7b83eRupesh Gujareenum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer) 5361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 5388fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5398fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd = container_of(timer, struct oz_pd, heartbeat); 5408fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_forward_now(timer, ktime_set(pd->pulse_period / 5418fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (pd->pulse_period % MSEC_PER_SEC) * NSEC_PER_MSEC)); 542b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_get(pd); 5438fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_schedule(&pd->heartbeat_tasklet); 5448fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare return HRTIMER_RESTART; 5451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5466e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5474e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5488fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare * Context: Interrupt 5491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5508fd070077410b26847ef6f5856850df417e7b83eRupesh Gujareenum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer) 5511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5528fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare struct oz_pd *pd; 5538fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 5548fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd = container_of(timer, struct oz_pd, timeout); 555b75d7d45f25c8361555f368665af6636bfd10102Rupesh Gujare oz_pd_get(pd); 5568fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_schedule(&pd->timeout_tasklet); 5578fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare return HRTIMER_NORESTART; 5581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5596e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5604e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5638fd070077410b26847ef6f5856850df417e7b83eRupesh Gujarevoid oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time) 5641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5658fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_lock_bh(&g_polling_lock); 5668fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare switch (type) { 5678fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_TOUT: 5688fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_STOP: 5698fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (hrtimer_active(&pd->timeout)) { 5708fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_set_expires(&pd->timeout, ktime_set(due_time / 5718fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5728fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC)); 5738fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL); 5741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 5758fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start(&pd->timeout, ktime_set(due_time / 5768fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5778fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC), HRTIMER_MODE_REL); 5781619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5798fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->timeout_type = type; 5808fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare break; 5818fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare case OZ_TIMER_HEARTBEAT: 5828fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (!hrtimer_active(&pd->heartbeat)) 5838fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_start(&pd->heartbeat, ktime_set(due_time / 5848fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * 5858fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare NSEC_PER_MSEC), HRTIMER_MODE_REL); 5868fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare break; 5871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 5888fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare spin_unlock_bh(&g_polling_lock); 5891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5906e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5914e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 5921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 5931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 5941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_pd_request_heartbeat(struct oz_pd *pd) 5951619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 5968fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_HEARTBEAT, pd->pulse_period > 0 ? 5978fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->pulse_period : OZ_QUANTUM); 5981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 5996e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6004e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq or process 6021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 603dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewestruct oz_pd *oz_pd_find(const u8 *mac_addr) 6041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 60618f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 6071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 608a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_entry(pd, &g_pd_list, link) { 60993dc5e429b4d8ac8d683b61052592812e9353f9fdingtianhong if (ether_addr_equal(pd->mac_addr, mac_addr)) { 610a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger oz_pd_get(pd); 6111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 6121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return pd; 6131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 61641ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe return NULL; 6171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6186e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6194e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6211619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6221619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyvoid oz_app_enable(int app_id, int enable) 6231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 624a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger if (app_id < OZ_NB_APPS) { 6251619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 6261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (enable) 6271619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_apps |= (1<<app_id); 6281619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly else 6291619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_apps &= ~(1<<app_id); 6301619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 6311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6321619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6336e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6344e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6351619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: softirq 6361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev, 6381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct packet_type *pt, struct net_device *orig_dev) 6391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6401619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb = skb_share_check(skb, GFP_ATOMIC); 64141ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe if (skb == NULL) 6421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 6431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_rx_queue.lock); 6441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (g_processing_rx) { 6451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* We already hold the lock so use __ variant. 6461619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6471619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly __skb_queue_head(&g_rx_queue, skb); 6481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 6501619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_processing_rx = 1; 6511619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly do { 6521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly 6531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_rx_frame(skb); 6551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_rx_queue.lock); 6561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (skb_queue_empty(&g_rx_queue)) { 6571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly g_processing_rx = 0; 6581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_rx_queue.lock); 6591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 6601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly /* We already hold the lock so use __ variant. 6621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 6631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb = __skb_dequeue(&g_rx_queue); 6641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } while (1); 6651619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6661619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 6671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6686e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6694e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 6711619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 67283e4817fc3a2092ac1545999705b799bea855bcbRupesh Gujarevoid oz_binding_add(const char *net_dev) 6731619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 6741619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_binding *binding; 6751ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman 676e4b41af14d7dc683ecd84a10fed8ea38b94f0f28Salym Senyonga binding = kzalloc(sizeof(struct oz_binding), GFP_KERNEL); 677a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga if (!binding) 678a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga return; 679a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga 680c632824ef26bb27e51518242650bf4195a33ae63Jérôme Pinot binding->ptype.type = htons(OZ_ETHERTYPE); 681a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga binding->ptype.func = oz_pkt_recv; 682a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga if (net_dev && *net_dev) { 683a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN); 684a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga oz_dbg(ON, "Adding binding: %s\n", net_dev); 685a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga binding->ptype.dev = dev_get_by_name(&init_net, net_dev); 686a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga if (binding->ptype.dev == NULL) { 687a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga oz_dbg(ON, "Netdev %s not found\n", net_dev); 688a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga kfree(binding); 689a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga return; 6901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 6911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 692a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga dev_add_pack(&binding->ptype); 693a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga spin_lock_bh(&g_binding_lock); 694a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga list_add_tail(&binding->link, &g_binding); 695a44755d88c1ac17549da59f97428f9204ba1bd5eSalym Senyonga spin_unlock_bh(&g_binding_lock); 6961619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 6976e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6984e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 6991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic void pd_stop_all_for_device(struct net_device *net_dev) 7021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 703a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger LIST_HEAD(h); 7041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 7051619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *n; 70618f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 7071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 7081619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_for_each_entry_safe(pd, n, &g_pd_list, link) { 7091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (pd->net_dev == net_dev) { 7101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly list_move(&pd->link, &h); 7111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_get(pd); 7121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7131619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7141619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 7151619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (!list_empty(&h)) { 7161619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd = list_first_entry(&h, struct oz_pd, link); 7171619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_stop(pd); 7181619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_pd_put(pd); 7191619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7201619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7216e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7224e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7231619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7241619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 72583e4817fc3a2092ac1545999705b799bea855bcbRupesh Gujarevoid oz_binding_remove(const char *net_dev) 7261619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 72741ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe struct oz_binding *binding; 7288a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare int found = 0; 7298a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare 730f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Removing binding: %s\n", net_dev); 7311619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_binding_lock); 7328a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_for_each_entry(binding, &g_binding, link) { 7334d6c9e57027940b6b492abac4c1b67710e38f366Rupesh Gujare if (strncmp(binding->name, net_dev, OZ_MAX_BINDING_LEN) == 0) { 734f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Binding '%s' found\n", net_dev); 7358a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare found = 1; 7361619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 7371619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7381619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7391619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_binding_lock); 7408a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare if (found) { 7411619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_remove_pack(&binding->ptype); 7421619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (binding->ptype.dev) { 7431619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly dev_put(binding->ptype.dev); 7441619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly pd_stop_all_for_device(binding->ptype.dev); 7451619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7468a3cac62efd0c447e017180aa7bf2638603ee21cRupesh Gujare list_del(&binding->link); 7471ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(binding); 7481619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7491619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7506e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7514e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7521619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7531619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7541619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellystatic char *oz_get_next_device_name(char *s, char *dname, int max_size) 7551619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7561619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*s == ',') 7571619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly s++; 7581619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*s && (*s != ',') && max_size > 1) { 7591619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly *dname++ = *s++; 7601619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly max_size--; 7611619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7621619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly *dname = 0; 7631619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return s; 7641619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7656e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7664e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7671619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7681619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7691619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyint oz_protocol_init(char *devs) 7701619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 7712b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger oz_elt_info_cache = KMEM_CACHE(oz_elt_info, 0); 7722b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger if (!oz_elt_info_cache) 7732b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger return -ENOMEM; 7742b8b61aaef59751fe85c1b2df51a848a6c50d202Christoph Jaeger 77550222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger oz_tx_frame_cache = KMEM_CACHE(oz_tx_frame, 0); 77650222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger if (!oz_tx_frame_cache) { 77750222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger kmem_cache_destroy(oz_elt_info_cache); 77850222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger return -ENOMEM; 77950222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger } 78050222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger 7811619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly skb_queue_head_init(&g_rx_queue); 78201c48ad3ea7f976ab9e02dca642c52f7cf1256b9Daeseok Youn if (devs[0] == '*') { 78341ebb8a1c5f1f567b9c30c9b50aace91387537f8Peter Huewe oz_binding_add(NULL); 7841619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } else { 7851619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly char d[32]; 786ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 7871619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly while (*devs) { 7881619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly devs = oz_get_next_device_name(devs, d, sizeof(d)); 7891619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (d[0]) 7901619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly oz_binding_add(d); 7911619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7921619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 7931619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return 0; 7941619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 7956e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7964e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 7971619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly * Context: process 7981619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly */ 7991619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kellyint oz_get_pd_list(struct oz_mac_addr *addr, int max_count) 8001619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly{ 8011619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly struct oz_pd *pd; 8021619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly int count = 0; 80318f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 8041619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_lock_bh(&g_polling_lock); 805a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_entry(pd, &g_pd_list, link) { 8061619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly if (count >= max_count) 8071619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly break; 808ae35f26644d1af10bfc96c5dffc5103c84a9b3c4Anil Belur ether_addr_copy((u8 *)&addr[count++], pd->mac_addr); 8091619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly } 8101619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly spin_unlock_bh(&g_polling_lock); 8111619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly return count; 8121619cb6f2dd9674491e5772bf37b45e03666dc10Chris Kelly} 8136e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 814