From patchwork Mon May 21 06:12:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Lei" X-Patchwork-Id: 10414003 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3F5B36016C for ; Mon, 21 May 2018 06:13:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 188AA2874C for ; Mon, 21 May 2018 06:13:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0CA5428789; Mon, 21 May 2018 06:13:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4B4202874C for ; Mon, 21 May 2018 06:13:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:In-Reply-To:References: Message-ID:Date:Subject:To:From:Reply-To:Cc:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=fKri/F62aO04xg5ug8sVjtZI19f8aOm5/B7BprvJqrM=; b=GzkNVYLFVC2gpv moWIhcE2ymI3DFTOAQlEgu98Yze6Cce3BTNPDSIT9PT7An1ks4Fqflvz5yZ6HQ40JdwwVeVc542WG z1sfazU3vuM8PkM+Yd92HVsLq2GOdj/ewLIlYijao8juRphugq+KLUS47d7uS+DvpDWzMx5yCftdw nQ+gv5gQ6G4rkFPSL2fYBZyba8ZuoWTk+FbnIICXQPRb/GQtBA5UPUSFnK1GuUVaecRbuH2gCROF9 BNYyV38t3V1vcorqmiuzwWL19k+M9qufhxYuzZzGY6pIE0blM+byQRtpYJPIkaSN2kojGWQfDCE2E zh0hfe4cg1vDVn7Tvm7g==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fKe4C-0005YL-3V; Mon, 21 May 2018 06:13:08 +0000 Received: from mgwym01.jp.fujitsu.com ([211.128.242.40]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1fKe47-0005X2-Mb for linux-arm-kernel@lists.infradead.org; Mon, 21 May 2018 06:13:06 +0000 Received: from yt-mxauth.gw.nic.fujitsu.com (unknown [192.168.229.68]) by mgwym01.jp.fujitsu.com with smtp id 1d80_5f79_91ccbd07_a680_44cd_ba1a_d8b81d962a7e; Mon, 21 May 2018 15:12:40 +0900 Received: from g01jpfmpwkw01.exch.g01.fujitsu.local (g01jpfmpwkw01.exch.g01.fujitsu.local [10.0.193.38]) by yt-mxauth.gw.nic.fujitsu.com (Postfix) with ESMTP id 71568AC02D1 for ; Mon, 21 May 2018 15:12:39 +0900 (JST) Received: from G01JPEXCHKW14.g01.fujitsu.local (G01JPEXCHKW14.g01.fujitsu.local [10.0.194.53]) by g01jpfmpwkw01.exch.g01.fujitsu.local (Postfix) with ESMTP id 05F5D692570; Mon, 21 May 2018 15:12:38 +0900 (JST) Received: from G01JPEXMBKW03.g01.fujitsu.local ([10.0.194.67]) by g01jpexchkw14 ([10.0.194.53]) with mapi id 14.03.0352.000; Mon, 21 May 2018 15:12:37 +0900 From: "Zhang, Lei" To: 'Marc Zyngier' , "linux-arm-kernel@lists.infradead.org" Subject: RE: [PATCH]irqchip/irq-gic-v3:Avoid a waste of LPI resource Thread-Topic: [PATCH]irqchip/irq-gic-v3:Avoid a waste of LPI resource Thread-Index: AdPeKgYnL3BjJXkkQmOU1arale4+n///eLoA//sdehCAF8P7gP/+Yg+ggAMqkQD//Rx74P/wk9yw/9xZ93A= Date: Mon, 21 May 2018 06:12:37 +0000 Message-ID: <8898674D84E3B24BA3A2D289B872026A69F0FB69@G01JPEXMBKW03> References: <8898674D84E3B24BA3A2D289B872026A69EECF90@G01JPEXMBKW03> <8898674D84E3B24BA3A2D289B872026A69EF9AF9@G01JPEXMBKW03> <78df845d-0788-3cbd-e435-5a3a8221fdc8@redhat.com> <8898674D84E3B24BA3A2D289B872026A69F09954@G01JPEXMBKW03> <907eb976-7a26-2800-bf1a-563aca482235@arm.com> <8898674D84E3B24BA3A2D289B872026A69F0ACA3@G01JPEXMBKW03> <8898674D84E3B24BA3A2D289B872026A69F0E26D@G01JPEXMBKW03> In-Reply-To: <8898674D84E3B24BA3A2D289B872026A69F0E26D@G01JPEXMBKW03> Accept-Language: ja-JP, en-US Content-Language: ja-JP X-MS-Has-Attach: X-MS-TNEF-Correlator: x-securitypolicycheck: OK by SHieldMailChecker v2.2.3 x-shieldmailcheckerpolicyversion: FJ-ISEC-20140219 x-originating-ip: [10.18.70.198] MIME-Version: 1.0 X-SecurityPolicyCheck-GC: OK by FENCE-Mail X-TM-AS-MML: disable X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180520_231304_150588_483CAC4A X-CRM114-Status: GOOD ( 17.38 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP My patch was based old kernel version, So I wrote a new patch based linux-4.17-rc6. > -----Original Message----- > From: linux-arm-kernel > [mailto:linux-arm-kernel-bounces@lists.infradead.org] On Behalf Of Zhang, > Lei > Sent: Friday, May 18, 2018 6:49 PM > To: 'Marc Zyngier'; linux-arm-kernel@lists.infradead.org > Subject: RE: [PATCH]irqchip/irq-gic-v3:Avoid a waste of LPI resource > > I rewrote the mechanism of lpis's management by using free list. > > Below is my patch for core ITS driver. > Would you give me comments? -------------------------------- -------------------------------- Best Regards, Lei Zhang --- Lei Zhang e-mail: zhang.lei@jp.fujitsu.com FUJITSU LIMITED diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 5416f2b..a42df4a 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -1405,82 +1405,122 @@ static int its_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info) .irq_set_vcpu_affinity = its_irq_set_vcpu_affinity, }; -/* - * How we allocate LPIs: - * - * The GIC has id_bits bits for interrupt identifiers. From there, we - * must subtract 8192 which are reserved for SGIs/PPIs/SPIs. Then, as - * we allocate LPIs by chunks of 32, we can shift the whole thing by 5 - * bits to the right. - * - * This gives us (((1UL << id_bits) - 8192) >> 5) possible allocations. - */ -#define IRQS_PER_CHUNK_SHIFT 5 -#define IRQS_PER_CHUNK (1UL << IRQS_PER_CHUNK_SHIFT) -#define ITS_MAX_LPI_NRBITS 16 /* 64K LPIs */ +static struct list_head lpi_free_list; +static struct list_head lpi_alloc_list; +struct lpi_mng { + struct list_head lpi_list; + int base; + int len; +}; -static unsigned long *lpi_bitmap; -static u32 lpi_chunks; +#define ITS_MAX_LPI_NRBITS 16 /* 64K LPIs */ static DEFINE_SPINLOCK(lpi_lock); -static int its_lpi_to_chunk(int lpi) -{ - return (lpi - 8192) >> IRQS_PER_CHUNK_SHIFT; -} - -static int its_chunk_to_lpi(int chunk) -{ - return (chunk << IRQS_PER_CHUNK_SHIFT) + 8192; -} static int __init its_lpi_init(u32 id_bits) { - lpi_chunks = its_lpi_to_chunk(1UL << id_bits); + u32 nr_irq = 1UL << id_bits; + struct lpi_mng *lpi_free_mng = NULL; + struct lpi_mng *lpi_new = NULL; + + INIT_LIST_HEAD(&lpi_free_list); + INIT_LIST_HEAD(&lpi_alloc_list); - lpi_bitmap = kzalloc(BITS_TO_LONGS(lpi_chunks) * sizeof(long), - GFP_KERNEL); - if (!lpi_bitmap) { - lpi_chunks = 0; + lpi_free_mng = kzalloc(sizeof(struct lpi_mng), GFP_KERNEL); + if (!lpi_free_mng) return -ENOMEM; - } - pr_info("ITS: Allocated %d chunks for LPIs\n", (int)lpi_chunks); + lpi_free_mng->base = 0; + lpi_free_mng->len = nr_irq; + list_add(&lpi_free_mng->lpi_list, &lpi_free_list); + + do { + lpi_free_mng = list_first_entry(&lpi_free_list, struct lpi_mng, + lpi_list); + if (lpi_free_mng->len == 8192) { + /*It is not lpi, so we delete */ + if (lpi_free_mng->base == 0) { + list_del_init(&lpi_free_mng->lpi_list); + kfree(lpi_free_mng); + continue; + } + if (lpi_free_mng->base == 8192) + goto out; + } + if (lpi_free_mng->len > 8192) { + lpi_new = kzalloc(sizeof(struct lpi_mng), + GFP_ATOMIC); + if (!lpi_new) + return -ENOMEM; + lpi_free_mng->len /= 2; + lpi_new->base = lpi_free_mng->base + lpi_free_mng->len; + lpi_new->len = lpi_free_mng->len; + list_add(&lpi_new->lpi_list, &lpi_free_mng->lpi_list); + } + } while (1); + +out: + pr_info("ITS: Allocated %d LPIs\n", nr_irq - 8192); return 0; } +static struct lpi_mng *its_alloc_lpi(int nr_irqs) +{ + struct lpi_mng *lpi_alloc_mng = NULL; + struct lpi_mng *lpi_split = NULL; + struct lpi_mng *lpi_new = NULL; + int base; + + base = 0x7fffffff; + do { + list_for_each_entry(lpi_alloc_mng, &lpi_free_list, lpi_list) { + if (nr_irqs > lpi_alloc_mng->len) + continue; + if (nr_irqs == lpi_alloc_mng->len) { + list_del_init(&lpi_alloc_mng->lpi_list); + list_add(&lpi_alloc_mng->lpi_list, + &lpi_alloc_list); + return lpi_alloc_mng; + } + if ((nr_irqs < lpi_alloc_mng->len) + && (lpi_alloc_mng->base < base)) { + base = lpi_alloc_mng->base; + lpi_split = lpi_alloc_mng; + } + } + lpi_new = kzalloc(sizeof(struct lpi_mng), + GFP_ATOMIC); + if (!lpi_new || !lpi_split) + return NULL; + + lpi_split->len /= 2; + lpi_new->base = lpi_split->base + lpi_split->len; + lpi_new->len = lpi_split->len; + list_add(&lpi_new->lpi_list, &lpi_split->lpi_list); + + } while (1); +} + static unsigned long *its_lpi_alloc_chunks(int nr_irqs, int *base, int *nr_ids) { unsigned long *bitmap = NULL; - int chunk_id; - int nr_chunks; - int i; - - nr_chunks = DIV_ROUND_UP(nr_irqs, IRQS_PER_CHUNK); + struct lpi_mng *lpi_alloc_mng = NULL; spin_lock(&lpi_lock); - do { - chunk_id = bitmap_find_next_zero_area(lpi_bitmap, lpi_chunks, - 0, nr_chunks, 0); - if (chunk_id < lpi_chunks) - break; - - nr_chunks--; - } while (nr_chunks > 0); + lpi_alloc_mng = its_alloc_lpi(nr_irqs); - if (!nr_chunks) + if (!lpi_alloc_mng) goto out; - bitmap = kzalloc(BITS_TO_LONGS(nr_chunks * IRQS_PER_CHUNK) * sizeof (long), + bitmap = kzalloc(BITS_TO_LONGS(nr_irqs) * sizeof(long), GFP_ATOMIC); if (!bitmap) goto out; - for (i = 0; i < nr_chunks; i++) - set_bit(chunk_id + i, lpi_bitmap); - *base = its_chunk_to_lpi(chunk_id); - *nr_ids = nr_chunks * IRQS_PER_CHUNK; + *base = lpi_alloc_mng->base; + *nr_ids = lpi_alloc_mng->len; out: spin_unlock(&lpi_lock); @@ -1491,23 +1531,53 @@ static unsigned long *its_lpi_alloc_chunks(int nr_irqs, int *base, int *nr_ids) return bitmap; } +static void its_joint_free_list(struct lpi_mng *free, struct lpi_mng *alloc) +{ + free->len = free->len * 2; + if (free->base > alloc->base) + free->base = alloc->base; +} + static void its_lpi_free_chunks(unsigned long *bitmap, int base, int nr_ids) { - int lpi; + struct lpi_mng *lpi_alloc_mng = NULL; + struct lpi_mng *lpi_free_mng = NULL; + bool first_half; + int pair_base; spin_lock(&lpi_lock); - for (lpi = base; lpi < (base + nr_ids); lpi += IRQS_PER_CHUNK) { - int chunk = its_lpi_to_chunk(lpi); - - BUG_ON(chunk > lpi_chunks); - if (test_bit(chunk, lpi_bitmap)) { - clear_bit(chunk, lpi_bitmap); - } else { - pr_err("Bad LPI chunk %d\n", chunk); + list_for_each_entry(lpi_alloc_mng, &lpi_alloc_list, lpi_list) { + if (lpi_alloc_mng->base == base) { + list_del_init(&lpi_alloc_mng->lpi_list); + break; } } + first_half = (lpi_alloc_mng->base % (lpi_alloc_mng->len * 2)) + ? false : true; + if (first_half) + pair_base = lpi_alloc_mng->base + lpi_alloc_mng->len; + else + pair_base = lpi_alloc_mng->base - lpi_alloc_mng->len; + + // found the other half + list_for_each_entry(lpi_free_mng, &lpi_free_list, lpi_list) { + if (lpi_free_mng->base == pair_base) { + its_joint_free_list(lpi_free_mng, lpi_alloc_mng); + kfree(lpi_alloc_mng); + goto out; + } + } + // Not found the other half + list_for_each_entry(lpi_free_mng, &lpi_free_list, lpi_list) { + if (lpi_alloc_mng->base < lpi_free_mng->base) { + list_add_tail(&lpi_alloc_mng->lpi_list, + &lpi_free_mng->lpi_list); + break; + } + } +out: spin_unlock(&lpi_lock); kfree(bitmap); @@ -2117,7 +2187,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, * We allocate at least one chunk worth of LPIs bet device, * and thus that many ITEs. The device may require less though. */ - nr_ites = max(IRQS_PER_CHUNK, roundup_pow_of_two(nvecs)); + nr_ites = max(2UL, roundup_pow_of_two(nvecs)); sz = nr_ites * its->ite_size; sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; itt = kzalloc(sz, GFP_KERNEL);