Skip to content

Commit

Permalink
misc: mic: SCIF RMA nodeqp and minor miscellaneous changes
Browse files Browse the repository at this point in the history
This patch adds the SCIF kernel node QP control messages required to
enable SCIF RMAs. Examples of such node QP control messages include
registration, unregistration, remote memory allocation requests,
remote memory unmap and SCIF remote fence requests.

The patch also updates the SCIF driver with minor changes required to
enable SCIF RMAs by adding the new files to the build, initializing
RMA specific information during SCIF endpoint creation, reserving SCIF
DMA channels, initializing SCIF RMA specific global data structures,
adding the IOCTL hooks required for SCIF RMAs and updating RMA
specific debugfs hooks.

Reviewed-by: Ashutosh Dixit <[email protected]>
Reviewed-by: Nikhil Rao <[email protected]>
Signed-off-by: Sudeep Dutt <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
sudeepdutt authored and gregkh committed Oct 4, 2015
1 parent 564c8d8 commit d182432
Show file tree
Hide file tree
Showing 14 changed files with 516 additions and 40 deletions.
1 change: 1 addition & 0 deletions drivers/misc/mic/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ comment "SCIF Driver"
config SCIF
tristate "SCIF Driver"
depends on 64BIT && PCI && X86 && SCIF_BUS
select IOMMU_IOVA
help
This enables SCIF Driver support for the Intel Many Integrated
Core (MIC) family of PCIe form factor coprocessor devices that
Expand Down
5 changes: 5 additions & 0 deletions drivers/misc/mic/scif/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ scif-objs += scif_epd.o
scif-objs += scif_rb.o
scif-objs += scif_nodeqp.o
scif-objs += scif_nm.o
scif-objs += scif_dma.o
scif-objs += scif_fence.o
scif-objs += scif_mmap.o
scif-objs += scif_rma.o
scif-objs += scif_rma_list.o
33 changes: 27 additions & 6 deletions drivers/misc/mic/scif/scif_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ scif_epd_t scif_open(void)
mutex_init(&ep->sendlock);
mutex_init(&ep->recvlock);

scif_rma_ep_init(ep);
ep->state = SCIFEP_UNBOUND;
dev_dbg(scif_info.mdev.this_device,
"SCIFAPI open: ep %p success\n", ep);
Expand Down Expand Up @@ -184,8 +185,11 @@ int scif_close(scif_epd_t epd)

switch (oldstate) {
case SCIFEP_ZOMBIE:
dev_err(scif_info.mdev.this_device,
"SCIFAPI close: zombie state unexpected\n");
case SCIFEP_DISCONNECTED:
spin_unlock(&ep->lock);
scif_unregister_all_windows(epd);
/* Remove from the disconnected list */
mutex_lock(&scif_info.connlock);
list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
Expand All @@ -207,6 +211,7 @@ int scif_close(scif_epd_t epd)
case SCIFEP_CLOSING:
{
spin_unlock(&ep->lock);
scif_unregister_all_windows(epd);
scif_disconnect_ep(ep);
break;
}
Expand All @@ -218,7 +223,7 @@ int scif_close(scif_epd_t epd)
struct scif_endpt *aep;

spin_unlock(&ep->lock);
spin_lock(&scif_info.eplock);
mutex_lock(&scif_info.eplock);

/* remove from listen list */
list_for_each_safe(pos, tmpq, &scif_info.listen) {
Expand All @@ -240,7 +245,7 @@ int scif_close(scif_epd_t epd)
break;
}
}
spin_unlock(&scif_info.eplock);
mutex_unlock(&scif_info.eplock);
mutex_lock(&scif_info.connlock);
list_for_each_safe(pos, tmpq, &scif_info.connected) {
tmpep = list_entry(pos,
Expand All @@ -260,13 +265,13 @@ int scif_close(scif_epd_t epd)
}
mutex_unlock(&scif_info.connlock);
scif_teardown_ep(aep);
spin_lock(&scif_info.eplock);
mutex_lock(&scif_info.eplock);
scif_add_epd_to_zombie_list(aep, SCIF_EPLOCK_HELD);
ep->acceptcnt--;
}

spin_lock(&ep->lock);
spin_unlock(&scif_info.eplock);
mutex_unlock(&scif_info.eplock);

/* Remove and reject any pending connection requests. */
while (ep->conreqcnt) {
Expand Down Expand Up @@ -428,9 +433,9 @@ int scif_listen(scif_epd_t epd, int backlog)
scif_teardown_ep(ep);
ep->qp_info.qp = NULL;

spin_lock(&scif_info.eplock);
mutex_lock(&scif_info.eplock);
list_add_tail(&ep->list, &scif_info.listen);
spin_unlock(&scif_info.eplock);
mutex_unlock(&scif_info.eplock);
return 0;
}
EXPORT_SYMBOL_GPL(scif_listen);
Expand Down Expand Up @@ -469,6 +474,13 @@ static int scif_conn_func(struct scif_endpt *ep)
struct scifmsg msg;
struct device *spdev;

