diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-10-06 11:01:27 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-10-06 11:01:27 -0400 |
commit | 907bc6c7fc7071b00083fc11e510e47dd93df45d (patch) | |
tree | 0697a608561522c00da9e1814974a2eb051bb96d /drivers/block | |
parent | d2b247a8be57647d1745535acd58169fbcbe431a (diff) | |
parent | 2a0f5cb32772e9a9560209e241a80bfbbc31dbc3 (diff) |
Merge branch 'for-2.6.32' into for-2.6.33
Diffstat (limited to 'drivers/block')
38 files changed, 1579 insertions, 474 deletions
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 668dc234b8e..eb4fa194394 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c | |||
@@ -36,7 +36,9 @@ | |||
36 | #include <linux/ioport.h> | 36 | #include <linux/ioport.h> |
37 | #include <linux/mm.h> | 37 | #include <linux/mm.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/smp_lock.h> | ||
39 | #include <linux/proc_fs.h> | 40 | #include <linux/proc_fs.h> |
41 | #include <linux/seq_file.h> | ||
40 | #include <linux/reboot.h> | 42 | #include <linux/reboot.h> |
41 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
42 | #include <linux/timer.h> | 44 | #include <linux/timer.h> |
@@ -151,7 +153,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk) | |||
151 | return 0; | 153 | return 0; |
152 | } | 154 | } |
153 | 155 | ||
154 | static struct block_device_operations DAC960_BlockDeviceOperations = { | 156 | static const struct block_device_operations DAC960_BlockDeviceOperations = { |
155 | .owner = THIS_MODULE, | 157 | .owner = THIS_MODULE, |
156 | .open = DAC960_open, | 158 | .open = DAC960_open, |
157 | .getgeo = DAC960_getgeo, | 159 | .getgeo = DAC960_getgeo, |
@@ -6421,16 +6423,10 @@ static bool DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller, | |||
6421 | return true; | 6423 | return true; |
6422 | } | 6424 | } |
6423 | 6425 | ||
6424 | 6426 | static int dac960_proc_show(struct seq_file *m, void *v) | |
6425 | /* | ||
6426 | DAC960_ProcReadStatus implements reading /proc/rd/status. | ||
6427 | */ | ||
6428 | |||
6429 | static int DAC960_ProcReadStatus(char *Page, char **Start, off_t Offset, | ||
6430 | int Count, int *EOF, void *Data) | ||
6431 | { | 6427 | { |
6432 | unsigned char *StatusMessage = "OK\n"; | 6428 | unsigned char *StatusMessage = "OK\n"; |
6433 | int ControllerNumber, BytesAvailable; | 6429 | int ControllerNumber; |
6434 | for (ControllerNumber = 0; | 6430 | for (ControllerNumber = 0; |
6435 | ControllerNumber < DAC960_ControllerCount; | 6431 | ControllerNumber < DAC960_ControllerCount; |
6436 | ControllerNumber++) | 6432 | ControllerNumber++) |
@@ -6443,52 +6439,49 @@ static int DAC960_ProcReadStatus(char *Page, char **Start, off_t Offset, | |||
6443 | break; | 6439 | break; |
6444 | } | 6440 | } |
6445 | } | 6441 | } |
6446 | BytesAvailable = strlen(StatusMessage) - Offset; | 6442 | seq_puts(m, StatusMessage); |
6447 | if (Count >= BytesAvailable) | 6443 | return 0; |
6448 | { | ||
6449 | Count = BytesAvailable; | ||
6450 | *EOF = true; | ||
6451 | } | ||
6452 | if (Count <= 0) return 0; | ||
6453 | *Start = Page; | ||
6454 | memcpy(Page, &StatusMessage[Offset], Count); | ||
6455 | return Count; | ||
6456 | } | 6444 | } |
6457 | 6445 | ||
6446 | static int dac960_proc_open(struct inode *inode, struct file *file) | ||
6447 | { | ||
6448 | return single_open(file, dac960_proc_show, NULL); | ||
6449 | } | ||
6458 | 6450 | ||
6459 | /* | 6451 | static const struct file_operations dac960_proc_fops = { |
6460 | DAC960_ProcReadInitialStatus implements reading /proc/rd/cN/initial_status. | 6452 | .owner = THIS_MODULE, |
6461 | */ | 6453 | .open = dac960_proc_open, |
6454 | .read = seq_read, | ||
6455 | .llseek = seq_lseek, | ||
6456 | .release = single_release, | ||
6457 | }; | ||
6462 | 6458 | ||
6463 | static int DAC960_ProcReadInitialStatus(char *Page, char **Start, off_t Offset, | 6459 | static int dac960_initial_status_proc_show(struct seq_file *m, void *v) |
6464 | int Count, int *EOF, void *Data) | ||
6465 | { | 6460 | { |
6466 | DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; | 6461 | DAC960_Controller_T *Controller = (DAC960_Controller_T *)m->private; |
6467 | int BytesAvailable = Controller->InitialStatusLength - Offset; | 6462 | seq_printf(m, "%.*s", Controller->InitialStatusLength, Controller->CombinedStatusBuffer); |
6468 | if (Count >= BytesAvailable) | 6463 | return 0; |
6469 | { | ||
6470 | Count = BytesAvailable; | ||
6471 | *EOF = true; | ||
6472 | } | ||
6473 | if (Count <= 0) return 0; | ||
6474 | *Start = Page; | ||
6475 | memcpy(Page, &Controller->CombinedStatusBuffer[Offset], Count); | ||
6476 | return Count; | ||
6477 | } | 6464 | } |
6478 | 6465 | ||
6466 | static int dac960_initial_status_proc_open(struct inode *inode, struct file *file) | ||
6467 | { | ||
6468 | return single_open(file, dac960_initial_status_proc_show, PDE(inode)->data); | ||
6469 | } | ||
6479 | 6470 | ||
6480 | /* | 6471 | static const struct file_operations dac960_initial_status_proc_fops = { |
6481 | DAC960_ProcReadCurrentStatus implements reading /proc/rd/cN/current_status. | 6472 | .owner = THIS_MODULE, |
6482 | */ | 6473 | .open = dac960_initial_status_proc_open, |
6474 | .read = seq_read, | ||
6475 | .llseek = seq_lseek, | ||
6476 | .release = single_release, | ||
6477 | }; | ||
6483 | 6478 | ||
6484 | static int DAC960_ProcReadCurrentStatus(char *Page, char **Start, off_t Offset, | 6479 | static int dac960_current_status_proc_show(struct seq_file *m, void *v) |
6485 | int Count, int *EOF, void *Data) | ||
6486 | { | 6480 | { |
6487 | DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; | 6481 | DAC960_Controller_T *Controller = (DAC960_Controller_T *) m->private; |
6488 | unsigned char *StatusMessage = | 6482 | unsigned char *StatusMessage = |
6489 | "No Rebuild or Consistency Check in Progress\n"; | 6483 | "No Rebuild or Consistency Check in Progress\n"; |
6490 | int ProgressMessageLength = strlen(StatusMessage); | 6484 | int ProgressMessageLength = strlen(StatusMessage); |
6491 | int BytesAvailable; | ||
6492 | if (jiffies != Controller->LastCurrentStatusTime) | 6485 | if (jiffies != Controller->LastCurrentStatusTime) |
6493 | { | 6486 | { |
6494 | Controller->CurrentStatusLength = 0; | 6487 | Controller->CurrentStatusLength = 0; |
@@ -6512,56 +6505,48 @@ static int DAC960_ProcReadCurrentStatus(char *Page, char **Start, off_t Offset, | |||
6512 | } | 6505 | } |
6513 | Controller->LastCurrentStatusTime = jiffies; | 6506 | Controller->LastCurrentStatusTime = jiffies; |
6514 | } | 6507 | } |
6515 | BytesAvailable = Controller->CurrentStatusLength - Offset; | 6508 | seq_printf(m, "%.*s", Controller->CurrentStatusLength, Controller->CurrentStatusBuffer); |
6516 | if (Count >= BytesAvailable) | 6509 | return 0; |
6517 | { | ||
6518 | Count = BytesAvailable; | ||
6519 | *EOF = true; | ||
6520 | } | ||
6521 | if (Count <= 0) return 0; | ||
6522 | *Start = Page; | ||
6523 | memcpy(Page, &Controller->CurrentStatusBuffer[Offset], Count); | ||
6524 | return Count; | ||
6525 | } | 6510 | } |
6526 | 6511 | ||
6512 | static int dac960_current_status_proc_open(struct inode *inode, struct file *file) | ||
6513 | { | ||
6514 | return single_open(file, dac960_current_status_proc_show, PDE(inode)->data); | ||
6515 | } | ||
6527 | 6516 | ||
6528 | /* | 6517 | static const struct file_operations dac960_current_status_proc_fops = { |
6529 | DAC960_ProcReadUserCommand implements reading /proc/rd/cN/user_command. | 6518 | .owner = THIS_MODULE, |
6530 | */ | 6519 | .open = dac960_current_status_proc_open, |
6520 | .read = seq_read, | ||
6521 | .llseek = seq_lseek, | ||
6522 | .release = single_release, | ||
6523 | }; | ||
6531 | 6524 | ||
6532 | static int DAC960_ProcReadUserCommand(char *Page, char **Start, off_t Offset, | 6525 | static int dac960_user_command_proc_show(struct seq_file *m, void *v) |
6533 | int Count, int *EOF, void *Data) | ||
6534 | { | 6526 | { |
6535 | DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; | 6527 | DAC960_Controller_T *Controller = (DAC960_Controller_T *)m->private; |
6536 | int BytesAvailable = Controller->UserStatusLength - Offset; | ||
6537 | if (Count >= BytesAvailable) | ||
6538 | { | ||
6539 | Count = BytesAvailable; | ||
6540 | *EOF = true; | ||
6541 | } | ||
6542 | if (Count <= 0) return 0; | ||
6543 | *Start = Page; | ||
6544 | memcpy(Page, &Controller->UserStatusBuffer[Offset], Count); | ||
6545 | return Count; | ||
6546 | } | ||
6547 | 6528 | ||
6529 | seq_printf(m, "%.*s", Controller->UserStatusLength, Controller->UserStatusBuffer); | ||
6530 | return 0; | ||
6531 | } | ||
6548 | 6532 | ||
6549 | /* | 6533 | static int dac960_user_command_proc_open(struct inode *inode, struct file *file) |
6550 | DAC960_ProcWriteUserCommand implements writing /proc/rd/cN/user_command. | 6534 | { |
6551 | */ | 6535 | return single_open(file, dac960_user_command_proc_show, PDE(inode)->data); |
6536 | } | ||
6552 | 6537 | ||
6553 | static int DAC960_ProcWriteUserCommand(struct file *file, | 6538 | static ssize_t dac960_user_command_proc_write(struct file *file, |
6554 | const char __user *Buffer, | 6539 | const char __user *Buffer, |
6555 | unsigned long Count, void *Data) | 6540 | size_t Count, loff_t *pos) |
6556 | { | 6541 | { |
6557 | DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; | 6542 | DAC960_Controller_T *Controller = (DAC960_Controller_T *) PDE(file->f_path.dentry->d_inode)->data; |
6558 | unsigned char CommandBuffer[80]; | 6543 | unsigned char CommandBuffer[80]; |
6559 | int Length; | 6544 | int Length; |
6560 | if (Count > sizeof(CommandBuffer)-1) return -EINVAL; | 6545 | if (Count > sizeof(CommandBuffer)-1) return -EINVAL; |
6561 | if (copy_from_user(CommandBuffer, Buffer, Count)) return -EFAULT; | 6546 | if (copy_from_user(CommandBuffer, Buffer, Count)) return -EFAULT; |
6562 | CommandBuffer[Count] = '\0'; | 6547 | CommandBuffer[Count] = '\0'; |
6563 | Length = strlen(CommandBuffer); | 6548 | Length = strlen(CommandBuffer); |
6564 | if (CommandBuffer[Length-1] == '\n') | 6549 | if (Length > 0 && CommandBuffer[Length-1] == '\n') |
6565 | CommandBuffer[--Length] = '\0'; | 6550 | CommandBuffer[--Length] = '\0'; |
6566 | if (Controller->FirmwareType == DAC960_V1_Controller) | 6551 | if (Controller->FirmwareType == DAC960_V1_Controller) |
6567 | return (DAC960_V1_ExecuteUserCommand(Controller, CommandBuffer) | 6552 | return (DAC960_V1_ExecuteUserCommand(Controller, CommandBuffer) |
@@ -6571,6 +6556,14 @@ static int DAC960_ProcWriteUserCommand(struct file *file, | |||
6571 | ? Count : -EBUSY); | 6556 | ? Count : -EBUSY); |
6572 | } | 6557 | } |
6573 | 6558 | ||
6559 | static const struct file_operations dac960_user_command_proc_fops = { | ||
6560 | .owner = THIS_MODULE, | ||
6561 | .open = dac960_user_command_proc_open, | ||
6562 | .read = seq_read, | ||
6563 | .llseek = seq_lseek, | ||
6564 | .release = single_release, | ||
6565 | .write = dac960_user_command_proc_write, | ||
6566 | }; | ||
6574 | 6567 | ||
6575 | /* | 6568 | /* |
6576 | DAC960_CreateProcEntries creates the /proc/rd/... entries for the | 6569 | DAC960_CreateProcEntries creates the /proc/rd/... entries for the |
@@ -6585,23 +6578,17 @@ static void DAC960_CreateProcEntries(DAC960_Controller_T *Controller) | |||
6585 | 6578 | ||
6586 | if (DAC960_ProcDirectoryEntry == NULL) { | 6579 | if (DAC960_ProcDirectoryEntry == NULL) { |
6587 | DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); | 6580 | DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); |
6588 | StatusProcEntry = create_proc_read_entry("status", 0, | 6581 | StatusProcEntry = proc_create("status", 0, |
6589 | DAC960_ProcDirectoryEntry, | 6582 | DAC960_ProcDirectoryEntry, |
6590 | DAC960_ProcReadStatus, NULL); | 6583 | &dac960_proc_fops); |
6591 | } | 6584 | } |
6592 | 6585 | ||
6593 | sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); | 6586 | sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); |
6594 | ControllerProcEntry = proc_mkdir(Controller->ControllerName, | 6587 | ControllerProcEntry = proc_mkdir(Controller->ControllerName, |
6595 | DAC960_ProcDirectoryEntry); | 6588 | DAC960_ProcDirectoryEntry); |
6596 | create_proc_read_entry("initial_status", 0, ControllerProcEntry, | 6589 | proc_create_data("initial_status", 0, ControllerProcEntry, &dac960_initial_status_proc_fops, Controller); |
6597 | DAC960_ProcReadInitialStatus, Controller); | 6590 | proc_create_data("current_status", 0, ControllerProcEntry, &dac960_current_status_proc_fops, Controller); |
6598 | create_proc_read_entry("current_status", 0, ControllerProcEntry, | 6591 | UserCommandProcEntry = proc_create_data("user_command", S_IWUSR | S_IRUSR, ControllerProcEntry, &dac960_user_command_proc_fops, Controller); |
6599 | DAC960_ProcReadCurrentStatus, Controller); | ||
6600 | UserCommandProcEntry = | ||
6601 | create_proc_read_entry("user_command", S_IWUSR | S_IRUSR, | ||
6602 | ControllerProcEntry, DAC960_ProcReadUserCommand, | ||
6603 | Controller); | ||
6604 | UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand; | ||
6605 | Controller->ControllerProcEntry = ControllerProcEntry; | 6592 | Controller->ControllerProcEntry = ControllerProcEntry; |
6606 | } | 6593 | } |
6607 | 6594 | ||
@@ -6652,7 +6639,7 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request, | |||
6652 | else ErrorCode = get_user(ControllerNumber, | 6639 | else ErrorCode = get_user(ControllerNumber, |
6653 | &UserSpaceControllerInfo->ControllerNumber); | 6640 | &UserSpaceControllerInfo->ControllerNumber); |
6654 | if (ErrorCode != 0) | 6641 | if (ErrorCode != 0) |
6655 | break;; | 6642 | break; |
6656 | ErrorCode = -ENXIO; | 6643 | ErrorCode = -ENXIO; |
6657 | if (ControllerNumber < 0 || | 6644 | if (ControllerNumber < 0 || |
6658 | ControllerNumber > DAC960_ControllerCount - 1) { | 6645 | ControllerNumber > DAC960_ControllerCount - 1) { |
@@ -6660,7 +6647,7 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request, | |||
6660 | } | 6647 | } |
6661 | Controller = DAC960_Controllers[ControllerNumber]; | 6648 | Controller = DAC960_Controllers[ControllerNumber]; |
6662 | if (Controller == NULL) | 6649 | if (Controller == NULL) |
6663 | break;; | 6650 | break; |
6664 | memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); | 6651 | memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); |
6665 | ControllerInfo.ControllerNumber = ControllerNumber; | 6652 | ControllerInfo.ControllerNumber = ControllerNumber; |
6666 | ControllerInfo.FirmwareType = Controller->FirmwareType; | 6653 | ControllerInfo.FirmwareType = Controller->FirmwareType; |
@@ -7209,7 +7196,7 @@ static struct pci_driver DAC960_pci_driver = { | |||
7209 | .remove = DAC960_Remove, | 7196 | .remove = DAC960_Remove, |
7210 | }; | 7197 | }; |
7211 | 7198 | ||
7212 | static int DAC960_init_module(void) | 7199 | static int __init DAC960_init_module(void) |
7213 | { | 7200 | { |
7214 | int ret; | 7201 | int ret; |
7215 | 7202 | ||
@@ -7221,7 +7208,7 @@ static int DAC960_init_module(void) | |||
7221 | return ret; | 7208 | return ret; |
7222 | } | 7209 | } |
7223 | 7210 | ||
7224 | static void DAC960_cleanup_module(void) | 7211 | static void __exit DAC960_cleanup_module(void) |
7225 | { | 7212 | { |
7226 | int i; | 7213 | int i; |
7227 | 7214 | ||
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index bb72ada9f07..1d886e079c5 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
@@ -298,6 +298,22 @@ config BLK_DEV_NBD | |||
298 | 298 | ||
299 | If unsure, say N. | 299 | If unsure, say N. |
300 | 300 | ||
301 | config BLK_DEV_OSD | ||
302 | tristate "OSD object-as-blkdev support" | ||
303 | depends on SCSI_OSD_ULD | ||
304 | ---help--- | ||
305 | Saying Y or M here will allow the exporting of a single SCSI | ||
306 | OSD (object-based storage) object as a Linux block device. | ||
307 | |||
308 | For example, if you create a 2G object on an OSD device, | ||
309 | you can then use this module to present that 2G object as | ||
310 | a Linux block device. | ||
311 | |||
312 | To compile this driver as a module, choose M here: the | ||
313 | module will be called osdblk. | ||
314 | |||
315 | If unsure, say N. | ||
316 | |||
301 | config BLK_DEV_SX8 | 317 | config BLK_DEV_SX8 |
302 | tristate "Promise SATA SX8 support" | 318 | tristate "Promise SATA SX8 support" |
303 | depends on PCI | 319 | depends on PCI |
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 7755a5e2a85..cdaa3f8fddf 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_XILINX_SYSACE) += xsysace.o | |||
23 | obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o | 23 | obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o |
24 | obj-$(CONFIG_MG_DISK) += mg_disk.o | 24 | obj-$(CONFIG_MG_DISK) += mg_disk.o |
25 | obj-$(CONFIG_SUNVDC) += sunvdc.o | 25 | obj-$(CONFIG_SUNVDC) += sunvdc.o |
26 | obj-$(CONFIG_BLK_DEV_OSD) += osdblk.o | ||
26 | 27 | ||
27 | obj-$(CONFIG_BLK_DEV_UMEM) += umem.o | 28 | obj-$(CONFIG_BLK_DEV_UMEM) += umem.o |
28 | obj-$(CONFIG_BLK_DEV_NBD) += nbd.o | 29 | obj-$(CONFIG_BLK_DEV_NBD) += nbd.o |
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 9c6e5b0fe89..05522583902 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c | |||
@@ -1632,7 +1632,7 @@ static int amiga_floppy_change(struct gendisk *disk) | |||
1632 | return 0; | 1632 | return 0; |
1633 | } | 1633 | } |
1634 | 1634 | ||
1635 | static struct block_device_operations floppy_fops = { | 1635 | static const struct block_device_operations floppy_fops = { |
1636 | .owner = THIS_MODULE, | 1636 | .owner = THIS_MODULE, |
1637 | .open = floppy_open, | 1637 | .open = floppy_open, |
1638 | .release = floppy_release, | 1638 | .release = floppy_release, |
@@ -1645,7 +1645,7 @@ static int __init fd_probe_drives(void) | |||
1645 | { | 1645 | { |
1646 | int drive,drives,nomem; | 1646 | int drive,drives,nomem; |
1647 | 1647 | ||
1648 | printk(KERN_INFO "FD: probing units\n" KERN_INFO "found "); | 1648 | printk(KERN_INFO "FD: probing units\nfound "); |
1649 | drives=0; | 1649 | drives=0; |
1650 | nomem=0; | 1650 | nomem=0; |
1651 | for(drive=0;drive<FD_MAX_UNITS;drive++) { | 1651 | for(drive=0;drive<FD_MAX_UNITS;drive++) { |
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 5e41e6dd657..db195abad69 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h | |||
@@ -155,7 +155,7 @@ struct aoedev { | |||
155 | u16 fw_ver; /* version of blade's firmware */ | 155 | u16 fw_ver; /* version of blade's firmware */ |
156 | struct work_struct work;/* disk create work struct */ | 156 | struct work_struct work;/* disk create work struct */ |
157 | struct gendisk *gd; | 157 | struct gendisk *gd; |
158 | struct request_queue blkq; | 158 | struct request_queue *blkq; |
159 | struct hd_geometry geo; | 159 | struct hd_geometry geo; |
160 | sector_t ssize; | 160 | sector_t ssize; |
161 | struct timer_list timer; | 161 | struct timer_list timer; |
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 2307a271bdc..3af97d4da2d 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c | |||
@@ -172,6 +172,9 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) | |||
172 | BUG(); | 172 | BUG(); |
173 | bio_endio(bio, -ENXIO); | 173 | bio_endio(bio, -ENXIO); |
174 | return 0; | 174 | return 0; |
175 | } else if (bio_rw_flagged(bio, BIO_RW_BARRIER)) { | ||
176 | bio_endio(bio, -EOPNOTSUPP); | ||
177 | return 0; | ||
175 | } else if (bio->bi_io_vec == NULL) { | 178 | } else if (bio->bi_io_vec == NULL) { |
176 | printk(KERN_ERR "aoe: bi_io_vec is NULL\n"); | 179 | printk(KERN_ERR "aoe: bi_io_vec is NULL\n"); |
177 | BUG(); | 180 | BUG(); |
@@ -234,7 +237,7 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
234 | return 0; | 237 | return 0; |
235 | } | 238 | } |
236 | 239 | ||
237 | static struct block_device_operations aoe_bdops = { | 240 | static const struct block_device_operations aoe_bdops = { |
238 | .open = aoeblk_open, | 241 | .open = aoeblk_open, |
239 | .release = aoeblk_release, | 242 | .release = aoeblk_release, |
240 | .getgeo = aoeblk_getgeo, | 243 | .getgeo = aoeblk_getgeo, |
@@ -264,9 +267,13 @@ aoeblk_gdalloc(void *vp) | |||
264 | goto err_disk; | 267 | goto err_disk; |
265 | } | 268 | } |
266 | 269 | ||
267 | blk_queue_make_request(&d->blkq, aoeblk_make_request); | 270 | d->blkq = blk_alloc_queue(GFP_KERNEL); |
268 | if (bdi_init(&d->blkq.backing_dev_info)) | 271 | if (!d->blkq) |
269 | goto err_mempool; | 272 | goto err_mempool; |
273 | blk_queue_make_request(d->blkq, aoeblk_make_request); | ||
274 | d->blkq->backing_dev_info.name = "aoe"; | ||
275 | if (bdi_init(&d->blkq->backing_dev_info)) | ||
276 | goto err_blkq; | ||
270 | spin_lock_irqsave(&d->lock, flags); | 277 | spin_lock_irqsave(&d->lock, flags); |
271 | gd->major = AOE_MAJOR; | 278 | gd->major = AOE_MAJOR; |
272 | gd->first_minor = d->sysminor * AOE_PARTITIONS; | 279 | gd->first_minor = d->sysminor * AOE_PARTITIONS; |
@@ -276,7 +283,7 @@ aoeblk_gdalloc(void *vp) | |||
276 | snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", | 283 | snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", |
277 | d->aoemajor, d->aoeminor); | 284 | d->aoemajor, d->aoeminor); |
278 | 285 | ||
279 | gd->queue = &d->blkq; | 286 | gd->queue = d->blkq; |
280 | d->gd = gd; | 287 | d->gd = gd; |
281 | d->flags &= ~DEVFL_GDALLOC; | 288 | d->flags &= ~DEVFL_GDALLOC; |
282 | d->flags |= DEVFL_UP; | 289 | d->flags |= DEVFL_UP; |
@@ -287,6 +294,9 @@ aoeblk_gdalloc(void *vp) | |||
287 | aoedisk_add_sysfs(d); | 294 | aoedisk_add_sysfs(d); |
288 | return; | 295 | return; |
289 | 296 | ||
297 | err_blkq: | ||
298 | blk_cleanup_queue(d->blkq); | ||
299 | d->blkq = NULL; | ||
290 | err_mempool: | 300 | err_mempool: |
291 | mempool_destroy(d->bufpool); | 301 | mempool_destroy(d->bufpool); |
292 | err_disk: | 302 | err_disk: |
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 19888354188..62141ec09a2 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
@@ -266,7 +266,7 @@ static const struct file_operations aoe_fops = { | |||
266 | .owner = THIS_MODULE, | 266 | .owner = THIS_MODULE, |
267 | }; | 267 | }; |
268 | 268 | ||
269 | static char *aoe_nodename(struct device *dev) | 269 | static char *aoe_devnode(struct device *dev, mode_t *mode) |
270 | { | 270 | { |
271 | return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev)); | 271 | return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev)); |
272 | } | 272 | } |
@@ -288,7 +288,7 @@ aoechr_init(void) | |||
288 | unregister_chrdev(AOE_MAJOR, "aoechr"); | 288 | unregister_chrdev(AOE_MAJOR, "aoechr"); |
289 | return PTR_ERR(aoe_class); | 289 | return PTR_ERR(aoe_class); |
290 | } | 290 | } |
291 | aoe_class->nodename = aoe_nodename; | 291 | aoe_class->devnode = aoe_devnode; |
292 | 292 | ||
293 | for (i = 0; i < ARRAY_SIZE(chardevs); ++i) | 293 | for (i = 0; i < ARRAY_SIZE(chardevs); ++i) |
294 | device_create(aoe_class, NULL, | 294 | device_create(aoe_class, NULL, |
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index eeea477d960..fa67027789a 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -113,6 +113,7 @@ aoedev_freedev(struct aoedev *d) | |||
113 | if (d->bufpool) | 113 | if (d->bufpool) |
114 | mempool_destroy(d->bufpool); | 114 | mempool_destroy(d->bufpool); |
115 | skbpoolfree(d); | 115 | skbpoolfree(d); |
116 | blk_cleanup_queue(d->blkq); | ||
116 | kfree(d); | 117 | kfree(d); |
117 | } | 118 | } |
118 | 119 | ||
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index f5e7180d7f4..847a9e57570 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c | |||
@@ -1627,7 +1627,7 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, | |||
1627 | drive, dtp->blocks, dtp->spt, dtp->stretch); | 1627 | drive, dtp->blocks, dtp->spt, dtp->stretch); |
1628 | 1628 | ||
1629 | /* sanity check */ | 1629 | /* sanity check */ |
1630 | if (!dtp || setprm.track != dtp->blocks/dtp->spt/2 || | 1630 | if (setprm.track != dtp->blocks/dtp->spt/2 || |
1631 | setprm.head != 2) { | 1631 | setprm.head != 2) { |
1632 | redo_fd_request(); | 1632 | redo_fd_request(); |
1633 | return -EINVAL; | 1633 | return -EINVAL; |
@@ -1856,7 +1856,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) | |||
1856 | return 0; | 1856 | return 0; |
1857 | } | 1857 | } |
1858 | 1858 | ||
1859 | static struct block_device_operations floppy_fops = { | 1859 | static const struct block_device_operations floppy_fops = { |
1860 | .owner = THIS_MODULE, | 1860 | .owner = THIS_MODULE, |
1861 | .open = floppy_open, | 1861 | .open = floppy_open, |
1862 | .release = floppy_release, | 1862 | .release = floppy_release, |
diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 4bf8705b3ac..4f688434daf 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c | |||
@@ -375,7 +375,7 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode, | |||
375 | return error; | 375 | return error; |
376 | } | 376 | } |
377 | 377 | ||
378 | static struct block_device_operations brd_fops = { | 378 | static const struct block_device_operations brd_fops = { |
379 | .owner = THIS_MODULE, | 379 | .owner = THIS_MODULE, |
380 | .locked_ioctl = brd_ioctl, | 380 | .locked_ioctl = brd_ioctl, |
381 | #ifdef CONFIG_BLK_DEV_XIP | 381 | #ifdef CONFIG_BLK_DEV_XIP |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index c7a527c08a0..fb5be2d95d5 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/smp_lock.h> | ||
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
30 | #include <linux/major.h> | 31 | #include <linux/major.h> |
31 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
@@ -35,9 +36,11 @@ | |||
35 | #include <linux/proc_fs.h> | 36 | #include <linux/proc_fs.h> |
36 | #include <linux/seq_file.h> | 37 | #include <linux/seq_file.h> |
37 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/jiffies.h> | ||
38 | #include <linux/hdreg.h> | 40 | #include <linux/hdreg.h> |
39 | #include <linux/spinlock.h> | 41 | #include <linux/spinlock.h> |
40 | #include <linux/compat.h> | 42 | #include <linux/compat.h> |
43 | #include <linux/mutex.h> | ||
41 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
42 | #include <asm/io.h> | 45 | #include <asm/io.h> |
43 | 46 | ||
@@ -154,6 +157,10 @@ static struct board_type products[] = { | |||
154 | 157 | ||
155 | static ctlr_info_t *hba[MAX_CTLR]; | 158 | static ctlr_info_t *hba[MAX_CTLR]; |
156 | 159 | ||
160 | static struct task_struct *cciss_scan_thread; | ||
161 | static DEFINE_MUTEX(scan_mutex); | ||
162 | static LIST_HEAD(scan_q); | ||
163 | |||
157 | static void do_cciss_request(struct request_queue *q); | 164 | static void do_cciss_request(struct request_queue *q); |
158 | static irqreturn_t do_cciss_intr(int irq, void *dev_id); | 165 | static irqreturn_t do_cciss_intr(int irq, void *dev_id); |
159 | static int cciss_open(struct block_device *bdev, fmode_t mode); | 166 | static int cciss_open(struct block_device *bdev, fmode_t mode); |
@@ -163,9 +170,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
163 | static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); | 170 | static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); |
164 | 171 | ||
165 | static int cciss_revalidate(struct gendisk *disk); | 172 | static int cciss_revalidate(struct gendisk *disk); |
166 | static int rebuild_lun_table(ctlr_info_t *h, int first_time); | 173 | static int rebuild_lun_table(ctlr_info_t *h, int first_time, int via_ioctl); |
167 | static int deregister_disk(ctlr_info_t *h, int drv_index, | 174 | static int deregister_disk(ctlr_info_t *h, int drv_index, |
168 | int clear_all); | 175 | int clear_all, int via_ioctl); |
169 | 176 | ||
170 | static void cciss_read_capacity(int ctlr, int logvol, int withirq, | 177 | static void cciss_read_capacity(int ctlr, int logvol, int withirq, |
171 | sector_t *total_size, unsigned int *block_size); | 178 | sector_t *total_size, unsigned int *block_size); |
@@ -188,8 +195,13 @@ static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c, | |||
188 | static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c); | 195 | static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c); |
189 | 196 | ||
190 | static void fail_all_cmds(unsigned long ctlr); | 197 | static void fail_all_cmds(unsigned long ctlr); |
198 | static int add_to_scan_list(struct ctlr_info *h); | ||
191 | static int scan_thread(void *data); | 199 | static int scan_thread(void *data); |
192 | static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c); | 200 | static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c); |
201 | static void cciss_hba_release(struct device *dev); | ||
202 | static void cciss_device_release(struct device *dev); | ||
203 | static void cciss_free_gendisk(ctlr_info_t *h, int drv_index); | ||
204 | static void cciss_free_drive_info(ctlr_info_t *h, int drv_index); | ||
193 | 205 | ||
194 | #ifdef CONFIG_PROC_FS | 206 | #ifdef CONFIG_PROC_FS |
195 | static void cciss_procinit(int i); | 207 | static void cciss_procinit(int i); |
@@ -204,7 +216,7 @@ static int cciss_compat_ioctl(struct block_device *, fmode_t, | |||
204 | unsigned, unsigned long); | 216 | unsigned, unsigned long); |
205 | #endif | 217 | #endif |
206 | 218 | ||
207 | static struct block_device_operations cciss_fops = { | 219 | static const struct block_device_operations cciss_fops = { |
208 | .owner = THIS_MODULE, | 220 | .owner = THIS_MODULE, |
209 | .open = cciss_open, | 221 | .open = cciss_open, |
210 | .release = cciss_release, | 222 | .release = cciss_release, |
@@ -226,15 +238,28 @@ static inline void addQ(struct hlist_head *list, CommandList_struct *c) | |||
226 | 238 | ||
227 | static inline void removeQ(CommandList_struct *c) | 239 | static inline void removeQ(CommandList_struct *c) |
228 | { | 240 | { |
229 | if (WARN_ON(hlist_unhashed(&c->list))) | 241 | /* |
242 | * After kexec/dump some commands might still | ||
243 | * be in flight, which the firmware will try | ||
244 | * to complete. Resetting the firmware doesn't work | ||
245 | * with old fw revisions, so we have to mark | ||
246 | * them off as 'stale' to prevent the driver from | ||
247 | * falling over. | ||
248 | */ | ||
249 | if (WARN_ON(hlist_unhashed(&c->list))) { | ||
250 | c->cmd_type = CMD_MSG_STALE; | ||
230 | return; | 251 | return; |
252 | } | ||
231 | 253 | ||
232 | hlist_del_init(&c->list); | 254 | hlist_del_init(&c->list); |
233 | } | 255 | } |
234 | 256 | ||
235 | #include "cciss_scsi.c" /* For SCSI tape support */ | 257 | #include "cciss_scsi.c" /* For SCSI tape support */ |
236 | 258 | ||
237 | #define RAID_UNKNOWN 6 | 259 | static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", |
260 | "UNKNOWN" | ||
261 | }; | ||
262 | #define RAID_UNKNOWN (sizeof(raid_label) / sizeof(raid_label[0])-1) | ||
238 | 263 | ||
239 | #ifdef CONFIG_PROC_FS | 264 | #ifdef CONFIG_PROC_FS |
240 | 265 | ||
@@ -244,9 +269,6 @@ static inline void removeQ(CommandList_struct *c) | |||
244 | #define ENG_GIG 1000000000 | 269 | #define ENG_GIG 1000000000 |
245 | #define ENG_GIG_FACTOR (ENG_GIG/512) | 270 | #define ENG_GIG_FACTOR (ENG_GIG/512) |
246 | #define ENGAGE_SCSI "engage scsi" | 271 | #define ENGAGE_SCSI "engage scsi" |
247 | static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", | ||
248 | "UNKNOWN" | ||
249 | }; | ||
250 | 272 | ||
251 | static struct proc_dir_entry *proc_cciss; | 273 | static struct proc_dir_entry *proc_cciss; |
252 | 274 | ||
@@ -307,7 +329,7 @@ static int cciss_seq_show(struct seq_file *seq, void *v) | |||
307 | ctlr_info_t *h = seq->private; | 329 | ctlr_info_t *h = seq->private; |
308 | unsigned ctlr = h->ctlr; | 330 | unsigned ctlr = h->ctlr; |
309 | loff_t *pos = v; | 331 | loff_t *pos = v; |
310 | drive_info_struct *drv = &h->drv[*pos]; | 332 | drive_info_struct *drv = h->drv[*pos]; |
311 | 333 | ||
312 | if (*pos > h->highest_lun) | 334 | if (*pos > h->highest_lun) |
313 | return 0; | 335 | return 0; |
@@ -320,7 +342,7 @@ static int cciss_seq_show(struct seq_file *seq, void *v) | |||
320 | vol_sz_frac *= 100; | 342 | vol_sz_frac *= 100; |
321 | sector_div(vol_sz_frac, ENG_GIG_FACTOR); | 343 | sector_div(vol_sz_frac, ENG_GIG_FACTOR); |
322 | 344 | ||
323 | if (drv->raid_level > 5) | 345 | if (drv->raid_level < 0 || drv->raid_level > RAID_UNKNOWN) |
324 | drv->raid_level = RAID_UNKNOWN; | 346 | drv->raid_level = RAID_UNKNOWN; |
325 | seq_printf(seq, "cciss/c%dd%d:" | 347 | seq_printf(seq, "cciss/c%dd%d:" |
326 | "\t%4u.%02uGB\tRAID %s\n", | 348 | "\t%4u.%02uGB\tRAID %s\n", |
@@ -352,7 +374,7 @@ static void cciss_seq_stop(struct seq_file *seq, void *v) | |||
352 | h->busy_configuring = 0; | 374 | h->busy_configuring = 0; |
353 | } | 375 | } |
354 | 376 | ||
355 | static struct seq_operations cciss_seq_ops = { | 377 | static const struct seq_operations cciss_seq_ops = { |
356 | .start = cciss_seq_start, | 378 | .start = cciss_seq_start, |
357 | .show = cciss_seq_show, | 379 | .show = cciss_seq_show, |
358 | .next = cciss_seq_next, | 380 | .next = cciss_seq_next, |
@@ -415,7 +437,7 @@ out: | |||
415 | return err; | 437 | return err; |
416 | } | 438 | } |
417 | 439 | ||
418 | static struct file_operations cciss_proc_fops = { | 440 | static const struct file_operations cciss_proc_fops = { |
419 | .owner = THIS_MODULE, | 441 | .owner = THIS_MODULE, |
420 | .open = cciss_seq_open, | 442 | .open = cciss_seq_open, |
421 | .read = seq_read, | 443 | .read = seq_read, |
@@ -443,9 +465,19 @@ static void __devinit cciss_procinit(int i) | |||
443 | #define to_hba(n) container_of(n, struct ctlr_info, dev) | 465 | #define to_hba(n) container_of(n, struct ctlr_info, dev) |
444 | #define to_drv(n) container_of(n, drive_info_struct, dev) | 466 | #define to_drv(n) container_of(n, drive_info_struct, dev) |
445 | 467 | ||
446 | static struct device_type cciss_host_type = { | 468 | static ssize_t host_store_rescan(struct device *dev, |
447 | .name = "cciss_host", | 469 | struct device_attribute *attr, |
448 | }; | 470 | const char *buf, size_t count) |
471 | { | ||
472 | struct ctlr_info *h = to_hba(dev); | ||
473 | |||
474 | add_to_scan_list(h); | ||
475 | wake_up_process(cciss_scan_thread); | ||
476 | wait_for_completion_interruptible(&h->scan_wait); | ||
477 | |||
478 | return count; | ||
479 | } | ||
480 | DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan); | ||
449 | 481 | ||
450 | static ssize_t dev_show_unique_id(struct device *dev, | 482 | static ssize_t dev_show_unique_id(struct device *dev, |
451 | struct device_attribute *attr, | 483 | struct device_attribute *attr, |
@@ -549,11 +581,101 @@ static ssize_t dev_show_rev(struct device *dev, | |||
549 | } | 581 | } |
550 | DEVICE_ATTR(rev, S_IRUGO, dev_show_rev, NULL); | 582 | DEVICE_ATTR(rev, S_IRUGO, dev_show_rev, NULL); |
551 | 583 | ||
584 | static ssize_t cciss_show_lunid(struct device *dev, | ||
585 | struct device_attribute *attr, char *buf) | ||
586 | { | ||
587 | drive_info_struct *drv = to_drv(dev); | ||
588 | struct ctlr_info *h = to_hba(drv->dev.parent); | ||
589 | unsigned long flags; | ||
590 | unsigned char lunid[8]; | ||
591 | |||
592 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
593 | if (h->busy_configuring) { | ||
594 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
595 | return -EBUSY; | ||
596 | } | ||
597 | if (!drv->heads) { | ||
598 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
599 | return -ENOTTY; | ||
600 | } | ||
601 | memcpy(lunid, drv->LunID, sizeof(lunid)); | ||
602 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
603 | return snprintf(buf, 20, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | ||
604 | lunid[0], lunid[1], lunid[2], lunid[3], | ||
605 | lunid[4], lunid[5], lunid[6], lunid[7]); | ||
606 | } | ||
607 | DEVICE_ATTR(lunid, S_IRUGO, cciss_show_lunid, NULL); | ||
608 | |||
609 | static ssize_t cciss_show_raid_level(struct device *dev, | ||
610 | struct device_attribute *attr, char *buf) | ||
611 | { | ||
612 | drive_info_struct *drv = to_drv(dev); | ||
613 | struct ctlr_info *h = to_hba(drv->dev.parent); | ||
614 | int raid; | ||
615 | unsigned long flags; | ||
616 | |||
617 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
618 | if (h->busy_configuring) { | ||
619 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
620 | return -EBUSY; | ||
621 | } | ||
622 | raid = drv->raid_level; | ||
623 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
624 | if (raid < 0 || raid > RAID_UNKNOWN) | ||
625 | raid = RAID_UNKNOWN; | ||
626 | |||
627 | return snprintf(buf, strlen(raid_label[raid]) + 7, "RAID %s\n", | ||
628 | raid_label[raid]); | ||
629 | } | ||
630 | DEVICE_ATTR(raid_level, S_IRUGO, cciss_show_raid_level, NULL); | ||
631 | |||
632 | static ssize_t cciss_show_usage_count(struct device *dev, | ||
633 | struct device_attribute *attr, char *buf) | ||
634 | { | ||
635 | drive_info_struct *drv = to_drv(dev); | ||
636 | struct ctlr_info *h = to_hba(drv->dev.parent); | ||
637 | unsigned long flags; | ||
638 | int count; | ||
639 | |||
640 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
641 | if (h->busy_configuring) { | ||
642 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
643 | return -EBUSY; | ||
644 | } | ||
645 | count = drv->usage_count; | ||
646 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
647 | return snprintf(buf, 20, "%d\n", count); | ||
648 | } | ||
649 | DEVICE_ATTR(usage_count, S_IRUGO, cciss_show_usage_count, NULL); | ||
650 | |||
651 | static struct attribute *cciss_host_attrs[] = { | ||
652 | &dev_attr_rescan.attr, | ||
653 | NULL | ||
654 | }; | ||
655 | |||
656 | static struct attribute_group cciss_host_attr_group = { | ||
657 | .attrs = cciss_host_attrs, | ||
658 | }; | ||
659 | |||
660 | static const struct attribute_group *cciss_host_attr_groups[] = { | ||
661 | &cciss_host_attr_group, | ||
662 | NULL | ||
663 | }; | ||
664 | |||
665 | static struct device_type cciss_host_type = { | ||
666 | .name = "cciss_host", | ||
667 | .groups = cciss_host_attr_groups, | ||
668 | .release = cciss_hba_release, | ||
669 | }; | ||
670 | |||
552 | static struct attribute *cciss_dev_attrs[] = { | 671 | static struct attribute *cciss_dev_attrs[] = { |
553 | &dev_attr_unique_id.attr, | 672 | &dev_attr_unique_id.attr, |
554 | &dev_attr_model.attr, | 673 | &dev_attr_model.attr, |
555 | &dev_attr_vendor.attr, | 674 | &dev_attr_vendor.attr, |
556 | &dev_attr_rev.attr, | 675 | &dev_attr_rev.attr, |
676 | &dev_attr_lunid.attr, | ||
677 | &dev_attr_raid_level.attr, | ||
678 | &dev_attr_usage_count.attr, | ||
557 | NULL | 679 | NULL |
558 | }; | 680 | }; |
559 | 681 | ||
@@ -561,7 +683,7 @@ static struct attribute_group cciss_dev_attr_group = { | |||
561 | .attrs = cciss_dev_attrs, | 683 | .attrs = cciss_dev_attrs, |
562 | }; | 684 | }; |
563 | 685 | ||
564 | static struct attribute_group *cciss_dev_attr_groups[] = { | 686 | static const struct attribute_group *cciss_dev_attr_groups[] = { |
565 | &cciss_dev_attr_group, | 687 | &cciss_dev_attr_group, |
566 | NULL | 688 | NULL |
567 | }; | 689 | }; |
@@ -569,12 +691,24 @@ static struct attribute_group *cciss_dev_attr_groups[] = { | |||
569 | static struct device_type cciss_dev_type = { | 691 | static struct device_type cciss_dev_type = { |
570 | .name = "cciss_device", | 692 | .name = "cciss_device", |
571 | .groups = cciss_dev_attr_groups, | 693 | .groups = cciss_dev_attr_groups, |
694 | .release = cciss_device_release, | ||
572 | }; | 695 | }; |
573 | 696 | ||
574 | static struct bus_type cciss_bus_type = { | 697 | static struct bus_type cciss_bus_type = { |
575 | .name = "cciss", | 698 | .name = "cciss", |
576 | }; | 699 | }; |
577 | 700 | ||
701 | /* | ||
702 | * cciss_hba_release is called when the reference count | ||
703 | * of h->dev goes to zero. | ||
704 | */ | ||
705 | static void cciss_hba_release(struct device *dev) | ||
706 | { | ||
707 | /* | ||
708 | * nothing to do, but need this to avoid a warning | ||
709 | * about not having a release handler from lib/kref.c. | ||
710 | */ | ||
711 | } | ||
578 | 712 | ||
579 | /* | 713 | /* |
580 | * Initialize sysfs entry for each controller. This sets up and registers | 714 | * Initialize sysfs entry for each controller. This sets up and registers |
@@ -598,6 +732,16 @@ static int cciss_create_hba_sysfs_entry(struct ctlr_info *h) | |||
598 | static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h) | 732 | static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h) |
599 | { | 733 | { |
600 | device_del(&h->dev); | 734 | device_del(&h->dev); |
735 | put_device(&h->dev); /* final put. */ | ||
736 | } | ||
737 | |||
738 | /* cciss_device_release is called when the reference count | ||
739 | * of h->drv[x]dev goes to zero. | ||
740 | */ | ||
741 | static void cciss_device_release(struct device *dev) | ||
742 | { | ||
743 | drive_info_struct *drv = to_drv(dev); | ||
744 | kfree(drv); | ||
601 | } | 745 | } |
602 | 746 | ||
603 | /* | 747 | /* |
@@ -606,24 +750,39 @@ static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h) | |||
606 | * /sys/bus/pci/devices/<dev/ccis#/. We also create a link from | 750 | * /sys/bus/pci/devices/<dev/ccis#/. We also create a link from |
607 | * /sys/block/cciss!c#d# to this entry. | 751 | * /sys/block/cciss!c#d# to this entry. |
608 | */ | 752 | */ |
609 | static int cciss_create_ld_sysfs_entry(struct ctlr_info *h, | 753 | static long cciss_create_ld_sysfs_entry(struct ctlr_info *h, |
610 | drive_info_struct *drv, | ||
611 | int drv_index) | 754 | int drv_index) |
612 | { | 755 | { |
613 | device_initialize(&drv->dev); | 756 | struct device *dev; |
614 | drv->dev.type = &cciss_dev_type; | 757 | |
615 | drv->dev.bus = &cciss_bus_type; | 758 | if (h->drv[drv_index]->device_initialized) |
616 | dev_set_name(&drv->dev, "c%dd%d", h->ctlr, drv_index); | 759 | return 0; |
617 | drv->dev.parent = &h->dev; | 760 | |
618 | return device_add(&drv->dev); | 761 | dev = &h->drv[drv_index]->dev; |
762 | device_initialize(dev); | ||
763 | dev->type = &cciss_dev_type; | ||
764 | dev->bus = &cciss_bus_type; | ||
765 | dev_set_name(dev, "c%dd%d", h->ctlr, drv_index); | ||
766 | dev->parent = &h->dev; | ||
767 | h->drv[drv_index]->device_initialized = 1; | ||
768 | return device_add(dev); | ||
619 | } | 769 | } |
620 | 770 | ||
621 | /* | 771 | /* |
622 | * Remove sysfs entries for a logical drive. | 772 | * Remove sysfs entries for a logical drive. |
623 | */ | 773 | */ |
624 | static void cciss_destroy_ld_sysfs_entry(drive_info_struct *drv) | 774 | static void cciss_destroy_ld_sysfs_entry(struct ctlr_info *h, int drv_index, |
775 | int ctlr_exiting) | ||
625 | { | 776 | { |
626 | device_del(&drv->dev); | 777 | struct device *dev = &h->drv[drv_index]->dev; |
778 | |||
779 | /* special case for c*d0, we only destroy it on controller exit */ | ||
780 | if (drv_index == 0 && !ctlr_exiting) | ||
781 | return; | ||
782 | |||
783 | device_del(dev); | ||
784 | put_device(dev); /* the "final" put. */ | ||
785 | h->drv[drv_index] = NULL; | ||
627 | } | 786 | } |
628 | 787 | ||
629 | /* | 788 | /* |
@@ -740,7 +899,7 @@ static int cciss_open(struct block_device *bdev, fmode_t mode) | |||
740 | printk(KERN_DEBUG "cciss_open %s\n", bdev->bd_disk->disk_name); | 899 | printk(KERN_DEBUG "cciss_open %s\n", bdev->bd_disk->disk_name); |
741 | #endif /* CCISS_DEBUG */ | 900 | #endif /* CCISS_DEBUG */ |
742 | 901 | ||
743 | if (host->busy_initializing || drv->busy_configuring) | 902 | if (drv->busy_configuring) |
744 | return -EBUSY; | 903 | return -EBUSY; |
745 | /* | 904 | /* |
746 | * Root is allowed to open raw volume zero even if it's not configured | 905 | * Root is allowed to open raw volume zero even if it's not configured |
@@ -756,7 +915,8 @@ static int cciss_open(struct block_device *bdev, fmode_t mode) | |||
756 | if (MINOR(bdev->bd_dev) & 0x0f) { | 915 | if (MINOR(bdev->bd_dev) & 0x0f) { |
757 | return -ENXIO; | 916 | return -ENXIO; |
758 | /* if it is, make sure we have a LUN ID */ | 917 | /* if it is, make sure we have a LUN ID */ |
759 | } else if (drv->LunID == 0) { | 918 | } else if (memcmp(drv->LunID, CTLR_LUNID, |
919 | sizeof(drv->LunID))) { | ||
760 | return -ENXIO; | 920 | return -ENXIO; |
761 | } | 921 | } |
762 | } | 922 | } |
@@ -1121,12 +1281,13 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
1121 | case CCISS_DEREGDISK: | 1281 | case CCISS_DEREGDISK: |
1122 | case CCISS_REGNEWD: | 1282 | case CCISS_REGNEWD: |
1123 | case CCISS_REVALIDVOLS: | 1283 | case CCISS_REVALIDVOLS: |
1124 | return rebuild_lun_table(host, 0); | 1284 | return rebuild_lun_table(host, 0, 1); |
1125 | 1285 | ||
1126 | case CCISS_GETLUNINFO:{ | 1286 | case CCISS_GETLUNINFO:{ |
1127 | LogvolInfo_struct luninfo; | 1287 | LogvolInfo_struct luninfo; |
1128 | 1288 | ||
1129 | luninfo.LunID = drv->LunID; | 1289 | memcpy(&luninfo.LunID, drv->LunID, |
1290 | sizeof(luninfo.LunID)); | ||
1130 | luninfo.num_opens = drv->usage_count; | 1291 | luninfo.num_opens = drv->usage_count; |
1131 | luninfo.num_parts = 0; | 1292 | luninfo.num_parts = 0; |
1132 | if (copy_to_user(argp, &luninfo, | 1293 | if (copy_to_user(argp, &luninfo, |
@@ -1464,7 +1625,10 @@ static void cciss_check_queues(ctlr_info_t *h) | |||
1464 | /* make sure the disk has been added and the drive is real | 1625 | /* make sure the disk has been added and the drive is real |
1465 | * because this can be called from the middle of init_one. | 1626 | * because this can be called from the middle of init_one. |
1466 | */ | 1627 | */ |
1467 | if (!(h->drv[curr_queue].queue) || !(h->drv[curr_queue].heads)) | 1628 | if (!h->drv[curr_queue]) |
1629 | continue; | ||
1630 | if (!(h->drv[curr_queue]->queue) || | ||
1631 | !(h->drv[curr_queue]->heads)) | ||
1468 | continue; | 1632 | continue; |
1469 | blk_start_queue(h->gendisk[curr_queue]->queue); | 1633 | blk_start_queue(h->gendisk[curr_queue]->queue); |
1470 | 1634 | ||
@@ -1521,13 +1685,11 @@ static void cciss_softirq_done(struct request *rq) | |||
1521 | spin_unlock_irqrestore(&h->lock, flags); | 1685 | spin_unlock_irqrestore(&h->lock, flags); |
1522 | } | 1686 | } |
1523 | 1687 | ||
1524 | static void log_unit_to_scsi3addr(ctlr_info_t *h, unsigned char scsi3addr[], | 1688 | static inline void log_unit_to_scsi3addr(ctlr_info_t *h, |
1525 | uint32_t log_unit) | 1689 | unsigned char scsi3addr[], uint32_t log_unit) |
1526 | { | 1690 | { |
1527 | log_unit = h->drv[log_unit].LunID & 0x03fff; | 1691 | memcpy(scsi3addr, h->drv[log_unit]->LunID, |
1528 | memset(&scsi3addr[4], 0, 4); | 1692 | sizeof(h->drv[log_unit]->LunID)); |
1529 | memcpy(&scsi3addr[0], &log_unit, 4); | ||
1530 | scsi3addr[3] |= 0x40; | ||
1531 | } | 1693 | } |
1532 | 1694 | ||
1533 | /* This function gets the SCSI vendor, model, and revision of a logical drive | 1695 | /* This function gets the SCSI vendor, model, and revision of a logical drive |
@@ -1604,16 +1766,23 @@ static void cciss_get_serial_no(int ctlr, int logvol, int withirq, | |||
1604 | return; | 1766 | return; |
1605 | } | 1767 | } |
1606 | 1768 | ||
1607 | static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | 1769 | /* |
1770 | * cciss_add_disk sets up the block device queue for a logical drive | ||
1771 | */ | ||
1772 | static int cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | ||
1608 | int drv_index) | 1773 | int drv_index) |
1609 | { | 1774 | { |
1610 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); | 1775 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); |
1776 | if (!disk->queue) | ||
1777 | goto init_queue_failure; | ||
1611 | sprintf(disk->disk_name, "cciss/c%dd%d", h->ctlr, drv_index); | 1778 | sprintf(disk->disk_name, "cciss/c%dd%d", h->ctlr, drv_index); |
1612 | disk->major = h->major; | 1779 | disk->major = h->major; |
1613 | disk->first_minor = drv_index << NWD_SHIFT; | 1780 | disk->first_minor = drv_index << NWD_SHIFT; |
1614 | disk->fops = &cciss_fops; | 1781 | disk->fops = &cciss_fops; |
1615 | disk->private_data = &h->drv[drv_index]; | 1782 | if (cciss_create_ld_sysfs_entry(h, drv_index)) |
1616 | disk->driverfs_dev = &h->drv[drv_index].dev; | 1783 | goto cleanup_queue; |
1784 | disk->private_data = h->drv[drv_index]; | ||
1785 | disk->driverfs_dev = &h->drv[drv_index]->dev; | ||
1617 | 1786 | ||
1618 | /* Set up queue information */ | 1787 | /* Set up queue information */ |
1619 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); | 1788 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); |
@@ -1631,14 +1800,21 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | |||
1631 | disk->queue->queuedata = h; | 1800 | disk->queue->queuedata = h; |
1632 | 1801 | ||
1633 | blk_queue_logical_block_size(disk->queue, | 1802 | blk_queue_logical_block_size(disk->queue, |
1634 | h->drv[drv_index].block_size); | 1803 | h->drv[drv_index]->block_size); |
1635 | 1804 | ||
1636 | /* Make sure all queue data is written out before */ | 1805 | /* Make sure all queue data is written out before */ |
1637 | /* setting h->drv[drv_index].queue, as setting this */ | 1806 | /* setting h->drv[drv_index]->queue, as setting this */ |
1638 | /* allows the interrupt handler to start the queue */ | 1807 | /* allows the interrupt handler to start the queue */ |
1639 | wmb(); | 1808 | wmb(); |
1640 | h->drv[drv_index].queue = disk->queue; | 1809 | h->drv[drv_index]->queue = disk->queue; |
1641 | add_disk(disk); | 1810 | add_disk(disk); |
1811 | return 0; | ||
1812 | |||
1813 | cleanup_queue: | ||
1814 | blk_cleanup_queue(disk->queue); | ||
1815 | disk->queue = NULL; | ||
1816 | init_queue_failure: | ||
1817 | return -1; | ||
1642 | } | 1818 | } |
1643 | 1819 | ||
1644 | /* This function will check the usage_count of the drive to be updated/added. | 1820 | /* This function will check the usage_count of the drive to be updated/added. |
@@ -1651,7 +1827,8 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | |||
1651 | * is also the controller node. Any changes to disk 0 will show up on | 1827 | * is also the controller node. Any changes to disk 0 will show up on |
1652 | * the next reboot. | 1828 | * the next reboot. |
1653 | */ | 1829 | */ |
1654 | static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | 1830 | static void cciss_update_drive_info(int ctlr, int drv_index, int first_time, |
1831 | int via_ioctl) | ||
1655 | { | 1832 | { |
1656 | ctlr_info_t *h = hba[ctlr]; | 1833 | ctlr_info_t *h = hba[ctlr]; |
1657 | struct gendisk *disk; | 1834 | struct gendisk *disk; |
@@ -1661,21 +1838,13 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | |||
1661 | unsigned long flags = 0; | 1838 | unsigned long flags = 0; |
1662 | int ret = 0; | 1839 | int ret = 0; |
1663 | drive_info_struct *drvinfo; | 1840 | drive_info_struct *drvinfo; |
1664 | int was_only_controller_node; | ||
1665 | 1841 | ||
1666 | /* Get information about the disk and modify the driver structure */ | 1842 | /* Get information about the disk and modify the driver structure */ |
1667 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); | 1843 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); |
1668 | drvinfo = kmalloc(sizeof(*drvinfo), GFP_KERNEL); | 1844 | drvinfo = kzalloc(sizeof(*drvinfo), GFP_KERNEL); |
1669 | if (inq_buff == NULL || drvinfo == NULL) | 1845 | if (inq_buff == NULL || drvinfo == NULL) |
1670 | goto mem_msg; | 1846 | goto mem_msg; |
1671 | 1847 | ||
1672 | /* See if we're trying to update the "controller node" | ||
1673 | * this will happen the when the first logical drive gets | ||
1674 | * created by ACU. | ||
1675 | */ | ||
1676 | was_only_controller_node = (drv_index == 0 && | ||
1677 | h->drv[0].raid_level == -1); | ||
1678 | |||
1679 | /* testing to see if 16-byte CDBs are already being used */ | 1848 | /* testing to see if 16-byte CDBs are already being used */ |
1680 | if (h->cciss_read == CCISS_READ_16) { | 1849 | if (h->cciss_read == CCISS_READ_16) { |
1681 | cciss_read_capacity_16(h->ctlr, drv_index, 1, | 1850 | cciss_read_capacity_16(h->ctlr, drv_index, 1, |
@@ -1708,16 +1877,19 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | |||
1708 | drvinfo->model, drvinfo->rev); | 1877 | drvinfo->model, drvinfo->rev); |
1709 | cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no, | 1878 | cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no, |
1710 | sizeof(drvinfo->serial_no)); | 1879 | sizeof(drvinfo->serial_no)); |
1880 | /* Save the lunid in case we deregister the disk, below. */ | ||
1881 | memcpy(drvinfo->LunID, h->drv[drv_index]->LunID, | ||
1882 | sizeof(drvinfo->LunID)); | ||
1711 | 1883 | ||
1712 | /* Is it the same disk we already know, and nothing's changed? */ | 1884 | /* Is it the same disk we already know, and nothing's changed? */ |
1713 | if (h->drv[drv_index].raid_level != -1 && | 1885 | if (h->drv[drv_index]->raid_level != -1 && |
1714 | ((memcmp(drvinfo->serial_no, | 1886 | ((memcmp(drvinfo->serial_no, |
1715 | h->drv[drv_index].serial_no, 16) == 0) && | 1887 | h->drv[drv_index]->serial_no, 16) == 0) && |
1716 | drvinfo->block_size == h->drv[drv_index].block_size && | 1888 | drvinfo->block_size == h->drv[drv_index]->block_size && |
1717 | drvinfo->nr_blocks == h->drv[drv_index].nr_blocks && | 1889 | drvinfo->nr_blocks == h->drv[drv_index]->nr_blocks && |
1718 | drvinfo->heads == h->drv[drv_index].heads && | 1890 | drvinfo->heads == h->drv[drv_index]->heads && |
1719 | drvinfo->sectors == h->drv[drv_index].sectors && | 1891 | drvinfo->sectors == h->drv[drv_index]->sectors && |
1720 | drvinfo->cylinders == h->drv[drv_index].cylinders)) | 1892 | drvinfo->cylinders == h->drv[drv_index]->cylinders)) |
1721 | /* The disk is unchanged, nothing to update */ | 1893 | /* The disk is unchanged, nothing to update */ |
1722 | goto freeret; | 1894 | goto freeret; |
1723 | 1895 | ||
@@ -1727,18 +1899,17 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | |||
1727 | * If the disk already exists then deregister it before proceeding | 1899 | * If the disk already exists then deregister it before proceeding |
1728 | * (unless it's the first disk (for the controller node). | 1900 | * (unless it's the first disk (for the controller node). |
1729 | */ | 1901 | */ |
1730 | if (h->drv[drv_index].raid_level != -1 && drv_index != 0) { | 1902 | if (h->drv[drv_index]->raid_level != -1 && drv_index != 0) { |
1731 | printk(KERN_WARNING "disk %d has changed.\n", drv_index); | 1903 | printk(KERN_WARNING "disk %d has changed.\n", drv_index); |
1732 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 1904 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
1733 | h->drv[drv_index].busy_configuring = 1; | 1905 | h->drv[drv_index]->busy_configuring = 1; |
1734 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 1906 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
1735 | 1907 | ||
1736 | /* deregister_disk sets h->drv[drv_index].queue = NULL | 1908 | /* deregister_disk sets h->drv[drv_index]->queue = NULL |
1737 | * which keeps the interrupt handler from starting | 1909 | * which keeps the interrupt handler from starting |
1738 | * the queue. | 1910 | * the queue. |
1739 | */ | 1911 | */ |
1740 | ret = deregister_disk(h, drv_index, 0); | 1912 | ret = deregister_disk(h, drv_index, 0, via_ioctl); |
1741 | h->drv[drv_index].busy_configuring = 0; | ||
1742 | } | 1913 | } |
1743 | 1914 | ||
1744 | /* If the disk is in use return */ | 1915 | /* If the disk is in use return */ |
@@ -1746,22 +1917,31 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | |||
1746 | goto freeret; | 1917 | goto freeret; |
1747 | 1918 | ||
1748 | /* Save the new information from cciss_geometry_inquiry | 1919 | /* Save the new information from cciss_geometry_inquiry |
1749 | * and serial number inquiry. | 1920 | * and serial number inquiry. If the disk was deregistered |
1921 | * above, then h->drv[drv_index] will be NULL. | ||
1750 | */ | 1922 | */ |
1751 | h->drv[drv_index].block_size = drvinfo->block_size; | 1923 | if (h->drv[drv_index] == NULL) { |
1752 | h->drv[drv_index].nr_blocks = drvinfo->nr_blocks; | 1924 | drvinfo->device_initialized = 0; |
1753 | h->drv[drv_index].heads = drvinfo->heads; | 1925 | h->drv[drv_index] = drvinfo; |
1754 | h->drv[drv_index].sectors = drvinfo->sectors; | 1926 | drvinfo = NULL; /* so it won't be freed below. */ |
1755 | h->drv[drv_index].cylinders = drvinfo->cylinders; | 1927 | } else { |
1756 | h->drv[drv_index].raid_level = drvinfo->raid_level; | 1928 | /* special case for cxd0 */ |
1757 | memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16); | 1929 | h->drv[drv_index]->block_size = drvinfo->block_size; |
1758 | memcpy(h->drv[drv_index].vendor, drvinfo->vendor, VENDOR_LEN + 1); | 1930 | h->drv[drv_index]->nr_blocks = drvinfo->nr_blocks; |
1759 | memcpy(h->drv[drv_index].model, drvinfo->model, MODEL_LEN + 1); | 1931 | h->drv[drv_index]->heads = drvinfo->heads; |
1760 | memcpy(h->drv[drv_index].rev, drvinfo->rev, REV_LEN + 1); | 1932 | h->drv[drv_index]->sectors = drvinfo->sectors; |
1933 | h->drv[drv_index]->cylinders = drvinfo->cylinders; | ||
1934 | h->drv[drv_index]->raid_level = drvinfo->raid_level; | ||
1935 | memcpy(h->drv[drv_index]->serial_no, drvinfo->serial_no, 16); | ||
1936 | memcpy(h->drv[drv_index]->vendor, drvinfo->vendor, | ||
1937 | VENDOR_LEN + 1); | ||
1938 | memcpy(h->drv[drv_index]->model, drvinfo->model, MODEL_LEN + 1); | ||
1939 | memcpy(h->drv[drv_index]->rev, drvinfo->rev, REV_LEN + 1); | ||
1940 | } | ||
1761 | 1941 | ||
1762 | ++h->num_luns; | 1942 | ++h->num_luns; |
1763 | disk = h->gendisk[drv_index]; | 1943 | disk = h->gendisk[drv_index]; |
1764 | set_capacity(disk, h->drv[drv_index].nr_blocks); | 1944 | set_capacity(disk, h->drv[drv_index]->nr_blocks); |
1765 | 1945 | ||
1766 | /* If it's not disk 0 (drv_index != 0) | 1946 | /* If it's not disk 0 (drv_index != 0) |
1767 | * or if it was disk 0, but there was previously | 1947 | * or if it was disk 0, but there was previously |
@@ -1769,8 +1949,15 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | |||
1769 | * (raid_leve == -1) then we want to update the | 1949 | * (raid_leve == -1) then we want to update the |
1770 | * logical drive's information. | 1950 | * logical drive's information. |
1771 | */ | 1951 | */ |
1772 | if (drv_index || first_time) | 1952 | if (drv_index || first_time) { |
1773 | cciss_add_disk(h, disk, drv_index); | 1953 | if (cciss_add_disk(h, disk, drv_index) != 0) { |
1954 | cciss_free_gendisk(h, drv_index); | ||
1955 | cciss_free_drive_info(h, drv_index); | ||
1956 | printk(KERN_WARNING "cciss:%d could not update " | ||
1957 | "disk %d\n", h->ctlr, drv_index); | ||
1958 | --h->num_luns; | ||
1959 | } | ||
1960 | } | ||
1774 | 1961 | ||
1775 | freeret: | 1962 | freeret: |
1776 | kfree(inq_buff); | 1963 | kfree(inq_buff); |
@@ -1782,28 +1969,70 @@ mem_msg: | |||
1782 | } | 1969 | } |
1783 | 1970 | ||
1784 | /* This function will find the first index of the controllers drive array | 1971 | /* This function will find the first index of the controllers drive array |
1785 | * that has a -1 for the raid_level and will return that index. This is | 1972 | * that has a null drv pointer and allocate the drive info struct and |
1786 | * where new drives will be added. If the index to be returned is greater | 1973 | * will return that index This is where new drives will be added. |
1787 | * than the highest_lun index for the controller then highest_lun is set | 1974 | * If the index to be returned is greater than the highest_lun index for |
1788 | * to this new index. If there are no available indexes then -1 is returned. | 1975 | * the controller then highest_lun is set * to this new index. |
1789 | * "controller_node" is used to know if this is a real logical drive, or just | 1976 | * If there are no available indexes or if tha allocation fails, then -1 |
1790 | * the controller node, which determines if this counts towards highest_lun. | 1977 | * is returned. * "controller_node" is used to know if this is a real |
1978 | * logical drive, or just the controller node, which determines if this | ||
1979 | * counts towards highest_lun. | ||
1791 | */ | 1980 | */ |
1792 | static int cciss_find_free_drive_index(int ctlr, int controller_node) | 1981 | static int cciss_alloc_drive_info(ctlr_info_t *h, int controller_node) |
1793 | { | 1982 | { |
1794 | int i; | 1983 | int i; |
1984 | drive_info_struct *drv; | ||
1795 | 1985 | ||
1986 | /* Search for an empty slot for our drive info */ | ||
1796 | for (i = 0; i < CISS_MAX_LUN; i++) { | 1987 | for (i = 0; i < CISS_MAX_LUN; i++) { |
1797 | if (hba[ctlr]->drv[i].raid_level == -1) { | 1988 | |
1798 | if (i > hba[ctlr]->highest_lun) | 1989 | /* if not cxd0 case, and it's occupied, skip it. */ |
1799 | if (!controller_node) | 1990 | if (h->drv[i] && i != 0) |
1800 | hba[ctlr]->highest_lun = i; | 1991 | continue; |
1992 | /* | ||
1993 | * If it's cxd0 case, and drv is alloc'ed already, and a | ||
1994 | * disk is configured there, skip it. | ||
1995 | */ | ||
1996 | if (i == 0 && h->drv[i] && h->drv[i]->raid_level != -1) | ||
1997 | continue; | ||
1998 | |||
1999 | /* | ||
2000 | * We've found an empty slot. Update highest_lun | ||
2001 | * provided this isn't just the fake cxd0 controller node. | ||
2002 | */ | ||
2003 | if (i > h->highest_lun && !controller_node) | ||
2004 | h->highest_lun = i; | ||
2005 | |||
2006 | /* If adding a real disk at cxd0, and it's already alloc'ed */ | ||
2007 | if (i == 0 && h->drv[i] != NULL) | ||
1801 | return i; | 2008 | return i; |
1802 | } | 2009 | |
2010 | /* | ||
2011 | * Found an empty slot, not already alloc'ed. Allocate it. | ||
2012 | * Mark it with raid_level == -1, so we know it's new later on. | ||
2013 | */ | ||
2014 | drv = kzalloc(sizeof(*drv), GFP_KERNEL); | ||
2015 | if (!drv) | ||
2016 | return -1; | ||
2017 | drv->raid_level = -1; /* so we know it's new */ | ||
2018 | h->drv[i] = drv; | ||
2019 | return i; | ||
1803 | } | 2020 | } |
1804 | return -1; | 2021 | return -1; |
1805 | } | 2022 | } |
1806 | 2023 | ||
2024 | static void cciss_free_drive_info(ctlr_info_t *h, int drv_index) | ||
2025 | { | ||
2026 | kfree(h->drv[drv_index]); | ||
2027 | h->drv[drv_index] = NULL; | ||
2028 | } | ||
2029 | |||
2030 | static void cciss_free_gendisk(ctlr_info_t *h, int drv_index) | ||
2031 | { | ||
2032 | put_disk(h->gendisk[drv_index]); | ||
2033 | h->gendisk[drv_index] = NULL; | ||
2034 | } | ||
2035 | |||
1807 | /* cciss_add_gendisk finds a free hba[]->drv structure | 2036 | /* cciss_add_gendisk finds a free hba[]->drv structure |
1808 | * and allocates a gendisk if needed, and sets the lunid | 2037 | * and allocates a gendisk if needed, and sets the lunid |
1809 | * in the drvinfo structure. It returns the index into | 2038 | * in the drvinfo structure. It returns the index into |
@@ -1813,13 +2042,15 @@ static int cciss_find_free_drive_index(int ctlr, int controller_node) | |||
1813 | * a means to talk to the controller in case no logical | 2042 | * a means to talk to the controller in case no logical |
1814 | * drives have yet been configured. | 2043 | * drives have yet been configured. |
1815 | */ | 2044 | */ |
1816 | static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node) | 2045 | static int cciss_add_gendisk(ctlr_info_t *h, unsigned char lunid[], |
2046 | int controller_node) | ||
1817 | { | 2047 | { |
1818 | int drv_index; | 2048 | int drv_index; |
1819 | 2049 | ||
1820 | drv_index = cciss_find_free_drive_index(h->ctlr, controller_node); | 2050 | drv_index = cciss_alloc_drive_info(h, controller_node); |
1821 | if (drv_index == -1) | 2051 | if (drv_index == -1) |
1822 | return -1; | 2052 | return -1; |
2053 | |||
1823 | /*Check if the gendisk needs to be allocated */ | 2054 | /*Check if the gendisk needs to be allocated */ |
1824 | if (!h->gendisk[drv_index]) { | 2055 | if (!h->gendisk[drv_index]) { |
1825 | h->gendisk[drv_index] = | 2056 | h->gendisk[drv_index] = |
@@ -1828,23 +2059,24 @@ static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node) | |||
1828 | printk(KERN_ERR "cciss%d: could not " | 2059 | printk(KERN_ERR "cciss%d: could not " |
1829 | "allocate a new disk %d\n", | 2060 | "allocate a new disk %d\n", |
1830 | h->ctlr, drv_index); | 2061 | h->ctlr, drv_index); |
1831 | return -1; | 2062 | goto err_free_drive_info; |
1832 | } | 2063 | } |
1833 | } | 2064 | } |
1834 | h->drv[drv_index].LunID = lunid; | 2065 | memcpy(h->drv[drv_index]->LunID, lunid, |
1835 | if (cciss_create_ld_sysfs_entry(h, &h->drv[drv_index], drv_index)) | 2066 | sizeof(h->drv[drv_index]->LunID)); |
2067 | if (cciss_create_ld_sysfs_entry(h, drv_index)) | ||
1836 | goto err_free_disk; | 2068 | goto err_free_disk; |
1837 | |||
1838 | /* Don't need to mark this busy because nobody */ | 2069 | /* Don't need to mark this busy because nobody */ |
1839 | /* else knows about this disk yet to contend */ | 2070 | /* else knows about this disk yet to contend */ |
1840 | /* for access to it. */ | 2071 | /* for access to it. */ |
1841 | h->drv[drv_index].busy_configuring = 0; | 2072 | h->drv[drv_index]->busy_configuring = 0; |
1842 | wmb(); | 2073 | wmb(); |
1843 | return drv_index; | 2074 | return drv_index; |
1844 | 2075 | ||
1845 | err_free_disk: | 2076 | err_free_disk: |
1846 | put_disk(h->gendisk[drv_index]); | 2077 | cciss_free_gendisk(h, drv_index); |
1847 | h->gendisk[drv_index] = NULL; | 2078 | err_free_drive_info: |
2079 | cciss_free_drive_info(h, drv_index); | ||
1848 | return -1; | 2080 | return -1; |
1849 | } | 2081 | } |
1850 | 2082 | ||
@@ -1861,21 +2093,25 @@ static void cciss_add_controller_node(ctlr_info_t *h) | |||
1861 | if (h->gendisk[0] != NULL) /* already did this? Then bail. */ | 2093 | if (h->gendisk[0] != NULL) /* already did this? Then bail. */ |
1862 | return; | 2094 | return; |
1863 | 2095 | ||
1864 | drv_index = cciss_add_gendisk(h, 0, 1); | 2096 | drv_index = cciss_add_gendisk(h, CTLR_LUNID, 1); |
1865 | if (drv_index == -1) { | 2097 | if (drv_index == -1) |
1866 | printk(KERN_WARNING "cciss%d: could not " | 2098 | goto error; |
1867 | "add disk 0.\n", h->ctlr); | 2099 | h->drv[drv_index]->block_size = 512; |
1868 | return; | 2100 | h->drv[drv_index]->nr_blocks = 0; |
1869 | } | 2101 | h->drv[drv_index]->heads = 0; |
1870 | h->drv[drv_index].block_size = 512; | 2102 | h->drv[drv_index]->sectors = 0; |
1871 | h->drv[drv_index].nr_blocks = 0; | 2103 | h->drv[drv_index]->cylinders = 0; |
1872 | h->drv[drv_index].heads = 0; | 2104 | h->drv[drv_index]->raid_level = -1; |
1873 | h->drv[drv_index].sectors = 0; | 2105 | memset(h->drv[drv_index]->serial_no, 0, 16); |
1874 | h->drv[drv_index].cylinders = 0; | ||
1875 | h->drv[drv_index].raid_level = -1; | ||
1876 | memset(h->drv[drv_index].serial_no, 0, 16); | ||
1877 | disk = h->gendisk[drv_index]; | 2106 | disk = h->gendisk[drv_index]; |
1878 | cciss_add_disk(h, disk, drv_index); | 2107 | if (cciss_add_disk(h, disk, drv_index) == 0) |
2108 | return; | ||
2109 | cciss_free_gendisk(h, drv_index); | ||
2110 | cciss_free_drive_info(h, drv_index); | ||
2111 | error: | ||
2112 | printk(KERN_WARNING "cciss%d: could not " | ||
2113 | "add disk 0.\n", h->ctlr); | ||
2114 | return; | ||
1879 | } | 2115 | } |
1880 | 2116 | ||
1881 | /* This function will add and remove logical drives from the Logical | 2117 | /* This function will add and remove logical drives from the Logical |
@@ -1886,7 +2122,8 @@ static void cciss_add_controller_node(ctlr_info_t *h) | |||
1886 | * INPUT | 2122 | * INPUT |
1887 | * h = The controller to perform the operations on | 2123 | * h = The controller to perform the operations on |
1888 | */ | 2124 | */ |
1889 | static int rebuild_lun_table(ctlr_info_t *h, int first_time) | 2125 | static int rebuild_lun_table(ctlr_info_t *h, int first_time, |
2126 | int via_ioctl) | ||
1890 | { | 2127 | { |
1891 | int ctlr = h->ctlr; | 2128 | int ctlr = h->ctlr; |
1892 | int num_luns; | 2129 | int num_luns; |
@@ -1896,7 +2133,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
1896 | int i; | 2133 | int i; |
1897 | int drv_found; | 2134 | int drv_found; |
1898 | int drv_index = 0; | 2135 | int drv_index = 0; |
1899 | __u32 lunid = 0; | 2136 | unsigned char lunid[8] = CTLR_LUNID; |
1900 | unsigned long flags; | 2137 | unsigned long flags; |
1901 | 2138 | ||
1902 | if (!capable(CAP_SYS_RAWIO)) | 2139 | if (!capable(CAP_SYS_RAWIO)) |
@@ -1949,13 +2186,13 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
1949 | drv_found = 0; | 2186 | drv_found = 0; |
1950 | 2187 | ||
1951 | /* skip holes in the array from already deleted drives */ | 2188 | /* skip holes in the array from already deleted drives */ |
1952 | if (h->drv[i].raid_level == -1) | 2189 | if (h->drv[i] == NULL) |
1953 | continue; | 2190 | continue; |
1954 | 2191 | ||
1955 | for (j = 0; j < num_luns; j++) { | 2192 | for (j = 0; j < num_luns; j++) { |
1956 | memcpy(&lunid, &ld_buff->LUN[j][0], 4); | 2193 | memcpy(lunid, &ld_buff->LUN[j][0], sizeof(lunid)); |
1957 | lunid = le32_to_cpu(lunid); | 2194 | if (memcmp(h->drv[i]->LunID, lunid, |
1958 | if (h->drv[i].LunID == lunid) { | 2195 | sizeof(lunid)) == 0) { |
1959 | drv_found = 1; | 2196 | drv_found = 1; |
1960 | break; | 2197 | break; |
1961 | } | 2198 | } |
@@ -1963,11 +2200,11 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
1963 | if (!drv_found) { | 2200 | if (!drv_found) { |
1964 | /* Deregister it from the OS, it's gone. */ | 2201 | /* Deregister it from the OS, it's gone. */ |
1965 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | 2202 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
1966 | h->drv[i].busy_configuring = 1; | 2203 | h->drv[i]->busy_configuring = 1; |
1967 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 2204 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
1968 | return_code = deregister_disk(h, i, 1); | 2205 | return_code = deregister_disk(h, i, 1, via_ioctl); |
1969 | cciss_destroy_ld_sysfs_entry(&h->drv[i]); | 2206 | if (h->drv[i] != NULL) |
1970 | h->drv[i].busy_configuring = 0; | 2207 | h->drv[i]->busy_configuring = 0; |
1971 | } | 2208 | } |
1972 | } | 2209 | } |
1973 | 2210 | ||
@@ -1981,17 +2218,16 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
1981 | 2218 | ||
1982 | drv_found = 0; | 2219 | drv_found = 0; |
1983 | 2220 | ||
1984 | memcpy(&lunid, &ld_buff->LUN[i][0], 4); | 2221 | memcpy(lunid, &ld_buff->LUN[i][0], sizeof(lunid)); |
1985 | lunid = le32_to_cpu(lunid); | ||
1986 | |||
1987 | /* Find if the LUN is already in the drive array | 2222 | /* Find if the LUN is already in the drive array |
1988 | * of the driver. If so then update its info | 2223 | * of the driver. If so then update its info |
1989 | * if not in use. If it does not exist then find | 2224 | * if not in use. If it does not exist then find |
1990 | * the first free index and add it. | 2225 | * the first free index and add it. |
1991 | */ | 2226 | */ |
1992 | for (j = 0; j <= h->highest_lun; j++) { | 2227 | for (j = 0; j <= h->highest_lun; j++) { |
1993 | if (h->drv[j].raid_level != -1 && | 2228 | if (h->drv[j] != NULL && |
1994 | h->drv[j].LunID == lunid) { | 2229 | memcmp(h->drv[j]->LunID, lunid, |
2230 | sizeof(h->drv[j]->LunID)) == 0) { | ||
1995 | drv_index = j; | 2231 | drv_index = j; |
1996 | drv_found = 1; | 2232 | drv_found = 1; |
1997 | break; | 2233 | break; |
@@ -2004,7 +2240,8 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
2004 | if (drv_index == -1) | 2240 | if (drv_index == -1) |
2005 | goto freeret; | 2241 | goto freeret; |
2006 | } | 2242 | } |
2007 | cciss_update_drive_info(ctlr, drv_index, first_time); | 2243 | cciss_update_drive_info(ctlr, drv_index, first_time, |
2244 | via_ioctl); | ||
2008 | } /* end for */ | 2245 | } /* end for */ |
2009 | 2246 | ||
2010 | freeret: | 2247 | freeret: |
@@ -2021,6 +2258,25 @@ mem_msg: | |||
2021 | goto freeret; | 2258 | goto freeret; |
2022 | } | 2259 | } |
2023 | 2260 | ||
2261 | static void cciss_clear_drive_info(drive_info_struct *drive_info) | ||
2262 | { | ||
2263 | /* zero out the disk size info */ | ||
2264 | drive_info->nr_blocks = 0; | ||
2265 | drive_info->block_size = 0; | ||
2266 | drive_info->heads = 0; | ||
2267 | drive_info->sectors = 0; | ||
2268 | drive_info->cylinders = 0; | ||
2269 | drive_info->raid_level = -1; | ||
2270 | memset(drive_info->serial_no, 0, sizeof(drive_info->serial_no)); | ||
2271 | memset(drive_info->model, 0, sizeof(drive_info->model)); | ||
2272 | memset(drive_info->rev, 0, sizeof(drive_info->rev)); | ||
2273 | memset(drive_info->vendor, 0, sizeof(drive_info->vendor)); | ||
2274 | /* | ||
2275 | * don't clear the LUNID though, we need to remember which | ||
2276 | * one this one is. | ||
2277 | */ | ||
2278 | } | ||
2279 | |||
2024 | /* This function will deregister the disk and it's queue from the | 2280 | /* This function will deregister the disk and it's queue from the |
2025 | * kernel. It must be called with the controller lock held and the | 2281 | * kernel. It must be called with the controller lock held and the |
2026 | * drv structures busy_configuring flag set. It's parameters are: | 2282 | * drv structures busy_configuring flag set. It's parameters are: |
@@ -2035,43 +2291,48 @@ mem_msg: | |||
2035 | * the disk in preparation for re-adding it. In this case | 2291 | * the disk in preparation for re-adding it. In this case |
2036 | * the highest_lun should be left unchanged and the LunID | 2292 | * the highest_lun should be left unchanged and the LunID |
2037 | * should not be cleared. | 2293 | * should not be cleared. |
2294 | * via_ioctl | ||
2295 | * This indicates whether we've reached this path via ioctl. | ||
2296 | * This affects the maximum usage count allowed for c0d0 to be messed with. | ||
2297 | * If this path is reached via ioctl(), then the max_usage_count will | ||
2298 | * be 1, as the process calling ioctl() has got to have the device open. | ||
2299 | * If we get here via sysfs, then the max usage count will be zero. | ||
2038 | */ | 2300 | */ |
2039 | static int deregister_disk(ctlr_info_t *h, int drv_index, | 2301 | static int deregister_disk(ctlr_info_t *h, int drv_index, |
2040 | int clear_all) | 2302 | int clear_all, int via_ioctl) |
2041 | { | 2303 | { |
2042 | int i; | 2304 | int i; |
2043 | struct gendisk *disk; | 2305 | struct gendisk *disk; |
2044 | drive_info_struct *drv; | 2306 | drive_info_struct *drv; |
2307 | int recalculate_highest_lun; | ||
2045 | 2308 | ||
2046 | if (!capable(CAP_SYS_RAWIO)) | 2309 | if (!capable(CAP_SYS_RAWIO)) |
2047 | return -EPERM; | 2310 | return -EPERM; |
2048 | 2311 | ||
2049 | drv = &h->drv[drv_index]; | 2312 | drv = h->drv[drv_index]; |
2050 | disk = h->gendisk[drv_index]; | 2313 | disk = h->gendisk[drv_index]; |
2051 | 2314 | ||
2052 | /* make sure logical volume is NOT is use */ | 2315 | /* make sure logical volume is NOT is use */ |
2053 | if (clear_all || (h->gendisk[0] == disk)) { | 2316 | if (clear_all || (h->gendisk[0] == disk)) { |
2054 | if (drv->usage_count > 1) | 2317 | if (drv->usage_count > via_ioctl) |
2055 | return -EBUSY; | 2318 | return -EBUSY; |
2056 | } else if (drv->usage_count > 0) | 2319 | } else if (drv->usage_count > 0) |
2057 | return -EBUSY; | 2320 | return -EBUSY; |
2058 | 2321 | ||
2322 | recalculate_highest_lun = (drv == h->drv[h->highest_lun]); | ||
2323 | |||
2059 | /* invalidate the devices and deregister the disk. If it is disk | 2324 | /* invalidate the devices and deregister the disk. If it is disk |
2060 | * zero do not deregister it but just zero out it's values. This | 2325 | * zero do not deregister it but just zero out it's values. This |
2061 | * allows us to delete disk zero but keep the controller registered. | 2326 | * allows us to delete disk zero but keep the controller registered. |
2062 | */ | 2327 | */ |
2063 | if (h->gendisk[0] != disk) { | 2328 | if (h->gendisk[0] != disk) { |
2064 | struct request_queue *q = disk->queue; | 2329 | struct request_queue *q = disk->queue; |
2065 | if (disk->flags & GENHD_FL_UP) | 2330 | if (disk->flags & GENHD_FL_UP) { |
2331 | cciss_destroy_ld_sysfs_entry(h, drv_index, 0); | ||
2066 | del_gendisk(disk); | 2332 | del_gendisk(disk); |
2067 | if (q) { | ||
2068 | blk_cleanup_queue(q); | ||
2069 | /* Set drv->queue to NULL so that we do not try | ||
2070 | * to call blk_start_queue on this queue in the | ||
2071 | * interrupt handler | ||
2072 | */ | ||
2073 | drv->queue = NULL; | ||
2074 | } | 2333 | } |
2334 | if (q) | ||
2335 | blk_cleanup_queue(q); | ||
2075 | /* If clear_all is set then we are deleting the logical | 2336 | /* If clear_all is set then we are deleting the logical |
2076 | * drive, not just refreshing its info. For drives | 2337 | * drive, not just refreshing its info. For drives |
2077 | * other than disk 0 we will call put_disk. We do not | 2338 | * other than disk 0 we will call put_disk. We do not |
@@ -2094,34 +2355,20 @@ static int deregister_disk(ctlr_info_t *h, int drv_index, | |||
2094 | } | 2355 | } |
2095 | } else { | 2356 | } else { |
2096 | set_capacity(disk, 0); | 2357 | set_capacity(disk, 0); |
2358 | cciss_clear_drive_info(drv); | ||
2097 | } | 2359 | } |
2098 | 2360 | ||
2099 | --h->num_luns; | 2361 | --h->num_luns; |
2100 | /* zero out the disk size info */ | ||
2101 | drv->nr_blocks = 0; | ||
2102 | drv->block_size = 0; | ||
2103 | drv->heads = 0; | ||
2104 | drv->sectors = 0; | ||
2105 | drv->cylinders = 0; | ||
2106 | drv->raid_level = -1; /* This can be used as a flag variable to | ||
2107 | * indicate that this element of the drive | ||
2108 | * array is free. | ||
2109 | */ | ||
2110 | |||
2111 | if (clear_all) { | ||
2112 | /* check to see if it was the last disk */ | ||
2113 | if (drv == h->drv + h->highest_lun) { | ||
2114 | /* if so, find the new hightest lun */ | ||
2115 | int i, newhighest = -1; | ||
2116 | for (i = 0; i <= h->highest_lun; i++) { | ||
2117 | /* if the disk has size > 0, it is available */ | ||
2118 | if (h->drv[i].heads) | ||
2119 | newhighest = i; | ||
2120 | } | ||
2121 | h->highest_lun = newhighest; | ||
2122 | } | ||
2123 | 2362 | ||
2124 | drv->LunID = 0; | 2363 | /* if it was the last disk, find the new hightest lun */ |
2364 | if (clear_all && recalculate_highest_lun) { | ||
2365 | int i, newhighest = -1; | ||
2366 | for (i = 0; i <= h->highest_lun; i++) { | ||
2367 | /* if the disk has size > 0, it is available */ | ||
2368 | if (h->drv[i] && h->drv[i]->heads) | ||
2369 | newhighest = i; | ||
2370 | } | ||
2371 | h->highest_lun = newhighest; | ||
2125 | } | 2372 | } |
2126 | return 0; | 2373 | return 0; |
2127 | } | 2374 | } |
@@ -2468,8 +2715,6 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, | |||
2468 | } else { /* Get geometry failed */ | 2715 | } else { /* Get geometry failed */ |
2469 | printk(KERN_WARNING "cciss: reading geometry failed\n"); | 2716 | printk(KERN_WARNING "cciss: reading geometry failed\n"); |
2470 | } | 2717 | } |
2471 | printk(KERN_INFO " heads=%d, sectors=%d, cylinders=%d\n\n", | ||
2472 | drv->heads, drv->sectors, drv->cylinders); | ||
2473 | } | 2718 | } |
2474 | 2719 | ||
2475 | static void | 2720 | static void |
@@ -2503,9 +2748,6 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, | |||
2503 | *total_size = 0; | 2748 | *total_size = 0; |
2504 | *block_size = BLOCK_SIZE; | 2749 | *block_size = BLOCK_SIZE; |
2505 | } | 2750 | } |
2506 | if (*total_size != 0) | ||
2507 | printk(KERN_INFO " blocks= %llu block_size= %d\n", | ||
2508 | (unsigned long long)*total_size+1, *block_size); | ||
2509 | kfree(buf); | 2751 | kfree(buf); |
2510 | } | 2752 | } |
2511 | 2753 | ||
@@ -2557,7 +2799,8 @@ static int cciss_revalidate(struct gendisk *disk) | |||
2557 | InquiryData_struct *inq_buff = NULL; | 2799 | InquiryData_struct *inq_buff = NULL; |
2558 | 2800 | ||
2559 | for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { | 2801 | for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { |
2560 | if (h->drv[logvol].LunID == drv->LunID) { | 2802 | if (memcmp(h->drv[logvol]->LunID, drv->LunID, |
2803 | sizeof(drv->LunID)) == 0) { | ||
2561 | FOUND = 1; | 2804 | FOUND = 1; |
2562 | break; | 2805 | break; |
2563 | } | 2806 | } |
@@ -3042,8 +3285,7 @@ static void do_cciss_request(struct request_queue *q) | |||
3042 | /* The first 2 bits are reserved for controller error reporting. */ | 3285 | /* The first 2 bits are reserved for controller error reporting. */ |
3043 | c->Header.Tag.lower = (c->cmdindex << 3); | 3286 | c->Header.Tag.lower = (c->cmdindex << 3); |
3044 | c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */ | 3287 | c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */ |
3045 | c->Header.LUN.LogDev.VolId = drv->LunID; | 3288 | memcpy(&c->Header.LUN, drv->LunID, sizeof(drv->LunID)); |
3046 | c->Header.LUN.LogDev.Mode = 1; | ||
3047 | c->Request.CDBLen = 10; // 12 byte commands not in FW yet; | 3289 | c->Request.CDBLen = 10; // 12 byte commands not in FW yet; |
3048 | c->Request.Type.Type = TYPE_CMD; // It is a command. | 3290 | c->Request.Type.Type = TYPE_CMD; // It is a command. |
3049 | c->Request.Type.Attribute = ATTR_SIMPLE; | 3291 | c->Request.Type.Attribute = ATTR_SIMPLE; |
@@ -3221,20 +3463,121 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id) | |||
3221 | return IRQ_HANDLED; | 3463 | return IRQ_HANDLED; |
3222 | } | 3464 | } |
3223 | 3465 | ||
3466 | /** | ||
3467 | * add_to_scan_list() - add controller to rescan queue | ||
3468 | * @h: Pointer to the controller. | ||
3469 | * | ||
3470 | * Adds the controller to the rescan queue if not already on the queue. | ||
3471 | * | ||
3472 | * returns 1 if added to the queue, 0 if skipped (could be on the | ||
3473 | * queue already, or the controller could be initializing or shutting | ||
3474 | * down). | ||
3475 | **/ | ||
3476 | static int add_to_scan_list(struct ctlr_info *h) | ||
3477 | { | ||
3478 | struct ctlr_info *test_h; | ||
3479 | int found = 0; | ||
3480 | int ret = 0; | ||
3481 | |||
3482 | if (h->busy_initializing) | ||
3483 | return 0; | ||
3484 | |||
3485 | if (!mutex_trylock(&h->busy_shutting_down)) | ||
3486 | return 0; | ||
3487 | |||
3488 | mutex_lock(&scan_mutex); | ||
3489 | list_for_each_entry(test_h, &scan_q, scan_list) { | ||
3490 | if (test_h == h) { | ||
3491 | found = 1; | ||
3492 | break; | ||
3493 | } | ||
3494 | } | ||
3495 | if (!found && !h->busy_scanning) { | ||
3496 | INIT_COMPLETION(h->scan_wait); | ||
3497 | list_add_tail(&h->scan_list, &scan_q); | ||
3498 | ret = 1; | ||
3499 | } | ||
3500 | mutex_unlock(&scan_mutex); | ||
3501 | mutex_unlock(&h->busy_shutting_down); | ||
3502 | |||
3503 | return ret; | ||
3504 | } | ||
3505 | |||
3506 | /** | ||
3507 | * remove_from_scan_list() - remove controller from rescan queue | ||
3508 | * @h: Pointer to the controller. | ||
3509 | * | ||
3510 | * Removes the controller from the rescan queue if present. Blocks if | ||
3511 | * the controller is currently conducting a rescan. | ||
3512 | **/ | ||
3513 | static void remove_from_scan_list(struct ctlr_info *h) | ||
3514 | { | ||
3515 | struct ctlr_info *test_h, *tmp_h; | ||
3516 | int scanning = 0; | ||
3517 | |||
3518 | mutex_lock(&scan_mutex); | ||
3519 | list_for_each_entry_safe(test_h, tmp_h, &scan_q, scan_list) { | ||
3520 | if (test_h == h) { | ||
3521 | list_del(&h->scan_list); | ||
3522 | complete_all(&h->scan_wait); | ||
3523 | mutex_unlock(&scan_mutex); | ||
3524 | return; | ||
3525 | } | ||
3526 | } | ||
3527 | if (&h->busy_scanning) | ||
3528 | scanning = 0; | ||
3529 | mutex_unlock(&scan_mutex); | ||
3530 | |||
3531 | if (scanning) | ||
3532 | wait_for_completion(&h->scan_wait); | ||
3533 | } | ||
3534 | |||
3535 | /** | ||
3536 | * scan_thread() - kernel thread used to rescan controllers | ||
3537 | * @data: Ignored. | ||
3538 | * | ||
3539 | * A kernel thread used scan for drive topology changes on | ||
3540 | * controllers. The thread processes only one controller at a time | ||
3541 | * using a queue. Controllers are added to the queue using | ||
3542 | * add_to_scan_list() and removed from the queue either after done | ||
3543 | * processing or using remove_from_scan_list(). | ||
3544 | * | ||
3545 | * returns 0. | ||
3546 | **/ | ||
3224 | static int scan_thread(void *data) | 3547 | static int scan_thread(void *data) |
3225 | { | 3548 | { |
3226 | ctlr_info_t *h = data; | 3549 | struct ctlr_info *h; |
3227 | int rc; | ||
3228 | DECLARE_COMPLETION_ONSTACK(wait); | ||
3229 | h->rescan_wait = &wait; | ||
3230 | 3550 | ||
3231 | for (;;) { | 3551 | while (1) { |
3232 | rc = wait_for_completion_interruptible(&wait); | 3552 | set_current_state(TASK_INTERRUPTIBLE); |
3553 | schedule(); | ||
3233 | if (kthread_should_stop()) | 3554 | if (kthread_should_stop()) |
3234 | break; | 3555 | break; |
3235 | if (!rc) | 3556 | |
3236 | rebuild_lun_table(h, 0); | 3557 | while (1) { |
3558 | mutex_lock(&scan_mutex); | ||
3559 | if (list_empty(&scan_q)) { | ||
3560 | mutex_unlock(&scan_mutex); | ||
3561 | break; | ||
3562 | } | ||
3563 | |||
3564 | h = list_entry(scan_q.next, | ||
3565 | struct ctlr_info, | ||
3566 | scan_list); | ||
3567 | list_del(&h->scan_list); | ||
3568 | h->busy_scanning = 1; | ||
3569 | mutex_unlock(&scan_mutex); | ||
3570 | |||
3571 | if (h) { | ||
3572 | rebuild_lun_table(h, 0, 0); | ||
3573 | complete_all(&h->scan_wait); | ||
3574 | mutex_lock(&scan_mutex); | ||
3575 | h->busy_scanning = 0; | ||
3576 | mutex_unlock(&scan_mutex); | ||
3577 | } | ||
3578 | } | ||
3237 | } | 3579 | } |
3580 | |||
3238 | return 0; | 3581 | return 0; |
3239 | } | 3582 | } |
3240 | 3583 | ||
@@ -3257,8 +3600,8 @@ static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c) | |||
3257 | case REPORT_LUNS_CHANGED: | 3600 | case REPORT_LUNS_CHANGED: |
3258 | printk(KERN_WARNING "cciss%d: report LUN data " | 3601 | printk(KERN_WARNING "cciss%d: report LUN data " |
3259 | "changed\n", h->ctlr); | 3602 | "changed\n", h->ctlr); |
3260 | if (h->rescan_wait) | 3603 | add_to_scan_list(h); |
3261 | complete(h->rescan_wait); | 3604 | wake_up_process(cciss_scan_thread); |
3262 | return 1; | 3605 | return 1; |
3263 | break; | 3606 | break; |
3264 | case POWER_OR_RESET: | 3607 | case POWER_OR_RESET: |
@@ -3478,7 +3821,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) | |||
3478 | if (scratchpad == CCISS_FIRMWARE_READY) | 3821 | if (scratchpad == CCISS_FIRMWARE_READY) |
3479 | break; | 3822 | break; |
3480 | set_current_state(TASK_INTERRUPTIBLE); | 3823 | set_current_state(TASK_INTERRUPTIBLE); |
3481 | schedule_timeout(HZ / 10); /* wait 100ms */ | 3824 | schedule_timeout(msecs_to_jiffies(100)); /* wait 100ms */ |
3482 | } | 3825 | } |
3483 | if (scratchpad != CCISS_FIRMWARE_READY) { | 3826 | if (scratchpad != CCISS_FIRMWARE_READY) { |
3484 | printk(KERN_WARNING "cciss: Board not ready. Timed out.\n"); | 3827 | printk(KERN_WARNING "cciss: Board not ready. Timed out.\n"); |
@@ -3604,7 +3947,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) | |||
3604 | break; | 3947 | break; |
3605 | /* delay and try again */ | 3948 | /* delay and try again */ |
3606 | set_current_state(TASK_INTERRUPTIBLE); | 3949 | set_current_state(TASK_INTERRUPTIBLE); |
3607 | schedule_timeout(10); | 3950 | schedule_timeout(msecs_to_jiffies(1)); |
3608 | } | 3951 | } |
3609 | 3952 | ||
3610 | #ifdef CCISS_DEBUG | 3953 | #ifdef CCISS_DEBUG |
@@ -3658,15 +4001,16 @@ Enomem: | |||
3658 | return -1; | 4001 | return -1; |
3659 | } | 4002 | } |
3660 | 4003 | ||
3661 | static void free_hba(int i) | 4004 | static void free_hba(int n) |
3662 | { | 4005 | { |
3663 | ctlr_info_t *p = hba[i]; | 4006 | ctlr_info_t *h = hba[n]; |
3664 | int n; | 4007 | int i; |
3665 | 4008 | ||
3666 | hba[i] = NULL; | 4009 | hba[n] = NULL; |
3667 | for (n = 0; n < CISS_MAX_LUN; n++) | 4010 | for (i = 0; i < h->highest_lun + 1; i++) |
3668 | put_disk(p->gendisk[n]); | 4011 | if (h->gendisk[i] != NULL) |
3669 | kfree(p); | 4012 | put_disk(h->gendisk[i]); |
4013 | kfree(h); | ||
3670 | } | 4014 | } |
3671 | 4015 | ||
3672 | /* Send a message CDB to the firmware. */ | 4016 | /* Send a message CDB to the firmware. */ |
@@ -3878,7 +4222,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3878 | int j = 0; | 4222 | int j = 0; |
3879 | int rc; | 4223 | int rc; |
3880 | int dac, return_code; | 4224 | int dac, return_code; |
3881 | InquiryData_struct *inq_buff = NULL; | 4225 | InquiryData_struct *inq_buff; |
3882 | 4226 | ||
3883 | if (reset_devices) { | 4227 | if (reset_devices) { |
3884 | /* Reset the controller with a PCI power-cycle */ | 4228 | /* Reset the controller with a PCI power-cycle */ |
@@ -3907,6 +4251,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3907 | hba[i]->busy_initializing = 1; | 4251 | hba[i]->busy_initializing = 1; |
3908 | INIT_HLIST_HEAD(&hba[i]->cmpQ); | 4252 | INIT_HLIST_HEAD(&hba[i]->cmpQ); |
3909 | INIT_HLIST_HEAD(&hba[i]->reqQ); | 4253 | INIT_HLIST_HEAD(&hba[i]->reqQ); |
4254 | mutex_init(&hba[i]->busy_shutting_down); | ||
3910 | 4255 | ||
3911 | if (cciss_pci_init(hba[i], pdev) != 0) | 4256 | if (cciss_pci_init(hba[i], pdev) != 0) |
3912 | goto clean0; | 4257 | goto clean0; |
@@ -3915,6 +4260,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3915 | hba[i]->ctlr = i; | 4260 | hba[i]->ctlr = i; |
3916 | hba[i]->pdev = pdev; | 4261 | hba[i]->pdev = pdev; |
3917 | 4262 | ||
4263 | init_completion(&hba[i]->scan_wait); | ||
4264 | |||
3918 | if (cciss_create_hba_sysfs_entry(hba[i])) | 4265 | if (cciss_create_hba_sysfs_entry(hba[i])) |
3919 | goto clean0; | 4266 | goto clean0; |
3920 | 4267 | ||
@@ -3990,8 +4337,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3990 | hba[i]->num_luns = 0; | 4337 | hba[i]->num_luns = 0; |
3991 | hba[i]->highest_lun = -1; | 4338 | hba[i]->highest_lun = -1; |
3992 | for (j = 0; j < CISS_MAX_LUN; j++) { | 4339 | for (j = 0; j < CISS_MAX_LUN; j++) { |
3993 | hba[i]->drv[j].raid_level = -1; | 4340 | hba[i]->drv[j] = NULL; |
3994 | hba[i]->drv[j].queue = NULL; | ||
3995 | hba[i]->gendisk[j] = NULL; | 4341 | hba[i]->gendisk[j] = NULL; |
3996 | } | 4342 | } |
3997 | 4343 | ||
@@ -4018,23 +4364,17 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
4018 | printk(KERN_WARNING "cciss: unable to determine firmware" | 4364 | printk(KERN_WARNING "cciss: unable to determine firmware" |
4019 | " version of controller\n"); | 4365 | " version of controller\n"); |
4020 | } | 4366 | } |
4367 | kfree(inq_buff); | ||
4021 | 4368 | ||
4022 | cciss_procinit(i); | 4369 | cciss_procinit(i); |
4023 | 4370 | ||
4024 | hba[i]->cciss_max_sectors = 2048; | 4371 | hba[i]->cciss_max_sectors = 2048; |
4025 | 4372 | ||
4373 | rebuild_lun_table(hba[i], 1, 0); | ||
4026 | hba[i]->busy_initializing = 0; | 4374 | hba[i]->busy_initializing = 0; |
4027 | |||
4028 | rebuild_lun_table(hba[i], 1); | ||
4029 | hba[i]->cciss_scan_thread = kthread_run(scan_thread, hba[i], | ||
4030 | "cciss_scan%02d", i); | ||
4031 | if (IS_ERR(hba[i]->cciss_scan_thread)) | ||
4032 | return PTR_ERR(hba[i]->cciss_scan_thread); | ||
4033 | |||
4034 | return 1; | 4375 | return 1; |
4035 | 4376 | ||
4036 | clean4: | 4377 | clean4: |
4037 | kfree(inq_buff); | ||
4038 | kfree(hba[i]->cmd_pool_bits); | 4378 | kfree(hba[i]->cmd_pool_bits); |
4039 | if (hba[i]->cmd_pool) | 4379 | if (hba[i]->cmd_pool) |
4040 | pci_free_consistent(hba[i]->pdev, | 4380 | pci_free_consistent(hba[i]->pdev, |
@@ -4052,12 +4392,7 @@ clean1: | |||
4052 | cciss_destroy_hba_sysfs_entry(hba[i]); | 4392 | cciss_destroy_hba_sysfs_entry(hba[i]); |
4053 | clean0: | 4393 | clean0: |
4054 | hba[i]->busy_initializing = 0; | 4394 | hba[i]->busy_initializing = 0; |
4055 | /* cleanup any queues that may have been initialized */ | 4395 | |
4056 | for (j=0; j <= hba[i]->highest_lun; j++){ | ||
4057 | drive_info_struct *drv = &(hba[i]->drv[j]); | ||
4058 | if (drv->queue) | ||
4059 | blk_cleanup_queue(drv->queue); | ||
4060 | } | ||
4061 | /* | 4396 | /* |
4062 | * Deliberately omit pci_disable_device(): it does something nasty to | 4397 | * Deliberately omit pci_disable_device(): it does something nasty to |
4063 | * Smart Array controllers that pci_enable_device does not undo | 4398 | * Smart Array controllers that pci_enable_device does not undo |
@@ -4114,8 +4449,9 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) | |||
4114 | return; | 4449 | return; |
4115 | } | 4450 | } |
4116 | 4451 | ||
4117 | kthread_stop(hba[i]->cciss_scan_thread); | 4452 | mutex_lock(&hba[i]->busy_shutting_down); |
4118 | 4453 | ||
4454 | remove_from_scan_list(hba[i]); | ||
4119 | remove_proc_entry(hba[i]->devname, proc_cciss); | 4455 | remove_proc_entry(hba[i]->devname, proc_cciss); |
4120 | unregister_blkdev(hba[i]->major, hba[i]->devname); | 4456 | unregister_blkdev(hba[i]->major, hba[i]->devname); |
4121 | 4457 | ||
@@ -4125,8 +4461,10 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) | |||
4125 | if (disk) { | 4461 | if (disk) { |
4126 | struct request_queue *q = disk->queue; | 4462 | struct request_queue *q = disk->queue; |
4127 | 4463 | ||
4128 | if (disk->flags & GENHD_FL_UP) | 4464 | if (disk->flags & GENHD_FL_UP) { |
4465 | cciss_destroy_ld_sysfs_entry(hba[i], j, 1); | ||
4129 | del_gendisk(disk); | 4466 | del_gendisk(disk); |
4467 | } | ||
4130 | if (q) | 4468 | if (q) |
4131 | blk_cleanup_queue(q); | 4469 | blk_cleanup_queue(q); |
4132 | } | 4470 | } |
@@ -4159,6 +4497,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) | |||
4159 | pci_release_regions(pdev); | 4497 | pci_release_regions(pdev); |
4160 | pci_set_drvdata(pdev, NULL); | 4498 | pci_set_drvdata(pdev, NULL); |
4161 | cciss_destroy_hba_sysfs_entry(hba[i]); | 4499 | cciss_destroy_hba_sysfs_entry(hba[i]); |
4500 | mutex_unlock(&hba[i]->busy_shutting_down); | ||
4162 | free_hba(i); | 4501 | free_hba(i); |
4163 | } | 4502 | } |
4164 | 4503 | ||
@@ -4191,15 +4530,25 @@ static int __init cciss_init(void) | |||
4191 | if (err) | 4530 | if (err) |
4192 | return err; | 4531 | return err; |
4193 | 4532 | ||
4533 | /* Start the scan thread */ | ||
4534 | cciss_scan_thread = kthread_run(scan_thread, NULL, "cciss_scan"); | ||
4535 | if (IS_ERR(cciss_scan_thread)) { | ||
4536 | err = PTR_ERR(cciss_scan_thread); | ||
4537 | goto err_bus_unregister; | ||
4538 | } | ||
4539 | |||
4194 | /* Register for our PCI devices */ | 4540 | /* Register for our PCI devices */ |
4195 | err = pci_register_driver(&cciss_pci_driver); | 4541 | err = pci_register_driver(&cciss_pci_driver); |
4196 | if (err) | 4542 | if (err) |
4197 | goto err_bus_register; | 4543 | goto err_thread_stop; |
4198 | 4544 | ||
4199 | return 0; | 4545 | return err; |
4200 | 4546 | ||
4201 | err_bus_register: | 4547 | err_thread_stop: |
4548 | kthread_stop(cciss_scan_thread); | ||
4549 | err_bus_unregister: | ||
4202 | bus_unregister(&cciss_bus_type); | 4550 | bus_unregister(&cciss_bus_type); |
4551 | |||
4203 | return err; | 4552 | return err; |
4204 | } | 4553 | } |
4205 | 4554 | ||
@@ -4216,6 +4565,7 @@ static void __exit cciss_cleanup(void) | |||
4216 | cciss_remove_one(hba[i]->pdev); | 4565 | cciss_remove_one(hba[i]->pdev); |
4217 | } | 4566 | } |
4218 | } | 4567 | } |
4568 | kthread_stop(cciss_scan_thread); | ||
4219 | remove_proc_entry("driver/cciss", NULL); | 4569 | remove_proc_entry("driver/cciss", NULL); |
4220 | bus_unregister(&cciss_bus_type); | 4570 | bus_unregister(&cciss_bus_type); |
4221 | } | 4571 | } |
@@ -4246,7 +4596,8 @@ static void fail_all_cmds(unsigned long ctlr) | |||
4246 | while (!hlist_empty(&h->cmpQ)) { | 4596 | while (!hlist_empty(&h->cmpQ)) { |
4247 | c = hlist_entry(h->cmpQ.first, CommandList_struct, list); | 4597 | c = hlist_entry(h->cmpQ.first, CommandList_struct, list); |
4248 | removeQ(c); | 4598 | removeQ(c); |
4249 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | 4599 | if (c->cmd_type != CMD_MSG_STALE) |
4600 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | ||
4250 | if (c->cmd_type == CMD_RWREQ) { | 4601 | if (c->cmd_type == CMD_RWREQ) { |
4251 | complete_command(h, c, 0); | 4602 | complete_command(h, c, 0); |
4252 | } else if (c->cmd_type == CMD_IOCTL_PEND) | 4603 | } else if (c->cmd_type == CMD_IOCTL_PEND) |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 06a5db25b29..31524cf42c7 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define CCISS_H | 2 | #define CCISS_H |
3 | 3 | ||
4 | #include <linux/genhd.h> | 4 | #include <linux/genhd.h> |
5 | #include <linux/mutex.h> | ||
5 | 6 | ||
6 | #include "cciss_cmd.h" | 7 | #include "cciss_cmd.h" |
7 | 8 | ||
@@ -29,7 +30,7 @@ struct access_method { | |||
29 | }; | 30 | }; |
30 | typedef struct _drive_info_struct | 31 | typedef struct _drive_info_struct |
31 | { | 32 | { |
32 | __u32 LunID; | 33 | unsigned char LunID[8]; |
33 | int usage_count; | 34 | int usage_count; |
34 | struct request_queue *queue; | 35 | struct request_queue *queue; |
35 | sector_t nr_blocks; | 36 | sector_t nr_blocks; |
@@ -51,6 +52,7 @@ typedef struct _drive_info_struct | |||
51 | char vendor[VENDOR_LEN + 1]; /* SCSI vendor string */ | 52 | char vendor[VENDOR_LEN + 1]; /* SCSI vendor string */ |
52 | char model[MODEL_LEN + 1]; /* SCSI model string */ | 53 | char model[MODEL_LEN + 1]; /* SCSI model string */ |
53 | char rev[REV_LEN + 1]; /* SCSI revision string */ | 54 | char rev[REV_LEN + 1]; /* SCSI revision string */ |
55 | char device_initialized; /* indicates whether dev is initialized */ | ||
54 | } drive_info_struct; | 56 | } drive_info_struct; |
55 | 57 | ||
56 | struct ctlr_info | 58 | struct ctlr_info |
@@ -86,7 +88,7 @@ struct ctlr_info | |||
86 | BYTE cciss_read_capacity; | 88 | BYTE cciss_read_capacity; |
87 | 89 | ||
88 | // information about each logical volume | 90 | // information about each logical volume |
89 | drive_info_struct drv[CISS_MAX_LUN]; | 91 | drive_info_struct *drv[CISS_MAX_LUN]; |
90 | 92 | ||
91 | struct access_method access; | 93 | struct access_method access; |
92 | 94 | ||
@@ -108,6 +110,8 @@ struct ctlr_info | |||
108 | int nr_frees; | 110 | int nr_frees; |
109 | int busy_configuring; | 111 | int busy_configuring; |
110 | int busy_initializing; | 112 | int busy_initializing; |
113 | int busy_scanning; | ||
114 | struct mutex busy_shutting_down; | ||
111 | 115 | ||
112 | /* This element holds the zero based queue number of the last | 116 | /* This element holds the zero based queue number of the last |
113 | * queue to be started. It is used for fairness. | 117 | * queue to be started. It is used for fairness. |
@@ -122,8 +126,8 @@ struct ctlr_info | |||
122 | /* and saved for later processing */ | 126 | /* and saved for later processing */ |
123 | #endif | 127 | #endif |
124 | unsigned char alive; | 128 | unsigned char alive; |
125 | struct completion *rescan_wait; | 129 | struct list_head scan_list; |
126 | struct task_struct *cciss_scan_thread; | 130 | struct completion scan_wait; |
127 | struct device dev; | 131 | struct device dev; |
128 | }; | 132 | }; |
129 | 133 | ||
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index cd665b00c7c..dbaed1ea0da 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h | |||
@@ -274,6 +274,7 @@ typedef struct _ErrorInfo_struct { | |||
274 | #define CMD_SCSI 0x03 | 274 | #define CMD_SCSI 0x03 |
275 | #define CMD_MSG_DONE 0x04 | 275 | #define CMD_MSG_DONE 0x04 |
276 | #define CMD_MSG_TIMEOUT 0x05 | 276 | #define CMD_MSG_TIMEOUT 0x05 |
277 | #define CMD_MSG_STALE 0xff | ||
277 | 278 | ||
278 | /* This structure needs to be divisible by 8 for new | 279 | /* This structure needs to be divisible by 8 for new |
279 | * indexing method. | 280 | * indexing method. |
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 44fa2018f6b..6422651ec36 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/blkpg.h> | 32 | #include <linux/blkpg.h> |
33 | #include <linux/timer.h> | 33 | #include <linux/timer.h> |
34 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
35 | #include <linux/seq_file.h> | ||
35 | #include <linux/init.h> | 36 | #include <linux/init.h> |
36 | #include <linux/hdreg.h> | 37 | #include <linux/hdreg.h> |
37 | #include <linux/spinlock.h> | 38 | #include <linux/spinlock.h> |
@@ -177,7 +178,6 @@ static int cpqarray_register_ctlr(int ctlr, struct pci_dev *pdev); | |||
177 | 178 | ||
178 | #ifdef CONFIG_PROC_FS | 179 | #ifdef CONFIG_PROC_FS |
179 | static void ida_procinit(int i); | 180 | static void ida_procinit(int i); |
180 | static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data); | ||
181 | #else | 181 | #else |
182 | static void ida_procinit(int i) {} | 182 | static void ida_procinit(int i) {} |
183 | #endif | 183 | #endif |
@@ -193,7 +193,7 @@ static inline ctlr_info_t *get_host(struct gendisk *disk) | |||
193 | } | 193 | } |
194 | 194 | ||
195 | 195 | ||
196 | static struct block_device_operations ida_fops = { | 196 | static const struct block_device_operations ida_fops = { |
197 | .owner = THIS_MODULE, | 197 | .owner = THIS_MODULE, |
198 | .open = ida_open, | 198 | .open = ida_open, |
199 | .release = ida_release, | 199 | .release = ida_release, |
@@ -206,6 +206,7 @@ static struct block_device_operations ida_fops = { | |||
206 | #ifdef CONFIG_PROC_FS | 206 | #ifdef CONFIG_PROC_FS |
207 | 207 | ||
208 | static struct proc_dir_entry *proc_array; | 208 | static struct proc_dir_entry *proc_array; |
209 | static const struct file_operations ida_proc_fops; | ||
209 | 210 | ||
210 | /* | 211 | /* |
211 | * Get us a file in /proc/array that says something about each controller. | 212 | * Get us a file in /proc/array that says something about each controller. |
@@ -218,19 +219,16 @@ static void __init ida_procinit(int i) | |||
218 | if (!proc_array) return; | 219 | if (!proc_array) return; |
219 | } | 220 | } |
220 | 221 | ||
221 | create_proc_read_entry(hba[i]->devname, 0, proc_array, | 222 | proc_create_data(hba[i]->devname, 0, proc_array, &ida_proc_fops, hba[i]); |
222 | ida_proc_get_info, hba[i]); | ||
223 | } | 223 | } |
224 | 224 | ||
225 | /* | 225 | /* |
226 | * Report information about this controller. | 226 | * Report information about this controller. |
227 | */ | 227 | */ |
228 | static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data) | 228 | static int ida_proc_show(struct seq_file *m, void *v) |
229 | { | 229 | { |
230 | off_t pos = 0; | 230 | int i, ctlr; |
231 | off_t len = 0; | 231 | ctlr_info_t *h = (ctlr_info_t*)m->private; |
232 | int size, i, ctlr; | ||
233 | ctlr_info_t *h = (ctlr_info_t*)data; | ||
234 | drv_info_t *drv; | 232 | drv_info_t *drv; |
235 | #ifdef CPQ_PROC_PRINT_QUEUES | 233 | #ifdef CPQ_PROC_PRINT_QUEUES |
236 | cmdlist_t *c; | 234 | cmdlist_t *c; |
@@ -238,7 +236,7 @@ static int ida_proc_get_info(char *buffer, char **start, off_t offset, int lengt | |||
238 | #endif | 236 | #endif |
239 | 237 | ||
240 | ctlr = h->ctlr; | 238 | ctlr = h->ctlr; |
241 | size = sprintf(buffer, "%s: Compaq %s Controller\n" | 239 | seq_printf(m, "%s: Compaq %s Controller\n" |
242 | " Board ID: 0x%08lx\n" | 240 | " Board ID: 0x%08lx\n" |
243 | " Firmware Revision: %c%c%c%c\n" | 241 | " Firmware Revision: %c%c%c%c\n" |
244 | " Controller Sig: 0x%08lx\n" | 242 | " Controller Sig: 0x%08lx\n" |
@@ -258,55 +256,54 @@ static int ida_proc_get_info(char *buffer, char **start, off_t offset, int lengt | |||
258 | h->log_drives, h->phys_drives, | 256 | h->log_drives, h->phys_drives, |
259 | h->Qdepth, h->maxQsinceinit); | 257 | h->Qdepth, h->maxQsinceinit); |
260 | 258 | ||
261 | pos += size; len += size; | 259 | seq_puts(m, "Logical Drive Info:\n"); |
262 | |||
263 | size = sprintf(buffer+len, "Logical Drive Info:\n"); | ||
264 | pos += size; len += size; | ||
265 | 260 | ||
266 | for(i=0; i<h->log_drives; i++) { | 261 | for(i=0; i<h->log_drives; i++) { |
267 | drv = &h->drv[i]; | 262 | drv = &h->drv[i]; |
268 | size = sprintf(buffer+len, "ida/c%dd%d: blksz=%d nr_blks=%d\n", | 263 | seq_printf(m, "ida/c%dd%d: blksz=%d nr_blks=%d\n", |
269 | ctlr, i, drv->blk_size, drv->nr_blks); | 264 | ctlr, i, drv->blk_size, drv->nr_blks); |
270 | pos += size; len += size; | ||
271 | } | 265 | } |
272 | 266 | ||
273 | #ifdef CPQ_PROC_PRINT_QUEUES | 267 | #ifdef CPQ_PROC_PRINT_QUEUES |
274 | spin_lock_irqsave(IDA_LOCK(h->ctlr), flags); | 268 | spin_lock_irqsave(IDA_LOCK(h->ctlr), flags); |
275 | size = sprintf(buffer+len, "\nCurrent Queues:\n"); | 269 | seq_puts(m, "\nCurrent Queues:\n"); |
276 | pos += size; len += size; | ||
277 | 270 | ||
278 | c = h->reqQ; | 271 | c = h->reqQ; |
279 | size = sprintf(buffer+len, "reqQ = %p", c); pos += size; len += size; | 272 | seq_printf(m, "reqQ = %p", c); |
280 | if (c) c=c->next; | 273 | if (c) c=c->next; |
281 | while(c && c != h->reqQ) { | 274 | while(c && c != h->reqQ) { |
282 | size = sprintf(buffer+len, "->%p", c); | 275 | seq_printf(m, "->%p", c); |
283 | pos += size; len += size; | ||
284 | c=c->next; | 276 | c=c->next; |
285 | } | 277 | } |
286 | 278 | ||
287 | c = h->cmpQ; | 279 | c = h->cmpQ; |
288 | size = sprintf(buffer+len, "\ncmpQ = %p", c); pos += size; len += size; | 280 | seq_printf(m, "\ncmpQ = %p", c); |
289 | if (c) c=c->next; | 281 | if (c) c=c->next; |
290 | while(c && c != h->cmpQ) { | 282 | while(c && c != h->cmpQ) { |
291 | size = sprintf(buffer+len, "->%p", c); | 283 | seq_printf(m, "->%p", c); |
292 | pos += size; len += size; | ||
293 | c=c->next; | 284 | c=c->next; |
294 | } | 285 | } |
295 | 286 | ||
296 | size = sprintf(buffer+len, "\n"); pos += size; len += size; | 287 | seq_putc(m, '\n'); |
297 | spin_unlock_irqrestore(IDA_LOCK(h->ctlr), flags); | 288 | spin_unlock_irqrestore(IDA_LOCK(h->ctlr), flags); |
298 | #endif | 289 | #endif |
299 | size = sprintf(buffer+len, "nr_allocs = %d\nnr_frees = %d\n", | 290 | seq_printf(m, "nr_allocs = %d\nnr_frees = %d\n", |
300 | h->nr_allocs, h->nr_frees); | 291 | h->nr_allocs, h->nr_frees); |
301 | pos += size; len += size; | 292 | return 0; |
302 | 293 | } | |
303 | *eof = 1; | 294 | |
304 | *start = buffer+offset; | 295 | static int ida_proc_open(struct inode *inode, struct file *file) |
305 | len -= offset; | 296 | { |
306 | if (len>length) | 297 | return single_open(file, ida_proc_show, PDE(inode)->data); |
307 | len = length; | ||
308 | return len; | ||
309 | } | 298 | } |
299 | |||
300 | static const struct file_operations ida_proc_fops = { | ||
301 | .owner = THIS_MODULE, | ||
302 | .open = ida_proc_open, | ||
303 | .read = seq_read, | ||
304 | .llseek = seq_lseek, | ||
305 | .release = single_release, | ||
306 | }; | ||
310 | #endif /* CONFIG_PROC_FS */ | 307 | #endif /* CONFIG_PROC_FS */ |
311 | 308 | ||
312 | module_param_array(eisa, int, NULL, 0); | 309 | module_param_array(eisa, int, NULL, 0); |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 862b40c9018..5c01f747571 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -3327,7 +3327,10 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, | |||
3327 | if (!capable(CAP_SYS_ADMIN)) | 3327 | if (!capable(CAP_SYS_ADMIN)) |
3328 | return -EPERM; | 3328 | return -EPERM; |
3329 | mutex_lock(&open_lock); | 3329 | mutex_lock(&open_lock); |
3330 | LOCK_FDC(drive, 1); | 3330 | if (lock_fdc(drive, 1)) { |
3331 | mutex_unlock(&open_lock); | ||
3332 | return -EINTR; | ||
3333 | } | ||
3331 | floppy_type[type] = *g; | 3334 | floppy_type[type] = *g; |
3332 | floppy_type[type].name = "user format"; | 3335 | floppy_type[type].name = "user format"; |
3333 | for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) | 3336 | for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) |
@@ -3904,7 +3907,7 @@ static int floppy_revalidate(struct gendisk *disk) | |||
3904 | return res; | 3907 | return res; |
3905 | } | 3908 | } |
3906 | 3909 | ||
3907 | static struct block_device_operations floppy_fops = { | 3910 | static const struct block_device_operations floppy_fops = { |
3908 | .owner = THIS_MODULE, | 3911 | .owner = THIS_MODULE, |
3909 | .open = floppy_open, | 3912 | .open = floppy_open, |
3910 | .release = floppy_release, | 3913 | .release = floppy_release, |
@@ -4148,7 +4151,7 @@ static void floppy_device_release(struct device *dev) | |||
4148 | { | 4151 | { |
4149 | } | 4152 | } |
4150 | 4153 | ||
4151 | static int floppy_resume(struct platform_device *dev) | 4154 | static int floppy_resume(struct device *dev) |
4152 | { | 4155 | { |
4153 | int fdc; | 4156 | int fdc; |
4154 | 4157 | ||
@@ -4159,10 +4162,15 @@ static int floppy_resume(struct platform_device *dev) | |||
4159 | return 0; | 4162 | return 0; |
4160 | } | 4163 | } |
4161 | 4164 | ||
4162 | static struct platform_driver floppy_driver = { | 4165 | static struct dev_pm_ops floppy_pm_ops = { |
4163 | .resume = floppy_resume, | 4166 | .resume = floppy_resume, |
4167 | .restore = floppy_resume, | ||
4168 | }; | ||
4169 | |||
4170 | static struct platform_driver floppy_driver = { | ||
4164 | .driver = { | 4171 | .driver = { |
4165 | .name = "floppy", | 4172 | .name = "floppy", |
4173 | .pm = &floppy_pm_ops, | ||
4166 | }, | 4174 | }, |
4167 | }; | 4175 | }; |
4168 | 4176 | ||
diff --git a/drivers/block/hd.c b/drivers/block/hd.c index f9d01608cbe..d5cdce08ffd 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c | |||
@@ -692,7 +692,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id) | |||
692 | return IRQ_HANDLED; | 692 | return IRQ_HANDLED; |
693 | } | 693 | } |
694 | 694 | ||
695 | static struct block_device_operations hd_fops = { | 695 | static const struct block_device_operations hd_fops = { |
696 | .getgeo = hd_getgeo, | 696 | .getgeo = hd_getgeo, |
697 | }; | 697 | }; |
698 | 698 | ||
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 801f4ab8330..edda9ea7c62 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -61,7 +61,6 @@ | |||
61 | #include <linux/blkdev.h> | 61 | #include <linux/blkdev.h> |
62 | #include <linux/blkpg.h> | 62 | #include <linux/blkpg.h> |
63 | #include <linux/init.h> | 63 | #include <linux/init.h> |
64 | #include <linux/smp_lock.h> | ||
65 | #include <linux/swap.h> | 64 | #include <linux/swap.h> |
66 | #include <linux/slab.h> | 65 | #include <linux/slab.h> |
67 | #include <linux/loop.h> | 66 | #include <linux/loop.h> |
@@ -476,7 +475,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) | |||
476 | pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; | 475 | pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; |
477 | 476 | ||
478 | if (bio_rw(bio) == WRITE) { | 477 | if (bio_rw(bio) == WRITE) { |
479 | int barrier = bio_barrier(bio); | 478 | bool barrier = bio_rw_flagged(bio, BIO_RW_BARRIER); |
480 | struct file *file = lo->lo_backing_file; | 479 | struct file *file = lo->lo_backing_file; |
481 | 480 | ||
482 | if (barrier) { | 481 | if (barrier) { |
@@ -1439,7 +1438,7 @@ out_unlocked: | |||
1439 | return 0; | 1438 | return 0; |
1440 | } | 1439 | } |
1441 | 1440 | ||
1442 | static struct block_device_operations lo_fops = { | 1441 | static const struct block_device_operations lo_fops = { |
1443 | .owner = THIS_MODULE, | 1442 | .owner = THIS_MODULE, |
1444 | .open = lo_open, | 1443 | .open = lo_open, |
1445 | .release = lo_release, | 1444 | .release = lo_release, |
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index f703f547824..e0339aaa181 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c | |||
@@ -36,7 +36,6 @@ | |||
36 | 36 | ||
37 | /* Register offsets */ | 37 | /* Register offsets */ |
38 | #define MG_BUFF_OFFSET 0x8000 | 38 | #define MG_BUFF_OFFSET 0x8000 |
39 | #define MG_STORAGE_BUFFER_SIZE 0x200 | ||
40 | #define MG_REG_OFFSET 0xC000 | 39 | #define MG_REG_OFFSET 0xC000 |
41 | #define MG_REG_FEATURE (MG_REG_OFFSET + 2) /* write case */ | 40 | #define MG_REG_FEATURE (MG_REG_OFFSET + 2) /* write case */ |
42 | #define MG_REG_ERROR (MG_REG_OFFSET + 2) /* read case */ | 41 | #define MG_REG_ERROR (MG_REG_OFFSET + 2) /* read case */ |
@@ -219,6 +218,16 @@ static unsigned int mg_wait(struct mg_host *host, u32 expect, u32 msec) | |||
219 | host->error = MG_ERR_NONE; | 218 | host->error = MG_ERR_NONE; |
220 | expire = jiffies + msecs_to_jiffies(msec); | 219 | expire = jiffies + msecs_to_jiffies(msec); |
221 | 220 | ||
221 | /* These 2 times dummy status read prevents reading invalid | ||
222 | * status. A very little time (3 times of mflash operating clk) | ||
223 | * is required for busy bit is set. Use dummy read instead of | ||
224 | * busy wait, because mflash's PLL is machine dependent. | ||
225 | */ | ||
226 | if (prv_data->use_polling) { | ||
227 | status = inb((unsigned long)host->dev_base + MG_REG_STATUS); | ||
228 | status = inb((unsigned long)host->dev_base + MG_REG_STATUS); | ||
229 | } | ||
230 | |||
222 | status = inb((unsigned long)host->dev_base + MG_REG_STATUS); | 231 | status = inb((unsigned long)host->dev_base + MG_REG_STATUS); |
223 | 232 | ||
224 | do { | 233 | do { |
@@ -245,8 +254,6 @@ static unsigned int mg_wait(struct mg_host *host, u32 expect, u32 msec) | |||
245 | mg_dump_status("not ready", status, host); | 254 | mg_dump_status("not ready", status, host); |
246 | return MG_ERR_INV_STAT; | 255 | return MG_ERR_INV_STAT; |
247 | } | 256 | } |
248 | if (prv_data->use_polling) | ||
249 | msleep(1); | ||
250 | 257 | ||
251 | status = inb((unsigned long)host->dev_base + MG_REG_STATUS); | 258 | status = inb((unsigned long)host->dev_base + MG_REG_STATUS); |
252 | } while (time_before(cur_jiffies, expire)); | 259 | } while (time_before(cur_jiffies, expire)); |
@@ -469,9 +476,18 @@ static unsigned int mg_out(struct mg_host *host, | |||
469 | return MG_ERR_NONE; | 476 | return MG_ERR_NONE; |
470 | } | 477 | } |
471 | 478 | ||
479 | static void mg_read_one(struct mg_host *host, struct request *req) | ||
480 | { | ||
481 | u16 *buff = (u16 *)req->buffer; | ||
482 | u32 i; | ||
483 | |||
484 | for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) | ||
485 | *buff++ = inw((unsigned long)host->dev_base + MG_BUFF_OFFSET + | ||
486 | (i << 1)); | ||
487 | } | ||
488 | |||
472 | static void mg_read(struct request *req) | 489 | static void mg_read(struct request *req) |
473 | { | 490 | { |
474 | u32 j; | ||
475 | struct mg_host *host = req->rq_disk->private_data; | 491 | struct mg_host *host = req->rq_disk->private_data; |
476 | 492 | ||
477 | if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req), | 493 | if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req), |
@@ -482,49 +498,65 @@ static void mg_read(struct request *req) | |||
482 | blk_rq_sectors(req), blk_rq_pos(req), req->buffer); | 498 | blk_rq_sectors(req), blk_rq_pos(req), req->buffer); |
483 | 499 | ||
484 | do { | 500 | do { |
485 | u16 *buff = (u16 *)req->buffer; | ||
486 | |||
487 | if (mg_wait(host, ATA_DRQ, | 501 | if (mg_wait(host, ATA_DRQ, |
488 | MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) { | 502 | MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) { |
489 | mg_bad_rw_intr(host); | 503 | mg_bad_rw_intr(host); |
490 | return; | 504 | return; |
491 | } | 505 | } |
492 | for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) | 506 | |
493 | *buff++ = inw((unsigned long)host->dev_base + | 507 | mg_read_one(host, req); |
494 | MG_BUFF_OFFSET + (j << 1)); | ||
495 | 508 | ||
496 | outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + | 509 | outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + |
497 | MG_REG_COMMAND); | 510 | MG_REG_COMMAND); |
498 | } while (mg_end_request(host, 0, MG_SECTOR_SIZE)); | 511 | } while (mg_end_request(host, 0, MG_SECTOR_SIZE)); |
499 | } | 512 | } |
500 | 513 | ||
514 | static void mg_write_one(struct mg_host *host, struct request *req) | ||
515 | { | ||
516 | u16 *buff = (u16 *)req->buffer; | ||
517 | u32 i; | ||
518 | |||
519 | for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) | ||
520 | outw(*buff++, (unsigned long)host->dev_base + MG_BUFF_OFFSET + | ||
521 | (i << 1)); | ||
522 | } | ||
523 | |||
501 | static void mg_write(struct request *req) | 524 | static void mg_write(struct request *req) |
502 | { | 525 | { |
503 | u32 j; | ||
504 | struct mg_host *host = req->rq_disk->private_data; | 526 | struct mg_host *host = req->rq_disk->private_data; |
527 | unsigned int rem = blk_rq_sectors(req); | ||
505 | 528 | ||
506 | if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req), | 529 | if (mg_out(host, blk_rq_pos(req), rem, |
507 | MG_CMD_WR, NULL) != MG_ERR_NONE) { | 530 | MG_CMD_WR, NULL) != MG_ERR_NONE) { |
508 | mg_bad_rw_intr(host); | 531 | mg_bad_rw_intr(host); |
509 | return; | 532 | return; |
510 | } | 533 | } |
511 | 534 | ||
512 | MG_DBG("requested %d sects (from %ld), buffer=0x%p\n", | 535 | MG_DBG("requested %d sects (from %ld), buffer=0x%p\n", |
513 | blk_rq_sectors(req), blk_rq_pos(req), req->buffer); | 536 | rem, blk_rq_pos(req), req->buffer); |
537 | |||
538 | if (mg_wait(host, ATA_DRQ, | ||
539 | MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) { | ||
540 | mg_bad_rw_intr(host); | ||
541 | return; | ||
542 | } | ||
514 | 543 | ||
515 | do { | 544 | do { |
516 | u16 *buff = (u16 *)req->buffer; | 545 | mg_write_one(host, req); |
517 | 546 | ||
518 | if (mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) { | 547 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + |
548 | MG_REG_COMMAND); | ||
549 | |||
550 | rem--; | ||
551 | if (rem > 1 && mg_wait(host, ATA_DRQ, | ||
552 | MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) { | ||
553 | mg_bad_rw_intr(host); | ||
554 | return; | ||
555 | } else if (mg_wait(host, MG_STAT_READY, | ||
556 | MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) { | ||
519 | mg_bad_rw_intr(host); | 557 | mg_bad_rw_intr(host); |
520 | return; | 558 | return; |
521 | } | 559 | } |
522 | for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) | ||
523 | outw(*buff++, (unsigned long)host->dev_base + | ||
524 | MG_BUFF_OFFSET + (j << 1)); | ||
525 | |||
526 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + | ||
527 | MG_REG_COMMAND); | ||
528 | } while (mg_end_request(host, 0, MG_SECTOR_SIZE)); | 560 | } while (mg_end_request(host, 0, MG_SECTOR_SIZE)); |
529 | } | 561 | } |
530 | 562 | ||
@@ -532,7 +564,6 @@ static void mg_read_intr(struct mg_host *host) | |||
532 | { | 564 | { |
533 | struct request *req = host->req; | 565 | struct request *req = host->req; |
534 | u32 i; | 566 | u32 i; |
535 | u16 *buff; | ||
536 | 567 | ||
537 | /* check status */ | 568 | /* check status */ |
538 | do { | 569 | do { |
@@ -550,13 +581,7 @@ static void mg_read_intr(struct mg_host *host) | |||
550 | return; | 581 | return; |
551 | 582 | ||
552 | ok_to_read: | 583 | ok_to_read: |
553 | /* get current segment of request */ | 584 | mg_read_one(host, req); |
554 | buff = (u16 *)req->buffer; | ||
555 | |||
556 | /* read 1 sector */ | ||
557 | for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) | ||
558 | *buff++ = inw((unsigned long)host->dev_base + MG_BUFF_OFFSET + | ||
559 | (i << 1)); | ||
560 | 585 | ||
561 | MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n", | 586 | MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n", |
562 | blk_rq_pos(req), blk_rq_sectors(req) - 1, req->buffer); | 587 | blk_rq_pos(req), blk_rq_sectors(req) - 1, req->buffer); |
@@ -575,8 +600,7 @@ ok_to_read: | |||
575 | static void mg_write_intr(struct mg_host *host) | 600 | static void mg_write_intr(struct mg_host *host) |
576 | { | 601 | { |
577 | struct request *req = host->req; | 602 | struct request *req = host->req; |
578 | u32 i, j; | 603 | u32 i; |
579 | u16 *buff; | ||
580 | bool rem; | 604 | bool rem; |
581 | 605 | ||
582 | /* check status */ | 606 | /* check status */ |
@@ -597,12 +621,7 @@ static void mg_write_intr(struct mg_host *host) | |||
597 | ok_to_write: | 621 | ok_to_write: |
598 | if ((rem = mg_end_request(host, 0, MG_SECTOR_SIZE))) { | 622 | if ((rem = mg_end_request(host, 0, MG_SECTOR_SIZE))) { |
599 | /* write 1 sector and set handler if remains */ | 623 | /* write 1 sector and set handler if remains */ |
600 | buff = (u16 *)req->buffer; | 624 | mg_write_one(host, req); |
601 | for (j = 0; j < MG_STORAGE_BUFFER_SIZE >> 1; j++) { | ||
602 | outw(*buff, (unsigned long)host->dev_base + | ||
603 | MG_BUFF_OFFSET + (j << 1)); | ||
604 | buff++; | ||
605 | } | ||
606 | MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n", | 625 | MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n", |
607 | blk_rq_pos(req), blk_rq_sectors(req), req->buffer); | 626 | blk_rq_pos(req), blk_rq_sectors(req), req->buffer); |
608 | host->mg_do_intr = mg_write_intr; | 627 | host->mg_do_intr = mg_write_intr; |
@@ -667,9 +686,6 @@ static unsigned int mg_issue_req(struct request *req, | |||
667 | unsigned int sect_num, | 686 | unsigned int sect_num, |
668 | unsigned int sect_cnt) | 687 | unsigned int sect_cnt) |
669 | { | 688 | { |
670 | u16 *buff; | ||
671 | u32 i; | ||
672 | |||
673 | switch (rq_data_dir(req)) { | 689 | switch (rq_data_dir(req)) { |
674 | case READ: | 690 | case READ: |
675 | if (mg_out(host, sect_num, sect_cnt, MG_CMD_RD, &mg_read_intr) | 691 | if (mg_out(host, sect_num, sect_cnt, MG_CMD_RD, &mg_read_intr) |
@@ -693,12 +709,7 @@ static unsigned int mg_issue_req(struct request *req, | |||
693 | mg_bad_rw_intr(host); | 709 | mg_bad_rw_intr(host); |
694 | return host->error; | 710 | return host->error; |
695 | } | 711 | } |
696 | buff = (u16 *)req->buffer; | 712 | mg_write_one(host, req); |
697 | for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) { | ||
698 | outw(*buff, (unsigned long)host->dev_base + | ||
699 | MG_BUFF_OFFSET + (i << 1)); | ||
700 | buff++; | ||
701 | } | ||
702 | mod_timer(&host->timer, jiffies + 3 * HZ); | 713 | mod_timer(&host->timer, jiffies + 3 * HZ); |
703 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + | 714 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + |
704 | MG_REG_COMMAND); | 715 | MG_REG_COMMAND); |
@@ -764,7 +775,7 @@ static int mg_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
764 | return 0; | 775 | return 0; |
765 | } | 776 | } |
766 | 777 | ||
767 | static struct block_device_operations mg_disk_ops = { | 778 | static const struct block_device_operations mg_disk_ops = { |
768 | .getgeo = mg_getgeo | 779 | .getgeo = mg_getgeo |
769 | }; | 780 | }; |
770 | 781 | ||
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 5d23ffad7c7..cc923a5b430 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -722,7 +722,7 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode, | |||
722 | return error; | 722 | return error; |
723 | } | 723 | } |
724 | 724 | ||
725 | static struct block_device_operations nbd_fops = | 725 | static const struct block_device_operations nbd_fops = |
726 | { | 726 | { |
727 | .owner = THIS_MODULE, | 727 | .owner = THIS_MODULE, |
728 | .locked_ioctl = nbd_ioctl, | 728 | .locked_ioctl = nbd_ioctl, |
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c new file mode 100644 index 00000000000..a808b1530b3 --- /dev/null +++ b/drivers/block/osdblk.c | |||
@@ -0,0 +1,701 @@ | |||
1 | |||
2 | /* | ||
3 | osdblk.c -- Export a single SCSI OSD object as a Linux block device | ||
4 | |||
5 | |||
6 | Copyright 2009 Red Hat, Inc. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | |||
21 | |||
22 | Instructions for use | ||
23 | -------------------- | ||
24 | |||
25 | 1) Map a Linux block device to an existing OSD object. | ||
26 | |||
27 | In this example, we will use partition id 1234, object id 5678, | ||
28 | OSD device /dev/osd1. | ||
29 | |||
30 | $ echo "1234 5678 /dev/osd1" > /sys/class/osdblk/add | ||
31 | |||
32 | |||
33 | 2) List all active blkdev<->object mappings. | ||
34 | |||
35 | In this example, we have performed step #1 twice, creating two blkdevs, | ||
36 | mapped to two separate OSD objects. | ||
37 | |||
38 | $ cat /sys/class/osdblk/list | ||
39 | 0 174 1234 5678 /dev/osd1 | ||
40 | 1 179 1994 897123 /dev/osd0 | ||
41 | |||
42 | The columns, in order, are: | ||
43 | - blkdev unique id | ||
44 | - blkdev assigned major | ||
45 | - OSD object partition id | ||
46 | - OSD object id | ||
47 | - OSD device | ||
48 | |||
49 | |||
50 | 3) Remove an active blkdev<->object mapping. | ||
51 | |||
52 | In this example, we remove the mapping with blkdev unique id 1. | ||
53 | |||
54 | $ echo 1 > /sys/class/osdblk/remove | ||
55 | |||
56 | |||
57 | NOTE: The actual creation and deletion of OSD objects is outside the scope | ||
58 | of this driver. | ||
59 | |||
60 | */ | ||
61 | |||
62 | #include <linux/kernel.h> | ||
63 | #include <linux/device.h> | ||
64 | #include <linux/module.h> | ||
65 | #include <linux/fs.h> | ||
66 | #include <scsi/osd_initiator.h> | ||
67 | #include <scsi/osd_attributes.h> | ||
68 | #include <scsi/osd_sec.h> | ||
69 | #include <scsi/scsi_device.h> | ||
70 | |||
71 | #define DRV_NAME "osdblk" | ||
72 | #define PFX DRV_NAME ": " | ||
73 | |||
74 | /* #define _OSDBLK_DEBUG */ | ||
75 | #ifdef _OSDBLK_DEBUG | ||
76 | #define OSDBLK_DEBUG(fmt, a...) \ | ||
77 | printk(KERN_NOTICE "osdblk @%s:%d: " fmt, __func__, __LINE__, ##a) | ||
78 | #else | ||
79 | #define OSDBLK_DEBUG(fmt, a...) \ | ||
80 | do { if (0) printk(fmt, ##a); } while (0) | ||
81 | #endif | ||
82 | |||
83 | MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>"); | ||
84 | MODULE_DESCRIPTION("block device inside an OSD object osdblk.ko"); | ||
85 | MODULE_LICENSE("GPL"); | ||
86 | |||
87 | struct osdblk_device; | ||
88 | |||
89 | enum { | ||
90 | OSDBLK_MINORS_PER_MAJOR = 256, /* max minors per blkdev */ | ||
91 | OSDBLK_MAX_REQ = 32, /* max parallel requests */ | ||
92 | OSDBLK_OP_TIMEOUT = 4 * 60, /* sync OSD req timeout */ | ||
93 | }; | ||
94 | |||
95 | struct osdblk_request { | ||
96 | struct request *rq; /* blk layer request */ | ||
97 | struct bio *bio; /* cloned bio */ | ||
98 | struct osdblk_device *osdev; /* associated blkdev */ | ||
99 | }; | ||
100 | |||
101 | struct osdblk_device { | ||
102 | int id; /* blkdev unique id */ | ||
103 | |||
104 | int major; /* blkdev assigned major */ | ||
105 | struct gendisk *disk; /* blkdev's gendisk and rq */ | ||
106 | struct request_queue *q; | ||
107 | |||
108 | struct osd_dev *osd; /* associated OSD */ | ||
109 | |||
110 | char name[32]; /* blkdev name, e.g. osdblk34 */ | ||
111 | |||
112 | spinlock_t lock; /* queue lock */ | ||
113 | |||
114 | struct osd_obj_id obj; /* OSD partition, obj id */ | ||
115 | uint8_t obj_cred[OSD_CAP_LEN]; /* OSD cred */ | ||
116 | |||
117 | struct osdblk_request req[OSDBLK_MAX_REQ]; /* request table */ | ||
118 | |||
119 | struct list_head node; | ||
120 | |||
121 | char osd_path[0]; /* OSD device path */ | ||
122 | }; | ||
123 | |||
124 | static struct class *class_osdblk; /* /sys/class/osdblk */ | ||
125 | static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ | ||
126 | static LIST_HEAD(osdblkdev_list); | ||
127 | |||
128 | static const struct block_device_operations osdblk_bd_ops = { | ||
129 | .owner = THIS_MODULE, | ||
130 | }; | ||
131 | |||
132 | static const struct osd_attr g_attr_logical_length = ATTR_DEF( | ||
133 | OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); | ||
134 | |||
135 | static void osdblk_make_credential(u8 cred_a[OSD_CAP_LEN], | ||
136 | const struct osd_obj_id *obj) | ||
137 | { | ||
138 | osd_sec_init_nosec_doall_caps(cred_a, obj, false, true); | ||
139 | } | ||
140 | |||
141 | /* copied from exofs; move to libosd? */ | ||
142 | /* | ||
143 | * Perform a synchronous OSD operation. copied from exofs; move to libosd? | ||
144 | */ | ||
145 | static int osd_sync_op(struct osd_request *or, int timeout, uint8_t *credential) | ||
146 | { | ||
147 | int ret; | ||
148 | |||
149 | or->timeout = timeout; | ||
150 | ret = osd_finalize_request(or, 0, credential, NULL); | ||
151 | if (ret) | ||
152 | return ret; | ||
153 | |||
154 | ret = osd_execute_request(or); | ||
155 | |||
156 | /* osd_req_decode_sense(or, ret); */ | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Perform an asynchronous OSD operation. copied from exofs; move to libosd? | ||
162 | */ | ||
163 | static int osd_async_op(struct osd_request *or, osd_req_done_fn *async_done, | ||
164 | void *caller_context, u8 *cred) | ||
165 | { | ||
166 | int ret; | ||
167 | |||
168 | ret = osd_finalize_request(or, 0, cred, NULL); | ||
169 | if (ret) | ||
170 | return ret; | ||
171 | |||
172 | ret = osd_execute_request_async(or, async_done, caller_context); | ||
173 | |||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | /* copied from exofs; move to libosd? */ | ||
178 | static int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr) | ||
179 | { | ||
180 | struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */ | ||
181 | void *iter = NULL; | ||
182 | int nelem; | ||
183 | |||
184 | do { | ||
185 | nelem = 1; | ||
186 | osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter); | ||
187 | if ((cur_attr.attr_page == attr->attr_page) && | ||
188 | (cur_attr.attr_id == attr->attr_id)) { | ||
189 | attr->len = cur_attr.len; | ||
190 | attr->val_ptr = cur_attr.val_ptr; | ||
191 | return 0; | ||
192 | } | ||
193 | } while (iter); | ||
194 | |||
195 | return -EIO; | ||
196 | } | ||
197 | |||
198 | static int osdblk_get_obj_size(struct osdblk_device *osdev, u64 *size_out) | ||
199 | { | ||
200 | struct osd_request *or; | ||
201 | struct osd_attr attr; | ||
202 | int ret; | ||
203 | |||
204 | /* start request */ | ||
205 | or = osd_start_request(osdev->osd, GFP_KERNEL); | ||
206 | if (!or) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | /* create a get-attributes(length) request */ | ||
210 | osd_req_get_attributes(or, &osdev->obj); | ||
211 | |||
212 | osd_req_add_get_attr_list(or, &g_attr_logical_length, 1); | ||
213 | |||
214 | /* execute op synchronously */ | ||
215 | ret = osd_sync_op(or, OSDBLK_OP_TIMEOUT, osdev->obj_cred); | ||
216 | if (ret) | ||
217 | goto out; | ||
218 | |||
219 | /* extract length from returned attribute info */ | ||
220 | attr = g_attr_logical_length; | ||
221 | ret = extract_attr_from_req(or, &attr); | ||
222 | if (ret) | ||
223 | goto out; | ||
224 | |||
225 | *size_out = get_unaligned_be64(attr.val_ptr); | ||
226 | |||
227 | out: | ||
228 | osd_end_request(or); | ||
229 | return ret; | ||
230 | |||
231 | } | ||
232 | |||
233 | static void osdblk_osd_complete(struct osd_request *or, void *private) | ||
234 | { | ||
235 | struct osdblk_request *orq = private; | ||
236 | struct osd_sense_info osi; | ||
237 | int ret = osd_req_decode_sense(or, &osi); | ||
238 | |||
239 | if (ret) { | ||
240 | ret = -EIO; | ||
241 | OSDBLK_DEBUG("osdblk_osd_complete with err=%d\n", ret); | ||
242 | } | ||
243 | |||
244 | /* complete OSD request */ | ||
245 | osd_end_request(or); | ||
246 | |||
247 | /* complete request passed to osdblk by block layer */ | ||
248 | __blk_end_request_all(orq->rq, ret); | ||
249 | } | ||
250 | |||
251 | static void bio_chain_put(struct bio *chain) | ||
252 | { | ||
253 | struct bio *tmp; | ||
254 | |||
255 | while (chain) { | ||
256 | tmp = chain; | ||
257 | chain = chain->bi_next; | ||
258 | |||
259 | bio_put(tmp); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask) | ||
264 | { | ||
265 | struct bio *tmp, *new_chain = NULL, *tail = NULL; | ||
266 | |||
267 | while (old_chain) { | ||
268 | tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs); | ||
269 | if (!tmp) | ||
270 | goto err_out; | ||
271 | |||
272 | __bio_clone(tmp, old_chain); | ||
273 | tmp->bi_bdev = NULL; | ||
274 | gfpmask &= ~__GFP_WAIT; | ||
275 | tmp->bi_next = NULL; | ||
276 | |||
277 | if (!new_chain) | ||
278 | new_chain = tail = tmp; | ||
279 | else { | ||
280 | tail->bi_next = tmp; | ||
281 | tail = tmp; | ||
282 | } | ||
283 | |||
284 | old_chain = old_chain->bi_next; | ||
285 | } | ||
286 | |||
287 | return new_chain; | ||
288 | |||
289 | err_out: | ||
290 | OSDBLK_DEBUG("bio_chain_clone with err\n"); | ||
291 | bio_chain_put(new_chain); | ||
292 | return NULL; | ||
293 | } | ||
294 | |||
295 | static void osdblk_rq_fn(struct request_queue *q) | ||
296 | { | ||
297 | struct osdblk_device *osdev = q->queuedata; | ||
298 | |||
299 | while (1) { | ||
300 | struct request *rq; | ||
301 | struct osdblk_request *orq; | ||
302 | struct osd_request *or; | ||
303 | struct bio *bio; | ||
304 | bool do_write, do_flush; | ||
305 | |||
306 | /* peek at request from block layer */ | ||
307 | rq = blk_fetch_request(q); | ||
308 | if (!rq) | ||
309 | break; | ||
310 | |||
311 | /* filter out block requests we don't understand */ | ||
312 | if (!blk_fs_request(rq) && !blk_barrier_rq(rq)) { | ||
313 | blk_end_request_all(rq, 0); | ||
314 | continue; | ||
315 | } | ||
316 | |||
317 | /* deduce our operation (read, write, flush) */ | ||
318 | /* I wish the block layer simplified cmd_type/cmd_flags/cmd[] | ||
319 | * into a clearly defined set of RPC commands: | ||
320 | * read, write, flush, scsi command, power mgmt req, | ||
321 | * driver-specific, etc. | ||
322 | */ | ||
323 | |||
324 | do_flush = (rq->special == (void *) 0xdeadbeefUL); | ||
325 | do_write = (rq_data_dir(rq) == WRITE); | ||
326 | |||
327 | if (!do_flush) { /* osd_flush does not use a bio */ | ||
328 | /* a bio clone to be passed down to OSD request */ | ||
329 | bio = bio_chain_clone(rq->bio, GFP_ATOMIC); | ||
330 | if (!bio) | ||
331 | break; | ||
332 | } else | ||
333 | bio = NULL; | ||
334 | |||
335 | /* alloc internal OSD request, for OSD command execution */ | ||
336 | or = osd_start_request(osdev->osd, GFP_ATOMIC); | ||
337 | if (!or) { | ||
338 | bio_chain_put(bio); | ||
339 | OSDBLK_DEBUG("osd_start_request with err\n"); | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | orq = &osdev->req[rq->tag]; | ||
344 | orq->rq = rq; | ||
345 | orq->bio = bio; | ||
346 | orq->osdev = osdev; | ||
347 | |||
348 | /* init OSD command: flush, write or read */ | ||
349 | if (do_flush) | ||
350 | osd_req_flush_object(or, &osdev->obj, | ||
351 | OSD_CDB_FLUSH_ALL, 0, 0); | ||
352 | else if (do_write) | ||
353 | osd_req_write(or, &osdev->obj, blk_rq_pos(rq) * 512ULL, | ||
354 | bio, blk_rq_bytes(rq)); | ||
355 | else | ||
356 | osd_req_read(or, &osdev->obj, blk_rq_pos(rq) * 512ULL, | ||
357 | bio, blk_rq_bytes(rq)); | ||
358 | |||
359 | OSDBLK_DEBUG("%s 0x%x bytes at 0x%llx\n", | ||
360 | do_flush ? "flush" : do_write ? | ||
361 | "write" : "read", blk_rq_bytes(rq), | ||
362 | blk_rq_pos(rq) * 512ULL); | ||
363 | |||
364 | /* begin OSD command execution */ | ||
365 | if (osd_async_op(or, osdblk_osd_complete, orq, | ||
366 | osdev->obj_cred)) { | ||
367 | osd_end_request(or); | ||
368 | blk_requeue_request(q, rq); | ||
369 | bio_chain_put(bio); | ||
370 | OSDBLK_DEBUG("osd_execute_request_async with err\n"); | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | /* remove the special 'flush' marker, now that the command | ||
375 | * is executing | ||
376 | */ | ||
377 | rq->special = NULL; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | static void osdblk_prepare_flush(struct request_queue *q, struct request *rq) | ||
382 | { | ||
383 | /* add driver-specific marker, to indicate that this request | ||
384 | * is a flush command | ||
385 | */ | ||
386 | rq->special = (void *) 0xdeadbeefUL; | ||
387 | } | ||
388 | |||
389 | static void osdblk_free_disk(struct osdblk_device *osdev) | ||
390 | { | ||
391 | struct gendisk *disk = osdev->disk; | ||
392 | |||
393 | if (!disk) | ||
394 | return; | ||
395 | |||
396 | if (disk->flags & GENHD_FL_UP) | ||
397 | del_gendisk(disk); | ||
398 | if (disk->queue) | ||
399 | blk_cleanup_queue(disk->queue); | ||
400 | put_disk(disk); | ||
401 | } | ||
402 | |||
403 | static int osdblk_init_disk(struct osdblk_device *osdev) | ||
404 | { | ||
405 | struct gendisk *disk; | ||
406 | struct request_queue *q; | ||
407 | int rc; | ||
408 | u64 obj_size = 0; | ||
409 | |||
410 | /* contact OSD, request size info about the object being mapped */ | ||
411 | rc = osdblk_get_obj_size(osdev, &obj_size); | ||
412 | if (rc) | ||
413 | return rc; | ||
414 | |||
415 | /* create gendisk info */ | ||
416 | disk = alloc_disk(OSDBLK_MINORS_PER_MAJOR); | ||
417 | if (!disk) | ||
418 | return -ENOMEM; | ||
419 | |||
420 | sprintf(disk->disk_name, DRV_NAME "%d", osdev->id); | ||
421 | disk->major = osdev->major; | ||
422 | disk->first_minor = 0; | ||
423 | disk->fops = &osdblk_bd_ops; | ||
424 | disk->private_data = osdev; | ||
425 | |||
426 | /* init rq */ | ||
427 | q = blk_init_queue(osdblk_rq_fn, &osdev->lock); | ||
428 | if (!q) { | ||
429 | put_disk(disk); | ||
430 | return -ENOMEM; | ||
431 | } | ||
432 | |||
433 | /* switch queue to TCQ mode; allocate tag map */ | ||
434 | rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL); | ||
435 | if (rc) { | ||
436 | blk_cleanup_queue(q); | ||
437 | put_disk(disk); | ||
438 | return rc; | ||
439 | } | ||
440 | |||
441 | /* Set our limits to the lower device limits, because osdblk cannot | ||
442 | * sleep when allocating a lower-request and therefore cannot be | ||
443 | * bouncing. | ||
444 | */ | ||
445 | blk_queue_stack_limits(q, osd_request_queue(osdev->osd)); | ||
446 | |||
447 | blk_queue_prep_rq(q, blk_queue_start_tag); | ||
448 | blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, osdblk_prepare_flush); | ||
449 | |||
450 | disk->queue = q; | ||
451 | |||
452 | q->queuedata = osdev; | ||
453 | |||
454 | osdev->disk = disk; | ||
455 | osdev->q = q; | ||
456 | |||
457 | /* finally, announce the disk to the world */ | ||
458 | set_capacity(disk, obj_size / 512ULL); | ||
459 | add_disk(disk); | ||
460 | |||
461 | printk(KERN_INFO "%s: Added of size 0x%llx\n", | ||
462 | disk->disk_name, (unsigned long long)obj_size); | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | /******************************************************************** | ||
468 | * /sys/class/osdblk/ | ||
469 | * add map OSD object to blkdev | ||
470 | * remove unmap OSD object | ||
471 | * list show mappings | ||
472 | *******************************************************************/ | ||
473 | |||
474 | static void class_osdblk_release(struct class *cls) | ||
475 | { | ||
476 | kfree(cls); | ||
477 | } | ||
478 | |||
479 | static ssize_t class_osdblk_list(struct class *c, char *data) | ||
480 | { | ||
481 | int n = 0; | ||
482 | struct list_head *tmp; | ||
483 | |||
484 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
485 | |||
486 | list_for_each(tmp, &osdblkdev_list) { | ||
487 | struct osdblk_device *osdev; | ||
488 | |||
489 | osdev = list_entry(tmp, struct osdblk_device, node); | ||
490 | |||
491 | n += sprintf(data+n, "%d %d %llu %llu %s\n", | ||
492 | osdev->id, | ||
493 | osdev->major, | ||
494 | osdev->obj.partition, | ||
495 | osdev->obj.id, | ||
496 | osdev->osd_path); | ||
497 | } | ||
498 | |||
499 | mutex_unlock(&ctl_mutex); | ||
500 | return n; | ||
501 | } | ||
502 | |||
503 | static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count) | ||
504 | { | ||
505 | struct osdblk_device *osdev; | ||
506 | ssize_t rc; | ||
507 | int irc, new_id = 0; | ||
508 | struct list_head *tmp; | ||
509 | |||
510 | if (!try_module_get(THIS_MODULE)) | ||
511 | return -ENODEV; | ||
512 | |||
513 | /* new osdblk_device object */ | ||
514 | osdev = kzalloc(sizeof(*osdev) + strlen(buf) + 1, GFP_KERNEL); | ||
515 | if (!osdev) { | ||
516 | rc = -ENOMEM; | ||
517 | goto err_out_mod; | ||
518 | } | ||
519 | |||
520 | /* static osdblk_device initialization */ | ||
521 | spin_lock_init(&osdev->lock); | ||
522 | INIT_LIST_HEAD(&osdev->node); | ||
523 | |||
524 | /* generate unique id: find highest unique id, add one */ | ||
525 | |||
526 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
527 | |||
528 | list_for_each(tmp, &osdblkdev_list) { | ||
529 | struct osdblk_device *osdev; | ||
530 | |||
531 | osdev = list_entry(tmp, struct osdblk_device, node); | ||
532 | if (osdev->id > new_id) | ||
533 | new_id = osdev->id + 1; | ||
534 | } | ||
535 | |||
536 | osdev->id = new_id; | ||
537 | |||
538 | /* add to global list */ | ||
539 | list_add_tail(&osdev->node, &osdblkdev_list); | ||
540 | |||
541 | mutex_unlock(&ctl_mutex); | ||
542 | |||
543 | /* parse add command */ | ||
544 | if (sscanf(buf, "%llu %llu %s", &osdev->obj.partition, &osdev->obj.id, | ||
545 | osdev->osd_path) != 3) { | ||
546 | rc = -EINVAL; | ||
547 | goto err_out_slot; | ||
548 | } | ||
549 | |||
550 | /* initialize rest of new object */ | ||
551 | sprintf(osdev->name, DRV_NAME "%d", osdev->id); | ||
552 | |||
553 | /* contact requested OSD */ | ||
554 | osdev->osd = osduld_path_lookup(osdev->osd_path); | ||
555 | if (IS_ERR(osdev->osd)) { | ||
556 | rc = PTR_ERR(osdev->osd); | ||
557 | goto err_out_slot; | ||
558 | } | ||
559 | |||
560 | /* build OSD credential */ | ||
561 | osdblk_make_credential(osdev->obj_cred, &osdev->obj); | ||
562 | |||
563 | /* register our block device */ | ||
564 | irc = register_blkdev(0, osdev->name); | ||
565 | if (irc < 0) { | ||
566 | rc = irc; | ||
567 | goto err_out_osd; | ||
568 | } | ||
569 | |||
570 | osdev->major = irc; | ||
571 | |||
572 | /* set up and announce blkdev mapping */ | ||
573 | rc = osdblk_init_disk(osdev); | ||
574 | if (rc) | ||
575 | goto err_out_blkdev; | ||
576 | |||
577 | return count; | ||
578 | |||
579 | err_out_blkdev: | ||
580 | unregister_blkdev(osdev->major, osdev->name); | ||
581 | err_out_osd: | ||
582 | osduld_put_device(osdev->osd); | ||
583 | err_out_slot: | ||
584 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
585 | list_del_init(&osdev->node); | ||
586 | mutex_unlock(&ctl_mutex); | ||
587 | |||
588 | kfree(osdev); | ||
589 | err_out_mod: | ||
590 | OSDBLK_DEBUG("Error adding device %s\n", buf); | ||
591 | module_put(THIS_MODULE); | ||
592 | return rc; | ||
593 | } | ||
594 | |||
595 | static ssize_t class_osdblk_remove(struct class *c, const char *buf, | ||
596 | size_t count) | ||
597 | { | ||
598 | struct osdblk_device *osdev = NULL; | ||
599 | int target_id, rc; | ||
600 | unsigned long ul; | ||
601 | struct list_head *tmp; | ||
602 | |||
603 | rc = strict_strtoul(buf, 10, &ul); | ||
604 | if (rc) | ||
605 | return rc; | ||
606 | |||
607 | /* convert to int; abort if we lost anything in the conversion */ | ||
608 | target_id = (int) ul; | ||
609 | if (target_id != ul) | ||
610 | return -EINVAL; | ||
611 | |||
612 | /* remove object from list immediately */ | ||
613 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
614 | |||
615 | list_for_each(tmp, &osdblkdev_list) { | ||
616 | osdev = list_entry(tmp, struct osdblk_device, node); | ||
617 | if (osdev->id == target_id) { | ||
618 | list_del_init(&osdev->node); | ||
619 | break; | ||
620 | } | ||
621 | osdev = NULL; | ||
622 | } | ||
623 | |||
624 | mutex_unlock(&ctl_mutex); | ||
625 | |||
626 | if (!osdev) | ||
627 | return -ENOENT; | ||
628 | |||
629 | /* clean up and free blkdev and associated OSD connection */ | ||
630 | osdblk_free_disk(osdev); | ||
631 | unregister_blkdev(osdev->major, osdev->name); | ||
632 | osduld_put_device(osdev->osd); | ||
633 | kfree(osdev); | ||
634 | |||
635 | /* release module ref */ | ||
636 | module_put(THIS_MODULE); | ||
637 | |||
638 | return count; | ||
639 | } | ||
640 | |||
641 | static struct class_attribute class_osdblk_attrs[] = { | ||
642 | __ATTR(add, 0200, NULL, class_osdblk_add), | ||
643 | __ATTR(remove, 0200, NULL, class_osdblk_remove), | ||
644 | __ATTR(list, 0444, class_osdblk_list, NULL), | ||
645 | __ATTR_NULL | ||
646 | }; | ||
647 | |||
648 | static int osdblk_sysfs_init(void) | ||
649 | { | ||
650 | int ret = 0; | ||
651 | |||
652 | /* | ||
653 | * create control files in sysfs | ||
654 | * /sys/class/osdblk/... | ||
655 | */ | ||
656 | class_osdblk = kzalloc(sizeof(*class_osdblk), GFP_KERNEL); | ||
657 | if (!class_osdblk) | ||
658 | return -ENOMEM; | ||
659 | |||
660 | class_osdblk->name = DRV_NAME; | ||
661 | class_osdblk->owner = THIS_MODULE; | ||
662 | class_osdblk->class_release = class_osdblk_release; | ||
663 | class_osdblk->class_attrs = class_osdblk_attrs; | ||
664 | |||
665 | ret = class_register(class_osdblk); | ||
666 | if (ret) { | ||
667 | kfree(class_osdblk); | ||
668 | class_osdblk = NULL; | ||
669 | printk(PFX "failed to create class osdblk\n"); | ||
670 | return ret; | ||
671 | } | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | static void osdblk_sysfs_cleanup(void) | ||
677 | { | ||
678 | if (class_osdblk) | ||
679 | class_destroy(class_osdblk); | ||
680 | class_osdblk = NULL; | ||
681 | } | ||
682 | |||
683 | static int __init osdblk_init(void) | ||
684 | { | ||
685 | int rc; | ||
686 | |||
687 | rc = osdblk_sysfs_init(); | ||
688 | if (rc) | ||
689 | return rc; | ||
690 | |||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | static void __exit osdblk_exit(void) | ||
695 | { | ||
696 | osdblk_sysfs_cleanup(); | ||
697 | } | ||
698 | |||
699 | module_init(osdblk_init); | ||
700 | module_exit(osdblk_exit); | ||
701 | |||
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 911dfd98d81..8866ca369d5 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c | |||
@@ -219,8 +219,6 @@ static int pcd_sector; /* address of next requested sector */ | |||
219 | static int pcd_count; /* number of blocks still to do */ | 219 | static int pcd_count; /* number of blocks still to do */ |
220 | static char *pcd_buf; /* buffer for request in progress */ | 220 | static char *pcd_buf; /* buffer for request in progress */ |
221 | 221 | ||
222 | static int pcd_warned; /* Have we logged a phase warning ? */ | ||
223 | |||
224 | /* kernel glue structures */ | 222 | /* kernel glue structures */ |
225 | 223 | ||
226 | static int pcd_block_open(struct block_device *bdev, fmode_t mode) | 224 | static int pcd_block_open(struct block_device *bdev, fmode_t mode) |
@@ -249,7 +247,7 @@ static int pcd_block_media_changed(struct gendisk *disk) | |||
249 | return cdrom_media_changed(&cd->info); | 247 | return cdrom_media_changed(&cd->info); |
250 | } | 248 | } |
251 | 249 | ||
252 | static struct block_device_operations pcd_bdops = { | 250 | static const struct block_device_operations pcd_bdops = { |
253 | .owner = THIS_MODULE, | 251 | .owner = THIS_MODULE, |
254 | .open = pcd_block_open, | 252 | .open = pcd_block_open, |
255 | .release = pcd_block_release, | 253 | .release = pcd_block_release, |
@@ -417,12 +415,10 @@ static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun) | |||
417 | printk | 415 | printk |
418 | ("%s: %s: Unexpected phase %d, d=%d, k=%d\n", | 416 | ("%s: %s: Unexpected phase %d, d=%d, k=%d\n", |
419 | cd->name, fun, p, d, k); | 417 | cd->name, fun, p, d, k); |
420 | if ((verbose < 2) && !pcd_warned) { | 418 | if (verbose < 2) |
421 | pcd_warned = 1; | 419 | printk_once( |
422 | printk | 420 | "%s: WARNING: ATAPI phase errors\n", |
423 | ("%s: WARNING: ATAPI phase errors\n", | 421 | cd->name); |
424 | cd->name); | ||
425 | } | ||
426 | mdelay(1); | 422 | mdelay(1); |
427 | } | 423 | } |
428 | if (k++ > PCD_TMO) { | 424 | if (k++ > PCD_TMO) { |
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index bf5955b3d87..569e39e8f11 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c | |||
@@ -807,7 +807,7 @@ static int pd_revalidate(struct gendisk *p) | |||
807 | return 0; | 807 | return 0; |
808 | } | 808 | } |
809 | 809 | ||
810 | static struct block_device_operations pd_fops = { | 810 | static const struct block_device_operations pd_fops = { |
811 | .owner = THIS_MODULE, | 811 | .owner = THIS_MODULE, |
812 | .open = pd_open, | 812 | .open = pd_open, |
813 | .release = pd_release, | 813 | .release = pd_release, |
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 68a90834e99..ea54ea39355 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c | |||
@@ -262,7 +262,7 @@ static char *pf_buf; /* buffer for request in progress */ | |||
262 | 262 | ||
263 | /* kernel glue structures */ | 263 | /* kernel glue structures */ |
264 | 264 | ||
265 | static struct block_device_operations pf_fops = { | 265 | static const struct block_device_operations pf_fops = { |
266 | .owner = THIS_MODULE, | 266 | .owner = THIS_MODULE, |
267 | .open = pf_open, | 267 | .open = pf_open, |
268 | .release = pf_release, | 268 | .release = pf_release, |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 83650e00632..2ddf03ae034 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -92,7 +92,7 @@ static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ | |||
92 | static mempool_t *psd_pool; | 92 | static mempool_t *psd_pool; |
93 | 93 | ||
94 | static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */ | 94 | static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */ |
95 | static struct dentry *pkt_debugfs_root = NULL; /* /debug/pktcdvd */ | 95 | static struct dentry *pkt_debugfs_root = NULL; /* /sys/kernel/debug/pktcdvd */ |
96 | 96 | ||
97 | /* forward declaration */ | 97 | /* forward declaration */ |
98 | static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev); | 98 | static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev); |
@@ -1372,8 +1372,10 @@ try_next_bio: | |||
1372 | wakeup = (pd->write_congestion_on > 0 | 1372 | wakeup = (pd->write_congestion_on > 0 |
1373 | && pd->bio_queue_size <= pd->write_congestion_off); | 1373 | && pd->bio_queue_size <= pd->write_congestion_off); |
1374 | spin_unlock(&pd->lock); | 1374 | spin_unlock(&pd->lock); |
1375 | if (wakeup) | 1375 | if (wakeup) { |
1376 | clear_bdi_congested(&pd->disk->queue->backing_dev_info, WRITE); | 1376 | clear_bdi_congested(&pd->disk->queue->backing_dev_info, |
1377 | BLK_RW_ASYNC); | ||
1378 | } | ||
1377 | 1379 | ||
1378 | pkt->sleep_time = max(PACKET_WAIT_TIME, 1); | 1380 | pkt->sleep_time = max(PACKET_WAIT_TIME, 1); |
1379 | pkt_set_state(pkt, PACKET_WAITING_STATE); | 1381 | pkt_set_state(pkt, PACKET_WAITING_STATE); |
@@ -2592,10 +2594,10 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio) | |||
2592 | spin_lock(&pd->lock); | 2594 | spin_lock(&pd->lock); |
2593 | if (pd->write_congestion_on > 0 | 2595 | if (pd->write_congestion_on > 0 |
2594 | && pd->bio_queue_size >= pd->write_congestion_on) { | 2596 | && pd->bio_queue_size >= pd->write_congestion_on) { |
2595 | set_bdi_congested(&q->backing_dev_info, WRITE); | 2597 | set_bdi_congested(&q->backing_dev_info, BLK_RW_ASYNC); |
2596 | do { | 2598 | do { |
2597 | spin_unlock(&pd->lock); | 2599 | spin_unlock(&pd->lock); |
2598 | congestion_wait(WRITE, HZ); | 2600 | congestion_wait(BLK_RW_ASYNC, HZ); |
2599 | spin_lock(&pd->lock); | 2601 | spin_lock(&pd->lock); |
2600 | } while(pd->bio_queue_size > pd->write_congestion_off); | 2602 | } while(pd->bio_queue_size > pd->write_congestion_off); |
2601 | } | 2603 | } |
@@ -2847,7 +2849,7 @@ static int pkt_media_changed(struct gendisk *disk) | |||
2847 | return attached_disk->fops->media_changed(attached_disk); | 2849 | return attached_disk->fops->media_changed(attached_disk); |
2848 | } | 2850 | } |
2849 | 2851 | ||
2850 | static struct block_device_operations pktcdvd_ops = { | 2852 | static const struct block_device_operations pktcdvd_ops = { |
2851 | .owner = THIS_MODULE, | 2853 | .owner = THIS_MODULE, |
2852 | .open = pkt_open, | 2854 | .open = pkt_open, |
2853 | .release = pkt_close, | 2855 | .release = pkt_close, |
@@ -2855,7 +2857,7 @@ static struct block_device_operations pktcdvd_ops = { | |||
2855 | .media_changed = pkt_media_changed, | 2857 | .media_changed = pkt_media_changed, |
2856 | }; | 2858 | }; |
2857 | 2859 | ||
2858 | static char *pktcdvd_nodename(struct gendisk *gd) | 2860 | static char *pktcdvd_devnode(struct gendisk *gd, mode_t *mode) |
2859 | { | 2861 | { |
2860 | return kasprintf(GFP_KERNEL, "pktcdvd/%s", gd->disk_name); | 2862 | return kasprintf(GFP_KERNEL, "pktcdvd/%s", gd->disk_name); |
2861 | } | 2863 | } |
@@ -2912,7 +2914,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) | |||
2912 | disk->fops = &pktcdvd_ops; | 2914 | disk->fops = &pktcdvd_ops; |
2913 | disk->flags = GENHD_FL_REMOVABLE; | 2915 | disk->flags = GENHD_FL_REMOVABLE; |
2914 | strcpy(disk->disk_name, pd->name); | 2916 | strcpy(disk->disk_name, pd->name); |
2915 | disk->nodename = pktcdvd_nodename; | 2917 | disk->devnode = pktcdvd_devnode; |
2916 | disk->private_data = pd; | 2918 | disk->private_data = pd; |
2917 | disk->queue = blk_alloc_queue(GFP_KERNEL); | 2919 | disk->queue = blk_alloc_queue(GFP_KERNEL); |
2918 | if (!disk->queue) | 2920 | if (!disk->queue) |
@@ -3068,7 +3070,7 @@ static const struct file_operations pkt_ctl_fops = { | |||
3068 | static struct miscdevice pkt_misc = { | 3070 | static struct miscdevice pkt_misc = { |
3069 | .minor = MISC_DYNAMIC_MINOR, | 3071 | .minor = MISC_DYNAMIC_MINOR, |
3070 | .name = DRIVER_NAME, | 3072 | .name = DRIVER_NAME, |
3071 | .name = "pktcdvd/control", | 3073 | .nodename = "pktcdvd/control", |
3072 | .fops = &pkt_ctl_fops | 3074 | .fops = &pkt_ctl_fops |
3073 | }; | 3075 | }; |
3074 | 3076 | ||
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 34cbb7f3efa..03a130dca8a 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c | |||
@@ -82,7 +82,7 @@ enum lv1_ata_in_out { | |||
82 | static int ps3disk_major; | 82 | static int ps3disk_major; |
83 | 83 | ||
84 | 84 | ||
85 | static struct block_device_operations ps3disk_fops = { | 85 | static const struct block_device_operations ps3disk_fops = { |
86 | .owner = THIS_MODULE, | 86 | .owner = THIS_MODULE, |
87 | }; | 87 | }; |
88 | 88 | ||
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c index 095f97e6066..3bb7c47c869 100644 --- a/drivers/block/ps3vram.c +++ b/drivers/block/ps3vram.c | |||
@@ -13,8 +13,8 @@ | |||
13 | #include <linux/proc_fs.h> | 13 | #include <linux/proc_fs.h> |
14 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
15 | 15 | ||
16 | #include <asm/cell-regs.h> | ||
16 | #include <asm/firmware.h> | 17 | #include <asm/firmware.h> |
17 | #include <asm/iommu.h> | ||
18 | #include <asm/lv1call.h> | 18 | #include <asm/lv1call.h> |
19 | #include <asm/ps3.h> | 19 | #include <asm/ps3.h> |
20 | #include <asm/ps3gpu.h> | 20 | #include <asm/ps3gpu.h> |
@@ -88,7 +88,7 @@ struct ps3vram_priv { | |||
88 | static int ps3vram_major; | 88 | static int ps3vram_major; |
89 | 89 | ||
90 | 90 | ||
91 | static struct block_device_operations ps3vram_fops = { | 91 | static const struct block_device_operations ps3vram_fops = { |
92 | .owner = THIS_MODULE, | 92 | .owner = THIS_MODULE, |
93 | }; | 93 | }; |
94 | 94 | ||
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index cbfd9c0aef0..411f064760b 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c | |||
@@ -103,7 +103,7 @@ static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
103 | return 0; | 103 | return 0; |
104 | } | 104 | } |
105 | 105 | ||
106 | static struct block_device_operations vdc_fops = { | 106 | static const struct block_device_operations vdc_fops = { |
107 | .owner = THIS_MODULE, | 107 | .owner = THIS_MODULE, |
108 | .getgeo = vdc_getgeo, | 108 | .getgeo = vdc_getgeo, |
109 | }; | 109 | }; |
diff --git a/drivers/block/swim.c b/drivers/block/swim.c index cf7877fb8a7..8f569e3df89 100644 --- a/drivers/block/swim.c +++ b/drivers/block/swim.c | |||
@@ -748,7 +748,7 @@ static int floppy_revalidate(struct gendisk *disk) | |||
748 | return !fs->disk_in; | 748 | return !fs->disk_in; |
749 | } | 749 | } |
750 | 750 | ||
751 | static struct block_device_operations floppy_fops = { | 751 | static const struct block_device_operations floppy_fops = { |
752 | .owner = THIS_MODULE, | 752 | .owner = THIS_MODULE, |
753 | .open = floppy_open, | 753 | .open = floppy_open, |
754 | .release = floppy_release, | 754 | .release = floppy_release, |
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 80df93e3cdd..6380ad8d91b 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c | |||
@@ -998,7 +998,7 @@ static int floppy_revalidate(struct gendisk *disk) | |||
998 | return ret; | 998 | return ret; |
999 | } | 999 | } |
1000 | 1000 | ||
1001 | static struct block_device_operations floppy_fops = { | 1001 | static const struct block_device_operations floppy_fops = { |
1002 | .open = floppy_open, | 1002 | .open = floppy_open, |
1003 | .release = floppy_release, | 1003 | .release = floppy_release, |
1004 | .locked_ioctl = floppy_ioctl, | 1004 | .locked_ioctl = floppy_ioctl, |
@@ -1062,7 +1062,7 @@ static int swim3_add_device(struct macio_dev *mdev, int index) | |||
1062 | goto out_release; | 1062 | goto out_release; |
1063 | } | 1063 | } |
1064 | fs->swim3_intr = macio_irq(mdev, 0); | 1064 | fs->swim3_intr = macio_irq(mdev, 0); |
1065 | fs->dma_intr = macio_irq(mdev, 1);; | 1065 | fs->dma_intr = macio_irq(mdev, 1); |
1066 | fs->cur_cyl = -1; | 1066 | fs->cur_cyl = -1; |
1067 | fs->cur_sector = -1; | 1067 | fs->cur_sector = -1; |
1068 | fs->secpercyl = 36; | 1068 | fs->secpercyl = 36; |
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index da403b6a7f4..a7c4184f4a6 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c | |||
@@ -423,7 +423,7 @@ static struct pci_driver carm_driver = { | |||
423 | .remove = carm_remove_one, | 423 | .remove = carm_remove_one, |
424 | }; | 424 | }; |
425 | 425 | ||
426 | static struct block_device_operations carm_bd_ops = { | 426 | static const struct block_device_operations carm_bd_ops = { |
427 | .owner = THIS_MODULE, | 427 | .owner = THIS_MODULE, |
428 | .getgeo = carm_bdev_getgeo, | 428 | .getgeo = carm_bdev_getgeo, |
429 | }; | 429 | }; |
@@ -1564,15 +1564,13 @@ static int carm_init_shm(struct carm_host *host) | |||
1564 | 1564 | ||
1565 | static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | 1565 | static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) |
1566 | { | 1566 | { |
1567 | static unsigned int printed_version; | ||
1568 | struct carm_host *host; | 1567 | struct carm_host *host; |
1569 | unsigned int pci_dac; | 1568 | unsigned int pci_dac; |
1570 | int rc; | 1569 | int rc; |
1571 | struct request_queue *q; | 1570 | struct request_queue *q; |
1572 | unsigned int i; | 1571 | unsigned int i; |
1573 | 1572 | ||
1574 | if (!printed_version++) | 1573 | printk_once(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); |
1575 | printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); | ||
1576 | 1574 | ||
1577 | rc = pci_enable_device(pdev); | 1575 | rc = pci_enable_device(pdev); |
1578 | if (rc) | 1576 | if (rc) |
diff --git a/drivers/block/ub.c b/drivers/block/ub.c index cc54473b8e7..c739b203fe9 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c | |||
@@ -1789,7 +1789,7 @@ static int ub_bd_media_changed(struct gendisk *disk) | |||
1789 | return lun->changed; | 1789 | return lun->changed; |
1790 | } | 1790 | } |
1791 | 1791 | ||
1792 | static struct block_device_operations ub_bd_fops = { | 1792 | static const struct block_device_operations ub_bd_fops = { |
1793 | .owner = THIS_MODULE, | 1793 | .owner = THIS_MODULE, |
1794 | .open = ub_bd_open, | 1794 | .open = ub_bd_open, |
1795 | .release = ub_bd_release, | 1795 | .release = ub_bd_release, |
diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 858c34dd032..ad1ba393801 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c | |||
@@ -140,7 +140,6 @@ struct cardinfo { | |||
140 | }; | 140 | }; |
141 | 141 | ||
142 | static struct cardinfo cards[MM_MAXCARDS]; | 142 | static struct cardinfo cards[MM_MAXCARDS]; |
143 | static struct block_device_operations mm_fops; | ||
144 | static struct timer_list battery_timer; | 143 | static struct timer_list battery_timer; |
145 | 144 | ||
146 | static int num_cards; | 145 | static int num_cards; |
@@ -789,7 +788,7 @@ static int mm_check_change(struct gendisk *disk) | |||
789 | return 0; | 788 | return 0; |
790 | } | 789 | } |
791 | 790 | ||
792 | static struct block_device_operations mm_fops = { | 791 | static const struct block_device_operations mm_fops = { |
793 | .owner = THIS_MODULE, | 792 | .owner = THIS_MODULE, |
794 | .getgeo = mm_getgeo, | 793 | .getgeo = mm_getgeo, |
795 | .revalidate_disk = mm_revalidate, | 794 | .revalidate_disk = mm_revalidate, |
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 390d69bb7c4..a8c8b56b275 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
@@ -219,7 +219,7 @@ static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
219 | /* | 219 | /* |
220 | * Our file operations table | 220 | * Our file operations table |
221 | */ | 221 | */ |
222 | static struct block_device_operations viodasd_fops = { | 222 | static const struct block_device_operations viodasd_fops = { |
223 | .owner = THIS_MODULE, | 223 | .owner = THIS_MODULE, |
224 | .open = viodasd_open, | 224 | .open = viodasd_open, |
225 | .release = viodasd_release, | 225 | .release = viodasd_release, |
@@ -416,15 +416,9 @@ retry: | |||
416 | goto retry; | 416 | goto retry; |
417 | } | 417 | } |
418 | if (we.max_disk > (MAX_DISKNO - 1)) { | 418 | if (we.max_disk > (MAX_DISKNO - 1)) { |
419 | static int warned; | 419 | printk_once(VIOD_KERN_INFO |
420 | 420 | "Only examining the first %d of %d disks connected\n", | |
421 | if (warned == 0) { | 421 | MAX_DISKNO, we.max_disk + 1); |
422 | warned++; | ||
423 | printk(VIOD_KERN_INFO | ||
424 | "Only examining the first %d " | ||
425 | "of %d disks connected\n", | ||
426 | MAX_DISKNO, we.max_disk + 1); | ||
427 | } | ||
428 | } | 422 | } |
429 | 423 | ||
430 | /* Send the close event to OS/400. We DON'T expect a response */ | 424 | /* Send the close event to OS/400. We DON'T expect a response */ |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 43db3ea15b5..43f19389647 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/blkdev.h> | 3 | #include <linux/blkdev.h> |
4 | #include <linux/hdreg.h> | 4 | #include <linux/hdreg.h> |
5 | #include <linux/virtio.h> | 5 | #include <linux/virtio.h> |
6 | #include <linux/virtio_ids.h> | ||
6 | #include <linux/virtio_blk.h> | 7 | #include <linux/virtio_blk.h> |
7 | #include <linux/scatterlist.h> | 8 | #include <linux/scatterlist.h> |
8 | 9 | ||
@@ -91,15 +92,26 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
91 | return false; | 92 | return false; |
92 | 93 | ||
93 | vbr->req = req; | 94 | vbr->req = req; |
94 | if (blk_fs_request(vbr->req)) { | 95 | switch (req->cmd_type) { |
96 | case REQ_TYPE_FS: | ||
95 | vbr->out_hdr.type = 0; | 97 | vbr->out_hdr.type = 0; |
96 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); | 98 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); |
97 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 99 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
98 | } else if (blk_pc_request(vbr->req)) { | 100 | break; |
101 | case REQ_TYPE_BLOCK_PC: | ||
99 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; | 102 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; |
100 | vbr->out_hdr.sector = 0; | 103 | vbr->out_hdr.sector = 0; |
101 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 104 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
102 | } else { | 105 | break; |
106 | case REQ_TYPE_LINUX_BLOCK: | ||
107 | if (req->cmd[0] == REQ_LB_OP_FLUSH) { | ||
108 | vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; | ||
109 | vbr->out_hdr.sector = 0; | ||
110 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | ||
111 | break; | ||
112 | } | ||
113 | /*FALLTHRU*/ | ||
114 | default: | ||
103 | /* We don't put anything else in the queue. */ | 115 | /* We don't put anything else in the queue. */ |
104 | BUG(); | 116 | BUG(); |
105 | } | 117 | } |
@@ -139,7 +151,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
139 | } | 151 | } |
140 | } | 152 | } |
141 | 153 | ||
142 | if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) { | 154 | if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr) < 0) { |
143 | mempool_free(vbr, vblk->pool); | 155 | mempool_free(vbr, vblk->pool); |
144 | return false; | 156 | return false; |
145 | } | 157 | } |
@@ -199,6 +211,12 @@ out: | |||
199 | return err; | 211 | return err; |
200 | } | 212 | } |
201 | 213 | ||
214 | static void virtblk_prepare_flush(struct request_queue *q, struct request *req) | ||
215 | { | ||
216 | req->cmd_type = REQ_TYPE_LINUX_BLOCK; | ||
217 | req->cmd[0] = REQ_LB_OP_FLUSH; | ||
218 | } | ||
219 | |||
202 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | 220 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, |
203 | unsigned cmd, unsigned long data) | 221 | unsigned cmd, unsigned long data) |
204 | { | 222 | { |
@@ -213,7 +231,7 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | |||
213 | * Only allow the generic SCSI ioctls if the host can support it. | 231 | * Only allow the generic SCSI ioctls if the host can support it. |
214 | */ | 232 | */ |
215 | if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) | 233 | if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) |
216 | return -ENOIOCTLCMD; | 234 | return -ENOTTY; |
217 | 235 | ||
218 | return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); | 236 | return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); |
219 | } | 237 | } |
@@ -243,7 +261,7 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) | |||
243 | return 0; | 261 | return 0; |
244 | } | 262 | } |
245 | 263 | ||
246 | static struct block_device_operations virtblk_fops = { | 264 | static const struct block_device_operations virtblk_fops = { |
247 | .locked_ioctl = virtblk_ioctl, | 265 | .locked_ioctl = virtblk_ioctl, |
248 | .owner = THIS_MODULE, | 266 | .owner = THIS_MODULE, |
249 | .getgeo = virtblk_getgeo, | 267 | .getgeo = virtblk_getgeo, |
@@ -337,7 +355,10 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
337 | index++; | 355 | index++; |
338 | 356 | ||
339 | /* If barriers are supported, tell block layer that queue is ordered */ | 357 | /* If barriers are supported, tell block layer that queue is ordered */ |
340 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) | 358 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) |
359 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_DRAIN_FLUSH, | ||
360 | virtblk_prepare_flush); | ||
361 | else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) | ||
341 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 362 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); |
342 | 363 | ||
343 | /* If disk is read-only in the host, the guest should obey */ | 364 | /* If disk is read-only in the host, the guest should obey */ |
@@ -360,6 +381,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
360 | blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); | 381 | blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); |
361 | blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); | 382 | blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); |
362 | 383 | ||
384 | /* No need to bounce any requests */ | ||
385 | blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY); | ||
386 | |||
363 | /* No real sector limit. */ | 387 | /* No real sector limit. */ |
364 | blk_queue_max_sectors(vblk->disk->queue, -1U); | 388 | blk_queue_max_sectors(vblk->disk->queue, -1U); |
365 | 389 | ||
@@ -421,10 +445,15 @@ static struct virtio_device_id id_table[] = { | |||
421 | static unsigned int features[] = { | 445 | static unsigned int features[] = { |
422 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, | 446 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, |
423 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, | 447 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, |
424 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY | 448 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY, VIRTIO_BLK_F_FLUSH |
425 | }; | 449 | }; |
426 | 450 | ||
427 | static struct virtio_driver virtio_blk = { | 451 | /* |
452 | * virtio_blk causes spurious section mismatch warning by | ||
453 | * simultaneously referring to a __devinit and a __devexit function. | ||
454 | * Use __refdata to avoid this warning. | ||
455 | */ | ||
456 | static struct virtio_driver __refdata virtio_blk = { | ||
428 | .feature_table = features, | 457 | .feature_table = features, |
429 | .feature_table_size = ARRAY_SIZE(features), | 458 | .feature_table_size = ARRAY_SIZE(features), |
430 | .driver.name = KBUILD_MODNAME, | 459 | .driver.name = KBUILD_MODNAME, |
diff --git a/drivers/block/xd.c b/drivers/block/xd.c index ce242921992..0877d3628fd 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c | |||
@@ -130,7 +130,7 @@ static struct gendisk *xd_gendisk[2]; | |||
130 | 130 | ||
131 | static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo); | 131 | static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo); |
132 | 132 | ||
133 | static struct block_device_operations xd_fops = { | 133 | static const struct block_device_operations xd_fops = { |
134 | .owner = THIS_MODULE, | 134 | .owner = THIS_MODULE, |
135 | .locked_ioctl = xd_ioctl, | 135 | .locked_ioctl = xd_ioctl, |
136 | .getgeo = xd_getgeo, | 136 | .getgeo = xd_getgeo, |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index e53284767f7..b8578bb3f4c 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -65,7 +65,7 @@ struct blk_shadow { | |||
65 | unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST]; | 65 | unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST]; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static struct block_device_operations xlvbd_block_fops; | 68 | static const struct block_device_operations xlvbd_block_fops; |
69 | 69 | ||
70 | #define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE) | 70 | #define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE) |
71 | 71 | ||
@@ -1039,7 +1039,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode) | |||
1039 | return 0; | 1039 | return 0; |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | static struct block_device_operations xlvbd_block_fops = | 1042 | static const struct block_device_operations xlvbd_block_fops = |
1043 | { | 1043 | { |
1044 | .owner = THIS_MODULE, | 1044 | .owner = THIS_MODULE, |
1045 | .open = blkif_open, | 1045 | .open = blkif_open, |
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index f08491a3a81..e5c5415eb45 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
@@ -390,9 +390,10 @@ static inline void ace_dump_mem(void *base, int len) | |||
390 | 390 | ||
391 | static void ace_dump_regs(struct ace_device *ace) | 391 | static void ace_dump_regs(struct ace_device *ace) |
392 | { | 392 | { |
393 | dev_info(ace->dev, " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" | 393 | dev_info(ace->dev, |
394 | KERN_INFO " status:%.8x mpu_lba:%.8x busmode:%4x\n" | 394 | " ctrl: %.8x seccnt/cmd: %.4x ver:%.4x\n" |
395 | KERN_INFO " error: %.8x cfg_lba:%.8x fatstat:%.4x\n", | 395 | " status:%.8x mpu_lba:%.8x busmode:%4x\n" |
396 | " error: %.8x cfg_lba:%.8x fatstat:%.4x\n", | ||
396 | ace_in32(ace, ACE_CTRL), | 397 | ace_in32(ace, ACE_CTRL), |
397 | ace_in(ace, ACE_SECCNTCMD), | 398 | ace_in(ace, ACE_SECCNTCMD), |
398 | ace_in(ace, ACE_VERSION), | 399 | ace_in(ace, ACE_VERSION), |
@@ -940,7 +941,7 @@ static int ace_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
940 | return 0; | 941 | return 0; |
941 | } | 942 | } |
942 | 943 | ||
943 | static struct block_device_operations ace_fops = { | 944 | static const struct block_device_operations ace_fops = { |
944 | .owner = THIS_MODULE, | 945 | .owner = THIS_MODULE, |
945 | .open = ace_open, | 946 | .open = ace_open, |
946 | .release = ace_release, | 947 | .release = ace_release, |
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 4575171e5be..64f941e0f14 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c | |||
@@ -64,7 +64,6 @@ static int current_device = -1; | |||
64 | 64 | ||
65 | static DEFINE_SPINLOCK(z2ram_lock); | 65 | static DEFINE_SPINLOCK(z2ram_lock); |
66 | 66 | ||
67 | static struct block_device_operations z2_fops; | ||
68 | static struct gendisk *z2ram_gendisk; | 67 | static struct gendisk *z2ram_gendisk; |
69 | 68 | ||
70 | static void do_z2_request(struct request_queue *q) | 69 | static void do_z2_request(struct request_queue *q) |
@@ -315,7 +314,7 @@ z2_release(struct gendisk *disk, fmode_t mode) | |||
315 | return 0; | 314 | return 0; |
316 | } | 315 | } |
317 | 316 | ||
318 | static struct block_device_operations z2_fops = | 317 | static const struct block_device_operations z2_fops = |
319 | { | 318 | { |
320 | .owner = THIS_MODULE, | 319 | .owner = THIS_MODULE, |
321 | .open = z2_open, | 320 | .open = z2_open, |
@@ -374,7 +373,7 @@ err: | |||
374 | static void __exit z2_exit(void) | 373 | static void __exit z2_exit(void) |
375 | { | 374 | { |
376 | int i, j; | 375 | int i, j; |
377 | blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256); | 376 | blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT); |
378 | unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME); | 377 | unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME); |
379 | del_gendisk(z2ram_gendisk); | 378 | del_gendisk(z2ram_gendisk); |
380 | put_disk(z2ram_gendisk); | 379 | put_disk(z2ram_gendisk); |