diff options
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r-- | drivers/block/cciss.c | 136 |
1 files changed, 64 insertions, 72 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 2cc4dda46279..8e0f9256eb58 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -66,6 +66,7 @@ MODULE_VERSION("3.6.26"); | |||
66 | MODULE_LICENSE("GPL"); | 66 | MODULE_LICENSE("GPL"); |
67 | 67 | ||
68 | static DEFINE_MUTEX(cciss_mutex); | 68 | static DEFINE_MUTEX(cciss_mutex); |
69 | static struct proc_dir_entry *proc_cciss; | ||
69 | 70 | ||
70 | #include "cciss_cmd.h" | 71 | #include "cciss_cmd.h" |
71 | #include "cciss.h" | 72 | #include "cciss.h" |
@@ -113,6 +114,8 @@ static struct board_type products[] = { | |||
113 | {0x409D0E11, "Smart Array 6400 EM", &SA5_access}, | 114 | {0x409D0E11, "Smart Array 6400 EM", &SA5_access}, |
114 | {0x40910E11, "Smart Array 6i", &SA5_access}, | 115 | {0x40910E11, "Smart Array 6i", &SA5_access}, |
115 | {0x3225103C, "Smart Array P600", &SA5_access}, | 116 | {0x3225103C, "Smart Array P600", &SA5_access}, |
117 | {0x3223103C, "Smart Array P800", &SA5_access}, | ||
118 | {0x3234103C, "Smart Array P400", &SA5_access}, | ||
116 | {0x3235103C, "Smart Array P400i", &SA5_access}, | 119 | {0x3235103C, "Smart Array P400i", &SA5_access}, |
117 | {0x3211103C, "Smart Array E200i", &SA5_access}, | 120 | {0x3211103C, "Smart Array E200i", &SA5_access}, |
118 | {0x3212103C, "Smart Array E200", &SA5_access}, | 121 | {0x3212103C, "Smart Array E200", &SA5_access}, |
@@ -361,8 +364,6 @@ static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", | |||
361 | #define ENG_GIG_FACTOR (ENG_GIG/512) | 364 | #define ENG_GIG_FACTOR (ENG_GIG/512) |
362 | #define ENGAGE_SCSI "engage scsi" | 365 | #define ENGAGE_SCSI "engage scsi" |
363 | 366 | ||
364 | static struct proc_dir_entry *proc_cciss; | ||
365 | |||
366 | static void cciss_seq_show_header(struct seq_file *seq) | 367 | static void cciss_seq_show_header(struct seq_file *seq) |
367 | { | 368 | { |
368 | ctlr_info_t *h = seq->private; | 369 | ctlr_info_t *h = seq->private; |
@@ -2833,6 +2834,8 @@ static int cciss_revalidate(struct gendisk *disk) | |||
2833 | InquiryData_struct *inq_buff = NULL; | 2834 | InquiryData_struct *inq_buff = NULL; |
2834 | 2835 | ||
2835 | for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { | 2836 | for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { |
2837 | if (!h->drv[logvol]) | ||
2838 | continue; | ||
2836 | if (memcmp(h->drv[logvol]->LunID, drv->LunID, | 2839 | if (memcmp(h->drv[logvol]->LunID, drv->LunID, |
2837 | sizeof(drv->LunID)) == 0) { | 2840 | sizeof(drv->LunID)) == 0) { |
2838 | FOUND = 1; | 2841 | FOUND = 1; |
@@ -3753,7 +3756,7 @@ static void __devinit cciss_wait_for_mode_change_ack(ctlr_info_t *h) | |||
3753 | for (i = 0; i < MAX_CONFIG_WAIT; i++) { | 3756 | for (i = 0; i < MAX_CONFIG_WAIT; i++) { |
3754 | if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) | 3757 | if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) |
3755 | break; | 3758 | break; |
3756 | msleep(10); | 3759 | usleep_range(10000, 20000); |
3757 | } | 3760 | } |
3758 | } | 3761 | } |
3759 | 3762 | ||
@@ -3937,10 +3940,9 @@ static int __devinit cciss_lookup_board_id(struct pci_dev *pdev, u32 *board_id) | |||
3937 | *board_id = ((subsystem_device_id << 16) & 0xffff0000) | | 3940 | *board_id = ((subsystem_device_id << 16) & 0xffff0000) | |
3938 | subsystem_vendor_id; | 3941 | subsystem_vendor_id; |
3939 | 3942 | ||
3940 | for (i = 0; i < ARRAY_SIZE(products); i++) { | 3943 | for (i = 0; i < ARRAY_SIZE(products); i++) |
3941 | if (*board_id == products[i].board_id) | 3944 | if (*board_id == products[i].board_id) |
3942 | return i; | 3945 | return i; |
3943 | } | ||
3944 | dev_warn(&pdev->dev, "unrecognized board ID: 0x%08x, ignoring.\n", | 3946 | dev_warn(&pdev->dev, "unrecognized board ID: 0x%08x, ignoring.\n", |
3945 | *board_id); | 3947 | *board_id); |
3946 | return -ENODEV; | 3948 | return -ENODEV; |
@@ -3971,18 +3973,31 @@ static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev, | |||
3971 | return -ENODEV; | 3973 | return -ENODEV; |
3972 | } | 3974 | } |
3973 | 3975 | ||
3974 | static int __devinit cciss_wait_for_board_ready(ctlr_info_t *h) | 3976 | static int __devinit cciss_wait_for_board_state(struct pci_dev *pdev, |
3977 | void __iomem *vaddr, int wait_for_ready) | ||
3978 | #define BOARD_READY 1 | ||
3979 | #define BOARD_NOT_READY 0 | ||
3975 | { | 3980 | { |
3976 | int i; | 3981 | int i, iterations; |
3977 | u32 scratchpad; | 3982 | u32 scratchpad; |
3978 | 3983 | ||
3979 | for (i = 0; i < CCISS_BOARD_READY_ITERATIONS; i++) { | 3984 | if (wait_for_ready) |
3980 | scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET); | 3985 | iterations = CCISS_BOARD_READY_ITERATIONS; |
3981 | if (scratchpad == CCISS_FIRMWARE_READY) | 3986 | else |
3982 | return 0; | 3987 | iterations = CCISS_BOARD_NOT_READY_ITERATIONS; |
3988 | |||
3989 | for (i = 0; i < iterations; i++) { | ||
3990 | scratchpad = readl(vaddr + SA5_SCRATCHPAD_OFFSET); | ||
3991 | if (wait_for_ready) { | ||
3992 | if (scratchpad == CCISS_FIRMWARE_READY) | ||
3993 | return 0; | ||
3994 | } else { | ||
3995 | if (scratchpad != CCISS_FIRMWARE_READY) | ||
3996 | return 0; | ||
3997 | } | ||
3983 | msleep(CCISS_BOARD_READY_POLL_INTERVAL_MSECS); | 3998 | msleep(CCISS_BOARD_READY_POLL_INTERVAL_MSECS); |
3984 | } | 3999 | } |
3985 | dev_warn(&h->pdev->dev, "board not ready, timed out.\n"); | 4000 | dev_warn(&pdev->dev, "board not ready, timed out.\n"); |
3986 | return -ENODEV; | 4001 | return -ENODEV; |
3987 | } | 4002 | } |
3988 | 4003 | ||
@@ -4031,6 +4046,11 @@ static int __devinit cciss_find_cfgtables(ctlr_info_t *h) | |||
4031 | static void __devinit cciss_get_max_perf_mode_cmds(struct ctlr_info *h) | 4046 | static void __devinit cciss_get_max_perf_mode_cmds(struct ctlr_info *h) |
4032 | { | 4047 | { |
4033 | h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); | 4048 | h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands)); |
4049 | |||
4050 | /* Limit commands in memory limited kdump scenario. */ | ||
4051 | if (reset_devices && h->max_commands > 32) | ||
4052 | h->max_commands = 32; | ||
4053 | |||
4034 | if (h->max_commands < 16) { | 4054 | if (h->max_commands < 16) { |
4035 | dev_warn(&h->pdev->dev, "Controller reports " | 4055 | dev_warn(&h->pdev->dev, "Controller reports " |
4036 | "max supported commands of %d, an obvious lie. " | 4056 | "max supported commands of %d, an obvious lie. " |
@@ -4148,7 +4168,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *h) | |||
4148 | err = -ENOMEM; | 4168 | err = -ENOMEM; |
4149 | goto err_out_free_res; | 4169 | goto err_out_free_res; |
4150 | } | 4170 | } |
4151 | err = cciss_wait_for_board_ready(h); | 4171 | err = cciss_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY); |
4152 | if (err) | 4172 | if (err) |
4153 | goto err_out_free_res; | 4173 | goto err_out_free_res; |
4154 | err = cciss_find_cfgtables(h); | 4174 | err = cciss_find_cfgtables(h); |
@@ -4313,36 +4333,6 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u | |||
4313 | #define cciss_soft_reset_controller(p) cciss_message(p, 1, 0) | 4333 | #define cciss_soft_reset_controller(p) cciss_message(p, 1, 0) |
4314 | #define cciss_noop(p) cciss_message(p, 3, 0) | 4334 | #define cciss_noop(p) cciss_message(p, 3, 0) |
4315 | 4335 | ||
4316 | static __devinit int cciss_reset_msi(struct pci_dev *pdev) | ||
4317 | { | ||
4318 | /* the #defines are stolen from drivers/pci/msi.h. */ | ||
4319 | #define msi_control_reg(base) (base + PCI_MSI_FLAGS) | ||
4320 | #define PCI_MSIX_FLAGS_ENABLE (1 << 15) | ||
4321 | |||
4322 | int pos; | ||
4323 | u16 control = 0; | ||
4324 | |||
4325 | pos = pci_find_capability(pdev, PCI_CAP_ID_MSI); | ||
4326 | if (pos) { | ||
4327 | pci_read_config_word(pdev, msi_control_reg(pos), &control); | ||
4328 | if (control & PCI_MSI_FLAGS_ENABLE) { | ||
4329 | dev_info(&pdev->dev, "resetting MSI\n"); | ||
4330 | pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSI_FLAGS_ENABLE); | ||
4331 | } | ||
4332 | } | ||
4333 | |||
4334 | pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); | ||
4335 | if (pos) { | ||
4336 | pci_read_config_word(pdev, msi_control_reg(pos), &control); | ||
4337 | if (control & PCI_MSIX_FLAGS_ENABLE) { | ||
4338 | dev_info(&pdev->dev, "resetting MSI-X\n"); | ||
4339 | pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSIX_FLAGS_ENABLE); | ||
4340 | } | ||
4341 | } | ||
4342 | |||
4343 | return 0; | ||
4344 | } | ||
4345 | |||
4346 | static int cciss_controller_hard_reset(struct pci_dev *pdev, | 4336 | static int cciss_controller_hard_reset(struct pci_dev *pdev, |
4347 | void * __iomem vaddr, bool use_doorbell) | 4337 | void * __iomem vaddr, bool use_doorbell) |
4348 | { | 4338 | { |
@@ -4397,17 +4387,17 @@ static int cciss_controller_hard_reset(struct pci_dev *pdev, | |||
4397 | * states or using the doorbell register. */ | 4387 | * states or using the doorbell register. */ |
4398 | static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) | 4388 | static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) |
4399 | { | 4389 | { |
4400 | u16 saved_config_space[32]; | ||
4401 | u64 cfg_offset; | 4390 | u64 cfg_offset; |
4402 | u32 cfg_base_addr; | 4391 | u32 cfg_base_addr; |
4403 | u64 cfg_base_addr_index; | 4392 | u64 cfg_base_addr_index; |
4404 | void __iomem *vaddr; | 4393 | void __iomem *vaddr; |
4405 | unsigned long paddr; | 4394 | unsigned long paddr; |
4406 | u32 misc_fw_support, active_transport; | 4395 | u32 misc_fw_support, active_transport; |
4407 | int rc, i; | 4396 | int rc; |
4408 | CfgTable_struct __iomem *cfgtable; | 4397 | CfgTable_struct __iomem *cfgtable; |
4409 | bool use_doorbell; | 4398 | bool use_doorbell; |
4410 | u32 board_id; | 4399 | u32 board_id; |
4400 | u16 command_register; | ||
4411 | 4401 | ||
4412 | /* For controllers as old a the p600, this is very nearly | 4402 | /* For controllers as old a the p600, this is very nearly |
4413 | * the same thing as | 4403 | * the same thing as |
@@ -4417,14 +4407,6 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) | |||
4417 | * pci_set_power_state(pci_dev, PCI_D0); | 4407 | * pci_set_power_state(pci_dev, PCI_D0); |
4418 | * pci_restore_state(pci_dev); | 4408 | * pci_restore_state(pci_dev); |
4419 | * | 4409 | * |
4420 | * but we can't use these nice canned kernel routines on | ||
4421 | * kexec, because they also check the MSI/MSI-X state in PCI | ||
4422 | * configuration space and do the wrong thing when it is | ||
4423 | * set/cleared. Also, the pci_save/restore_state functions | ||
4424 | * violate the ordering requirements for restoring the | ||
4425 | * configuration space from the CCISS document (see the | ||
4426 | * comment below). So we roll our own .... | ||
4427 | * | ||
4428 | * For controllers newer than the P600, the pci power state | 4410 | * For controllers newer than the P600, the pci power state |
4429 | * method of resetting doesn't work so we have another way | 4411 | * method of resetting doesn't work so we have another way |
4430 | * using the doorbell register. | 4412 | * using the doorbell register. |
@@ -4443,8 +4425,13 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) | |||
4443 | return -ENODEV; | 4425 | return -ENODEV; |
4444 | } | 4426 | } |
4445 | 4427 | ||
4446 | for (i = 0; i < 32; i++) | 4428 | /* Save the PCI command register */ |
4447 | pci_read_config_word(pdev, 2*i, &saved_config_space[i]); | 4429 | pci_read_config_word(pdev, 4, &command_register); |
4430 | /* Turn the board off. This is so that later pci_restore_state() | ||
4431 | * won't turn the board on before the rest of config space is ready. | ||
4432 | */ | ||
4433 | pci_disable_device(pdev); | ||
4434 | pci_save_state(pdev); | ||
4448 | 4435 | ||
4449 | /* find the first memory BAR, so we can find the cfg table */ | 4436 | /* find the first memory BAR, so we can find the cfg table */ |
4450 | rc = cciss_pci_find_memory_BAR(pdev, &paddr); | 4437 | rc = cciss_pci_find_memory_BAR(pdev, &paddr); |
@@ -4479,26 +4466,32 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) | |||
4479 | rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell); | 4466 | rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell); |
4480 | if (rc) | 4467 | if (rc) |
4481 | goto unmap_cfgtable; | 4468 | goto unmap_cfgtable; |
4482 | 4469 | pci_restore_state(pdev); | |
4483 | /* Restore the PCI configuration space. The Open CISS | 4470 | rc = pci_enable_device(pdev); |
4484 | * Specification says, "Restore the PCI Configuration | 4471 | if (rc) { |
4485 | * Registers, offsets 00h through 60h. It is important to | 4472 | dev_warn(&pdev->dev, "failed to enable device.\n"); |
4486 | * restore the command register, 16-bits at offset 04h, | 4473 | goto unmap_cfgtable; |
4487 | * last. Do not restore the configuration status register, | ||
4488 | * 16-bits at offset 06h." Note that the offset is 2*i. | ||
4489 | */ | ||
4490 | for (i = 0; i < 32; i++) { | ||
4491 | if (i == 2 || i == 3) | ||
4492 | continue; | ||
4493 | pci_write_config_word(pdev, 2*i, saved_config_space[i]); | ||
4494 | } | 4474 | } |
4495 | wmb(); | 4475 | pci_write_config_word(pdev, 4, command_register); |
4496 | pci_write_config_word(pdev, 4, saved_config_space[2]); | ||
4497 | 4476 | ||
4498 | /* Some devices (notably the HP Smart Array 5i Controller) | 4477 | /* Some devices (notably the HP Smart Array 5i Controller) |
4499 | need a little pause here */ | 4478 | need a little pause here */ |
4500 | msleep(CCISS_POST_RESET_PAUSE_MSECS); | 4479 | msleep(CCISS_POST_RESET_PAUSE_MSECS); |
4501 | 4480 | ||
4481 | /* Wait for board to become not ready, then ready. */ | ||
4482 | dev_info(&pdev->dev, "Waiting for board to become ready.\n"); | ||
4483 | rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY); | ||
4484 | if (rc) /* Don't bail, might be E500, etc. which can't be reset */ | ||
4485 | dev_warn(&pdev->dev, | ||
4486 | "failed waiting for board to become not ready\n"); | ||
4487 | rc = cciss_wait_for_board_state(pdev, vaddr, BOARD_READY); | ||
4488 | if (rc) { | ||
4489 | dev_warn(&pdev->dev, | ||
4490 | "failed waiting for board to become ready\n"); | ||
4491 | goto unmap_cfgtable; | ||
4492 | } | ||
4493 | dev_info(&pdev->dev, "board ready.\n"); | ||
4494 | |||
4502 | /* Controller should be in simple mode at this point. If it's not, | 4495 | /* Controller should be in simple mode at this point. If it's not, |
4503 | * It means we're on one of those controllers which doesn't support | 4496 | * It means we're on one of those controllers which doesn't support |
4504 | * the doorbell reset method and on which the PCI power management reset | 4497 | * the doorbell reset method and on which the PCI power management reset |
@@ -4539,8 +4532,6 @@ static __devinit int cciss_init_reset_devices(struct pci_dev *pdev) | |||
4539 | return 0; /* just try to do the kdump anyhow. */ | 4532 | return 0; /* just try to do the kdump anyhow. */ |
4540 | if (rc) | 4533 | if (rc) |
4541 | return -ENODEV; | 4534 | return -ENODEV; |
4542 | if (cciss_reset_msi(pdev)) | ||
4543 | return -ENODEV; | ||
4544 | 4535 | ||
4545 | /* Now try to get the controller to respond to a no-op */ | 4536 | /* Now try to get the controller to respond to a no-op */ |
4546 | for (i = 0; i < CCISS_POST_RESET_NOOP_RETRIES; i++) { | 4537 | for (i = 0; i < CCISS_POST_RESET_NOOP_RETRIES; i++) { |
@@ -4936,7 +4927,8 @@ static void __exit cciss_cleanup(void) | |||
4936 | } | 4927 | } |
4937 | } | 4928 | } |
4938 | kthread_stop(cciss_scan_thread); | 4929 | kthread_stop(cciss_scan_thread); |
4939 | remove_proc_entry("driver/cciss", NULL); | 4930 | if (proc_cciss) |
4931 | remove_proc_entry("driver/cciss", NULL); | ||
4940 | bus_unregister(&cciss_bus_type); | 4932 | bus_unregister(&cciss_bus_type); |
4941 | } | 4933 | } |
4942 | 4934 | ||