您的位置:首页 > 其它

Nouveau源码分析(五):NVIDIA设备初始化之nouveau_drm_load (2)

2015-09-01 16:39 633 查看


Nouveau源码分析(五)

接着上一篇来,先把nouveau_drm_load再贴出一遍来吧:

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/nouveau_drm.c

364 static int

365 nouveau_drm_load(struct drm_device *dev, unsigned long flags)

366 {

367 struct pci_dev *pdev = dev->pdev;

368 struct nouveau_drm *drm;

369 int ret;

370

371 ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm),

372 (void **)&drm);

373 if (ret)

374 return ret;

375

376 dev->dev_private = drm;

377 drm->dev = dev;

378 nvkm_client(&drm->client.base)->debug =

379 nouveau_dbgopt(nouveau_debug, "DRM");

380

381 INIT_LIST_HEAD(&drm->clients);

382 spin_lock_init(&drm->tile.lock);

383

384 nouveau_get_hdmi_dev(drm);

385

386 /* make sure AGP controller is in a consistent state before we

387 * (possibly) execute vbios init tables (see nouveau_agp.h)

388 */

389 if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {

390 const u64 enables = NV_DEVICE_V0_DISABLE_IDENTIFY |

391 NV_DEVICE_V0_DISABLE_MMIO;

392 /* dummy device object, doesn't init anything, but allows

393 * agp code access to registers

394 */

395 ret = nvif_device_init(&drm->client.base.base, NULL,

396 NVDRM_DEVICE, NV_DEVICE,

397 &(struct nv_device_v0) {

398 .device = ~0,

399 .disable = ~enables,

400 .debug0 = ~0,

401 }, sizeof(struct nv_device_v0),

402 &drm->device);

403 if (ret)

404 goto fail_device;

405

406 nouveau_agp_reset(drm);

407 nvif_device_fini(&drm->device);

408 }

409

410 ret = nvif_device_init(&drm->client.base.base, NULL, NVDRM_DEVICE,

411 NV_DEVICE,

412 &(struct nv_device_v0) {

413 .device = ~0,

414 .disable = 0,

415 .debug0 = 0,

416 }, sizeof(struct nv_device_v0),

417 &drm->device);

418 if (ret)

419 goto fail_device;

420

421 dev->irq_enabled = true;

422

423 /* workaround an odd issue on nvc1 by disabling the device's

424 * nosnoop capability. hopefully won't cause issues until a

425 * better fix is found - assuming there is one...

426 */

427 if (drm->device.info.chipset == 0xc1)

428 nvif_mask(&drm->device, 0x00088080, 0x00000800, 0x00000000);

429

430 nouveau_vga_init(drm);

431 nouveau_agp_init(drm);

432

433 if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {

434 ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40),

435 0x1000, &drm->client.vm);

436 if (ret)

437 goto fail_device;

438

439 nvkm_client(&drm->client.base)->vm = drm->client.vm;

440 }

441

442 ret = nouveau_ttm_init(drm);

443 if (ret)

444 goto fail_ttm;

445

446 ret = nouveau_bios_init(dev);

447 if (ret)

448 goto fail_bios;

449

450 ret = nouveau_display_create(dev);

451 if (ret)

452 goto fail_dispctor;

453

454 if (dev->mode_config.num_crtc) {

455 ret = nouveau_display_init(dev);

456 if (ret)

457 goto fail_dispinit;

458 }

459

460 nouveau_sysfs_init(dev);

461 nouveau_hwmon_init(dev);

462 nouveau_accel_init(drm);

463 nouveau_fbcon_init(dev);

464

465 if (nouveau_runtime_pm != 0) {

466 pm_runtime_use_autosuspend(dev->dev);

467 pm_runtime_set_autosuspend_delay(dev->dev, 5000);

468 pm_runtime_set_active(dev->dev);

469 pm_runtime_allow(dev->dev);

470 pm_runtime_mark_last_busy(dev->dev);

471 pm_runtime_put(dev->dev);

472 }

473 return 0;

474

475 fail_dispinit:

476 nouveau_display_destroy(dev);

477 fail_dispctor:

478 nouveau_bios_takedown(dev);

479 fail_bios:

480 nouveau_ttm_fini(drm);

481 fail_ttm:

482 nouveau_agp_fini(drm);

483 nouveau_vga_fini(drm);

484 fail_device:

485 nvif_device_fini(&drm->device);

486 nouveau_cli_destroy(&drm->client);

487 return ret;

488 }

