/*------------------------------------------------------------------------------ * Context: softirq-serialized */ struct oz_pd *oz_pd_alloc(u8 *mac_addr) { struct oz_pd *pd = kzalloc(sizeof(struct oz_pd), GFP_ATOMIC); if (pd) { int i; atomic_set(&pd->ref_count, 2); for (i = 0; i < OZ_APPID_MAX; i++) spin_lock_init(&pd->app_lock[i]); pd->last_rx_pkt_num = 0xffffffff; oz_pd_set_state(pd, OZ_PD_S_IDLE); pd->max_tx_size = OZ_MAX_TX_SIZE; memcpy(pd->mac_addr, mac_addr, ETH_ALEN); if (0 != oz_elt_buf_init(&pd->elt_buff)) { kfree(pd); pd = 0; } spin_lock_init(&pd->tx_frame_lock); INIT_LIST_HEAD(&pd->tx_queue); INIT_LIST_HEAD(&pd->farewell_list); pd->last_sent_frame = &pd->tx_queue; spin_lock_init(&pd->stream_lock); INIT_LIST_HEAD(&pd->stream_list); } return pd; }
/*------------------------------------------------------------------------------ * Context: softirq */ int oz_pd_sleep(struct oz_pd *pd) { int do_stop = 0; u16 stop_apps = 0; oz_polling_lock_bh(); if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) { oz_polling_unlock_bh(); return 0; } if (pd->keep_alive_j && pd->session_id) { oz_pd_set_state(pd, OZ_PD_S_SLEEP); pd->pulse_time_j = jiffies + pd->keep_alive_j; oz_trace("Sleep Now %lu until %lu\n", jiffies, pd->pulse_time_j); } else { do_stop = 1; } stop_apps = pd->total_apps; oz_polling_unlock_bh(); if (do_stop) { oz_pd_stop(pd); } else { oz_services_stop(pd, stop_apps, 1); oz_timer_add(pd, OZ_TIMER_STOP, jiffies + pd->keep_alive_j, 1); } return do_stop; }
/* * Context: softirq */ int oz_pd_sleep(struct oz_pd *pd) { int do_stop = 0; u16 stop_apps; oz_polling_lock_bh(); if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) { oz_polling_unlock_bh(); return 0; } if (pd->keep_alive && pd->session_id) oz_pd_set_state(pd, OZ_PD_S_SLEEP); else do_stop = 1; stop_apps = pd->total_apps; oz_polling_unlock_bh(); if (do_stop) { oz_pd_stop(pd); } else { oz_services_stop(pd, stop_apps, 1); oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive); } return do_stop; }
/* * Context: softirq-serialized */ struct oz_pd *oz_pd_alloc(const u8 *mac_addr) { struct oz_pd *pd = kzalloc(sizeof(struct oz_pd), GFP_ATOMIC); if (pd) { int i; atomic_set(&pd->ref_count, 2); for (i = 0; i < OZ_APPID_MAX; i++) spin_lock_init(&pd->app_lock[i]); pd->last_rx_pkt_num = 0xffffffff; oz_pd_set_state(pd, OZ_PD_S_IDLE); pd->max_tx_size = OZ_MAX_TX_SIZE; memcpy(pd->mac_addr, mac_addr, ETH_ALEN); if (0 != oz_elt_buf_init(&pd->elt_buff)) { kfree(pd); pd = NULL; } spin_lock_init(&pd->tx_frame_lock); INIT_LIST_HEAD(&pd->tx_queue); INIT_LIST_HEAD(&pd->farewell_list); pd->last_sent_frame = &pd->tx_queue; spin_lock_init(&pd->stream_lock); INIT_LIST_HEAD(&pd->stream_list); tasklet_init(&pd->heartbeat_tasklet, oz_pd_heartbeat_handler, (unsigned long)pd); tasklet_init(&pd->timeout_tasklet, oz_pd_timeout_handler, (unsigned long)pd); hrtimer_init(&pd->heartbeat, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pd->heartbeat.function = oz_pd_heartbeat_event; pd->timeout.function = oz_pd_timeout_event; } return pd; }
/*------------------------------------------------------------------------------ * Context: softirq */ int oz_pd_sleep(struct oz_pd *pd) { int do_stop = 0; u16 stop_apps = 0; oz_polling_lock_bh(); if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) { oz_polling_unlock_bh(); return 0; } if (pd->keep_alive && pd->session_id) { if (pd->keep_alive >= OZ_KALIVE_INFINITE) oz_pd_indicate_farewells(pd); oz_pd_set_state(pd, OZ_PD_S_SLEEP); oz_pd_notify_uevent(pd); } else { do_stop = 1; } stop_apps = pd->total_apps; oz_polling_unlock_bh(); if (do_stop) { oz_pd_stop(pd); } else { oz_services_stop(pd, stop_apps, 1); oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive); } return do_stop; }
/*------------------------------------------------------------------------------ * Context: softirq or process */ void oz_pd_stop(struct oz_pd *pd) { u16 stop_apps = 0; oz_trace_msg(M, "oz_pd_stop() State = 0x%x\n", pd->state); oz_polling_lock_bh(); oz_pd_indicate_farewells(pd); stop_apps = pd->total_apps; pd->total_apps = 0; pd->paused_apps = 0; oz_polling_unlock_bh(); oz_services_stop(pd, stop_apps, 0); oz_polling_lock_bh(); oz_pd_set_state(pd, OZ_PD_S_STOPPED); if (hrtimer_active(&pd->timeout)) { oz_trace_msg(M, "hrtimer timeout active\n"); hrtimer_cancel(&pd->timeout); } if (hrtimer_active(&pd->heartbeat)) { oz_trace_msg(M, "hrtimer heartbeat active\n"); hrtimer_cancel(&pd->heartbeat); } /* connect_req will restart timers */ /* Remove from PD list.*/ list_del(&pd->link); oz_polling_unlock_bh(); oz_trace_msg(M, "pd ref count = %d\n", atomic_read(&pd->ref_count)); oz_pd_put(pd); }
/*------------------------------------------------------------------------------ * Context: softirq or process */ void oz_pd_stop(struct oz_pd *pd) { u16 stop_apps = 0; oz_trace("oz_pd_stop() State = 0x%x\n", pd->state); oz_pd_indicate_farewells(pd); oz_polling_lock_bh(); stop_apps = pd->total_apps; pd->total_apps = 0; pd->paused_apps = 0; oz_polling_unlock_bh(); oz_services_stop(pd, stop_apps, 0); oz_polling_lock_bh(); oz_pd_set_state(pd, OZ_PD_S_STOPPED); /* Remove from PD list.*/ list_del(&pd->link); oz_polling_unlock_bh(); oz_trace("pd ref count = %d\n", atomic_read(&pd->ref_count)); oz_timer_delete(pd, 0); oz_pd_put(pd); }