]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/block/cciss.c
cciss: disable DMA refetch on Smart Array P600
[linux-2.6-omap-h63xx.git] / drivers / block / cciss.c
index 1be82d544dc3866d15f8819e3f1b2a5859152531..e330c26c5ad9c082b6f67c989cc44e36f1512167 100644 (file)
@@ -1191,10 +1191,9 @@ static inline void complete_buffers(struct bio *bio, int status)
 {
        while (bio) {
                struct bio *xbh = bio->bi_next;
-               int nr_sectors = bio_sectors(bio);
 
                bio->bi_next = NULL;
-               bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
+               bio_endio(bio, status ? 0 : -EIO);
                bio = xbh;
        }
 }
@@ -1977,12 +1976,13 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
 {
        ReadCapdata_struct *buf;
        int return_code;
-       buf = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
-       if (buf == NULL) {
+
+       buf = kzalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+       if (!buf) {
                printk(KERN_WARNING "cciss: out of memory\n");
                return;
        }
-       memset(buf, 0, sizeof(ReadCapdata_struct));
+
        if (withirq)
                return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
                                ctlr, buf, sizeof(ReadCapdata_struct),
@@ -2003,7 +2003,6 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
                printk(KERN_INFO "      blocks= %llu block_size= %d\n",
                (unsigned long long)*total_size+1, *block_size);
        kfree(buf);
-       return;
 }
 
 static void
@@ -2011,12 +2010,13 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,
 {
        ReadCapdata_struct_16 *buf;
        int return_code;
-       buf = kmalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL);
-       if (buf == NULL) {
+
+       buf = kzalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL);
+       if (!buf) {
                printk(KERN_WARNING "cciss: out of memory\n");
                return;
        }
-       memset(buf, 0, sizeof(ReadCapdata_struct_16));
+
        if (withirq) {
                return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
                        ctlr, buf, sizeof(ReadCapdata_struct_16),
@@ -2038,7 +2038,6 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,
        printk(KERN_INFO "      blocks= %llu block_size= %d\n",
               (unsigned long long)*total_size+1, *block_size);
        kfree(buf);
-       return;
 }
 
 static int cciss_revalidate(struct gendisk *disk)
@@ -2570,6 +2569,7 @@ static void do_cciss_request(struct request_queue *q)
               (int)creq->nr_sectors);
 #endif                         /* CCISS_DEBUG */
 
+       memset(tmp_sg, 0, sizeof(tmp_sg));
        seg = blk_rq_map_sg(q, creq, tmp_sg);
 
        /* get the DMA records for the setup */
@@ -3035,15 +3035,20 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        }
 #endif
 
-       /* Disabling DMA prefetch for the P600
-        * An ASIC bug may result in a prefetch beyond
-        * physical memory.
+       /* Disabling DMA prefetch and refetch for the P600.
+        * An ASIC bug may result in accesses to invalid memory addresses.
+        * We've disabled prefetch for some time now. Testing with XEN
+        * kernels revealed a bug in the refetch if dom0 resides on a P600.
         */
        if(board_id == 0x3225103C) {
                __u32 dma_prefetch;
+               __u32 dma_refetch;
                dma_prefetch = readl(c->vaddr + I2O_DMA1_CFG);
                dma_prefetch |= 0x8000;
                writel(dma_prefetch, c->vaddr + I2O_DMA1_CFG);
+               pci_read_config_dword(pdev, PCI_COMMAND_PARITY, &dma_refetch);
+               dma_refetch |= 0x1;
+               pci_write_config_dword(pdev, PCI_COMMAND_PARITY, dma_refetch);
        }
 
 #ifdef CCISS_DEBUG
@@ -3101,7 +3106,7 @@ static void cciss_getgeometry(int cntl_num)
        int i;
        int listlength = 0;
        __u32 lunid = 0;
-       int block_size;
+       unsigned block_size;
        sector_t total_size;
 
        ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
@@ -3227,12 +3232,15 @@ static int alloc_cciss_hba(void)
        for (i = 0; i < MAX_CTLR; i++) {
                if (!hba[i]) {
                        ctlr_info_t *p;
+
                        p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
                        if (!p)
                                goto Enomem;
                        p->gendisk[0] = alloc_disk(1 << NWD_SHIFT);
-                       if (!p->gendisk[0])
+                       if (!p->gendisk[0]) {
+                               kfree(p);
                                goto Enomem;
+                       }
                        hba[i] = p;
                        return i;
                }