第386行到第408行,注释说的很清楚,重置AGP. 好了来看nvif_device_init:

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/nvif/device.c

33 int

34 nvif_device_init(struct nvif_object *parent, void (*dtor)(struct nvif_device *),

35 u32 handle, u32 oclass, void *data, u32 size,

36 struct nvif_device *device)

37 {

38 int ret = nvif_object_init(parent, (void *)dtor, handle, oclass,

39 data, size, &device->base);

40 if (ret == 0) {

41 device->object = &device->base;

42 device->info.version = 0;

43 ret = nvif_object_mthd(&device->base, NV_DEVICE_V0_INFO,

44 &device->info, sizeof(device->info));

45 }

46 return ret;

47 }

首先第38行,nvif_object_init,还记得在上一篇中被忽略掉的那部分代码吗? 这里展开说:

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/nvif/object.c

217 int

218 nvif_object_init(struct nvif_object *parent, void (*dtor)(struct nvif_object *),

219 u32 handle, u32 oclass, void *data, u32 size,

220 struct nvif_object *object)

221 {

222 struct ctor *ctor;

223 int ret = 0;

224

225 object->parent = NULL;

226 object->object = object;

227 nvif_object_ref(parent, &object->parent);

228 kref_init(&object->refcount);

229 object->handle = handle;

230 object->oclass = oclass;

231 object->data = NULL;

232 object->size = 0;

233 object->dtor = dtor;

234 object->map.ptr = NULL;

235 object->map.size = 0;

236

237 if (object->parent) {

238 if (!(ctor = kmalloc(sizeof(*ctor) + size, GFP_KERNEL))) {

239 nvif_object_fini(object);

240 return -ENOMEM;

241 }

242 object->data = ctor->new.data;

243 object->size = size;

244 memcpy(object->data, data, size);

245

246 ctor->ioctl.version = 0;

247 ctor->ioctl.type = NVIF_IOCTL_V0_NEW;

248 ctor->new.version = 0;

249 ctor->new.route = NVIF_IOCTL_V0_ROUTE_NVIF;

250 ctor->new.token = (unsigned long)(void *)object;

251 ctor->new.handle = handle;

252 ctor->new.oclass = oclass;

253

254 ret = nvif_object_ioctl(parent, ctor, sizeof(*ctor) +

255 object->size, &object->priv);

256 }

257

258 if (ret)

259 nvif_object_fini(object);

260 return ret;

261 }

第238行,分配一个ctor.

第244行,把传进来的数据复制进去,数据就是:"&(struct nv_device_v0) { .device = ~0, .disable = ~enables, .debug0 = ~0, }"

下面的几个字段简单说一下:

ctor->ioctl.version 貌似是用来校验版本的东西,目前只可能是0.

ctor->ioctl.type 表示ioctl的命令.

ctor->new.version 貌似和上面那个version一样.

ctor->new.route 表示这是nvif. 除了nvif另一种是usif,用户空间用的.

ctor->new.token 此处是储存对应的nvif_object.

ctor->new.handle 此处是储存要创建的nouveau_object的handle.

ctor->new.oclass 此处是储存要创建的nouveau_object的oclass.

第254行,正式调用nvif_object_ioctl函数.

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/nvif/object.c

30 int

31 nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)

32 {

33 struct nvif_client *client = nvif_client(object);

34 union {

35 struct nvif_ioctl_v0 v0;

36 } *args = data;

37

38 if (size >= sizeof(*args) && args->v0.version == 0) {

39 args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;

40 args->v0.path_nr = 0;

41 while (args->v0.path_nr < ARRAY_SIZE(args->v0.path)) {

42 args->v0.path[args->v0.path_nr++] = object->handle;

43 if (object->parent == object)

44 break;

45 object = object->parent;

46 }

47 } else

48 return -ENOSYS;

49

50 return client->driver->ioctl(client->base.priv, client->super, data, size, hack);

51 }

第38行,首先检查version和大小是否正确

第39行,设置一下owner,这个是表示是对nvif还是usif还是any进行ioctl的. 可以防止用户态程序ioctl的时候ioctl到nvif [只能对usif进行ioctl.].

之后第41行一个whlie循环,逐级object = object->parent,然后把handle储存到path里.

第50行,交给client的driver进行处理.

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/nouveau_nvif.c

54 static int

55 nvkm_client_ioctl(void *priv, bool super, void *data, u32 size, void **hack)

56 {

57 return nvkm_ioctl(priv, super, data, size, hack);

58 }

