summaryrefslogtreecommitdiff
path: root/xpp/xbus-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/xbus-core.c')
-rw-r--r--xpp/xbus-core.c180
1 files changed, 154 insertions, 26 deletions
diff --git a/xpp/xbus-core.c b/xpp/xbus-core.c
index 3c057da..cbec226 100644
--- a/xpp/xbus-core.c
+++ b/xpp/xbus-core.c
@@ -76,6 +76,8 @@ static DEVICE_ATTR_FUNC(status_show, dev, buf);
static void xbus_release(struct device *dev);
static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data);
+static int read_proc_xmitter(char *page, char **start, off_t off, int count, int *eof, void *data);
+
/* Data structures */
static spinlock_t xbuses_lock = SPIN_LOCK_UNLOCKED;
@@ -86,6 +88,14 @@ static struct proc_dir_entry *proc_xbuses = NULL;
static DEVICE_ATTR(connector, S_IRUGO, connector_show, NULL);
static DEVICE_ATTR(status, S_IRUGO, status_show, NULL);
+/*
+ * Command Statistics
+ */
+uint command_count;
+ulong sum_latency;
+struct proc_dir_entry *proc_commands;
+#define PROC_CMDS "cmds"
+
/*------------------------- Debugfs Handling -----------------------*/
#ifdef XPP_DEBUGFS
@@ -131,7 +141,7 @@ int xbus_log(xbus_t *xbus, xpd_t *xpd, int direction, const void *buf, unsigned
}
header.len = sizeof(struct log_header) + len;
header.time = jiffies_to_msecs(jiffies);
- header.xpd_num = xpd->id;
+ header.xpd_num = xpd->xbus_idx;
header.direction = (char)direction;
tail = d->tail;
tail += add_to_buf(d, tail, &header, sizeof(header));
@@ -252,6 +262,8 @@ xframe_t *xbus_xframe_new(xbus_t *xbus, gfp_t flags)
return NULL;
memset(frm, 0, sizeof(xframe_t) + XFRAME_DATASIZE);
atomic_set(&frm->frame_len, 0);
+ frm->xbus = xbus;
+ do_gettimeofday(&frm->tv_created);
frm->packets = (byte *)frm + sizeof(xframe_t);
return frm;
}
@@ -288,6 +300,7 @@ static spinlock_t serialize_dump_xframe = SPIN_LOCK_UNLOCKED;
static void do_hexdump(const char msg[], byte *data, uint16_t len)
{
int i;
+ int print_dbg = 1;
for(i = 0; i < len; i++)
DBG("%s: %3d> %02X\n", msg, i, data[i]);
@@ -308,7 +321,7 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe)
do {
if(pos >= XFRAME_DATASIZE) {
if(printk_ratelimit()) {
- ERR("%s: xframe overflow (%d bytes)\n",
+ NOTICE("%s: xframe overflow (%d bytes)\n",
msg, frame_len);
do_hexdump(msg, xframe->packets, frame_len);
}
@@ -316,7 +329,7 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe)
}
if(pos > frame_len) {
if(printk_ratelimit()) {
- ERR("%s: packet overflow pos=%d frame_len=%d\n",
+ NOTICE("%s: packet overflow pos=%d frame_len=%d\n",
msg, pos, frame_len);
do_hexdump(msg, xframe->packets, frame_len);
}
@@ -325,7 +338,7 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe)
pack = (xpacket_t *)&xframe->packets[pos];
if(pack->datalen <= 0) {
if(printk_ratelimit()) {
- ERR("%s: xframe -- bad datalen=%d pos=%d frame_len=%d\n",
+ NOTICE("%s: xframe -- bad datalen=%d pos=%d frame_len=%d\n",
msg, pack->datalen, pos, frame_len);
do_hexdump(msg, xframe->packets, frame_len);
}
@@ -334,7 +347,7 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe)
nextpos = pos + pack->datalen;
if(nextpos > frame_len) {
if(printk_ratelimit()) {
- ERR("%s: packet overflow nextpos=%d frame_len=%d\n",
+ NOTICE("%s: packet overflow nextpos=%d frame_len=%d\n",
msg, nextpos, frame_len);
do_hexdump(msg, xframe->packets, frame_len);
}
@@ -350,7 +363,7 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe)
if(num == 1)
DBG("%s: %s: frame_len=%d.\n",
msg, xbus->busname, frame_len);
- DBG(" %3d. DATALEN=%d OP=0x%02X XPD-%d-%d (pos=%d)\n",
+ DBG(" %3d. DATALEN=%d OP=0x%02X XPD-%d%d (pos=%d)\n",
num, pack->datalen, pack->opcode,
pack->addr.unit, pack->addr.subunit, pos);
dump_packet(" ", pack, print_dbg);
@@ -363,6 +376,59 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe)
spin_unlock_irqrestore(&serialize_dump_xframe, flags);
}
+/**
+ *
+ * Frame is freed:
+ * - In case of error, by this function.
+ * - Otherwise, by the underlying sending mechanism
+ */
+int xframe_send(xbus_t *xbus, xframe_t *xframe)
+{
+ int ret = -ENODEV;
+
+ if(!xframe) {
+ DBG("null xframe\n");
+ return -EINVAL;
+ }
+ if(!xbus) {
+ DBG("null xbus\n");
+ ret = -EINVAL;
+ goto error;
+ }
+ if (!xbus->hardware_exists) {
+ DBG("xbus %s Dropped a xframe -- NO HARDWARE.", xbus->busname);
+ ret = -ENODEV;
+ goto error;
+ }
+ if(down_read_trylock(&xbus->in_use)) {
+ ret = xbus->ops->xframe_send(xbus, xframe);
+ XBUS_COUNTER(xbus, TX_BYTES) += XFRAME_LEN(xframe);
+ up_read(&xbus->in_use);
+ } else {
+ DBG("Dropped xframe. %s is in_use\n", xbus->busname);
+ }
+ return ret;
+
+error:
+ xbus->ops->xframe_free(xbus, xframe);
+ return ret;
+}
+
+int send_cmd_frame(xbus_t *xbus, xframe_t *xframe)
+{
+ struct timeval now;
+ struct timeval *created = &xframe->tv_created;
+ ulong usec_diff;
+
+ DBG("%s:\n", xbus->busname);
+ command_count++;
+ do_gettimeofday(&now);
+ usec_diff =
+ (now.tv_sec - created->tv_sec) * 1000000 +
+ (now.tv_usec - created->tv_usec);
+ sum_latency += usec_diff;
+ return xframe_send(xbus, xframe);
+}
/*------------------------- Bus Management -------------------------*/
xbus_t *xbus_of(int xbus_num)
@@ -379,9 +445,16 @@ xpd_t *xpd_of(const xbus_t *xbus, int xpd_num)
return xbus->xpds[xpd_num];
}
+xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit)
+{
+ if(unit > MAX_UNIT || subunit > MAX_SUBUNIT)
+ return NULL;
+ return xbus->xpds[XPD_IDX(unit,subunit)];
+}
+
int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd)
{
- unsigned int xpd_num = xpd->id;
+ unsigned int xpd_num = xpd->xbus_idx;
unsigned long flags;
int ret = 0;
@@ -400,6 +473,7 @@ int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd)
goto out;
}
xbus->xpds[xpd_num] = xpd;
+ xpd->xbus = xbus;
xbus->num_xpds++;
out:
spin_unlock_irqrestore(&xbus->lock, flags);
@@ -408,27 +482,31 @@ out:
int xbus_unregister_xpd(xbus_t *xbus, xpd_t *xpd)
{
- unsigned int xpd_num = xpd->id;
+ unsigned int xpd_num = xpd->xbus_idx;
unsigned long flags;
- int ret = 0;
+ int ret = -EINVAL;
spin_lock_irqsave(&xbus->lock, flags);
if(!VALID_XPD_NUM(xpd_num)) {
- ERR("%s: Bad xpd_num = %d\n", xbus->busname, xpd_num);
- ret = -EINVAL;
+ ERR("%s: %s: Bad xpd_num = %d\n", __FUNCTION__, xbus->busname, xpd_num);
+ goto out;
+ }
+ if(xbus->xpds[xpd_num] == NULL) {
+ ERR("%s: %s: slot xpd_num=%d is empty\n",
+ __FUNCTION__, xbus->busname, xpd_num);
goto out;
}
if(xbus->xpds[xpd_num] != xpd) {
xpd_t *other = xbus->xpds[xpd_num];
- ERR("%s: xpd_num=%d is occupied by %p (%s)\n",
- xbus->busname, xpd_num, other, other->xpdname);
- ret = -EINVAL;
+ ERR("%s: %s: slot xpd_num=%d is occupied by %p (%s)\n",
+ __FUNCTION__, xbus->busname, xpd_num, other, other->xpdname);
goto out;
}
xbus->xpds[xpd_num] = NULL;
xbus->num_xpds--;
xpd->xbus = NULL;
+ ret = 0;
out:
spin_unlock_irqrestore(&xbus->lock, flags);
return ret;
@@ -485,7 +563,6 @@ static void xbus_poll(void *data)
ERR("xpp: %s: Failed sending DESC_REQ to XPD #%d\n", __FUNCTION__, id);
goto out;
}
- mdelay(1); /* FIXME: debugging for Dima */
}
spin_unlock_irqrestore(&xbus->lock, flags);
/*
@@ -517,7 +594,7 @@ static void xbus_poll(void *data)
xpd_t *xpd;
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
- xpd = xpd_by_addr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit);
+ xpd = xpd_byaddr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit);
if(xpd && type == XPD_TYPE_NOMODULE) { /* card removal */
list_move_tail(card, &removal_list);
@@ -545,7 +622,7 @@ static void xbus_poll(void *data)
xpd_t *xpd;
list_del(card);
- xpd = xpd_by_addr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit);
+ xpd = xpd_byaddr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit);
if(xpd)
xpd_disconnect(xpd);
kfree(card);
@@ -577,7 +654,7 @@ void xbus_poller_notify(xbus_t *xbus, struct card_desc_struct *card_desc)
poller = xbus->poller;
BUG_ON(!poller);
if(!poller->is_polling) {
- NOTICE("%s: %d-%d replied not during poll. Ignore\n",
+ NOTICE("%s: %d%d replied not during poll. Ignore\n",
xbus->busname,
card_desc->xpd_addr.unit,
card_desc->xpd_addr.subunit);
@@ -710,8 +787,8 @@ void xbus_disconnect(xbus_t *xbus)
xpd_t *xpd = xpd_of(xbus, i);
if(!xpd)
continue;
- if(xpd->id != i) {
- ERR("%s: BUG: xpd->id=%d != i=%d\n", __FUNCTION__, xpd->id, i);
+ if(xpd->xbus_idx != i) {
+ ERR("%s: BUG: xpd->xbus_idx=%d != i=%d\n", __FUNCTION__, xpd->xbus_idx, i);
continue;
}
xpd_disconnect(xpd);
@@ -830,6 +907,7 @@ xbus_t *xbus_new(xbus_ops_t *ops)
INFO("New xbus: %s\n", xbus->busname);
init_waitqueue_head(&xbus->packet_cache_empty);
atomic_set(&xbus->packet_counter, 0);
+ atomic_set(&xbus->pcm_nesting, 1);
xbus->min_tx_sync = INT_MAX;
xbus->min_rx_sync = INT_MAX;
@@ -840,7 +918,6 @@ xbus_t *xbus_new(xbus_ops_t *ops)
xbus_free(xbus);
return NULL;
}
-
init_rwsem(&xbus->in_use);
xbus_reset_counters(xbus);
@@ -951,11 +1028,11 @@ void xbus_remove(xbus_t *xbus)
xpd_t *xpd = xpd_of(xbus, i);
if(xpd) {
- if(xpd->id != i) {
- ERR("%s: BUG: xpd->id=%d != i=%d\n", __FUNCTION__, xpd->id, i);
+ if(xpd->xbus_idx != i) {
+ ERR("%s: BUG: xpd->xbus_idx=%d != i=%d\n", __FUNCTION__, xpd->xbus_idx, i);
continue;
}
- DBG(" Removing xpd id=%d\n", xpd->id);
+ DBG(" Removing xpd xbus_idx=%d\n", xpd->xbus_idx);
xpd_remove(xpd);
}
xbus->xpds[i] = NULL;
@@ -1022,6 +1099,11 @@ static int xbus_read_proc(char *page, char **start, off_t off, int count, int *e
xbus_counters[i].name, xbus->counters[i]);
}
len += sprintf(page + len, "<-- len=%d\n", len);
+ /* reset statistics */
+ xbus->min_tx_sync = INT_MAX;
+ xbus->max_tx_sync = 0;
+ xbus->min_rx_sync = INT_MAX;
+ xbus->max_rx_sync = 0;
spin_unlock_irqrestore(&xbus->lock, flags);
out:
if (len <= off+count)
@@ -1139,7 +1221,7 @@ static int proc_xbus_command_write(struct file *file, const char __user *buffer,
return -ENOMEM;
}
memcpy(pack, pack_start, q - pack_start); /* FRAMES: checksum? */
- xframe_send(xbus, xframe);
+ send_cmd_frame(xbus, xframe);
return count;
}
#endif
@@ -1179,6 +1261,32 @@ static int read_proc_xbuses(char *page, char **start, off_t off, int count, int
return len;
}
+
+static int read_proc_xmitter(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+ len += sprintf(page + len, "command_count: %d\n",
+ command_count);
+ len += sprintf(page + len, "sum_latency: %ld\n",
+ sum_latency);
+ if(command_count)
+ len += sprintf(page + len, "average latency: %ld\n",
+ sum_latency/command_count);
+#if 0
+ len += sprintf(page + len, "<-- len=%d\n", len);
+#endif
+ if (len <= off+count)
+ *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
+ return len;
+
+}
+
#endif
/*------------------------- Initialization -------------------------*/
@@ -1245,13 +1353,20 @@ static void xbus_core_cleanup(void)
proc_xbuses = NULL;
}
#endif
+#ifdef CONFIG_PROC_FS
+ if(proc_commands) {
+ DBG("Removing %s from proc\n", PROC_CMDS);
+ remove_proc_entry(PROC_CMDS, xpp_proc_toplevel);
+ proc_commands = NULL;
+ }
+#endif
if(xframes_cache)
kmem_cache_destroy(xframes_cache);
}
int __init xbus_core_init(void)
{
- int ret;
+ int ret = 0;
#ifdef PROTOCOL_DEBUG
INFO("FEATURE: %s with PROTOCOL_DEBUG\n", THIS_MODULE->name);
@@ -1267,6 +1382,16 @@ int __init xbus_core_init(void)
return -ENOMEM;
}
#ifdef CONFIG_PROC_FS
+ proc_commands = create_proc_read_entry(
+ PROC_CMDS, 0444, xpp_proc_toplevel,
+ read_proc_xmitter, NULL);
+ if (!proc_commands) {
+ ERR("Failed to create proc file %s\n", PROC_CMDS);
+ goto err;
+ }
+ proc_commands->owner = THIS_MODULE;
+#endif
+#ifdef CONFIG_PROC_FS
proc_xbuses = create_proc_read_entry(PROC_XBUSES, 0444, xpp_proc_toplevel, read_proc_xbuses, NULL);
if (!proc_xbuses) {
ERR("Failed to create proc file %s\n", PROC_XBUSES);
@@ -1311,6 +1436,7 @@ void __exit xbus_core_shutdown(void)
}
EXPORT_SYMBOL(xpd_of);
+EXPORT_SYMBOL(xpd_byaddr);
EXPORT_SYMBOL(xbus_new);
EXPORT_SYMBOL(xbus_remove);
EXPORT_SYMBOL(xbus_activate);
@@ -1318,6 +1444,8 @@ EXPORT_SYMBOL(xbus_disconnect);
EXPORT_SYMBOL(xbus_reset_counters);
EXPORT_SYMBOL(xframe_next_packet);
EXPORT_SYMBOL(dump_xframe);
+EXPORT_SYMBOL(xframe_send);
+EXPORT_SYMBOL(send_cmd_frame);
EXPORT_SYMBOL(xbus_poller_notify);
#ifdef XPP_DEBUGFS
EXPORT_SYMBOL(xbus_log);