Updated `README.md` with instructions for building/using the kernel module.
[xeon-phi-kernel-module] / host / acptboot.c
CommitLineData
800f879a
AT
1/*
2 * Copyright 2010-2017 Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * Disclaimer: The codes contained in these modules may be specific to
14 * the Intel Software Development Platform codenamed Knights Ferry,
15 * and the Intel product codenamed Knights Corner, and are not backward
16 * compatible with other Intel products. Additionally, Intel will NOT
17 * support the codes or instruction set in future products.
18 *
19 * Intel offers no warranty of any kind regarding the code. This code is
20 * licensed on an "AS IS" basis and Intel is not obligated to provide
21 * any support, assistance, installation, training, or other services
22 * of any kind. Intel is also not obligated to provide any updates,
23 * enhancements or extensions. Intel specifically disclaims any warranty
24 * of merchantability, non-infringement, fitness for any particular
25 * purpose, and any other warranty.
26 *
27 * Further, Intel disclaims all liability of any kind, including but
28 * not limited to liability for infringement of any proprietary rights,
29 * relating to the use of the code, even if Intel is notified of the
30 * possibility of such liability. Except as expressly stated in an Intel
31 * license agreement provided with this code and agreed upon with Intel,
32 * no license, express or implied, by estoppel or otherwise, to any
33 * intellectual property rights is granted herein.
34 */
35
36#include <linux/string.h>
37#include <linux/module.h>
38#include <linux/kernel.h>
39#include <linux/err.h>
40#include <micint.h>
41
42#include <scif.h>
43#include <mic_common.h>
44
45#define ACPT_BACKLOG 120
46#define ACPT_POLL_MS 2000
47
48#define ACPT_BOOTED 1
49#define ACPT_BOOT_ACK 2
50#define ACPT_NACK_VERSION 3
51#define ACPT_REQUEST_TIME 4
52#define ACPT_TIME_DATA 5
53
54#define ACPT_VERSION 1
55
56static acptboot_data_t *acptboot_data;
57
58
59void acptboot_getconn(struct work_struct *work)
60{
61 mic_ctx_t *node_ctx;
62 struct scif_portID data;
63 scif_epd_t conn_epd;
64 struct timespec tod;
65 int proto;
66 int version;
67 int err;
68
69 if ((err = scif_accept(acptboot_data->listen_epd, &data, &conn_epd,
70 SCIF_ACCEPT_SYNC))) {
71 pr_debug("ACPTBOOT: scif_accept_failed %d\n", err);
72 return;
73
74 //goto requeue_accept;
75 }
76
77 if (!data.node) {
78 printk(KERN_ERR "ACPTBOOT: connect received from invalid dev %d\n",
79 -EINVAL);
80 goto close_epd;
81 }
82
83 if ((err = scif_recv(conn_epd, &version, sizeof(version), SCIF_RECV_BLOCK)) != sizeof(version)) {
84 printk(KERN_ERR "ACPTBOOT: failed to recieve version number err %d\n", err);
85 goto close_epd;
86 }
87
88 if ((err = scif_recv(conn_epd, &proto, sizeof(proto), SCIF_RECV_BLOCK)) != sizeof(proto)) {
89 printk(KERN_ERR "ACPTBOOT: failed to recieve proto id %d\n", err);
90 goto close_epd;
91 }
92
93 switch (proto) {
94 case ACPT_BOOTED:
95 node_ctx = get_per_dev_ctx(data.node - 1);
96 mic_setstate(node_ctx, MIC_ONLINE);
97 node_ctx->boot_count++;
98
99 proto = ACPT_BOOT_ACK;
100 scif_send(conn_epd, &proto, sizeof(proto), SCIF_SEND_BLOCK);
101 break;
102
103 case ACPT_REQUEST_TIME:
104 getnstimeofday(&tod);
105 proto = ACPT_TIME_DATA;
106 scif_send(conn_epd, &proto, sizeof(proto), SCIF_SEND_BLOCK);
107 scif_send(conn_epd, &tod, sizeof(tod), SCIF_SEND_BLOCK);
108 break;
109 }
110
111close_epd:
112 if ((err = scif_close(conn_epd)))
113 printk(KERN_ERR "ACPTBOOT: scif_close failed %d\n", err);
114
115//requeue_accept:
116 queue_work(acptboot_data->acptbootwq, &acptboot_data->acptbootwork);
117}
118
119void acptboot_exit(void)
120{
121 int err = 0;
122 if (acptboot_data) {
123 if (acptboot_data->listen_epd)
124 if ((err = scif_close(acptboot_data->listen_epd)) < 0)
125 pr_debug("scif_close failed %d\n", err);
126 destroy_workqueue(acptboot_data->acptbootwq);
127
128 kfree(acptboot_data);
129 }
130}
131
132int
133acptboot_init(void)
134{
135 int err, ret;
136
137 acptboot_data = (acptboot_data_t *)kzalloc(sizeof(*acptboot_data), GFP_KERNEL);
138
139 if (!acptboot_data) {
140 printk(KERN_ERR "ACPTBOOT: memory allocation failure\n");
141 return -ENOMEM;
142 }
143
144 acptboot_data->listen_epd = scif_open();
145
146 if (!acptboot_data->listen_epd) {
147 printk(KERN_ERR "ACPTBOOT: scif_open() failed!\n");
148 err = -ENOMEM;
149 goto error;
150 }
151
152 err = scif_bind(acptboot_data->listen_epd, MIC_NOTIFY);
153 if (err < 0) {
154 pr_debug("ACPTBOOT: scif_bind() failed! %d\n", err);
155 goto error;
156 }
157
158 acptboot_data->acptboot_pn = err;
159
160 err = scif_listen(acptboot_data->listen_epd, ACPT_BACKLOG);
161 if (err < 0) {
162 pr_debug("scif_listen() failed! %d\n", err);
163 goto error;
164
165 }
166
167 pr_debug("ACPT endpoint listening port %d\n",
168 acptboot_data->acptboot_pn);
169
170 // Create workqueue
171 acptboot_data->acptbootwq = __mic_create_singlethread_workqueue(
172 "ACPTBOOT_WQ");
173
174 if (!acptboot_data->acptbootwq) {
175 printk(KERN_ERR "%s %d wq creation failed!\n", __func__, __LINE__);
176 goto error;
177 }
178
179 INIT_WORK(&acptboot_data->acptbootwork, acptboot_getconn);
180 queue_work(acptboot_data->acptbootwq,
181 &acptboot_data->acptbootwork);
182 return 0;
183
184error:
185
186 if (acptboot_data->listen_epd)
187 if ((ret = scif_close(acptboot_data->listen_epd)) < 0)
188 pr_debug("ACPTBOOT: scif_close() failed! %d\n", ret);
189
190 kfree(acptboot_data);
191
192 return err;
193}
194