aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ixp4xx
diff options
context:
space:
mode:
authorKrzysztof Hałasa <khc@pm.waw.pl>2009-02-19 19:01:33 -0500
committerKrzysztof Hałasa <khc@pm.waw.pl>2009-05-20 09:27:07 -0400
commita6a9fb857b5599b3cefef5576967389c1c43eb4c (patch)
tree3a6d3d8e9d7560c1c496fc6c38698687196fab55 /arch/arm/mach-ixp4xx
parent1406de8e11eb043681297adf86d6892ff8efc27a (diff)
IXP4xx: Add support for the second half of the 64 hardware queues.
Signed-off-by: Krzysztof Hałasa <khc@pm.waw.pl>
Diffstat (limited to 'arch/arm/mach-ixp4xx')
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/qmgr.h65
-rw-r--r--arch/arm/mach-ixp4xx/ixp4xx_qmgr.c71
2 files changed, 105 insertions, 31 deletions
diff --git a/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
index 0cbe6ceb67c5..32077e11f17a 100644
--- a/arch/arm/mach-ixp4xx/include/mach/qmgr.h
+++ b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
@@ -15,7 +15,7 @@
15#define DEBUG_QMGR 0 15#define DEBUG_QMGR 0
16 16
17#define HALF_QUEUES 32 17#define HALF_QUEUES 32
18#define QUEUES 64 /* only 32 lower queues currently supported */ 18#define QUEUES 64
19#define MAX_QUEUE_LENGTH 4 /* in dwords */ 19#define MAX_QUEUE_LENGTH 4 /* in dwords */
20 20
21#define QUEUE_STAT1_EMPTY 1 /* queue status bits */ 21#define QUEUE_STAT1_EMPTY 1 /* queue status bits */
@@ -110,48 +110,95 @@ static inline u32 qmgr_get_entry(unsigned int queue)
110 return val; 110 return val;
111} 111}
112 112
113static inline int qmgr_get_stat1(unsigned int queue) 113static inline int __qmgr_get_stat1(unsigned int queue)
114{ 114{
115 extern struct qmgr_regs __iomem *qmgr_regs; 115 extern struct qmgr_regs __iomem *qmgr_regs;
116 return (__raw_readl(&qmgr_regs->stat1[queue >> 3]) 116 return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
117 >> ((queue & 7) << 2)) & 0xF; 117 >> ((queue & 7) << 2)) & 0xF;
118} 118}
119 119
120static inline int qmgr_get_stat2(unsigned int queue) 120static inline int __qmgr_get_stat2(unsigned int queue)
121{ 121{
122 extern struct qmgr_regs __iomem *qmgr_regs; 122 extern struct qmgr_regs __iomem *qmgr_regs;
123 BUG_ON(queue >= HALF_QUEUES);
123 return (__raw_readl(&qmgr_regs->stat2[queue >> 4]) 124 return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
124 >> ((queue & 0xF) << 1)) & 0x3; 125 >> ((queue & 0xF) << 1)) & 0x3;
125} 126}
126 127
128/**
129 * qmgr_stat_empty() - checks if a hardware queue is empty
130 * @queue: queue number
131 *
132 * Returns non-zero value if the queue is empty.
133 */
127static inline int qmgr_stat_empty(unsigned int queue) 134static inline int qmgr_stat_empty(unsigned int queue)
128{ 135{
129 return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY); 136 BUG_ON(queue >= HALF_QUEUES);
137 return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY;
130} 138}
131 139
140/**
141 * qmgr_stat_empty() - checks if a hardware queue is nearly empty
142 * @queue: queue number
143 *
144 * Returns non-zero value if the queue is nearly or completely empty.
145 */
132static inline int qmgr_stat_nearly_empty(unsigned int queue) 146static inline int qmgr_stat_nearly_empty(unsigned int queue)
133{ 147{
134 return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY); 148 extern struct qmgr_regs __iomem *qmgr_regs;
149 if (queue >= HALF_QUEUES)
150 return (__raw_readl(&qmgr_regs->statne_h) >>
151 (queue - HALF_QUEUES)) & 0x01;
152 return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY;
135} 153}
136 154
155/**
156 * qmgr_stat_empty() - checks if a hardware queue is nearly full
157 * @queue: queue number
158 *
159 * Returns non-zero value if the queue is nearly or completely full.
160 */
137static inline int qmgr_stat_nearly_full(unsigned int queue) 161static inline int qmgr_stat_nearly_full(unsigned int queue)
138{ 162{
139 return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL); 163 BUG_ON(queue >= HALF_QUEUES);
164 return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL;
140} 165}
141 166
167/**
168 * qmgr_stat_empty() - checks if a hardware queue is full
169 * @queue: queue number
170 *
171 * Returns non-zero value if the queue is full.
172 */
142static inline int qmgr_stat_full(unsigned int queue) 173static inline int qmgr_stat_full(unsigned int queue)
143{ 174{
144 return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_FULL); 175 extern struct qmgr_regs __iomem *qmgr_regs;
176 if (queue >= HALF_QUEUES)
177 return (__raw_readl(&qmgr_regs->statf_h) >>
178 (queue - HALF_QUEUES)) & 0x01;
179 return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL;
145} 180}
146 181
182/**
183 * qmgr_stat_empty() - checks if a hardware queue experienced underflow
184 * @queue: queue number
185 *
186 * Returns non-zero value if empty.
187 */
147static inline int qmgr_stat_underflow(unsigned int queue) 188static inline int qmgr_stat_underflow(unsigned int queue)
148{ 189{
149 return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW); 190 return __qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW;
150} 191}
151 192
193/**
194 * qmgr_stat_empty() - checks if a hardware queue experienced overflow
195 * @queue: queue number
196 *
197 * Returns non-zero value if empty.
198 */
152static inline int qmgr_stat_overflow(unsigned int queue) 199static inline int qmgr_stat_overflow(unsigned int queue)
153{ 200{
154 return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW); 201 return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW;
155} 202}
156 203
157#endif 204#endif
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
index bfddc73d0a20..7531bfdb7b4e 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
@@ -18,8 +18,8 @@ struct qmgr_regs __iomem *qmgr_regs;
18static struct resource *mem_res; 18static struct resource *mem_res;
19static spinlock_t qmgr_lock; 19static spinlock_t qmgr_lock;
20static u32 used_sram_bitmap[4]; /* 128 16-dword pages */ 20static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
21static void (*irq_handlers[HALF_QUEUES])(void *pdev); 21static void (*irq_handlers[QUEUES])(void *pdev);
22static void *irq_pdevs[HALF_QUEUES]; 22static void *irq_pdevs[QUEUES];
23 23
24#if DEBUG_QMGR 24#if DEBUG_QMGR
25char qmgr_queue_descs[QUEUES][32]; 25char qmgr_queue_descs[QUEUES][32];
@@ -28,29 +28,38 @@ char qmgr_queue_descs[QUEUES][32];
28void qmgr_set_irq(unsigned int queue, int src, 28void qmgr_set_irq(unsigned int queue, int src,
29 void (*handler)(void *pdev), void *pdev) 29 void (*handler)(void *pdev), void *pdev)
30{ 30{
31 u32 __iomem *reg = &qmgr_regs->irqsrc[queue / 8]; /* 8 queues / u32 */
32 int bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
33 unsigned long flags; 31 unsigned long flags;
34 32
35 src &= 7;
36 spin_lock_irqsave(&qmgr_lock, flags); 33 spin_lock_irqsave(&qmgr_lock, flags);
37 __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), reg); 34 if (queue < HALF_QUEUES) {
35 u32 __iomem *reg;
36 int bit;
37 BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL);
38 reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */
39 bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
40 __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit),
41 reg);
42 } else
43 /* IRQ source for queues 32-63 is fixed */
44 BUG_ON(src != QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY);
45
38 irq_handlers[queue] = handler; 46 irq_handlers[queue] = handler;
39 irq_pdevs[queue] = pdev; 47 irq_pdevs[queue] = pdev;
40 spin_unlock_irqrestore(&qmgr_lock, flags); 48 spin_unlock_irqrestore(&qmgr_lock, flags);
41} 49}
42 50
43 51
44static irqreturn_t qmgr_irq1(int irq, void *pdev) 52static irqreturn_t qmgr_irq(int irq, void *pdev)
45{ 53{
46 int i; 54 int i, half = (irq == IRQ_IXP4XX_QM1 ? 0 : 1);
47 u32 val = __raw_readl(&qmgr_regs->irqstat[0]); 55 u32 val = __raw_readl(&qmgr_regs->irqstat[half]);
48 __raw_writel(val, &qmgr_regs->irqstat[0]); /* ACK */ 56 __raw_writel(val, &qmgr_regs->irqstat[half]); /* ACK */
49 57
50 for (i = 0; i < HALF_QUEUES; i++) 58 for (i = 0; i < HALF_QUEUES; i++)
51 if (val & (1 << i)) 59 if (val & (1 << i)) {
52 irq_handlers[i](irq_pdevs[i]); 60 int irq = half * HALF_QUEUES + i;
53 61 irq_handlers[irq](irq_pdevs[irq]);
62 }
54 return val ? IRQ_HANDLED : 0; 63 return val ? IRQ_HANDLED : 0;
55} 64}
56 65
@@ -58,21 +67,25 @@ static irqreturn_t qmgr_irq1(int irq, void *pdev)
58void qmgr_enable_irq(unsigned int queue) 67void qmgr_enable_irq(unsigned int queue)
59{ 68{
60 unsigned long flags; 69 unsigned long flags;
70 int half = queue / 32;
71 u32 mask = 1 << (queue & (HALF_QUEUES - 1));
61 72
62 spin_lock_irqsave(&qmgr_lock, flags); 73 spin_lock_irqsave(&qmgr_lock, flags);
63 __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | (1 << queue), 74 __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask,
64 &qmgr_regs->irqen[0]); 75 &qmgr_regs->irqen[half]);
65 spin_unlock_irqrestore(&qmgr_lock, flags); 76 spin_unlock_irqrestore(&qmgr_lock, flags);
66} 77}
67 78
68void qmgr_disable_irq(unsigned int queue) 79void qmgr_disable_irq(unsigned int queue)
69{ 80{
70 unsigned long flags; 81 unsigned long flags;
82 int half = queue / 32;
83 u32 mask = 1 << (queue & (HALF_QUEUES - 1));
71 84
72 spin_lock_irqsave(&qmgr_lock, flags); 85 spin_lock_irqsave(&qmgr_lock, flags);
73 __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~(1 << queue), 86 __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask,
74 &qmgr_regs->irqen[0]); 87 &qmgr_regs->irqen[half]);
75 __raw_writel(1 << queue, &qmgr_regs->irqstat[0]); /* clear */ 88 __raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */
76 spin_unlock_irqrestore(&qmgr_lock, flags); 89 spin_unlock_irqrestore(&qmgr_lock, flags);
77} 90}
78 91
@@ -98,8 +111,7 @@ int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
98 u32 cfg, addr = 0, mask[4]; /* in 16-dwords */ 111 u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
99 int err; 112 int err;
100 113
101 if (queue >= HALF_QUEUES) 114 BUG_ON(queue >= QUEUES);
102 return -ERANGE;
103 115
104 if ((nearly_empty_watermark | nearly_full_watermark) & ~7) 116 if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
105 return -EINVAL; 117 return -EINVAL;
@@ -180,7 +192,7 @@ void qmgr_release_queue(unsigned int queue)
180{ 192{
181 u32 cfg, addr, mask[4]; 193 u32 cfg, addr, mask[4];
182 194
183 BUG_ON(queue >= HALF_QUEUES); /* not in valid range */ 195 BUG_ON(queue >= QUEUES); /* not in valid range */
184 196
185 spin_lock_irq(&qmgr_lock); 197 spin_lock_irq(&qmgr_lock);
186 cfg = __raw_readl(&qmgr_regs->sram[queue]); 198 cfg = __raw_readl(&qmgr_regs->sram[queue]);
@@ -247,10 +259,13 @@ static int qmgr_init(void)
247 __raw_writel(0, &qmgr_regs->irqen[i]); 259 __raw_writel(0, &qmgr_regs->irqen[i]);
248 } 260 }
249 261
262 __raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h);
263 __raw_writel(0, &qmgr_regs->statf_h);
264
250 for (i = 0; i < QUEUES; i++) 265 for (i = 0; i < QUEUES; i++)
251 __raw_writel(0, &qmgr_regs->sram[i]); 266 __raw_writel(0, &qmgr_regs->sram[i]);
252 267
253 err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq1, 0, 268 err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq, 0,
254 "IXP4xx Queue Manager", NULL); 269 "IXP4xx Queue Manager", NULL);
255 if (err) { 270 if (err) {
256 printk(KERN_ERR "qmgr: failed to request IRQ%i\n", 271 printk(KERN_ERR "qmgr: failed to request IRQ%i\n",
@@ -258,12 +273,22 @@ static int qmgr_init(void)
258 goto error_irq; 273 goto error_irq;
259 } 274 }
260 275
276 err = request_irq(IRQ_IXP4XX_QM2, qmgr_irq, 0,
277 "IXP4xx Queue Manager", NULL);
278 if (err) {
279 printk(KERN_ERR "qmgr: failed to request IRQ%i\n",
280 IRQ_IXP4XX_QM2);
281 goto error_irq2;
282 }
283
261 used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */ 284 used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
262 spin_lock_init(&qmgr_lock); 285 spin_lock_init(&qmgr_lock);
263 286
264 printk(KERN_INFO "IXP4xx Queue Manager initialized.\n"); 287 printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
265 return 0; 288 return 0;
266 289
290error_irq2:
291 free_irq(IRQ_IXP4XX_QM1, NULL);
267error_irq: 292error_irq:
268 iounmap(qmgr_regs); 293 iounmap(qmgr_regs);
269error_map: 294error_map:
@@ -274,7 +299,9 @@ error_map:
274static void qmgr_remove(void) 299static void qmgr_remove(void)
275{ 300{
276 free_irq(IRQ_IXP4XX_QM1, NULL); 301 free_irq(IRQ_IXP4XX_QM1, NULL);
302 free_irq(IRQ_IXP4XX_QM2, NULL);
277 synchronize_irq(IRQ_IXP4XX_QM1); 303 synchronize_irq(IRQ_IXP4XX_QM1);
304 synchronize_irq(IRQ_IXP4XX_QM2);
278 iounmap(qmgr_regs); 305 iounmap(qmgr_regs);
279 release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE); 306 release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
280} 307}