base.c revision 4c4101d29fb6c63f78791d02c437702b11e1d4f0
13863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs/* 23863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * Copyright 2012 Red Hat Inc. 33863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * 43863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 53863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * copy of this software and associated documentation files (the "Software"), 63863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * to deal in the Software without restriction, including without limitation 73863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 83863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the 93863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * Software is furnished to do so, subject to the following conditions: 103863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * 113863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * The above copyright notice and this permission notice shall be included in 123863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * all copies or substantial portions of the Software. 133863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * 143863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 153863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 163863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 173863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 183863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 193863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 203863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * OTHER DEALINGS IN THE SOFTWARE. 213863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * 223863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs * Authors: Ben Skeggs 233863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs */ 243863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 253863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs#include <subdev/instmem.h> 263863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 273863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsint 283863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsnouveau_instobj_create_(struct nouveau_object *parent, 293863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_object *engine, 303863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_oclass *oclass, 313863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs int length, void **pobject) 323863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs{ 333863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_instmem *imem = (void *)engine; 343863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_instobj *iobj; 353863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs int ret; 363863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 373863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs ret = nouveau_object_create_(parent, engine, oclass, NV_MEMOBJ_CLASS, 383863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs length, pobject); 393863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs iobj = *pobject; 403863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs if (ret) 413863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return ret; 423863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 434c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz mutex_lock(&imem->base.mutex); 443863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs list_add(&iobj->head, &imem->list); 454c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz mutex_unlock(&imem->base.mutex); 463863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return 0; 473863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs} 483863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 493863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsvoid 503863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsnouveau_instobj_destroy(struct nouveau_instobj *iobj) 513863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs{ 524c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); 534c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz 544c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz mutex_lock(&subdev->mutex); 554c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz list_del(&iobj->head); 564c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz mutex_unlock(&subdev->mutex); 574c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz 583863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return nouveau_object_destroy(&iobj->base); 593863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs} 603863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 613863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsvoid 623863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs_nouveau_instobj_dtor(struct nouveau_object *object) 633863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs{ 643863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_instobj *iobj = (void *)object; 653863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return nouveau_instobj_destroy(iobj); 663863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs} 673863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 683863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsint 693863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsnouveau_instmem_create_(struct nouveau_object *parent, 703863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_object *engine, 713863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_oclass *oclass, 723863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs int length, void **pobject) 733863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs{ 743863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_instmem *imem; 753863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs int ret; 763863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 773863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs ret = nouveau_subdev_create_(parent, engine, oclass, 0, 783863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs "INSTMEM", "instmem", length, pobject); 793863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs imem = *pobject; 803863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs if (ret) 813863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return ret; 823863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 833863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs INIT_LIST_HEAD(&imem->list); 843863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return 0; 853863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs} 863863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 873863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsint 883863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsnouveau_instmem_init(struct nouveau_instmem *imem) 893863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs{ 903863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_instobj *iobj; 913863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs int ret, i; 923863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 933863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs ret = nouveau_subdev_init(&imem->base); 943863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs if (ret) 953863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return ret; 963863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 974c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz mutex_lock(&imem->base.mutex); 984c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz 993863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs list_for_each_entry(iobj, &imem->list, head) { 1003863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs if (iobj->suspend) { 1013863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs for (i = 0; i < iobj->size; i += 4) 1023863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs nv_wo32(iobj, i, iobj->suspend[i / 4]); 1033863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs vfree(iobj->suspend); 1043863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs iobj->suspend = NULL; 1053863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs } 1063863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs } 1073863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 1084c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz mutex_unlock(&imem->base.mutex); 1094c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz 1103863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return 0; 1113863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs} 1123863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 1133863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsint 1143863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsnouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) 1153863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs{ 1163863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_instobj *iobj; 1174c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz int i, ret = 0; 1183863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 1193863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs if (suspend) { 1204c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz mutex_lock(&imem->base.mutex); 1214c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz 1223863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs list_for_each_entry(iobj, &imem->list, head) { 1233863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs iobj->suspend = vmalloc(iobj->size); 1244c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz if (!iobj->suspend) { 1254c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz ret = -ENOMEM; 1264c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz break; 1274c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz } 1284c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz 1294c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz for (i = 0; i < iobj->size; i += 4) 1304c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz iobj->suspend[i / 4] = nv_ro32(iobj, i); 1313863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs } 1324c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz 1334c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz mutex_unlock(&imem->base.mutex); 1344c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz 1354c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz if (ret) 1364c4101d29fb6c63f78791d02c437702b11e1d4f0Marcin Slusarz return ret; 1373863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs } 1383863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 1393863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return nouveau_subdev_fini(&imem->base, suspend); 1403863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs} 1413863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 1423863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsint 1433863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs_nouveau_instmem_init(struct nouveau_object *object) 1443863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs{ 1453863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_instmem *imem = (void *)object; 1463863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return nouveau_instmem_init(imem); 1473863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs} 1483863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs 1493863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggsint 1503863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs_nouveau_instmem_fini(struct nouveau_object *object, bool suspend) 1513863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs{ 1523863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs struct nouveau_instmem *imem = (void *)object; 1533863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs return nouveau_instmem_fini(imem, suspend); 1543863c9bc887e9638a9d905d55f6038641ece78d6Ben Skeggs} 155