再交给nvkm_ioctl处理.

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/core/ioctl.c

502 int

503 nvkm_ioctl(struct nouveau_client *client, bool supervisor,

504 void *data, u32 size, void **hack)

505 {

506 union {

507 struct nvif_ioctl_v0 v0;

508 } *args = data;

509 int ret;

510

511 client->super = supervisor;

512 nv_ioctl(client, "size %d\n", size);

513

514 if (nvif_unpack(args->v0, 0, 0, true)) {

515 nv_ioctl(client, "vers %d type %02x path %d owner %02x\n",

516 args->v0.version, args->v0.type, args->v0.path_nr,

517 args->v0.owner);

518 ret = nvkm_ioctl_path(client->root, args->v0.type,

519 args->v0.path_nr, args->v0.path,

520 data, size, args->v0.owner,

521 &args->v0.route, &args->v0.token);

522 }

523

524 nv_ioctl(client, "return %d\n", ret);

525 if (hack) {

526 *hack = client->data;

527 client->data = NULL;

528 }

529 client->super = false;

530 return ret;

531 }

client->super意义不明,忽略之.

然后第514行,看看nvif_unpack:

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/nvif/unpack.h

9 #define nvif_unpack(d,vl,vh,m) ({ \

10 if ((vl) == 0 || ret == -ENOSYS) { \

11 int _size = sizeof(d); \

12 if (_size <= size && (d).version >= (vl) && \

13 (d).version <= (vh)) { \

14 data = (u8 *)data + _size; \

15 size = size - _size; \

16 ret = ((m) || !size) ? 0 : -E2BIG; \

17 } else { \

18 ret = -ENOSYS; \

19 } \

20 } \

21 (ret == 0); \

22 })

大体上来说就是检查版本是否对应,大小是否正常,然后把data加上header的size,把size减去header的size.

第518行,调用nvkm_ioctl_path.

第526行,把data存到*hack里.

重点看nvkm_ioctl_path:

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/core/ioctl.c

459 static int

460 nvkm_ioctl_path(struct nouveau_handle *parent, u32 type, u32 nr,

461 u32 *path, void *data, u32 size,

462 u8 owner, u8 *route, u64 *token)

463 {

464 struct nouveau_handle *handle = parent;

465 struct nouveau_namedb *namedb;

466 struct nouveau_object *object;

467 int ret;

468

469 while ((object = parent->object), nr--) {

470 nv_ioctl(object, "path 0x%08x\n", path[nr]);

471 if (!nv_iclass(object, NV_PARENT_CLASS)) {

472 nv_debug(object, "cannot have children (path)\n");

473 return -EINVAL;

474 }

475

476 if (!(namedb = (void *)nv_pclass(object, NV_NAMEDB_CLASS)) ||

477 !(handle = nouveau_namedb_get(namedb, path[nr]))) {

478 nv_debug(object, "handle 0x%08x not found\n", path[nr]);

479 return -ENOENT;

480 }

481 nouveau_namedb_put(handle);

482 parent = handle;

483 }

484

485 if (owner != NVIF_IOCTL_V0_OWNER_ANY &&

486 owner != handle->route) {

487 nv_ioctl(object, "object route != owner\n");

488 return -EACCES;

489 }

490 *route = handle->route;

491 *token = handle->token;

492

493 if (ret = -EINVAL, type < ARRAY_SIZE(nvkm_ioctl_v0)) {

494 if (nvkm_ioctl_v0[type].version == 0) {

495 ret = nvkm_ioctl_v0[type].func(handle, data, size);

496 }

497 }

498

499 return ret;

500 }

参数parent是client->root,它对应的object就是它自己client.

第469行的while语句,逐个把path[--nr]取出来,从后往前,也就是从parent到children,在namedb中查找.

这样一来,最后的handle就是path[0]所对应的nouveau_handle. 也就是当初调用nvif_object_init第一个参数nvif_object *object对应的nouveau_object *object对应的nouveau_handle *handle! 对于这个例子就是nouveau_client *client的root字段.

接下来第485行,检查owner和handle->route是否匹配,作用前面提到了.

第490行.把handle->route和handle->token储存到*route和*token中,再调用真正的ioctl函数.

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/core/ioctl.c

439 static struct {

440 int version;

441 int (*func)(struct nouveau_handle *, void *, u32);

442 }

