From patchwork Fri Jun 14 07:15:59 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Minghuan Lian X-Patchwork-Id: 251245 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id 3ED1D2C0317 for ; Fri, 14 Jun 2013 17:18:32 +1000 (EST) Received: from tx2outboundpool.messaging.microsoft.com (tx2ehsobe004.messaging.microsoft.com [65.55.88.14]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (Client CN "mail.global.frontbridge.com", Issuer "MSIT Machine Auth CA 2" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 639C72C02A1 for ; Fri, 14 Jun 2013 17:15:55 +1000 (EST) Received: from mail40-tx2-R.bigfish.com (10.9.14.226) by TX2EHSOBE001.bigfish.com (10.9.40.21) with Microsoft SMTP Server id 14.1.225.23; Fri, 14 Jun 2013 07:15:51 +0000 Received: from mail40-tx2 (localhost [127.0.0.1]) by mail40-tx2-R.bigfish.com (Postfix) with ESMTP id 8DDF8300581 for ; Fri, 14 Jun 2013 07:15:51 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 0 X-BigFish: VS0(zzzz1f42h1ee6h1de0h1fdah1202h1e76h1d1ah1d2ah1fc6hzz8275bhz2dh2a8h668h839he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1d0ch1d2eh1d3fh1dfeh1dffh1e23h1155h) Received: from mail40-tx2 (localhost.localdomain [127.0.0.1]) by mail40-tx2 (MessageSwitch) id 1371194149964586_28355; Fri, 14 Jun 2013 07:15:49 +0000 (UTC) Received: from TX2EHSMHS022.bigfish.com (unknown [10.9.14.248]) by mail40-tx2.bigfish.com (Postfix) with ESMTP id E00FD2C009C for ; Fri, 14 Jun 2013 07:15:49 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by TX2EHSMHS022.bigfish.com (10.9.99.122) with Microsoft SMTP Server (TLS) id 14.1.225.23; Fri, 14 Jun 2013 07:15:49 +0000 Received: from az84smr01.freescale.net (10.64.34.197) by 039-SN1MMR1-002.039d.mgd.msft.net (10.84.1.15) with Microsoft SMTP Server (TLS) id 14.2.328.11; Fri, 14 Jun 2013 07:15:49 +0000 Received: from lmh.ap.freescale.net (lmh.ap.freescale.net [10.193.20.35]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id r5E7FbJq018550; Fri, 14 Jun 2013 00:15:47 -0700 From: Minghuan Lian To: Subject: [PATCH 5/5] powerpc/fsl_msi: add 'msiregs' kernel parameter Date: Fri, 14 Jun 2013 15:15:59 +0800 Message-ID: <1371194159-17332-5-git-send-email-Minghuan.Lian@freescale.com> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1371194159-17332-1-git-send-email-Minghuan.Lian@freescale.com> References: <1371194159-17332-1-git-send-email-Minghuan.Lian@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com Cc: Scott Wood , Minghuan Lian , Zang Roy-R61911 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" 1. Only MSIIR1 can index 16 MSI registers, but when using MSIIR1 the IRQs of a register are not continuous. for example, the first register irq values are 0x0, 0x10, 0x20, 0x30 ... 0x1f0. So it is hard to use 'msi-available-ranges' property to indicate the available ranges and 'msi-available-ranges' property has been removed from dts node, so this patch removes the related code. 2. Add 'msiregs' kernel parameter instead of 'msi-available-ranges' functionality. 'msiregs' is used to indicate the available MSI registers ranges and uses a colon ':' to separate the multiple banks. The range representation format is 'start-end', 'start' and 'end' are integers describe the start and end register index, the available registers lies between start and end and not include end. For example, the available register x satisfying start <= x < end. Signed-off-by: Minghuan Lian --- arch/powerpc/sysdev/fsl_msi.c | 118 ++++++++++++++++++++++++++++-------------- arch/powerpc/sysdev/fsl_msi.h | 1 + 2 files changed, 80 insertions(+), 39 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 34510b7..db382ef9b 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -52,6 +52,60 @@ struct fsl_msi_cascade_data { int index; }; +struct msi_reg_range { + u32 start; + u32 end; +}; + +static struct msi_reg_range msiregs[NR_MSI_BANK] = { + {.start = 0, .end = NR_MSI_REG }, + {.start = 0, .end = NR_MSI_REG }, + {.start = 0, .end = NR_MSI_REG }, + {.start = 0, .end = NR_MSI_REG }, +}; + +/* + * Handle 'msiregs' parameter. + * msiregs is used to indicate the available MSI registers range and + * uses colon ':' to separate the multiple banks ranges. + * For each bank, the registers range format is 'start-end' + * start and end are integers, used to the indicate the start and end + * register index. The range is a set of real numbers that lies between + * start and end but not include end. For example, the set of all numbers + * x satisfying start <= x < end. + * if no range specified, driver will use the default range including all + * the registers. + * if you do no want to use this bank, you can set range as '0-0' + * For example msiregs=0-16:0-0::0-2 + */ +static int msi_regs_setup(char *s) +{ + int bank = 0; + char *p; + struct msi_reg_range *range; + + while ((p = strsep(&s, ":")) != NULL) { + int start = 0, end = NR_MSI_REG; + + if (bank >= NR_MSI_BANK) + break; + range = &msiregs[bank]; + + if ((*p != '\0') && (sscanf(p, "%d-%d", &start, &end) < 1)) + pr_err("msiregs correct format is: start-end\n"); + + /* Ok, gets the specified value */ + range->start = start; + range->end = end; + pr_info("MSI bank%d available regs range is %d-%d\n", + bank, range->start, range->end); + bank++; + } + return 1; +} + +__setup("msiregs=", msi_regs_setup); + static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) { return in_be32(base + (reg >> 2)); @@ -350,7 +404,7 @@ static int fsl_of_msi_remove(struct platform_device *ofdev) static struct lock_class_key fsl_msi_irq_class; static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, - int offset, int irq_index) + int irq_index) { struct fsl_msi_cascade_data *cascade_data = NULL; int virt_msir, i; @@ -369,7 +423,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, } irq_set_lockdep_class(virt_msir, &fsl_msi_irq_class); msi->msi_virqs[irq_index] = virt_msir; - cascade_data->index = offset; + cascade_data->index = irq_index; cascade_data->msi_data = msi; irq_set_handler_data(virt_msir, cascade_data); irq_set_chained_handler(virt_msir, fsl_msi_cascade); @@ -377,7 +431,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, /* Release the hwirqs corresponding to this MSI register */ for (i = 0; i < IRQS_PER_MSI_REG; i++) msi_bitmap_free_hwirqs(&msi->bitmap, - msi_hwirq(msi, offset, i), 1); + msi_hwirq(msi, irq_index, i), 1); return 0; } @@ -387,21 +441,29 @@ static int fsl_of_msi_probe(struct platform_device *dev) { const struct of_device_id *match; struct fsl_msi *msi; + static int bank; + struct msi_reg_range *range; struct resource res, msiir; - int err, i, j, irq_index, count; + int err, irq_index, count; int rc; - const u32 *p; const struct fsl_msi_feature *features; - int len; - u32 offset; - static const u32 all_avail[] = { 0, NR_MSI_IRQS }; match = of_match_device(fsl_of_msi_ids, &dev->dev); if (!match) return -EINVAL; features = match->data; - printk(KERN_DEBUG "Setting up Freescale MSI support\n"); + if (bank >= NR_MSI_BANK) + return -EINVAL; + range = &msiregs[bank]; + pr_debug("Setting up Freescale MSI bank%d support\n", bank); + + count = of_irq_count(dev->dev.of_node); + if (!count) + return -ENODEV; + + if (count > NR_MSI_REG) + count = NR_MSI_REG; msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); if (!msi) { @@ -475,39 +537,17 @@ static int fsl_of_msi_probe(struct platform_device *dev) goto error_out; } - p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len); - if (p && len % (2 * sizeof(u32)) != 0) { - dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n", - __func__); - err = -EINVAL; - goto error_out; - } - - if (!p) { - p = all_avail; - len = sizeof(all_avail); - } - - for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) { - if (p[i * 2] % IRQS_PER_MSI_REG || - p[i * 2 + 1] % IRQS_PER_MSI_REG) { - printk(KERN_WARNING "%s: %s: msi available range of %u at %u is not IRQ-aligned\n", - __func__, dev->dev.of_node->full_name, - p[i * 2 + 1], p[i * 2]); - err = -EINVAL; + for (irq_index = 0; irq_index < count; irq_index++) { + /* Check whether the register is contained in range */ + if (irq_index < range->start || + irq_index >= range->end) + continue; + err = fsl_msi_setup_hwirq(msi, dev, irq_index); + if (err) goto error_out; - } - - offset = p[i * 2] / IRQS_PER_MSI_REG; - count = p[i * 2 + 1] / IRQS_PER_MSI_REG; - - for (j = 0; j < count; j++, irq_index++) { - err = fsl_msi_setup_hwirq(msi, dev, offset + j, irq_index); - if (err) - goto error_out; - } } + bank++; list_add_tail(&msi->list, &msi_head); /* The multiple setting ppc_md.setup_msi_irqs will not harm things */ diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index 43a9d99..6048415 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h @@ -16,6 +16,7 @@ #include #include +#define NR_MSI_BANK 4 #define NR_MSI_REG 16 #define IRQS_PER_MSI_REG 32 #define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG)