diff options
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 91 |
1 files changed, 53 insertions, 38 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 05dfe357527..65a725cd342 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1291,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; @@ -1306,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]); @@ -1432,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"); @@ -1908,6 +1915,7 @@ 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]; @@ -1917,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"); @@ -1953,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; } @@ -1989,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; } @@ -3119,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; @@ -3395,7 +3405,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, 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; @@ -3413,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]); @@ -3433,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); @@ -3472,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, }; /* |