err = scif_reserve_dma_chan(ep);
if (err) {
dev_err(&ep->remote_dev->sdev->dev,
"%s %d err %d\n", __func__, __LINE__, err);
ep->state = SCIFEP_BOUND;
goto connect_error_simple;
}
/* Initiate the first part of the endpoint QP setup */
err = scif_setup_qp_connect(ep->qp_info.qp, &ep->qp_info.qp_offset,
SCIF_ENDPT_QP_SIZE, ep->remote_dev);
Expand Down Expand Up @@ -804,6 +816,15 @@ int scif_accept(scif_epd_t epd, struct scif_port_id *peer,
cep->remote_dev = &scif_dev[peer->node];
cep->remote_ep = conreq->msg.payload[0];

scif_rma_ep_init(cep);

err = scif_reserve_dma_chan(cep);
if (err) {
dev_err(scif_info.mdev.this_device,
"%s %d err %d\n", __func__, __LINE__, err);
goto scif_accept_error_qpalloc;
}

cep->qp_info.qp = kzalloc(sizeof(*cep->qp_info.qp), GFP_KERNEL);
if (!cep->qp_info.qp) {
err = -ENOMEM;
Expand Down
85 changes: 81 additions & 4 deletions drivers/misc/mic/scif/scif_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,96 @@ static const struct file_operations scif_dev_ops = {
.release = scif_dev_test_release
};

void __init scif_init_debugfs(void)
static void scif_display_window(struct scif_window *window, struct seq_file *s)
{
int j;
struct scatterlist *sg;
scif_pinned_pages_t pin = window->pinned_pages;

seq_printf(s, "window %p type %d temp %d offset 0x%llx ",
window, window->type, window->temp, window->offset);
seq_printf(s, "nr_pages 0x%llx nr_contig_chunks 0x%x prot %d ",
window->nr_pages, window->nr_contig_chunks, window->prot);
seq_printf(s, "ref_count %d magic 0x%llx peer_window 0x%llx ",
window->ref_count, window->magic, window->peer_window);
seq_printf(s, "unreg_state 0x%x va_for_temp 0x%lx\n",
window->unreg_state, window->va_for_temp);

for (j = 0; j < window->nr_contig_chunks; j++)
seq_printf(s, "page[%d] dma_addr 0x%llx num_pages 0x%llx\n", j,
window->dma_addr[j], window->num_pages[j]);

if (window->type == SCIF_WINDOW_SELF && pin)
for (j = 0; j < window->nr_pages; j++)
seq_printf(s, "page[%d] = pinned_pages %p address %p\n",
j, pin->pages[j],
page_address(pin->pages[j]));

if (window->st)
for_each_sg(window->st->sgl, sg, window->st->nents, j)
seq_printf(s, "sg[%d] dma addr 0x%llx length 0x%x\n",
j, sg_dma_address(sg), sg_dma_len(sg));
}

static void scif_display_all_windows(struct list_head *head, struct seq_file *s)
{
struct dentry *d;
struct list_head *item;
struct scif_window *window;

list_for_each(item, head) {
window = list_entry(item, struct scif_window, list);
scif_display_window(window, s);
}
}

static int scif_rma_test(struct seq_file *s, void *unused)
{
struct scif_endpt *ep;
struct list_head *pos;

mutex_lock(&scif_info.connlock);
list_for_each(pos, &scif_info.connected) {
ep = list_entry(pos, struct scif_endpt, list);
seq_printf(s, "ep %p self windows\n", ep);
mutex_lock(&ep->rma_info.rma_lock);
scif_display_all_windows(&ep->rma_info.reg_list, s);
seq_printf(s, "ep %p remote windows\n", ep);
scif_display_all_windows(&ep->rma_info.remote_reg_list, s);
mutex_unlock(&ep->rma_info.rma_lock);
}
mutex_unlock(&scif_info.connlock);
return 0;
}

static int scif_rma_test_open(struct inode *inode, struct file *file)
{
return single_open(file, scif_rma_test, inode->i_private);
}

static int scif_rma_test_release(struct inode *inode, struct file *file)
{
return single_release(inode, file);
}

static const struct file_operations scif_rma_ops = {
.owner = THIS_MODULE,
.open = scif_rma_test_open,
.read = seq_read,
.llseek = seq_lseek,
.release = scif_rma_test_release
};

void __init scif_init_debugfs(void)
{
scif_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
if (!scif_dbg) {
dev_err(scif_info.mdev.this_device,
"can't create debugfs dir scif\n");
return;
}

d = debugfs_create_file("scif_dev", 0444, scif_dbg,
NULL, &scif_dev_ops);
debugfs_create_file("scif_dev", 0444, scif_dbg, NULL, &scif_dev_ops);
debugfs_create_file("scif_rma", 0444, scif_dbg, NULL, &scif_rma_ops);
debugfs_create_u8("en_msg_log", 0666, scif_dbg, &scif_info.en_msg_log);
debugfs_create_u8("p2p_enable", 0666, scif_dbg, &scif_info.p2p_enable);
}
Expand Down
26 changes: 15 additions & 11 deletions drivers/misc/mic/scif/scif_epd.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ void scif_teardown_ep(void *endpt)
void scif_add_epd_to_zombie_list(struct scif_endpt *ep, bool eplock_held)
{
if (!eplock_held)
spin_lock(&scif_info.eplock);
mutex_lock(&scif_info.eplock);
spin_lock(&ep->lock);
ep->state = SCIFEP_ZOMBIE;
spin_unlock(&ep->lock);
list_add_tail(&ep->list, &scif_info.zombie);
scif_info.nr_zombies++;
if (!eplock_held)
spin_unlock(&scif_info.eplock);
mutex_unlock(&scif_info.eplock);
schedule_work(&scif_info.misc_work);
}

Expand All @@ -81,16 +81,15 @@ static struct scif_endpt *scif_find_listen_ep(u16 port)
struct scif_endpt *ep = NULL;
struct list_head *pos, *tmpq;

spin_lock(&scif_info.eplock);
mutex_lock(&scif_info.eplock);
list_for_each_safe(pos, tmpq, &scif_info.listen) {
ep = list_entry(pos, struct scif_endpt, list);
if (ep->port.port == port) {
spin_lock(&ep->lock);
spin_unlock(&scif_info.eplock);
mutex_unlock(&scif_info.eplock);
return ep;
}
}
spin_unlock(&scif_info.eplock);
mutex_unlock(&scif_info.eplock);
return NULL;
}

Expand All @@ -99,14 +98,17 @@ void scif_cleanup_zombie_epd(void)
struct list_head *pos, *tmpq;
struct scif_endpt *ep;

spin_lock(&scif_info.eplock);
mutex_lock(&scif_info.eplock);
list_for_each_safe(pos, tmpq, &scif_info.zombie) {
ep = list_entry(pos, struct scif_endpt, list);
list_del(pos);
scif_info.nr_zombies--;
kfree(ep);
if (scif_rma_ep_can_uninit(ep)) {
list_del(pos);
scif_info.nr_zombies--;
put_iova_domain(&ep->rma_info.iovad);
kfree(ep);
}
}
spin_unlock(&scif_info.eplock);
mutex_unlock(&scif_info.eplock);
}

