aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMadhuranath Iyengar <Madhu.Iyengar@qlogic.com>2010-10-15 14:27:46 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-10-25 17:03:18 -0400
commite30d1756480dc5d139458b140b69873cdb10119f (patch)
treea3177311cd8c687c781e70f9b19774c79954bdd1
parent339aa70ecb3d0ef733f4d0393e2b5f6aea617839 (diff)
[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>
-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 77c68a789681..a7ad22bf77e0 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1344,6 +1344,13 @@ cont_alloc:
1344 qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " 1344 qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for "
1345 "firmware dump!!!\n", dump_size / 1024); 1345 "firmware dump!!!\n", dump_size / 1024);
1346 1346
1347 if (ha->fce) {
1348 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
1349 ha->fce_dma);
1350 ha->fce = NULL;
1351 ha->fce_dma = 0;
1352 }
1353
1347 if (ha->eft) { 1354 if (ha->eft) {
1348 dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft, 1355 dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft,
1349 ha->eft_dma); 1356 ha->eft_dma);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 941b4a66fc2b..05977e736f76 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 *);
260 260
261static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t, 261static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
262 struct req_que **, struct rsp_que **); 262 struct req_que **, struct rsp_que **);
263static void qla2x00_free_fw_dump(struct qla_hw_data *);
263static void qla2x00_mem_free(struct qla_hw_data *); 264static void qla2x00_mem_free(struct qla_hw_data *);
264static void qla2x00_sp_free_dma(srb_t *); 265static void qla2x00_sp_free_dma(srb_t *);
265 266
@@ -2342,6 +2343,42 @@ probe_out:
2342} 2343}
2343 2344
2344static void 2345static void
2346qla2x00_shutdown(struct pci_dev *pdev)
2347{
2348 scsi_qla_host_t *vha;
2349 struct qla_hw_data *ha;
2350
2351 vha = pci_get_drvdata(pdev);
2352 ha = vha->hw;
2353
2354 /* Turn-off FCE trace */
2355 if (ha->flags.fce_enabled) {
2356 qla2x00_disable_fce_trace(vha, NULL, NULL);
2357 ha->flags.fce_enabled = 0;
2358 }
2359
2360 /* Turn-off EFT trace */
2361 if (ha->eft)
2362 qla2x00_disable_eft_trace(vha);
2363
2364 /* Stop currently executing firmware. */
2365 qla2x00_try_to_stop_firmware(vha);
2366
2367 /* Turn adapter off line */
2368 vha->flags.online = 0;
2369
2370 /* turn-off interrupts on the card */
2371 if (ha->interrupts_on) {
2372 vha->flags.init_done = 0;
2373 ha->isp_ops->disable_intrs(ha);
2374 }
2375
2376 qla2x00_free_irqs(vha);
2377
2378 qla2x00_free_fw_dump(ha);
2379}
2380
2381static void
2345qla2x00_remove_one(struct pci_dev *pdev) 2382qla2x00_remove_one(struct pci_dev *pdev)
2346{ 2383{
2347 scsi_qla_host_t *base_vha, *vha; 2384 scsi_qla_host_t *base_vha, *vha;
@@ -2830,28 +2867,48 @@ fail:
2830} 2867}
2831 2868
2832/* 2869/*
2833* qla2x00_mem_free 2870* qla2x00_free_fw_dump
2834* Frees all adapter allocated memory. 2871* Frees fw dump stuff.
2835* 2872*
2836* Input: 2873* Input:
2837* ha = adapter block pointer. 2874* ha = adapter block pointer.
2838*/ 2875*/
2839static void 2876static void
2840qla2x00_mem_free(struct qla_hw_data *ha) 2877qla2x00_free_fw_dump(struct qla_hw_data *ha)
2841{ 2878{
2842 if (ha->srb_mempool)
2843 mempool_destroy(ha->srb_mempool);
2844
2845 if (ha->fce) 2879 if (ha->fce)
2846 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce, 2880 dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce,
2847 ha->fce_dma); 2881 ha->fce_dma);
2848 2882
2849 if (ha->fw_dump) { 2883 if (ha->fw_dump) {
2850 if (ha->eft) 2884 if (ha->eft)
2851 dma_free_coherent(&ha->pdev->dev, 2885 dma_free_coherent(&ha->pdev->dev,
2852 ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma); 2886 ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma);
2853 vfree(ha->fw_dump); 2887 vfree(ha->fw_dump);
2854 } 2888 }
2889 ha->fce = NULL;
2890 ha->fce_dma = 0;
2891 ha->eft = NULL;
2892 ha->eft_dma = 0;
2893 ha->fw_dump = NULL;
2894 ha->fw_dumped = 0;
2895 ha->fw_dump_reading = 0;
2896}
2897
2898/*
2899* qla2x00_mem_free
2900* Frees all adapter allocated memory.
2901*
2902* Input:
2903* ha = adapter block pointer.
2904*/
2905static void
2906qla2x00_mem_free(struct qla_hw_data *ha)
2907{
2908 qla2x00_free_fw_dump(ha);
2909
2910 if (ha->srb_mempool)
2911 mempool_destroy(ha->srb_mempool);
2855 2912
2856 if (ha->dcbx_tlv) 2913 if (ha->dcbx_tlv)
2857 dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE, 2914 dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
@@ -2925,8 +2982,6 @@ qla2x00_mem_free(struct qla_hw_data *ha)
2925 2982
2926 ha->srb_mempool = NULL; 2983 ha->srb_mempool = NULL;
2927 ha->ctx_mempool = NULL; 2984 ha->ctx_mempool = NULL;
2928 ha->eft = NULL;
2929 ha->eft_dma = 0;
2930 ha->sns_cmd = NULL; 2985 ha->sns_cmd = NULL;
2931 ha->sns_cmd_dma = 0; 2986 ha->sns_cmd_dma = 0;
2932 ha->ct_sns = NULL; 2987 ha->ct_sns = NULL;
@@ -2946,10 +3001,6 @@ qla2x00_mem_free(struct qla_hw_data *ha)
2946 3001
2947 ha->gid_list = NULL; 3002 ha->gid_list = NULL;
2948 ha->gid_list_dma = 0; 3003 ha->gid_list_dma = 0;
2949
2950 ha->fw_dump = NULL;
2951 ha->fw_dumped = 0;
2952 ha->fw_dump_reading = 0;
2953} 3004}
2954 3005
2955struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, 3006struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
@@ -4049,6 +4100,7 @@ static struct pci_driver qla2xxx_pci_driver = {
4049 .id_table = qla2xxx_pci_tbl, 4100 .id_table = qla2xxx_pci_tbl,
4050 .probe = qla2x00_probe_one, 4101 .probe = qla2x00_probe_one,
4051 .remove = qla2x00_remove_one, 4102 .remove = qla2x00_remove_one,
4103 .shutdown = qla2x00_shutdown,
4052 .err_handler = &qla2xxx_err_handler, 4104 .err_handler = &qla2xxx_err_handler,
4053}; 4105};
4054 4106