* 2 of the License, or (at your option) any later version.
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/i2o.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
#include <linux/smp_lock.h>
-#include <linux/ioctl32.h>
#include <linux/compat.h>
-#include <linux/syscalls.h>
#include <asm/uaccess.h>
-#include <asm/io.h>
-extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+#include "core.h"
-static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
-struct wait_queue *i2o_wait_queue;
+#define SG_TABLESIZE 30
+
+static int i2o_cfg_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
+
+static spinlock_t i2o_config_lock;
#define MODINC(x,y) ((x) = ((x) + 1) % (y))
static struct i2o_cfg_info *open_files = NULL;
static ulong i2o_cfg_info_id = 0;
-#if 0
-/*
- * This is the callback for any message we have posted. The message itself
- * will be returned to the message pool when we return from the IRQ
- *
- * This runs in irq context so be short and sweet.
- */
-static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c,
- struct i2o_message *m)
-{
- u32 *msg = (u32 *) m;
-
- if (msg[0] & MSG_FAIL) {
- u32 *preserved_msg = (u32 *) (c->msg_virt + msg[7]);
-
- printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n");
-
- /* Release the preserved msg frame by resubmitting it as a NOP */
-
- preserved_msg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
- preserved_msg[1] = I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0;
- preserved_msg[2] = 0;
- i2o_post_message(c, msg[7]);
- }
-
- if (msg[4] >> 24) // ReqStatus != SUCCESS
- i2o_report_status(KERN_INFO, "i2o_config", msg);
-
- if (m->function == I2O_CMD_UTIL_EVT_REGISTER) {
- struct i2o_cfg_info *inf;
-
- for (inf = open_files; inf; inf = inf->next)
- if (inf->q_id == i2o_cntxt_list_get(c, msg[3]))
- break;
-
- //
- // If this is the case, it means that we're getting
- // events for a file descriptor that's been close()'d
- // w/o the user unregistering for events first.
- // The code currently assumes that the user will
- // take care of unregistering for events before closing
- // a file.
- //
- // TODO:
- // Should we track event registartion and deregister
- // for events when a file is close()'d so this doesn't
- // happen? That would get rid of the search through
- // the linked list since file->private_data could point
- // directly to the i2o_config_info data structure...but
- // it would mean having all sorts of tables to track
- // what each file is registered for...I think the
- // current method is simpler. - DS
- //
- if (!inf)
- return;
-
- inf->event_q[inf->q_in].id.iop = c->unit;
- inf->event_q[inf->q_in].id.tid = m->target_tid;
- inf->event_q[inf->q_in].id.evt_mask = msg[4];
-
- //
- // Data size = msg size - reply header
- //
- inf->event_q[inf->q_in].data_size = (m->size - 5) * 4;
- if (inf->event_q[inf->q_in].data_size)
- memcpy(inf->event_q[inf->q_in].evt_data,
- (unsigned char *)(msg + 5),
- inf->event_q[inf->q_in].data_size);
-
- spin_lock(&i2o_config_lock);
- MODINC(inf->q_in, I2O_EVT_Q_LEN);
- if (inf->q_len == I2O_EVT_Q_LEN) {
- MODINC(inf->q_out, I2O_EVT_Q_LEN);
- inf->q_lost++;
- } else {
- // Keep I2OEVTGET on another CPU from touching this
- inf->q_len++;
- }
- spin_unlock(&i2o_config_lock);
-
-// printk(KERN_INFO "File %p w/id %d has %d events\n",
-// inf->fp, inf->q_id, inf->q_len);
-
- kill_fasync(&inf->fasync, SIGIO, POLL_IN);
- }
-
- return;
-}
-#endif
-
-/*
- * Each of these describes an i2o message handler. They are
- * multiplexed by the i2o_core code
- */
-
-struct i2o_driver i2o_config_driver = {
- .name = "Config-OSM"
-};
-
static int i2o_cfg_getiops(unsigned long arg)
{
struct i2o_controller *c;
u8 __user *user_iop_table = (void __user *)arg;
u8 tmp[MAX_I2O_CONTROLLERS];
+ int ret = 0;
memset(tmp, 0, MAX_I2O_CONTROLLERS);
- if (!access_ok(VERIFY_WRITE, user_iop_table, MAX_I2O_CONTROLLERS))
- return -EFAULT;
-
list_for_each_entry(c, &i2o_controllers, list)
tmp[c->unit] = 1;
- __copy_to_user(user_iop_table, tmp, MAX_I2O_CONTROLLERS);
+ if (copy_to_user(user_iop_table, tmp, MAX_I2O_CONTROLLERS))
+ ret = -EFAULT;
- return 0;
+ return ret;
};
static int i2o_cfg_gethrt(unsigned long arg)
if (!dev)
return -ENXIO;
- ops = (u8 *) kmalloc(kcmd.oplen, GFP_KERNEL);
+ ops = kmalloc(kcmd.oplen, GFP_KERNEL);
if (!ops)
return -ENOMEM;
* It's possible to have a _very_ large table
* and that the user asks for all of it at once...
*/
- res = (u8 *) kmalloc(65536, GFP_KERNEL);
+ res = kmalloc(65536, GFP_KERNEL);
if (!res) {
kfree(ops);
return -ENOMEM;
unsigned char maxfrag = 0, curfrag = 1;
struct i2o_dma buffer;
struct i2o_message *msg;
- u32 m;
unsigned int status = 0, swlen = 0, fragsize = 8192;
struct i2o_controller *c;
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
return -ENOMEM;
}
- __copy_from_user(buffer.virt, kxfer.buf, fragsize);
-
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
- writel(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- writel((((u32) kxfer.flags) << 24) | (((u32) kxfer.sw_type) << 16) |
- (((u32) maxfrag) << 8) | (((u32) curfrag)), &msg->body[0]);
- writel(swlen, &msg->body[1]);
- writel(kxfer.sw_id, &msg->body[2]);
- writel(0xD0000000 | fragsize, &msg->body[3]);
- writel(buffer.phys, &msg->body[4]);
+ if (__copy_from_user(buffer.virt, kxfer.buf, fragsize)) {
+ i2o_msg_nop(c, msg);
+ i2o_dma_free(&c->pdev->dev, &buffer);
+ return -EFAULT;
+ }
-// printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+ msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
+ msg->body[0] =
+ cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer.
+ sw_type) << 16) |
+ (((u32) maxfrag) << 8) | (((u32) curfrag)));
+ msg->body[1] = cpu_to_le32(swlen);
+ msg->body[2] = cpu_to_le32(kxfer.sw_id);
+ msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
+ msg->body[4] = cpu_to_le32(buffer.phys);
+
+ osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
+ status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
if (status != -ETIMEDOUT)
i2o_dma_free(&c->pdev->dev, &buffer);
if (status != I2O_POST_WAIT_OK) {
// it fails if you try and send frags out of order
// and for some yet unknown reasons too
- printk(KERN_INFO
- "i2o_config: swdl failed, DetailedStatus = %d\n",
- status);
+ osm_info("swdl failed, DetailedStatus = %d\n", status);
return status;
}
unsigned char maxfrag = 0, curfrag = 1;
struct i2o_dma buffer;
struct i2o_message *msg;
- u32 m;
unsigned int status = 0, swlen = 0, fragsize = 8192;
struct i2o_controller *c;
+ int ret = 0;
if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
- return -EFAULT;
+ goto return_fault;
if (get_user(swlen, kxfer.swlen) < 0)
- return -EFAULT;
+ goto return_fault;
if (get_user(maxfrag, kxfer.maxfrag) < 0)
- return -EFAULT;
+ goto return_fault;
if (get_user(curfrag, kxfer.curfrag) < 0)
- return -EFAULT;
+ goto return_fault;
if (curfrag == maxfrag)
fragsize = swlen - (maxfrag - 1) * 8192;
- if (!kxfer.buf || !access_ok(VERIFY_WRITE, kxfer.buf, fragsize))
- return -EFAULT;
+ if (!kxfer.buf)
+ goto return_fault;
c = i2o_find_iop(kxfer.iop);
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
return -ENOMEM;
}
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
- writel(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- writel((u32) kxfer.flags << 24 | (u32) kxfer.
- sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag,
- &msg->body[0]);
- writel(swlen, &msg->body[1]);
- writel(kxfer.sw_id, &msg->body[2]);
- writel(0xD0000000 | fragsize, &msg->body[3]);
- writel(buffer.phys, &msg->body[4]);
-
-// printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+ msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
+ msg->body[0] =
+ cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.
+ sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag);
+ msg->body[1] = cpu_to_le32(swlen);
+ msg->body[2] = cpu_to_le32(kxfer.sw_id);
+ msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
+ msg->body[4] = cpu_to_le32(buffer.phys);
+
+ osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
+ status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
if (status != I2O_POST_WAIT_OK) {
if (status != -ETIMEDOUT)
i2o_dma_free(&c->pdev->dev, &buffer);
- printk(KERN_INFO
- "i2o_config: swul failed, DetailedStatus = %d\n",
- status);
+ osm_info("swul failed, DetailedStatus = %d\n", status);
return status;
}
- __copy_to_user(kxfer.buf, buffer.virt, fragsize);
+ if (copy_to_user(kxfer.buf, buffer.virt, fragsize))
+ ret = -EFAULT;
+
i2o_dma_free(&c->pdev->dev, &buffer);
- return 0;
+ return_ret:
+ return ret;
+ return_fault:
+ ret = -EFAULT;
+ goto return_ret;
};
static int i2o_cfg_swdel(unsigned long arg)
struct i2o_sw_xfer kxfer;
struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
struct i2o_message *msg;
- u32 m;
unsigned int swlen;
int token;
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- writel((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16,
- &msg->body[0]);
- writel(swlen, &msg->body[1]);
- writel(kxfer.sw_id, &msg->body[2]);
+ msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
+ msg->body[0] =
+ cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16);
+ msg->body[1] = cpu_to_le32(swlen);
+ msg->body[2] = cpu_to_le32(kxfer.sw_id);
- token = i2o_msg_post_wait(c, m, 10);
+ token = i2o_msg_post_wait(c, msg, 10);
if (token != I2O_POST_WAIT_OK) {
- printk(KERN_INFO
- "i2o_config: swdel failed, DetailedStatus = %d\n",
- token);
+ osm_info("swdel failed, DetailedStatus = %d\n", token);
return -ETIMEDOUT;
}
int token;
int iop = (int)arg;
struct i2o_message *msg;
- u32 m;
struct i2o_controller *c;
c = i2o_find_iop(iop);
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
- token = i2o_msg_post_wait(c, m, 10);
+ token = i2o_msg_post_wait(c, msg, 10);
if (token != I2O_POST_WAIT_OK) {
- printk(KERN_INFO "Can't validate configuration, ErrorStatus = "
- "%d\n", token);
+ osm_info("Can't validate configuration, ErrorStatus = %d\n",
+ token);
return -ETIMEDOUT;
}
static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
{
struct i2o_message *msg;
- u32 m;
struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg;
struct i2o_evt_id kdesc;
struct i2o_controller *c;
if (!d)
return -ENODEV;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | kdesc.tid,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(i2o_cntxt_list_add(c, fp->private_data), &msg->u.head[3]);
- writel(kdesc.evt_mask, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 |
+ kdesc.tid);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data));
+ msg->body[0] = cpu_to_le32(kdesc.evt_mask);
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
return 0;
}
}
#ifdef CONFIG_COMPAT
-static int i2o_cfg_passthru32(unsigned fd, unsigned cmnd, unsigned long arg,
- struct file *file)
+static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
+ unsigned long arg)
{
struct i2o_cmd_passthru32 __user *cmd;
struct i2o_controller *c;
u32 sg_offset = 0;
u32 sg_count = 0;
u32 i = 0;
+ u32 sg_index = 0;
i2o_status_block *sb;
struct i2o_message *msg;
- u32 m;
unsigned int iop;
cmd = (struct i2o_cmd_passthru32 __user *)arg;
c = i2o_find_iop(iop);
if (!c) {
- pr_debug("controller %d not found\n", iop);
+ osm_debug("controller %d not found\n", iop);
return -ENXIO;
}
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
sb = c->status_block.virt;
if (get_user(size, &user_msg[0])) {
- printk(KERN_WARNING "unable to get size!\n");
+ osm_warn("unable to get size!\n");
return -EFAULT;
}
size = size >> 16;
if (size > sb->inbound_frame_size) {
- pr_debug("size of message > inbound_frame_size");
+ osm_warn("size of message > inbound_frame_size");
return -EFAULT;
}
/* Copy in the user's I2O command */
if (copy_from_user(msg, user_msg, size)) {
- printk(KERN_WARNING "unable to copy user message\n");
+ osm_warn("unable to copy user message\n");
return -EFAULT;
}
i2o_dump_message(msg);
reply_size >>= 16;
reply_size <<= 2;
- reply = kmalloc(reply_size, GFP_KERNEL);
+ reply = kzalloc(reply_size, GFP_KERNEL);
if (!reply) {
printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
c->name);
return -ENOMEM;
}
- memset(reply, 0, reply_size);
sg_offset = (msg->u.head[0] >> 4) & 0x0f;
- writel(i2o_config_driver.context, &msg->u.s.icntxt);
- writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
-
memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
if (sg_offset) {
struct sg_simple_element *sg;
if (sg_count > SG_TABLESIZE) {
printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
c->name, sg_count);
- kfree(reply);
- return -EINVAL;
+ rcode = -EINVAL;
+ goto cleanup;
}
for (i = 0; i < sg_count; i++) {
goto cleanup;
}
sg_size = sg[i].flag_count & 0xffffff;
- p = &(sg_list[i]);
+ p = &(sg_list[sg_index]);
/* Allocate memory for the transfer */
if (i2o_dma_alloc
(&c->pdev->dev, p, sg_size,
"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
c->name, sg_size, i, sg_count);
rcode = -ENOMEM;
- goto cleanup;
+ goto sg_list_cleanup;
}
+ sg_index++;
/* Copy in the user's SG buffer if necessary */
if (sg[i].
flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
// TODO 64bit fix
if (copy_from_user
- (p->virt, (void __user *)(unsigned long)sg[i].addr_bus,
- sg_size)) {
+ (p->virt,
+ (void __user *)(unsigned long)sg[i].
+ addr_bus, sg_size)) {
printk(KERN_DEBUG
"%s: Could not copy SG buf %d FROM user\n",
c->name, i);
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
}
//TODO 64bit fix
}
}
- rcode = i2o_msg_post_wait(c, m, 60);
- if (rcode)
- goto cleanup;
+ rcode = i2o_msg_post_wait(c, msg, 60);
+ if (rcode) {
+ reply[4] = ((u32) rcode) << 24;
+ goto sg_list_cleanup;
+ }
if (sg_offset) {
- u32 msg[128];
+ u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
/* Copy back the Scatter Gather buffers back to user space */
u32 j;
// TODO 64bit fix
struct sg_simple_element *sg;
int sg_size;
- printk(KERN_INFO "sg_offset\n");
// re-acquire the original message to handle correctly the sg copy operation
- memset(&msg, 0, MSG_FRAME_SIZE * 4);
+ memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
// get user msg size in u32s
if (get_user(size, &user_msg[0])) {
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
size = size >> 16;
size *= 4;
/* Copy in the user's I2O command */
if (copy_from_user(msg, user_msg, size)) {
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
sg_count =
(size - sg_offset * 4) / sizeof(struct sg_simple_element);
c->name, sg_list[j].virt,
sg[j].addr_bus);
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
}
}
}
+ sg_list_cleanup:
/* Copy back the reply to user space */
if (reply_size) {
// we wrote our own values for context - now restore the user supplied ones
- printk(KERN_INFO "reply_size\n");
if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {
printk(KERN_WARNING
"%s: Could not copy message context FROM user\n",
c->name);
rcode = -EFAULT;
+ goto sg_list_cleanup;
}
if (copy_to_user(user_reply, reply, reply_size)) {
printk(KERN_WARNING
}
}
+ for (i = 0; i < sg_index; i++)
+ i2o_dma_free(&c->pdev->dev, &sg_list[i]);
+
cleanup:
kfree(reply);
- printk(KERN_INFO "rcode: %d\n", rcode);
return rcode;
}
-#else
+static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
+ unsigned long arg)
+{
+ int ret;
+ lock_kernel();
+ switch (cmd) {
+ case I2OGETIOPS:
+ ret = i2o_cfg_ioctl(NULL, file, cmd, arg);
+ break;
+ case I2OPASSTHRU32:
+ ret = i2o_cfg_passthru32(file, cmd, arg);
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+ unlock_kernel();
+ return ret;
+}
+
+#endif
+#ifdef CONFIG_I2O_EXT_ADAPTEC
static int i2o_cfg_passthru(unsigned long arg)
{
struct i2o_cmd_passthru __user *cmd =
void *p = NULL;
i2o_status_block *sb;
struct i2o_message *msg;
- u32 m;
unsigned int iop;
if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))
c = i2o_find_iop(iop);
if (!c) {
- pr_debug("controller %d not found\n", iop);
+ osm_warn("controller %d not found\n", iop);
return -ENXIO;
}
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
sb = c->status_block.virt;
size = size >> 16;
if (size > sb->inbound_frame_size) {
- pr_debug("size of message > inbound_frame_size");
+ osm_warn("size of message > inbound_frame_size");
return -EFAULT;
}
reply_size >>= 16;
reply_size <<= 2;
- reply = kmalloc(reply_size, GFP_KERNEL);
+ reply = kzalloc(reply_size, GFP_KERNEL);
if (!reply) {
printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
c->name);
return -ENOMEM;
}
- memset(reply, 0, reply_size);
sg_offset = (msg->u.head[0] >> 4) & 0x0f;
- writel(i2o_config_driver.context, &msg->u.s.icntxt);
- writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
-
memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
if (sg_offset) {
struct sg_simple_element *sg;
if (sg_count > SG_TABLESIZE) {
printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
c->name, sg_count);
- kfree(reply);
- return -EINVAL;
+ rcode = -EINVAL;
+ goto cleanup;
}
for (i = 0; i < sg_count; i++) {
"%s:Bad SG element %d - not simple (%x)\n",
c->name, i, sg[i].flag_count);
rcode = -EINVAL;
- goto cleanup;
+ goto sg_list_cleanup;
}
sg_size = sg[i].flag_count & 0xffffff;
/* Allocate memory for the transfer */
"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
c->name, sg_size, i, sg_count);
rcode = -ENOMEM;
- goto cleanup;
+ goto sg_list_cleanup;
}
sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
/* Copy in the user's SG buffer if necessary */
"%s: Could not copy SG buf %d FROM user\n",
c->name, i);
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
}
//TODO 64bit fix
}
}
- rcode = i2o_msg_post_wait(c, m, 60);
- if (rcode)
- goto cleanup;
+ rcode = i2o_msg_post_wait(c, msg, 60);
+ if (rcode) {
+ reply[4] = ((u32) rcode) << 24;
+ goto sg_list_cleanup;
+ }
if (sg_offset) {
u32 msg[128];
// TODO 64bit fix
struct sg_simple_element *sg;
int sg_size;
- printk(KERN_INFO "sg_offset\n");
// re-acquire the original message to handle correctly the sg copy operation
- memset(&msg, 0, MSG_FRAME_SIZE * 4);
+ memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
// get user msg size in u32s
if (get_user(size, &user_msg[0])) {
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
size = size >> 16;
size *= 4;
/* Copy in the user's I2O command */
if (copy_from_user(msg, user_msg, size)) {
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
sg_count =
(size - sg_offset * 4) / sizeof(struct sg_simple_element);
c->name, sg_list[j],
sg[j].addr_bus);
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
}
}
}
+ sg_list_cleanup:
/* Copy back the reply to user space */
if (reply_size) {
// we wrote our own values for context - now restore the user supplied ones
- printk(KERN_INFO "reply_size\n");
if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {
printk(KERN_WARNING
"%s: Could not copy message context FROM user\n",
}
}
+ for (i = 0; i < sg_index; i++)
+ kfree(sg_list[i]);
+
cleanup:
kfree(reply);
return rcode;
ret = i2o_cfg_evt_get(arg, fp);
break;
-#ifndef CONFIG_COMPAT
+#ifdef CONFIG_I2O_EXT_ADAPTEC
case I2OPASSTHRU:
ret = i2o_cfg_passthru(arg);
break;
#endif
default:
- pr_debug("i2o_config: unknown ioctl called!\n");
+ osm_debug("unknown ioctl called!\n");
ret = -EINVAL;
}
.owner = THIS_MODULE,
.llseek = no_llseek,
.ioctl = i2o_cfg_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = i2o_cfg_compat_ioctl,
+#endif
.open = cfg_open,
.release = cfg_release,
.fasync = cfg_fasync,
&config_fops
};
-static int __init i2o_config_init(void)
+static int __init i2o_config_old_init(void)
{
- printk(KERN_INFO "I2O configuration manager v 0.04.\n");
- printk(KERN_INFO " (C) Copyright 1999 Red Hat Software\n");
+ spin_lock_init(&i2o_config_lock);
if (misc_register(&i2o_miscdev) < 0) {
- printk(KERN_ERR "i2o_config: can't register device.\n");
- return -EBUSY;
- }
- /*
- * Install our handler
- */
- if (i2o_driver_register(&i2o_config_driver)) {
- printk(KERN_ERR "i2o_config: handler register failed.\n");
- misc_deregister(&i2o_miscdev);
+ osm_err("can't register device.\n");
return -EBUSY;
}
-#ifdef CONFIG_COMPAT
- register_ioctl32_conversion(I2OPASSTHRU32, i2o_cfg_passthru32);
- register_ioctl32_conversion(I2OGETIOPS, (void *)sys_ioctl);
-#endif
+
return 0;
}
-static void i2o_config_exit(void)
+static void i2o_config_old_exit(void)
{
-#ifdef CONFIG_COMPAT
- unregister_ioctl32_conversion(I2OPASSTHRU32);
- unregister_ioctl32_conversion(I2OGETIOPS);
-#endif
misc_deregister(&i2o_miscdev);
- i2o_driver_unregister(&i2o_config_driver);
}
MODULE_AUTHOR("Red Hat Software");
-MODULE_DESCRIPTION("I2O Configuration");
-MODULE_LICENSE("GPL");
-
-module_init(i2o_config_init);
-module_exit(i2o_config_exit);