443 nvkm_ioctl_v0[] = {

444 { 0x00, nvkm_ioctl_nop },

445 { 0x00, nvkm_ioctl_sclass },

446 { 0x00, nvkm_ioctl_new },

447 { 0x00, nvkm_ioctl_del },

448 { 0x00, nvkm_ioctl_mthd },

449 { 0x00, nvkm_ioctl_rd },

450 { 0x00, nvkm_ioctl_wr },

451 { 0x00, nvkm_ioctl_map },

452 { 0x00, nvkm_ioctl_unmap },

453 { 0x00, nvkm_ioctl_ntfy_new },

454 { 0x00, nvkm_ioctl_ntfy_del },

455 { 0x00, nvkm_ioctl_ntfy_get },

456 { 0x00, nvkm_ioctl_ntfy_put },

457 };

本例当然是nvkm_ioctl_new,来看一下这个函数:

[cpp] view
plaincopyprint?





87 static int

88 nvkm_ioctl_new(struct nouveau_handle *parent, void *data, u32 size)

89 {

90 union {

91 struct nvif_ioctl_new_v0 v0;

92 } *args = data;

93 struct nouveau_client *client = nouveau_client(parent->object);

94 struct nouveau_object *engctx = NULL;

95 struct nouveau_object *object = NULL;

96 struct nouveau_object *engine;

97 struct nouveau_oclass *oclass;

98 struct nouveau_handle *handle;

99 u32 _handle, _oclass;

100 int ret;

101

102 nv_ioctl(client, "new size %d\n", size);

103 if (nvif_unpack(args->v0, 0, 0, true)) {

104 _handle = args->v0.handle;

105 _oclass = args->v0.oclass;

106 } else

107 return ret;

108

109 nv_ioctl(client, "new vers %d handle %08x class %08x "

110 "route %02x token %llx\n",

111 args->v0.version, _handle, _oclass,

112 args->v0.route, args->v0.token);

113

114 if (!nv_iclass(parent->object, NV_PARENT_CLASS)) {

115 nv_debug(parent->object, "cannot have children (ctor)\n");

116 ret = -ENODEV;

117 goto fail_class;

118 }

119

120 /* check that parent supports the requested subclass */

121 ret = nouveau_parent_sclass(parent->object, _oclass, &engine, &oclass);

122 if (ret) {

123 nv_debug(parent->object, "illegal class 0x%04x\n", _oclass);

124 goto fail_class;

125 }

126

127 /* make sure engine init has been completed *before* any objects

128 * it controls are created - the constructors may depend on

129 * state calculated at init (ie. default context construction)

130 */

131 if (engine) {

132 ret = nouveau_object_inc(engine);

133 if (ret)

134 goto fail_class;

135 }

136

137 /* if engine requires it, create a context object to insert

138 * between the parent and its children (eg. PGRAPH context)

139 */

140 if (engine && nv_engine(engine)->cclass) {

141 ret = nouveau_object_ctor(parent->object, engine,

142 nv_engine(engine)->cclass,

143 data, size, &engctx);

144 if (ret)

145 goto fail_engctx;

146 } else {

147 nouveau_object_ref(parent->object, &engctx);

148 }

149

150 /* finally, create new object and bind it to its handle */

151 ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);

152 client->data = object;

153 if (ret)

154 goto fail_ctor;

155

156 ret = nouveau_object_inc(object);

157 if (ret)

158 goto fail_init;

159

160 ret = nouveau_handle_create(parent->object, parent->name,

161 _handle, object, &handle);

162 if (ret)

163 goto fail_handle;

164

165 ret = nouveau_handle_init(handle);

166 handle->route = args->v0.route;

167 handle->token = args->v0.token;

168 if (ret)

169 nouveau_handle_destroy(handle);

170

171 fail_handle:

172 nouveau_object_dec(object, false);

173 fail_init:

174 nouveau_object_ref(NULL, &object);

175 fail_ctor:

176 nouveau_object_ref(NULL, &engctx);

177 fail_engctx:

178 if (engine)

179 nouveau_object_dec(engine, false);

180 fail_class:

181 return ret;

182 }

第103行,再次使用nvif_unpack检查参数的正确性.

第121行,这就是u32 oclass到nouveau_oclass *oclass的转换了.

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/core/parent.c

29 int

30 nouveau_parent_sclass(struct nouveau_object *parent, u16 handle,

31 struct nouveau_object **pengine,

32 struct nouveau_oclass **poclass)

