aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-23 01:34:29 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-23 01:34:29 -0400
commitb7c2a75725dee9b5643a0aae3a4cb47f52e00a49 (patch)
tree9078edae88d93db2228f20d12e334a46a37a07e7 /arch
parent4a0a088970a553e9f89d23eec688932f689d57f9 (diff)
sparc64: Fix lockdep issues in LDC protocol layer.
We're calling request_irq() with a IRQs disabled. No straightforward fix exists because we want to enable these IRQs and setup state atomically before getting into the IRQ handler the first time. What happens now is that we mark the VIRQ to not be automatically enabled by request_irq(). Then we make explicit enable_irq() calls when we grab the LDC channel. This way we don't need to call request_irq() illegally under the LDC channel lock any more. Bump LDC version and release date. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/irq.c10
-rw-r--r--arch/sparc64/kernel/ldc.c38
2 files changed, 28 insertions, 20 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index b441a26b73b0..c481673d249c 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -621,8 +621,9 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
621unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) 621unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
622{ 622{
623 struct irq_handler_data *data; 623 struct irq_handler_data *data;
624 struct ino_bucket *bucket;
625 unsigned long hv_err, cookie; 624 unsigned long hv_err, cookie;
625 struct ino_bucket *bucket;
626 struct irq_desc *desc;
626 unsigned int virt_irq; 627 unsigned int virt_irq;
627 628
628 bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); 629 bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
@@ -643,6 +644,13 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
643 if (unlikely(!data)) 644 if (unlikely(!data))
644 return 0; 645 return 0;
645 646
647 /* In order to make the LDC channel startup sequence easier,
648 * especially wrt. locking, we do not let request_irq() enable
649 * the interrupt.
650 */
651 desc = irq_desc + virt_irq;
652 desc->status |= IRQ_NOAUTOEN;
653
646 set_irq_chip_data(virt_irq, data); 654 set_irq_chip_data(virt_irq, data);
647 655
648 /* Catch accidental accesses to these things. IMAP/ICLR handling 656 /* Catch accidental accesses to these things. IMAP/ICLR handling
diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c
index 63969f610284..d68982330f66 100644
--- a/arch/sparc64/kernel/ldc.c
+++ b/arch/sparc64/kernel/ldc.c
@@ -1,6 +1,6 @@
1/* ldc.c: Logical Domain Channel link-layer protocol driver. 1/* ldc.c: Logical Domain Channel link-layer protocol driver.
2 * 2 *
3 * Copyright (C) 2007 David S. Miller <davem@davemloft.net> 3 * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
4 */ 4 */
5 5
6#include <linux/kernel.h> 6#include <linux/kernel.h>
@@ -23,8 +23,8 @@
23 23
24#define DRV_MODULE_NAME "ldc" 24#define DRV_MODULE_NAME "ldc"
25#define PFX DRV_MODULE_NAME ": " 25#define PFX DRV_MODULE_NAME ": "
26#define DRV_MODULE_VERSION "1.0" 26#define DRV_MODULE_VERSION "1.1"
27#define DRV_MODULE_RELDATE "June 25, 2007" 27#define DRV_MODULE_RELDATE "July 22, 2008"
28 28
29static char version[] __devinitdata = 29static char version[] __devinitdata =
30 DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; 30 DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -1235,13 +1235,9 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
1235 unsigned long hv_err, flags; 1235 unsigned long hv_err, flags;
1236 int err = -EINVAL; 1236 int err = -EINVAL;
1237 1237
1238 spin_lock_irqsave(&lp->lock, flags); 1238 if (!name ||
1239 1239 (lp->state != LDC_STATE_INIT))
1240 if (!name) 1240 return -EINVAL;
1241 goto out_err;
1242
1243 if (lp->state != LDC_STATE_INIT)
1244 goto out_err;
1245 1241
1246 snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name); 1242 snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
1247 snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name); 1243 snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
@@ -1250,25 +1246,32 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
1250 IRQF_SAMPLE_RANDOM | IRQF_SHARED, 1246 IRQF_SAMPLE_RANDOM | IRQF_SHARED,
1251 lp->rx_irq_name, lp); 1247 lp->rx_irq_name, lp);
1252 if (err) 1248 if (err)
1253 goto out_err; 1249 return err;
1254 1250
1255 err = request_irq(lp->cfg.tx_irq, ldc_tx, 1251 err = request_irq(lp->cfg.tx_irq, ldc_tx,
1256 IRQF_SAMPLE_RANDOM | IRQF_SHARED, 1252 IRQF_SAMPLE_RANDOM | IRQF_SHARED,
1257 lp->tx_irq_name, lp); 1253 lp->tx_irq_name, lp);
1258 if (err) 1254 if (err) {
1259 goto out_free_rx_irq; 1255 free_irq(lp->cfg.rx_irq, lp);
1256 return err;
1257 }
1258
1260 1259
1260 spin_lock_irqsave(&lp->lock, flags);
1261
1262 enable_irq(lp->cfg.rx_irq);
1263 enable_irq(lp->cfg.tx_irq);
1261 1264
1262 lp->flags |= LDC_FLAG_REGISTERED_IRQS; 1265 lp->flags |= LDC_FLAG_REGISTERED_IRQS;
1263 1266
1264 err = -ENODEV; 1267 err = -ENODEV;
1265 hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0); 1268 hv_err = sun4v_ldc_tx_qconf(lp->id, 0, 0);
1266 if (hv_err) 1269 if (hv_err)
1267 goto out_free_tx_irq; 1270 goto out_free_irqs;
1268 1271
1269 hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries); 1272 hv_err = sun4v_ldc_tx_qconf(lp->id, lp->tx_ra, lp->tx_num_entries);
1270 if (hv_err) 1273 if (hv_err)
1271 goto out_free_tx_irq; 1274 goto out_free_irqs;
1272 1275
1273 hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0); 1276 hv_err = sun4v_ldc_rx_qconf(lp->id, 0, 0);
1274 if (hv_err) 1277 if (hv_err)
@@ -1304,14 +1307,11 @@ out_unmap_rx:
1304out_unmap_tx: 1307out_unmap_tx:
1305 sun4v_ldc_tx_qconf(lp->id, 0, 0); 1308 sun4v_ldc_tx_qconf(lp->id, 0, 0);
1306 1309
1307out_free_tx_irq: 1310out_free_irqs:
1308 lp->flags &= ~LDC_FLAG_REGISTERED_IRQS; 1311 lp->flags &= ~LDC_FLAG_REGISTERED_IRQS;
1309 free_irq(lp->cfg.tx_irq, lp); 1312 free_irq(lp->cfg.tx_irq, lp);
1310
1311out_free_rx_irq:
1312 free_irq(lp->cfg.rx_irq, lp); 1313 free_irq(lp->cfg.rx_irq, lp);
1313 1314
1314out_err:
1315 spin_unlock_irqrestore(&lp->lock, flags); 1315 spin_unlock_irqrestore(&lp->lock, flags);
1316 1316
1317 return err; 1317 return err;