Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2016 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Ben Skeggs <bskeggs@redhat.com>
0023  */
0024 #include "priv.h"
0025 
0026 struct nvkm_top_device *
0027 nvkm_top_device_new(struct nvkm_top *top)
0028 {
0029     struct nvkm_top_device *info = kmalloc(sizeof(*info), GFP_KERNEL);
0030     if (info) {
0031         info->type = NVKM_SUBDEV_NR;
0032         info->inst = -1;
0033         info->addr = 0;
0034         info->fault = -1;
0035         info->engine = -1;
0036         info->runlist = -1;
0037         info->reset = -1;
0038         info->intr = -1;
0039         list_add_tail(&info->head, &top->device);
0040     }
0041     return info;
0042 }
0043 
0044 u32
0045 nvkm_top_addr(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
0046 {
0047     struct nvkm_top *top = device->top;
0048     struct nvkm_top_device *info;
0049 
0050     if (top) {
0051         list_for_each_entry(info, &top->device, head) {
0052             if (info->type == type && info->inst == inst)
0053                 return info->addr;
0054         }
0055     }
0056 
0057     return 0;
0058 }
0059 
0060 u32
0061 nvkm_top_reset(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
0062 {
0063     struct nvkm_top *top = device->top;
0064     struct nvkm_top_device *info;
0065 
0066     if (top) {
0067         list_for_each_entry(info, &top->device, head) {
0068             if (info->type == type && info->inst == inst && info->reset >= 0)
0069                 return BIT(info->reset);
0070         }
0071     }
0072 
0073     return 0;
0074 }
0075 
0076 u32
0077 nvkm_top_intr_mask(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
0078 {
0079     struct nvkm_top *top = device->top;
0080     struct nvkm_top_device *info;
0081 
0082     if (top) {
0083         list_for_each_entry(info, &top->device, head) {
0084             if (info->type == type && info->inst == inst && info->intr >= 0)
0085                 return BIT(info->intr);
0086         }
0087     }
0088 
0089     return 0;
0090 }
0091 
0092 int
0093 nvkm_top_fault_id(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
0094 {
0095     struct nvkm_top *top = device->top;
0096     struct nvkm_top_device *info;
0097 
0098     list_for_each_entry(info, &top->device, head) {
0099         if (info->type == type && info->inst == inst && info->fault >= 0)
0100             return info->fault;
0101     }
0102 
0103     return -ENOENT;
0104 }
0105 
0106 struct nvkm_subdev *
0107 nvkm_top_fault(struct nvkm_device *device, int fault)
0108 {
0109     struct nvkm_top *top = device->top;
0110     struct nvkm_top_device *info;
0111 
0112     list_for_each_entry(info, &top->device, head) {
0113         if (info->fault == fault)
0114             return nvkm_device_subdev(device, info->type, info->inst);
0115     }
0116 
0117     return NULL;
0118 }
0119 
0120 static int
0121 nvkm_top_oneinit(struct nvkm_subdev *subdev)
0122 {
0123     struct nvkm_top *top = nvkm_top(subdev);
0124     return top->func->oneinit(top);
0125 }
0126 
0127 static void *
0128 nvkm_top_dtor(struct nvkm_subdev *subdev)
0129 {
0130     struct nvkm_top *top = nvkm_top(subdev);
0131     struct nvkm_top_device *info, *temp;
0132 
0133     list_for_each_entry_safe(info, temp, &top->device, head) {
0134         list_del(&info->head);
0135         kfree(info);
0136     }
0137 
0138     return top;
0139 }
0140 
0141 static const struct nvkm_subdev_func
0142 nvkm_top = {
0143     .dtor = nvkm_top_dtor,
0144     .oneinit = nvkm_top_oneinit,
0145 };
0146 
0147 int
0148 nvkm_top_new_(const struct nvkm_top_func *func, struct nvkm_device *device,
0149           enum nvkm_subdev_type type, int inst, struct nvkm_top **ptop)
0150 {
0151     struct nvkm_top *top;
0152     if (!(top = *ptop = kzalloc(sizeof(*top), GFP_KERNEL)))
0153         return -ENOMEM;
0154     nvkm_subdev_ctor(&nvkm_top, device, type, inst, &top->subdev);
0155     top->func = func;
0156     INIT_LIST_HEAD(&top->device);
0157     return 0;
0158 }