frontend.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. /*
  2. * AGPGART driver frontend
  3. * Copyright (C) 2004 Silicon Graphics, Inc.
  4. * Copyright (C) 2002-2003 Dave Jones
  5. * Copyright (C) 1999 Jeff Hartmann
  6. * Copyright (C) 1999 Precision Insight, Inc.
  7. * Copyright (C) 1999 Xi Graphics, Inc.
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included
  17. * in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
  23. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  24. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  25. * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26. *
  27. */
  28. #include <linux/types.h>
  29. #include <linux/kernel.h>
  30. #include <linux/module.h>
  31. #include <linux/mman.h>
  32. #include <linux/pci.h>
  33. #include <linux/miscdevice.h>
  34. #include <linux/agp_backend.h>
  35. #include <linux/agpgart.h>
  36. #include <linux/slab.h>
  37. #include <linux/mm.h>
  38. #include <linux/fs.h>
  39. #include <linux/sched.h>
  40. #include <linux/uaccess.h>
  41. #include "agp.h"
  42. #include "compat_ioctl.h"
  43. struct agp_front_data agp_fe;
  44. struct agp_memory *agp_find_mem_by_key(int key)
  45. {
  46. struct agp_memory *curr;
  47. if (agp_fe.current_controller == NULL)
  48. return NULL;
  49. curr = agp_fe.current_controller->pool;
  50. while (curr != NULL) {
  51. if (curr->key == key)
  52. break;
  53. curr = curr->next;
  54. }
  55. DBG("key=%d -> mem=%p", key, curr);
  56. return curr;
  57. }
  58. static void agp_remove_from_pool(struct agp_memory *temp)
  59. {
  60. struct agp_memory *prev;
  61. struct agp_memory *next;
  62. /* Check to see if this is even in the memory pool */
  63. DBG("mem=%p", temp);
  64. if (agp_find_mem_by_key(temp->key) != NULL) {
  65. next = temp->next;
  66. prev = temp->prev;
  67. if (prev != NULL) {
  68. prev->next = next;
  69. if (next != NULL)
  70. next->prev = prev;
  71. } else {
  72. /* This is the first item on the list */
  73. if (next != NULL)
  74. next->prev = NULL;
  75. agp_fe.current_controller->pool = next;
  76. }
  77. }
  78. }
  79. /*
  80. * Routines for managing each client's segment list -
  81. * These routines handle adding and removing segments
  82. * to each auth'ed client.
  83. */
  84. static struct
  85. agp_segment_priv *agp_find_seg_in_client(const struct agp_client *client,
  86. unsigned long offset,
  87. int size, pgprot_t page_prot)
  88. {
  89. struct agp_segment_priv *seg;
  90. int i;
  91. off_t pg_start;
  92. size_t pg_count;
  93. pg_start = offset / 4096;
  94. pg_count = size / 4096;
  95. seg = *(client->segments);
  96. for (i = 0; i < client->num_segments; i++) {
  97. if ((seg[i].pg_start == pg_start) &&
  98. (seg[i].pg_count == pg_count) &&
  99. (pgprot_val(seg[i].prot) == pgprot_val(page_prot))) {
  100. return seg + i;
  101. }
  102. }
  103. return NULL;
  104. }
  105. static void agp_remove_seg_from_client(struct agp_client *client)
  106. {
  107. DBG("client=%p", client);
  108. if (client->segments != NULL) {
  109. if (*(client->segments) != NULL) {
  110. DBG("Freeing %p from client %p", *(client->segments), client);
  111. kfree(*(client->segments));
  112. }
  113. DBG("Freeing %p from client %p", client->segments, client);
  114. kfree(client->segments);
  115. client->segments = NULL;
  116. }
  117. }
  118. static void agp_add_seg_to_client(struct agp_client *client,
  119. struct agp_segment_priv ** seg, int num_segments)
  120. {
  121. struct agp_segment_priv **prev_seg;
  122. prev_seg = client->segments;
  123. if (prev_seg != NULL)
  124. agp_remove_seg_from_client(client);
  125. DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client);
  126. client->num_segments = num_segments;
  127. client->segments = seg;
  128. }
  129. static pgprot_t agp_convert_mmap_flags(int prot)
  130. {
  131. unsigned long prot_bits;
  132. prot_bits = calc_vm_prot_bits(prot, 0) | VM_SHARED;
  133. return vm_get_page_prot(prot_bits);
  134. }
  135. int agp_create_segment(struct agp_client *client, struct agp_region *region)
  136. {
  137. struct agp_segment_priv **ret_seg;
  138. struct agp_segment_priv *seg;
  139. struct agp_segment *user_seg;
  140. size_t i;
  141. seg = kzalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL);
  142. if (seg == NULL) {
  143. kfree(region->seg_list);
  144. region->seg_list = NULL;
  145. return -ENOMEM;
  146. }
  147. user_seg = region->seg_list;
  148. for (i = 0; i < region->seg_count; i++) {
  149. seg[i].pg_start = user_seg[i].pg_start;
  150. seg[i].pg_count = user_seg[i].pg_count;
  151. seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot);
  152. }
  153. kfree(region->seg_list);
  154. region->seg_list = NULL;
  155. ret_seg = kmalloc(sizeof(void *), GFP_KERNEL);
  156. if (ret_seg == NULL) {
  157. kfree(seg);
  158. return -ENOMEM;
  159. }
  160. *ret_seg = seg;
  161. agp_add_seg_to_client(client, ret_seg, region->seg_count);
  162. return 0;
  163. }
  164. /* End - Routines for managing each client's segment list */
  165. /* This function must only be called when current_controller != NULL */
  166. static void agp_insert_into_pool(struct agp_memory * temp)
  167. {
  168. struct agp_memory *prev;
  169. prev = agp_fe.current_controller->pool;
  170. if (prev != NULL) {
  171. prev->prev = temp;
  172. temp->next = prev;
  173. }
  174. agp_fe.current_controller->pool = temp;
  175. }
  176. /* File private list routines */
  177. struct agp_file_private *agp_find_private(pid_t pid)
  178. {
  179. struct agp_file_private *curr;
  180. curr = agp_fe.file_priv_list;
  181. while (curr != NULL) {
  182. if (curr->my_pid == pid)
  183. return curr;
  184. curr = curr->next;
  185. }
  186. return NULL;
  187. }
  188. static void agp_insert_file_private(struct agp_file_private * priv)
  189. {
  190. struct agp_file_private *prev;
  191. prev = agp_fe.file_priv_list;
  192. if (prev != NULL)
  193. prev->prev = priv;
  194. priv->next = prev;
  195. agp_fe.file_priv_list = priv;
  196. }
  197. static void agp_remove_file_private(struct agp_file_private * priv)
  198. {
  199. struct agp_file_private *next;
  200. struct agp_file_private *prev;
  201. next = priv->next;
  202. prev = priv->prev;
  203. if (prev != NULL) {
  204. prev->next = next;
  205. if (next != NULL)
  206. next->prev = prev;
  207. } else {
  208. if (next != NULL)
  209. next->prev = NULL;
  210. agp_fe.file_priv_list = next;
  211. }
  212. }
  213. /* End - File flag list routines */
  214. /*
  215. * Wrappers for agp_free_memory & agp_allocate_memory
  216. * These make sure that internal lists are kept updated.
  217. */
  218. void agp_free_memory_wrap(struct agp_memory *memory)
  219. {
  220. agp_remove_from_pool(memory);
  221. agp_free_memory(memory);
  222. }
  223. struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
  224. {
  225. struct agp_memory *memory;
  226. memory = agp_allocate_memory(agp_bridge, pg_count, type);
  227. if (memory == NULL)
  228. return NULL;
  229. agp_insert_into_pool(memory);
  230. return memory;
  231. }
  232. /* Routines for managing the list of controllers -
  233. * These routines manage the current controller, and the list of
  234. * controllers
  235. */
  236. static struct agp_controller *agp_find_controller_by_pid(pid_t id)
  237. {
  238. struct agp_controller *controller;
  239. controller = agp_fe.controllers;
  240. while (controller != NULL) {
  241. if (controller->pid == id)
  242. return controller;
  243. controller = controller->next;
  244. }
  245. return NULL;
  246. }
  247. static struct agp_controller *agp_create_controller(pid_t id)
  248. {
  249. struct agp_controller *controller;
  250. controller = kzalloc(sizeof(struct agp_controller), GFP_KERNEL);
  251. if (controller == NULL)
  252. return NULL;
  253. controller->pid = id;
  254. return controller;
  255. }
  256. static int agp_insert_controller(struct agp_controller *controller)
  257. {
  258. struct agp_controller *prev_controller;
  259. prev_controller = agp_fe.controllers;
  260. controller->next = prev_controller;
  261. if (prev_controller != NULL)
  262. prev_controller->prev = controller;
  263. agp_fe.controllers = controller;
  264. return 0;
  265. }
  266. static void agp_remove_all_clients(struct agp_controller *controller)
  267. {
  268. struct agp_client *client;
  269. struct agp_client *temp;
  270. client = controller->clients;
  271. while (client) {
  272. struct agp_file_private *priv;
  273. temp = client;
  274. agp_remove_seg_from_client(temp);
  275. priv = agp_find_private(temp->pid);
  276. if (priv != NULL) {
  277. clear_bit(AGP_FF_IS_VALID, &priv->access_flags);
  278. clear_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
  279. }
  280. client = client->next;
  281. kfree(temp);
  282. }
  283. }
  284. static void agp_remove_all_memory(struct agp_controller *controller)
  285. {
  286. struct agp_memory *memory;
  287. struct agp_memory *temp;
  288. memory = controller->pool;
  289. while (memory) {
  290. temp = memory;
  291. memory = memory->next;
  292. agp_free_memory_wrap(temp);
  293. }
  294. }
  295. static int agp_remove_controller(struct agp_controller *controller)
  296. {
  297. struct agp_controller *prev_controller;
  298. struct agp_controller *next_controller;
  299. prev_controller = controller->prev;
  300. next_controller = controller->next;
  301. if (prev_controller != NULL) {
  302. prev_controller->next = next_controller;
  303. if (next_controller != NULL)
  304. next_controller->prev = prev_controller;
  305. } else {
  306. if (next_controller != NULL)
  307. next_controller->prev = NULL;
  308. agp_fe.controllers = next_controller;
  309. }
  310. agp_remove_all_memory(controller);
  311. agp_remove_all_clients(controller);
  312. if (agp_fe.current_controller == controller) {
  313. agp_fe.current_controller = NULL;
  314. agp_fe.backend_acquired = false;
  315. agp_backend_release(agp_bridge);
  316. }
  317. kfree(controller);
  318. return 0;
  319. }
  320. static void agp_controller_make_current(struct agp_controller *controller)
  321. {
  322. struct agp_client *clients;
  323. clients = controller->clients;
  324. while (clients != NULL) {
  325. struct agp_file_private *priv;
  326. priv = agp_find_private(clients->pid);
  327. if (priv != NULL) {
  328. set_bit(AGP_FF_IS_VALID, &priv->access_flags);
  329. set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
  330. }
  331. clients = clients->next;
  332. }
  333. agp_fe.current_controller = controller;
  334. }
  335. static void agp_controller_release_current(struct agp_controller *controller,
  336. struct agp_file_private *controller_priv)
  337. {
  338. struct agp_client *clients;
  339. clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags);
  340. clients = controller->clients;
  341. while (clients != NULL) {
  342. struct agp_file_private *priv;
  343. priv = agp_find_private(clients->pid);
  344. if (priv != NULL)
  345. clear_bit(AGP_FF_IS_VALID, &priv->access_flags);
  346. clients = clients->next;
  347. }
  348. agp_fe.current_controller = NULL;
  349. agp_fe.used_by_controller = false;
  350. agp_backend_release(agp_bridge);
  351. }
  352. /*
  353. * Routines for managing client lists -
  354. * These routines are for managing the list of auth'ed clients.
  355. */
  356. static struct agp_client
  357. *agp_find_client_in_controller(struct agp_controller *controller, pid_t id)
  358. {
  359. struct agp_client *client;
  360. if (controller == NULL)
  361. return NULL;
  362. client = controller->clients;
  363. while (client != NULL) {
  364. if (client->pid == id)
  365. return client;
  366. client = client->next;
  367. }
  368. return NULL;
  369. }
  370. static struct agp_controller *agp_find_controller_for_client(pid_t id)
  371. {
  372. struct agp_controller *controller;
  373. controller = agp_fe.controllers;
  374. while (controller != NULL) {
  375. if ((agp_find_client_in_controller(controller, id)) != NULL)
  376. return controller;
  377. controller = controller->next;
  378. }
  379. return NULL;
  380. }
  381. struct agp_client *agp_find_client_by_pid(pid_t id)
  382. {
  383. struct agp_client *temp;
  384. if (agp_fe.current_controller == NULL)
  385. return NULL;
  386. temp = agp_find_client_in_controller(agp_fe.current_controller, id);
  387. return temp;
  388. }
  389. static void agp_insert_client(struct agp_client *client)
  390. {
  391. struct agp_client *prev_client;
  392. prev_client = agp_fe.current_controller->clients;
  393. client->next = prev_client;
  394. if (prev_client != NULL)
  395. prev_client->prev = client;
  396. agp_fe.current_controller->clients = client;
  397. agp_fe.current_controller->num_clients++;
  398. }
  399. struct agp_client *agp_create_client(pid_t id)
  400. {
  401. struct agp_client *new_client;
  402. new_client = kzalloc(sizeof(struct agp_client), GFP_KERNEL);
  403. if (new_client == NULL)
  404. return NULL;
  405. new_client->pid = id;
  406. agp_insert_client(new_client);
  407. return new_client;
  408. }
  409. int agp_remove_client(pid_t id)
  410. {
  411. struct agp_client *client;
  412. struct agp_client *prev_client;
  413. struct agp_client *next_client;
  414. struct agp_controller *controller;
  415. controller = agp_find_controller_for_client(id);
  416. if (controller == NULL)
  417. return -EINVAL;
  418. client = agp_find_client_in_controller(controller, id);
  419. if (client == NULL)
  420. return -EINVAL;
  421. prev_client = client->prev;
  422. next_client = client->next;
  423. if (prev_client != NULL) {
  424. prev_client->next = next_client;
  425. if (next_client != NULL)
  426. next_client->prev = prev_client;
  427. } else {
  428. if (next_client != NULL)
  429. next_client->prev = NULL;
  430. controller->clients = next_client;
  431. }
  432. controller->num_clients--;
  433. agp_remove_seg_from_client(client);
  434. kfree(client);
  435. return 0;
  436. }
  437. /* End - Routines for managing client lists */
  438. /* File Operations */
  439. static int agp_mmap(struct file *file, struct vm_area_struct *vma)
  440. {
  441. unsigned int size, current_size;
  442. unsigned long offset;
  443. struct agp_client *client;
  444. struct agp_file_private *priv = file->private_data;
  445. struct agp_kern_info kerninfo;
  446. mutex_lock(&(agp_fe.agp_mutex));
  447. if (agp_fe.backend_acquired != true)
  448. goto out_eperm;
  449. if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))
  450. goto out_eperm;
  451. agp_copy_info(agp_bridge, &kerninfo);
  452. size = vma->vm_end - vma->vm_start;
  453. current_size = kerninfo.aper_size;
  454. current_size = current_size * 0x100000;
  455. offset = vma->vm_pgoff << PAGE_SHIFT;
  456. DBG("%lx:%lx", offset, offset+size);
  457. if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
  458. if ((size + offset) > current_size)
  459. goto out_inval;
  460. client = agp_find_client_by_pid(current->pid);
  461. if (client == NULL)
  462. goto out_eperm;
  463. if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot))
  464. goto out_inval;
  465. DBG("client vm_ops=%p", kerninfo.vm_ops);
  466. if (kerninfo.vm_ops) {
  467. vma->vm_ops = kerninfo.vm_ops;
  468. } else if (io_remap_pfn_range(vma, vma->vm_start,
  469. (kerninfo.aper_base + offset) >> PAGE_SHIFT,
  470. size,
  471. pgprot_writecombine(vma->vm_page_prot))) {
  472. goto out_again;
  473. }
  474. mutex_unlock(&(agp_fe.agp_mutex));
  475. return 0;
  476. }
  477. if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
  478. if (size != current_size)
  479. goto out_inval;
  480. DBG("controller vm_ops=%p", kerninfo.vm_ops);
  481. if (kerninfo.vm_ops) {
  482. vma->vm_ops = kerninfo.vm_ops;
  483. } else if (io_remap_pfn_range(vma, vma->vm_start,
  484. kerninfo.aper_base >> PAGE_SHIFT,
  485. size,
  486. pgprot_writecombine(vma->vm_page_prot))) {
  487. goto out_again;
  488. }
  489. mutex_unlock(&(agp_fe.agp_mutex));
  490. return 0;
  491. }
  492. out_eperm:
  493. mutex_unlock(&(agp_fe.agp_mutex));
  494. return -EPERM;
  495. out_inval:
  496. mutex_unlock(&(agp_fe.agp_mutex));
  497. return -EINVAL;
  498. out_again:
  499. mutex_unlock(&(agp_fe.agp_mutex));
  500. return -EAGAIN;
  501. }
  502. static int agp_release(struct inode *inode, struct file *file)
  503. {
  504. struct agp_file_private *priv = file->private_data;
  505. mutex_lock(&(agp_fe.agp_mutex));
  506. DBG("priv=%p", priv);
  507. if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
  508. struct agp_controller *controller;
  509. controller = agp_find_controller_by_pid(priv->my_pid);
  510. if (controller != NULL) {
  511. if (controller == agp_fe.current_controller)
  512. agp_controller_release_current(controller, priv);
  513. agp_remove_controller(controller);
  514. controller = NULL;
  515. }
  516. }
  517. if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags))
  518. agp_remove_client(priv->my_pid);
  519. agp_remove_file_private(priv);
  520. kfree(priv);
  521. file->private_data = NULL;
  522. mutex_unlock(&(agp_fe.agp_mutex));
  523. return 0;
  524. }
  525. static int agp_open(struct inode *inode, struct file *file)
  526. {
  527. int minor = iminor(inode);
  528. struct agp_file_private *priv;
  529. struct agp_client *client;
  530. if (minor != AGPGART_MINOR)
  531. return -ENXIO;
  532. mutex_lock(&(agp_fe.agp_mutex));
  533. priv = kzalloc(sizeof(struct agp_file_private), GFP_KERNEL);
  534. if (priv == NULL) {
  535. mutex_unlock(&(agp_fe.agp_mutex));
  536. return -ENOMEM;
  537. }
  538. set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);
  539. priv->my_pid = current->pid;
  540. if (capable(CAP_SYS_RAWIO))
  541. /* Root priv, can be controller */
  542. set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags);
  543. client = agp_find_client_by_pid(current->pid);
  544. if (client != NULL) {
  545. set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
  546. set_bit(AGP_FF_IS_VALID, &priv->access_flags);
  547. }
  548. file->private_data = (void *) priv;
  549. agp_insert_file_private(priv);
  550. DBG("private=%p, client=%p", priv, client);
  551. mutex_unlock(&(agp_fe.agp_mutex));
  552. return 0;
  553. }
  554. static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
  555. {
  556. struct agp_info userinfo;
  557. struct agp_kern_info kerninfo;
  558. agp_copy_info(agp_bridge, &kerninfo);
  559. memset(&userinfo, 0, sizeof(userinfo));
  560. userinfo.version.major = kerninfo.version.major;
  561. userinfo.version.minor = kerninfo.version.minor;
  562. userinfo.bridge_id = kerninfo.device->vendor |
  563. (kerninfo.device->device << 16);
  564. userinfo.agp_mode = kerninfo.mode;
  565. userinfo.aper_base = kerninfo.aper_base;
  566. userinfo.aper_size = kerninfo.aper_size;
  567. userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
  568. userinfo.pg_used = kerninfo.current_memory;
  569. if (copy_to_user(arg, &userinfo, sizeof(struct agp_info)))
  570. return -EFAULT;
  571. return 0;
  572. }
  573. int agpioc_acquire_wrap(struct agp_file_private *priv)
  574. {
  575. struct agp_controller *controller;
  576. DBG("");
  577. if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags)))
  578. return -EPERM;
  579. if (agp_fe.current_controller != NULL)
  580. return -EBUSY;
  581. if (!agp_bridge)
  582. return -ENODEV;
  583. if (atomic_read(&agp_bridge->agp_in_use))
  584. return -EBUSY;
  585. atomic_inc(&agp_bridge->agp_in_use);
  586. agp_fe.backend_acquired = true;
  587. controller = agp_find_controller_by_pid(priv->my_pid);
  588. if (controller != NULL) {
  589. agp_controller_make_current(controller);
  590. } else {
  591. controller = agp_create_controller(priv->my_pid);
  592. if (controller == NULL) {
  593. agp_fe.backend_acquired = false;
  594. agp_backend_release(agp_bridge);
  595. return -ENOMEM;
  596. }
  597. agp_insert_controller(controller);
  598. agp_controller_make_current(controller);
  599. }
  600. set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags);
  601. set_bit(AGP_FF_IS_VALID, &priv->access_flags);
  602. return 0;
  603. }
  604. int agpioc_release_wrap(struct agp_file_private *priv)
  605. {
  606. DBG("");
  607. agp_controller_release_current(agp_fe.current_controller, priv);
  608. return 0;
  609. }
  610. int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
  611. {
  612. struct agp_setup mode;
  613. DBG("");
  614. if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
  615. return -EFAULT;
  616. agp_enable(agp_bridge, mode.agp_mode);
  617. return 0;
  618. }
  619. static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
  620. {
  621. struct agp_region reserve;
  622. struct agp_client *client;
  623. struct agp_file_private *client_priv;
  624. DBG("");
  625. if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
  626. return -EFAULT;
  627. if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
  628. return -EFAULT;
  629. client = agp_find_client_by_pid(reserve.pid);
  630. if (reserve.seg_count == 0) {
  631. /* remove a client */
  632. client_priv = agp_find_private(reserve.pid);
  633. if (client_priv != NULL) {
  634. set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
  635. set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
  636. }
  637. if (client == NULL) {
  638. /* client is already removed */
  639. return 0;
  640. }
  641. return agp_remove_client(reserve.pid);
  642. } else {
  643. struct agp_segment *segment;
  644. if (reserve.seg_count >= 16384)
  645. return -EINVAL;
  646. segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count),
  647. GFP_KERNEL);
  648. if (segment == NULL)
  649. return -ENOMEM;
  650. if (copy_from_user(segment, (void __user *) reserve.seg_list,
  651. sizeof(struct agp_segment) * reserve.seg_count)) {
  652. kfree(segment);
  653. return -EFAULT;
  654. }
  655. reserve.seg_list = segment;
  656. if (client == NULL) {
  657. /* Create the client and add the segment */
  658. client = agp_create_client(reserve.pid);
  659. if (client == NULL) {
  660. kfree(segment);
  661. return -ENOMEM;
  662. }
  663. client_priv = agp_find_private(reserve.pid);
  664. if (client_priv != NULL) {
  665. set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
  666. set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
  667. }
  668. }
  669. return agp_create_segment(client, &reserve);
  670. }
  671. /* Will never really happen */
  672. return -EINVAL;
  673. }
  674. int agpioc_protect_wrap(struct agp_file_private *priv)
  675. {
  676. DBG("");
  677. /* This function is not currently implemented */
  678. return -EINVAL;
  679. }
  680. static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
  681. {
  682. struct agp_memory *memory;
  683. struct agp_allocate alloc;
  684. DBG("");
  685. if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
  686. return -EFAULT;
  687. if (alloc.type >= AGP_USER_TYPES)
  688. return -EINVAL;
  689. memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
  690. if (memory == NULL)
  691. return -ENOMEM;
  692. alloc.key = memory->key;
  693. alloc.physical = memory->physical;
  694. if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) {
  695. agp_free_memory_wrap(memory);
  696. return -EFAULT;
  697. }
  698. return 0;
  699. }
  700. int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
  701. {
  702. struct agp_memory *memory;
  703. DBG("");
  704. memory = agp_find_mem_by_key(arg);
  705. if (memory == NULL)
  706. return -EINVAL;
  707. agp_free_memory_wrap(memory);
  708. return 0;
  709. }
  710. static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
  711. {
  712. struct agp_bind bind_info;
  713. struct agp_memory *memory;
  714. DBG("");
  715. if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind)))
  716. return -EFAULT;
  717. memory = agp_find_mem_by_key(bind_info.key);
  718. if (memory == NULL)
  719. return -EINVAL;
  720. return agp_bind_memory(memory, bind_info.pg_start);
  721. }
  722. static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
  723. {
  724. struct agp_memory *memory;
  725. struct agp_unbind unbind;
  726. DBG("");
  727. if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind)))
  728. return -EFAULT;
  729. memory = agp_find_mem_by_key(unbind.key);
  730. if (memory == NULL)
  731. return -EINVAL;
  732. return agp_unbind_memory(memory);
  733. }
  734. static long agp_ioctl(struct file *file,
  735. unsigned int cmd, unsigned long arg)
  736. {
  737. struct agp_file_private *curr_priv = file->private_data;
  738. int ret_val = -ENOTTY;
  739. DBG("priv=%p, cmd=%x", curr_priv, cmd);
  740. mutex_lock(&(agp_fe.agp_mutex));
  741. if ((agp_fe.current_controller == NULL) &&
  742. (cmd != AGPIOC_ACQUIRE)) {
  743. ret_val = -EINVAL;
  744. goto ioctl_out;
  745. }
  746. if ((agp_fe.backend_acquired != true) &&
  747. (cmd != AGPIOC_ACQUIRE)) {
  748. ret_val = -EBUSY;
  749. goto ioctl_out;
  750. }
  751. if (cmd != AGPIOC_ACQUIRE) {
  752. if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
  753. ret_val = -EPERM;
  754. goto ioctl_out;
  755. }
  756. /* Use the original pid of the controller,
  757. * in case it's threaded */
  758. if (agp_fe.current_controller->pid != curr_priv->my_pid) {
  759. ret_val = -EBUSY;
  760. goto ioctl_out;
  761. }
  762. }
  763. switch (cmd) {
  764. case AGPIOC_INFO:
  765. ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg);
  766. break;
  767. case AGPIOC_ACQUIRE:
  768. ret_val = agpioc_acquire_wrap(curr_priv);
  769. break;
  770. case AGPIOC_RELEASE:
  771. ret_val = agpioc_release_wrap(curr_priv);
  772. break;
  773. case AGPIOC_SETUP:
  774. ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
  775. break;
  776. case AGPIOC_RESERVE:
  777. ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);
  778. break;
  779. case AGPIOC_PROTECT:
  780. ret_val = agpioc_protect_wrap(curr_priv);
  781. break;
  782. case AGPIOC_ALLOCATE:
  783. ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);
  784. break;
  785. case AGPIOC_DEALLOCATE:
  786. ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
  787. break;
  788. case AGPIOC_BIND:
  789. ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);
  790. break;
  791. case AGPIOC_UNBIND:
  792. ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
  793. break;
  794. case AGPIOC_CHIPSET_FLUSH:
  795. break;
  796. }
  797. ioctl_out:
  798. DBG("ioctl returns %d\n", ret_val);
  799. mutex_unlock(&(agp_fe.agp_mutex));
  800. return ret_val;
  801. }
  802. static const struct file_operations agp_fops =
  803. {
  804. .owner = THIS_MODULE,
  805. .llseek = no_llseek,
  806. .unlocked_ioctl = agp_ioctl,
  807. #ifdef CONFIG_COMPAT
  808. .compat_ioctl = compat_agp_ioctl,
  809. #endif
  810. .mmap = agp_mmap,
  811. .open = agp_open,
  812. .release = agp_release,
  813. };
  814. static struct miscdevice agp_miscdev =
  815. {
  816. .minor = AGPGART_MINOR,
  817. .name = "agpgart",
  818. .fops = &agp_fops
  819. };
  820. int agp_frontend_initialize(void)
  821. {
  822. memset(&agp_fe, 0, sizeof(struct agp_front_data));
  823. mutex_init(&(agp_fe.agp_mutex));
  824. if (misc_register(&agp_miscdev)) {
  825. printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
  826. return -EIO;
  827. }
  828. return 0;
  829. }
  830. void agp_frontend_cleanup(void)
  831. {
  832. misc_deregister(&agp_miscdev);
  833. }