162 lines · c
1/*2 * Copyright 2016 Red Hat Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: Ben Skeggs <bskeggs@redhat.com>23 */24#include "priv.h"25 26struct nvkm_top_device *27nvkm_top_device_new(struct nvkm_top *top)28{29 struct nvkm_top_device *info = kmalloc(sizeof(*info), GFP_KERNEL);30 if (info) {31 info->type = NVKM_SUBDEV_NR;32 info->inst = -1;33 info->addr = 0;34 info->fault = -1;35 info->engine = -1;36 info->runlist = -1;37 info->reset = -1;38 info->intr = -1;39 list_add_tail(&info->head, &top->device);40 }41 return info;42}43 44u3245nvkm_top_addr(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)46{47 struct nvkm_top *top = device->top;48 struct nvkm_top_device *info;49 50 if (top) {51 list_for_each_entry(info, &top->device, head) {52 if (info->type == type && info->inst == inst)53 return info->addr;54 }55 }56 57 return 0;58}59 60u3261nvkm_top_reset(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)62{63 struct nvkm_top *top = device->top;64 struct nvkm_top_device *info;65 66 if (top) {67 list_for_each_entry(info, &top->device, head) {68 if (info->type == type && info->inst == inst && info->reset >= 0)69 return BIT(info->reset);70 }71 }72 73 return 0;74}75 76u3277nvkm_top_intr_mask(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)78{79 struct nvkm_top *top = device->top;80 struct nvkm_top_device *info;81 82 if (top) {83 list_for_each_entry(info, &top->device, head) {84 if (info->type == type && info->inst == inst && info->intr >= 0)85 return BIT(info->intr);86 }87 }88 89 return 0;90}91 92int93nvkm_top_fault_id(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)94{95 struct nvkm_top *top = device->top;96 struct nvkm_top_device *info;97 98 list_for_each_entry(info, &top->device, head) {99 if (info->type == type && info->inst == inst && info->fault >= 0)100 return info->fault;101 }102 103 return -ENOENT;104}105 106struct nvkm_subdev *107nvkm_top_fault(struct nvkm_device *device, int fault)108{109 struct nvkm_top *top = device->top;110 struct nvkm_top_device *info;111 112 list_for_each_entry(info, &top->device, head) {113 if (info->fault == fault)114 return nvkm_device_subdev(device, info->type, info->inst);115 }116 117 return NULL;118}119 120int121nvkm_top_parse(struct nvkm_device *device)122{123 struct nvkm_top *top = device->top;124 125 if (!top || !list_empty(&top->device))126 return 0;127 128 return top->func->parse(top);129}130 131static void *132nvkm_top_dtor(struct nvkm_subdev *subdev)133{134 struct nvkm_top *top = nvkm_top(subdev);135 struct nvkm_top_device *info, *temp;136 137 list_for_each_entry_safe(info, temp, &top->device, head) {138 list_del(&info->head);139 kfree(info);140 }141 142 return top;143}144 145static const struct nvkm_subdev_func146nvkm_top = {147 .dtor = nvkm_top_dtor,148};149 150int151nvkm_top_new_(const struct nvkm_top_func *func, struct nvkm_device *device,152 enum nvkm_subdev_type type, int inst, struct nvkm_top **ptop)153{154 struct nvkm_top *top;155 if (!(top = *ptop = kzalloc(sizeof(*top), GFP_KERNEL)))156 return -ENOMEM;157 nvkm_subdev_ctor(&nvkm_top, device, type, inst, &top->subdev);158 top->func = func;159 INIT_LIST_HEAD(&top->device);160 return 0;161}162