summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMadhuranath Iyengar <Madhu.Iyengar@qlogic.com>2010-10-15 11:27:46 -0700
committerJames Bottomley <James.Bottomley@suse.de>2010-10-25 16:03:18 -0500
commite30d1756480dc5d139458b140b69873cdb10119f (patch)
treea3177311cd8c687c781e70f9b19774c79954bdd1 /drivers
parent339aa70ecb3d0ef733f4d0393e2b5f6aea617839 (diff)
downloadop-kernel-dev-e30d1756480dc5d139458b140b69873cdb10119f.zip
op-kernel-dev-e30d1756480dc5d139458b140b69873cdb10119f.tar.gz
[SCSI] qla2xxx: Addition of shutdown callback handler.
This patch adds a shutdown handler to qla2xxx driver to make sure that all DMA and firmware activities are stopped, and any associated driver resources are released. The need for this handler arose when executing kexec in specific environments caused the data of the 2nd kernel to be corrupted, due to DMA activities. Signed-off-by: Madhuranath Iyengar <Madhu.Iyengar@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c7
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c82
2 files changed, 74 insertions, 15 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 77c68a7..a7ad22b 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1344,6 +1344,13 @@ cont_alloc:
qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for "
"firmware dump!!!\n", dump_size / 1024);
+ if (ha->fce) {
+ dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
+ ha->fce_dma);
+ ha->fce = NULL;
+ ha->fce_dma = 0;
+ }
+
if (ha->eft) {
dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft,
ha->eft_dma);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 941b4a6..05977e7 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -260,6 +260,7 @@ static void qla2x00_rst_aen(scsi_qla_host_t *);
static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
struct req_que **, struct rsp_que **);
+static void qla2x00_free_fw_dump(struct qla_hw_data *);
static void qla2x00_mem_free(struct qla_hw_data *);
static void qla2x00_sp_free_dma(srb_t *);
@@ -2342,6 +2343,42 @@ probe_out:
}
static void
+qla2x00_shutdown(struct pci_dev *pdev)
+{
+ scsi_qla_host_t *vha;
+ struct qla_hw_data *ha;
+
+ vha = pci_get_drvdata(pdev);
+ ha = vha->hw;
+
+ /* Turn-off FCE trace */
+ if (ha->flags.fce_enabled) {
+ qla2x00_disable_fce_trace(vha, NULL, NULL);
+ ha->flags.fce_enabled = 0;
+ }
+
+ /* Turn-off EFT trace */
+ if (ha->eft)
+ qla2x00_disable_eft_trace(vha);
+
+ /* Stop currently executing firmware. */
+ qla2x00_try_to_stop_firmware(vha);
+
+ /* Turn adapter off line */
+ vha->flags.online = 0;
+
+ /* turn-off interrupts on the card */
+ if (ha->interrupts_on) {
+ vha->flags.init_done = 0;
+ ha->isp_ops->disable_intrs(ha);
+ }
+
+ qla2x00_free_irqs(vha);
+
+ qla2x00_free_fw_dump(ha);
+}
+
+static void
qla2x00_remove_one(struct pci_dev *pdev)
{
scsi_qla_host_t *base_vha, *vha;
@@ -2830,28 +2867,48 @@ fail:
}
/*
-* qla2x00_mem_free
-* Frees all adapter allocated memory.
+* qla2x00_free_fw_dump
+* Frees fw dump stuff.
*
* Input:
-* ha = adapter block pointer.
+* ha = adapter block pointer.
*/
static void
-qla2x00_mem_free(struct qla_hw_data *ha)
+qla2x00_free_fw_dump(struct qla_hw_data *ha)
{
- if (ha->srb_mempool)
- mempool_destroy(ha->srb_mempool);
-
if (ha->fce)
dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
- ha->fce_dma);
+ ha->fce_dma);
if (ha->fw_dump) {
if (ha->eft)
dma_free_coherent(&ha->pdev->dev,
- ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);
+ ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);
vfree(ha->fw_dump);
}
+ ha->fce = NULL;
+ ha->fce_dma = 0;
+ ha->eft = NULL;
+ ha->eft_dma = 0;
+ ha->fw_dump = NULL;
+ ha->fw_dumped = 0;
+ ha->fw_dump_reading = 0;
+}
+
+/*
+* qla2x00_mem_free
+* Frees all adapter allocated memory.
+*
+* Input:
+* ha = adapter block pointer.
+*/
+static void
+qla2x00_mem_free(struct qla_hw_data *ha)
+{
+ qla2x00_free_fw_dump(ha);
+
+ if (ha->srb_mempool)
+ mempool_destroy(ha->srb_mempool);
if (ha->dcbx_tlv)
dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
@@ -2925,8 +2982,6 @@ qla2x00_mem_free(struct qla_hw_data *ha)
ha->srb_mempool = NULL;
ha->ctx_mempool = NULL;
- ha->eft = NULL;
- ha->eft_dma = 0;
ha->sns_cmd = NULL;
ha->sns_cmd_dma = 0;
ha->ct_sns = NULL;
@@ -2946,10 +3001,6 @@ qla2x00_mem_free(struct qla_hw_data *ha)
ha->gid_list = NULL;
ha->gid_list_dma = 0;
-
- ha->fw_dump = NULL;
- ha->fw_dumped = 0;
- ha->fw_dump_reading = 0;
}
struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
@@ -4049,6 +4100,7 @@ static struct pci_driver qla2xxx_pci_driver = {
.id_table = qla2xxx_pci_tbl,
.probe = qla2x00_probe_one,
.remove = qla2x00_remove_one,
+ .shutdown = qla2x00_shutdown,
.err_handler = &qla2xxx_err_handler,
};
OpenPOWER on IntegriCloud