/**
Expand Down Expand Up @@ -137,6 +139,8 @@ void scif_cnctreq(struct scif_dev *scifdev, struct scifmsg *msg)
if (!ep)
/* Send reject due to no listening ports */
goto conreq_sendrej_free;
else
spin_lock(&ep->lock);

if (ep->backlog <= ep->conreqcnt) {
/* Send reject due to too many pending requests */
Expand Down
28 changes: 28 additions & 0 deletions drivers/misc/mic/scif/scif_epd.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ struct scif_endpt_qp_info {
* @conn_async_state: Async connection
* @conn_pend_wq: Used by poll while waiting for incoming connections
* @conn_list: List of async connection requests
* @rma_info: Information for triggering SCIF RMA and DMA operations
* @mmu_list: link to list of MMU notifier cleanup work
* @anon: anonymous file for use in kernel mode scif poll
*/
struct scif_endpt {
Expand Down Expand Up @@ -129,6 +131,8 @@ struct scif_endpt {
int conn_async_state;
wait_queue_head_t conn_pend_wq;
struct list_head conn_list;
struct scif_endpt_rma_info rma_info;
struct list_head mmu_list;
struct file *anon;
};

Expand All @@ -137,6 +141,27 @@ static inline int scifdev_alive(struct scif_endpt *ep)
return _scifdev_alive(ep->remote_dev);
}

/*
* scif_verify_epd:
* ep: SCIF endpoint
*
* Checks several generic error conditions and returns the
* appropriate error.
*/
static inline int scif_verify_epd(struct scif_endpt *ep)
{
if (ep->state == SCIFEP_DISCONNECTED)
return -ECONNRESET;

if (ep->state != SCIFEP_CONNECTED)
return -ENOTCONN;

if (!scifdev_alive(ep))
return -ENODEV;

return 0;
}

static inline int scif_anon_inode_getfile(scif_epd_t epd)
{
epd->anon = anon_inode_getfile("scif", &scif_anon_fops, NULL, 0);
Expand Down Expand Up @@ -177,6 +202,9 @@ void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg);
int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block);
int __scif_flush(scif_epd_t epd);
int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd);
unsigned int __scif_pollfd(struct file *f, poll_table *wait,
struct scif_endpt *ep);
int __scif_pin_pages(void *addr, size_t len, int *out_prot,
int map_flags, scif_pinned_pages_t *pages);
#endif /* SCIF_EPD_H */
Loading

0 comments on commit d182432

Please sign in to comment.