33 {

34 struct nouveau_sclass *sclass;

35 struct nouveau_engine *engine;

36 struct nouveau_oclass *oclass;

37 u64 mask;

38

39 sclass = nv_parent(parent)->sclass;

40 while (sclass) {

41 if ((sclass->oclass->handle & 0xffff) == handle) {

42 *pengine = parent->engine;

43 *poclass = sclass->oclass;

44 return 0;

45 }

46

47 sclass = sclass->sclass;

48 }

49

50 mask = nv_parent(parent)->engine;

51 while (mask) {

52 int i = __ffs64(mask);

53

54 if (nv_iclass(parent, NV_CLIENT_CLASS))

55 engine = nv_engine(nv_client(parent)->device);

56 else

57 engine = nouveau_engine(parent, i);

58

59 if (engine) {

60 oclass = engine->sclass;

61 while (oclass->ofuncs) {

62 if ((oclass->handle & 0xffff) == handle) {

63 *pengine = nv_object(engine);

64 *poclass = oclass;

65 return 0;

66 }

67 oclass++;

68 }

69 }

70

71 mask &= ~(1ULL << i);

72 }

73

74 return -EINVAL;

75 }

首先第40行的while语句,直接在parent->sclass中寻找,这个东西可以看作是一个单向链表. 对于这个例子,parent->sclass为0,故不存在这种可能性.

然后第52行,从((nouveau_parent *)parent)->engine指示的subdev中寻找. __ffs64返回的是二进制中第一个为1的位是第几位. 比如0b1返回0 ,0b1000返回3.

如果parent不是一个nouveau_client对象,那么就先向上获取一个nouveau_device对象,然后返回device->subdev[i] .

如果parent是一个nouveau_client对象,那么直接使用client->device.

对于本例当然是后者,也就是直接使用我们在第三篇中用nouveau_device_create创建的那个nouveau_device *device. (此处需要注意nouveau_parent::sclass是个单向链表,但nouveau_device::sclass是个数组.)

还记得当初传递进去的sclass是什么吗?

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/engine/device/base.c

501 static struct nouveau_oclass

502 nouveau_device_sclass[] = {

503 { 0x0080, &nouveau_devobj_ofuncs },

504 {}

505 };

看看我们现在的这个oclass是什么:

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/include/nvif/class.h

9 #define NV_DEVICE 0x00000080

匹配成功! 于是对pengine和poclass进行赋值操作,返回.

第132行,对engine执行nouveau_object_inc函数:

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/core/object.c

164 int

165 nouveau_object_inc(struct nouveau_object *object)

166 {

167 int ref = atomic_add_return(1, &object->usecount);

168 int ret;

169

170 nv_trace(object, "use(+1) == %d\n", atomic_read(&object->usecount));

171 if (ref != 1)

172 return 0;

173

174 nv_trace(object, "initialising...\n");

175 if (object->parent) {

176 ret = nouveau_object_inc(object->parent);

177 if (ret) {

178 nv_error(object, "parent failed, %d\n", ret);

179 goto fail_parent;

180 }

181 }

182

183 if (object->engine) {

184 mutex_lock(&nv_subdev(object->engine)->mutex);

185 ret = nouveau_object_inc(object->engine);

186 mutex_unlock(&nv_subdev(object->engine)->mutex);

187 if (ret) {

188 nv_error(object, "engine failed, %d\n", ret);

189 goto fail_engine;

190 }

191 }

192

193 ret = nv_ofuncs(object)->init(object);

194 atomic_set(&object->usecount, 1);

195 if (ret) {

196 nv_error(object, "init failed, %d\n", ret);

197 goto fail_self;

198 }

199

200 nv_trace(object, "initialised\n");

201 return 0;

202

203 fail_self:

204 if (object->engine) {

205 mutex_lock(&nv_subdev(object->engine)->mutex);

206 nouveau_object_dec(object->engine, false);

207 mutex_unlock(&nv_subdev(object->engine)->mutex);

208 }

209 fail_engine:

210 if (object->parent)

211 nouveau_object_dec(object->parent, false);

212 fail_parent:

213 atomic_dec(&object->usecount);

214 return ret;

215 }

因此这是第一次执行nouveau_object_inc函数,所以第171行并没有返回.

然后第176行,对parent执行inc操作,第185行,对engine执行inc操作. 此处对由于parent和engine都为0,所以并没有执行进这两个if语句.

第193行,执行oclass里的init函数:

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/engine/device/base.c

652 static struct nouveau_oclass

653 nouveau_device_oclass = {

654 .handle = NV_ENGINE(DEVICE, 0x00),

655 .ofuncs = &(struct nouveau_ofuncs) {

656 .dtor = nouveau_device_dtor,

657 .init = nouveau_device_init,

658 .fini = nouveau_device_fini,

659 },

660 };

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/engine/device/base.c

