lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [day] [month] [year] [list]
Date:	Wed, 10 Dec 2008 12:32:20 +0100
From:	"Miguel Ángel Álvarez" <gotzoncabanes@...il.com>
To:	linux-arm-kernel@...ts.arm.linux.org.uk,
	linux-kernel@...r.kernel.org, "Krzysztof Halasa" <khc@...waw.pl>,
	"Karl Hiramoto" <karl@...amoto.org>
Subject: [PATCH] ixp4xx_qmgr: support 64 queues

Hi

I have read Karl Hiramoto's patch for supporting 64 queues in
ixp4xx_qmgr, and the comments from Krzysztof Halasa.

I am not sure of some of the features implemented by Karl, but I think
that the work in supporting 64 queues is quite valuable.

I have remade the patch so that this "minimal" functionallity can be
analysed. Here it is.


diff -urN linux-2.6.26.7_hssorig/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
linux-2.6.26.7/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
--- linux-2.6.26.7_hssorig/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c	2008-10-22
23:46:18.000000000 +0200
+++ linux-2.6.26.7/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c	2008-12-10
11:26:28.000000000 +0100
@@ -26,13 +26,21 @@
 void qmgr_set_irq(unsigned int queue, int src,
 		  void (*handler)(void *pdev), void *pdev)
 {
-	u32 __iomem *reg = &qmgr_regs->irqsrc[queue / 8]; /* 8 queues / u32 */
-	int bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
+	u32 __iomem *reg;
+	int bit;
 	unsigned long flags;

-	src &= 7;
+	BUG_ON(queue >= HALF_QUEUES && src != QUEUE_IRQ_SRC_NOT_EMPTY);
+
 	spin_lock_irqsave(&qmgr_lock, flags);
-	__raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), reg);
+
+	if (queue < HALF_QUEUES) {
+		src &= 7;
+		reg = &qmgr_regs->irqsrc[queue / 8];
+		bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */	
+		__raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), reg);
+	}
+
 	irq_handlers[queue] = handler;
 	irq_pdevs[queue] = pdev;
 	spin_unlock_irqrestore(&qmgr_lock, flags);
@@ -53,13 +61,31 @@
 }


+static irqreturn_t qmgr_irq2(int irq, void *pdev)
+{
+	int i;
+	u32 val = __raw_readl(&qmgr_regs->irqstat[1]);
+	__raw_writel(val, &qmgr_regs->irqstat[1]); /* ACK */
+
+	for (i = HALF_QUEUES; i < QUEUES; i++)
+		if (val & (1 << i))
+			irq_handlers[i](irq_pdevs[i]);
+
+	return val ? IRQ_HANDLED : 0;
+}
+
+
 void qmgr_enable_irq(unsigned int queue)
 {
 	unsigned long flags;

 	spin_lock_irqsave(&qmgr_lock, flags);
-	__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | (1 << queue),
-		     &qmgr_regs->irqen[0]);
+	if (queue < HALF_QUEUES)
+		__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | (1 << queue),
+			     &qmgr_regs->irqen[0]);
+	else
+		__raw_writel(__raw_readl(&qmgr_regs->irqen[1]) |
+				(1 << (queue - HALF_QUEUES)), &qmgr_regs->irqen[1]);
 	spin_unlock_irqrestore(&qmgr_lock, flags);
 }

@@ -68,8 +94,12 @@
 	unsigned long flags;

 	spin_lock_irqsave(&qmgr_lock, flags);
-	__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~(1 << queue),
-		     &qmgr_regs->irqen[0]);
+	if (queue < HALF_QUEUES)
+		__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~(1 << queue),
+			     &qmgr_regs->irqen[0]);
+	else
+		__raw_writel(__raw_readl(&qmgr_regs->irqen[1]) &
+				~(1 << (queue - HALF_QUEUES)), &qmgr_regs->irqen[1]);
 	spin_unlock_irqrestore(&qmgr_lock, flags);
 }

@@ -88,7 +118,7 @@
 	u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
 	int err;

-	if (queue >= HALF_QUEUES)
+	if (queue >= QUEUES)
 		return -ERANGE;

 	if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
