diff options
-rw-r--r-- | drivers/misc/sgi-xp/xpc.h | 3 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_channel.c | 197 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_main.c | 2 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_sn2.c | 205 |
4 files changed, 204 insertions, 203 deletions
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h index da2680892dfa..defd08881184 100644 --- a/drivers/misc/sgi-xp/xpc.h +++ b/drivers/misc/sgi-xp/xpc.h | |||
@@ -666,6 +666,8 @@ extern void (*xpc_online_heartbeat) (void); | |||
666 | extern void (*xpc_check_remote_hb) (void); | 666 | extern void (*xpc_check_remote_hb) (void); |
667 | extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *); | 667 | extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *); |
668 | extern u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *); | 668 | extern u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *); |
669 | extern enum xp_retval (*xpc_allocate_msgqueues) (struct xpc_channel *); | ||
670 | extern void (*xpc_free_msgqueues) (struct xpc_channel *); | ||
669 | extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *); | 671 | extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *); |
670 | extern void (*xpc_process_msg_chctl_flags) (struct xpc_partition *, int); | 672 | extern void (*xpc_process_msg_chctl_flags) (struct xpc_partition *, int); |
671 | extern int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *); | 673 | extern int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *); |
@@ -728,7 +730,6 @@ extern void xpc_deactivate_partition(const int, struct xpc_partition *, | |||
728 | extern enum xp_retval xpc_initiate_partid_to_nasids(short, void *); | 730 | extern enum xp_retval xpc_initiate_partid_to_nasids(short, void *); |
729 | 731 | ||
730 | /* found in xpc_channel.c */ | 732 | /* found in xpc_channel.c */ |
731 | extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **); | ||
732 | extern void xpc_initiate_connect(int); | 733 | extern void xpc_initiate_connect(int); |
733 | extern void xpc_initiate_disconnect(int); | 734 | extern void xpc_initiate_disconnect(int); |
734 | extern enum xp_retval xpc_allocate_msg_wait(struct xpc_channel *); | 735 | extern enum xp_retval xpc_allocate_msg_wait(struct xpc_channel *); |
diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c index 0d3c153d1d0b..1c73423665bd 100644 --- a/drivers/misc/sgi-xp/xpc_channel.c +++ b/drivers/misc/sgi-xp/xpc_channel.c | |||
@@ -25,145 +25,6 @@ | |||
25 | #include "xpc.h" | 25 | #include "xpc.h" |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Guarantee that the kzalloc'd memory is cacheline aligned. | ||
29 | */ | ||
30 | void * | ||
31 | xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base) | ||
32 | { | ||
33 | /* see if kzalloc will give us cachline aligned memory by default */ | ||
34 | *base = kzalloc(size, flags); | ||
35 | if (*base == NULL) | ||
36 | return NULL; | ||
37 | |||
38 | if ((u64)*base == L1_CACHE_ALIGN((u64)*base)) | ||
39 | return *base; | ||
40 | |||
41 | kfree(*base); | ||
42 | |||
43 | /* nope, we'll have to do it ourselves */ | ||
44 | *base = kzalloc(size + L1_CACHE_BYTES, flags); | ||
45 | if (*base == NULL) | ||
46 | return NULL; | ||
47 | |||
48 | return (void *)L1_CACHE_ALIGN((u64)*base); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Allocate the local message queue and the notify queue. | ||
53 | */ | ||
54 | static enum xp_retval | ||
55 | xpc_allocate_local_msgqueue(struct xpc_channel *ch) | ||
56 | { | ||
57 | unsigned long irq_flags; | ||
58 | int nentries; | ||
59 | size_t nbytes; | ||
60 | |||
61 | for (nentries = ch->local_nentries; nentries > 0; nentries--) { | ||
62 | |||
63 | nbytes = nentries * ch->msg_size; | ||
64 | ch->local_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes, | ||
65 | GFP_KERNEL, | ||
66 | &ch->local_msgqueue_base); | ||
67 | if (ch->local_msgqueue == NULL) | ||
68 | continue; | ||
69 | |||
70 | nbytes = nentries * sizeof(struct xpc_notify); | ||
71 | ch->notify_queue = kzalloc(nbytes, GFP_KERNEL); | ||
72 | if (ch->notify_queue == NULL) { | ||
73 | kfree(ch->local_msgqueue_base); | ||
74 | ch->local_msgqueue = NULL; | ||
75 | continue; | ||
76 | } | ||
77 | |||
78 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
79 | if (nentries < ch->local_nentries) { | ||
80 | dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, " | ||
81 | "partid=%d, channel=%d\n", nentries, | ||
82 | ch->local_nentries, ch->partid, ch->number); | ||
83 | |||
84 | ch->local_nentries = nentries; | ||
85 | } | ||
86 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
87 | return xpSuccess; | ||
88 | } | ||
89 | |||
90 | dev_dbg(xpc_chan, "can't get memory for local message queue and notify " | ||
91 | "queue, partid=%d, channel=%d\n", ch->partid, ch->number); | ||
92 | return xpNoMemory; | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * Allocate the cached remote message queue. | ||
97 | */ | ||
98 | static enum xp_retval | ||
99 | xpc_allocate_remote_msgqueue(struct xpc_channel *ch) | ||
100 | { | ||
101 | unsigned long irq_flags; | ||
102 | int nentries; | ||
103 | size_t nbytes; | ||
104 | |||
105 | DBUG_ON(ch->remote_nentries <= 0); | ||
106 | |||
107 | for (nentries = ch->remote_nentries; nentries > 0; nentries--) { | ||
108 | |||
109 | nbytes = nentries * ch->msg_size; | ||
110 | ch->remote_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes, | ||
111 | GFP_KERNEL, | ||
112 | &ch->remote_msgqueue_base); | ||
113 | if (ch->remote_msgqueue == NULL) | ||
114 | continue; | ||
115 | |||
116 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
117 | if (nentries < ch->remote_nentries) { | ||
118 | dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, " | ||
119 | "partid=%d, channel=%d\n", nentries, | ||
120 | ch->remote_nentries, ch->partid, ch->number); | ||
121 | |||
122 | ch->remote_nentries = nentries; | ||
123 | } | ||
124 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
125 | return xpSuccess; | ||
126 | } | ||
127 | |||
128 | dev_dbg(xpc_chan, "can't get memory for cached remote message queue, " | ||
129 | "partid=%d, channel=%d\n", ch->partid, ch->number); | ||
130 | return xpNoMemory; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * Allocate message queues and other stuff associated with a channel. | ||
135 | * | ||
136 | * Note: Assumes all of the channel sizes are filled in. | ||
137 | */ | ||
138 | static enum xp_retval | ||
139 | xpc_allocate_msgqueues(struct xpc_channel *ch) | ||
140 | { | ||
141 | unsigned long irq_flags; | ||
142 | enum xp_retval ret; | ||
143 | |||
144 | DBUG_ON(ch->flags & XPC_C_SETUP); | ||
145 | |||
146 | ret = xpc_allocate_local_msgqueue(ch); | ||
147 | if (ret != xpSuccess) | ||
148 | return ret; | ||
149 | |||
150 | ret = xpc_allocate_remote_msgqueue(ch); | ||
151 | if (ret != xpSuccess) { | ||
152 | kfree(ch->local_msgqueue_base); | ||
153 | ch->local_msgqueue = NULL; | ||
154 | kfree(ch->notify_queue); | ||
155 | ch->notify_queue = NULL; | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
160 | ch->flags |= XPC_C_SETUP; | ||
161 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
162 | |||
163 | return xpSuccess; | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * Process a connect message from a remote partition. | 28 | * Process a connect message from a remote partition. |
168 | * | 29 | * |
169 | * Note: xpc_process_connect() is expecting to be called with the | 30 | * Note: xpc_process_connect() is expecting to be called with the |
@@ -191,10 +52,11 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags) | |||
191 | if (ret != xpSuccess) | 52 | if (ret != xpSuccess) |
192 | XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags); | 53 | XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags); |
193 | 54 | ||
55 | ch->flags |= XPC_C_SETUP; | ||
56 | |||
194 | if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) | 57 | if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) |
195 | return; | 58 | return; |
196 | 59 | ||
197 | DBUG_ON(!(ch->flags & XPC_C_SETUP)); | ||
198 | DBUG_ON(ch->local_msgqueue == NULL); | 60 | DBUG_ON(ch->local_msgqueue == NULL); |
199 | DBUG_ON(ch->remote_msgqueue == NULL); | 61 | DBUG_ON(ch->remote_msgqueue == NULL); |
200 | } | 62 | } |
@@ -220,55 +82,6 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags) | |||
220 | } | 82 | } |
221 | 83 | ||
222 | /* | 84 | /* |
223 | * Free up message queues and other stuff that were allocated for the specified | ||
224 | * channel. | ||
225 | * | ||
226 | * Note: ch->reason and ch->reason_line are left set for debugging purposes, | ||
227 | * they're cleared when XPC_C_DISCONNECTED is cleared. | ||
228 | */ | ||
229 | static void | ||
230 | xpc_free_msgqueues(struct xpc_channel *ch) | ||
231 | { | ||
232 | struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; | ||
233 | |||
234 | DBUG_ON(!spin_is_locked(&ch->lock)); | ||
235 | DBUG_ON(atomic_read(&ch->n_to_notify) != 0); | ||
236 | |||
237 | ch->remote_msgqueue_pa = 0; | ||
238 | ch->func = NULL; | ||
239 | ch->key = NULL; | ||
240 | ch->msg_size = 0; | ||
241 | ch->local_nentries = 0; | ||
242 | ch->remote_nentries = 0; | ||
243 | ch->kthreads_assigned_limit = 0; | ||
244 | ch->kthreads_idle_limit = 0; | ||
245 | |||
246 | ch_sn2->local_GP->get = 0; | ||
247 | ch_sn2->local_GP->put = 0; | ||
248 | ch_sn2->remote_GP.get = 0; | ||
249 | ch_sn2->remote_GP.put = 0; | ||
250 | ch_sn2->w_local_GP.get = 0; | ||
251 | ch_sn2->w_local_GP.put = 0; | ||
252 | ch_sn2->w_remote_GP.get = 0; | ||
253 | ch_sn2->w_remote_GP.put = 0; | ||
254 | ch_sn2->next_msg_to_pull = 0; | ||
255 | |||
256 | if (ch->flags & XPC_C_SETUP) { | ||
257 | ch->flags &= ~XPC_C_SETUP; | ||
258 | |||
259 | dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n", | ||
260 | ch->flags, ch->partid, ch->number); | ||
261 | |||
262 | kfree(ch->local_msgqueue_base); | ||
263 | ch->local_msgqueue = NULL; | ||
264 | kfree(ch->remote_msgqueue_base); | ||
265 | ch->remote_msgqueue = NULL; | ||
266 | kfree(ch->notify_queue); | ||
267 | ch->notify_queue = NULL; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * spin_lock_irqsave() is expected to be held on entry. | 85 | * spin_lock_irqsave() is expected to be held on entry. |
273 | */ | 86 | */ |
274 | static void | 87 | static void |
@@ -331,7 +144,11 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) | |||
331 | /* it's now safe to free the channel's message queues */ | 144 | /* it's now safe to free the channel's message queues */ |
332 | xpc_free_msgqueues(ch); | 145 | xpc_free_msgqueues(ch); |
333 | 146 | ||
334 | /* mark disconnected, clear all other flags except XPC_C_WDISCONNECT */ | 147 | /* |
148 | * Mark the channel disconnected and clear all other flags, including | ||
149 | * XPC_C_SETUP (because of call to xpc_free_msgqueues()) but not | ||
150 | * including XPC_C_WDISCONNECT (if it was set). | ||
151 | */ | ||
335 | ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT)); | 152 | ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT)); |
336 | 153 | ||
337 | atomic_dec(&part->nchannels_active); | 154 | atomic_dec(&part->nchannels_active); |
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 2934b4473001..b5f3c5e59db0 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c | |||
@@ -186,6 +186,8 @@ void (*xpc_check_remote_hb) (void); | |||
186 | enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part); | 186 | enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part); |
187 | void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *ch); | 187 | void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *ch); |
188 | u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *part); | 188 | u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *part); |
189 | enum xp_retval (*xpc_allocate_msgqueues) (struct xpc_channel *ch); | ||
190 | void (*xpc_free_msgqueues) (struct xpc_channel *ch); | ||
189 | void (*xpc_process_msg_chctl_flags) (struct xpc_partition *part, int ch_number); | 191 | void (*xpc_process_msg_chctl_flags) (struct xpc_partition *part, int ch_number); |
190 | int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *ch); | 192 | int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *ch); |
191 | struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch); | 193 | struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch); |
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c index 01dd40ec2a89..e5dc8c44c6fb 100644 --- a/drivers/misc/sgi-xp/xpc_sn2.c +++ b/drivers/misc/sgi-xp/xpc_sn2.c | |||
@@ -1049,6 +1049,30 @@ xpc_process_activate_IRQ_rcvd_sn2(int n_IRQs_expected) | |||
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | /* | 1051 | /* |
1052 | * Guarantee that the kzalloc'd memory is cacheline aligned. | ||
1053 | */ | ||
1054 | static void * | ||
1055 | xpc_kzalloc_cacheline_aligned_sn2(size_t size, gfp_t flags, void **base) | ||
1056 | { | ||
1057 | /* see if kzalloc will give us cachline aligned memory by default */ | ||
1058 | *base = kzalloc(size, flags); | ||
1059 | if (*base == NULL) | ||
1060 | return NULL; | ||
1061 | |||
1062 | if ((u64)*base == L1_CACHE_ALIGN((u64)*base)) | ||
1063 | return *base; | ||
1064 | |||
1065 | kfree(*base); | ||
1066 | |||
1067 | /* nope, we'll have to do it ourselves */ | ||
1068 | *base = kzalloc(size + L1_CACHE_BYTES, flags); | ||
1069 | if (*base == NULL) | ||
1070 | return NULL; | ||
1071 | |||
1072 | return (void *)L1_CACHE_ALIGN((u64)*base); | ||
1073 | } | ||
1074 | |||
1075 | /* | ||
1052 | * Setup the infrastructure necessary to support XPartition Communication | 1076 | * Setup the infrastructure necessary to support XPartition Communication |
1053 | * between the specified remote partition and the local one. | 1077 | * between the specified remote partition and the local one. |
1054 | */ | 1078 | */ |
@@ -1078,10 +1102,9 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part) | |||
1078 | 1102 | ||
1079 | /* allocate all the required GET/PUT values */ | 1103 | /* allocate all the required GET/PUT values */ |
1080 | 1104 | ||
1081 | part_sn2->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, | 1105 | part_sn2->local_GPs = |
1082 | GFP_KERNEL, | 1106 | xpc_kzalloc_cacheline_aligned_sn2(XPC_GP_SIZE, GFP_KERNEL, |
1083 | &part_sn2-> | 1107 | &part_sn2->local_GPs_base); |
1084 | local_GPs_base); | ||
1085 | if (part_sn2->local_GPs == NULL) { | 1108 | if (part_sn2->local_GPs == NULL) { |
1086 | dev_err(xpc_chan, "can't get memory for local get/put " | 1109 | dev_err(xpc_chan, "can't get memory for local get/put " |
1087 | "values\n"); | 1110 | "values\n"); |
@@ -1089,10 +1112,9 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part) | |||
1089 | goto out_1; | 1112 | goto out_1; |
1090 | } | 1113 | } |
1091 | 1114 | ||
1092 | part_sn2->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, | 1115 | part_sn2->remote_GPs = |
1093 | GFP_KERNEL, | 1116 | xpc_kzalloc_cacheline_aligned_sn2(XPC_GP_SIZE, GFP_KERNEL, |
1094 | &part_sn2-> | 1117 | &part_sn2->remote_GPs_base); |
1095 | remote_GPs_base); | ||
1096 | if (part_sn2->remote_GPs == NULL) { | 1118 | if (part_sn2->remote_GPs == NULL) { |
1097 | dev_err(xpc_chan, "can't get memory for remote get/put " | 1119 | dev_err(xpc_chan, "can't get memory for remote get/put " |
1098 | "values\n"); | 1120 | "values\n"); |
@@ -1105,8 +1127,9 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part) | |||
1105 | /* allocate all the required open and close args */ | 1127 | /* allocate all the required open and close args */ |
1106 | 1128 | ||
1107 | part->local_openclose_args = | 1129 | part->local_openclose_args = |
1108 | xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL, | 1130 | xpc_kzalloc_cacheline_aligned_sn2(XPC_OPENCLOSE_ARGS_SIZE, |
1109 | &part->local_openclose_args_base); | 1131 | GFP_KERNEL, |
1132 | &part->local_openclose_args_base); | ||
1110 | if (part->local_openclose_args == NULL) { | 1133 | if (part->local_openclose_args == NULL) { |
1111 | dev_err(xpc_chan, "can't get memory for local connect args\n"); | 1134 | dev_err(xpc_chan, "can't get memory for local connect args\n"); |
1112 | retval = xpNoMemory; | 1135 | retval = xpNoMemory; |
@@ -1114,8 +1137,9 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part) | |||
1114 | } | 1137 | } |
1115 | 1138 | ||
1116 | part->remote_openclose_args = | 1139 | part->remote_openclose_args = |
1117 | xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL, | 1140 | xpc_kzalloc_cacheline_aligned_sn2(XPC_OPENCLOSE_ARGS_SIZE, |
1118 | &part->remote_openclose_args_base); | 1141 | GFP_KERNEL, |
1142 | &part->remote_openclose_args_base); | ||
1119 | if (part->remote_openclose_args == NULL) { | 1143 | if (part->remote_openclose_args == NULL) { |
1120 | dev_err(xpc_chan, "can't get memory for remote connect args\n"); | 1144 | dev_err(xpc_chan, "can't get memory for remote connect args\n"); |
1121 | retval = xpNoMemory; | 1145 | retval = xpNoMemory; |
@@ -1528,6 +1552,161 @@ xpc_get_chctl_all_flags_sn2(struct xpc_partition *part) | |||
1528 | } | 1552 | } |
1529 | 1553 | ||
1530 | /* | 1554 | /* |
1555 | * Allocate the local message queue and the notify queue. | ||
1556 | */ | ||
1557 | static enum xp_retval | ||
1558 | xpc_allocate_local_msgqueue_sn2(struct xpc_channel *ch) | ||
1559 | { | ||
1560 | unsigned long irq_flags; | ||
1561 | int nentries; | ||
1562 | size_t nbytes; | ||
1563 | |||
1564 | for (nentries = ch->local_nentries; nentries > 0; nentries--) { | ||
1565 | |||
1566 | nbytes = nentries * ch->msg_size; | ||
1567 | ch->local_msgqueue = | ||
1568 | xpc_kzalloc_cacheline_aligned_sn2(nbytes, GFP_KERNEL, | ||
1569 | &ch->local_msgqueue_base); | ||
1570 | if (ch->local_msgqueue == NULL) | ||
1571 | continue; | ||
1572 | |||
1573 | nbytes = nentries * sizeof(struct xpc_notify); | ||
1574 | ch->notify_queue = kzalloc(nbytes, GFP_KERNEL); | ||
1575 | if (ch->notify_queue == NULL) { | ||
1576 | kfree(ch->local_msgqueue_base); | ||
1577 | ch->local_msgqueue = NULL; | ||
1578 | continue; | ||
1579 | } | ||
1580 | |||
1581 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
1582 | if (nentries < ch->local_nentries) { | ||
1583 | dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, " | ||
1584 | "partid=%d, channel=%d\n", nentries, | ||
1585 | ch->local_nentries, ch->partid, ch->number); | ||
1586 | |||
1587 | ch->local_nentries = nentries; | ||
1588 | } | ||
1589 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
1590 | return xpSuccess; | ||
1591 | } | ||
1592 | |||
1593 | dev_dbg(xpc_chan, "can't get memory for local message queue and notify " | ||
1594 | "queue, partid=%d, channel=%d\n", ch->partid, ch->number); | ||
1595 | return xpNoMemory; | ||
1596 | } | ||
1597 | |||
1598 | /* | ||
1599 | * Allocate the cached remote message queue. | ||
1600 | */ | ||
1601 | static enum xp_retval | ||
1602 | xpc_allocate_remote_msgqueue_sn2(struct xpc_channel *ch) | ||
1603 | { | ||
1604 | unsigned long irq_flags; | ||
1605 | int nentries; | ||
1606 | size_t nbytes; | ||
1607 | |||
1608 | DBUG_ON(ch->remote_nentries <= 0); | ||
1609 | |||
1610 | for (nentries = ch->remote_nentries; nentries > 0; nentries--) { | ||
1611 | |||
1612 | nbytes = nentries * ch->msg_size; | ||
1613 | ch->remote_msgqueue = | ||
1614 | xpc_kzalloc_cacheline_aligned_sn2(nbytes, GFP_KERNEL, | ||
1615 | &ch->remote_msgqueue_base); | ||
1616 | if (ch->remote_msgqueue == NULL) | ||
1617 | continue; | ||
1618 | |||
1619 | spin_lock_irqsave(&ch->lock, irq_flags); | ||
1620 | if (nentries < ch->remote_nentries) { | ||
1621 | dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, " | ||
1622 | "partid=%d, channel=%d\n", nentries, | ||
1623 | ch->remote_nentries, ch->partid, ch->number); | ||
1624 | |||
1625 | ch->remote_nentries = nentries; | ||
1626 | } | ||
1627 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
1628 | return xpSuccess; | ||
1629 | } | ||
1630 | |||
1631 | dev_dbg(xpc_chan, "can't get memory for cached remote message queue, " | ||
1632 | "partid=%d, channel=%d\n", ch->partid, ch->number); | ||
1633 | return xpNoMemory; | ||
1634 | } | ||
1635 | |||
1636 | /* | ||
1637 | * Allocate message queues and other stuff associated with a channel. | ||
1638 | * | ||
1639 | * Note: Assumes all of the channel sizes are filled in. | ||
1640 | */ | ||
1641 | static enum xp_retval | ||
1642 | xpc_allocate_msgqueues_sn2(struct xpc_channel *ch) | ||
1643 | { | ||
1644 | enum xp_retval ret; | ||
1645 | |||
1646 | DBUG_ON(ch->flags & XPC_C_SETUP); | ||
1647 | |||
1648 | ret = xpc_allocate_local_msgqueue_sn2(ch); | ||
1649 | if (ret == xpSuccess) { | ||
1650 | |||
1651 | ret = xpc_allocate_remote_msgqueue_sn2(ch); | ||
1652 | if (ret != xpSuccess) { | ||
1653 | kfree(ch->local_msgqueue_base); | ||
1654 | ch->local_msgqueue = NULL; | ||
1655 | kfree(ch->notify_queue); | ||
1656 | ch->notify_queue = NULL; | ||
1657 | } | ||
1658 | } | ||
1659 | return ret; | ||
1660 | } | ||
1661 | |||
1662 | /* | ||
1663 | * Free up message queues and other stuff that were allocated for the specified | ||
1664 | * channel. | ||
1665 | * | ||
1666 | * Note: ch->reason and ch->reason_line are left set for debugging purposes, | ||
1667 | * they're cleared when XPC_C_DISCONNECTED is cleared. | ||
1668 | */ | ||
1669 | static void | ||
1670 | xpc_free_msgqueues_sn2(struct xpc_channel *ch) | ||
1671 | { | ||
1672 | struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; | ||
1673 | |||
1674 | DBUG_ON(!spin_is_locked(&ch->lock)); | ||
1675 | DBUG_ON(atomic_read(&ch->n_to_notify) != 0); | ||
1676 | |||
1677 | ch->remote_msgqueue_pa = 0; | ||
1678 | ch->func = NULL; | ||
1679 | ch->key = NULL; | ||
1680 | ch->msg_size = 0; | ||
1681 | ch->local_nentries = 0; | ||
1682 | ch->remote_nentries = 0; | ||
1683 | ch->kthreads_assigned_limit = 0; | ||
1684 | ch->kthreads_idle_limit = 0; | ||
1685 | |||
1686 | ch_sn2->local_GP->get = 0; | ||
1687 | ch_sn2->local_GP->put = 0; | ||
1688 | ch_sn2->remote_GP.get = 0; | ||
1689 | ch_sn2->remote_GP.put = 0; | ||
1690 | ch_sn2->w_local_GP.get = 0; | ||
1691 | ch_sn2->w_local_GP.put = 0; | ||
1692 | ch_sn2->w_remote_GP.get = 0; | ||
1693 | ch_sn2->w_remote_GP.put = 0; | ||
1694 | ch_sn2->next_msg_to_pull = 0; | ||
1695 | |||
1696 | if (ch->flags & XPC_C_SETUP) { | ||
1697 | dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n", | ||
1698 | ch->flags, ch->partid, ch->number); | ||
1699 | |||
1700 | kfree(ch->local_msgqueue_base); | ||
1701 | ch->local_msgqueue = NULL; | ||
1702 | kfree(ch->remote_msgqueue_base); | ||
1703 | ch->remote_msgqueue = NULL; | ||
1704 | kfree(ch->notify_queue); | ||
1705 | ch->notify_queue = NULL; | ||
1706 | } | ||
1707 | } | ||
1708 | |||
1709 | /* | ||
1531 | * Notify those who wanted to be notified upon delivery of their message. | 1710 | * Notify those who wanted to be notified upon delivery of their message. |
1532 | */ | 1711 | */ |
1533 | static void | 1712 | static void |
@@ -2177,6 +2356,8 @@ xpc_init_sn2(void) | |||
2177 | xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2; | 2356 | xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2; |
2178 | xpc_make_first_contact = xpc_make_first_contact_sn2; | 2357 | xpc_make_first_contact = xpc_make_first_contact_sn2; |
2179 | xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_sn2; | 2358 | xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_sn2; |
2359 | xpc_allocate_msgqueues = xpc_allocate_msgqueues_sn2; | ||
2360 | xpc_free_msgqueues = xpc_free_msgqueues_sn2; | ||
2180 | xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2; | 2361 | xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2; |
2181 | xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2; | 2362 | xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2; |
2182 | xpc_n_of_deliverable_msgs = xpc_n_of_deliverable_msgs_sn2; | 2363 | xpc_n_of_deliverable_msgs = xpc_n_of_deliverable_msgs_sn2; |