drm/nouveau/core: add a macro to better handle multiple firmware versions

Will be used in upcoming commits to allow subdevs to better customise
themselves based on which (if any) firmware is available.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2020-01-15 06:34:21 +10:00
parent 5ff41544fc
commit 47c8f8e1a2
1 changed files with 40 additions and 0 deletions

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_FIRMWARE_H__
#define __NVKM_FIRMWARE_H__
#include <core/option.h>
#include <core/subdev.h>
int nvkm_firmware_get_version(const struct nvkm_subdev *, const char *fwname,
@ -9,4 +10,43 @@ int nvkm_firmware_get_version(const struct nvkm_subdev *, const char *fwname,
int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname,
const struct firmware **);
void nvkm_firmware_put(const struct firmware *);
#define nvkm_firmware_load(s,l,o,p...) ({ \
struct nvkm_subdev *_s = (s); \
const char *_opts = (o); \
char _option[32]; \
typeof(l[0]) *_list = (l), *_next, *_fwif = NULL; \
int _ver, _fwv, _ret = 0; \
\
snprintf(_option, sizeof(_option), "Nv%sFw", _opts); \
_ver = nvkm_longopt(_s->device->cfgopt, _option, -2); \
if (_ver >= -1) { \
for (_next = _list; !_fwif && _next->load; _next++) { \
if (_next->version == _ver) \
_fwif = _next; \
} \
_ret = _fwif ? 0 : -EINVAL; \
} \
\
if (_ret == 0) { \
snprintf(_option, sizeof(_option), "Nv%sFwVer", _opts); \
_fwv = _fwif ? _fwif->version : -1; \
_ver = nvkm_longopt(_s->device->cfgopt, _option, _fwv); \
for (_next = _fwif ? _fwif : _list; _next->load; _next++) { \
_fwv = (_ver >= 0) ? _ver : _next->version; \
_ret = _next->load(p, _fwv, _next); \
if (_ret == 0 || _ver >= 0) { \
_fwif = _next; \
break; \
} \
} \
} \
\
if (_ret) { \
nvkm_error(_s, "failed to load firmware\n"); \
_fwif = ERR_PTR(_ret); \
} \
\
_fwif; \
})
#endif