]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/block/cciss.c
[PATCH] i386: pte clear optimization
[linux-2.6-omap-h63xx.git] / drivers / block / cciss.c
index 335e218b6dccc2b00190ab275bc81e1d5a0ef084..65a725cd3422ec565d9508de378d32cb9c52ffd5 100644 (file)
@@ -225,6 +225,8 @@ static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
 
 #include "cciss_scsi.c"                /* For SCSI tape support */
 
+#define RAID_UNKNOWN 6
+
 #ifdef CONFIG_PROC_FS
 
 /*
@@ -232,7 +234,6 @@ static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
  */
 #define ENG_GIG 1000000000
 #define ENG_GIG_FACTOR (ENG_GIG/512)
-#define RAID_UNKNOWN 6
 static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
        "UNKNOWN"
 };
@@ -1039,7 +1040,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                                status = -ENOMEM;
                                goto cleanup1;
                        }
-                       buff_size = (int *)kmalloc(MAXSGENTRIES * sizeof(int),
+                       buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
                                                   GFP_KERNEL);
                        if (!buff_size) {
                                status = -ENOMEM;
@@ -1290,13 +1291,19 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
        if (inq_buff == NULL)
                goto mem_msg;
 
+       /* testing to see if 16-byte CDBs are already being used */
+       if (h->cciss_read == CCISS_READ_16) {
+               cciss_read_capacity_16(h->ctlr, drv_index, 1,
+                       &total_size, &block_size);
+               goto geo_inq;
+       }
+
        cciss_read_capacity(ctlr, drv_index, 1,
                            &total_size, &block_size);
 
-       /* total size = last LBA + 1 */
-       /* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */
-       /* so we assume this volume this must be >2TB in size */
-       if (total_size == (__u32) 0) {
+       /* if read_capacity returns all F's this volume is >2TB in size */
+       /* so we switch to 16-byte CDB's for all read/write ops */
+       if (total_size == 0xFFFFFFFFULL) {
                cciss_read_capacity_16(ctlr, drv_index, 1,
                &total_size, &block_size);
                h->cciss_read = CCISS_READ_16;
@@ -1305,6 +1312,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
                h->cciss_read = CCISS_READ_10;
                h->cciss_write = CCISS_WRITE_10;
        }
+geo_inq:
        cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
                               inq_buff, &h->drv[drv_index]);
 
@@ -1431,7 +1439,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
 
                if (return_code == IO_OK) {
                        listlength =
-                               be32_to_cpu(*(__u32 *) ld_buff->LUNListLength);
+                               be32_to_cpu(*(__be32 *) ld_buff->LUNListLength);
                } else {        /* reading number of logical volumes failed */
                        printk(KERN_WARNING "cciss: report logical volume"
                               " command failed\n");
@@ -1907,6 +1915,8 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
                               "does not support reading geometry\n");
                        drv->heads = 255;
                        drv->sectors = 32;      // Sectors per track
+                       drv->cylinders = total_size + 1;
+                       drv->raid_level = RAID_UNKNOWN;
                } else {
                        drv->heads = inq_buff->data_byte[6];
                        drv->sectors = inq_buff->data_byte[7];
@@ -1915,13 +1925,14 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
                        drv->raid_level = inq_buff->data_byte[8];
                }
                drv->block_size = block_size;
-               drv->nr_blocks = total_size;
+               drv->nr_blocks = total_size + 1;
                t = drv->heads * drv->sectors;
                if (t > 1) {
-                       unsigned rem = sector_div(total_size, t);
+                       sector_t real_size = total_size + 1;
+                       unsigned long rem = sector_div(real_size, t);
                        if (rem)
-                               total_size++;
-                       drv->cylinders = total_size;
+                               real_size++;
+                       drv->cylinders = real_size;
                }
        } else {                /* Get geometry failed */
                printk(KERN_WARNING "cciss: reading geometry failed\n");
@@ -1951,16 +1962,16 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
                                ctlr, buf, sizeof(ReadCapdata_struct),
                                        1, logvol, 0, NULL, TYPE_CMD);
        if (return_code == IO_OK) {
-               *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1;
-               *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
+               *total_size = be32_to_cpu(*(__be32 *) buf->total_size);
+               *block_size = be32_to_cpu(*(__be32 *) buf->block_size);
        } else {                /* read capacity command failed */
                printk(KERN_WARNING "cciss: read capacity failed\n");
                *total_size = 0;
                *block_size = BLOCK_SIZE;
        }
-       if (*total_size != (__u32) 0)
+       if (*total_size != 0)
                printk(KERN_INFO "      blocks= %llu block_size= %d\n",
-               (unsigned long long)*total_size, *block_size);
+               (unsigned long long)*total_size+1, *block_size);
        kfree(buf);
        return;
 }
@@ -1987,15 +1998,15 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size,
                                1, logvol, 0, NULL, TYPE_CMD);
        }
        if (return_code == IO_OK) {
-               *total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1;
-               *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
+               *total_size = be64_to_cpu(*(__be64 *) buf->total_size);
+               *block_size = be32_to_cpu(*(__be32 *) buf->block_size);
        } else {                /* read capacity command failed */
                printk(KERN_WARNING "cciss: read capacity failed\n");
                *total_size = 0;
                *block_size = BLOCK_SIZE;
        }
        printk(KERN_INFO "      blocks= %llu block_size= %d\n",
-              (unsigned long long)*total_size, *block_size);
+              (unsigned long long)*total_size+1, *block_size);
        kfree(buf);
        return;
 }
