Commit 8fd07007 authored by Rupesh Gujare's avatar Rupesh Gujare Committed by Greg Kroah-Hartman

staging: ozwpan: High resolution timers

Current implementation assumes HZ = 1000 for calculating
all internal timer intervals, which creates problem on
platforms where HZ != 1000.

As well we need resolution of less than 10 mSec for heartbeat
calculation, this creates problem on some platforms where HZ is
configured as HZ = 100, or around, which restricts us to timer interval
of 10 mSec. This is particularly found on embedded devices.

This patch moves on to use high resolution timers to calculate
all timer intervals as it allows us to have very small resolution
of timer interval, removing dependency on HZ.
Signed-off-by: default avatarRupesh Gujare <rupesh.gujare@atmel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 70bcbc06
This diff is collapsed.
......@@ -176,6 +176,14 @@ struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
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;
}
......@@ -189,6 +197,13 @@ void oz_pd_destroy(struct oz_pd *pd)
struct oz_isoc_stream *st;
struct oz_farewell *fwell;
oz_pd_dbg(pd, ON, "Destroying PD\n");
if (hrtimer_active(&pd->timeout))
hrtimer_cancel(&pd->timeout);
if (hrtimer_active(&pd->heartbeat))
hrtimer_cancel(&pd->heartbeat);
/*Disable timer tasklets*/
tasklet_kill(&pd->heartbeat_tasklet);
tasklet_kill(&pd->timeout_tasklet);
/* Delete any streams.
*/
e = pd->stream_list.next;
......@@ -287,8 +302,8 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
more = 1;
}
}
if (more)
oz_pd_request_heartbeat(pd);
if ((!more) && (hrtimer_active(&pd->heartbeat)))
hrtimer_cancel(&pd->heartbeat);
if (pd->mode & OZ_F_ISOC_ANYTIME) {
int count = 8;
while (count-- && (oz_send_isoc_frame(pd) >= 0))
......@@ -315,7 +330,6 @@ void oz_pd_stop(struct oz_pd *pd)
list_del(&pd->link);
oz_polling_unlock_bh();
oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count));
oz_timer_delete(pd, 0);
oz_pd_put(pd);
}
/*------------------------------------------------------------------------------
......@@ -330,21 +344,18 @@ int oz_pd_sleep(struct oz_pd *pd)
oz_polling_unlock_bh();
return 0;
}
if (pd->keep_alive_j && pd->session_id) {
if (pd->keep_alive && pd->session_id)
oz_pd_set_state(pd, OZ_PD_S_SLEEP);
pd->pulse_time_j = jiffies + pd->keep_alive_j;
oz_dbg(ON, "Sleep Now %lu until %lu\n",
jiffies, pd->pulse_time_j);
} else {
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);
oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive);
}
return do_stop;
}
......
......@@ -6,6 +6,7 @@
#ifndef _OZPD_H_
#define _OZPD_H_
#include <linux/interrupt.h>
#include "ozeltbuf.h"
/* PD state
......@@ -68,18 +69,16 @@ struct oz_pd {
u8 isoc_sent;
u32 last_rx_pkt_num;
u32 last_tx_pkt_num;
struct timespec last_rx_timestamp;
u32 trigger_pkt_num;
unsigned long pulse_time_j;
unsigned long timeout_time_j;
unsigned long pulse_period_j;
unsigned long presleep_j;
unsigned long keep_alive_j;
unsigned long last_rx_time_j;
unsigned long pulse_time;
unsigned long pulse_period;
unsigned long presleep;
unsigned long keep_alive;
struct oz_elt_buf elt_buff;
void *app_ctx[OZ_APPID_MAX];
spinlock_t app_lock[OZ_APPID_MAX];
int max_tx_size;
u8 heartbeat_requested;
u8 mode;
u8 ms_per_isoc;
unsigned isoc_latency;
......@@ -95,6 +94,11 @@ struct oz_pd {
spinlock_t stream_lock;
struct list_head stream_list;
struct net_device *net_dev;
struct hrtimer heartbeat;
struct hrtimer timeout;
u8 timeout_type;
struct tasklet_struct heartbeat_tasklet;
struct tasklet_struct timeout_tasklet;
};
#define OZ_MAX_QUEUED_FRAMES 4
......
This diff is collapsed.
......@@ -12,20 +12,11 @@
#define OZ_ALLOCATED_SPACE(__x) (LL_RESERVED_SPACE(__x)+(__x)->needed_tailroom)
/* Converts millisecs to jiffies.
*/
#define oz_ms_to_jiffies(__x) msecs_to_jiffies(__x)
/* Quantum milliseconds.
*/
#define OZ_QUANTUM_MS 8
/* Quantum jiffies
*/
#define OZ_QUANTUM_J (oz_ms_to_jiffies(OZ_QUANTUM_MS))
/* Quantum in MS */
#define OZ_QUANTUM 8
/* Default timeouts.
*/
#define OZ_CONNECTION_TOUT_J (2*HZ)
#define OZ_PRESLEEP_TOUT_J (11*HZ)
#define OZ_PRESLEEP_TOUT 11
/* Maximun sizes of tx frames. */
#define OZ_MAX_TX_SIZE 1514
......@@ -65,11 +56,16 @@ void oz_app_enable(int app_id, int enable);
struct oz_pd *oz_pd_find(const u8 *mac_addr);
void oz_binding_add(char *net_dev);
void oz_binding_remove(char *net_dev);
void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time,
int remove);
void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time);
void oz_timer_delete(struct oz_pd *pd, int type);
void oz_pd_request_heartbeat(struct oz_pd *pd);
void oz_polling_lock_bh(void);
void oz_polling_unlock_bh(void);
void oz_pd_heartbeat_handler(unsigned long data);
void oz_pd_timeout_handler(unsigned long data);
enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer);
enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer);
int oz_get_pd_status_list(char *pd_list, int max_count);
int oz_get_binding_list(char *buf, int max_if);
#endif /* _OZPROTO_H */
......@@ -24,7 +24,7 @@ void oz_remember_urb(struct urb *urb)
spin_lock_irqsave(&g_urb_mem_lock, irq_state);
if (g_nb_urbs < OZ_MAX_URBS) {
g_urb_memory[g_nb_urbs++] = urb;
oz_dbg(ON, "%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb);
oz_dbg(ON, "urb up = %d %p\n", g_nb_urbs, urb);
} else {
oz_dbg(ON, "ERROR urb buffer full\n");
}
......@@ -44,8 +44,7 @@ int oz_forget_urb(struct urb *urb)
if (--g_nb_urbs > i)
memcpy(&g_urb_memory[i], &g_urb_memory[i+1],
(g_nb_urbs - i) * sizeof(struct urb *));
oz_dbg(ON, "%lu: urb down = %d %p\n",
jiffies, g_nb_urbs, urb);
oz_dbg(ON, "urb down = %d %p\n", g_nb_urbs, urb);
}
}
spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
......
......@@ -123,7 +123,8 @@ void oz_usb_stop(struct oz_pd *pd, int pause)
pd->app_ctx[OZ_APPID_USB-1] = NULL;
spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
if (usb_ctx) {
unsigned long tout = jiffies + HZ;
struct timespec ts, now;
getnstimeofday(&ts);
oz_dbg(ON, "USB service stopping...\n");
usb_ctx->stopped = 1;
/* At this point the reference count on the usb context should
......@@ -132,9 +133,12 @@ void oz_usb_stop(struct oz_pd *pd, int pause)
* should get in but someone may already be in. So wait
* until they leave but timeout after 1 second.
*/
while ((atomic_read(&usb_ctx->ref_count) > 2) &&
time_before(jiffies, tout))
;
while ((atomic_read(&usb_ctx->ref_count) > 2)) {
getnstimeofday(&now);
/*Approx 1 Sec. this is not perfect calculation*/
if (now.tv_sec != ts.tv_sec)
break;
}
oz_dbg(ON, "USB service stopped\n");
oz_hcd_pd_departed(usb_ctx->hport);
/* Release the reference taken in oz_usb_start.
......@@ -155,7 +159,7 @@ void oz_usb_get(void *hpd)
/*------------------------------------------------------------------------------
* This decrements the reference count of the context area for a specific PD
* and destroys the context area if the reference count becomes zero.
* Context: softirq or process
* Context: irq or process
*/
void oz_usb_put(void *hpd)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment