1 // SPDX-License-Identifier: GPL-2.0
2 /* Shared Memory Communications Direct over ISM devices (SMC-D)
4 * Functions for ISM device.
6 * Copyright IBM Corp. 2018
9 #include <linux/spinlock.h>
10 #include <linux/mutex.h>
11 #include <linux/slab.h>
18 #include "smc_netlink.h"
20 struct smcd_dev_list smcd_dev_list
= {
21 .list
= LIST_HEAD_INIT(smcd_dev_list
.list
),
22 .mutex
= __MUTEX_INITIALIZER(smcd_dev_list
.mutex
)
25 static bool smc_ism_v2_capable
;
27 /* Test if an ISM communication is possible - same CPC */
28 int smc_ism_cantalk(u64 peer_gid
, unsigned short vlan_id
, struct smcd_dev
*smcd
)
30 return smcd
->ops
->query_remote_gid(smcd
, peer_gid
, vlan_id
? 1 : 0,
34 int smc_ism_write(struct smcd_dev
*smcd
, const struct smc_ism_position
*pos
,
35 void *data
, size_t len
)
39 rc
= smcd
->ops
->move_data(smcd
, pos
->token
, pos
->index
, pos
->signal
,
40 pos
->offset
, data
, len
);
42 return rc
< 0 ? rc
: 0;
45 void smc_ism_get_system_eid(struct smcd_dev
*smcd
, u8
**eid
)
47 smcd
->ops
->get_system_eid(smcd
, eid
);
50 u16
smc_ism_get_chid(struct smcd_dev
*smcd
)
52 return smcd
->ops
->get_chid(smcd
);
55 /* HW supports ISM V2 and thus System EID is defined */
56 bool smc_ism_is_v2_capable(void)
58 return smc_ism_v2_capable
;
61 /* Set a connection using this DMBE. */
62 void smc_ism_set_conn(struct smc_connection
*conn
)
66 spin_lock_irqsave(&conn
->lgr
->smcd
->lock
, flags
);
67 conn
->lgr
->smcd
->conn
[conn
->rmb_desc
->sba_idx
] = conn
;
68 spin_unlock_irqrestore(&conn
->lgr
->smcd
->lock
, flags
);
71 /* Unset a connection using this DMBE. */
72 void smc_ism_unset_conn(struct smc_connection
*conn
)
79 spin_lock_irqsave(&conn
->lgr
->smcd
->lock
, flags
);
80 conn
->lgr
->smcd
->conn
[conn
->rmb_desc
->sba_idx
] = NULL
;
81 spin_unlock_irqrestore(&conn
->lgr
->smcd
->lock
, flags
);
84 /* Register a VLAN identifier with the ISM device. Use a reference count
85 * and add a VLAN identifier only when the first DMB using this VLAN is
88 int smc_ism_get_vlan(struct smcd_dev
*smcd
, unsigned short vlanid
)
90 struct smc_ism_vlanid
*new_vlan
, *vlan
;
94 if (!vlanid
) /* No valid vlan id */
97 /* create new vlan entry, in case we need it */
98 new_vlan
= kzalloc(sizeof(*new_vlan
), GFP_KERNEL
);
101 new_vlan
->vlanid
= vlanid
;
102 refcount_set(&new_vlan
->refcnt
, 1);
104 /* if there is an existing entry, increase count and return */
105 spin_lock_irqsave(&smcd
->lock
, flags
);
106 list_for_each_entry(vlan
, &smcd
->vlan
, list
) {
107 if (vlan
->vlanid
== vlanid
) {
108 refcount_inc(&vlan
->refcnt
);
114 /* no existing entry found.
115 * add new entry to device; might fail, e.g., if HW limit reached
117 if (smcd
->ops
->add_vlan_id(smcd
, vlanid
)) {
122 list_add_tail(&new_vlan
->list
, &smcd
->vlan
);
124 spin_unlock_irqrestore(&smcd
->lock
, flags
);
128 /* Unregister a VLAN identifier with the ISM device. Use a reference count
129 * and remove a VLAN identifier only when the last DMB using this VLAN is
132 int smc_ism_put_vlan(struct smcd_dev
*smcd
, unsigned short vlanid
)
134 struct smc_ism_vlanid
*vlan
;
139 if (!vlanid
) /* No valid vlan id */
142 spin_lock_irqsave(&smcd
->lock
, flags
);
143 list_for_each_entry(vlan
, &smcd
->vlan
, list
) {
144 if (vlan
->vlanid
== vlanid
) {
145 if (!refcount_dec_and_test(&vlan
->refcnt
))
153 goto out
; /* VLAN id not in table */
156 /* Found and the last reference just gone */
157 if (smcd
->ops
->del_vlan_id(smcd
, vlanid
))
159 list_del(&vlan
->list
);
162 spin_unlock_irqrestore(&smcd
->lock
, flags
);
166 int smc_ism_unregister_dmb(struct smcd_dev
*smcd
, struct smc_buf_desc
*dmb_desc
)
171 if (!dmb_desc
->dma_addr
)
174 memset(&dmb
, 0, sizeof(dmb
));
175 dmb
.dmb_tok
= dmb_desc
->token
;
176 dmb
.sba_idx
= dmb_desc
->sba_idx
;
177 dmb
.cpu_addr
= dmb_desc
->cpu_addr
;
178 dmb
.dma_addr
= dmb_desc
->dma_addr
;
179 dmb
.dmb_len
= dmb_desc
->len
;
180 rc
= smcd
->ops
->unregister_dmb(smcd
, &dmb
);
181 if (!rc
|| rc
== ISM_ERROR
) {
182 dmb_desc
->cpu_addr
= NULL
;
183 dmb_desc
->dma_addr
= 0;
189 int smc_ism_register_dmb(struct smc_link_group
*lgr
, int dmb_len
,
190 struct smc_buf_desc
*dmb_desc
)
195 memset(&dmb
, 0, sizeof(dmb
));
196 dmb
.dmb_len
= dmb_len
;
197 dmb
.sba_idx
= dmb_desc
->sba_idx
;
198 dmb
.vlan_id
= lgr
->vlan_id
;
199 dmb
.rgid
= lgr
->peer_gid
;
200 rc
= lgr
->smcd
->ops
->register_dmb(lgr
->smcd
, &dmb
);
202 dmb_desc
->sba_idx
= dmb
.sba_idx
;
203 dmb_desc
->token
= dmb
.dmb_tok
;
204 dmb_desc
->cpu_addr
= dmb
.cpu_addr
;
205 dmb_desc
->dma_addr
= dmb
.dma_addr
;
206 dmb_desc
->len
= dmb
.dmb_len
;
211 static int smc_nl_handle_smcd_dev(struct smcd_dev
*smcd
,
213 struct netlink_callback
*cb
)
215 char smc_pnet
[SMC_MAX_PNETID_LEN
+ 1];
216 struct smc_pci_dev smc_pci_dev
;
217 struct nlattr
*port_attrs
;
218 struct nlattr
*attrs
;
222 nlh
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
, cb
->nlh
->nlmsg_seq
,
223 &smc_gen_nl_family
, NLM_F_MULTI
,
224 SMC_NETLINK_GET_DEV_SMCD
);
227 attrs
= nla_nest_start(skb
, SMC_GEN_DEV_SMCD
);
230 use_cnt
= atomic_read(&smcd
->lgr_cnt
);
231 if (nla_put_u32(skb
, SMC_NLA_DEV_USE_CNT
, use_cnt
))
233 if (nla_put_u8(skb
, SMC_NLA_DEV_IS_CRIT
, use_cnt
> 0))
235 memset(&smc_pci_dev
, 0, sizeof(smc_pci_dev
));
236 smc_set_pci_values(to_pci_dev(smcd
->dev
.parent
), &smc_pci_dev
);
237 if (nla_put_u32(skb
, SMC_NLA_DEV_PCI_FID
, smc_pci_dev
.pci_fid
))
239 if (nla_put_u16(skb
, SMC_NLA_DEV_PCI_CHID
, smc_pci_dev
.pci_pchid
))
241 if (nla_put_u16(skb
, SMC_NLA_DEV_PCI_VENDOR
, smc_pci_dev
.pci_vendor
))
243 if (nla_put_u16(skb
, SMC_NLA_DEV_PCI_DEVICE
, smc_pci_dev
.pci_device
))
245 if (nla_put_string(skb
, SMC_NLA_DEV_PCI_ID
, smc_pci_dev
.pci_id
))
248 port_attrs
= nla_nest_start(skb
, SMC_NLA_DEV_PORT
);
251 if (nla_put_u8(skb
, SMC_NLA_DEV_PORT_PNET_USR
, smcd
->pnetid_by_user
))
253 snprintf(smc_pnet
, sizeof(smc_pnet
), "%s", smcd
->pnetid
);
254 if (nla_put_string(skb
, SMC_NLA_DEV_PORT_PNETID
, smc_pnet
))
257 nla_nest_end(skb
, port_attrs
);
258 nla_nest_end(skb
, attrs
);
259 genlmsg_end(skb
, nlh
);
263 nla_nest_cancel(skb
, port_attrs
);
265 nla_nest_cancel(skb
, attrs
);
267 nlmsg_cancel(skb
, nlh
);
272 static void smc_nl_prep_smcd_dev(struct smcd_dev_list
*dev_list
,
274 struct netlink_callback
*cb
)
276 struct smc_nl_dmp_ctx
*cb_ctx
= smc_nl_dmp_ctx(cb
);
277 int snum
= cb_ctx
->pos
[0];
278 struct smcd_dev
*smcd
;
281 mutex_lock(&dev_list
->mutex
);
282 list_for_each_entry(smcd
, &dev_list
->list
, list
) {
285 if (smc_nl_handle_smcd_dev(smcd
, skb
, cb
))
291 mutex_unlock(&dev_list
->mutex
);
292 cb_ctx
->pos
[0] = num
;
295 int smcd_nl_get_device(struct sk_buff
*skb
, struct netlink_callback
*cb
)
297 smc_nl_prep_smcd_dev(&smcd_dev_list
, skb
, cb
);
301 struct smc_ism_event_work
{
302 struct work_struct work
;
303 struct smcd_dev
*smcd
;
304 struct smcd_event event
;
307 #define ISM_EVENT_REQUEST 0x0001
308 #define ISM_EVENT_RESPONSE 0x0002
309 #define ISM_EVENT_REQUEST_IR 0x00000001
310 #define ISM_EVENT_CODE_SHUTDOWN 0x80
311 #define ISM_EVENT_CODE_TESTLINK 0x83
313 union smcd_sw_event_info
{
316 u8 uid
[SMC_LGR_ID_SIZE
];
317 unsigned short vlan_id
;
322 static void smcd_handle_sw_event(struct smc_ism_event_work
*wrk
)
324 union smcd_sw_event_info ev_info
;
326 ev_info
.info
= wrk
->event
.info
;
327 switch (wrk
->event
.code
) {
328 case ISM_EVENT_CODE_SHUTDOWN
: /* Peer shut down DMBs */
329 smc_smcd_terminate(wrk
->smcd
, wrk
->event
.tok
, ev_info
.vlan_id
);
331 case ISM_EVENT_CODE_TESTLINK
: /* Activity timer */
332 if (ev_info
.code
== ISM_EVENT_REQUEST
) {
333 ev_info
.code
= ISM_EVENT_RESPONSE
;
334 wrk
->smcd
->ops
->signal_event(wrk
->smcd
,
336 ISM_EVENT_REQUEST_IR
,
337 ISM_EVENT_CODE_TESTLINK
,
344 int smc_ism_signal_shutdown(struct smc_link_group
*lgr
)
347 union smcd_sw_event_info ev_info
;
349 if (lgr
->peer_shutdown
)
352 memcpy(ev_info
.uid
, lgr
->id
, SMC_LGR_ID_SIZE
);
353 ev_info
.vlan_id
= lgr
->vlan_id
;
354 ev_info
.code
= ISM_EVENT_REQUEST
;
355 rc
= lgr
->smcd
->ops
->signal_event(lgr
->smcd
, lgr
->peer_gid
,
356 ISM_EVENT_REQUEST_IR
,
357 ISM_EVENT_CODE_SHUTDOWN
,
362 /* worker for SMC-D events */
363 static void smc_ism_event_work(struct work_struct
*work
)
365 struct smc_ism_event_work
*wrk
=
366 container_of(work
, struct smc_ism_event_work
, work
);
368 switch (wrk
->event
.type
) {
369 case ISM_EVENT_GID
: /* GID event, token is peer GID */
370 smc_smcd_terminate(wrk
->smcd
, wrk
->event
.tok
, VLAN_VID_MASK
);
374 case ISM_EVENT_SWR
: /* Software defined event */
375 smcd_handle_sw_event(wrk
);
381 static void smcd_release(struct device
*dev
)
383 struct smcd_dev
*smcd
= container_of(dev
, struct smcd_dev
, dev
);
389 struct smcd_dev
*smcd_alloc_dev(struct device
*parent
, const char *name
,
390 const struct smcd_ops
*ops
, int max_dmbs
)
392 struct smcd_dev
*smcd
;
394 smcd
= kzalloc(sizeof(*smcd
), GFP_KERNEL
);
397 smcd
->conn
= kcalloc(max_dmbs
, sizeof(struct smc_connection
*),
404 smcd
->dev
.parent
= parent
;
405 smcd
->dev
.release
= smcd_release
;
406 device_initialize(&smcd
->dev
);
407 dev_set_name(&smcd
->dev
, name
);
409 if (smc_pnetid_by_dev_port(parent
, 0, smcd
->pnetid
))
410 smc_pnetid_by_table_smcd(smcd
);
412 spin_lock_init(&smcd
->lock
);
413 spin_lock_init(&smcd
->lgr_lock
);
414 INIT_LIST_HEAD(&smcd
->vlan
);
415 INIT_LIST_HEAD(&smcd
->lgr_list
);
416 init_waitqueue_head(&smcd
->lgrs_deleted
);
417 smcd
->event_wq
= alloc_ordered_workqueue("ism_evt_wq-%s)",
418 WQ_MEM_RECLAIM
, name
);
419 if (!smcd
->event_wq
) {
426 EXPORT_SYMBOL_GPL(smcd_alloc_dev
);
428 int smcd_register_dev(struct smcd_dev
*smcd
)
430 mutex_lock(&smcd_dev_list
.mutex
);
431 if (list_empty(&smcd_dev_list
.list
)) {
432 u8
*system_eid
= NULL
;
434 smc_ism_get_system_eid(smcd
, &system_eid
);
435 if (system_eid
[24] != '0' || system_eid
[28] != '0')
436 smc_ism_v2_capable
= true;
438 /* sort list: devices without pnetid before devices with pnetid */
440 list_add_tail(&smcd
->list
, &smcd_dev_list
.list
);
442 list_add(&smcd
->list
, &smcd_dev_list
.list
);
443 mutex_unlock(&smcd_dev_list
.mutex
);
445 pr_warn_ratelimited("smc: adding smcd device %s with pnetid %.16s%s\n",
446 dev_name(&smcd
->dev
), smcd
->pnetid
,
447 smcd
->pnetid_by_user
? " (user defined)" : "");
449 return device_add(&smcd
->dev
);
451 EXPORT_SYMBOL_GPL(smcd_register_dev
);
453 void smcd_unregister_dev(struct smcd_dev
*smcd
)
455 pr_warn_ratelimited("smc: removing smcd device %s\n",
456 dev_name(&smcd
->dev
));
457 mutex_lock(&smcd_dev_list
.mutex
);
458 list_del_init(&smcd
->list
);
459 mutex_unlock(&smcd_dev_list
.mutex
);
460 smcd
->going_away
= 1;
461 smc_smcd_terminate_all(smcd
);
462 flush_workqueue(smcd
->event_wq
);
463 destroy_workqueue(smcd
->event_wq
);
465 device_del(&smcd
->dev
);
467 EXPORT_SYMBOL_GPL(smcd_unregister_dev
);
469 void smcd_free_dev(struct smcd_dev
*smcd
)
471 put_device(&smcd
->dev
);
473 EXPORT_SYMBOL_GPL(smcd_free_dev
);
475 /* SMCD Device event handler. Called from ISM device interrupt handler.
476 * Parameters are smcd device pointer,
477 * - event->type (0 --> DMB, 1 --> GID),
478 * - event->code (event code),
479 * - event->tok (either DMB token when event type 0, or GID when event type 1)
480 * - event->time (time of day)
481 * - event->info (debug info).
484 * - Function called in IRQ context from ISM device driver event handler.
486 void smcd_handle_event(struct smcd_dev
*smcd
, struct smcd_event
*event
)
488 struct smc_ism_event_work
*wrk
;
490 if (smcd
->going_away
)
492 /* copy event to event work queue, and let it be handled there */
493 wrk
= kmalloc(sizeof(*wrk
), GFP_ATOMIC
);
496 INIT_WORK(&wrk
->work
, smc_ism_event_work
);
499 queue_work(smcd
->event_wq
, &wrk
->work
);
501 EXPORT_SYMBOL_GPL(smcd_handle_event
);
503 /* SMCD Device interrupt handler. Called from ISM device interrupt handler.
504 * Parameters are smcd device pointer and DMB number. Find the connection and
505 * schedule the tasklet for this connection.
508 * - Function called in IRQ context from ISM device driver IRQ handler.
510 void smcd_handle_irq(struct smcd_dev
*smcd
, unsigned int dmbno
)
512 struct smc_connection
*conn
= NULL
;
515 spin_lock_irqsave(&smcd
->lock
, flags
);
516 conn
= smcd
->conn
[dmbno
];
517 if (conn
&& !conn
->killed
)
518 tasklet_schedule(&conn
->rx_tsklet
);
519 spin_unlock_irqrestore(&smcd
->lock
, flags
);
521 EXPORT_SYMBOL_GPL(smcd_handle_irq
);
523 void __init
smc_ism_init(void)
525 smc_ism_v2_capable
= false;