aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorChad Dupuis <chad.dupuis@qlogic.com>2012-05-15 14:34:14 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-05-22 06:25:50 -0400
commit9a347ff404d786d044ed09a4ec9a38ca70e8c803 (patch)
tree699ff5a897129337de90f7439948b7b54f441195 /drivers/scsi/qla2xxx
parent01b6585d8af737a82b45ca22a938f2a930659775 (diff)
[SCSI] qla2xxx: Handle interrupt registration failures more gracefully.
If interrupt registration failed we could crash the machine as we were trying to deference some pointers which weren't allocated yet. Move the allocation a little earlier and make some checks to the free resource code to make sure that we don't try to free a resource that was never allocated. Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c44
2 files changed, 40 insertions, 14 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index ce42288049b5..f4b8a5f7840a 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -2564,7 +2564,15 @@ void
2564qla2x00_free_irqs(scsi_qla_host_t *vha) 2564qla2x00_free_irqs(scsi_qla_host_t *vha)
2565{ 2565{
2566 struct qla_hw_data *ha = vha->hw; 2566 struct qla_hw_data *ha = vha->hw;
2567 struct rsp_que *rsp = ha->rsp_q_map[0]; 2567 struct rsp_que *rsp;
2568
2569 /*
2570 * We need to check that ha->rsp_q_map is valid in case we are called
2571 * from a probe failure context.
2572 */
2573 if (!ha->rsp_q_map || !ha->rsp_q_map[0])
2574 return;
2575 rsp = ha->rsp_q_map[0];
2568 2576
2569 if (ha->flags.msix_enabled) 2577 if (ha->flags.msix_enabled)
2570 qla24xx_disable_msix(ha); 2578 qla24xx_disable_msix(ha);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7db803377c64..2e6dd88fbf50 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -306,7 +306,8 @@ static void qla2x00_free_fw_dump(struct qla_hw_data *);
306static void qla2x00_mem_free(struct qla_hw_data *); 306static void qla2x00_mem_free(struct qla_hw_data *);
307 307
308/* -------------------------------------------------------------------------- */ 308/* -------------------------------------------------------------------------- */
309static int qla2x00_alloc_queues(struct qla_hw_data *ha) 309static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
310 struct rsp_que *rsp)
310{ 311{
311 scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); 312 scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
312 ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues, 313 ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
@@ -324,6 +325,12 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha)
324 "Unable to allocate memory for response queue ptrs.\n"); 325 "Unable to allocate memory for response queue ptrs.\n");
325 goto fail_rsp_map; 326 goto fail_rsp_map;
326 } 327 }
328 /*
329 * Make sure we record at least the request and response queue zero in
330 * case we need to free them if part of the probe fails.
331 */
332 ha->rsp_q_map[0] = rsp;
333 ha->req_q_map[0] = req;
327 set_bit(0, ha->rsp_qid_map); 334 set_bit(0, ha->rsp_qid_map);
328 set_bit(0, ha->req_qid_map); 335 set_bit(0, ha->req_qid_map);
329 return 1; 336 return 1;
@@ -2417,6 +2424,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2417 host->max_cmd_len, host->max_channel, host->max_lun, 2424 host->max_cmd_len, host->max_channel, host->max_lun,
2418 host->transportt, sht->vendor_id); 2425 host->transportt, sht->vendor_id);
2419 2426
2427que_init:
2428 /* Alloc arrays of request and response ring ptrs */
2429 if (!qla2x00_alloc_queues(ha, req, rsp)) {
2430 ql_log(ql_log_fatal, base_vha, 0x003d,
2431 "Failed to allocate memory for queue pointers..."
2432 "aborting.\n");
2433 goto probe_init_failed;
2434 }
2435
2436
2420 /* Set up the irqs */ 2437 /* Set up the irqs */
2421 ret = qla2x00_request_irqs(ha, rsp); 2438 ret = qla2x00_request_irqs(ha, rsp);
2422 if (ret) 2439 if (ret)
@@ -2424,20 +2441,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2424 2441
2425 pci_save_state(pdev); 2442 pci_save_state(pdev);
2426 2443
2427 /* Alloc arrays of request and response ring ptrs */ 2444 /* Assign back pointers */
2428que_init:
2429 if (!qla2x00_alloc_queues(ha)) {
2430 ql_log(ql_log_fatal, base_vha, 0x003d,
2431 "Failed to allocate memory for queue pointers.. aborting.\n");
2432 goto probe_init_failed;
2433 }
2434
2435 ha->rsp_q_map[0] = rsp;
2436 ha->req_q_map[0] = req;
2437 rsp->req = req; 2445 rsp->req = req;
2438 req->rsp = rsp; 2446 req->rsp = rsp;
2439 set_bit(0, ha->req_qid_map); 2447
2440 set_bit(0, ha->rsp_qid_map);
2441 /* FWI2-capable only. */ 2448 /* FWI2-capable only. */
2442 req->req_q_in = &ha->iobase->isp24.req_q_in; 2449 req->req_q_in = &ha->iobase->isp24.req_q_in;
2443 req->req_q_out = &ha->iobase->isp24.req_q_out; 2450 req->req_q_out = &ha->iobase->isp24.req_q_out;
@@ -2581,7 +2588,11 @@ skip_dpc:
2581 2588
2582probe_init_failed: 2589probe_init_failed:
2583 qla2x00_free_req_que(ha, req); 2590 qla2x00_free_req_que(ha, req);
2591 ha->req_q_map[0] = NULL;
2592 clear_bit(0, ha->req_qid_map);
2584 qla2x00_free_rsp_que(ha, rsp); 2593 qla2x00_free_rsp_que(ha, rsp);
2594 ha->rsp_q_map[0] = NULL;
2595 clear_bit(0, ha->rsp_qid_map);
2585 ha->max_req_queues = ha->max_rsp_queues = 0; 2596 ha->max_req_queues = ha->max_rsp_queues = 0;
2586 2597
2587probe_failed: 2598probe_failed:
@@ -2663,6 +2674,13 @@ qla2x00_remove_one(struct pci_dev *pdev)
2663 struct qla_hw_data *ha; 2674 struct qla_hw_data *ha;
2664 unsigned long flags; 2675 unsigned long flags;
2665 2676
2677 /*
2678 * If the PCI device is disabled that means that probe failed and any
2679 * resources should be have cleaned up on probe exit.
2680 */
2681 if (!atomic_read(&pdev->enable_cnt))
2682 return;
2683
2666 base_vha = pci_get_drvdata(pdev); 2684 base_vha = pci_get_drvdata(pdev);
2667 ha = base_vha->hw; 2685 ha = base_vha->hw;
2668 2686