Patchwork [4/6,NET-NEXT] qlge: Cleanup chip reset path.

login
register
mail settings
Submitter Ron Mercer
Date Oct. 11, 2008, 5:17 p.m.
Message ID <1223745433-26440-4-git-send-email-ron.mercer@qlogic.com>
Download mbox | patch
Permalink /patch/4016/
State Deferred
Delegated to: David Miller
Headers show

Comments

Ron Mercer - Oct. 11, 2008, 5:17 p.m.
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qlge/qlge_main.c |   41 +++++++++++++++++------------------------
 1 files changed, 17 insertions(+), 24 deletions(-)
fran├žois romieu - Oct. 11, 2008, 9:30 p.m.
Ron Mercer <ron.mercer@qlogic.com> :
[...]
> diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
> index c257546..1788e5c 100755
> --- a/drivers/net/qlge/qlge_main.c
> +++ b/drivers/net/qlge/qlge_main.c
[...]
> @@ -3471,14 +3449,29 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p)
>  static void qlge_tx_timeout(struct net_device *ndev)
>  {
>  	struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
> -	queue_delayed_work(qdev->workqueue, &qdev->asic_reset_work, 0);
> +	ql_queue_asic_error(qdev);
>  }
>  
>  static void ql_asic_reset_work(struct work_struct *work)
>  {
>  	struct ql_adapter *qdev =
>  	    container_of(work, struct ql_adapter, asic_reset_work.work);
> -	ql_cycle_adapter(qdev);
> +	int status;
> +
> +	status = ql_adapter_down(qdev);
> +	if (status)
> +		goto error;
> +
> +	status = ql_adapter_up(qdev);
> +	if (status)
> +		goto error;
> +	return;
> +error:
> +	QPRINTK(qdev, IFUP, ALERT,
> +		"Driver up/down cycle failed, closing device\n");
> +	rtnl_lock();
> +	dev_close(qdev->ndev);
> +	rtnl_unlock();

ql_asic_reset_work
-> dev_close
   -> qlge_close
      -> ql_adapter_down
         -> cancel_delayed_work_sync(&qdev->asic_reset_work);
            -> __cancel_work_timer
               -> wait_on_work
                  -> wait_on_cpu_work
                     -> wait_for_completion

Imho it will wait forever.
Ron Mercer - Oct. 14, 2008, 8:31 p.m.
On Sat, Oct 11, 2008 at 11:30:00PM +0200, Francois Romieu wrote:
> Ron Mercer <ron.mercer@qlogic.com> :
> [...]
> > diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
> > index c257546..1788e5c 100755
> > --- a/drivers/net/qlge/qlge_main.c
> > +++ b/drivers/net/qlge/qlge_main.c
> [...]
> > @@ -3471,14 +3449,29 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p)
> >  static void qlge_tx_timeout(struct net_device *ndev)
> >  {
> >  	struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
> > -	queue_delayed_work(qdev->workqueue, &qdev->asic_reset_work, 0);
> > +	ql_queue_asic_error(qdev);
> >  }
> >  
> >  static void ql_asic_reset_work(struct work_struct *work)
> >  {
> >  	struct ql_adapter *qdev =
> >  	    container_of(work, struct ql_adapter, asic_reset_work.work);
> > -	ql_cycle_adapter(qdev);
> > +	int status;
> > +
> > +	status = ql_adapter_down(qdev);
> > +	if (status)
> > +		goto error;
> > +
> > +	status = ql_adapter_up(qdev);
> > +	if (status)
> > +		goto error;
> > +	return;
> > +error:
> > +	QPRINTK(qdev, IFUP, ALERT,
> > +		"Driver up/down cycle failed, closing device\n");
> > +	rtnl_lock();
> > +	dev_close(qdev->ndev);
> > +	rtnl_unlock();
> 
> ql_asic_reset_work
> -> dev_close
>    -> qlge_close
>       -> ql_adapter_down
>          -> cancel_delayed_work_sync(&qdev->asic_reset_work);
>             -> __cancel_work_timer
>                -> wait_on_work
>                   -> wait_on_cpu_work
>                      -> wait_for_completion
> 
> Imho it will wait forever.

Francois,
Thanks for your input.  I think you are correct and believe I've fixed this though I need to
test the scenario you've pointed out.
Cheers,
Ron


> 
> -- 
> Ueimor
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index c257546..1788e5c 100755
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -3141,28 +3141,6 @@  err_init:
 	return err;
 }
 
-static int ql_cycle_adapter(struct ql_adapter *qdev)
-{
-	int status;
-
-	status = ql_adapter_down(qdev);
-	if (status)
-		goto error;
-
-	status = ql_adapter_up(qdev);
-	if (status)
-		goto error;
-
-	return status;
-error:
-	QPRINTK(qdev, IFUP, ALERT,
-		"Driver up/down cycle failed, closing device\n");
-	rtnl_lock();
-	dev_close(qdev->ndev);
-	rtnl_unlock();
-	return status;
-}
-
 static void ql_release_adapter_resources(struct ql_adapter *qdev)
 {
 	ql_free_mem_resources(qdev);
@@ -3471,14 +3449,29 @@  static int qlge_set_mac_address(struct net_device *ndev, void *p)
 static void qlge_tx_timeout(struct net_device *ndev)
 {
 	struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
-	queue_delayed_work(qdev->workqueue, &qdev->asic_reset_work, 0);
+	ql_queue_asic_error(qdev);
 }
 
 static void ql_asic_reset_work(struct work_struct *work)
 {
 	struct ql_adapter *qdev =
 	    container_of(work, struct ql_adapter, asic_reset_work.work);
-	ql_cycle_adapter(qdev);
+	int status;
+
+	status = ql_adapter_down(qdev);
+	if (status)
+		goto error;
+
+	status = ql_adapter_up(qdev);
+	if (status)
+		goto error;
+	return;
+error:
+	QPRINTK(qdev, IFUP, ALERT,
+		"Driver up/down cycle failed, closing device\n");
+	rtnl_lock();
+	dev_close(qdev->ndev);
+	rtnl_unlock();
 }
 
 static void ql_get_board_info(struct ql_adapter *qdev)