From patchwork Mon Dec 13 00:46:02 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Richter X-Patchwork-Id: 75275 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id D5841B6EE8 for ; Mon, 13 Dec 2010 11:47:21 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932090Ab0LMArA (ORCPT ); Sun, 12 Dec 2010 19:47:00 -0500 Received: from einhorn.in-berlin.de ([192.109.42.8]:58932 "EHLO einhorn.in-berlin.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753586Ab0LMAq7 (ORCPT ); Sun, 12 Dec 2010 19:46:59 -0500 X-Envelope-From: stefanr@s5r6.in-berlin.de Received: from stein ([83.221.231.7]) (authenticated bits=0) by einhorn.in-berlin.de (8.13.6/8.13.6/Debian-1) with ESMTP id oBD0k3SR030919 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT); Mon, 13 Dec 2010 01:46:04 +0100 Date: Mon, 13 Dec 2010 01:46:02 +0100 From: Stefan Richter To: Ben Hutchings , Maxim Levitsky Cc: Peter Stuge , linux1394-devel@lists.sourceforge.net, netdev@vger.kernel.org Subject: [PATCH update 2] firewire: net: add carrier detection Message-ID: <20101213014602.6bc2727b@stein> In-Reply-To: <1292195134.3136.296.camel@localhost> References: <1290996593-32416-1-git-send-email-maximlevitsky@gmail.com> <1291779177.32420.8.camel@maxim-laptop> <20101208040559.20639.qmail@stuge.se> <1291809485.5421.0.camel@maxim-laptop> <20101212180916.71a57a71@stein> <1292195134.3136.296.camel@localhost> X-Mailer: Claws Mail 3.7.6 (GTK+ 2.20.1; x86_64-pc-linux-gnu) Mime-Version: 1.0 X-Scanned-By: MIMEDefang_at_IN-Berlin_e.V. on 192.109.42.8 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Maxim Levitsky To make userland, e.g. NetworkManager work with firewire, we need to detect whether cable is plugged or not. Simple and correct way of doing that is just counting number of peers. No peers - no link and vice versa. (Stefan R.: Drop ethtool_ops.get_link) Signed-off-by: Stefan Richter --- Update 2: Removed ethtool related hunks; dev->peer_count does not need to be accessed within the spinlock as I first thought; reduced pointer reference depth in fwnet_remove_peer. Maxim, do you observe a remaining need for a get_link implementation? I can't tell, I use rather minimal userland that doesn't care for link status. drivers/firewire/net.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) Index: b/drivers/firewire/net.c =================================================================== --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -179,6 +179,7 @@ struct fwnet_device { /* Number of tx datagrams that have been queued but not yet acked */ int queued_datagrams; + int peer_count; struct list_head peer_list; struct fw_card *card; struct net_device *netdev; @@ -1465,6 +1466,10 @@ static int fwnet_add_peer(struct fwnet_d list_add_tail(&peer->peer_link, &dev->peer_list); spin_unlock_irq(&dev->lock); + /* dev->peer_count acess is serialized by fwnet_device_mutex. */ + if (++dev->peer_count > 1) + netif_carrier_on(dev->netdev); + return 0; } @@ -1543,13 +1548,16 @@ static int fwnet_probe(struct device *_d return ret; } -static void fwnet_remove_peer(struct fwnet_peer *peer) +static void fwnet_remove_peer(struct fwnet_peer *peer, struct fwnet_device *dev) { struct fwnet_partial_datagram *pd, *pd_next; - spin_lock_irq(&peer->dev->lock); + if (--dev->peer_count == 1) + netif_carrier_off(dev->netdev); + + spin_lock_irq(&dev->lock); list_del(&peer->peer_link); - spin_unlock_irq(&peer->dev->lock); + spin_unlock_irq(&dev->lock); list_for_each_entry_safe(pd, pd_next, &peer->pd_list, pd_link) fwnet_pd_delete(pd); @@ -1566,7 +1574,7 @@ static int fwnet_remove(struct device *_ mutex_lock(&fwnet_device_mutex); - fwnet_remove_peer(peer); + fwnet_remove_peer(peer, dev); if (list_empty(&dev->peer_list)) { net = dev->netdev;