aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIoan Nicu <ioan.nicu.ext@nokia.com>2017-10-03 19:15:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-10-03 20:54:24 -0400
commit31d1e130f4a0f8f629a460167569577cac9b17c1 (patch)
treeea592c410053b35919ddbd5b116480598e6d957b
parent57148a64e823bb1f49112fa52a92a7f372cda892 (diff)
rapidio: remove global irq spinlocks from the subsystem
Locking of config and doorbell operations should be done only if the underlying hardware requires it. This patch removes the global spinlocks from the rapidio subsystem and moves them to the mport drivers (fsl_rio and tsi721), only to the necessary places. For example, local config space read and write operations (lcread/lcwrite) are atomic in all existing drivers, so there should be no need for locking, while the cread/cwrite operations which generate maintenance transactions need to be synchronized with a lock. Later, each driver could chose to use a per-port lock instead of a global one, or even more granular locking. Link: http://lkml.kernel.org/r/20170824113023.GD50104@nokia.com Signed-off-by: Ioan Nicu <ioan.nicu.ext@nokia.com> Signed-off-by: Frank Kunz <frank.kunz@nokia.com> Acked-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Nicholas Piggin <npiggin@gmail.com> Cc: Randy Dunlap <rdunlap@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c17
-rw-r--r--arch/powerpc/sysdev/fsl_rmu.c8
-rw-r--r--drivers/rapidio/devices/tsi721.c7
-rw-r--r--drivers/rapidio/rio-access.c40
4 files changed, 35 insertions, 37 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 9234be1e66f5..5011ffea4e4b 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -71,6 +71,8 @@
71#define RIWAR_WRTYP_ALLOC 0x00006000 71#define RIWAR_WRTYP_ALLOC 0x00006000
72#define RIWAR_SIZE_MASK 0x0000003F 72#define RIWAR_SIZE_MASK 0x0000003F
73 73
74static DEFINE_SPINLOCK(fsl_rio_config_lock);
75
74#define __fsl_read_rio_config(x, addr, err, op) \ 76#define __fsl_read_rio_config(x, addr, err, op) \
75 __asm__ __volatile__( \ 77 __asm__ __volatile__( \
76 "1: "op" %1,0(%2)\n" \ 78 "1: "op" %1,0(%2)\n" \
@@ -184,6 +186,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
184 u8 hopcount, u32 offset, int len, u32 *val) 186 u8 hopcount, u32 offset, int len, u32 *val)
185{ 187{
186 struct rio_priv *priv = mport->priv; 188 struct rio_priv *priv = mport->priv;
189 unsigned long flags;
187 u8 *data; 190 u8 *data;
188 u32 rval, err = 0; 191 u32 rval, err = 0;
189 192
@@ -197,6 +200,8 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
197 if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len)) 200 if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
198 return -EINVAL; 201 return -EINVAL;
199 202
203 spin_lock_irqsave(&fsl_rio_config_lock, flags);
204
200 out_be32(&priv->maint_atmu_regs->rowtar, 205 out_be32(&priv->maint_atmu_regs->rowtar,
201 (destid << 22) | (hopcount << 12) | (offset >> 12)); 206 (destid << 22) | (hopcount << 12) | (offset >> 12));
202 out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10)); 207 out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
@@ -213,6 +218,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
213 __fsl_read_rio_config(rval, data, err, "lwz"); 218 __fsl_read_rio_config(rval, data, err, "lwz");
214 break; 219 break;
215 default: 220 default:
221 spin_unlock_irqrestore(&fsl_rio_config_lock, flags);
216 return -EINVAL; 222 return -EINVAL;
217 } 223 }
218 224
@@ -221,6 +227,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
221 err, destid, hopcount, offset); 227 err, destid, hopcount, offset);
222 } 228 }
223 229
230 spin_unlock_irqrestore(&fsl_rio_config_lock, flags);
224 *val = rval; 231 *val = rval;
225 232
226 return err; 233 return err;
@@ -244,7 +251,10 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
244 u8 hopcount, u32 offset, int len, u32 val) 251 u8 hopcount, u32 offset, int len, u32 val)
245{ 252{
246 struct rio_priv *priv = mport->priv; 253 struct rio_priv *priv = mport->priv;
254 unsigned long flags;
247 u8 *data; 255 u8 *data;
256 int ret = 0;
257
248 pr_debug 258 pr_debug
249 ("fsl_rio_config_write:" 259 ("fsl_rio_config_write:"
250 " index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", 260 " index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
@@ -255,6 +265,8 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
255 if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len)) 265 if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
256 return -EINVAL; 266 return -EINVAL;
257 267
268 spin_lock_irqsave(&fsl_rio_config_lock, flags);
269
258 out_be32(&priv->maint_atmu_regs->rowtar, 270 out_be32(&priv->maint_atmu_regs->rowtar,
259 (destid << 22) | (hopcount << 12) | (offset >> 12)); 271 (destid << 22) | (hopcount << 12) | (offset >> 12));
260 out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10)); 272 out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
@@ -271,10 +283,11 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
271 out_be32((u32 *) data, val); 283 out_be32((u32 *) data, val);
272 break; 284 break;
273 default: 285 default:
274 return -EINVAL; 286 ret = -EINVAL;
275 } 287 }
288 spin_unlock_irqrestore(&fsl_rio_config_lock, flags);
276 289
277 return 0; 290 return ret;
278} 291}
279 292
280static void fsl_rio_inbound_mem_init(struct rio_priv *priv) 293static void fsl_rio_inbound_mem_init(struct rio_priv *priv)
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c
index ab7a74c75be8..88b35a3dcdc5 100644
--- a/arch/powerpc/sysdev/fsl_rmu.c
+++ b/arch/powerpc/sysdev/fsl_rmu.c
@@ -104,6 +104,8 @@
104 104
105#define DOORBELL_MESSAGE_SIZE 0x08 105#define DOORBELL_MESSAGE_SIZE 0x08
106 106
107static DEFINE_SPINLOCK(fsl_rio_doorbell_lock);
108
107struct rio_msg_regs { 109struct rio_msg_regs {
108 u32 omr; 110 u32 omr;
109 u32 osr; 111 u32 osr;
@@ -626,9 +628,13 @@ err_out:
626int fsl_rio_doorbell_send(struct rio_mport *mport, 628int fsl_rio_doorbell_send(struct rio_mport *mport,
627 int index, u16 destid, u16 data) 629 int index, u16 destid, u16 data)
628{ 630{
631 unsigned long flags;
632
629 pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n", 633 pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n",
630 index, destid, data); 634 index, destid, data);
631 635
636 spin_lock_irqsave(&fsl_rio_doorbell_lock, flags);
637
632 /* In the serial version silicons, such as MPC8548, MPC8641, 638 /* In the serial version silicons, such as MPC8548, MPC8641,
633 * below operations is must be. 639 * below operations is must be.
634 */ 640 */
@@ -638,6 +644,8 @@ int fsl_rio_doorbell_send(struct rio_mport *mport,
638 out_be32(&dbell->dbell_regs->oddatr, (index << 20) | data); 644 out_be32(&dbell->dbell_regs->oddatr, (index << 20) | data);
639 out_be32(&dbell->dbell_regs->odmr, 0x00000001); 645 out_be32(&dbell->dbell_regs->odmr, 0x00000001);
640 646
647 spin_unlock_irqrestore(&fsl_rio_doorbell_lock, flags);
648
641 return 0; 649 return 0;
642} 650}
643 651
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index 315a4be8dc1e..9a68914100ad 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -51,6 +51,8 @@ module_param(mbox_sel, byte, S_IRUGO);
51MODULE_PARM_DESC(mbox_sel, 51MODULE_PARM_DESC(mbox_sel,
52 "RIO Messaging MBOX Selection Mask (default: 0x0f = all)"); 52 "RIO Messaging MBOX Selection Mask (default: 0x0f = all)");
53 53
54static DEFINE_SPINLOCK(tsi721_maint_lock);
55
54static void tsi721_omsg_handler(struct tsi721_device *priv, int ch); 56static void tsi721_omsg_handler(struct tsi721_device *priv, int ch);
55static void tsi721_imsg_handler(struct tsi721_device *priv, int ch); 57static void tsi721_imsg_handler(struct tsi721_device *priv, int ch);
56 58
@@ -124,12 +126,15 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size,
124 void __iomem *regs = priv->regs + TSI721_DMAC_BASE(priv->mdma.ch_id); 126 void __iomem *regs = priv->regs + TSI721_DMAC_BASE(priv->mdma.ch_id);
125 struct tsi721_dma_desc *bd_ptr; 127 struct tsi721_dma_desc *bd_ptr;
126 u32 rd_count, swr_ptr, ch_stat; 128 u32 rd_count, swr_ptr, ch_stat;
129 unsigned long flags;
127 int i, err = 0; 130 int i, err = 0;
128 u32 op = do_wr ? MAINT_WR : MAINT_RD; 131 u32 op = do_wr ? MAINT_WR : MAINT_RD;
129 132
130 if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32))) 133 if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32)))
131 return -EINVAL; 134 return -EINVAL;
132 135
136 spin_lock_irqsave(&tsi721_maint_lock, flags);
137
133 bd_ptr = priv->mdma.bd_base; 138 bd_ptr = priv->mdma.bd_base;
134 139
135 rd_count = ioread32(regs + TSI721_DMAC_DRDCNT); 140 rd_count = ioread32(regs + TSI721_DMAC_DRDCNT);
@@ -197,7 +202,9 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size,
197 */ 202 */
198 swr_ptr = ioread32(regs + TSI721_DMAC_DSWP); 203 swr_ptr = ioread32(regs + TSI721_DMAC_DSWP);
199 iowrite32(swr_ptr, regs + TSI721_DMAC_DSRP); 204 iowrite32(swr_ptr, regs + TSI721_DMAC_DSRP);
205
200err_out: 206err_out:
207 spin_unlock_irqrestore(&tsi721_maint_lock, flags);
201 208
202 return err; 209 return err;
203} 210}
diff --git a/drivers/rapidio/rio-access.c b/drivers/rapidio/rio-access.c
index a3824baca2e5..3ee9af83b638 100644
--- a/drivers/rapidio/rio-access.c
+++ b/drivers/rapidio/rio-access.c
@@ -14,16 +14,8 @@
14#include <linux/module.h> 14#include <linux/module.h>
15 15
16/* 16/*
17 * These interrupt-safe spinlocks protect all accesses to RIO
18 * configuration space and doorbell access.
19 */
20static DEFINE_SPINLOCK(rio_config_lock);
21static DEFINE_SPINLOCK(rio_doorbell_lock);
22
23/*
24 * Wrappers for all RIO configuration access functions. They just check 17 * Wrappers for all RIO configuration access functions. They just check
25 * alignment, do locking and call the low-level functions pointed to 18 * alignment and call the low-level functions pointed to by rio_mport->ops.
26 * by rio_mport->ops.
27 */ 19 */
28 20
29#define RIO_8_BAD 0 21#define RIO_8_BAD 0
@@ -44,13 +36,10 @@ int __rio_local_read_config_##size \
44 (struct rio_mport *mport, u32 offset, type *value) \ 36 (struct rio_mport *mport, u32 offset, type *value) \
45{ \ 37{ \
46 int res; \ 38 int res; \
47 unsigned long flags; \
48 u32 data = 0; \ 39 u32 data = 0; \
49 if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ 40 if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
50 spin_lock_irqsave(&rio_config_lock, flags); \
51 res = mport->ops->lcread(mport, mport->id, offset, len, &data); \ 41 res = mport->ops->lcread(mport, mport->id, offset, len, &data); \
52 *value = (type)data; \ 42 *value = (type)data; \
53 spin_unlock_irqrestore(&rio_config_lock, flags); \
54 return res; \ 43 return res; \
55} 44}
56 45
@@ -67,13 +56,8 @@ int __rio_local_read_config_##size \
67int __rio_local_write_config_##size \ 56int __rio_local_write_config_##size \
68 (struct rio_mport *mport, u32 offset, type value) \ 57 (struct rio_mport *mport, u32 offset, type value) \
69{ \ 58{ \
70 int res; \
71 unsigned long flags; \
72 if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ 59 if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
73 spin_lock_irqsave(&rio_config_lock, flags); \ 60 return mport->ops->lcwrite(mport, mport->id, offset, len, value);\
74 res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\
75 spin_unlock_irqrestore(&rio_config_lock, flags); \
76 return res; \
77} 61}
78 62
79RIO_LOP_READ(8, u8, 1) 63RIO_LOP_READ(8, u8, 1)
@@ -104,13 +88,10 @@ int rio_mport_read_config_##size \
104 (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value) \ 88 (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value) \
105{ \ 89{ \
106 int res; \ 90 int res; \
107 unsigned long flags; \
108 u32 data = 0; \ 91 u32 data = 0; \
109 if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ 92 if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
110 spin_lock_irqsave(&rio_config_lock, flags); \
111 res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \ 93 res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
112 *value = (type)data; \ 94 *value = (type)data; \
113 spin_unlock_irqrestore(&rio_config_lock, flags); \
114 return res; \ 95 return res; \
115} 96}
116 97
@@ -127,13 +108,9 @@ int rio_mport_read_config_##size \
127int rio_mport_write_config_##size \ 108int rio_mport_write_config_##size \
128 (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value) \ 109 (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value) \
129{ \ 110{ \
130 int res; \
131 unsigned long flags; \
132 if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ 111 if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
133 spin_lock_irqsave(&rio_config_lock, flags); \ 112 return mport->ops->cwrite(mport, mport->id, destid, hopcount, \
134 res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \ 113 offset, len, value); \
135 spin_unlock_irqrestore(&rio_config_lock, flags); \
136 return res; \
137} 114}
138 115
139RIO_OP_READ(8, u8, 1) 116RIO_OP_READ(8, u8, 1)
@@ -162,14 +139,7 @@ EXPORT_SYMBOL_GPL(rio_mport_write_config_32);
162 */ 139 */
163int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data) 140int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
164{ 141{
165 int res; 142 return mport->ops->dsend(mport, mport->id, destid, data);
166 unsigned long flags;
167
168 spin_lock_irqsave(&rio_doorbell_lock, flags);
169 res = mport->ops->dsend(mport, mport->id, destid, data);
170 spin_unlock_irqrestore(&rio_doorbell_lock, flags);
171
172 return res;
173} 143}
174 144
175EXPORT_SYMBOL_GPL(rio_mport_send_doorbell); 145EXPORT_SYMBOL_GPL(rio_mport_send_doorbell);