1bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/* ----------------------------------------------------------------------------- 2bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Copyright (c) 2011 Ozmo Inc 3bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Released under the GNU General Public License Version 2 (GPLv2). 4bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * ----------------------------------------------------------------------------- 5bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 605f608f237dcc3c4e5188d054d9918cbfd2916c2Joe Perches 7bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/module.h> 8bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/timer.h> 9bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/sched.h> 10bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/netdevice.h> 11072dc1146fb85a9c344138a9751136dff1251333Jérôme Pinot#include <linux/etherdevice.h> 12bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/errno.h> 13f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches#include "ozdbg.h" 14bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozprotocol.h" 15bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozeltbuf.h" 16bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozpd.h" 17bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozproto.h" 18bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozcdev.h" 19bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozusbsvc.h" 20bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <asm/unaligned.h> 21bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/uaccess.h> 22bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <net/psnap.h> 2305f608f237dcc3c4e5188d054d9918cbfd2916c2Joe Perches 24bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd); 25bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f); 2633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujarestatic void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f); 27bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f); 28bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic int oz_send_isoc_frame(struct oz_pd *pd); 29bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f); 30bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_isoc_stream_free(struct oz_isoc_stream *st); 3133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujarestatic int oz_send_next_queued_frame(struct oz_pd *pd, int more_data); 32bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_isoc_destructor(struct sk_buff *skb); 336e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 344e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 35bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Counts the uncompleted isoc frames submitted to netcard. 36bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 37bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic atomic_t g_submitted_isoc = ATOMIC_INIT(0); 386e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 39bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/* Application handler functions. 40bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 41a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaegerstatic const struct oz_app_if g_app_if[OZ_NB_APPS] = { 42a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger [OZ_APPID_USB] = { 43a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .init = oz_usb_init, 44a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .term = oz_usb_term, 45a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .start = oz_usb_start, 46a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .stop = oz_usb_stop, 47a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .rx = oz_usb_rx, 48a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .heartbeat = oz_usb_heartbeat, 49a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .farewell = oz_usb_farewell, 50a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger }, 51a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger [OZ_APPID_SERIAL] = { 52a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .init = oz_cdev_init, 53a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .term = oz_cdev_term, 54a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .start = oz_cdev_start, 55a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .stop = oz_cdev_stop, 56a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger .rx = oz_cdev_rx, 57a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger }, 58bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly}; 596e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 606e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 614e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 62bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 63bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 64bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_set_state(struct oz_pd *pd, unsigned state) 65bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 66bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->state = state; 67bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly switch (state) { 68bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly case OZ_PD_S_IDLE: 69f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_IDLE\n"); 70bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 71bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly case OZ_PD_S_CONNECTED: 72f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_CONNECTED\n"); 73bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 74bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly case OZ_PD_S_STOPPED: 75f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_STOPPED\n"); 76bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 77bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly case OZ_PD_S_SLEEP: 78f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_SLEEP\n"); 79bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 80bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 81bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 826e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 834e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 84bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 85bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 86bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_get(struct oz_pd *pd) 87bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 88bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly atomic_inc(&pd->ref_count); 89bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 906e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 914e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 92bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 93bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 94bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_put(struct oz_pd *pd) 95bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 96bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (atomic_dec_and_test(&pd->ref_count)) 97bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_destroy(pd); 98bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 996e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1004e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 101bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 102bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 103dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewestruct oz_pd *oz_pd_alloc(const u8 *mac_addr) 104bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 1051ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman struct oz_pd *pd = kzalloc(sizeof(struct oz_pd), GFP_ATOMIC); 10618f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 107bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd) { 108bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int i; 109ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 110bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly atomic_set(&pd->ref_count, 2); 111a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger for (i = 0; i < OZ_NB_APPS; i++) 112bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_init(&pd->app_lock[i]); 113bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->last_rx_pkt_num = 0xffffffff; 114bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_set_state(pd, OZ_PD_S_IDLE); 115bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->max_tx_size = OZ_MAX_TX_SIZE; 116072dc1146fb85a9c344138a9751136dff1251333Jérôme Pinot ether_addr_copy(pd->mac_addr, mac_addr); 117a7ae725c9295d9076c889bbb75f83cd8e053bfb6Christoph Jaeger oz_elt_buf_init(&pd->elt_buff); 118bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_init(&pd->tx_frame_lock); 119bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&pd->tx_queue); 120bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&pd->farewell_list); 121bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->last_sent_frame = &pd->tx_queue; 122bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_init(&pd->stream_lock); 123bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&pd->stream_list); 1248fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_init(&pd->heartbeat_tasklet, oz_pd_heartbeat_handler, 1258fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare (unsigned long)pd); 1268fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_init(&pd->timeout_tasklet, oz_pd_timeout_handler, 1278fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare (unsigned long)pd); 1288fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_init(&pd->heartbeat, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 1298fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 1308fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->heartbeat.function = oz_pd_heartbeat_event; 1318fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare pd->timeout.function = oz_pd_timeout_event; 132bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 133bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return pd; 134bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 1356e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1364e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 137bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 138bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 139421acbc251a016b98797a06103374b48b30f943aFengguang Wustatic void oz_pd_free(struct work_struct *work) 140bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 141a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger struct list_head *e, *n; 1426af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare struct oz_pd *pd; 14318f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 144f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "Destroying PD\n"); 1456af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare pd = container_of(work, struct oz_pd, workitem); 1468fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare /*Disable timer tasklets*/ 1478fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_kill(&pd->heartbeat_tasklet); 1488fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare tasklet_kill(&pd->timeout_tasklet); 149a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger 150a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger /* Free streams, queued tx frames and farewells. */ 151a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger 152a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_safe(e, n, &pd->stream_list) 153a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger oz_isoc_stream_free(list_entry(e, struct oz_isoc_stream, link)); 154a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger 155a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_safe(e, n, &pd->tx_queue) { 156a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger struct oz_tx_frame *f = list_entry(e, struct oz_tx_frame, link); 157ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 15833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (f->skb != NULL) 159dd3cef0f0715b79d29a4b0482117175f44b7d83cGreg Kroah-Hartman kfree_skb(f->skb); 160bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_retire_frame(pd, f); 161bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 162a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger 163bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_elt_buf_term(&pd->elt_buff); 164a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger 165a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_safe(e, n, &pd->farewell_list) 166a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger kfree(list_entry(e, struct oz_farewell, link)); 167a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger 168bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->net_dev) 169bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly dev_put(pd->net_dev); 1701ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(pd); 171bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 1726e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 1734e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 1746af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare * Context: softirq or Process 1756af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare */ 1766af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujarevoid oz_pd_destroy(struct oz_pd *pd) 1776af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare{ 1786af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare if (hrtimer_active(&pd->timeout)) 1796af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare hrtimer_cancel(&pd->timeout); 1806af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare if (hrtimer_active(&pd->heartbeat)) 1816af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare hrtimer_cancel(&pd->heartbeat); 1826af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare 1836af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare INIT_WORK(&pd->workitem, oz_pd_free); 184dfc065f19fe0ce4ef7a52011801c5c19131e6529Rupesh Gujare if (!schedule_work(&pd->workitem)) 1856af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare oz_pd_dbg(pd, ON, "failed to schedule workitem\n"); 1866af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare} 1876af47622398d65e4cb3a52af5de52c6b447270d5Rupesh Gujare 1884e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 189bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 190bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 191bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_services_start(struct oz_pd *pd, u16 apps, int resume) 192bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 193a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger int i, rc = 0; 19418f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 195f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "%s: (0x%x) resume(%d)\n", __func__, apps, resume); 196a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger for (i = 0; i < OZ_NB_APPS; i++) { 197a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger if (g_app_if[i].start && (apps & (1 << i))) { 198a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger if (g_app_if[i].start(pd, resume)) { 199bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly rc = -1; 200f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, 201a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger "Unable to start service %d\n", i); 202bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 203bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 2046b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_lock_bh(&g_polling_lock); 205a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger pd->total_apps |= (1 << i); 206bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (resume) 207a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger pd->paused_apps &= ~(1 << i); 2086b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_unlock_bh(&g_polling_lock); 209bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 210bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 211bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return rc; 212bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 2136e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 2144e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 215bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 216bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 217bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_services_stop(struct oz_pd *pd, u16 apps, int pause) 218bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 219a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger int i; 22018f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 221f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "%s: (0x%x) pause(%d)\n", __func__, apps, pause); 222a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger for (i = 0; i < OZ_NB_APPS; i++) { 223a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger if (g_app_if[i].stop && (apps & (1 << i))) { 2246b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_lock_bh(&g_polling_lock); 225bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pause) { 226a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger pd->paused_apps |= (1 << i); 227bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } else { 228a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger pd->total_apps &= ~(1 << i); 229a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger pd->paused_apps &= ~(1 << i); 230bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 2316b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_unlock_bh(&g_polling_lock); 232a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger g_app_if[i].stop(pd, pause); 233bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 234bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 235bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 2366e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 2374e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 238bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 239bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 240bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_heartbeat(struct oz_pd *pd, u16 apps) 241bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 242a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger int i, more = 0; 24318f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 244a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger for (i = 0; i < OZ_NB_APPS; i++) { 245a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger if (g_app_if[i].heartbeat && (apps & (1 << i))) { 246a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger if (g_app_if[i].heartbeat(pd)) 247bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly more = 1; 248bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 249bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 2508fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if ((!more) && (hrtimer_active(&pd->heartbeat))) 2518fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare hrtimer_cancel(&pd->heartbeat); 252bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->mode & OZ_F_ISOC_ANYTIME) { 253bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int count = 8; 254ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 255bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (count-- && (oz_send_isoc_frame(pd) >= 0)) 256bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ; 257bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 258bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 2596e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 2604e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 261bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 262bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 263bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_stop(struct oz_pd *pd) 264bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 265a15e042e262bb62cd8dd9a7ccda9137c9e65cedcRupesh Gujare u16 stop_apps; 26618f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 267f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "oz_pd_stop() State = 0x%x\n", pd->state); 268bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_indicate_farewells(pd); 2696b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_lock_bh(&g_polling_lock); 270bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly stop_apps = pd->total_apps; 271bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->total_apps = 0; 272bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->paused_apps = 0; 2736b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_unlock_bh(&g_polling_lock); 274bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_services_stop(pd, stop_apps, 0); 2756b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_lock_bh(&g_polling_lock); 276bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_set_state(pd, OZ_PD_S_STOPPED); 277bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Remove from PD list.*/ 278bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_del(&pd->link); 2796b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_unlock_bh(&g_polling_lock); 280f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count)); 281bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_put(pd); 282bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 2836e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 2844e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 285bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 286bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 287bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_pd_sleep(struct oz_pd *pd) 288bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 289bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int do_stop = 0; 290a15e042e262bb62cd8dd9a7ccda9137c9e65cedcRupesh Gujare u16 stop_apps; 29118f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 2926b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_lock_bh(&g_polling_lock); 293bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) { 2946b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_unlock_bh(&g_polling_lock); 295bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 296bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 2978fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare if (pd->keep_alive && pd->session_id) 298bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_set_state(pd, OZ_PD_S_SLEEP); 2998fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare else 300bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly do_stop = 1; 3018fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare 302bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly stop_apps = pd->total_apps; 3036b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_unlock_bh(&g_polling_lock); 304bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (do_stop) { 305bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_stop(pd); 306bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } else { 307bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_services_stop(pd, stop_apps, 1); 3088fd070077410b26847ef6f5856850df417e7b83eRupesh Gujare oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive); 309bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 310bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return do_stop; 311bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 3126e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 3134e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 314bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 315bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 316bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd) 317bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 31850222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger struct oz_tx_frame *f; 31918f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 32050222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger f = kmem_cache_alloc(oz_tx_frame_cache, GFP_ATOMIC); 321bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (f) { 322bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f->total_size = sizeof(struct oz_hdr); 323bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&f->link); 324bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&f->elt_list); 325bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 326bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return f; 327bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 3286e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 3294e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 330bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 331bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 33233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujarestatic void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f) 33333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare{ 33433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare pd->nb_queued_isoc_frames--; 33533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare list_del_init(&f->link); 33650222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger 33750222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger kmem_cache_free(oz_tx_frame_cache, f); 33850222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger 339f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n", 340f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->nb_queued_isoc_frames); 34133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare} 3426e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 3434e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 34433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare * Context: softirq or process 34533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare */ 346bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f) 347bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 34850222db4b03ac8f3259c6d39bbd585ed3358f70fChristoph Jaeger kmem_cache_free(oz_tx_frame_cache, f); 349bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 3506e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 3514e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 35233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare * Context: softirq-serialized 35333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare */ 354a7f74c3005cf6830a20d71c4e1d8d6d77443e5cbPeter Huewestatic void oz_set_more_bit(struct sk_buff *skb) 35533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare{ 35633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); 35718f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 35833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_hdr->control |= OZ_F_MORE_DATA; 35933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare} 3606e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 3614e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 36200ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare * Context: softirq-serialized 36300ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare */ 364a7f74c3005cf6830a20d71c4e1d8d6d77443e5cbPeter Huewestatic void oz_set_last_pkt_nb(struct oz_pd *pd, struct sk_buff *skb) 36500ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare{ 36600ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); 36718f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 36800ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; 36900ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare} 3706e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 3714e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 372bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 373bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 374bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_prepare_frame(struct oz_pd *pd, int empty) 375bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 376bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_tx_frame *f; 37718f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 378bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if ((pd->mode & OZ_MODE_MASK) != OZ_MODE_TRIGGERED) 379bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 380bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->nb_queued_frames >= OZ_MAX_QUEUED_FRAMES) 381bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 382bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!empty && !oz_are_elts_available(&pd->elt_buff)) 383bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 384bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f = oz_tx_frame_alloc(pd); 38586b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (f == NULL) 386bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 38733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare f->skb = NULL; 388bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f->hdr.control = 389bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ACK_REQUESTED; 390bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ++pd->last_tx_pkt_num; 391bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly put_unaligned(cpu_to_le32(pd->last_tx_pkt_num), &f->hdr.pkt_num); 392bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (empty == 0) { 393bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_select_elts_for_tx(&pd->elt_buff, 0, &f->total_size, 394bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->max_tx_size, &f->elt_list); 395bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 396bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock(&pd->tx_frame_lock); 397bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_add_tail(&f->link, &pd->tx_queue); 398bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->nb_queued_frames++; 399bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock(&pd->tx_frame_lock); 400bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 401bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 4026e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 4034e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 404bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 405bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 406bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f) 407bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 40886b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct sk_buff *skb; 409bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct net_device *dev = pd->net_dev; 410bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_hdr *oz_hdr; 411bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_elt *elt; 412a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger struct oz_elt_info *ei; 41318f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 414bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Allocate skb with enough space for the lower layers as well 415bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * as the space we need. 416bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 417ec0ee957f657b6200a2629d4c54df68d2c622e12Greg Kroah-Hartman skb = alloc_skb(f->total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); 41886b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (skb == NULL) 41986b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe return NULL; 420bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Reserve the head room for lower layers. 421bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 422bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 423bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reset_network_header(skb); 424bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->dev = dev; 425bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 426bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 427bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly dev->dev_addr, skb->len) < 0) 428bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly goto fail; 429bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Push the tail to the end of the area we are going to copy to. 430bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 431bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, f->total_size); 432bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f->hdr.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; 433bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(oz_hdr, &f->hdr, sizeof(struct oz_hdr)); 434bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Copy the elements into the frame body. 435bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 436bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly elt = (struct oz_elt *)(oz_hdr+1); 437a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_entry(ei, &f->elt_list, link) { 438bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(elt, ei->data, ei->length); 439bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly elt = oz_next_elt(elt); 440bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 441bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return skb; 442bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyfail: 443dd3cef0f0715b79d29a4b0482117175f44b7d83cGreg Kroah-Hartman kfree_skb(skb); 44486b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe return NULL; 445bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 4466e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 4474e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 448bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 449bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 450bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f) 451bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 452a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger struct oz_elt_info *ei, *n; 45318f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 454a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_entry_safe(ei, n, &f->elt_list, link) { 455bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_del_init(&ei->link); 456bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (ei->callback) 457bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ei->callback(pd, ei->context); 458bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->elt_buff.lock); 459bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_elt_info_free(&pd->elt_buff, ei); 460bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->elt_buff.lock); 461bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 462bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_tx_frame_free(pd, f); 463bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 4646e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 4654e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 466bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 467bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 46833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujarestatic int oz_send_next_queued_frame(struct oz_pd *pd, int more_data) 469bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 470bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct sk_buff *skb; 471bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_tx_frame *f; 472bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct list_head *e; 47318f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 474bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock(&pd->tx_frame_lock); 475bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = pd->last_sent_frame->next; 476bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (e == &pd->tx_queue) { 477bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock(&pd->tx_frame_lock); 478bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 479bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 480a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger f = list_entry(e, struct oz_tx_frame, link); 48133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 48233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (f->skb != NULL) { 48333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare skb = f->skb; 48433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_tx_isoc_free(pd, f); 48533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare spin_unlock(&pd->tx_frame_lock); 48633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (more_data) 48733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_set_more_bit(skb); 48800ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare oz_set_last_pkt_nb(pd, skb); 48933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if ((int)atomic_read(&g_submitted_isoc) < 49033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare OZ_MAX_SUBMITTED_ISOC) { 49133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (dev_queue_xmit(skb) < 0) { 492f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Dropping ISOC Frame\n"); 49333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return -1; 49433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 49533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare atomic_inc(&g_submitted_isoc); 496f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Sending ISOC Frame, nb_isoc= %d\n", 497f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->nb_queued_isoc_frames); 49833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return 0; 49933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 500d75b6c6154267618363f0126bd50c73f8d448a24Adrian Nicoara kfree_skb(skb); 501d75b6c6154267618363f0126bd50c73f8d448a24Adrian Nicoara oz_dbg(TX_FRAMES, "Dropping ISOC Frame>\n"); 502d75b6c6154267618363f0126bd50c73f8d448a24Adrian Nicoara return -1; 50333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 50433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 50533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare pd->last_sent_frame = e; 506bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb = oz_build_frame(pd, f); 507bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock(&pd->tx_frame_lock); 50837bc8f7856fc0c851980f01174ca936741511523Rupesh Gujare if (!skb) 50937bc8f7856fc0c851980f01174ca936741511523Rupesh Gujare return -1; 51033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (more_data) 51133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_set_more_bit(skb); 512f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num); 51337bc8f7856fc0c851980f01174ca936741511523Rupesh Gujare if (dev_queue_xmit(skb) < 0) 51437bc8f7856fc0c851980f01174ca936741511523Rupesh Gujare return -1; 51533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 516bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 517bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 5186e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5194e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 520bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 521bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 522bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_send_queued_frames(struct oz_pd *pd, int backlog) 523bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 52433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare while (oz_prepare_frame(pd, 0) >= 0) 52533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare backlog++; 52633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 52733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare switch (pd->mode & (OZ_F_ISOC_NO_ELTS | OZ_F_ISOC_ANYTIME)) { 52833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 52933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare case OZ_F_ISOC_NO_ELTS: { 53033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare backlog += pd->nb_queued_isoc_frames; 53133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (backlog <= 0) 53233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 53333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (backlog > OZ_MAX_SUBMITTED_ISOC) 53433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare backlog = OZ_MAX_SUBMITTED_ISOC; 53533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare break; 536bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 53733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare case OZ_NO_ELTS_ANYTIME: { 53833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if ((backlog <= 0) && (pd->isoc_sent == 0)) 53933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 54033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare break; 54133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 54233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare default: { 54333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (backlog <= 0) 54433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 54533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare break; 54633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 54733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 54833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare while (backlog--) { 54933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (oz_send_next_queued_frame(pd, backlog) < 0) 55033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare break; 551bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 55233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return; 55333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 55433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujareout: oz_prepare_frame(pd, 1); 55533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_send_next_queued_frame(pd, 0); 556bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 5576e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 5584e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 559bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 560bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 561bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic int oz_send_isoc_frame(struct oz_pd *pd) 562bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 56386b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct sk_buff *skb; 564bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct net_device *dev = pd->net_dev; 565bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_hdr *oz_hdr; 566bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_elt *elt; 567a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger struct oz_elt_info *ei; 568a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger LIST_HEAD(list); 569bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int total_size = sizeof(struct oz_hdr); 57018f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 571bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_select_elts_for_tx(&pd->elt_buff, 1, &total_size, 572bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->max_tx_size, &list); 573a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger if (list_empty(&list)) 574bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 575ec0ee957f657b6200a2629d4c54df68d2c622e12Greg Kroah-Hartman skb = alloc_skb(total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); 57686b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (skb == NULL) { 577f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Cannot alloc skb\n"); 578bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_elt_info_free_chain(&pd->elt_buff, &list); 579bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 580bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 581bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 582bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reset_network_header(skb); 583bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->dev = dev; 584bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 585bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 586bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly dev->dev_addr, skb->len) < 0) { 587dd3cef0f0715b79d29a4b0482117175f44b7d83cGreg Kroah-Hartman kfree_skb(skb); 588bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 589bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 590bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, total_size); 591bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC; 592bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; 593bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly elt = (struct oz_elt *)(oz_hdr+1); 594bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly 595a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_entry(ei, &list, link) { 596bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(elt, ei->data, ei->length); 597bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly elt = oz_next_elt(elt); 598bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 599bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly dev_queue_xmit(skb); 600bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_elt_info_free_chain(&pd->elt_buff, &list); 601bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 602bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 6036e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6044e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 605bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 606bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 607bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_retire_tx_frames(struct oz_pd *pd, u8 lpn) 608bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 609a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger struct oz_tx_frame *f, *tmp = NULL; 610bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly u8 diff; 611bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly u32 pkt_num; 612bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly 613a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger LIST_HEAD(list); 614a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger 615bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock(&pd->tx_frame_lock); 616a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_entry(f, &pd->tx_queue, link) { 617bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pkt_num = le32_to_cpu(get_unaligned(&f->hdr.pkt_num)); 618bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly diff = (lpn - (pkt_num & OZ_LAST_PN_MASK)) & OZ_LAST_PN_MASK; 61933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0)) 620bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 621f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n", 622f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pkt_num, pd->nb_queued_frames); 623a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger tmp = f; 624bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->nb_queued_frames--; 625bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 626a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger if (tmp) 627a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_cut_position(&list, &pd->tx_queue, &tmp->link); 628bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->last_sent_frame = &pd->tx_queue; 629bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock(&pd->tx_frame_lock); 630a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger 631a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_entry_safe(f, tmp, &list, link) 632bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_retire_frame(pd, f); 633bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 6346e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6354e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 636bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Precondition: stream_lock must be held. 637bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 638bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 639bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct oz_isoc_stream *pd_stream_find(struct oz_pd *pd, u8 ep_num) 640bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 641bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_stream *st; 64218f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 643a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_entry(st, &pd->stream_list, link) { 644bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (st->ep_num == ep_num) 645bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return st; 646bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 64786b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe return NULL; 648bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 6496e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6504e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 651bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 652bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 653bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num) 654bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 655bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_stream *st = 6561ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kzalloc(sizeof(struct oz_isoc_stream), GFP_ATOMIC); 657bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!st) 6581ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman return -ENOMEM; 659bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->ep_num = ep_num; 660bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 661bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!pd_stream_find(pd, ep_num)) { 662bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_add(&st->link, &pd->stream_list); 66386b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe st = NULL; 664bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 665bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 666b150718ecb6468d2de1ff593c402ec257dd80c8cSachin Kamat kfree(st); 667bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 668bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 6696e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6704e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 671bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 672bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 673bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_isoc_stream_free(struct oz_isoc_stream *st) 674bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 675dd3cef0f0715b79d29a4b0482117175f44b7d83cGreg Kroah-Hartman kfree_skb(st->skb); 6761ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(st); 677bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 6786e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6794e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 680bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 681bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 682bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num) 683bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 684bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_stream *st; 68518f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 686bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 687bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st = pd_stream_find(pd, ep_num); 688bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (st) 689bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_del(&st->link); 690bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 691bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (st) 692bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_isoc_stream_free(st); 693bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 694bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 6956e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 6964e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 697bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: any 698bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 699bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_isoc_destructor(struct sk_buff *skb) 700bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 701bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly atomic_dec(&g_submitted_isoc); 702bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 7036e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 7044e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 705bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 706bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 707dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Hueweint oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len) 708bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 709bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct net_device *dev = pd->net_dev; 710bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_stream *st; 711bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly u8 nb_units = 0; 71286b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct sk_buff *skb = NULL; 71386b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct oz_hdr *oz_hdr = NULL; 714bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int size = 0; 71518f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 716bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 717bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st = pd_stream_find(pd, ep_num); 718bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (st) { 719bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb = st->skb; 72086b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe st->skb = NULL; 721bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly nb_units = st->nb_units; 722bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->nb_units = 0; 723bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr = st->oz_hdr; 724bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly size = st->size; 725bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 726bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 727bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!st) 728bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 729bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!skb) { 730bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Allocate enough space for max size frame. */ 731ec0ee957f657b6200a2629d4c54df68d2c622e12Greg Kroah-Hartman skb = alloc_skb(pd->max_tx_size + OZ_ALLOCATED_SPACE(dev), 732ec0ee957f657b6200a2629d4c54df68d2c622e12Greg Kroah-Hartman GFP_ATOMIC); 73386b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (skb == NULL) 734bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 735bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Reserve the head room for lower layers. */ 736bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 737bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reset_network_header(skb); 738bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->dev = dev; 739bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 74086c948b4416b4c2c064d6c7e15476afbc04e2bf5Rupesh Gujare /* For audio packet set priority to AC_VO */ 74186c948b4416b4c2c064d6c7e15476afbc04e2bf5Rupesh Gujare skb->priority = 0x7; 742bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly size = sizeof(struct oz_hdr) + sizeof(struct oz_isoc_large); 743bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, size); 744bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 745bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(skb_put(skb, len), data, len); 746bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly size += len; 747bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (++nb_units < pd->ms_per_isoc) { 748bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 749bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->skb = skb; 750bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->nb_units = nb_units; 751bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->oz_hdr = oz_hdr; 752bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->size = size; 753bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 754bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } else { 755bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_hdr oz; 756bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_large iso; 757ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 758bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 759bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly iso.frame_number = st->frame_num; 760bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->frame_num += nb_units; 761bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 762bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz.control = 763bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC; 764bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; 765bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz.pkt_num = 0; 766bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly iso.endpoint = ep_num; 767bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly iso.format = OZ_DATA_F_ISOC_LARGE; 768bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly iso.ms_data = nb_units; 769bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(oz_hdr, &oz, sizeof(oz)); 770bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(oz_hdr+1, &iso, sizeof(iso)); 771bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 77233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare dev->dev_addr, skb->len) < 0) 77333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 77433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 77533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare skb->destructor = oz_isoc_destructor; 77633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare /*Queue for Xmit if mode is not ANYTIME*/ 77733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (!(pd->mode & OZ_F_ISOC_ANYTIME)) { 77833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare struct oz_tx_frame *isoc_unit = NULL; 77933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare int nb = pd->nb_queued_isoc_frames; 780ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 78186d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare if (nb >= pd->isoc_latency) { 7822dc2ee5ccdaf88b41bf9c025acf14ebdc2959a21Rupesh Gujare struct oz_tx_frame *f; 783ce6880e17508b31e04628a71d4691ef4a00a8b3fAdrian Nicoara 784f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Dropping ISOC Unit nb= %d\n", 785f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches nb); 7862dc2ee5ccdaf88b41bf9c025acf14ebdc2959a21Rupesh Gujare spin_lock(&pd->tx_frame_lock); 787a87c38090ea95d36925fefc5cb3d475416f3796cChristoph Jaeger list_for_each_entry(f, &pd->tx_queue, link) { 7882dc2ee5ccdaf88b41bf9c025acf14ebdc2959a21Rupesh Gujare if (f->skb != NULL) { 7892dc2ee5ccdaf88b41bf9c025acf14ebdc2959a21Rupesh Gujare oz_tx_isoc_free(pd, f); 7902dc2ee5ccdaf88b41bf9c025acf14ebdc2959a21Rupesh Gujare break; 7912dc2ee5ccdaf88b41bf9c025acf14ebdc2959a21Rupesh Gujare } 7922dc2ee5ccdaf88b41bf9c025acf14ebdc2959a21Rupesh Gujare } 7932dc2ee5ccdaf88b41bf9c025acf14ebdc2959a21Rupesh Gujare spin_unlock(&pd->tx_frame_lock); 79433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 79533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare isoc_unit = oz_tx_frame_alloc(pd); 79633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (isoc_unit == NULL) 79733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 79833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare isoc_unit->hdr = oz; 79933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare isoc_unit->skb = skb; 80033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare spin_lock_bh(&pd->tx_frame_lock); 80133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare list_add_tail(&isoc_unit->link, &pd->tx_queue); 80233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare pd->nb_queued_isoc_frames++; 80333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare spin_unlock_bh(&pd->tx_frame_lock); 804f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, 805f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches "Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n", 806f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->nb_queued_isoc_frames, pd->nb_queued_frames); 80733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return 0; 808bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 80933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 81033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare /*In ANYTIME mode Xmit unit immediately*/ 811bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (atomic_read(&g_submitted_isoc) < OZ_MAX_SUBMITTED_ISOC) { 812bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly atomic_inc(&g_submitted_isoc); 813255ece7c4d9e63e2a5e784247bc2e7b639cae4ddRupesh Gujare if (dev_queue_xmit(skb) < 0) 814bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 815d75b6c6154267618363f0126bd50c73f8d448a24Adrian Nicoara return 0; 816bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 81733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 818255ece7c4d9e63e2a5e784247bc2e7b639cae4ddRupesh Gujareout: kfree_skb(skb); 81933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return -1; 82033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 821bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 822bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 823bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 8246e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 8254e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 826bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: process 827bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 828bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_apps_init(void) 829bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 830bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int i; 83118f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 832a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger for (i = 0; i < OZ_NB_APPS; i++) { 833bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (g_app_if[i].init) 834bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly g_app_if[i].init(); 835a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger } 836bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 8376e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 8384e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 839bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: process 840bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 841bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_apps_term(void) 842bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 843bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int i; 84418f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 845bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Terminate all the apps. */ 846a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger for (i = 0; i < OZ_NB_APPS; i++) { 847bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (g_app_if[i].term) 848bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly g_app_if[i].term(); 849a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger } 850bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 8516e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 8524e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 853bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 854bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 855bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt) 856bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 857a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger if (app_id < OZ_NB_APPS && g_app_if[app_id].rx) 858a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger g_app_if[app_id].rx(pd, elt); 859bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 8606e244a8319ab80acdda424795e85687fb6af0be2Rupesh Gujare 8614e7fb829771de2cf8a5ba9576290d76936d3e814Rupesh Gujare/* 862bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 863bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 864bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_indicate_farewells(struct oz_pd *pd) 865bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 866bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_farewell *f; 867a9686e786896297f9f1d74a2cac4ffccc7b3e50eChristoph Jaeger const struct oz_app_if *ai = &g_app_if[OZ_APPID_USB]; 86818f8191e1f35d65221ad3b7c68c08fe1c09edb1dRupesh Gujare 869bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (1) { 8706b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_lock_bh(&g_polling_lock); 871bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (list_empty(&pd->farewell_list)) { 8726b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_unlock_bh(&g_polling_lock); 873bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 874bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 875bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f = list_first_entry(&pd->farewell_list, 876bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_farewell, link); 877bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_del(&f->link); 8786b029336d93d8f9a94b0256b1f7d9c1768eedba7Surendra Patil spin_unlock_bh(&g_polling_lock); 879bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (ai->farewell) 880bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ai->farewell(pd, f->ep_num, f->report, f->len); 8811ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(f); 882bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 883bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 884