Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754187AbbLOQlI (ORCPT ); Tue, 15 Dec 2015 11:41:08 -0500 Received: from mga03.intel.com ([134.134.136.65]:64865 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751516AbbLOQlG (ORCPT ); Tue, 15 Dec 2015 11:41:06 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,433,1444719600"; d="scan'208";a="841718531" From: Ashutosh Dixit To: Greg Kroah-Hartman , linux-kernel@vger.kernel.org Cc: Arnd Bergmann , Ashutosh Dixit , Sudeep Dutt Subject: [PATCH RESEND] misc: mic: Fix crash when MIC reset is invoked in RESET_FAILED state Date: Tue, 15 Dec 2015 09:07:22 -0800 Message-Id: <6193fa943afcb78a07a196c36930eaf70192a444.1450198822.git.ashutosh.dixit@intel.com> X-Mailer: git-send-email 2.0.0.rc3.2.g998f840 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3245 Lines: 82 This patch fixes the following crash seen when MIC reset is invoked in RESET_FAILED state due to device_del being called a second time on an already deleted device: [] device_del+0x45/0x1d0 [] device_unregister+0x1e/0x60 [] scif_unregister_device+0x12/0x20 [scif_bus] [] cosm_stop+0xaa/0xe0 [mic_cosm] [] cosm_reset_trigger_work+0x14/0x20 [mic_cosm] The fix consists in realizing that because cosm_reset changes the state to MIC_RESETTING, cosm_stop needs the previous state, before it changed to MIC_RESETTING, to decide whether a hw_ops->stop had previously been issued. This is now provided in a new cosm_device member cdev->prev_state. Reviewed-by: Sudeep Dutt Signed-off-by: Ashutosh Dixit --- drivers/misc/mic/bus/cosm_bus.h | 2 ++ drivers/misc/mic/cosm/cosm_main.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/misc/mic/bus/cosm_bus.h b/drivers/misc/mic/bus/cosm_bus.h index f7c57f2..8b63418 100644 --- a/drivers/misc/mic/bus/cosm_bus.h +++ b/drivers/misc/mic/bus/cosm_bus.h @@ -30,6 +30,7 @@ * @attr_group: Pointer to list of sysfs attribute groups. * @sdev: Device for sysfs entries. * @state: MIC state. + * @prev_state: MIC state previous to MIC_RESETTING * @shutdown_status: MIC status reported by card for shutdown/crashes. * @shutdown_status_int: Internal shutdown status maintained by the driver * @cosm_mutex: Mutex for synchronizing access to data structures. @@ -55,6 +56,7 @@ struct cosm_device { const struct attribute_group **attr_group; struct device *sdev; u8 state; + u8 prev_state; u8 shutdown_status; u8 shutdown_status_int; struct mutex cosm_mutex; diff --git a/drivers/misc/mic/cosm/cosm_main.c b/drivers/misc/mic/cosm/cosm_main.c index 4b4b356..7005cb1 100644 --- a/drivers/misc/mic/cosm/cosm_main.c +++ b/drivers/misc/mic/cosm/cosm_main.c @@ -153,8 +153,10 @@ void cosm_stop(struct cosm_device *cdev, bool force) * stop(..) calls device_unregister and will crash the system if * called multiple times. */ - bool call_hw_ops = cdev->state != MIC_RESET_FAILED && - cdev->state != MIC_READY; + u8 state = cdev->state == MIC_RESETTING ? + cdev->prev_state : cdev->state; + bool call_hw_ops = state != MIC_RESET_FAILED && + state != MIC_READY; if (cdev->state != MIC_RESETTING) cosm_set_state(cdev, MIC_RESETTING); @@ -195,8 +197,11 @@ int cosm_reset(struct cosm_device *cdev) mutex_lock(&cdev->cosm_mutex); if (cdev->state != MIC_READY) { - cosm_set_state(cdev, MIC_RESETTING); - schedule_work(&cdev->reset_trigger_work); + if (cdev->state != MIC_RESETTING) { + cdev->prev_state = cdev->state; + cosm_set_state(cdev, MIC_RESETTING); + schedule_work(&cdev->reset_trigger_work); + } } else { dev_err(&cdev->dev, "%s %d MIC is READY\n", __func__, __LINE__); rc = -EINVAL; -- 2.0.0.rc3.2.g998f840 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/