mei: bus: simplify how we build nfc bus name
[firefly-linux-kernel-4.4.55.git] / drivers / misc / mei / bus-fixup.c
1 /*
2  *
3  * Intel Management Engine Interface (Intel MEI) Linux driver
4  * Copyright (c) 2003-2013, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/sched.h>
19 #include <linux/module.h>
20 #include <linux/moduleparam.h>
21 #include <linux/device.h>
22 #include <linux/slab.h>
23 #include <linux/uuid.h>
24
25 #include <linux/mei_cl_bus.h>
26
27 #include "mei_dev.h"
28 #include "client.h"
29
30 #define MEI_UUID_NFC_INFO UUID_LE(0xd2de1625, 0x382d, 0x417d, \
31                         0x48, 0xa4, 0xef, 0xab, 0xba, 0x8a, 0x12, 0x06)
32
33 #define MEI_UUID_ANY NULL_UUID_LE
34
35 /**
36  * number_of_connections - determine whether an client be on the bus
37  *    according number of connections
38  *    We support only clients:
39  *       1. with single connection
40  *       2. and fixed clients (max_number_of_connections == 0)
41  *
42  * @cldev: me clients device
43  */
44 static void number_of_connections(struct mei_cl_device *cldev)
45 {
46         dev_dbg(&cldev->dev, "running hook %s on %pUl\n",
47                         __func__, mei_me_cl_uuid(cldev->me_cl));
48
49         if (cldev->me_cl->props.max_number_of_connections > 1)
50                 cldev->do_match = 0;
51 }
52
53 /**
54  * blacklist - blacklist a client from the bus
55  *
56  * @cldev: me clients device
57  */
58 static void blacklist(struct mei_cl_device *cldev)
59 {
60         dev_dbg(&cldev->dev, "running hook %s on %pUl\n",
61                         __func__, mei_me_cl_uuid(cldev->me_cl));
62         cldev->do_match = 0;
63 }
64
65 struct mei_nfc_cmd {
66         u8 command;
67         u8 status;
68         u16 req_id;
69         u32 reserved;
70         u16 data_size;
71         u8 sub_command;
72         u8 data[];
73 } __packed;
74
75 struct mei_nfc_reply {
76         u8 command;
77         u8 status;
78         u16 req_id;
79         u32 reserved;
80         u16 data_size;
81         u8 sub_command;
82         u8 reply_status;
83         u8 data[];
84 } __packed;
85
86 struct mei_nfc_if_version {
87         u8 radio_version_sw[3];
88         u8 reserved[3];
89         u8 radio_version_hw[3];
90         u8 i2c_addr;
91         u8 fw_ivn;
92         u8 vendor_id;
93         u8 radio_type;
94 } __packed;
95
96 struct mei_nfc_connect {
97         u8 fw_ivn;
98         u8 vendor_id;
99 } __packed;
100
101 struct mei_nfc_connect_resp {
102         u8 fw_ivn;
103         u8 vendor_id;
104         u16 me_major;
105         u16 me_minor;
106         u16 me_hotfix;
107         u16 me_build;
108 } __packed;
109
110 struct mei_nfc_hci_hdr {
111         u8 cmd;
112         u8 status;
113         u16 req_id;
114         u32 reserved;
115         u16 data_size;
116 } __packed;
117
118 #define MEI_NFC_CMD_MAINTENANCE 0x00
119 #define MEI_NFC_CMD_HCI_SEND 0x01
120 #define MEI_NFC_CMD_HCI_RECV 0x02
121
122 #define MEI_NFC_SUBCMD_CONNECT    0x00
123 #define MEI_NFC_SUBCMD_IF_VERSION 0x01
124
125 #define MEI_NFC_HEADER_SIZE 10
126
127 /**
128  * struct mei_nfc_dev - NFC mei device
129  *
130  * @me_cl: NFC me client
131  * @cl: NFC host client
132  * @cl_info: NFC info host client
133  * @init_work: perform connection to the info client
134  * @fw_ivn: NFC Interface Version Number
135  * @vendor_id: NFC manufacturer ID
136  * @radio_type: NFC radio type
137  * @bus_name: bus name
138  *
139  */
140 struct mei_nfc_dev {
141         struct mei_me_client *me_cl;
142         struct mei_cl *cl;
143         struct mei_cl *cl_info;
144         struct work_struct init_work;
145         u8 fw_ivn;
146         u8 vendor_id;
147         u8 radio_type;
148         const char *bus_name;
149 };
150
151 /* UUIDs for NFC F/W clients */
152 const uuid_le mei_nfc_guid = UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50,
153                                      0x94, 0xd4, 0x50, 0x26,
154                                      0x67, 0x23, 0x77, 0x5c);
155
156 static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO;
157
158 /* Vendors */
159 #define MEI_NFC_VENDOR_INSIDE 0x00
160 #define MEI_NFC_VENDOR_NXP    0x01
161
162 /* Radio types */
163 #define MEI_NFC_VENDOR_INSIDE_UREAD 0x00
164 #define MEI_NFC_VENDOR_NXP_PN544    0x01
165
166 static void mei_nfc_free(struct mei_nfc_dev *ndev)
167 {
168         if (!ndev)
169                 return;
170
171         if (ndev->cl) {
172                 list_del(&ndev->cl->device_link);
173                 mei_cl_unlink(ndev->cl);
174                 kfree(ndev->cl);
175         }
176
177         if (ndev->cl_info) {
178                 list_del(&ndev->cl_info->device_link);
179                 mei_cl_unlink(ndev->cl_info);
180                 kfree(ndev->cl_info);
181         }
182
183         mei_me_cl_put(ndev->me_cl);
184         kfree(ndev);
185 }
186
187 /**
188  * mei_nfc_if_version - get NFC interface version
189  *
190  * @cl: host client (nfc info)
191  * @ver: NFC interface version to be filled in
192  *
193  * Return: 0 on success; < 0 otherwise
194  */
195 static int mei_nfc_if_version(struct mei_cl *cl,
196                               struct mei_nfc_if_version *ver)
197 {
198         struct mei_device *bus;
199         struct mei_nfc_cmd cmd = {
200                 .command = MEI_NFC_CMD_MAINTENANCE,
201                 .data_size = 1,
202                 .sub_command = MEI_NFC_SUBCMD_IF_VERSION,
203         };
204         struct mei_nfc_reply *reply = NULL;
205         size_t if_version_length;
206         int bytes_recv, ret;
207
208         bus = cl->dev;
209
210         WARN_ON(mutex_is_locked(&bus->device_lock));
211
212         ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd), 1);
213         if (ret < 0) {
214                 dev_err(bus->dev, "Could not send IF version cmd\n");
215                 return ret;
216         }
217
218         /* to be sure on the stack we alloc memory */
219         if_version_length = sizeof(struct mei_nfc_reply) +
220                 sizeof(struct mei_nfc_if_version);
221
222         reply = kzalloc(if_version_length, GFP_KERNEL);
223         if (!reply)
224                 return -ENOMEM;
225
226         ret = 0;
227         bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
228         if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
229                 dev_err(bus->dev, "Could not read IF version\n");
230                 ret = -EIO;
231                 goto err;
232         }
233
234         memcpy(ver, reply->data, sizeof(struct mei_nfc_if_version));
235
236         dev_info(bus->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
237                 ver->fw_ivn, ver->vendor_id, ver->radio_type);
238
239 err:
240         kfree(reply);
241         return ret;
242 }
243
244 /**
245  * mei_nfc_radio_name - derive nfc radio name from the interface version
246  *
247  * @ver: NFC radio version
248  *
249  * Return: radio name string
250  */
251 static const char *mei_nfc_radio_name(struct mei_nfc_if_version *ver)
252 {
253
254         if (ver->vendor_id == MEI_NFC_VENDOR_INSIDE) {
255                 if (ver->radio_type == MEI_NFC_VENDOR_INSIDE_UREAD)
256                         return "microread";
257         }
258
259         if (ver->vendor_id == MEI_NFC_VENDOR_NXP) {
260                 if (ver->radio_type == MEI_NFC_VENDOR_NXP_PN544)
261                         return "pn544";
262         }
263
264         return NULL;
265 }
266
267 static void mei_nfc_init(struct work_struct *work)
268 {
269         struct mei_device *bus;
270         struct mei_cl_device *cldev;
271         struct mei_nfc_dev *ndev;
272         struct mei_cl *cl_info;
273         struct mei_me_client *me_cl_info;
274         struct mei_nfc_if_version version;
275
276         ndev = container_of(work, struct mei_nfc_dev, init_work);
277
278         cl_info = ndev->cl_info;
279         bus = cl_info->dev;
280
281         mutex_lock(&bus->device_lock);
282
283         /* check for valid client id */
284         me_cl_info = mei_me_cl_by_uuid(bus, &mei_nfc_info_guid);
285         if (!me_cl_info) {
286                 mutex_unlock(&bus->device_lock);
287                 dev_info(bus->dev, "nfc: failed to find the info client\n");
288                 goto err;
289         }
290
291         if (mei_cl_connect(cl_info, me_cl_info, NULL) < 0) {
292                 mei_me_cl_put(me_cl_info);
293                 mutex_unlock(&bus->device_lock);
294                 dev_err(bus->dev, "Could not connect to the NFC INFO ME client");
295
296                 goto err;
297         }
298         mei_me_cl_put(me_cl_info);
299         mutex_unlock(&bus->device_lock);
300
301         if (mei_nfc_if_version(cl_info, &version) < 0) {
302                 dev_err(bus->dev, "Could not get the NFC interface version");
303
304                 goto err;
305         }
306
307         ndev->fw_ivn = version.fw_ivn;
308         ndev->vendor_id = version.vendor_id;
309         ndev->radio_type = version.radio_type;
310
311         dev_info(bus->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
312                 ndev->fw_ivn, ndev->vendor_id, ndev->radio_type);
313
314         mutex_lock(&bus->device_lock);
315
316         if (mei_cl_disconnect(cl_info) < 0) {
317                 mutex_unlock(&bus->device_lock);
318                 dev_err(bus->dev, "Could not disconnect the NFC INFO ME client");
319
320                 goto err;
321         }
322
323         mutex_unlock(&bus->device_lock);
324
325         ndev->bus_name = mei_nfc_radio_name(&version);
326
327         if (!ndev->bus_name) {
328                 dev_err(bus->dev, "Could not build the bus ID name\n");
329                 return;
330         }
331
332         cldev = mei_cl_add_device(bus, ndev->me_cl, ndev->cl,
333                                   ndev->bus_name);
334         if (!cldev) {
335                 dev_err(bus->dev, "Could not add the NFC device to the MEI bus\n");
336
337                 goto err;
338         }
339
340         cldev->priv_data = ndev;
341
342
343         return;
344
345 err:
346         mutex_lock(&bus->device_lock);
347         mei_nfc_free(ndev);
348         mutex_unlock(&bus->device_lock);
349
350 }
351
352
353 int mei_nfc_host_init(struct mei_device *bus, struct mei_me_client *me_cl)
354 {
355         struct mei_nfc_dev *ndev;
356         struct mei_cl *cl_info, *cl;
357         int ret;
358
359
360         /* in case of internal reset bail out
361          * as the device is already setup
362          */
363         cl = mei_cl_bus_find_cl_by_uuid(bus, mei_nfc_guid);
364         if (cl)
365                 return 0;
366
367         ndev = kzalloc(sizeof(struct mei_nfc_dev), GFP_KERNEL);
368         if (!ndev) {
369                 ret = -ENOMEM;
370                 goto err;
371         }
372
373         ndev->me_cl = mei_me_cl_get(me_cl);
374         if (!ndev->me_cl) {
375                 ret = -ENODEV;
376                 goto err;
377         }
378
379         cl_info = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY);
380         if (IS_ERR(cl_info)) {
381                 ret = PTR_ERR(cl_info);
382                 goto err;
383         }
384
385         list_add_tail(&cl_info->device_link, &bus->device_list);
386
387         ndev->cl_info = cl_info;
388
389         cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY);
390         if (IS_ERR(cl)) {
391                 ret = PTR_ERR(cl);
392                 goto err;
393         }
394
395         list_add_tail(&cl->device_link, &bus->device_list);
396
397         ndev->cl = cl;
398
399         INIT_WORK(&ndev->init_work, mei_nfc_init);
400         schedule_work(&ndev->init_work);
401
402         return 0;
403
404 err:
405         mei_nfc_free(ndev);
406
407         return ret;
408 }
409
410 void mei_nfc_host_exit(struct mei_device *bus)
411 {
412         struct mei_nfc_dev *ndev;
413         struct mei_cl *cl;
414         struct mei_cl_device *cldev;
415
416         cl = mei_cl_bus_find_cl_by_uuid(bus, mei_nfc_guid);
417         if (!cl)
418                 return;
419
420         cldev = cl->cldev;
421         if (!cldev)
422                 return;
423
424         ndev = (struct mei_nfc_dev *)cldev->priv_data;
425         if (ndev)
426                 cancel_work_sync(&ndev->init_work);
427
428         cldev->priv_data = NULL;
429
430         /* Need to remove the device here
431          * since mei_nfc_free will unlink the clients
432          */
433         mei_cl_remove_device(cldev);
434
435         mutex_lock(&bus->device_lock);
436         mei_nfc_free(ndev);
437         mutex_unlock(&bus->device_lock);
438 }
439
440 #define MEI_FIXUP(_uuid, _hook) { _uuid, _hook }
441
442 static struct mei_fixup {
443
444         const uuid_le uuid;
445         void (*hook)(struct mei_cl_device *cldev);
446 } mei_fixups[] = {
447         MEI_FIXUP(MEI_UUID_ANY, number_of_connections),
448         MEI_FIXUP(MEI_UUID_NFC_INFO, blacklist),
449 };
450
451 /**
452  * mei_cl_dev_fixup - run fixup handlers
453  *
454  * @cldev: me client device
455  */
456 void mei_cl_dev_fixup(struct mei_cl_device *cldev)
457 {
458         struct mei_fixup *f;
459         const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
460         int i;
461
462         for (i = 0; i < ARRAY_SIZE(mei_fixups); i++) {
463
464                 f = &mei_fixups[i];
465                 if (uuid_le_cmp(f->uuid, MEI_UUID_ANY) == 0 ||
466                     uuid_le_cmp(f->uuid, *uuid) == 0)
467                         f->hook(cldev);
468         }
469 }
470