ozpd.c revision f724b5843431aba591a01b6988a725689cd9ebb3
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 */ 6bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/init.h> 7bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/module.h> 8bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/timer.h> 9bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/sched.h> 10bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/netdevice.h> 11bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/errno.h> 12f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches#include "ozdbg.h" 13bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozconfig.h" 14bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozprotocol.h" 15bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozeltbuf.h" 16bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozpd.h" 17bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozproto.h" 18bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "oztrace.h" 19bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozcdev.h" 20bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include "ozusbsvc.h" 21bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <asm/unaligned.h> 22bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <linux/uaccess.h> 23bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#include <net/psnap.h> 24bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 25bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 26bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#define OZ_MAX_TX_POOL_SIZE 6 27bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 28bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 29bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd); 30bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f); 3133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujarestatic void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f); 32bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f); 33bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic int oz_send_isoc_frame(struct oz_pd *pd); 34bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f); 35bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_isoc_stream_free(struct oz_isoc_stream *st); 3633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujarestatic int oz_send_next_queued_frame(struct oz_pd *pd, int more_data); 37bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_isoc_destructor(struct sk_buff *skb); 38bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic int oz_def_app_init(void); 39bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_def_app_term(void); 40bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic int oz_def_app_start(struct oz_pd *pd, int resume); 41bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_def_app_stop(struct oz_pd *pd, int pause); 42bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_def_app_rx(struct oz_pd *pd, struct oz_elt *elt); 43bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 44bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Counts the uncompleted isoc frames submitted to netcard. 45bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 46bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic atomic_t g_submitted_isoc = ATOMIC_INIT(0); 47bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/* Application handler functions. 48bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 49dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewestatic const struct oz_app_if g_app_if[OZ_APPID_MAX] = { 50bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly {oz_usb_init, 51bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_usb_term, 52bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_usb_start, 53bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_usb_stop, 54bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_usb_rx, 55bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_usb_heartbeat, 56bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_usb_farewell, 57bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly OZ_APPID_USB}, 58bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly 59bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly {oz_def_app_init, 60bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_def_app_term, 61bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_def_app_start, 62bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_def_app_stop, 63bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_def_app_rx, 6486b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe NULL, 6586b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe NULL, 66bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly OZ_APPID_UNUSED1}, 67bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly 68bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly {oz_def_app_init, 69bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_def_app_term, 70bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_def_app_start, 71bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_def_app_stop, 72bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_def_app_rx, 7386b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe NULL, 7486b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe NULL, 75bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly OZ_APPID_UNUSED2}, 76bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly 77bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly {oz_cdev_init, 78bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_cdev_term, 79bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_cdev_start, 80bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_cdev_stop, 81bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_cdev_rx, 8286b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe NULL, 8386b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe NULL, 84bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly OZ_APPID_SERIAL}, 85bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly}; 86bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 87bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: process 88bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 89bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic int oz_def_app_init(void) 90bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 91bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 92bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 93bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 94bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: process 95bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 96bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_def_app_term(void) 97bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 98bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 99bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 100bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 101bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 102bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic int oz_def_app_start(struct oz_pd *pd, int resume) 103bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 104bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 105bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 106bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 107bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 108bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 109bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_def_app_stop(struct oz_pd *pd, int pause) 110bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 111bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 112bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 113bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 114bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 115bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_def_app_rx(struct oz_pd *pd, struct oz_elt *elt) 116bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 117bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 118bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 119bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 120bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 121bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_set_state(struct oz_pd *pd, unsigned state) 122bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 123bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->state = state; 124bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#ifdef WANT_TRACE 125bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly switch (state) { 126bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly case OZ_PD_S_IDLE: 127f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_IDLE\n"); 128bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 129bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly case OZ_PD_S_CONNECTED: 130f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_CONNECTED\n"); 131bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 132bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly case OZ_PD_S_STOPPED: 133f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_STOPPED\n"); 134bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 135bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly case OZ_PD_S_SLEEP: 136f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_SLEEP\n"); 137bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 138bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 139bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly#endif /* WANT_TRACE */ 140bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 141bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 142bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 143bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 144bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_get(struct oz_pd *pd) 145bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 146bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly atomic_inc(&pd->ref_count); 147bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 148bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 149bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 150bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 151bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_put(struct oz_pd *pd) 152bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 153bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (atomic_dec_and_test(&pd->ref_count)) 154bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_destroy(pd); 155bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 156bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 157bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 158bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 159dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewestruct oz_pd *oz_pd_alloc(const u8 *mac_addr) 160bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 1611ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman struct oz_pd *pd = kzalloc(sizeof(struct oz_pd), GFP_ATOMIC); 162bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd) { 163bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int i; 164bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly atomic_set(&pd->ref_count, 2); 165bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly for (i = 0; i < OZ_APPID_MAX; i++) 166bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_init(&pd->app_lock[i]); 167bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->last_rx_pkt_num = 0xffffffff; 168bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_set_state(pd, OZ_PD_S_IDLE); 169bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->max_tx_size = OZ_MAX_TX_SIZE; 170bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(pd->mac_addr, mac_addr, ETH_ALEN); 171bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (0 != oz_elt_buf_init(&pd->elt_buff)) { 1721ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(pd); 17386b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe pd = NULL; 174bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 175bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_init(&pd->tx_frame_lock); 176bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&pd->tx_queue); 177bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&pd->farewell_list); 178bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->last_sent_frame = &pd->tx_queue; 179bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_init(&pd->stream_lock); 180bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&pd->stream_list); 181bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 182bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return pd; 183bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 184bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 185bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 186bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 187bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_destroy(struct oz_pd *pd) 188bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 189bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct list_head *e; 190bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_tx_frame *f; 191bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_stream *st; 192bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_farewell *fwell; 193f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "Destroying PD\n"); 194bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Delete any streams. 195bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 196bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = pd->stream_list.next; 197bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (e != &pd->stream_list) { 198bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st = container_of(e, struct oz_isoc_stream, link); 199bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = e->next; 200bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_isoc_stream_free(st); 201bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 202bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Free any queued tx frames. 203bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 204bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = pd->tx_queue.next; 205bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (e != &pd->tx_queue) { 206bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f = container_of(e, struct oz_tx_frame, link); 207bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = e->next; 20833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (f->skb != NULL) 209dd3cef0f0715b79d29a4b0482117175f44b7d83cGreg Kroah-Hartman kfree_skb(f->skb); 210bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_retire_frame(pd, f); 211bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 212bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_elt_buf_term(&pd->elt_buff); 213bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Free any farewells. 214bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 215bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = pd->farewell_list.next; 216bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (e != &pd->farewell_list) { 217bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly fwell = container_of(e, struct oz_farewell, link); 218bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = e->next; 2191ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(fwell); 220bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 221bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Deallocate all frames in tx pool. 222bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 223bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (pd->tx_pool) { 224bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = pd->tx_pool; 225bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->tx_pool = e->next; 2261ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(container_of(e, struct oz_tx_frame, link)); 227bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 228bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->net_dev) 229bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly dev_put(pd->net_dev); 2301ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(pd); 231bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 232bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 233bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 234bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 235bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_services_start(struct oz_pd *pd, u16 apps, int resume) 236bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 237dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const struct oz_app_if *ai; 238bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int rc = 0; 239f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "%s: (0x%x) resume(%d)\n", __func__, apps, resume); 240bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) { 241bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (apps & (1<<ai->app_id)) { 242bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (ai->start(pd, resume)) { 243bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly rc = -1; 244f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, 245f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches "Unable to start service %d\n", 246f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches ai->app_id); 247bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 248bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 249bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_lock_bh(); 250bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->total_apps |= (1<<ai->app_id); 251bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (resume) 252bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->paused_apps &= ~(1<<ai->app_id); 253bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_unlock_bh(); 254bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 255bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 256bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return rc; 257bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 258bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 259bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 260bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 261bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_services_stop(struct oz_pd *pd, u16 apps, int pause) 262bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 263dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const struct oz_app_if *ai; 264f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_pd_dbg(pd, ON, "%s: (0x%x) pause(%d)\n", __func__, apps, pause); 265bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) { 266bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (apps & (1<<ai->app_id)) { 267bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_lock_bh(); 268bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pause) { 269bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->paused_apps |= (1<<ai->app_id); 270bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } else { 271bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->total_apps &= ~(1<<ai->app_id); 272bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->paused_apps &= ~(1<<ai->app_id); 273bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 274bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_unlock_bh(); 275bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ai->stop(pd, pause); 276bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 277bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 278bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 279bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 280bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 281bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 282bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_heartbeat(struct oz_pd *pd, u16 apps) 283bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 284dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const struct oz_app_if *ai; 285bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int more = 0; 286bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) { 287bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (ai->heartbeat && (apps & (1<<ai->app_id))) { 288bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (ai->heartbeat(pd)) 289bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly more = 1; 290bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 291bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 292bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (more) 293bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_request_heartbeat(pd); 294bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->mode & OZ_F_ISOC_ANYTIME) { 295bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int count = 8; 296bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (count-- && (oz_send_isoc_frame(pd) >= 0)) 297bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ; 298bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 299bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 300bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 301bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 302bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 303bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_stop(struct oz_pd *pd) 304bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 305bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly u16 stop_apps = 0; 306f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "oz_pd_stop() State = 0x%x\n", pd->state); 307bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_indicate_farewells(pd); 308bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_lock_bh(); 309bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly stop_apps = pd->total_apps; 310bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->total_apps = 0; 311bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->paused_apps = 0; 312bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_unlock_bh(); 313bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_services_stop(pd, stop_apps, 0); 314bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_lock_bh(); 315bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_set_state(pd, OZ_PD_S_STOPPED); 316bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Remove from PD list.*/ 317bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_del(&pd->link); 318bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_unlock_bh(); 319f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count)); 320bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_timer_delete(pd, 0); 321bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_put(pd); 322bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 323bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 324bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 325bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 326bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_pd_sleep(struct oz_pd *pd) 327bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 328bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int do_stop = 0; 329bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly u16 stop_apps = 0; 330bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_lock_bh(); 331bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) { 332bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_unlock_bh(); 333bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 334bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 335bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->keep_alive_j && pd->session_id) { 336bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_set_state(pd, OZ_PD_S_SLEEP); 337bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->pulse_time_j = jiffies + pd->keep_alive_j; 338f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Sleep Now %lu until %lu\n", 339f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches jiffies, pd->pulse_time_j); 340bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } else { 341bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly do_stop = 1; 342bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 343bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly stop_apps = pd->total_apps; 344bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_unlock_bh(); 345bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (do_stop) { 346bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_pd_stop(pd); 347bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } else { 348bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_services_stop(pd, stop_apps, 1); 349bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_timer_add(pd, OZ_TIMER_STOP, jiffies + pd->keep_alive_j, 1); 350bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 351bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return do_stop; 352bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 353bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 354bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 355bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 356bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd) 357bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 35886b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct oz_tx_frame *f = NULL; 359bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->tx_frame_lock); 360bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->tx_pool) { 361bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f = container_of(pd->tx_pool, struct oz_tx_frame, link); 362bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->tx_pool = pd->tx_pool->next; 363bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->tx_pool_count--; 364bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 365bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->tx_frame_lock); 36686b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (f == NULL) 3671ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman f = kmalloc(sizeof(struct oz_tx_frame), GFP_ATOMIC); 368bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (f) { 369bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f->total_size = sizeof(struct oz_hdr); 370bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&f->link); 371bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&f->elt_list); 372bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 373bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return f; 374bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 375bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 376bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 377bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 37833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujarestatic void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f) 37933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare{ 38033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare pd->nb_queued_isoc_frames--; 38133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare list_del_init(&f->link); 38233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (pd->tx_pool_count < OZ_MAX_TX_POOL_SIZE) { 38333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare f->link.next = pd->tx_pool; 38433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare pd->tx_pool = &f->link; 38533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare pd->tx_pool_count++; 38633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } else { 38733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare kfree(f); 38833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 389f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n", 390f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->nb_queued_isoc_frames); 39133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare} 39233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare/*------------------------------------------------------------------------------ 39333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare * Context: softirq or process 39433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare */ 395bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f) 396bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 397bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->tx_frame_lock); 398bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->tx_pool_count < OZ_MAX_TX_POOL_SIZE) { 399bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f->link.next = pd->tx_pool; 400bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->tx_pool = &f->link; 401bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->tx_pool_count++; 40286b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe f = NULL; 403bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 404bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->tx_frame_lock); 405b150718ecb6468d2de1ff593c402ec257dd80c8cSachin Kamat kfree(f); 406bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 407bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 40833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare * Context: softirq-serialized 40933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare */ 410a7f74c3005cf6830a20d71c4e1d8d6d77443e5cbPeter Huewestatic void oz_set_more_bit(struct sk_buff *skb) 41133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare{ 41233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); 41333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_hdr->control |= OZ_F_MORE_DATA; 41433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare} 41533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare/*------------------------------------------------------------------------------ 41600ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare * Context: softirq-serialized 41700ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare */ 418a7f74c3005cf6830a20d71c4e1d8d6d77443e5cbPeter Huewestatic void oz_set_last_pkt_nb(struct oz_pd *pd, struct sk_buff *skb) 41900ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare{ 42000ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); 42100ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; 42200ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare} 42300ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare/*------------------------------------------------------------------------------ 424bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 425bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 426bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_prepare_frame(struct oz_pd *pd, int empty) 427bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 428bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_tx_frame *f; 429bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if ((pd->mode & OZ_MODE_MASK) != OZ_MODE_TRIGGERED) 430bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 431bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->nb_queued_frames >= OZ_MAX_QUEUED_FRAMES) 432bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 433bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!empty && !oz_are_elts_available(&pd->elt_buff)) 434bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 435bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f = oz_tx_frame_alloc(pd); 43686b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (f == NULL) 437bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 43833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare f->skb = NULL; 439bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f->hdr.control = 440bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ACK_REQUESTED; 441bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ++pd->last_tx_pkt_num; 442bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly put_unaligned(cpu_to_le32(pd->last_tx_pkt_num), &f->hdr.pkt_num); 443bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (empty == 0) { 444bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_select_elts_for_tx(&pd->elt_buff, 0, &f->total_size, 445bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->max_tx_size, &f->elt_list); 446bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 447bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock(&pd->tx_frame_lock); 448bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_add_tail(&f->link, &pd->tx_queue); 449bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->nb_queued_frames++; 450bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock(&pd->tx_frame_lock); 451bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 452bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 453bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 454bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 455bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 456bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f) 457bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 45886b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct sk_buff *skb; 459bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct net_device *dev = pd->net_dev; 460bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_hdr *oz_hdr; 461bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_elt *elt; 462bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct list_head *e; 463bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Allocate skb with enough space for the lower layers as well 464bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * as the space we need. 465bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 466ec0ee957f657b6200a2629d4c54df68d2c622e12Greg Kroah-Hartman skb = alloc_skb(f->total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); 46786b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (skb == NULL) 46886b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe return NULL; 469bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Reserve the head room for lower layers. 470bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 471bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 472bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reset_network_header(skb); 473bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->dev = dev; 474bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 475bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 476bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly dev->dev_addr, skb->len) < 0) 477bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly goto fail; 478bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Push the tail to the end of the area we are going to copy to. 479bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 480bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, f->total_size); 481bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f->hdr.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; 482bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(oz_hdr, &f->hdr, sizeof(struct oz_hdr)); 483bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Copy the elements into the frame body. 484bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 485bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly elt = (struct oz_elt *)(oz_hdr+1); 486bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly for (e = f->elt_list.next; e != &f->elt_list; e = e->next) { 487bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_elt_info *ei; 488bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ei = container_of(e, struct oz_elt_info, link); 489bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(elt, ei->data, ei->length); 490bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly elt = oz_next_elt(elt); 491bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 492bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return skb; 493bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyfail: 494dd3cef0f0715b79d29a4b0482117175f44b7d83cGreg Kroah-Hartman kfree_skb(skb); 49586b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe return NULL; 496bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 497bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 498bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 499bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 500bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f) 501bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 502bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct list_head *e; 503bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_elt_info *ei; 504bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = f->elt_list.next; 505bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (e != &f->elt_list) { 506bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ei = container_of(e, struct oz_elt_info, link); 507bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = e->next; 508bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_del_init(&ei->link); 509bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (ei->callback) 510bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ei->callback(pd, ei->context); 511bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->elt_buff.lock); 512bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_elt_info_free(&pd->elt_buff, ei); 513bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->elt_buff.lock); 514bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 515bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_tx_frame_free(pd, f); 516bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (pd->elt_buff.free_elts > pd->elt_buff.max_free_elts) 517bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_trim_elt_pool(&pd->elt_buff); 518bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 519bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 520bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 521bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 52233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujarestatic int oz_send_next_queued_frame(struct oz_pd *pd, int more_data) 523bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 524bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct sk_buff *skb; 525bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_tx_frame *f; 526bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct list_head *e; 527bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock(&pd->tx_frame_lock); 528bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = pd->last_sent_frame->next; 529bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (e == &pd->tx_queue) { 530bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock(&pd->tx_frame_lock); 531bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 532bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 533bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f = container_of(e, struct oz_tx_frame, link); 53433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 53533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (f->skb != NULL) { 53633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare skb = f->skb; 53733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_tx_isoc_free(pd, f); 53833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare spin_unlock(&pd->tx_frame_lock); 53933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (more_data) 54033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_set_more_bit(skb); 54100ec12b827d2f99202e0c9d804514aef2febf8d6Rupesh Gujare oz_set_last_pkt_nb(pd, skb); 54233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if ((int)atomic_read(&g_submitted_isoc) < 54333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare OZ_MAX_SUBMITTED_ISOC) { 54433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (dev_queue_xmit(skb) < 0) { 545f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Dropping ISOC Frame\n"); 54633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return -1; 54733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 54833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare atomic_inc(&g_submitted_isoc); 549f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Sending ISOC Frame, nb_isoc= %d\n", 550f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->nb_queued_isoc_frames); 55133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return 0; 55233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } else { 553dd3cef0f0715b79d29a4b0482117175f44b7d83cGreg Kroah-Hartman kfree_skb(skb); 554f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Dropping ISOC Frame>\n"); 55533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return -1; 55633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 55733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 55833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 55933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare pd->last_sent_frame = e; 560bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb = oz_build_frame(pd, f); 561bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock(&pd->tx_frame_lock); 56233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (more_data) 56333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_set_more_bit(skb); 564f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num); 565bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (skb) { 566bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (dev_queue_xmit(skb) < 0) 567bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 56833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 569bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 570bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 571bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 572bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 573bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 574bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 575bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_send_queued_frames(struct oz_pd *pd, int backlog) 576bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 57733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare while (oz_prepare_frame(pd, 0) >= 0) 57833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare backlog++; 57933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 58033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare switch (pd->mode & (OZ_F_ISOC_NO_ELTS | OZ_F_ISOC_ANYTIME)) { 58133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 58233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare case OZ_F_ISOC_NO_ELTS: { 58333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare backlog += pd->nb_queued_isoc_frames; 58433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (backlog <= 0) 58533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 58633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (backlog > OZ_MAX_SUBMITTED_ISOC) 58733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare backlog = OZ_MAX_SUBMITTED_ISOC; 58833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare break; 589bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 59033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare case OZ_NO_ELTS_ANYTIME: { 59133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if ((backlog <= 0) && (pd->isoc_sent == 0)) 59233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 59333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare break; 59433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 59533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare default: { 59633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (backlog <= 0) 59733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 59833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare break; 59933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 60033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 60133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare while (backlog--) { 60233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (oz_send_next_queued_frame(pd, backlog) < 0) 60333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare break; 604bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 60533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return; 60633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 60733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujareout: oz_prepare_frame(pd, 1); 60833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare oz_send_next_queued_frame(pd, 0); 609bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 610bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 611bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 612bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 613bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic int oz_send_isoc_frame(struct oz_pd *pd) 614bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 61586b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct sk_buff *skb; 616bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct net_device *dev = pd->net_dev; 617bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_hdr *oz_hdr; 618bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_elt *elt; 619bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct list_head *e; 620bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct list_head list; 621bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int total_size = sizeof(struct oz_hdr); 622bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly INIT_LIST_HEAD(&list); 623bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly 624bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_select_elts_for_tx(&pd->elt_buff, 1, &total_size, 625bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->max_tx_size, &list); 626bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (list.next == &list) 627bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 628ec0ee957f657b6200a2629d4c54df68d2c622e12Greg Kroah-Hartman skb = alloc_skb(total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); 62986b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (skb == NULL) { 630f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(ON, "Cannot alloc skb\n"); 631bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_elt_info_free_chain(&pd->elt_buff, &list); 632bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 633bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 634bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 635bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reset_network_header(skb); 636bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->dev = dev; 637bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 638bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 639bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly dev->dev_addr, skb->len) < 0) { 640dd3cef0f0715b79d29a4b0482117175f44b7d83cGreg Kroah-Hartman kfree_skb(skb); 641bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 642bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 643bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, total_size); 644bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC; 645bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; 646bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly elt = (struct oz_elt *)(oz_hdr+1); 647bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly 648bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly for (e = list.next; e != &list; e = e->next) { 649bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_elt_info *ei; 650bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ei = container_of(e, struct oz_elt_info, link); 651bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(elt, ei->data, ei->length); 652bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly elt = oz_next_elt(elt); 653bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 654bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly dev_queue_xmit(skb); 655bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_elt_info_free_chain(&pd->elt_buff, &list); 656bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 657bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 658bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 659bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 660bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 661bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_retire_tx_frames(struct oz_pd *pd, u8 lpn) 662bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 663bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct list_head *e; 664bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_tx_frame *f; 66586b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct list_head *first = NULL; 66686b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct list_head *last = NULL; 667bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly u8 diff; 668bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly u32 pkt_num; 669bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly 670bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock(&pd->tx_frame_lock); 671bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = pd->tx_queue.next; 672bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (e != &pd->tx_queue) { 673bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f = container_of(e, struct oz_tx_frame, link); 674bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pkt_num = le32_to_cpu(get_unaligned(&f->hdr.pkt_num)); 675bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly diff = (lpn - (pkt_num & OZ_LAST_PN_MASK)) & OZ_LAST_PN_MASK; 67633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0)) 677bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 678f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n", 679f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pkt_num, pd->nb_queued_frames); 68086b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (first == NULL) 681bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly first = e; 682bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly last = e; 683bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly e = e->next; 684bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->nb_queued_frames--; 685bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 686bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (first) { 687bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly last->next->prev = &pd->tx_queue; 688bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->tx_queue.next = last->next; 68986b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe last->next = NULL; 690bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 691bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly pd->last_sent_frame = &pd->tx_queue; 692bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock(&pd->tx_frame_lock); 693bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (first) { 694bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f = container_of(first, struct oz_tx_frame, link); 695bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly first = first->next; 696bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_retire_frame(pd, f); 697bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 698bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 699bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 700bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Precondition: stream_lock must be held. 701bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 702bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 703bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic struct oz_isoc_stream *pd_stream_find(struct oz_pd *pd, u8 ep_num) 704bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 705bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct list_head *e; 706bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_stream *st; 707bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_for_each(e, &pd->stream_list) { 708bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st = container_of(e, struct oz_isoc_stream, link); 709bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (st->ep_num == ep_num) 710bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return st; 711bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 71286b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe return NULL; 713bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 714bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 715bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 716bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 717bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num) 718bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 719bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_stream *st = 7201ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kzalloc(sizeof(struct oz_isoc_stream), GFP_ATOMIC); 721bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!st) 7221ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman return -ENOMEM; 723bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->ep_num = ep_num; 724bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 725bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!pd_stream_find(pd, ep_num)) { 726bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_add(&st->link, &pd->stream_list); 72786b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe st = NULL; 728bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 729bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 730b150718ecb6468d2de1ff593c402ec257dd80c8cSachin Kamat kfree(st); 731bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 732bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 733bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 734bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 735bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 736bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_isoc_stream_free(struct oz_isoc_stream *st) 737bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 738dd3cef0f0715b79d29a4b0482117175f44b7d83cGreg Kroah-Hartman kfree_skb(st->skb); 7391ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(st); 740bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 741bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 742bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 743bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 744bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyint oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num) 745bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 746bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_stream *st; 747bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 748bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st = pd_stream_find(pd, ep_num); 749bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (st) 750bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_del(&st->link); 751bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 752bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (st) 753bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_isoc_stream_free(st); 754bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 755bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 756bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 757bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: any 758bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 759bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellystatic void oz_isoc_destructor(struct sk_buff *skb) 760bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 761bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly atomic_dec(&g_submitted_isoc); 762bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 763bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 764bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq 765bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 766dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Hueweint oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len) 767bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 768bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct net_device *dev = pd->net_dev; 769bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_stream *st; 770bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly u8 nb_units = 0; 77186b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct sk_buff *skb = NULL; 77286b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe struct oz_hdr *oz_hdr = NULL; 773bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int size = 0; 774bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 775bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st = pd_stream_find(pd, ep_num); 776bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (st) { 777bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb = st->skb; 77886b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe st->skb = NULL; 779bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly nb_units = st->nb_units; 780bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->nb_units = 0; 781bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr = st->oz_hdr; 782bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly size = st->size; 783bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 784bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 785bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!st) 786bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 787bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (!skb) { 788bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Allocate enough space for max size frame. */ 789ec0ee957f657b6200a2629d4c54df68d2c622e12Greg Kroah-Hartman skb = alloc_skb(pd->max_tx_size + OZ_ALLOCATED_SPACE(dev), 790ec0ee957f657b6200a2629d4c54df68d2c622e12Greg Kroah-Hartman GFP_ATOMIC); 79186b02be043c42e1d7450be025177e3e248a2e8c1Peter Huewe if (skb == NULL) 792bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 793bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Reserve the head room for lower layers. */ 794bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reserve(skb, LL_RESERVED_SPACE(dev)); 795bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb_reset_network_header(skb); 796bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->dev = dev; 797bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly skb->protocol = htons(OZ_ETHERTYPE); 79886c948b4416b4c2c064d6c7e15476afbc04e2bf5Rupesh Gujare /* For audio packet set priority to AC_VO */ 79986c948b4416b4c2c064d6c7e15476afbc04e2bf5Rupesh Gujare skb->priority = 0x7; 800bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly size = sizeof(struct oz_hdr) + sizeof(struct oz_isoc_large); 801bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_hdr = (struct oz_hdr *)skb_put(skb, size); 802bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 803bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(skb_put(skb, len), data, len); 804bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly size += len; 805bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (++nb_units < pd->ms_per_isoc) { 806bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 807bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->skb = skb; 808bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->nb_units = nb_units; 809bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->oz_hdr = oz_hdr; 810bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->size = size; 811bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 812bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } else { 813bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_hdr oz; 814bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_isoc_large iso; 815bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_lock_bh(&pd->stream_lock); 816bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly iso.frame_number = st->frame_num; 817bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly st->frame_num += nb_units; 818bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly spin_unlock_bh(&pd->stream_lock); 819bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz.control = 820bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC; 821bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; 822bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz.pkt_num = 0; 823bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly iso.endpoint = ep_num; 824bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly iso.format = OZ_DATA_F_ISOC_LARGE; 825bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly iso.ms_data = nb_units; 826bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(oz_hdr, &oz, sizeof(oz)); 827bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly memcpy(oz_hdr+1, &iso, sizeof(iso)); 828bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, 82933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare dev->dev_addr, skb->len) < 0) 83033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 83133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 83233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare skb->destructor = oz_isoc_destructor; 83333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare /*Queue for Xmit if mode is not ANYTIME*/ 83433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (!(pd->mode & OZ_F_ISOC_ANYTIME)) { 83533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare struct oz_tx_frame *isoc_unit = NULL; 83633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare int nb = pd->nb_queued_isoc_frames; 83786d03a0f4f575dda7988800a3da8d6e9f776a819Rupesh Gujare if (nb >= pd->isoc_latency) { 838f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, "Dropping ISOC Unit nb= %d\n", 839f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches nb); 84033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 84133e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare } 84233e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare isoc_unit = oz_tx_frame_alloc(pd); 84333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare if (isoc_unit == NULL) 84433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare goto out; 84533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare isoc_unit->hdr = oz; 84633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare isoc_unit->skb = skb; 84733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare spin_lock_bh(&pd->tx_frame_lock); 84833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare list_add_tail(&isoc_unit->link, &pd->tx_queue); 84933e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare pd->nb_queued_isoc_frames++; 85033e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare spin_unlock_bh(&pd->tx_frame_lock); 851f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches oz_dbg(TX_FRAMES, 852f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches "Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n", 853f724b5843431aba591a01b6988a725689cd9ebb3Joe Perches pd->nb_queued_isoc_frames, pd->nb_queued_frames); 85433e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return 0; 855bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 85633e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 85733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare /*In ANYTIME mode Xmit unit immediately*/ 858bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (atomic_read(&g_submitted_isoc) < OZ_MAX_SUBMITTED_ISOC) { 859bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly atomic_inc(&g_submitted_isoc); 860255ece7c4d9e63e2a5e784247bc2e7b639cae4ddRupesh Gujare if (dev_queue_xmit(skb) < 0) 861bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return -1; 862255ece7c4d9e63e2a5e784247bc2e7b639cae4ddRupesh Gujare else 86333e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return 0; 864bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 86533e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 866255ece7c4d9e63e2a5e784247bc2e7b639cae4ddRupesh Gujareout: kfree_skb(skb); 86733e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare return -1; 86833e6ada17fffc54c24607d5acb279363b30ac401Rupesh Gujare 869bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 870bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return 0; 871bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 872bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 873bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: process 874bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 875bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_apps_init(void) 876bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 877bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int i; 878bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly for (i = 0; i < OZ_APPID_MAX; i++) 879bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (g_app_if[i].init) 880bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly g_app_if[i].init(); 881bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 882bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 883bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: process 884bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 885bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_apps_term(void) 886bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 887bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly int i; 888bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly /* Terminate all the apps. */ 889bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly for (i = 0; i < OZ_APPID_MAX; i++) 890bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (g_app_if[i].term) 891bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly g_app_if[i].term(); 892bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 893bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 894bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq-serialized 895bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 896bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt) 897bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 898dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const struct oz_app_if *ai; 89992a6253299d74833a36edb94d5a4bc541418b17aDan Carpenter if (app_id == 0 || app_id > OZ_APPID_MAX) 900bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly return; 901bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ai = &g_app_if[app_id-1]; 902bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ai->rx(pd, elt); 903bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 904bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly/*------------------------------------------------------------------------------ 905bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly * Context: softirq or process 906bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly */ 907bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kellyvoid oz_pd_indicate_farewells(struct oz_pd *pd) 908bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly{ 909bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_farewell *f; 910dc7f5b3594fdb846890192fd75793a791d7ba83bPeter Huewe const struct oz_app_if *ai = &g_app_if[OZ_APPID_USB-1]; 911bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly while (1) { 912bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_lock_bh(); 913bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (list_empty(&pd->farewell_list)) { 914bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_unlock_bh(); 915bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly break; 916bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 917bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly f = list_first_entry(&pd->farewell_list, 918bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly struct oz_farewell, link); 919bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly list_del(&f->link); 920bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly oz_polling_unlock_bh(); 921bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly if (ai->farewell) 922bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly ai->farewell(pd, f->ep_num, f->report, f->len); 9231ec41a31fb695682cab7fc7c1f6ced84d188b6f9Greg Kroah-Hartman kfree(f); 924bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly } 925bc3157dde35ac3b2ec12229edcfaca58cd7925c0Chris Kelly} 926