hc
2024-09-20 cf4ce59b3b70238352c7f1729f0f7223214828ad
kernel/net/smc/smc_ism.c
....@@ -7,6 +7,7 @@
77 */
88
99 #include <linux/spinlock.h>
10
+#include <linux/mutex.h>
1011 #include <linux/slab.h>
1112 #include <asm/page.h>
1213
....@@ -17,10 +18,12 @@
1718
1819 struct smcd_dev_list smcd_dev_list = {
1920 .list = LIST_HEAD_INIT(smcd_dev_list.list),
20
- .lock = __SPIN_LOCK_UNLOCKED(smcd_dev_list.lock)
21
+ .mutex = __MUTEX_INITIALIZER(smcd_dev_list.mutex)
2122 };
2223
23
-/* Test if an ISM communication is possible. */
24
+bool smc_ism_v2_capable;
25
+
26
+/* Test if an ISM communication is possible - same CPC */
2427 int smc_ism_cantalk(u64 peer_gid, unsigned short vlan_id, struct smcd_dev *smcd)
2528 {
2629 return smcd->ops->query_remote_gid(smcd, peer_gid, vlan_id ? 1 : 0,
....@@ -36,6 +39,16 @@
3639 pos->offset, data, len);
3740
3841 return rc < 0 ? rc : 0;
42
+}
43
+
44
+void smc_ism_get_system_eid(struct smcd_dev *smcd, u8 **eid)
45
+{
46
+ smcd->ops->get_system_eid(smcd, eid);
47
+}
48
+
49
+u16 smc_ism_get_chid(struct smcd_dev *smcd)
50
+{
51
+ return smcd->ops->get_chid(smcd);
3952 }
4053
4154 /* Set a connection using this DMBE. */
....@@ -146,6 +159,10 @@
146159 int smc_ism_unregister_dmb(struct smcd_dev *smcd, struct smc_buf_desc *dmb_desc)
147160 {
148161 struct smcd_dmb dmb;
162
+ int rc = 0;
163
+
164
+ if (!dmb_desc->dma_addr)
165
+ return rc;
149166
150167 memset(&dmb, 0, sizeof(dmb));
151168 dmb.dmb_tok = dmb_desc->token;
....@@ -153,7 +170,13 @@
153170 dmb.cpu_addr = dmb_desc->cpu_addr;
154171 dmb.dma_addr = dmb_desc->dma_addr;
155172 dmb.dmb_len = dmb_desc->len;
156
- return smcd->ops->unregister_dmb(smcd, &dmb);
173
+ rc = smcd->ops->unregister_dmb(smcd, &dmb);
174
+ if (!rc || rc == ISM_ERROR) {
175
+ dmb_desc->cpu_addr = NULL;
176
+ dmb_desc->dma_addr = 0;
177
+ }
178
+
179
+ return rc;
157180 }
158181
159182 int smc_ism_register_dmb(struct smc_link_group *lgr, int dmb_len,
....@@ -187,22 +210,28 @@
187210 #define ISM_EVENT_REQUEST 0x0001
188211 #define ISM_EVENT_RESPONSE 0x0002
189212 #define ISM_EVENT_REQUEST_IR 0x00000001
213
+#define ISM_EVENT_CODE_SHUTDOWN 0x80
190214 #define ISM_EVENT_CODE_TESTLINK 0x83
215
+
216
+union smcd_sw_event_info {
217
+ u64 info;
218
+ struct {
219
+ u8 uid[SMC_LGR_ID_SIZE];
220
+ unsigned short vlan_id;
221
+ u16 code;
222
+ };
223
+};
191224
192225 static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
193226 {
194
- union {
195
- u64 info;
196
- struct {
197
- u32 uid;
198
- unsigned short vlanid;
199
- u16 code;
200
- };
201
- } ev_info;
227
+ union smcd_sw_event_info ev_info;
202228
229
+ ev_info.info = wrk->event.info;
203230 switch (wrk->event.code) {
231
+ case ISM_EVENT_CODE_SHUTDOWN: /* Peer shut down DMBs */
232
+ smc_smcd_terminate(wrk->smcd, wrk->event.tok, ev_info.vlan_id);
233
+ break;
204234 case ISM_EVENT_CODE_TESTLINK: /* Activity timer */
205
- ev_info.info = wrk->event.info;
206235 if (ev_info.code == ISM_EVENT_REQUEST) {
207236 ev_info.code = ISM_EVENT_RESPONSE;
208237 wrk->smcd->ops->signal_event(wrk->smcd,
....@@ -215,6 +244,24 @@
215244 }
216245 }
217246
247
+int smc_ism_signal_shutdown(struct smc_link_group *lgr)
248
+{
249
+ int rc;
250
+ union smcd_sw_event_info ev_info;
251
+
252
+ if (lgr->peer_shutdown)
253
+ return 0;
254
+
255
+ memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
256
+ ev_info.vlan_id = lgr->vlan_id;
257
+ ev_info.code = ISM_EVENT_REQUEST;
258
+ rc = lgr->smcd->ops->signal_event(lgr->smcd, lgr->peer_gid,
259
+ ISM_EVENT_REQUEST_IR,
260
+ ISM_EVENT_CODE_SHUTDOWN,
261
+ ev_info.info);
262
+ return rc;
263
+}
264
+
218265 /* worker for SMC-D events */
219266 static void smc_ism_event_work(struct work_struct *work)
220267 {
....@@ -223,7 +270,7 @@
223270
224271 switch (wrk->event.type) {
225272 case ISM_EVENT_GID: /* GID event, token is peer GID */
226
- smc_smcd_terminate(wrk->smcd, wrk->event.tok);
273
+ smc_smcd_terminate(wrk->smcd, wrk->event.tok, VLAN_VID_MASK);
227274 break;
228275 case ISM_EVENT_DMB:
229276 break;
....@@ -257,39 +304,76 @@
257304 return NULL;
258305 }
259306
307
+ smcd->event_wq = alloc_ordered_workqueue("ism_evt_wq-%s)",
308
+ WQ_MEM_RECLAIM, name);
309
+ if (!smcd->event_wq) {
310
+ kfree(smcd->conn);
311
+ kfree(smcd);
312
+ return NULL;
313
+ }
314
+
260315 smcd->dev.parent = parent;
261316 smcd->dev.release = smcd_release;
262317 device_initialize(&smcd->dev);
263318 dev_set_name(&smcd->dev, name);
264319 smcd->ops = ops;
265
- smc_pnetid_by_dev_port(parent, 0, smcd->pnetid);
320
+ if (smc_pnetid_by_dev_port(parent, 0, smcd->pnetid))
321
+ smc_pnetid_by_table_smcd(smcd);
266322
267323 spin_lock_init(&smcd->lock);
324
+ spin_lock_init(&smcd->lgr_lock);
268325 INIT_LIST_HEAD(&smcd->vlan);
269
- smcd->event_wq = alloc_ordered_workqueue("ism_evt_wq-%s)",
270
- WQ_MEM_RECLAIM, name);
326
+ INIT_LIST_HEAD(&smcd->lgr_list);
327
+ init_waitqueue_head(&smcd->lgrs_deleted);
271328 return smcd;
272329 }
273330 EXPORT_SYMBOL_GPL(smcd_alloc_dev);
274331
275332 int smcd_register_dev(struct smcd_dev *smcd)
276333 {
277
- spin_lock(&smcd_dev_list.lock);
278
- list_add_tail(&smcd->list, &smcd_dev_list.list);
279
- spin_unlock(&smcd_dev_list.lock);
334
+ int rc;
280335
281
- return device_add(&smcd->dev);
336
+ mutex_lock(&smcd_dev_list.mutex);
337
+ if (list_empty(&smcd_dev_list.list)) {
338
+ u8 *system_eid = NULL;
339
+
340
+ smc_ism_get_system_eid(smcd, &system_eid);
341
+ if (system_eid[24] != '0' || system_eid[28] != '0')
342
+ smc_ism_v2_capable = true;
343
+ }
344
+ /* sort list: devices without pnetid before devices with pnetid */
345
+ if (smcd->pnetid[0])
346
+ list_add_tail(&smcd->list, &smcd_dev_list.list);
347
+ else
348
+ list_add(&smcd->list, &smcd_dev_list.list);
349
+ mutex_unlock(&smcd_dev_list.mutex);
350
+
351
+ pr_warn_ratelimited("smc: adding smcd device %s with pnetid %.16s%s\n",
352
+ dev_name(&smcd->dev), smcd->pnetid,
353
+ smcd->pnetid_by_user ? " (user defined)" : "");
354
+
355
+ rc = device_add(&smcd->dev);
356
+ if (rc) {
357
+ mutex_lock(&smcd_dev_list.mutex);
358
+ list_del(&smcd->list);
359
+ mutex_unlock(&smcd_dev_list.mutex);
360
+ }
361
+
362
+ return rc;
282363 }
283364 EXPORT_SYMBOL_GPL(smcd_register_dev);
284365
285366 void smcd_unregister_dev(struct smcd_dev *smcd)
286367 {
287
- spin_lock(&smcd_dev_list.lock);
288
- list_del(&smcd->list);
289
- spin_unlock(&smcd_dev_list.lock);
368
+ pr_warn_ratelimited("smc: removing smcd device %s\n",
369
+ dev_name(&smcd->dev));
370
+ mutex_lock(&smcd_dev_list.mutex);
371
+ list_del_init(&smcd->list);
372
+ mutex_unlock(&smcd_dev_list.mutex);
373
+ smcd->going_away = 1;
374
+ smc_smcd_terminate_all(smcd);
290375 flush_workqueue(smcd->event_wq);
291376 destroy_workqueue(smcd->event_wq);
292
- smc_smcd_terminate(smcd, 0);
293377
294378 device_del(&smcd->dev);
295379 }
....@@ -316,6 +400,8 @@
316400 {
317401 struct smc_ism_event_work *wrk;
318402
403
+ if (smcd->going_away)
404
+ return;
319405 /* copy event to event work queue, and let it be handled there */
320406 wrk = kmalloc(sizeof(*wrk), GFP_ATOMIC);
321407 if (!wrk)
....@@ -341,8 +427,13 @@
341427
342428 spin_lock_irqsave(&smcd->lock, flags);
343429 conn = smcd->conn[dmbno];
344
- if (conn)
430
+ if (conn && !conn->killed)
345431 tasklet_schedule(&conn->rx_tsklet);
346432 spin_unlock_irqrestore(&smcd->lock, flags);
347433 }
348434 EXPORT_SYMBOL_GPL(smcd_handle_irq);
435
+
436
+void __init smc_ism_init(void)
437
+{
438
+ smc_ism_v2_capable = false;
439
+}