From c65ceeb86e91d6d94cf15d4cb9884845c2ce8a04 Mon Sep 17 00:00:00 2001 From: Andy Giles Date: Tue, 12 Aug 2014 17:06:33 -0700 Subject: [PATCH] 5081 mpt_sas watchdog timout needs to be initialized earlier 5080 potential memory leak in mpt_sas Reviewed by: Hans Rosenfeld Reviewed by: Garrett D'Amore Reviewed by: Dan McDonald Approved by: Robert Mustacchi --- .../uts/common/io/scsi/adapters/mpt_sas/mptsas.c | 77 ++++++++++++++-------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c index d92678971c..1d12a65bd9 100644 --- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c +++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c @@ -1037,6 +1037,7 @@ mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) char event_taskq_create = 0; char dr_taskq_create = 0; char doneq_thread_create = 0; + char added_watchdog = 0; scsi_hba_tran_t *hba_tran; uint_t mem_bar = MEM_SPACE; int rval = DDI_FAILURE; @@ -1398,7 +1399,28 @@ mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) mutex_exit(&mpt->m_mutex); /* - * Initialize PHY info for smhba + * used for mptsas_watch + */ + mptsas_list_add(mpt); + + mutex_enter(&mptsas_global_mutex); + if (mptsas_timeouts_enabled == 0) { + mptsas_scsi_watchdog_tick = ddi_prop_get_int(DDI_DEV_T_ANY, + dip, 0, "scsi-watchdog-tick", DEFAULT_WD_TICK); + + mptsas_tick = mptsas_scsi_watchdog_tick * + drv_usectohz((clock_t)1000000); + + mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick); + mptsas_timeouts_enabled = 1; + } + mutex_exit(&mptsas_global_mutex); + added_watchdog++; + + /* + * Initialize PHY info for smhba. + * This requires watchdog to be enabled otherwise if interrupts + * don't work the system will hang. */ if (mptsas_smhba_setup(mpt)) { mptsas_log(mpt, CE_WARN, "mptsas phy initialization " @@ -1440,23 +1462,6 @@ mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) /* * After this point, we are not going to fail the attach. */ - /* - * used for mptsas_watch - */ - mptsas_list_add(mpt); - - mutex_enter(&mptsas_global_mutex); - if (mptsas_timeouts_enabled == 0) { - mptsas_scsi_watchdog_tick = ddi_prop_get_int(DDI_DEV_T_ANY, - dip, 0, "scsi-watchdog-tick", DEFAULT_WD_TICK); - - mptsas_tick = mptsas_scsi_watchdog_tick * - drv_usectohz((clock_t)1000000); - - mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick); - mptsas_timeouts_enabled = 1; - } - mutex_exit(&mptsas_global_mutex); /* Print message of HBA present */ ddi_report_dev(dip); @@ -1473,18 +1478,22 @@ fail: mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE); ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST); if (mpt) { - mutex_enter(&mptsas_global_mutex); + /* deallocate in reverse order */ + if (added_watchdog) { + mptsas_list_del(mpt); + mutex_enter(&mptsas_global_mutex); - if (mptsas_timeout_id && (mptsas_head == NULL)) { - timeout_id_t tid = mptsas_timeout_id; - mptsas_timeouts_enabled = 0; - mptsas_timeout_id = 0; + if (mptsas_timeout_id && (mptsas_head == NULL)) { + timeout_id_t tid = mptsas_timeout_id; + mptsas_timeouts_enabled = 0; + mptsas_timeout_id = 0; + mutex_exit(&mptsas_global_mutex); + (void) untimeout(tid); + mutex_enter(&mptsas_global_mutex); + } mutex_exit(&mptsas_global_mutex); - (void) untimeout(tid); - mutex_enter(&mptsas_global_mutex); } - mutex_exit(&mptsas_global_mutex); - /* deallocate in reverse order */ + mptsas_cache_destroy(mpt); if (smp_attach_setup) { @@ -5491,6 +5500,8 @@ mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply, mptsas_handle_dr, (void *)topo_node, DDI_NOSLEEP)) != DDI_SUCCESS) { + kmem_free(topo_node, + sizeof (mptsas_topo_change_list_t)); mptsas_log(mpt, CE_NOTE, "mptsas start taskq" "for handle SAS dynamic reconfigure" "failed. \n"); @@ -7229,6 +7240,12 @@ mptsas_handle_event_sync(void *args) if ((ddi_taskq_dispatch(mpt->m_dr_taskq, mptsas_handle_dr, (void *)topo_head, DDI_NOSLEEP)) != DDI_SUCCESS) { + while (topo_head != NULL) { + topo_node = topo_head; + topo_head = topo_head->next; + kmem_free(topo_node, + sizeof (mptsas_topo_change_list_t)); + } mptsas_log(mpt, CE_NOTE, "mptsas start taskq " "for handle SAS DR event failed. \n"); } @@ -7407,6 +7424,12 @@ mptsas_handle_event_sync(void *args) if ((ddi_taskq_dispatch(mpt->m_dr_taskq, mptsas_handle_dr, (void *)topo_head, DDI_NOSLEEP)) != DDI_SUCCESS) { + while (topo_head != NULL) { + topo_node = topo_head; + topo_head = topo_head->next; + kmem_free(topo_node, + sizeof (mptsas_topo_change_list_t)); + } mptsas_log(mpt, CE_NOTE, "mptsas start taskq " "for handle SAS DR event failed. \n"); } -- 2.11.4.GIT