/*
* Functions to handle I2O controllers and I2O message handling
*
* Copyright (C) 1999-2002 Red Hat Software
*
* Written by Alan Cox, Building Number Three Ltd
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* A lot of the I2O message side code from this is taken from the
* Red Creek RCPCI45 adapter driver by Red Creek Communications
*
* Fixes/additions:
* Philipp Rumpf
* Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
* Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
* Deepak Saxena <deepak@plexity.net>
* Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
* Alan Cox <alan@redhat.com>:
* Ported to Linux 2.5.
* Markus Lidel <Markus.Lidel@shadowconnect.com>:
* Minor fixes for 2.6.
*/
#include <linux/module.h>
#include <linux/i2o.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include "core.h"
#define OSM_NAME "i2o"
#define OSM_VERSION "1.325"
#define OSM_DESCRIPTION "I2O subsystem"
/* global I2O controller list */
LIST_HEAD(i2o_controllers);
/*
* global I2O System Table. Contains information about all the IOPs in the
* system. Used to inform IOPs about each others existence.
*/
static struct i2o_dma i2o_systab;
static int i2o_hrt_get(struct i2o_controller *c);
/**
* i2o_msg_get_wait - obtain an I2O message from the IOP
* @c: I2O controller
* @msg: pointer to a I2O message pointer
* @wait: how long to wait until timeout
*
* This function waits up to wait seconds for a message slot to be
* available.
*
* On a success the message is returned and the pointer to the message is
* set in msg. The returned message is the physical page frame offset
* address from the read port (see the i2o spec). If no message is
* available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
*/
struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait)
{
unsigned long timeout = jiffies + wait * HZ;
struct i2o_message *msg;
while (IS_ERR(msg = i2o_msg_get(c))) {
if (time_after(jiffies, timeout)) {
osm_debug("%s: Timeout waiting for message frame.\n",
c->name);
return ERR_PTR(-ETIMEDOUT);
}
schedule_timeout_uninterruptible(1);
}
return msg;
};
#if BITS_PER_LONG == 64
/**
* i2o_cntxt_list_add - Append a pointer to context list and return a id
* @c: controller to which the context list belong
* @ptr: pointer to add to the context list
*
* Because the context field in I2O is only 32-bit large, on 64-bit the
* pointer is to large to fit in the context field. The i2o_cntxt_list
* functions therefore map pointers to context fields.
*
* Returns context id > 0 on success or 0 on failure.
*/
u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr)
{
struct i2o_context_list_element *entry;
unsigned long flags;
if (!ptr)
osm_err("%s: couldn't add NULL pointer to context list!\n",
c->name);
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry) {
osm_err("%s: Could not allocate memory for context list element"
"\n", c->name);
return 0;
}
entry->ptr = ptr;
entry->timestamp = jiffies;
INIT_LIST_HEAD(&entry->list);
spin_lock_irqsave(&c->context_list_lock, flags);
if (unlikely(atomic_inc_and_test(&c->context_list_counter)))
atomic_inc(&c->context_list_counter);
entry->context = atomic_read(&c->context_list_counter);
list_add(&entry->list, &c->context_list);
spin_unlock_irqrestore(&c->context_list_lock, flags);
osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context);