From patchwork Fri May 13 12:44:02 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: sjur.brandeland@stericsson.com X-Patchwork-Id: 95474 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 C5B39B6F08 for ; Fri, 13 May 2011 23:16:27 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932849Ab1EMNQW (ORCPT ); Fri, 13 May 2011 09:16:22 -0400 Received: from sf1.isp.kq.no ([213.172.193.37]:29698 "EHLO slow1.isp.as2116.net" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1758843Ab1EMNQW (ORCPT ); Fri, 13 May 2011 09:16:22 -0400 Received: from pmx.vmail.no (pmx.vmail.no [193.75.16.11]) by slow1.isp.as2116.net (Postfix) with ESMTP id 7553B80165 for ; Fri, 13 May 2011 14:45:33 +0200 (CEST) Received: from pmx.vmail.no (localhost [127.0.0.1]) by localhost (pmx10.isp.as2116.net) with SMTP id 1A0A8227F4; Fri, 13 May 2011 14:40:58 +0200 (CEST) Received: from smtp.bluecom.no (smtp.bluecom.no [193.75.75.28]) by pmx.vmail.no (pmx10.isp.as2116.net) with ESMTP id 09C3E1FB46; Fri, 13 May 2011 14:40:58 +0200 (CEST) Received: from localhost.localdomain (unknown [212.4.57.94]) by smtp.bluecom.no (Postfix) with ESMTP id 5B560C5; Fri, 13 May 2011 14:44:10 +0200 (CEST) From: =?UTF-8?q?Sjur=20Br=C3=A6ndeland?= To: "David S. Miller" , netdev@vger.kernel.org Cc: =?UTF-8?q?Sjur=20Br=C3=A6ndeland?= Subject: [net-next-2.6 04/10] caif: Add ref-count to framing layer Date: Fri, 13 May 2011 14:44:02 +0200 Message-Id: <1305290648-9613-5-git-send-email-sjur.brandeland@stericsson.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1305290648-9613-1-git-send-email-sjur.brandeland@stericsson.com> References: <1305290648-9613-1-git-send-email-sjur.brandeland@stericsson.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Introduce Per-cpu reference for lower part of CAIF Stack. Before freeing payload is disabled, synchronize_rcu() is called, and then ref-count verified to be zero. Signed-off-by: Sjur Brændeland --- include/net/caif/cffrml.h | 5 ++++- net/caif/cfcnfg.c | 9 ++++++++- net/caif/cffrml.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/include/net/caif/cffrml.h b/include/net/caif/cffrml.h index 4f126d7..afac1a4 100644 --- a/include/net/caif/cffrml.h +++ b/include/net/caif/cffrml.h @@ -7,12 +7,15 @@ #ifndef CFFRML_H_ #define CFFRML_H_ #include +#include struct cffrml; -struct cflayer *cffrml_create(u16 phyid, bool DoFCS); +struct cflayer *cffrml_create(u16 phyid, bool use_fcs); +void cffrml_free(struct cflayer *layr); void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up); void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn); void cffrml_put(struct cflayer *layr); void cffrml_hold(struct cflayer *layr); +int cffrml_refcnt_read(struct cflayer *layr); #endif /* CFFRML_H_ */ diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 7892cc0..3f4f31f 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -519,6 +519,13 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) caif_assert(phy_layer->id == phyid); caif_assert(phyinfo->frm_layer->id == phyid); + /* Fail if reference count is not zero */ + if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) { + pr_info("Wait for device inuse\n"); + mutex_unlock(&cnfg->lock); + return -EAGAIN; + } + list_del_rcu(&phyinfo->node); synchronize_rcu(); @@ -537,7 +544,7 @@ int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) if (phyinfo->phy_layer != frml_dn) kfree(frml_dn); - kfree(frml); + cffrml_free(frml); kfree(phyinfo); mutex_unlock(&cnfg->lock); diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c index f4b8892..4f4f756 100644 --- a/net/caif/cffrml.c +++ b/net/caif/cffrml.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ struct cffrml { struct cflayer layer; bool dofcs; /* !< FCS active */ + int __percpu *pcpu_refcnt; }; static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); @@ -31,12 +33,19 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, static u32 cffrml_rcv_error; static u32 cffrml_rcv_checsum_error; struct cflayer *cffrml_create(u16 phyid, bool use_fcs) + { struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC); if (!this) { pr_warn("Out of memory\n"); return NULL; } + this->pcpu_refcnt = alloc_percpu(int); + if (this->pcpu_refcnt == NULL) { + kfree(this); + return NULL; + } + caif_assert(offsetof(struct cffrml, layer) == 0); memset(this, 0, sizeof(struct cflayer)); @@ -49,6 +58,13 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs) return (struct cflayer *) this; } +void cffrml_free(struct cflayer *layer) +{ + struct cffrml *this = container_obj(layer); + free_percpu(this->pcpu_refcnt); + kfree(layer); +} + void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) { this->up = up; @@ -148,8 +164,23 @@ static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, void cffrml_put(struct cflayer *layr) { + struct cffrml *this = container_obj(layr); + if (layr != NULL && this->pcpu_refcnt != NULL) + irqsafe_cpu_dec(*this->pcpu_refcnt); } void cffrml_hold(struct cflayer *layr) { + struct cffrml *this = container_obj(layr); + if (layr != NULL && this->pcpu_refcnt != NULL) + irqsafe_cpu_inc(*this->pcpu_refcnt); +} + +int cffrml_refcnt_read(struct cflayer *layr) +{ + int i, refcnt = 0; + struct cffrml *this = container_obj(layr); + for_each_possible_cpu(i) + refcnt += *per_cpu_ptr(this->pcpu_refcnt, i); + return refcnt; }