blob: 2d7246887547255fcfe25d826e69eaafdb0d7b74 [file] [log] [blame]
Viresh Kumarcca22202016-04-28 10:06:38 +05301/*
2 * Greybus Firmware Download Protocol Driver.
3 *
4 * Copyright 2016 Google Inc.
5 * Copyright 2016 Linaro Ltd.
6 *
7 * Released under the GPLv2 only.
8 */
9
10#include <linux/firmware.h>
Viresh Kumar69c87632016-05-05 15:33:20 +053011#include <linux/jiffies.h>
12#include <linux/mutex.h>
Viresh Kumarc6cc8e72016-05-09 10:59:01 +053013#include <linux/workqueue.h>
Viresh Kumarcca22202016-04-28 10:06:38 +053014#include "firmware.h"
15#include "greybus.h"
16
Viresh Kumar69c87632016-05-05 15:33:20 +053017/* Estimated minimum buffer size, actual size can be smaller than this */
18#define MIN_FETCH_SIZE 512
19/* Timeout, in jiffies, within which fetch or release firmware must be called */
20#define NEXT_REQ_TIMEOUT_J msecs_to_jiffies(1000)
Viresh Kumar7557d042016-05-02 10:51:49 +053021
Viresh Kumarcca22202016-04-28 10:06:38 +053022struct fw_request {
23 u8 firmware_id;
Viresh Kumar69c87632016-05-05 15:33:20 +053024 bool disabled;
25 bool timedout;
Viresh Kumarb2abeaa2016-08-11 13:27:23 -070026 char name[FW_NAME_SIZE];
Viresh Kumarcca22202016-04-28 10:06:38 +053027 const struct firmware *fw;
28 struct list_head node;
Viresh Kumarf63a8962016-05-05 15:33:19 +053029
Viresh Kumarc6cc8e72016-05-09 10:59:01 +053030 struct delayed_work dwork;
Viresh Kumar69c87632016-05-05 15:33:20 +053031 /* Timeout, in jiffies, within which the firmware shall download */
32 unsigned long release_timeout_j;
Viresh Kumarf63a8962016-05-05 15:33:19 +053033 struct kref kref;
34 struct fw_download *fw_download;
Viresh Kumarcca22202016-04-28 10:06:38 +053035};
36
37struct fw_download {
38 struct device *parent;
39 struct gb_connection *connection;
40 struct list_head fw_requests;
41 struct ida id_map;
Viresh Kumar69c87632016-05-05 15:33:20 +053042 struct mutex mutex;
Viresh Kumarcca22202016-04-28 10:06:38 +053043};
44
Viresh Kumarf63a8962016-05-05 15:33:19 +053045static void fw_req_release(struct kref *kref)
46{
47 struct fw_request *fw_req = container_of(kref, struct fw_request, kref);
48
49 dev_dbg(fw_req->fw_download->parent, "firmware %s released\n",
50 fw_req->name);
51
52 release_firmware(fw_req->fw);
Viresh Kumar69c87632016-05-05 15:33:20 +053053
54 /*
55 * The request timed out and the module may send a fetch-fw or
56 * release-fw request later. Lets block the id we allocated for this
57 * request, so that the AP doesn't refer to a later fw-request (with
58 * same firmware_id) for the old timedout fw-request.
59 *
60 * NOTE:
61 *
62 * This also means that after 255 timeouts we will fail to service new
63 * firmware downloads. But what else can we do in that case anyway? Lets
64 * just hope that it never happens.
65 */
66 if (!fw_req->timedout)
67 ida_simple_remove(&fw_req->fw_download->id_map,
68 fw_req->firmware_id);
69
Viresh Kumarf63a8962016-05-05 15:33:19 +053070 kfree(fw_req);
71}
72
Viresh Kumar69c87632016-05-05 15:33:20 +053073/*
74 * Incoming requests are serialized for a connection, and the only race possible
75 * is between the timeout handler freeing this and an incoming request.
76 *
77 * The operations on the fw-request list are protected by the mutex and
78 * get_fw_req() increments the reference count before returning a fw_req pointer
79 * to the users.
80 *
81 * free_firmware() also takes the mutex while removing an entry from the list,
82 * it guarantees that every user of fw_req has taken a kref-reference by now and
83 * we wouldn't have any new users.
84 *
85 * Once the last user drops the reference, the fw_req structure is freed.
86 */
87static void put_fw_req(struct fw_request *fw_req)
88{
89 kref_put(&fw_req->kref, fw_req_release);
90}
91
Viresh Kumarf63a8962016-05-05 15:33:19 +053092/* Caller must call put_fw_req() after using struct fw_request */
93static struct fw_request *get_fw_req(struct fw_download *fw_download,
94 u8 firmware_id)
Viresh Kumarcca22202016-04-28 10:06:38 +053095{
96 struct fw_request *fw_req;
97
Viresh Kumar69c87632016-05-05 15:33:20 +053098 mutex_lock(&fw_download->mutex);
99
Viresh Kumarcca22202016-04-28 10:06:38 +0530100 list_for_each_entry(fw_req, &fw_download->fw_requests, node) {
Viresh Kumarf63a8962016-05-05 15:33:19 +0530101 if (fw_req->firmware_id == firmware_id) {
102 kref_get(&fw_req->kref);
Viresh Kumar69c87632016-05-05 15:33:20 +0530103 goto unlock;
Viresh Kumarf63a8962016-05-05 15:33:19 +0530104 }
Viresh Kumarcca22202016-04-28 10:06:38 +0530105 }
106
Viresh Kumar69c87632016-05-05 15:33:20 +0530107 fw_req = NULL;
Viresh Kumarcca22202016-04-28 10:06:38 +0530108
Viresh Kumar69c87632016-05-05 15:33:20 +0530109unlock:
110 mutex_unlock(&fw_download->mutex);
111
112 return fw_req;
Viresh Kumarf63a8962016-05-05 15:33:19 +0530113}
114
Viresh Kumarcca22202016-04-28 10:06:38 +0530115static void free_firmware(struct fw_download *fw_download,
116 struct fw_request *fw_req)
117{
Viresh Kumar69c87632016-05-05 15:33:20 +0530118 /* Already disabled from timeout handlers */
119 if (fw_req->disabled)
120 return;
Viresh Kumarf63a8962016-05-05 15:33:19 +0530121
Viresh Kumar69c87632016-05-05 15:33:20 +0530122 mutex_lock(&fw_download->mutex);
123 list_del(&fw_req->node);
124 mutex_unlock(&fw_download->mutex);
125
126 fw_req->disabled = true;
Viresh Kumarf63a8962016-05-05 15:33:19 +0530127 put_fw_req(fw_req);
Viresh Kumarcca22202016-04-28 10:06:38 +0530128}
129
Viresh Kumarc6cc8e72016-05-09 10:59:01 +0530130static void fw_request_timedout(struct work_struct *work)
Viresh Kumar69c87632016-05-05 15:33:20 +0530131{
Viresh Kumarc6cc8e72016-05-09 10:59:01 +0530132 struct delayed_work *dwork = to_delayed_work(work);
133 struct fw_request *fw_req = container_of(dwork, struct fw_request, dwork);
Viresh Kumar69c87632016-05-05 15:33:20 +0530134 struct fw_download *fw_download = fw_req->fw_download;
135
136 dev_err(fw_download->parent,
137 "Timed out waiting for fetch / release firmware requests: %u\n",
138 fw_req->firmware_id);
139
140 fw_req->timedout = true;
141 free_firmware(fw_download, fw_req);
142}
143
144static int exceeds_release_timeout(struct fw_request *fw_req)
145{
146 struct fw_download *fw_download = fw_req->fw_download;
147
148 if (time_before(jiffies, fw_req->release_timeout_j))
149 return 0;
150
151 dev_err(fw_download->parent,
152 "Firmware download didn't finish in time, abort: %d\n",
153 fw_req->firmware_id);
154
155 fw_req->timedout = true;
156 free_firmware(fw_download, fw_req);
157
158 return -ETIMEDOUT;
159}
160
Viresh Kumarcca22202016-04-28 10:06:38 +0530161/* This returns path of the firmware blob on the disk */
162static struct fw_request *find_firmware(struct fw_download *fw_download,
163 const char *tag)
164{
165 struct gb_interface *intf = fw_download->connection->bundle->intf;
166 struct fw_request *fw_req;
Viresh Kumar69c87632016-05-05 15:33:20 +0530167 int ret, req_count;
Viresh Kumarcca22202016-04-28 10:06:38 +0530168
169 fw_req = kzalloc(sizeof(*fw_req), GFP_KERNEL);
170 if (!fw_req)
171 return ERR_PTR(-ENOMEM);
172
173 /* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */
174 ret = ida_simple_get(&fw_download->id_map, 1, 256, GFP_KERNEL);
175 if (ret < 0) {
176 dev_err(fw_download->parent,
177 "failed to allocate firmware id (%d)\n", ret);
178 goto err_free_req;
179 }
180 fw_req->firmware_id = ret;
181
182 snprintf(fw_req->name, sizeof(fw_req->name),
Greg Kroah-Hartman8a704562016-07-20 10:11:37 -0700183 FW_NAME_PREFIX "%08x_%08x_%08x_%08x_%s.tftf",
Viresh Kumarcca22202016-04-28 10:06:38 +0530184 intf->ddbl1_manufacturer_id, intf->ddbl1_product_id,
185 intf->vendor_id, intf->product_id, tag);
186
187 dev_info(fw_download->parent, "Requested firmware package '%s'\n",
188 fw_req->name);
189
190 ret = request_firmware(&fw_req->fw, fw_req->name, fw_download->parent);
191 if (ret) {
192 dev_err(fw_download->parent,
193 "firmware request failed for %s (%d)\n", fw_req->name,
194 ret);
195 goto err_free_id;
196 }
197
Viresh Kumarf63a8962016-05-05 15:33:19 +0530198 fw_req->fw_download = fw_download;
199 kref_init(&fw_req->kref);
Viresh Kumar69c87632016-05-05 15:33:20 +0530200
201 mutex_lock(&fw_download->mutex);
Viresh Kumarcca22202016-04-28 10:06:38 +0530202 list_add(&fw_req->node, &fw_download->fw_requests);
Viresh Kumar69c87632016-05-05 15:33:20 +0530203 mutex_unlock(&fw_download->mutex);
204
205 /* Timeout, in jiffies, within which firmware should get loaded */
206 req_count = DIV_ROUND_UP(fw_req->fw->size, MIN_FETCH_SIZE);
207 fw_req->release_timeout_j = jiffies + req_count * NEXT_REQ_TIMEOUT_J;
208
Viresh Kumarc6cc8e72016-05-09 10:59:01 +0530209 INIT_DELAYED_WORK(&fw_req->dwork, fw_request_timedout);
210 schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J);
Viresh Kumarcca22202016-04-28 10:06:38 +0530211
212 return fw_req;
213
214err_free_id:
215 ida_simple_remove(&fw_download->id_map, fw_req->firmware_id);
216err_free_req:
217 kfree(fw_req);
218
219 return ERR_PTR(ret);
220}
221
222static int fw_download_find_firmware(struct gb_operation *op)
223{
224 struct gb_connection *connection = op->connection;
225 struct fw_download *fw_download = gb_connection_get_data(connection);
226 struct gb_fw_download_find_firmware_request *request;
227 struct gb_fw_download_find_firmware_response *response;
228 struct fw_request *fw_req;
229 const char *tag;
230
231 if (op->request->payload_size != sizeof(*request)) {
232 dev_err(fw_download->parent,
233 "illegal size of find firmware request (%zu != %zu)\n",
234 op->request->payload_size, sizeof(*request));
235 return -EINVAL;
236 }
237
238 request = op->request->payload;
Viresh Kumar769cb832016-08-11 13:27:22 -0700239 tag = (const char *)request->firmware_tag;
Viresh Kumarcca22202016-04-28 10:06:38 +0530240
Viresh Kumar06753632016-08-11 13:27:24 -0700241 /* firmware_tag must be null-terminated */
Viresh Kumarb2abeaa2016-08-11 13:27:23 -0700242 if (strnlen(tag, GB_FIRMWARE_TAG_MAX_SIZE) == GB_FIRMWARE_TAG_MAX_SIZE) {
Viresh Kumarcca22202016-04-28 10:06:38 +0530243 dev_err(fw_download->parent,
244 "firmware-tag is not null-terminated\n");
245 return -EINVAL;
246 }
247
Viresh Kumar295b5262016-08-10 10:48:31 -0700248 fw_req = find_firmware(fw_download, tag);
Viresh Kumarcca22202016-04-28 10:06:38 +0530249 if (IS_ERR(fw_req))
250 return PTR_ERR(fw_req);
251
252 if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) {
253 dev_err(fw_download->parent, "error allocating response\n");
254 free_firmware(fw_download, fw_req);
255 return -ENOMEM;
256 }
257
258 response = op->response->payload;
259 response->firmware_id = fw_req->firmware_id;
260 response->size = cpu_to_le32(fw_req->fw->size);
261
262 dev_dbg(fw_download->parent,
263 "firmware size is %zu bytes\n", fw_req->fw->size);
264
265 return 0;
266}
267
268static int fw_download_fetch_firmware(struct gb_operation *op)
269{
270 struct gb_connection *connection = op->connection;
271 struct fw_download *fw_download = gb_connection_get_data(connection);
272 struct gb_fw_download_fetch_firmware_request *request;
273 struct gb_fw_download_fetch_firmware_response *response;
274 struct fw_request *fw_req;
275 const struct firmware *fw;
276 unsigned int offset, size;
277 u8 firmware_id;
Viresh Kumarf63a8962016-05-05 15:33:19 +0530278 int ret = 0;
Viresh Kumarcca22202016-04-28 10:06:38 +0530279
280 if (op->request->payload_size != sizeof(*request)) {
281 dev_err(fw_download->parent,
282 "Illegal size of fetch firmware request (%zu %zu)\n",
283 op->request->payload_size, sizeof(*request));
284 return -EINVAL;
285 }
286
287 request = op->request->payload;
288 offset = le32_to_cpu(request->offset);
289 size = le32_to_cpu(request->size);
290 firmware_id = request->firmware_id;
291
Viresh Kumarf63a8962016-05-05 15:33:19 +0530292 fw_req = get_fw_req(fw_download, firmware_id);
Viresh Kumarcca22202016-04-28 10:06:38 +0530293 if (!fw_req) {
294 dev_err(fw_download->parent,
295 "firmware not available for id: %02u\n", firmware_id);
296 return -EINVAL;
297 }
298
Viresh Kumarc6cc8e72016-05-09 10:59:01 +0530299 /* Make sure work handler isn't running in parallel */
300 cancel_delayed_work_sync(&fw_req->dwork);
Viresh Kumar69c87632016-05-05 15:33:20 +0530301
302 /* We timed-out before reaching here ? */
303 if (fw_req->disabled) {
304 ret = -ETIMEDOUT;
305 goto put_fw;
306 }
307
308 /*
309 * Firmware download must finish within a limited time interval. If it
310 * doesn't, then we might have a buggy Module on the other side. Abort
311 * download.
312 */
313 ret = exceeds_release_timeout(fw_req);
314 if (ret)
315 goto put_fw;
316
Viresh Kumarcca22202016-04-28 10:06:38 +0530317 fw = fw_req->fw;
318
319 if (offset >= fw->size || size > fw->size - offset) {
320 dev_err(fw_download->parent,
321 "bad fetch firmware request (offs = %u, size = %u)\n",
322 offset, size);
Viresh Kumarf63a8962016-05-05 15:33:19 +0530323 ret = -EINVAL;
324 goto put_fw;
Viresh Kumarcca22202016-04-28 10:06:38 +0530325 }
326
327 if (!gb_operation_response_alloc(op, sizeof(*response) + size,
328 GFP_KERNEL)) {
329 dev_err(fw_download->parent,
330 "error allocating fetch firmware response\n");
Viresh Kumarf63a8962016-05-05 15:33:19 +0530331 ret = -ENOMEM;
332 goto put_fw;
Viresh Kumarcca22202016-04-28 10:06:38 +0530333 }
334
335 response = op->response->payload;
336 memcpy(response->data, fw->data + offset, size);
337
338 dev_dbg(fw_download->parent,
339 "responding with firmware (offs = %u, size = %u)\n", offset,
340 size);
341
Viresh Kumar69c87632016-05-05 15:33:20 +0530342 /* Refresh timeout */
Viresh Kumarc6cc8e72016-05-09 10:59:01 +0530343 schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J);
Viresh Kumar69c87632016-05-05 15:33:20 +0530344
Viresh Kumarf63a8962016-05-05 15:33:19 +0530345put_fw:
346 put_fw_req(fw_req);
347
348 return ret;
Viresh Kumarcca22202016-04-28 10:06:38 +0530349}
350
351static int fw_download_release_firmware(struct gb_operation *op)
352{
353 struct gb_connection *connection = op->connection;
354 struct fw_download *fw_download = gb_connection_get_data(connection);
355 struct gb_fw_download_release_firmware_request *request;
356 struct fw_request *fw_req;
357 u8 firmware_id;
358
359 if (op->request->payload_size != sizeof(*request)) {
360 dev_err(fw_download->parent,
361 "Illegal size of release firmware request (%zu %zu)\n",
362 op->request->payload_size, sizeof(*request));
363 return -EINVAL;
364 }
365
366 request = op->request->payload;
367 firmware_id = request->firmware_id;
368
Viresh Kumarf63a8962016-05-05 15:33:19 +0530369 fw_req = get_fw_req(fw_download, firmware_id);
Viresh Kumarcca22202016-04-28 10:06:38 +0530370 if (!fw_req) {
371 dev_err(fw_download->parent,
372 "firmware not available for id: %02u\n", firmware_id);
373 return -EINVAL;
374 }
375
Viresh Kumarc6cc8e72016-05-09 10:59:01 +0530376 cancel_delayed_work_sync(&fw_req->dwork);
Viresh Kumar69c87632016-05-05 15:33:20 +0530377
Viresh Kumarcca22202016-04-28 10:06:38 +0530378 free_firmware(fw_download, fw_req);
Viresh Kumarf63a8962016-05-05 15:33:19 +0530379 put_fw_req(fw_req);
Viresh Kumarcca22202016-04-28 10:06:38 +0530380
381 dev_dbg(fw_download->parent, "release firmware\n");
382
383 return 0;
384}
385
386int gb_fw_download_request_handler(struct gb_operation *op)
387{
388 u8 type = op->type;
389
390 switch (type) {
391 case GB_FW_DOWNLOAD_TYPE_FIND_FIRMWARE:
392 return fw_download_find_firmware(op);
393 case GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE:
394 return fw_download_fetch_firmware(op);
395 case GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE:
396 return fw_download_release_firmware(op);
397 default:
398 dev_err(&op->connection->bundle->dev,
399 "unsupported request: %u\n", type);
400 return -EINVAL;
401 }
402}
403
404int gb_fw_download_connection_init(struct gb_connection *connection)
405{
406 struct fw_download *fw_download;
407 int ret;
408
409 if (!connection)
410 return 0;
411
412 fw_download = kzalloc(sizeof(*fw_download), GFP_KERNEL);
413 if (!fw_download)
414 return -ENOMEM;
415
416 fw_download->parent = &connection->bundle->dev;
417 INIT_LIST_HEAD(&fw_download->fw_requests);
418 ida_init(&fw_download->id_map);
419 gb_connection_set_data(connection, fw_download);
420 fw_download->connection = connection;
Viresh Kumar69c87632016-05-05 15:33:20 +0530421 mutex_init(&fw_download->mutex);
Viresh Kumarcca22202016-04-28 10:06:38 +0530422
423 ret = gb_connection_enable(connection);
424 if (ret)
425 goto err_destroy_id_map;
426
427 return 0;
428
429err_destroy_id_map:
430 ida_destroy(&fw_download->id_map);
431 kfree(fw_download);
432
433 return ret;
434}
435
436void gb_fw_download_connection_exit(struct gb_connection *connection)
437{
438 struct fw_download *fw_download;
439 struct fw_request *fw_req, *tmp;
440
441 if (!connection)
442 return;
443
444 fw_download = gb_connection_get_data(connection);
445 gb_connection_disable(fw_download->connection);
446
Viresh Kumar69c87632016-05-05 15:33:20 +0530447 /*
448 * Make sure we have a reference to the pending requests, before they
449 * are freed from the timeout handler.
450 */
451 mutex_lock(&fw_download->mutex);
452 list_for_each_entry(fw_req, &fw_download->fw_requests, node)
453 kref_get(&fw_req->kref);
454 mutex_unlock(&fw_download->mutex);
455
Viresh Kumarcca22202016-04-28 10:06:38 +0530456 /* Release pending firmware packages */
Viresh Kumar69c87632016-05-05 15:33:20 +0530457 list_for_each_entry_safe(fw_req, tmp, &fw_download->fw_requests, node) {
Viresh Kumarc6cc8e72016-05-09 10:59:01 +0530458 cancel_delayed_work_sync(&fw_req->dwork);
Viresh Kumarcca22202016-04-28 10:06:38 +0530459 free_firmware(fw_download, fw_req);
Viresh Kumar69c87632016-05-05 15:33:20 +0530460 put_fw_req(fw_req);
461 }
Viresh Kumarcca22202016-04-28 10:06:38 +0530462
463 ida_destroy(&fw_download->id_map);
464 kfree(fw_download);
465}