Commit 0bd4095a authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] bring i2o_block/i2o_scsi back to life

parent 4acc3931
......@@ -55,8 +55,6 @@
* Serial number scanning to find duplicates for FC multipathing
*/
#error Please convert me to Documentation/DMA-mapping.txt
#include <linux/major.h>
#include <linux/module.h>
......@@ -132,15 +130,12 @@
#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D
#define I2O_BSA_DSC_TIMEOUT 0x000E
#define I2O_UNIT(dev) (i2ob_dev[minor((dev)) & 0xf0])
#define I2O_LOCK(unit) (i2ob_dev[(unit)].req_queue->queue_lock)
/*
* Some of these can be made smaller later
*/
static int i2ob_blksizes[MAX_I2OB<<4];
static int i2ob_sizes[MAX_I2OB<<4];
static int i2ob_media_change_flag[MAX_I2OB];
static u32 i2ob_max_sectors[MAX_I2OB<<4];
......@@ -166,6 +161,7 @@ struct i2ob_device
int rcache;
int wcache;
int power;
int index;
};
/*
......@@ -179,6 +175,9 @@ struct i2ob_request
struct i2ob_request *next;
struct request *req;
int num;
int sg_dma_direction;
int sg_nents;
struct scatterlist sg_table[16];
};
/*
......@@ -260,6 +259,30 @@ static u32 i2ob_get(struct i2ob_device *dev)
return I2O_POST_READ32(c);
}
static int i2ob_build_sglist(struct i2ob_device *dev, struct i2ob_request *ireq)
{
struct scatterlist *sg = ireq->sg_table;
int nents;
nents = blk_rq_map_sg(dev->req_queue, ireq->req, ireq->sg_table);
if (rq_data_dir(ireq->req) == READ)
ireq->sg_dma_direction = PCI_DMA_FROMDEVICE;
else
ireq->sg_dma_direction = PCI_DMA_TODEVICE;
ireq->sg_nents = pci_map_sg(dev->controller->pdev, sg, nents, ireq->sg_dma_direction);
return ireq->sg_nents;
}
void i2ob_free_sglist(struct i2ob_device *dev, struct i2ob_request *ireq)
{
struct pci_dev *pdev = dev->controller->pdev;
struct scatterlist *sg = ireq->sg_table;
int nents = ireq->sg_nents;
pci_unmap_sg(pdev, sg, nents, ireq->sg_dma_direction);
}
/**
* i2ob_send - Turn a request into a message and send it
* @m: Message offset
......@@ -273,8 +296,6 @@ static u32 i2ob_get(struct i2ob_device *dev)
*
* No cleanup is done by this interface. It is done on the interrupt side when the
* reply arrives
*
* To Fix: Generate PCI maps of the buffers
*/
static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, int unit)
......@@ -285,15 +306,21 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
unsigned long mptr;
u64 offset;
struct request *req = ireq->req;
struct bio *bio = req->bio;
int count = req->nr_sectors<<9;
unsigned long last = 0;
unsigned short size = 0;
struct scatterlist *sg;
int sgnum;
int i;
// printk(KERN_INFO "i2ob_send called\n");
/* Map the message to a virtual address */
msg = c->mem_offset + m;
sgnum = i2ob_build_sglist(dev, ireq);
/* FIXME: if we have no resources how should we get out of this */
if(sgnum == 0)
BUG();
/*
* Build the message based on the request.
*/
......@@ -313,34 +340,21 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
i2o_raw_writel(offset>>32, msg+28);
mptr=msg+32;
if(req->cmd == READ)
sg = ireq->sg_table;
if(rq_data_dir(req) == READ)
{
DEBUG("READ\n");
i2o_raw_writel(I2O_CMD_BLOCK_READ<<24|HOST_TID<<12|tid, msg+4);
while(bio!=NULL)
for(i = sgnum; i > 0; i--)
{
if(bio_to_phys(bio) == last) {
size += bio->bi_size;
last += bio->bi_size;
if(bio->bi_next)
i2o_raw_writel(0x10000000|(size), mptr-8);
if(i != 1)
i2o_raw_writel(0x10000000|sg_dma_len(sg), mptr);
else
__raw_writel(0xD0000000|(size), mptr-8);
}
else
{
if(bio->bi_next)
i2o_raw_writel(0x10000000|bio->bi_size, mptr);
else
i2o_raw_writel(0xD0000000|bio->bi_size, mptr);
i2o_raw_writel(bio_to_phys(bio), mptr+4);
i2o_raw_writel(0xD0000000|sg_dma_len(sg), mptr);
i2o_raw_writel(sg_dma_address(sg), mptr+4);
mptr += 8;
size = bio->bi_size;
last = bio_to_phys(bio) + size;
}
count -= bio->bi_size;
bio = bio->bi_next;
count -= sg_dma_len(sg);
sg++;
}
switch(dev->rcache)
{
......@@ -359,34 +373,20 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
// printk("Reading %d entries %d bytes.\n",
// mptr-msg-8, req->nr_sectors<<9);
}
else if(req->cmd == WRITE)
else if(rq_data_dir(req) == WRITE)
{
DEBUG("WRITE\n");
i2o_raw_writel(I2O_CMD_BLOCK_WRITE<<24|HOST_TID<<12|tid, msg+4);
while(bio!=NULL)
{
if(bio_to_phys(bio) == last) {
size += bio->bi_size;
last += bio->bi_size;
if(bio->bi_next)
i2o_raw_writel(0x14000000|(size), mptr-8);
else
i2o_raw_writel(0xD4000000|(size), mptr-8);
}
else
for(i = sgnum; i > 0; i--)
{
if(bio->bi_next)
i2o_raw_writel(0x14000000|(bio->bi_size), mptr);
if(i != 1)
i2o_raw_writel(0x14000000|sg_dma_len(sg), mptr);
else
i2o_raw_writel(0xD4000000|(bio->bi_size), mptr);
i2o_raw_writel(bio_to_phys(bio), mptr+4);
i2o_raw_writel(0xD4000000|sg_dma_len(sg), mptr);
i2o_raw_writel(sg_dma_address(sg), mptr+4);
mptr += 8;
size = bio->bi_size;
last = bio_to_phys(bio) + bio->bi_size;
}
count -= bio->bi_size;
bio = bio->bi_next;
count -= sg_dma_len(sg);
sg++;
}
switch(dev->wcache)
......@@ -502,7 +502,7 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
/* Now flush the message by making it a NOP */
m[0]&=0x00FFFFFF;
m[0]|=(I2O_CMD_UTIL_NOP)<<24;
i2o_post_message(c,virt_to_bus(m));
i2o_post_message(c, ((unsigned long)m) - c->mem_offset);
return;
}
......@@ -594,6 +594,7 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
* may be running polled controllers from a BH...
*/
i2ob_free_sglist(dev, ireq);
spin_lock_irqsave(I2O_LOCK(c->unit), flags);
i2ob_unhook_request(ireq, c->unit);
i2ob_end_request(ireq->req);
......@@ -715,7 +716,6 @@ static int i2ob_evt(void *dummy)
i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8);
spin_lock_irqsave(I2O_LOCK(unit), flags);
i2ob_sizes[unit] = (int)(size>>10);
set_capacity(i2ob_disk[unit>>4], size>>9);
spin_unlock_irqrestore(I2O_LOCK(unit), flags);
break;
......@@ -782,7 +782,6 @@ static void i2ob_request(request_queue_t *q)
{
struct request *req;
struct i2ob_request *ireq;
int unit;
struct i2ob_device *dev;
u32 m;
......@@ -797,8 +796,7 @@ static void i2ob_request(request_queue_t *q)
if(req->rq_status == RQ_INACTIVE)
return;
unit = minor(req->rq_dev);
dev = &i2ob_dev[(unit&0xF0)];
dev = req->rq_disk->private_data;
/*
* Queue depths probably belong with some kind of
......@@ -828,7 +826,7 @@ static void i2ob_request(request_queue_t *q)
i2ob_queues[dev->unit]->i2ob_qhead = ireq->next;
ireq->req = req;
i2ob_send(m, dev, ireq, (unit&0xF0));
i2ob_send(m, dev, ireq, (dev->unit&0xF0));
}
}
......@@ -896,26 +894,18 @@ static void i2o_block_biosparam(
static int i2ob_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct i2ob_device *dev;
int minor;
struct gendisk *disk = inode->i_bdev->bd_disk;
struct i2ob_device *dev = disk->private_data;
/* Anyone capable of this syscall can do *real bad* things */
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (!inode)
return -EINVAL;
minor = minor(inode->i_rdev);
if (minor >= (MAX_I2OB<<4))
return -ENODEV;
dev = &i2ob_dev[minor];
switch (cmd) {
case HDIO_GETGEO:
{
struct hd_geometry g;
int u=minor >> 4;
i2o_block_biosparam(get_capacity(i2ob_disk[u]),
i2o_block_biosparam(get_capacity(disk),
&g.cylinders, &g.heads, &g.sectors);
g.start = get_start_sect(inode->i_bdev);
return copy_to_user((void *)arg,&g, sizeof(g))?-EFAULT:0;
......@@ -945,13 +935,8 @@ static int i2ob_ioctl(struct inode *inode, struct file *file,
static int i2ob_release(struct inode *inode, struct file *file)
{
struct i2ob_device *dev;
int minor;
minor = minor(inode->i_rdev);
if (minor >= (MAX_I2OB<<4))
return -ENODEV;
dev = &i2ob_dev[(minor&0xF0)];
struct gendisk *disk = inode->i_bdev->bd_disk;
struct i2ob_device *dev = disk->private_data;
/*
* This is to deail with the case of an application
......@@ -1022,15 +1007,8 @@ static int i2ob_release(struct inode *inode, struct file *file)
static int i2ob_open(struct inode *inode, struct file *file)
{
int minor;
struct i2ob_device *dev;
if (!inode)
return -EINVAL;
minor = minor(inode->i_rdev);
if (minor >= MAX_I2OB<<4)
return -ENODEV;
dev=&i2ob_dev[(minor&0xF0)];
struct gendisk *disk = inode->i_bdev->bd_disk;
struct i2ob_device *dev = disk->private_data;
if(!dev->i2odev)
return -ENODEV;
......@@ -1133,7 +1111,6 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
power = 0;
i2ob_query_device(dev, 0x0000, 5, &flags, 4);
i2ob_query_device(dev, 0x0000, 6, &status, 4);
i2ob_sizes[unit] = (int)(size>>10);
set_capacity(i2ob_disk[unit>>4], size>>9);
/*
......@@ -1146,14 +1123,18 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
for(i=unit;i<=unit+15;i++)
{
request_queue_t *q = i2ob_dev[unit].req_queue;
int segments = (d->controller->status_block->inbound_frame_size - 7) / 2;
if(segments > 16)
segments = 16;
i2ob_dev[i].power = power; /* Save power state */
i2ob_dev[unit].flags = flags; /* Keep the type info */
blk_queue_max_sectors(q, 96); /* 256 might be nicer but many controllers
explode on 65536 or higher */
blk_queue_max_phys_segments(q, (d->controller->status_block->inbound_frame_size - 7) / 2);
blk_queue_max_hw_segments(q, (d->controller->status_block->inbound_frame_size - 7) / 2);
blk_queue_max_phys_segments(q, segments);
blk_queue_max_hw_segments(q, segments);
i2ob_dev[i].rcache = CACHE_SMARTFETCH;
i2ob_dev[i].wcache = CACHE_WRITETHROUGH;
......@@ -1372,7 +1353,7 @@ static void i2ob_scan(int bios)
printk(KERN_WARNING "Could not install I2O block device\n");
else
{
add_disk(i2o_disk[scan_unit>>4]);
add_disk(i2ob_disk[scan_unit>>4]);
scan_unit+=16;
i2ob_dev_count++;
......@@ -1459,7 +1440,7 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d)
printk(KERN_ERR "i2o_block: Could not install new device\n");
else
{
add_disk(i2o_disk[unit>>4]);
add_disk(i2ob_disk[unit>>4]);
i2ob_dev_count++;
i2o_device_notify_on(d, &i2o_block_handler);
}
......@@ -1544,7 +1525,8 @@ void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
*/
static int i2ob_media_change(struct gendisk *disk)
{
int i = (int)disk->private_data;
struct i2ob_device *p = disk->private_data;
int i = p->index;
if(i2ob_media_change_flag[i])
{
i2ob_media_change_flag[i]=0;
......@@ -1555,9 +1537,8 @@ static int i2ob_media_change(struct gendisk *disk)
static int i2ob_revalidate(struct gendisk *disk)
{
int i = (int)disk->private_data;
return i2ob_install_device(i2ob_dev[i<<4].controller,
i2ob_dev[i<<4].i2odev, i<<4);
struct i2ob_device *p = disk->private_data;
return i2ob_install_device(p->controller, p->i2odev, p->index<<4);
}
/*
......@@ -1640,10 +1621,9 @@ static int i2o_block_init(void)
struct gendisk *disk = alloc_disk(16);
if (!disk)
goto oom;
/* to be cleaned up */
disk->private_data = (void*)i;
i2ob_dev[i<<4].index = i;
disk->queue = i2ob_dev[i<<4].req_queue;
i2o_disk[i] = disk;
i2ob_disk[i] = disk;
}
#ifdef MODULE
printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR);
......@@ -1662,12 +1642,11 @@ static int i2o_block_init(void)
i2ob_dev[i].head = NULL;
i2ob_dev[i].tail = NULL;
i2ob_dev[i].depth = MAX_I2OB_DEPTH;
i2ob_blksizes[i] = 1024;
i2ob_max_sectors[i] = 2;
}
for (i = 0; i < MAX_I2OB; i++) {
struct gendisk *disk = i2ob_disk + i;
struct gendisk *disk = i2ob_disk[i];
disk->major = MAJOR_NR;
disk->first_minor = i<<4;
disk->fops = &i2ob_fops;
......@@ -1715,7 +1694,7 @@ static int i2o_block_init(void)
oom:
while (i--)
put_disk(i2o_disk[i]);
put_disk(i2ob_disk[i]);
unregister_blkdev(MAJOR_NR, "i2o_block");
return -ENOMEM;
}
......@@ -1769,7 +1748,7 @@ static void i2o_block_exit(void)
i2o_remove_handler(&i2o_block_handler);
for (i = 0; i < MAX_I2OB; i++)
put_disk(i2o_disk[i]);
put_disk(i2ob_disk[i]);
/*
* Return the block device
......
......@@ -37,7 +37,6 @@
* Fix the resource management problems.
*/
#error Please convert me to Documentation/DMA-mapping.txt
#include <linux/module.h>
#include <linux/kernel.h>
......@@ -55,17 +54,21 @@
#include <asm/io.h>
#include <asm/atomic.h>
#include <linux/blk.h>
#include <linux/version.h>
#include <linux/i2o.h>
#include "../../scsi/scsi.h"
#include "../../scsi/hosts.h"
#include "../../scsi/sd.h"
#include "i2o_scsi.h"
#define VERSION_STRING "Version 0.1.1"
#if BITS_PER_LONG == 64
#error FIXME: driver does not support 64-bit platforms
#endif
#define VERSION_STRING "Version 0.1.2"
#define dprintk(x)
#define I2O_SCSI_CAN_QUEUE 4
#define MAXHOSTS 32
struct i2o_scsi_host
......@@ -320,6 +323,12 @@ static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, stru
* It worked maybe ?
*/
current_command->result = DID_OK << 16 | ds;
if (current_command->use_sg)
pci_unmap_sg(c->pdev, (struct scatterlist *)current_command->buffer, current_command->use_sg, scsi_to_pci_dma_dir(current_command->sc_data_direction));
else if (current_command->request_bufflen)
pci_unmap_single(c->pdev, (dma_addr_t)((long)current_command->SCp.ptr), current_command->request_bufflen, scsi_to_pci_dma_dir(current_command->sc_data_direction));
lock = current_command->host->host_lock;
spin_lock_irqsave(lock, flags);
current_command->scsi_done(current_command);
......@@ -453,7 +462,6 @@ static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct
static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
{
unsigned long flags;
struct Scsi_Host *shpnt = NULL;
int i;
int count;
......@@ -681,6 +689,7 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
return 0;
}
i2o_raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]);
i2o_raw_writel(scsi_context, &msg[2]); /* So the I2O layer passes to us */
/* Sorry 64bit folks. FIXME */
......@@ -752,10 +761,18 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
if(SCpnt->use_sg)
{
struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer;
int sg_count;
int chain = 0;
len = 0;
sg_count = pci_map_sg(c->pdev, sg, SCpnt->use_sg,
scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
/* FIXME: handle fail */
if(!sg_count)
BUG();
if((sg_max_frags > 11) && (SCpnt->use_sg > 11))
{
chain = 1;
......@@ -775,27 +792,27 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
sg_chain_tag = 0;
for(i = 0 ; i < SCpnt->use_sg; i++)
{
*mptr++=direction|0x10000000|sg->length;
len+=sg->length;
*mptr++=virt_to_bus(page_address(sg->page)+sg->offset);
*mptr++=cpu_to_le32(direction|0x10000000|sg_dma_len(sg));
len+=sg_dma_len(sg);
*mptr++=cpu_to_le32(sg_dma_address(sg));
sg++;
}
mptr[-2]=direction|0xD0000000|(sg-1)->length;
mptr[-2]=cpu_to_le32(direction|0xD0000000|sg_dma_len(sg-1));
}
else
{
for(i = 0 ; i < SCpnt->use_sg; i++)
{
i2o_raw_writel(direction|0x10000000|sg->length, mptr++);
i2o_raw_writel(direction|0x10000000|sg_dma_len(sg), mptr++);
len+=sg->length;
i2o_raw_writel(virt_to_bus(page_address(sg->page) + sg->offset), mptr++);
i2o_raw_writel(sg_dma_address(sg), mptr++);
sg++;
}
/* Make this an end of list. Again evade the 920 bug and
unwanted PCI read traffic */
i2o_raw_writel(direction|0xD0000000|(sg-1)->length, &mptr[-2]);
i2o_raw_writel(direction|0xD0000000|sg_dma_len(sg-1), &mptr[-2]);
}
if(!chain)
......@@ -818,8 +835,16 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
}
else
{
dma_addr_t dma_addr;
dma_addr = pci_map_single(c->pdev,
SCpnt->request_buffer,
SCpnt->request_bufflen,
scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
if(dma_addr == 0)
BUG(); /* How to handle ?? */
SCpnt->SCp.ptr = (char *)(unsigned long) dma_addr;
i2o_raw_writel(0xD0000000|direction|SCpnt->request_bufflen, mptr++);
i2o_raw_writel(virt_to_bus(SCpnt->request_buffer), mptr++);
i2o_raw_writel(dma_addr, mptr++);
}
}
......@@ -1046,6 +1071,24 @@ MODULE_AUTHOR("Red Hat Software");
MODULE_LICENSE("GPL");
static Scsi_Host_Template driver_template = I2OSCSI;
static Scsi_Host_Template driver_template = {
.proc_name = "i2o_scsi",
.name = "I2O SCSI Layer",
.detect = i2o_scsi_detect,
.release = i2o_scsi_release,
.info = i2o_scsi_info,
.command = i2o_scsi_command,
.queuecommand = i2o_scsi_queuecommand,
.eh_abort_handler = i2o_scsi_abort,
.eh_bus_reset_handler = i2o_scsi_bus_reset,
.eh_device_reset_handler= i2o_scsi_device_reset,
.eh_host_reset_handler = i2o_scsi_host_reset,
.bios_param = i2o_scsi_bios_param,
.can_queue = I2O_SCSI_CAN_QUEUE,
.this_id = 15,
.sg_tablesize = 8,
.cmd_per_lun = 6,
.use_clustering = ENABLE_CLUSTERING,
};
#include "../../scsi/scsi_module.c"
#ifndef _I2O_SCSI_H
#define _I2O_SCSI_H
#include <linux/types.h>
#include <linux/kdev_t.h>
#define I2O_SCSI_ID 15
#define I2O_SCSI_CAN_QUEUE 4
#define I2O_SCSI_CMD_PER_LUN 6
static int i2o_scsi_detect(Scsi_Host_Template *);
static const char *i2o_scsi_info(struct Scsi_Host *);
static int i2o_scsi_command(Scsi_Cmnd *);
static int i2o_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int i2o_scsi_abort(Scsi_Cmnd *);
static int i2o_scsi_bus_reset(Scsi_Cmnd *);
static int i2o_scsi_host_reset(Scsi_Cmnd *);
static int i2o_scsi_device_reset(Scsi_Cmnd *);
static int i2o_scsi_bios_param(Disk *, struct block_device *, int *);
static int i2o_scsi_release(struct Scsi_Host *host);
#define I2OSCSI { \
next: NULL, \
proc_name: "i2o_scsi", \
name: "I2O SCSI Layer", \
detect: i2o_scsi_detect, \
release: i2o_scsi_release, \
info: i2o_scsi_info, \
command: i2o_scsi_command, \
queuecommand: i2o_scsi_queuecommand, \
eh_abort_handler: i2o_scsi_abort, \
eh_bus_reset_handler: i2o_scsi_bus_reset, \
eh_device_reset_handler: i2o_scsi_device_reset, \
eh_host_reset_handler: i2o_scsi_host_reset, \
bios_param: i2o_scsi_bios_param, \
can_queue: I2O_SCSI_CAN_QUEUE, \
this_id: I2O_SCSI_ID, \
sg_tablesize: 8, \
cmd_per_lun: I2O_SCSI_CMD_PER_LUN, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING \
}
#endif
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