Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 195f2c65 authored by Robert Elliott's avatar Robert Elliott Committed by James Bottomley
Browse files

hpsa: clean up error handling



refactor error cleanup and shutdown
disable interrupts and pci_disable_device on critical failures
add hpsa_free_cfgtables function

Reviewed-by: default avatarScott Teel <scott.teel@pmcs.com>
Reviewed-by: default avatarKevin Barnett <kevin.barnett@pmcs.com>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Reviewed-by: default avatarHannes Reinecke <hare@Suse.de>
Signed-off-by: default avatarRobert Elliott <elliott@hp.com>
Signed-off-by: default avatarDon Brace <don.brace@pmcs.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent cc64c817
Loading
Loading
Loading
Loading
+58 −34
Original line number Diff line number Diff line
@@ -6495,6 +6495,17 @@ static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr,
	return 0;
}

static void hpsa_free_cfgtables(struct ctlr_info *h)
{
	if (h->transtable)
		iounmap(h->transtable);
	if (h->cfgtable)
		iounmap(h->cfgtable);
}

/* Find and map CISS config table and transfer table
+ * several items must be unmapped (freed) later
+ * */
static int hpsa_find_cfgtables(struct ctlr_info *h)
{
	u64 cfg_offset;
@@ -6521,8 +6532,11 @@ static int hpsa_find_cfgtables(struct ctlr_info *h)
	h->transtable = remap_pci_mem(pci_resource_start(h->pdev,
				cfg_base_addr_index)+cfg_offset+trans_offset,
				sizeof(*h->transtable));
	if (!h->transtable)
	if (!h->transtable) {
		dev_err(&h->pdev->dev, "Failed mapping transfer table\n");
		hpsa_free_cfgtables(h);
		return -ENOMEM;
	}
	return 0;
}

@@ -6698,6 +6712,17 @@ static int hpsa_enter_simple_mode(struct ctlr_info *h)
	return -ENODEV;
}

/* free items allocated or mapped by hpsa_pci_init */
static void hpsa_free_pci_init(struct ctlr_info *h)
{
	hpsa_free_cfgtables(h);			/* pci_init 4 */
	iounmap(h->vaddr);			/* pci_init 3 */
	hpsa_disable_interrupt_mode(h);		/* pci_init 2 */
	pci_release_regions(h->pdev);		/* pci_init 2 */
	pci_disable_device(h->pdev);		/* pci_init 1 */
}

/* several items must be freed later */
static int hpsa_pci_init(struct ctlr_info *h)
{
	int prod_index, err;
@@ -6716,15 +6741,15 @@ static int hpsa_pci_init(struct ctlr_info *h)

	err = pci_enable_device(h->pdev);
	if (err) {
		dev_warn(&h->pdev->dev, "unable to enable PCI device\n");
		dev_err(&h->pdev->dev, "failed to enable PCI device\n");
		return err;
	}

	err = pci_request_regions(h->pdev, HPSA);
	if (err) {
		dev_err(&h->pdev->dev,
			"cannot obtain PCI resources, aborting\n");
		return err;
			"failed to obtain PCI resources\n");
		goto clean1;	/* pci */
	}

	pci_set_master(h->pdev);
@@ -6732,40 +6757,41 @@ static int hpsa_pci_init(struct ctlr_info *h)
	hpsa_interrupt_mode(h);
	err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr);
	if (err)
		goto err_out_free_res;
		goto clean2;	/* intmode+region, pci */
	h->vaddr = remap_pci_mem(h->paddr, 0x250);
	if (!h->vaddr) {
		dev_err(&h->pdev->dev, "failed to remap PCI mem\n");
		err = -ENOMEM;
		goto err_out_free_res;
		goto clean2;	/* intmode+region, pci */
	}
	err = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY);
	if (err)
		goto err_out_free_res;
		goto clean3;	/* vaddr, intmode+region, pci */
	err = hpsa_find_cfgtables(h);
	if (err)
		goto err_out_free_res;
		goto clean3;	/* vaddr, intmode+region, pci */
	hpsa_find_board_params(h);

	if (!hpsa_CISS_signature_present(h)) {
		err = -ENODEV;
		goto err_out_free_res;
		goto clean4;	/* cfgtables, vaddr, intmode+region, pci */
	}
	hpsa_set_driver_support_bits(h);
	hpsa_p600_dma_prefetch_quirk(h);
	err = hpsa_enter_simple_mode(h);
	if (err)
		goto err_out_free_res;
		goto clean4;	/* cfgtables, vaddr, intmode+region, pci */
	return 0;

