patch-2.4.5 linux/drivers/block/cpqarray.c
Next file: linux/drivers/block/cpqarray.h
Previous file: linux/drivers/block/cciss_cmd.h
Back to the patch index
Back to the overall index
- Lines: 446
- Date:
Tue May 22 10:23:16 2001
- Orig file:
v2.4.4/linux/drivers/block/cpqarray.c
- Orig date:
Tue Feb 13 14:13:43 2001
diff -u --recursive --new-file v2.4.4/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
@@ -44,8 +44,8 @@
#define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.2)"
-#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,2)
+#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.4)"
+#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,4)
/* Embedded module documentation macros - see modules.h */
/* Original author Chris Frantz - Compaq Computer Corporation */
@@ -68,6 +68,8 @@
#define MAX_CTLR 8
#define CTLR_SHIFT 8
+#define CPQARRAY_DMA_MASK 0xFFFFFFFF /* 32 bit DMA */
+
static int nr_ctlr;
static ctlr_info_t *hba[MAX_CTLR];
@@ -123,8 +125,8 @@
static void getgeometry(int ctlr);
static void start_fwbk(int ctlr);
-static cmdlist_t * cmd_alloc(ctlr_info_t *h);
-static void cmd_free(ctlr_info_t *h, cmdlist_t *c);
+static cmdlist_t * cmd_alloc(ctlr_info_t *h, int get_from_pool);
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c, int got_from_pool);
static int sendcmd(
__u8 cmd,
@@ -204,7 +206,7 @@
static void __init ida_procinit(int i)
{
if (proc_array == NULL) {
- proc_array = proc_mkdir("driver/array", NULL);
+ proc_array = proc_mkdir("array", proc_root_driver);
if (!proc_array) return;
}
@@ -228,12 +230,12 @@
ctlr = h->ctlr;
size = sprintf(buffer, "%s: Compaq %s Controller\n"
- " Board ID: %08lx\n"
+ " Board ID: 0x%08lx\n"
" Firmware Revision: %c%c%c%c\n"
- " Controller Sig: %08lx\n"
- " Memory Address: %08lx\n"
- " I/O Port: %04x\n"
- " IRQ: %x\n"
+ " Controller Sig: 0x%08lx\n"
+ " Memory Address: 0x%08lx\n"
+ " I/O Port: 0x%04x\n"
+ " IRQ: %d\n"
" Logical drives: %d\n"
" Physical drives: %d\n\n"
" Current Q depth: %d\n"
@@ -314,7 +316,7 @@
int i;
struct gendisk *g;
- remove_proc_entry("driver/array", NULL);
+ remove_proc_entry("array", proc_root_driver);
for(i=0; i<nr_ctlr; i++) {
hba[i]->access.set_intr_mask(hba[i], 0);
@@ -324,7 +326,9 @@
del_timer(&hba[i]->timer);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i));
remove_proc_entry(hba[i]->devname, proc_array);
- kfree(hba[i]->cmd_pool);
+ pci_free_consistent(hba[i]->pci_dev,
+ NR_CMDS * sizeof(cmdlist_t), (hba[i]->cmd_pool),
+ hba[i]->cmd_pool_dhandle);
kfree(hba[i]->cmd_pool_bits);
if (gendisk_head == &ida_gendisk[i]) {
@@ -474,8 +478,9 @@
continue;
}
num_cntlrs_reg++;
- hba[i]->cmd_pool = (cmdlist_t *)kmalloc(
- NR_CMDS * sizeof(cmdlist_t), GFP_KERNEL);
+ hba[i]->cmd_pool = (cmdlist_t *)pci_alloc_consistent(
+ hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t),
+ &(hba[i]->cmd_pool_dhandle));
hba[i]->cmd_pool_bits = (__u32*)kmalloc(
((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
@@ -485,7 +490,10 @@
if(hba[i]->cmd_pool_bits)
kfree(hba[i]->cmd_pool_bits);
if(hba[i]->cmd_pool)
- kfree(hba[i]->cmd_pool);
+ pci_free_consistent(hba[i]->pci_dev,
+ NR_CMDS * sizeof(cmdlist_t),
+ hba[i]->cmd_pool,
+ hba[i]->cmd_pool_dhandle);
free_irq(hba[i]->intr, hba[i]);
unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
num_cntlrs_reg--;
@@ -580,9 +588,11 @@
pdev = pci_find_device(ida_vendor_id[brdtype],
ida_device_id[brdtype], NULL);
while (pdev) {
- printk(KERN_DEBUG "cpqarray: Device %x has been found at %x %x\n",
+ printk(KERN_DEBUG "cpqarray: Device 0x%x has"
+ " been found at bus %d dev %d func %d\n",
ida_vendor_id[brdtype],
- pdev->bus->number, pdev->devfn);
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn));
if (nr_ctlr == 8) {
printk(KERN_WARNING "cpqarray: This driver"
" supports a maximum of 8 controllers.\n");
@@ -647,7 +657,15 @@
addr[i] = pci_resource_start(pdev, i);
if (pci_enable_device(pdev))
+ {
+ printk(KERN_ERR "cpqarray: Unable to Enable PCI device\n");
+ return -1;
+ }
+ if (pci_set_dma_mask(pdev, CPQARRAY_DMA_MASK) != 0)
+ {
+ printk(KERN_ERR "cpqarray: Unable to set DMA mask\n");
return -1;
+ }
pci_read_config_word(pdev, PCI_COMMAND, &command);
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
@@ -905,7 +923,12 @@
struct list_head * queue_head = &q->queue_head;
struct buffer_head *bh;
struct request *creq;
+ struct my_sg tmp_sg[SG_MAX];
+ int i;
+// Loop till the queue is empty if or it is plugged
+ while (1)
+{
if (q->plugged || list_empty(queue_head)) {
start_io(h);
return;
@@ -925,7 +948,7 @@
return;
}
- if ((c = cmd_alloc(h)) == NULL)
+ if ((c = cmd_alloc(h,1)) == NULL)
{
start_io(h);
return;
@@ -951,18 +974,28 @@
while(bh) {
sect += bh->b_size/512;
if (bh->b_data == lastdataend) {
- c->req.sg[seg-1].size += bh->b_size;
+ tmp_sg[seg-1].size += bh->b_size;
lastdataend += bh->b_size;
} else {
if (seg == SG_MAX)
BUG();
- c->req.sg[seg].size = bh->b_size;
- c->req.sg[seg].addr = (__u32)virt_to_bus(bh->b_data);
+ tmp_sg[seg].size = bh->b_size;
+ tmp_sg[seg].start_addr = bh->b_data;
lastdataend = bh->b_data + bh->b_size;
seg++;
}
bh = bh->b_reqnext;
}
+ /* Now do all the DMA Mappings */
+ for( i=0; i < seg; i++)
+ {
+ c->req.sg[i].size = tmp_sg[i].size;
+ c->req.sg[i].addr = (__u32) pci_map_single(
+ h->pci_dev, tmp_sg[i].start_addr,
+ tmp_sg[i].size,
+ (creq->cmd == READ) ?
+ PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+ }
DBGPX( printk("Submitting %d sectors in %d segments\n", sect, seg); );
c->req.hdr.sg_cnt = seg;
c->req.hdr.blk_cnt = sect;
@@ -993,8 +1026,7 @@
h->Qdepth++;
if (h->Qdepth > h->maxQsinceinit)
h->maxQsinceinit = h->Qdepth;
-
- start_io(h);
+ } // while loop
}
/*
@@ -1043,6 +1075,7 @@
static inline void complete_command(cmdlist_t *cmd, int timeout)
{
int ok=1;
+ int i;
if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
(hba[cmd->ctlr]->misc_tflags & MISC_NONFATAL_WARN) == 0) {
@@ -1063,6 +1096,13 @@
ok = 0;
}
if (timeout) ok = 0;
+ /* unmap the DMA mapping for all the scatter gather elements */
+ for(i=0; i<cmd->req.hdr.sg_cnt; i++)
+ {
+ pci_unmap_single(hba[cmd->ctlr]->pci_dev,
+ cmd->req.sg[i].addr, cmd->req.sg[i].size,
+ (cmd->req.hdr.cmd == IDA_READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+ }
complete_buffers(cmd->bh, ok);
}
@@ -1110,7 +1150,7 @@
removeQ(&h->cmpQ, c);
if (c->type == CMD_RWREQ) {
complete_command(c, 0);
- cmd_free(h, c);
+ cmd_free(h, c, 1);
} else if (c->type == CMD_IOCTL_PEND) {
c->type = CMD_IOCTL_DONE;
}
@@ -1243,7 +1283,7 @@
unsigned long flags;
int error;
- if ((c = cmd_alloc(NULL)) == NULL)
+ if ((c = cmd_alloc(h, 0)) == NULL)
return -ENOMEM;
c->ctlr = ctlr;
c->hdr.unit = (io->unit & UNITVALID) ? (io->unit & ~UNITVALID) : dsk;
@@ -1262,13 +1302,16 @@
if (!p)
{
error = -ENOMEM;
- cmd_free(NULL, c);
+ cmd_free(h, c, 0);
return(error);
}
copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
- c->req.hdr.blk = virt_to_bus(&(io->c));
+ c->req.hdr.blk = pci_map_single(h->pci_dev, &(io->c),
+ sizeof(ida_ioctl_t),
+ PCI_DMA_BIDIRECTIONAL);
c->req.sg[0].size = io->sg[0].size;
- c->req.sg[0].addr = virt_to_bus(p);
+ c->req.sg[0].addr = pci_map_single(h->pci_dev, p,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
c->req.hdr.sg_cnt = 1;
break;
case IDA_READ:
@@ -1276,12 +1319,13 @@
if (!p)
{
error = -ENOMEM;
- cmd_free(NULL, c);
+ cmd_free(h, c, 0);
return(error);
}
c->req.sg[0].size = io->sg[0].size;
- c->req.sg[0].addr = virt_to_bus(p);
+ c->req.sg[0].addr = pci_map_single(h->pci_dev, p,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
c->req.hdr.sg_cnt = 1;
break;
case IDA_WRITE:
@@ -1291,20 +1335,22 @@
if (!p)
{
error = -ENOMEM;
- cmd_free(NULL, c);
+ cmd_free(h, c, 0);
return(error);
}
copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
c->req.sg[0].size = io->sg[0].size;
- c->req.sg[0].addr = virt_to_bus(p);
+ c->req.sg[0].addr = pci_map_single(h->pci_dev, p,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
c->req.hdr.sg_cnt = 1;
break;
default:
c->req.sg[0].size = sizeof(io->c);
- c->req.sg[0].addr = virt_to_bus(&io->c);
+ c->req.sg[0].addr = pci_map_single(h->pci_dev,&io->c,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
c->req.hdr.sg_cnt = 1;
}
-
+
/* Put the request on the tail of the request queue */
spin_lock_irqsave(&io_request_lock, flags);
addQ(&h->reqQ, c);
@@ -1316,9 +1362,15 @@
while(c->type != CMD_IOCTL_DONE)
schedule();
+ /* Unmap the DMA */
+ pci_unmap_single(h->pci_dev, c->req.sg[0].addr, c->req.sg[0].size,
+ PCI_DMA_BIDIRECTIONAL);
/* Post submit processing */
switch(io->cmd) {
case PASSTHRU_A:
+ pci_unmap_single(h->pci_dev, c->req.hdr.blk,
+ sizeof(ida_ioctl_t),
+ PCI_DMA_BIDIRECTIONAL);
case IDA_READ:
case DIAG_PASS_THRU:
copy_to_user((void*)io->sg[0].addr, p, io->sg[0].size);
@@ -1332,7 +1384,7 @@
}
io->rcode = c->req.hdr.rcode;
- cmd_free(NULL, c);
+ cmd_free(h, c, 0);
return(0);
}
@@ -1342,13 +1394,15 @@
* critical (and can wait for kmalloc and possibly sleep) can pass in NULL
* as the first argument to get a new command.
*/
-static cmdlist_t * cmd_alloc(ctlr_info_t *h)
+static cmdlist_t * cmd_alloc(ctlr_info_t *h, int get_from_pool)
{
cmdlist_t * c;
int i;
+ dma_addr_t cmd_dhandle;
- if (h == NULL) {
- c = (cmdlist_t*)kmalloc(sizeof(cmdlist_t), GFP_KERNEL);
+ if (!get_from_pool) {
+ c = (cmdlist_t*)pci_alloc_consistent(h->pci_dev,
+ sizeof(cmdlist_t), &cmd_dhandle);
if(c==NULL)
return NULL;
} else {
@@ -1358,20 +1412,22 @@
return NULL;
} while(test_and_set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0);
c = h->cmd_pool + i;
+ cmd_dhandle = h->cmd_pool_dhandle + i*sizeof(cmdlist_t);
h->nr_allocs++;
}
memset(c, 0, sizeof(cmdlist_t));
- c->busaddr = virt_to_bus(c);
+ c->busaddr = cmd_dhandle;
return c;
}
-static void cmd_free(ctlr_info_t *h, cmdlist_t *c)
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c, int got_from_pool)
{
int i;
- if (h == NULL) {
- kfree(c);
+ if (!got_from_pool) {
+ pci_free_consistent(h->pci_dev, sizeof(cmdlist_t), c,
+ c->busaddr);
} else {
i = c - h->cmd_pool;
clear_bit(i%32, h->cmd_pool_bits+(i/32));
@@ -1400,7 +1456,7 @@
unsigned long i;
ctlr_info_t *info_p = hba[ctlr];
- c = cmd_alloc(info_p);
+ c = cmd_alloc(info_p, 1);
if(!c)
return IO_ERROR;
c->ctlr = ctlr;
@@ -1424,7 +1480,8 @@
c->req.hdr.blk = blk;
c->req.hdr.blk_cnt = blkcnt;
c->req.hdr.cmd = (unsigned char) cmd;
- c->req.sg[0].addr = (__u32) virt_to_bus(buff);
+ c->req.sg[0].addr = (__u32) pci_map_single(info_p->pci_dev,
+ buff, c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
/*
* Disable interrupt
*/
@@ -1447,13 +1504,16 @@
*/
info_p->access.submit_command(info_p, c);
complete = pollcomplete(ctlr);
+
+ pci_unmap_single(info_p->pci_dev, (dma_addr_t) c->req.sg[0].addr,
+ c->req.sg[0].size, PCI_DMA_BIDIRECTIONAL);
if (complete != 1) {
if (complete != c->busaddr) {
printk( KERN_WARNING
"cpqarray ida%d: idaSendPciCmd "
"Invalid command list address returned! (%08lx)\n",
ctlr, (unsigned long)complete);
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_ERROR);
}
} else {
@@ -1461,7 +1521,7 @@
"cpqarray ida%d: idaSendPciCmd Timeout out, "
"No command list address returned!\n",
ctlr);
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_ERROR);
}
@@ -1473,11 +1533,11 @@
"cmd: 0x%x, return code = 0x%x\n",
ctlr, c->req.hdr.cmd, c->req.hdr.rcode);
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_ERROR);
}
}
- cmd_free(info_p, c);
+ cmd_free(info_p, c, 1);
return (IO_OK);
}
@@ -1574,13 +1634,9 @@
max_p = gdev->max_p;
start = target << gdev->minor_shift;
- for(i=max_p; i>=0; i--) {
+ for(i=max_p-1; i>=0; i--) {
int minor = start+i;
- kdev_t devi = MKDEV(MAJOR_NR + ctlr, minor);
- struct super_block *sb = get_super(devi);
- sync_dev(devi);
- if (sb) invalidate_inodes(sb);
- invalidate_buffers(devi);
+ invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1);
gdev->part[minor].start_sect = 0;
gdev->part[minor].nr_sects = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)