466 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Greybus Firmware Download Protocol Driver.4 *5 * Copyright 2016 Google Inc.6 * Copyright 2016 Linaro Ltd.7 */8 9#include <linux/firmware.h>10#include <linux/jiffies.h>11#include <linux/mutex.h>12#include <linux/workqueue.h>13#include <linux/greybus.h>14#include "firmware.h"15 16/* Estimated minimum buffer size, actual size can be smaller than this */17#define MIN_FETCH_SIZE 51218/* Timeout, in jiffies, within which fetch or release firmware must be called */19#define NEXT_REQ_TIMEOUT_J msecs_to_jiffies(1000)20 21struct fw_request {22 u8 firmware_id;23 bool disabled;24 bool timedout;25 char name[FW_NAME_SIZE];26 const struct firmware *fw;27 struct list_head node;28 29 struct delayed_work dwork;30 /* Timeout, in jiffies, within which the firmware shall download */31 unsigned long release_timeout_j;32 struct kref kref;33 struct fw_download *fw_download;34};35 36struct fw_download {37 struct device *parent;38 struct gb_connection *connection;39 struct list_head fw_requests;40 struct ida id_map;41 struct mutex mutex;42};43 44static void fw_req_release(struct kref *kref)45{46 struct fw_request *fw_req = container_of(kref, struct fw_request, kref);47 48 dev_dbg(fw_req->fw_download->parent, "firmware %s released\n",49 fw_req->name);50 51 release_firmware(fw_req->fw);52 53 /*54 * The request timed out and the module may send a fetch-fw or55 * release-fw request later. Lets block the id we allocated for this56 * request, so that the AP doesn't refer to a later fw-request (with57 * same firmware_id) for the old timedout fw-request.58 *59 * NOTE:60 *61 * This also means that after 255 timeouts we will fail to service new62 * firmware downloads. But what else can we do in that case anyway? Lets63 * just hope that it never happens.64 */65 if (!fw_req->timedout)66 ida_free(&fw_req->fw_download->id_map, fw_req->firmware_id);67 68 kfree(fw_req);69}70 71/*72 * Incoming requests are serialized for a connection, and the only race possible73 * is between the timeout handler freeing this and an incoming request.74 *75 * The operations on the fw-request list are protected by the mutex and76 * get_fw_req() increments the reference count before returning a fw_req pointer77 * to the users.78 *79 * free_firmware() also takes the mutex while removing an entry from the list,80 * it guarantees that every user of fw_req has taken a kref-reference by now and81 * we wouldn't have any new users.82 *83 * Once the last user drops the reference, the fw_req structure is freed.84 */85static void put_fw_req(struct fw_request *fw_req)86{87 kref_put(&fw_req->kref, fw_req_release);88}89 90/* Caller must call put_fw_req() after using struct fw_request */91static struct fw_request *get_fw_req(struct fw_download *fw_download,92 u8 firmware_id)93{94 struct fw_request *fw_req;95 96 mutex_lock(&fw_download->mutex);97 98 list_for_each_entry(fw_req, &fw_download->fw_requests, node) {99 if (fw_req->firmware_id == firmware_id) {100 kref_get(&fw_req->kref);101 goto unlock;102 }103 }104 105 fw_req = NULL;106 107unlock:108 mutex_unlock(&fw_download->mutex);109 110 return fw_req;111}112 113static void free_firmware(struct fw_download *fw_download,114 struct fw_request *fw_req)115{116 /* Already disabled from timeout handlers */117 if (fw_req->disabled)118 return;119 120 mutex_lock(&fw_download->mutex);121 list_del(&fw_req->node);122 mutex_unlock(&fw_download->mutex);123 124 fw_req->disabled = true;125 put_fw_req(fw_req);126}127 128static void fw_request_timedout(struct work_struct *work)129{130 struct delayed_work *dwork = to_delayed_work(work);131 struct fw_request *fw_req = container_of(dwork,132 struct fw_request, dwork);133 struct fw_download *fw_download = fw_req->fw_download;134 135 dev_err(fw_download->parent,136 "Timed out waiting for fetch / release firmware requests: %u\n",137 fw_req->firmware_id);138 139 fw_req->timedout = true;140 free_firmware(fw_download, fw_req);141}142 143static int exceeds_release_timeout(struct fw_request *fw_req)144{145 struct fw_download *fw_download = fw_req->fw_download;146 147 if (time_before(jiffies, fw_req->release_timeout_j))148 return 0;149 150 dev_err(fw_download->parent,151 "Firmware download didn't finish in time, abort: %d\n",152 fw_req->firmware_id);153 154 fw_req->timedout = true;155 free_firmware(fw_download, fw_req);156 157 return -ETIMEDOUT;158}159 160/* This returns path of the firmware blob on the disk */161static struct fw_request *find_firmware(struct fw_download *fw_download,162 const char *tag)163{164 struct gb_interface *intf = fw_download->connection->bundle->intf;165 struct fw_request *fw_req;166 int ret, req_count;167 168 fw_req = kzalloc(sizeof(*fw_req), GFP_KERNEL);169 if (!fw_req)170 return ERR_PTR(-ENOMEM);171 172 /* Allocate ids from 1 to 255 (u8-max), 0 is an invalid id */173 ret = ida_alloc_range(&fw_download->id_map, 1, 255, GFP_KERNEL);174 if (ret < 0) {175 dev_err(fw_download->parent,176 "failed to allocate firmware id (%d)\n", ret);177 goto err_free_req;178 }179 fw_req->firmware_id = ret;180 181 snprintf(fw_req->name, sizeof(fw_req->name),182 FW_NAME_PREFIX "%08x_%08x_%08x_%08x_%s.tftf",183 intf->ddbl1_manufacturer_id, intf->ddbl1_product_id,184 intf->vendor_id, intf->product_id, tag);185 186 dev_info(fw_download->parent, "Requested firmware package '%s'\n",187 fw_req->name);188 189 ret = request_firmware(&fw_req->fw, fw_req->name, fw_download->parent);190 if (ret) {191 dev_err(fw_download->parent,192 "firmware request failed for %s (%d)\n", fw_req->name,193 ret);194 goto err_free_id;195 }196 197 fw_req->fw_download = fw_download;198 kref_init(&fw_req->kref);199 200 mutex_lock(&fw_download->mutex);201 list_add(&fw_req->node, &fw_download->fw_requests);202 mutex_unlock(&fw_download->mutex);203 204 /* Timeout, in jiffies, within which firmware should get loaded */205 req_count = DIV_ROUND_UP(fw_req->fw->size, MIN_FETCH_SIZE);206 fw_req->release_timeout_j = jiffies + req_count * NEXT_REQ_TIMEOUT_J;207 208 INIT_DELAYED_WORK(&fw_req->dwork, fw_request_timedout);209 schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J);210 211 return fw_req;212 213err_free_id:214 ida_free(&fw_download->id_map, fw_req->firmware_id);215err_free_req:216 kfree(fw_req);217 218 return ERR_PTR(ret);219}220 221static int fw_download_find_firmware(struct gb_operation *op)222{223 struct gb_connection *connection = op->connection;224 struct fw_download *fw_download = gb_connection_get_data(connection);225 struct gb_fw_download_find_firmware_request *request;226 struct gb_fw_download_find_firmware_response *response;227 struct fw_request *fw_req;228 const char *tag;229 230 if (op->request->payload_size != sizeof(*request)) {231 dev_err(fw_download->parent,232 "illegal size of find firmware request (%zu != %zu)\n",233 op->request->payload_size, sizeof(*request));234 return -EINVAL;235 }236 237 request = op->request->payload;238 tag = (const char *)request->firmware_tag;239 240 /* firmware_tag must be null-terminated */241 if (strnlen(tag, GB_FIRMWARE_TAG_MAX_SIZE) ==242 GB_FIRMWARE_TAG_MAX_SIZE) {243 dev_err(fw_download->parent,244 "firmware-tag is not null-terminated\n");245 return -EINVAL;246 }247 248 fw_req = find_firmware(fw_download, tag);249 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 fw_request *fw_req;274 const struct firmware *fw;275 unsigned int offset, size;276 u8 firmware_id;277 u8 *response;278 int ret = 0;279 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 292 fw_req = get_fw_req(fw_download, firmware_id);293 if (!fw_req) {294 dev_err(fw_download->parent,295 "firmware not available for id: %02u\n", firmware_id);296 return -EINVAL;297 }298 299 /* Make sure work handler isn't running in parallel */300 cancel_delayed_work_sync(&fw_req->dwork);301 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 it310 * doesn't, then we might have a buggy Module on the other side. Abort311 * download.312 */313 ret = exceeds_release_timeout(fw_req);314 if (ret)315 goto put_fw;316 317 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);323 ret = -EINVAL;324 goto put_fw;325 }326 327 /* gb_fw_download_fetch_firmware_response contains only a byte array */328 if (!gb_operation_response_alloc(op, size, GFP_KERNEL)) {329 dev_err(fw_download->parent,330 "error allocating fetch firmware response\n");331 ret = -ENOMEM;332 goto put_fw;333 }334 335 response = op->response->payload;336 memcpy(response, fw->data + offset, size);337 338 dev_dbg(fw_download->parent,339 "responding with firmware (offs = %u, size = %u)\n", offset,340 size);341 342 /* Refresh timeout */343 schedule_delayed_work(&fw_req->dwork, NEXT_REQ_TIMEOUT_J);344 345put_fw:346 put_fw_req(fw_req);347 348 return ret;349}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 369 fw_req = get_fw_req(fw_download, firmware_id);370 if (!fw_req) {371 dev_err(fw_download->parent,372 "firmware not available for id: %02u\n", firmware_id);373 return -EINVAL;374 }375 376 cancel_delayed_work_sync(&fw_req->dwork);377 378 free_firmware(fw_download, fw_req);379 put_fw_req(fw_req);380 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;421 mutex_init(&fw_download->mutex);422 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 447 /*448 * Make sure we have a reference to the pending requests, before they449 * 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 456 /* Release pending firmware packages */457 list_for_each_entry_safe(fw_req, tmp, &fw_download->fw_requests, node) {458 cancel_delayed_work_sync(&fw_req->dwork);459 free_firmware(fw_download, fw_req);460 put_fw_req(fw_req);461 }462 463 ida_destroy(&fw_download->id_map);464 kfree(fw_download);465}466