aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/cciss.c73
1 files changed, 15 insertions, 58 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index fd08644bf2a0..2e547bddc5a7 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -4361,36 +4361,6 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u
4361#define cciss_soft_reset_controller(p) cciss_message(p, 1, 0) 4361#define cciss_soft_reset_controller(p) cciss_message(p, 1, 0)
4362#define cciss_noop(p) cciss_message(p, 3, 0) 4362#define cciss_noop(p) cciss_message(p, 3, 0)
4363 4363
4364static __devinit int cciss_reset_msi(struct pci_dev *pdev)
4365{
4366/* the #defines are stolen from drivers/pci/msi.h. */
4367#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
4368#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
4369
4370 int pos;
4371 u16 control = 0;
4372
4373 pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
4374 if (pos) {
4375 pci_read_config_word(pdev, msi_control_reg(pos), &control);
4376 if (control & PCI_MSI_FLAGS_ENABLE) {
4377 dev_info(&pdev->dev, "resetting MSI\n");
4378 pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSI_FLAGS_ENABLE);
4379 }
4380 }
4381
4382 pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
4383 if (pos) {
4384 pci_read_config_word(pdev, msi_control_reg(pos), &control);
4385 if (control & PCI_MSIX_FLAGS_ENABLE) {
4386 dev_info(&pdev->dev, "resetting MSI-X\n");
4387 pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSIX_FLAGS_ENABLE);
4388 }
4389 }
4390
4391 return 0;
4392}
4393
4394static int cciss_controller_hard_reset(struct pci_dev *pdev, 4364static int cciss_controller_hard_reset(struct pci_dev *pdev,
4395 void * __iomem vaddr, bool use_doorbell) 4365 void * __iomem vaddr, bool use_doorbell)
4396{ 4366{
@@ -4445,17 +4415,17 @@ static int cciss_controller_hard_reset(struct pci_dev *pdev,
4445 * states or using the doorbell register. */ 4415 * states or using the doorbell register. */
4446static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) 4416static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
4447{ 4417{
4448 u16 saved_config_space[32];
4449 u64 cfg_offset; 4418 u64 cfg_offset;
4450 u32 cfg_base_addr; 4419 u32 cfg_base_addr;
4451 u64 cfg_base_addr_index; 4420 u64 cfg_base_addr_index;
4452 void __iomem *vaddr; 4421 void __iomem *vaddr;
4453 unsigned long paddr; 4422 unsigned long paddr;
4454 u32 misc_fw_support, active_transport; 4423 u32 misc_fw_support, active_transport;
4455 int rc, i; 4424 int rc;
4456 CfgTable_struct __iomem *cfgtable; 4425 CfgTable_struct __iomem *cfgtable;
4457 bool use_doorbell; 4426 bool use_doorbell;
4458 u32 board_id; 4427 u32 board_id;
4428 u16 command_register;
4459 4429
4460 /* For controllers as old a the p600, this is very nearly 4430 /* For controllers as old a the p600, this is very nearly
4461 * the same thing as 4431 * the same thing as
@@ -4465,14 +4435,6 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
4465 * pci_set_power_state(pci_dev, PCI_D0); 4435 * pci_set_power_state(pci_dev, PCI_D0);
4466 * pci_restore_state(pci_dev); 4436 * pci_restore_state(pci_dev);
4467 * 4437 *
4468 * but we can't use these nice canned kernel routines on
4469 * kexec, because they also check the MSI/MSI-X state in PCI
4470 * configuration space and do the wrong thing when it is
4471 * set/cleared. Also, the pci_save/restore_state functions
4472 * violate the ordering requirements for restoring the
4473 * configuration space from the CCISS document (see the
4474 * comment below). So we roll our own ....
4475 *
4476 * For controllers newer than the P600, the pci power state 4438 * For controllers newer than the P600, the pci power state
4477 * method of resetting doesn't work so we have another way 4439 * method of resetting doesn't work so we have another way
4478 * using the doorbell register. 4440 * using the doorbell register.
@@ -4491,8 +4453,13 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
4491 return -ENODEV; 4453 return -ENODEV;
4492 } 4454 }
4493 4455
4494 for (i = 0; i < 32; i++) 4456 /* Save the PCI command register */
4495 pci_read_config_word(pdev, 2*i, &saved_config_space[i]); 4457 pci_read_config_word(pdev, 4, &command_register);
4458 /* Turn the board off. This is so that later pci_restore_state()
4459 * won't turn the board on before the rest of config space is ready.
4460 */
4461 pci_disable_device(pdev);
4462 pci_save_state(pdev);
4496 4463
4497 /* find the first memory BAR, so we can find the cfg table */ 4464 /* find the first memory BAR, so we can find the cfg table */
4498 rc = cciss_pci_find_memory_BAR(pdev, &paddr); 4465 rc = cciss_pci_find_memory_BAR(pdev, &paddr);
@@ -4527,21 +4494,13 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev)
4527 rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell); 4494 rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell);
4528 if (rc) 4495 if (rc)
4529 goto unmap_cfgtable; 4496 goto unmap_cfgtable;
4530 4497 pci_restore_state(pdev);
4531 /* Restore the PCI configuration space. The Open CISS 4498 rc = pci_enable_device(pdev);
4532 * Specification says, "Restore the PCI Configuration 4499 if (rc) {
4533 * Registers, offsets 00h through 60h. It is important to 4500 dev_warn(&pdev->dev, "failed to enable device.\n");
4534 * restore the command register, 16-bits at offset 04h, 4501 goto unmap_cfgtable;
4535 * last. Do not restore the configuration status register,
4536 * 16-bits at offset 06h." Note that the offset is 2*i.
4537 */
4538 for (i = 0; i < 32; i++) {
4539 if (i == 2 || i == 3)
4540 continue;
4541 pci_write_config_word(pdev, 2*i, saved_config_space[i]);
4542 } 4502 }
4543 wmb(); 4503 pci_write_config_word(pdev, 4, command_register);
4544 pci_write_config_word(pdev, 4, saved_config_space[2]);
4545 4504
4546 /* Some devices (notably the HP Smart Array 5i Controller) 4505 /* Some devices (notably the HP Smart Array 5i Controller)
4547 need a little pause here */ 4506 need a little pause here */
@@ -4601,8 +4560,6 @@ static __devinit int cciss_init_reset_devices(struct pci_dev *pdev)
4601 return 0; /* just try to do the kdump anyhow. */ 4560 return 0; /* just try to do the kdump anyhow. */
4602 if (rc) 4561 if (rc)
4603 return -ENODEV; 4562 return -ENODEV;
4604 if (cciss_reset_msi(pdev))
4605 return -ENODEV;
4606 4563
4607 /* Now try to get the controller to respond to a no-op */ 4564 /* Now try to get the controller to respond to a no-op */
4608 for (i = 0; i < CCISS_POST_RESET_NOOP_RETRIES; i++) { 4565 for (i = 0; i < CCISS_POST_RESET_NOOP_RETRIES; i++) {