u32 m; /* message id */
struct i2o_message *msg; /* pointer to the reply message */
struct list_head list; /* node in global wait list */
+ spinlock_t lock; /* lock before modifying */
};
/* Work struct needed to handle LCT NOTIFY replies */
return NULL;
INIT_LIST_HEAD(&wait->list);
+ spin_lock_init(&wait->lock);
return wait;
};
/**
- * i2o_exec_wait_free - Free a i2o_exec_wait struct
- * @i2o_exec_wait: I2O wait data which should be cleaned up
+ * i2o_exec_wait_free - Free an i2o_exec_wait struct
+ * @wait: I2O wait data which should be cleaned up
*/
static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
{
/**
* i2o_msg_post_wait_mem - Post and wait a message with DMA buffers
* @c: controller
- * @m: message to post
+ * @msg: message to post
* @timeout: time in seconds to wait
* @dma: i2o_dma struct of the DMA buffer to free on failure
*
int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
unsigned long timeout, struct i2o_dma *dma)
{
- DECLARE_WAIT_QUEUE_HEAD(wq);
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
struct i2o_exec_wait *wait;
static u32 tcntxt = 0x80000000;
+ unsigned long flags;
int rc = 0;
wait = i2o_exec_wait_alloc();
wait->tcntxt = tcntxt++;
msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt);
+ wait->wq = &wq;
+ /*
+ * we add elements to the head, because if a entry in the list will
+ * never be removed, we have to iterate over it every time
+ */
+ list_add(&wait->list, &i2o_exec_wait_list);
+
/*
* Post the message to the controller. At some point later it will
* return. If we time out before it returns then complete will be zero.
*/
i2o_msg_post(c, msg);
- if (!wait->complete) {
- wait->wq = &wq;
- /*
- * we add elements add the head, because if a entry in the list
- * will never be removed, we have to iterate over it every time
- */
- list_add(&wait->list, &i2o_exec_wait_list);
-
- wait_event_interruptible_timeout(wq, wait->complete,
- timeout * HZ);
+ wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ);
- wait->wq = NULL;
- }
+ spin_lock_irqsave(&wait->lock, flags);
- barrier();
+ wait->wq = NULL;
- if (wait->complete) {
+ if (wait->complete)
rc = le32_to_cpu(wait->msg->body[0]) >> 24;
- i2o_flush_reply(c, wait->m);
- i2o_exec_wait_free(wait);
- } else {
+ else {
/*
* We cannot remove it now. This is important. When it does
* terminate (which it must do if the controller has not
rc = -ETIMEDOUT;
}
+ spin_unlock_irqrestore(&wait->lock, flags);
+
+ if (rc != -ETIMEDOUT) {
+ i2o_flush_reply(c, wait->m);
+ i2o_exec_wait_free(wait);
+ }
+
return rc;
};
{
struct i2o_exec_wait *wait, *tmp;
unsigned long flags;
- static spinlock_t lock = SPIN_LOCK_UNLOCKED;
int rc = 1;
/*
* already expired. Not much we can do about that except log it for
* debug purposes, increase timeout, and recompile.
*/
- spin_lock_irqsave(&lock, flags);
list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
if (wait->tcntxt == context) {
- list_del(&wait->list);
+ spin_lock_irqsave(&wait->lock, flags);
- spin_unlock_irqrestore(&lock, flags);
+ list_del(&wait->list);
wait->m = m;
wait->msg = msg;
wait->complete = 1;
- barrier();
-
- if (wait->wq) {
- wake_up_interruptible(wait->wq);
+ if (wait->wq)
rc = 0;
- } else {
+ else
+ rc = -1;
+
+ spin_unlock_irqrestore(&wait->lock, flags);
+
+ if (rc) {
struct device *dev;
dev = &c->pdev->dev;
c->name);
i2o_dma_free(dev, &wait->dma);
i2o_exec_wait_free(wait);
- rc = -1;
- }
+ } else
+ wake_up_interruptible(wait->wq);
return rc;
}
}
- spin_unlock_irqrestore(&lock, flags);
-
osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
context);
/**
* i2o_exec_show_vendor_id - Displays Vendor ID of controller
* @d: device of which the Vendor ID should be displayed
+ * @attr: device_attribute to display
* @buf: buffer into which the Vendor ID should be printed
*
* Returns number of bytes printed into buffer.
/**
* i2o_exec_show_product_id - Displays Product ID of controller
* @d: device of which the Product ID should be displayed
+ * @attr: device_attribute to display
* @buf: buffer into which the Product ID should be printed
*
* Returns number of bytes printed into buffer.
static int i2o_exec_probe(struct device *dev)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
- struct i2o_controller *c = i2o_dev->iop;
-
- i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
+ int rc;
- c->exec = i2o_dev;
+ rc = i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
+ if (rc) goto err_out;
- i2o_exec_lct_notify(c, c->lct->change_ind + 1);
-
- device_create_file(dev, &dev_attr_vendor_id);
- device_create_file(dev, &dev_attr_product_id);
+ rc = device_create_file(dev, &dev_attr_vendor_id);
+ if (rc) goto err_evtreg;
+ rc = device_create_file(dev, &dev_attr_product_id);
+ if (rc) goto err_vid;
return 0;
+
+err_vid:
+ device_remove_file(dev, &dev_attr_vendor_id);
+err_evtreg:
+ i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0);
+err_out:
+ return rc;
};
/**
/**
* i2o_exec_lct_modified - Called on LCT NOTIFY reply
- * @c: I2O controller on which the LCT has modified
+ * @work: work struct for a specific controller
*
* This function handles asynchronus LCT NOTIFY replies. It parses the
* new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
* again, otherwise send LCT NOTIFY to get informed on next LCT change.
*/
-static void i2o_exec_lct_modified(struct i2o_exec_lct_notify_work *work)
+static void i2o_exec_lct_modified(struct work_struct *_work)
{
+ struct i2o_exec_lct_notify_work *work =
+ container_of(_work, struct i2o_exec_lct_notify_work, work);
u32 change_ind = 0;
struct i2o_controller *c = work->c;
work->c = c;
- INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified,
- work);
+ INIT_WORK(&work->work, i2o_exec_lct_modified);
queue_work(i2o_exec_driver.event_queue, &work->work);
return 1;
}
/**
* i2o_exec_event - Event handling function
- * @evt: Event which occurs
+ * @work: Work item in occurring event
*
* Handles events send by the Executive device. At the moment does not do
* anything useful.
*/
-static void i2o_exec_event(struct i2o_event *evt)
+static void i2o_exec_event(struct work_struct *work)
{
+ struct i2o_event *evt = container_of(work, struct i2o_event, work);
+
if (likely(evt->i2o_dev))
osm_debug("Event received from device: %d\n",
evt->i2o_dev->lct_data.tid);
struct device *dev;
struct i2o_message *msg;
+ down(&c->lct_lock);
+
dev = &c->pdev->dev;
if (i2o_dma_realloc
i2o_msg_post(c, msg);
+ up(&c->lct_lock);
+
return 0;
};