@@ -169,7 +199,7 @@
 {
 	u32 cfg, addr, mask[4];

-	BUG_ON(queue >= HALF_QUEUES); /* not in valid range */
+	BUG_ON(queue >= QUEUES); /* not in valid range */

 	spin_lock_irq(&qmgr_lock);
 	cfg = __raw_readl(&qmgr_regs->sram[queue]);
@@ -234,20 +264,32 @@
 		__raw_writel(0, &qmgr_regs->sram[i]);

 	err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq1, 0,
-			  "IXP4xx Queue Manager", NULL);
+			  "IXP4xx Queue Manager QM1", NULL);
 	if (err) {
 		printk(KERN_ERR "qmgr: failed to request IRQ%i\n",
 		       IRQ_IXP4XX_QM1);
-		goto error_irq;
+		goto error_irq1;
+	}
+
+	err = request_irq(IRQ_IXP4XX_QM2, qmgr_irq2, 0,
+			  "IXP4xx Queue Manager QM2", NULL);
+	if (err) {
+		printk(KERN_ERR "qmgr: failed to request IRQ%i\n",
+		       IRQ_IXP4XX_QM2);
+		goto error_irq2;
 	}

+
 	used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
 	spin_lock_init(&qmgr_lock);

 	printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
 	return 0;

-error_irq:
+error_irq2:
+	free_irq(IRQ_IXP4XX_QM1, NULL);
+	synchronize_irq(IRQ_IXP4XX_QM2);
+error_irq1:
 	iounmap(qmgr_regs);
 error_map:
 	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
@@ -257,7 +299,9 @@
 static void qmgr_remove(void)
 {
 	free_irq(IRQ_IXP4XX_QM1, NULL);
+	free_irq(IRQ_IXP4XX_QM2, NULL);
 	synchronize_irq(IRQ_IXP4XX_QM1);
+	synchronize_irq(IRQ_IXP4XX_QM2);
 	iounmap(qmgr_regs);
 	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
 }
diff -urN linux-2.6.26.7_hssorig/include/asm-arm/arch-ixp4xx/qmgr.h
linux-2.6.26.7/include/asm-arm/arch-ixp4xx/qmgr.h
--- linux-2.6.26.7_hssorig/include/asm-arm/arch-ixp4xx/qmgr.h	2008-10-22
23:46:18.000000000 +0200
+++ linux-2.6.26.7/include/asm-arm/arch-ixp4xx/qmgr.h	2008-12-10
11:31:00.000000000 +0100
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2007 Krzysztof Halasa <khc@...waw.pl>
+ * Portions Copyright (C) 2008 Karl Hiramoto <karl@...amoto.org>
+ * Portions Copyright (C) 2008 Miguel Angel Alvarez <gotzoncabanes@...il.com>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -82,6 +84,7 @@
 static inline int qmgr_get_stat1(unsigned int queue)
 {
 	extern struct qmgr_regs __iomem *qmgr_regs;
+	BUG_ON(queue >= HALF_QUEUES);
 	return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
 		>> ((queue & 7) << 2)) & 0xF;
 }
@@ -89,37 +92,52 @@
 static inline int qmgr_get_stat2(unsigned int queue)
 {
 	extern struct qmgr_regs __iomem *qmgr_regs;
+	BUG_ON(queue >= HALF_QUEUES);
 	return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
 		>> ((queue & 0xF) << 1)) & 0x3;
 }

 static inline int qmgr_stat_empty(unsigned int queue)
 {
+	BUG_ON(queue >= HALF_QUEUES);
 	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY);
 }

 static inline int qmgr_stat_nearly_empty(unsigned int queue)
 {
-	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY);
+	extern struct qmgr_regs __iomem *qmgr_regs;
+	if (queue < HALF_QUEUES)
+		return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY);
+	else
+		return !!((__raw_readl(&qmgr_regs->statne_h)
+			>> (queue - HALF_QUEUES)) & 0x1);
 }

 static inline int qmgr_stat_nearly_full(unsigned int queue)
 {
+	BUG_ON(queue >= HALF_QUEUES);
 	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL);
 }

 static inline int qmgr_stat_full(unsigned int queue)
 {
-	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_FULL);
+	extern struct qmgr_regs __iomem *qmgr_regs;
+	if (queue < HALF_QUEUES)
+		return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_FULL);
+	else
+		return !!((__raw_readl(&qmgr_regs->statf_h)
+			>> (queue - HALF_QUEUES)) & 0x1);
 }

 static inline int qmgr_stat_underflow(unsigned int queue)
 {
+	BUG_ON(queue >= HALF_QUEUES);
 	return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW);
 }

 static inline int qmgr_stat_overflow(unsigned int queue)
 {
+	BUG_ON(queue >= HALF_QUEUES);
 	return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW);
 }


I think it could be quite useful to add it to the mainstream.

Thanks

Miguel Ángel Álvarez
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