@@ -2491,7 +2502,7 @@ static void do_cciss_request(request_queue_t *q)
        c->Request.Type.Type = TYPE_CMD;        // It is a command.
        c->Request.Type.Attribute = ATTR_SIMPLE;
        c->Request.Type.Direction =
-           (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
+           (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE;
        c->Request.Timeout = 0; // Don't time out
        c->Request.CDB[0] =
            (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
@@ -2837,7 +2848,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        if (err) {
                printk(KERN_ERR "cciss: Cannot obtain PCI resources, "
                       "aborting\n");
-               goto err_out_disable_pdev;
+               return err;
        }
 
        subsystem_vendor_id = pdev->subsystem_vendor;
@@ -3004,10 +3015,13 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        }
        return 0;
 
-      err_out_free_res:
+err_out_free_res:
+       /*
+        * Deliberately omit pci_disable_device(): it does something nasty to
+        * Smart Array controllers that pci_enable_device does not undo
+        */
        pci_release_regions(pdev);
        return err;
-
 }
 
 /*
@@ -3114,8 +3128,9 @@ static void cciss_getgeometry(int cntl_num)
                }
                cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size);
 
-               /* total_size = last LBA + 1 */
-               if(total_size == (__u32) 0) {
+               /* If read_capacity returns all F's the logical is >2TB */
+               /* so we switch to 16-byte CDBs for all read/write ops */
+               if(total_size == 0xFFFFFFFFULL) {
                        cciss_read_capacity_16(cntl_num, i, 0,
                        &total_size, &block_size);
                        hba[cntl_num]->cciss_read = CCISS_READ_16;
@@ -3380,13 +3395,17 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
                if (drv->queue)
                        blk_cleanup_queue(drv->queue);
        }
+       /*
+        * Deliberately omit pci_disable_device(): it does something nasty to
+        * Smart Array controllers that pci_enable_device does not undo
+        */
        pci_release_regions(pdev);
        pci_set_drvdata(pdev, NULL);
        free_hba(i);
        return -1;
 }
 
-static void __devexit cciss_remove_one(struct pci_dev *pdev)
+static void cciss_remove_one(struct pci_dev *pdev)
 {
        ctlr_info_t *tmp_ptr;
        int i, j;
@@ -3404,15 +3423,35 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
                       "already be removed \n");
                return;
        }
+
+       remove_proc_entry(hba[i]->devname, proc_cciss);
+       unregister_blkdev(hba[i]->major, hba[i]->devname);
+
+       /* remove it from the disk list */
+       for (j = 0; j < CISS_MAX_LUN; j++) {
+               struct gendisk *disk = hba[i]->gendisk[j];
+               if (disk) {
+                       request_queue_t *q = disk->queue;
+
+                       if (disk->flags & GENHD_FL_UP)
+                               del_gendisk(disk);
+                       if (q)
+                               blk_cleanup_queue(q);
+               }
+       }
+
+       cciss_unregister_scsi(i);       /* unhook from SCSI subsystem */
+
        /* Turn board interrupts off  and send the flush cache command */
        /* sendcmd will turn off interrupt, and send the flush...
         * To write all data in the battery backed cache to disks */
        memset(flush_buf, 0, 4);
        return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
                              TYPE_CMD);
-       if (return_code != IO_OK) {
-               printk(KERN_WARNING "Error Flushing cache on controller %d\n",
-                      i);
+       if (return_code == IO_OK) {
+               printk(KERN_INFO "Completed flushing cache on controller %d\n", i);
+       } else {
+               printk(KERN_WARNING "Error flushing cache on controller %d\n", i);
        }
        free_irq(hba[i]->intr[2], hba[i]);
 
@@ -3424,22 +3463,6 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
 #endif                         /* CONFIG_PCI_MSI */
 
        iounmap(hba[i]->vaddr);
-       cciss_unregister_scsi(i);       /* unhook from SCSI subsystem */
-       unregister_blkdev(hba[i]->major, hba[i]->devname);
-       remove_proc_entry(hba[i]->devname, proc_cciss);
-
-       /* remove it from the disk list */
-       for (j = 0; j < CISS_MAX_LUN; j++) {
-               struct gendisk *disk = hba[i]->gendisk[j];
-               if (disk) {
-                       request_queue_t *q = disk->queue;
-
-                       if (disk->flags & GENHD_FL_UP)
-                               del_gendisk(disk);
-                       if (q)
-                               blk_cleanup_queue(q);
-               }
-       }
 
        pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(CommandList_struct),
                            hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
@@ -3449,6 +3472,10 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
 #ifdef CONFIG_CISS_SCSI_TAPE
        kfree(hba[i]->scsi_rejects.complete);
 #endif
+       /*
+        * Deliberately omit pci_disable_device(): it does something nasty to
+        * Smart Array controllers that pci_enable_device does not undo
+        */
        pci_release_regions(pdev);
        pci_set_drvdata(pdev, NULL);
        free_hba(i);
@@ -3459,6 +3486,7 @@ static struct pci_driver cciss_pci_driver = {
        .probe = cciss_init_one,
        .remove = __devexit_p(cciss_remove_one),
        .id_table = cciss_pci_device_id,        /* id_table */
+       .shutdown = cciss_remove_one,
 };
 
 /*