err_out_free_res:
	if (h->transtable)
		iounmap(h->transtable);
	if (h->cfgtable)
		iounmap(h->cfgtable);
	if (h->vaddr)
clean4:	/* cfgtables, vaddr, intmode+region, pci */
	hpsa_free_cfgtables(h);
clean3:	/* vaddr, intmode+region, pci */
	iounmap(h->vaddr);
	pci_disable_device(h->pdev);
clean2:	/* intmode+region, pci */
	hpsa_disable_interrupt_mode(h);
	pci_release_regions(h->pdev);
clean1:	/* pci */
	pci_disable_device(h->pdev);
	return err;
}

@@ -6974,8 +7000,9 @@ static int hpsa_request_irqs(struct ctlr_info *h,
		}
	}
	if (rc) {
		dev_err(&h->pdev->dev, "unable to get irq %d for %s\n",
		dev_err(&h->pdev->dev, "failed to get irq %d for %s\n",
		       h->intr[h->intr_mode], h->devname);
		hpsa_free_irqs(h);
		return -ENODEV;
	}
	return 0;
@@ -7027,15 +7054,11 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
	kfree(h->ioaccel1_blockFetchTable);
	kfree(h->blockFetchTable);
	hpsa_free_reply_queues(h);
	if (h->vaddr)
		iounmap(h->vaddr);
	if (h->transtable)
		iounmap(h->transtable);
	if (h->cfgtable)
		iounmap(h->cfgtable);
	hpsa_disable_interrupt_mode(h);
	hpsa_free_cfgtables(h);			/* pci_init 4 */
	iounmap(h->vaddr);			/* pci_init 3 */
	hpsa_disable_interrupt_mode(h);		/* pci_init 2 */
	pci_disable_device(h->pdev);
	pci_release_regions(h->pdev);
	pci_release_regions(h->pdev);		/* pci_init 2 */
	kfree(h);
}

@@ -7359,7 +7382,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
			dac = 0;
		} else {
			dev_err(&pdev->dev, "no suitable DMA available\n");
			goto clean1;
			goto clean2;
		}
	}

@@ -7470,6 +7493,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
clean2_and_free_irqs:
	hpsa_free_irqs(h);
clean2:
	hpsa_free_pci_init(h);
clean1:
	if (h->resubmit_wq)
		destroy_workqueue(h->resubmit_wq);
@@ -7561,12 +7585,10 @@ static void hpsa_remove_one(struct pci_dev *pdev)
	destroy_workqueue(h->resubmit_wq);
	hpsa_unregister_scsi(h);	/* unhook from SCSI subsystem */

	/* includes hpsa_free_irqs and hpsa_disable_interrupt_mode */
	/* includes hpsa_free_irqs */
	/* includes hpsa_disable_interrupt_mode - pci_init 2 */
	hpsa_shutdown(pdev);

	iounmap(h->vaddr);
	iounmap(h->transtable);
	iounmap(h->cfgtable);
	hpsa_free_device_info(h);
	hpsa_free_sg_chain_blocks(h);
	pci_free_consistent(h->pdev,
@@ -7581,8 +7603,10 @@ static void hpsa_remove_one(struct pci_dev *pdev)
	kfree(h->ioaccel1_blockFetchTable);
	kfree(h->ioaccel2_blockFetchTable);
	kfree(h->hba_inquiry_data);
	pci_disable_device(pdev);
	pci_release_regions(pdev);

	/* includes hpsa_disable_interrupt_mode - pci_init 2 */
	hpsa_free_pci_init(h);

	free_percpu(h->lockup_detected);
	kfree(h);
}