aboutsummaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/DAC960.c4
-rw-r--r--drivers/block/DAC960.h2
-rw-r--r--drivers/block/Kconfig4
-rw-r--r--drivers/block/cciss.c238
-rw-r--r--drivers/block/cciss.h3
-rw-r--r--drivers/block/cciss_cmd.h33
-rw-r--r--drivers/block/cciss_scsi.c2
-rw-r--r--drivers/block/cpqarray.c1
-rw-r--r--drivers/block/floppy.c4
-rw-r--r--drivers/block/loop.c240
-rw-r--r--drivers/block/nbd.c8
-rw-r--r--drivers/block/paride/pd.c8
-rw-r--r--drivers/block/pktcdvd.c10
-rw-r--r--drivers/block/swim3.c4
-rw-r--r--drivers/block/swim_iop.c4
-rw-r--r--drivers/block/xd.c2
16 files changed, 417 insertions, 150 deletions
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index a360215dbce..b3f639fbf22 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -770,7 +770,7 @@ static void DAC960_P_QueueCommand(DAC960_Command_T *Command)
static void DAC960_ExecuteCommand(DAC960_Command_T *Command)
{
DAC960_Controller_T *Controller = Command->Controller;
- DECLARE_COMPLETION(Completion);
+ DECLARE_COMPLETION_ONSTACK(Completion);
unsigned long flags;
Command->Completion = &Completion;
@@ -3331,7 +3331,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_
Command->DmaDirection = PCI_DMA_TODEVICE;
Command->CommandType = DAC960_WriteCommand;
}
- Command->Completion = Request->waiting;
+ Command->Completion = Request->end_io_data;
Command->LogicalDriveNumber = (long)Request->rq_disk->private_data;
Command->BlockNumber = Request->sector;
Command->BlockCount = Request->nr_sectors;
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index a82f37f749a..f9217c34bc2 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -71,7 +71,7 @@
Define a Boolean data type.
*/
-typedef enum { false, true } __attribute__ ((packed)) boolean;
+typedef bool boolean;
/*
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b5382cedf0c..422e31d5f8e 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -2,6 +2,8 @@
# Block device driver configuration
#
+if BLOCK
+
menu "Block devices"
config BLK_DEV_FD
@@ -468,3 +470,5 @@ config ATA_OVER_ETH
devices like the Coraid EtherDrive (R) Storage Blade.
endmenu
+
+endif
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 2cd3391ff87..99f87efe0f5 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -144,13 +144,13 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
int clear_all);
-static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
- int withirq, unsigned int *total_size,
- unsigned int *block_size);
-static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq,
- unsigned int total_size,
- unsigned int block_size,
- InquiryData_struct *inq_buff,
+static void cciss_read_capacity(int ctlr, int logvol, int withirq,
+ sector_t *total_size, unsigned int *block_size);
+static void cciss_read_capacity_16(int ctlr, int logvol, int withirq,
+ sector_t *total_size, unsigned int *block_size);
+static void cciss_geometry_inquiry(int ctlr, int logvol,
+ int withirq, sector_t total_size,
+ unsigned int block_size, InquiryData_struct *inq_buff,
drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num);
static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
@@ -879,7 +879,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
char *buff = NULL;
u64bit temp64;
unsigned long flags;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
if (!arg)
return -EINVAL;
@@ -997,7 +997,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
BYTE sg_used = 0;
int status = 0;
int i;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
__u32 left;
__u32 sz;
BYTE __user *data_ptr;
@@ -1229,7 +1229,6 @@ static inline void complete_buffers(struct bio *bio, int status)
int nr_sectors = bio_sectors(bio);
bio->bi_next = NULL;
- blk_finished_io(len);
bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
bio = xbh;
}
@@ -1326,10 +1325,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
{
ctlr_info_t *h = hba[ctlr];
struct gendisk *disk;
- ReadCapdata_struct *size_buff = NULL;
InquiryData_struct *inq_buff = NULL;
unsigned int block_size;
- unsigned int total_size;
+ sector_t total_size;
unsigned long flags = 0;
int ret = 0;
@@ -1348,15 +1346,25 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
return;
/* Get information about the disk and modify the driver structure */
- size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL)
- goto mem_msg;
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL)
goto mem_msg;
- cciss_read_capacity(ctlr, drv_index, size_buff, 1,
+ 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) {
+ cciss_read_capacity_16(ctlr, drv_index, 1,
+ &total_size, &block_size);
+ h->cciss_read = CCISS_READ_16;
+ h->cciss_write = CCISS_WRITE_16;
+ } else {
+ h->cciss_read = CCISS_READ_10;
+ h->cciss_write = CCISS_WRITE_10;
+ }
cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
inq_buff, &h->drv[drv_index]);
@@ -1392,7 +1400,6 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
}
freeret:
- kfree(size_buff);
kfree(inq_buff);
return;
mem_msg:
@@ -1717,6 +1724,22 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_
c->Request.Timeout = 0;
c->Request.CDB[0] = cmd;
break;
+ case CCISS_READ_CAPACITY_16:
+ c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID;
+ c->Header.LUN.LogDev.Mode = 1;
+ c->Request.CDBLen = 16;
+ c->Request.Type.Attribute = ATTR_SIMPLE;
+ c->Request.Type.Direction = XFER_READ;
+ c->Request.Timeout = 0;
+ c->Request.CDB[0] = cmd;
+ c->Request.CDB[1] = 0x10;
+ c->Request.CDB[10] = (size >> 24) & 0xFF;
+ c->Request.CDB[11] = (size >> 16) & 0xFF;
+ c->Request.CDB[12] = (size >> 8) & 0xFF;
+ c->Request.CDB[13] = size & 0xFF;
+ c->Request.Timeout = 0;
+ c->Request.CDB[0] = cmd;
+ break;
case CCISS_CACHE_FLUSH:
c->Request.CDBLen = 12;
c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1750,6 +1773,7 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
c->Request.CDB[0] = cmd; /* reset */
c->Request.CDB[1] = 0x04; /* reset a LUN */
+ break;
case 3: /* No-Op message */
c->Request.CDBLen = 1;
c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1792,7 +1816,7 @@ static int sendcmd_withirq(__u8 cmd,
u64bit buff_dma_handle;
unsigned long flags;
int return_status;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
if ((c = cmd_alloc(h, 0)) == NULL)
return -ENOMEM;
@@ -1893,12 +1917,15 @@ static int sendcmd_withirq(__u8 cmd,
}
static void cciss_geometry_inquiry(int ctlr, int logvol,
- int withirq, unsigned int total_size,
+ int withirq, sector_t total_size,
unsigned int block_size,
InquiryData_struct *inq_buff,
drive_info_struct *drv)
{
int return_code;
+ unsigned long t;
+ unsigned long rem;
+
memset(inq_buff, 0, sizeof(InquiryData_struct));
if (withirq)
return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
@@ -1917,10 +1944,10 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
drv->nr_blocks = total_size;
drv->heads = 255;
drv->sectors = 32; // Sectors per track
- drv->cylinders = total_size / 255 / 32;
+ t = drv->heads * drv->sectors;
+ drv->cylinders = total_size;
+ rem = do_div(drv->cylinders, t);
} else {
- unsigned int t;
-
drv->block_size = block_size;
drv->nr_blocks = total_size;
drv->heads = inq_buff->data_byte[6];
@@ -1930,42 +1957,84 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
drv->raid_level = inq_buff->data_byte[8];
t = drv->heads * drv->sectors;
if (t > 1) {
- drv->cylinders = total_size / t;
+ drv->cylinders = total_size;
+ rem = do_div(drv->cylinders, t);
}
}
} else { /* Get geometry failed */
printk(KERN_WARNING "cciss: reading geometry failed\n");
}
- printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n",
+ printk(KERN_INFO " heads=%d, sectors=%d, cylinders=%d\n\n",
drv->heads, drv->sectors, drv->cylinders);
}
static void
-cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
- int withirq, unsigned int *total_size,
+cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
unsigned int *block_size)
{
+ ReadCapdata_struct *buf;
int return_code;
- memset(buf, 0, sizeof(*buf));
+ buf = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+ if (buf == NULL) {
+ 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(*buf), 1,
- logvol, 0, TYPE_CMD);
+ ctlr, buf, sizeof(ReadCapdata_struct),
+ 1, logvol, 0, TYPE_CMD);
else
return_code = sendcmd(CCISS_READ_CAPACITY,
- ctlr, buf, sizeof(*buf), 1, logvol, 0,
- NULL, TYPE_CMD);
+ ctlr, buf, sizeof(ReadCapdata_struct),
+ 1, logvol, 0, NULL, TYPE_CMD);
if (return_code == IO_OK) {
- *total_size =
- be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1;
- *block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0]));
+ *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1;
+ *block_size = be32_to_cpu(*(__u32 *) 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= %u block_size= %d\n",
+ if (*total_size != (__u32) 0)
+ printk(KERN_INFO " blocks= %lld block_size= %d\n",
+ *total_size, *block_size);
+ kfree(buf);
+ return;
+}
+
+static void
+cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size)
+{
+ ReadCapdata_struct_16 *buf;
+ int return_code;
+ buf = kmalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL);
+ if (buf == NULL) {
+ 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),
+ 1, logvol, 0, TYPE_CMD);
+ }
+ else {
+ return_code = sendcmd(CCISS_READ_CAPACITY_16,
+ ctlr, buf, sizeof(ReadCapdata_struct_16),
+ 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);
+ } else { /* read capacity command failed */
+ printk(KERN_WARNING "cciss: read capacity failed\n");
+ *total_size = 0;
+ *block_size = BLOCK_SIZE;
+ }
+ printk(KERN_INFO " blocks= %lld block_size= %d\n",
*total_size, *block_size);
+ kfree(buf);
return;
}
@@ -1976,8 +2045,7 @@ static int cciss_revalidate(struct gendisk *disk)
int logvol;
int FOUND = 0;
unsigned int block_size;
- unsigned int total_size;
- ReadCapdata_struct *size_buff = NULL;
+ sector_t total_size;
InquiryData_struct *inq_buff = NULL;
for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
@@ -1990,27 +2058,24 @@ static int cciss_revalidate(struct gendisk *disk)
if (!FOUND)
return 1;
- size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL) {
- printk(KERN_WARNING "cciss: out of memory\n");
- return 1;
- }
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_WARNING "cciss: out of memory\n");
- kfree(size_buff);
return 1;
}
-
- cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size,
- &block_size);
+ if (h->cciss_read == CCISS_READ_10) {
+ cciss_read_capacity(h->ctlr, logvol, 1,
+ &total_size, &block_size);
+ } else {
+ cciss_read_capacity_16(h->ctlr, logvol, 1,
+ &total_size, &block_size);
+ }
cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
inq_buff, drv);
blk_queue_hardsect_size(drv->queue, drv->block_size);
set_capacity(disk, drv->nr_blocks);
- kfree(size_buff);
kfree(inq_buff);
return 0;
}
@@ -2419,7 +2484,8 @@ static void do_cciss_request(request_queue_t *q)
{
ctlr_info_t *h = q->queuedata;
CommandList_struct *c;
- int start_blk, seg;
+ sector_t start_blk;
+ int seg;
struct request *creq;
u64bit temp64;
struct scatterlist tmp_sg[MAXSGENTRIES];
@@ -2463,10 +2529,10 @@ 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) ? XFER_READ : XFER_WRITE;
+ (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
c->Request.Timeout = 0; // Don't time out
c->Request.CDB[0] =
- (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE;
+ (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
start_blk = creq->sector;
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector,
@@ -2500,15 +2566,33 @@ static void do_cciss_request(request_queue_t *q)
#endif /* CCISS_DEBUG */
c->Header.SGList = c->Header.SGTotal = seg;
- c->Request.CDB[1] = 0;
- c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB
- c->Request.CDB[3] = (start_blk >> 16) & 0xff;
- c->Request.CDB[4] = (start_blk >> 8) & 0xff;
- c->Request.CDB[5] = start_blk & 0xff;
- c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB
- c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
- c->Request.CDB[8] = creq->nr_sectors & 0xff;
- c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
+ if(h->cciss_read == CCISS_READ_10) {
+ c->Request.CDB[1] = 0;
+ c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB
+ c->Request.CDB[3] = (start_blk >> 16) & 0xff;
+ c->Request.CDB[4] = (start_blk >> 8) & 0xff;
+ c->Request.CDB[5] = start_blk & 0xff;
+ c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB
+ c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
+ c->Request.CDB[8] = creq->nr_sectors & 0xff;
+ c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
+ } else {
+ c->Request.CDBLen = 16;
+ c->Request.CDB[1]= 0;
+ c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB
+ c->Request.CDB[3]= (start_blk >> 48) & 0xff;
+ c->Request.CDB[4]= (start_blk >> 40) & 0xff;
+ c->Request.CDB[5]= (start_blk >> 32) & 0xff;
+ c->Request.CDB[6]= (start_blk >> 24) & 0xff;
+ c->Request.CDB[7]= (start_blk >> 16) & 0xff;
+ c->Request.CDB[8]= (start_blk >> 8) & 0xff;
+ c->Request.CDB[9]= start_blk & 0xff;
+ c->Request.CDB[10]= (creq->nr_sectors >> 24) & 0xff;
+ c->Request.CDB[11]= (creq->nr_sectors >> 16) & 0xff;
+ c->Request.CDB[12]= (creq->nr_sectors >> 8) & 0xff;
+ c->Request.CDB[13]= creq->nr_sectors & 0xff;
+ c->Request.CDB[14] = c->Request.CDB[15] = 0;
+ }
spin_lock_irq(q->queue_lock);
@@ -2518,9 +2602,9 @@ static void do_cciss_request(request_queue_t *q)
h->maxQsinceinit = h->Qdepth;
goto queue;
- full:
+full:
blk_stop_queue(q);
- startio:
+startio:
/* We will already have the driver lock here so not need
* to lock it.
*/
@@ -2948,31 +3032,23 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
static void cciss_getgeometry(int cntl_num)
{
ReportLunData_struct *ld_buff;
- ReadCapdata_struct *size_buff;
InquiryData_struct *inq_buff;
int return_code;
int i;
int listlength = 0;
__u32 lunid = 0;
int block_size;
- int total_size;
+ sector_t total_size;
ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
if (ld_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
return;
}
- size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL) {
- printk(KERN_ERR "cciss: out of memory\n");
- kfree(ld_buff);
- return;
- }
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
- kfree(size_buff);
return;
}
/* Get the firmware version */
@@ -3027,7 +3103,6 @@ static void cciss_getgeometry(int cntl_num)
#endif /* CCISS_DEBUG */
hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1;
-// for(i=0; i< hba[cntl_num]->num_luns; i++)
for (i = 0; i < CISS_MAX_LUN; i++) {
if (i < hba[cntl_num]->num_luns) {
lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
@@ -3046,8 +3121,26 @@ static void cciss_getgeometry(int cntl_num)
ld_buff->LUN[i][2], ld_buff->LUN[i][3],
hba[cntl_num]->drv[i].LunID);
#endif /* CCISS_DEBUG */
- cciss_read_capacity(cntl_num, i, size_buff, 0,
+
+ /* testing to see if 16-byte CDBs are already being used */
+ if(hba[cntl_num]->cciss_read == CCISS_READ_16) {
+ cciss_read_capacity_16(cntl_num, i, 0,
&total_size, &block_size);
+ goto geo_inq;
+ }
+ cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size);
+
+ /* total_size = last LBA + 1 */
+ if(total_size == (__u32) 0) {
+ cciss_read_capacity_16(cntl_num, i, 0,
+ &total_size, &block_size);
+ hba[cntl_num]->cciss_read = CCISS_READ_16;
+ hba[cntl_num]->cciss_write = CCISS_WRITE_16;
+ } else {
+ hba[cntl_num]->cciss_read = CCISS_READ_10;
+ hba[cntl_num]->cciss_write = CCISS_WRITE_10;
+ }
+geo_inq:
cciss_geometry_inquiry(cntl_num, i, 0, total_size,
block_size, inq_buff,
&hba[cntl_num]->drv[i]);
@@ -3057,7 +3150,6 @@ static void cciss_getgeometry(int cntl_num)
}
}
kfree(ld_buff);
- kfree(size_buff);
kfree(inq_buff);
}
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 868e0d862b0..562235c1445 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -76,6 +76,9 @@ struct ctlr_info
unsigned int intr[4];
unsigned int msix_vector;
unsigned int msi_vector;
+ BYTE cciss_read;
+ BYTE cciss_write;
+ BYTE cciss_read_capacity;
// information about each logical volume
drive_info_struct drv[CISS_MAX_LUN];
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index 53fea549ba8..4af7c4c0c7a 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -118,11 +118,34 @@ typedef struct _ReadCapdata_struct
BYTE block_size[4]; // Size of blocks in bytes
} ReadCapdata_struct;
-// 12 byte commands not implemented in firmware yet.
-// #define CCISS_READ 0xa8 // Read(12)
-// #define CCISS_WRITE 0xaa // Write(12)
- #define CCISS_READ 0x28 // Read(10)
- #define CCISS_WRITE 0x2a // Write(10)
+#define CCISS_READ_CAPACITY_16 0x9e /* Read Capacity 16 */
+
+/* service action to differentiate a 16 byte read capacity from
+ other commands that use the 0x9e SCSI op code */
+
+#define CCISS_READ_CAPACITY_16_SERVICE_ACT 0x10
+
+typedef struct _ReadCapdata_struct_16
+{
+ BYTE total_size[8]; /* Total size in blocks */
+ BYTE block_size[4]; /* Size of blocks in bytes */
+ BYTE prot_en:1; /* protection enable bit */
+ BYTE rto_en:1; /* reference tag own enable bit */
+ BYTE reserved:6; /* reserved bits */
+ BYTE reserved2[18]; /* reserved bytes per spec */
+} ReadCapdata_struct_16;
+
+/* Define the supported read/write commands for cciss based controllers */
+
+#define CCISS_READ_10 0x28 /* Read(10) */
+#define CCISS_WRITE_10 0x2a /* Write(10) */
+#define CCISS_READ_16 0x88 /* Read(16) */
+#define CCISS_WRITE_16 0x8a /* Write(16) */
+
+/* Define the CDB lengths supported by cciss based controllers */
+
+#define CDB_LEN10 10
+#define CDB_LEN16 16
// BMIC commands
#define BMIC_READ 0x26
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 05f79d7393f..bb15051ffbe 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -766,7 +766,7 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c,
int direction)
{
unsigned long flags;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
cp->cmd_type = CMD_IOCTL_PEND; // treat this like an ioctl
cp->scsi_cmd = NULL;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 78082edc14b..4abc193314e 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -989,7 +989,6 @@ static inline void complete_buffers(struct bio *bio, int ok)
xbh = bio->bi_next;
bio->bi_next = NULL;
- blk_finished_io(nr_sectors);
bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO);
bio = xbh;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index ad1d7065a1b..629c5769d99 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -2991,8 +2991,8 @@ static void do_fd_request(request_queue_t * q)
if (usage_count == 0) {
printk("warning: usage count=0, current_req=%p exiting\n",
current_req);
- printk("sect=%ld flags=%lx\n", (long)current_req->sector,
- current_req->flags);
+ printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector,
+ current_req->cmd_type, current_req->cmd_flags);
return;
}
if (test_bit(0, &fdc_busy)) {
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index c774121684d..d6bb8da955a 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -66,12 +66,14 @@
#include <linux/swap.h>
#include <linux/slab.h>
#include <linux/loop.h>
+#include <linux/compat.h>
#include <linux/suspend.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */
#include <linux/completion.h>
#include <linux/highmem.h>
#include <linux/gfp.h>
+#include <linux/kthread.h>
#include <asm/uaccess.h>
@@ -522,15 +524,12 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio)
goto out;
if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
goto out;
- lo->lo_pending++;
loop_add_bio(lo, old_bio);
+ wake_up(&lo->lo_event);
spin_unlock_irq(&lo->lo_lock);
- complete(&lo->lo_bh_done);
return 0;
out:
- if (lo->lo_pending == 0)
- complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
bio_io_error(old_bio, old_bio->bi_size);
return 0;
@@ -570,14 +569,18 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
* to avoid blocking in our make_request_fn. it also does loop decrypting
* on reads for block backed loop, as that is too heavy to do from
* b_end_io context where irqs may be disabled.
+ *
+ * Loop explanation: loop_clr_fd() sets lo_state to Lo_rundown before
+ * calling kthread_stop(). Therefore once kthread_should_stop() is
+ * true, make_request will not place any more requests. Therefore
+ * once kthread_should_stop() is true and lo_bio is NULL, we are
+ * done with the loop.
*/
static int loop_thread(void *data)
{
struct loop_device *lo = data;
struct bio *bio;
- daemonize("loop%d", lo->lo_number);
-
/*
* loop can be used in an encrypted device,
* hence, it mustn't be stopped at all
@@ -587,47 +590,21 @@ static int loop_thread(void *data)
set_user_nice(current, -20);
- lo->lo_state = Lo_bound;
- lo->lo_pending = 1;
+ while (!kthread_should_stop() || lo->lo_bio) {
- /*
- * complete it, we are running
- */
- complete(&lo->lo_done);
-
- for (;;) {
- int pending;
+ wait_event_interruptible(lo->lo_event,
+ lo->lo_bio || kthread_should_stop());
- if (wait_for_completion_interruptible(&lo->lo_bh_done))
+ if (!lo->lo_bio)
continue;
-
spin_lock_irq(&lo->lo_lock);
-
- /*
- * could be completed because of tear-down, not pending work
- */
- if (unlikely(!lo->lo_pending)) {
- spin_unlock_irq(&lo->lo_lock);
- break;
- }
-
bio = loop_get_bio(lo);
- lo->lo_pending--;
- pending = lo->lo_pending;
spin_unlock_irq(&lo->lo_lock);
BUG_ON(!bio);
loop_handle_bio(lo, bio);
-
- /*
- * upped both for pending work and tear-down, lo_pending
- * will hit zero then
- */
- if (unlikely(!pending))
- break;
}
- complete(&lo->lo_done);
return 0;
}
@@ -840,12 +817,26 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
set_blocksize(bdev, lo_blocksize);
- error = kernel_thread(loop_thread, lo, CLONE_KERNEL);
- if (error < 0)
- goto out_putf;
- wait_for_completion(&lo->lo_done);
+ lo->lo_thread = kthread_create(loop_thread, lo, "loop%d",
+ lo->lo_number);
+ if (IS_ERR(lo->lo_thread)) {
+ error = PTR_ERR(lo->lo_thread);
+ goto out_clr;
+ }
+ lo->lo_state = Lo_bound;
+ wake_up_process(lo->lo_thread);
return 0;
+out_clr:
+ lo->lo_thread = NULL;
+ lo->lo_device = NULL;
+ lo->lo_backing_file = NULL;
+ lo->lo_flags = 0;
+ set_capacity(disks[lo->lo_number], 0);
+ invalidate_bdev(bdev, 0);
+ bd_set_size(bdev, 0);
+ mapping_set_gfp_mask(mapping, lo->old_gfp_mask);
+ lo->lo_state = Lo_unbound;
out_putf:
fput(file);
out:
@@ -907,12 +898,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
spin_lock_irq(&lo->lo_lock);
lo->lo_state = Lo_rundown;
- lo->lo_pending--;
- if (!lo->lo_pending)
- complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
- wait_for_completion(&lo->lo_done);
+ kthread_stop(lo->lo_thread);
lo->lo_backing_file = NULL;
@@ -925,6 +913,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
lo->lo_sizelimit = 0;
lo->lo_encrypt_key_size = 0;
lo->lo_flags = 0;
+ lo->lo_thread = NULL;
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
memset(lo->lo_file_name, 0, LO_NAME_SIZE);
@@ -1177,6 +1166,162 @@ static int lo_ioctl(struct inode * inode, struct file * file,
return err;
}
+#ifdef CONFIG_COMPAT
+struct compat_loop_info {
+ compat_int_t lo_number; /* ioctl r/o */
+ compat_dev_t lo_device; /* ioctl r/o */
+ compat_ulong_t lo_inode; /* ioctl r/o */
+ compat_dev_t lo_rdevice; /* ioctl r/o */
+ compat_int_t lo_offset;
+ compat_int_t lo_encrypt_type;
+ compat_int_t lo_encrypt_key_size; /* ioctl w/o */
+ compat_int_t lo_flags; /* ioctl r/o */
+ char lo_name[LO_NAME_SIZE];
+ unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+ compat_ulong_t lo_init[2];
+ char reserved[4];
+};
+
+/*
+ * Transfer 32-bit compatibility structure in userspace to 64-bit loop info
+ * - noinlined to reduce stack space usage in main part of driver
+ */
+static noinline int
+loop_info64_from_compat(const struct compat_loop_info *arg,
+ struct loop_info64 *info64)
+{
+ struct compat_loop_info info;
+
+ if (copy_from_user(&info, arg, sizeof(info)))
+ return -EFAULT;
+
+ memset(info64, 0, sizeof(*info64));
+ info64->lo_number = info.lo_number;
+ info64->lo_device = info.lo_device;
+ info64->lo_inode = info.lo_inode;
+ info64->lo_rdevice = info.lo_rdevice;
+ info64->lo_offset = info.lo_offset;
+ info64->lo_sizelimit = 0;
+ info64->lo_encrypt_type = info.lo_encrypt_type;
+ info64->lo_encrypt_key_size = info.lo_encrypt_key_size;
+ info64->lo_flags = info.lo_flags;
+ info64->lo_init[0] = info.lo_init[0];
+ info64->lo_init[1] = info.lo_init[1];
+ if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+ memcpy(info64->lo_crypt_name, info.lo_name, LO_NAME_SIZE);
+ else
+ memcpy(info64->lo_file_name, info.lo_name, LO_NAME_SIZE);
+ memcpy(info64->lo_encrypt_key, info.lo_encrypt_key, LO_KEY_SIZE);
+ return 0;
+}
+
+/*
+ * Transfer 64-bit loop info to 32-bit compatibility structure in userspace
+ * - noinlined to reduce stack space usage in main part of driver
+ */
+static noinline int
+loop_info64_to_compat(const struct loop_info64 *info64,
+ struct compat_loop_info __user *arg)
+{
+ struct compat_loop_info info;
+
+ memset(&info, 0, sizeof(info));
+ info.lo_number = info64->lo_number;
+ info.lo_device = info64->lo_device;
+ info.lo_inode = info64->lo_inode;
+ info.lo_rdevice = info64->lo_rdevice;
+ info.lo_offset = info64->lo_offset;
+ info.lo_encrypt_type = info64->lo_encrypt_type;
+ info.lo_encrypt_key_size = info64->lo_encrypt_key_size;
+ info.lo_flags = info64->lo_flags;
+ info.lo_init[0] = info64->lo_init[0];
+ info.lo_init[1] = info64->lo_init[1];
+ if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+ memcpy(info.lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
+ else
+ memcpy(info.lo_name, info64->lo_file_name, LO_NAME_SIZE);
+ memcpy(info.lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
+
+ /* error in case values were truncated */
+ if (info.lo_device != info64->lo_device ||
+ info.lo_rdevice != info64->lo_rdevice ||
+ info.lo_inode != info64->lo_inode ||
+ info.lo_offset != info64->lo_offset ||
+ info.lo_init[0] != info64->lo_init[0] ||
+ info.lo_init[1] != info64->lo_init[1])
+ return -EOVERFLOW;
+
+ if (copy_to_user(arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+}
+
+static int
+loop_set_status_compat(struct loop_device *lo,
+ const struct compat_loop_info __user *arg)
+{
+ struct loop_info64 info64;
+ int ret;
+
+ ret = loop_info64_from_compat(arg, &info64);
+ if (ret < 0)
+ return ret;
+ return loop_set_status(lo, &info64);
+}
+
+static int
+loop_get_status_compat(struct loop_device *lo,
+ struct compat_loop_info __user *arg)
+{
+ struct loop_info64 info64;
+ int err = 0;
+
+ if (!arg)
+ err = -EINVAL;
+ if (!err)
+ err = loop_get_status(lo, &info64);
+ if (!err)
+ err = loop_info64_to_compat(&info64, arg);
+ return err;
+}
+
+static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ int err;
+
+ lock_kernel();
+ switch(cmd) {
+ case LOOP_SET_STATUS:
+ mutex_lock(&lo->lo_ctl_mutex);
+ err = loop_set_status_compat(
+ lo, (const struct compat_loop_info __user *) arg);
+ mutex_unlock(&lo->lo_ctl_mutex);
+ break;
+ case LOOP_GET_STATUS:
+ mutex_lock(&lo->lo_ctl_mutex);
+ err = loop_get_status_compat(
+ lo, (struct compat_loop_info __user *) arg);
+ mutex_unlock(&lo->lo_ctl_mutex);
+ break;
+ case LOOP_CLR_FD:
+ case LOOP_GET_STATUS64:
+ case LOOP_SET_STATUS64:
+ arg = (unsigned long) compat_ptr(arg);
+ case LOOP_SET_FD:
+ case LOOP_CHANGE_FD:
+ err = lo_ioctl(inode, file, cmd, arg);
+ break;
+ default:
+ err = -ENOIOCTLCMD;
+ break;
+ }
+ unlock_kernel();
+ return err;
+}
+#endif
+
static int lo_open(struct inode *inode, struct file *file)
{
struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
@@ -1204,6 +1349,9 @@ static struct block_device_operations lo_fops = {
.open = lo_open,
.release = lo_release,
.ioctl = lo_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = lo_compat_ioctl,
+#endif
};
/*
@@ -1287,9 +1435,9 @@ static int __init loop_init(void)
if (!lo->lo_queue)
goto out_mem4;
mutex_init(&lo->lo_ctl_mutex);
- init_completion(&lo->lo_done);
- init_completion(&lo->lo_bh_done);
lo->lo_number = i;
+ lo->lo_thread = NULL;
+ init_waitqueue_head(&lo->lo_event);
spin_lock_init(&lo->lo_lock);
disk->major = LOOP_MAJOR;
disk->first_minor = i;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index bdbade9a5cf..9d1035e8d9d 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -407,10 +407,10 @@ static void do_nbd_request(request_queue_t * q)
struct nbd_device *lo;
blkdev_dequeue_request(req);
- dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n",
- req->rq_disk->disk_name, req, req->flags);
+ dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
+ req->rq_disk->disk_name, req, req->cmd_type);
- if (!(req->flags & REQ_CMD))
+ if (!blk_fs_request(req))
goto error_out;
lo = req->rq_disk->private_data;
@@ -489,7 +489,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case NBD_DISCONNECT:
printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
- sreq.flags = REQ_SPECIAL;
+ sreq.cmd_type = REQ_TYPE_SPECIAL;
nbd_cmd(&sreq) = NBD_CMD_DISC;
/*
* Set these to sane values in case server implementation
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 2403721f9db..40a11e56797 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -437,7 +437,7 @@ static char *pd_buf; /* buffer for request in progress */
static enum action do_pd_io_start(void)
{
- if (pd_req->flags & REQ_SPECIAL) {
+ if (blk_special_request(pd_req)) {
phase = pd_special;
return pd_special();
}
@@ -713,20 +713,18 @@ static void do_pd_request(request_queue_t * q)
static int pd_special_command(struct pd_unit *disk,
enum action (*func)(struct pd_unit *disk))
{
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
struct request rq;
int err = 0;
memset(&rq, 0, sizeof(rq));
rq.errors = 0;
- rq.rq_status = RQ_ACTIVE;
rq.rq_disk = disk->gd;
rq.ref_count = 1;
- rq.waiting = &wait;
+ rq.end_io_data = &wait;
rq.end_io = blk_end_sync_rq;
blk_insert_request(disk->gd->queue, &rq, 0, func);
wait_for_completion(&wait);
- rq.waiting = NULL;
if (rq.errors)
err = -EIO;
blk_put_request(&rq);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 451b996bba9..a6b2aa67c9b 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -348,7 +348,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
char sense[SCSI_SENSE_BUFFERSIZE];
request_queue_t *q;
struct request *rq;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
int err = 0;
q = bdev_get_queue(pd->bdev);
@@ -365,17 +365,17 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
rq->sense = sense;
memset(sense, 0, sizeof(sense));
rq->sense_len = 0;
- rq->flags |= REQ_BLOCK_PC | REQ_HARDBARRIER;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+ rq->cmd_flags |= REQ_HARDBARRIER;
if (cgc->quiet)
- rq->flags |= REQ_QUIET;
+ rq->cmd_flags |= REQ_QUIET;
memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
rq->ref_count++;
- rq->flags |= REQ_NOMERGE;
- rq->waiting = &wait;
+ rq->end_io_data = &wait;
rq->end_io = blk_end_sync_rq;
elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
generic_unplug_device(q);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index cc42e762396..f2305ee792a 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -319,8 +319,8 @@ static void start_request(struct floppy_state *fs)
printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
req->rq_disk->disk_name, req->cmd,
(long)req->sector, req->nr_sectors, req->buffer);
- printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n",
- req->rq_status, req->errors, req->current_nr_sectors);
+ printk(" errors=%d current_nr_sectors=%ld\n",
+ req->errors, req->current_nr_sectors);
#endif
if (req->sector < 0 || req->sector >= fs->total_secs) {
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index 89e3c2f8b77..dfda796eba5 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -529,8 +529,8 @@ static void start_request(struct floppy_state *fs)
printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
CURRENT->rq_disk->disk_name, CURRENT->cmd,
CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer);
- printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n",
- CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors);
+ printk(" errors=%d current_nr_sectors=%ld\n",
+ CURRENT->errors, CURRENT->current_nr_sectors);
#endif
if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index e828e4cbd3e..ebf3025721d 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -313,7 +313,7 @@ static void do_xd_request (request_queue_t * q)
int res = 0;
int retry;
- if (!(req->flags & REQ_CMD)) {
+ if (!blk_fs_request(req)) {
end_request(req, 0);
continue;
}