557 static int

558 nouveau_device_init(struct nouveau_object *object)

559 {

560 struct nouveau_device *device = (void *)object;

561 struct nouveau_object *subdev;

562 int ret, i = 0;

563

564 ret = nvkm_acpi_init(device);

565 if (ret)

566 goto fail;

567

568 for (i = 0; i < NVDEV_SUBDEV_NR; i++) {

569 if ((subdev = device->subdev[i])) {

570 if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {

571 ret = nouveau_object_inc(subdev);

572 if (ret)

573 goto fail;

574 } else {

575 nouveau_subdev_reset(subdev);

576 }

577 }

578 }

579

580 ret = 0;

581 fail:

582 for (--i; ret && i >= 0; i--) {

583 if ((subdev = device->subdev[i])) {

584 if (!nv_iclass(subdev, NV_ENGINE_CLASS))

585 nouveau_object_dec(subdev, false);

586 }

587 }

588

589 if (ret)

590 nvkm_acpi_fini(device, false);

591 return ret;

592 }

首先第564行执行nvkm_acpi_init,这个函数对ACPI模块注册了一个回调函数,当AC Adapter发出事件时就触发device->event,然后这个事件会在clock中被受理. 暂时不展开说了.

接下来第568行的for语句,遍历一下device->subdev,执行nouveau_object_inc或者nouveau_subdev_reset.

然后第582行的for语句,再遍历一遍执行nouveau_object_dec. 前面执行一次inc,这里再执行一次dec,也就相当于reset了. 所以这段代码的作用就是reset所有subdev..

但现在subdev还没有被初始化,因此所有if语句都不会进入,所以啥也没做直接返回.

回到nvkm_ioctl_new,第141行,检查engine有没有cclass,有的话创建一个context object,对于这个例子没有.

第151行,创建一个nvif_object对应的nouveau_object:

[cpp] view
plaincopyprint?





// /drivers/gpu/drm/nouveau/core/core/object.c

105 int

106 nouveau_object_ctor(struct nouveau_object *parent,

107 struct nouveau_object *engine,

108 struct nouveau_oclass *oclass, void *data, u32 size,

109 struct nouveau_object **pobject)

110 {

111 struct nouveau_ofuncs *ofuncs = oclass->ofuncs;

112 struct nouveau_object *object = NULL;

113 int ret;

114

115 ret = ofuncs->ctor(parent, engine, oclass, data, size, &object);

116 *pobject = object;

117 if (ret < 0) {

118 if (ret != -ENODEV) {

119 nv_error(parent, "failed to create 0x%08x, %d\n",

120 oclass->handle, ret);

121 }

122

123 if (object) {

124 ofuncs->dtor(object);

125 *pobject = NULL;

126 }

127

128 return ret;

129 }

130

131 if (ret == 0) {

132 nv_trace(object, "created\n");

133 atomic_set(&object->refcount, 1);

134 }

135

136 return 0;

137 }

这个函数就是调用了一下oclass里的ctor函数,然后进行错误检查,出错就销毁一下. 第133行,再初始化一下refcount,返回.

对于这个例子,对应的是"nouveau_devobj_init",这又是一个超级长的函数,所以决定下一篇单独描述这个函数,现在只需要知道它对设备的类型进行了检测,然后初始化了各个subdev就可以了.

再看nvkm_ioctl_new的第156行,对新创建的nouveau_object执行nouveau_object_inc操作,将会调用它的oclass里对应的init函数,对于这个例子是个空函数,无视.

第160行,创建一个nouveau_handle,它将会被自动加入到对应的namedb中,下一次我们就能从namedb中找到这个nouveau_object了.

第165行,执行一个nouveau_handle_init函数,这个函数首先执行nouveau_object_inc(handle->object); 然后对handle->tree链表里储存的所有children进行nouveau_handle_init操作.

然后第166行,把route和token储存到handle里.

最后第171行到第181行,进行一些清理操作,返回. [这些清理操作绝对不会执行任何对象的析构函数,或者导致内存释放. 因为这些对象均已经在其他地方被引用. (除非是出错之后用goto跳过来的,那种情况另说.)]

于是我们一路回到了nvif_device_init, 第43行,发送一个mthd ioctl,作用是获取设备信息储存到device->info里,这个同样留到下一篇在说.

然后我们回到了nouveau_drm_load的第395行,这一篇就先写到这里了.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: