dasd_devmap.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  1. /*
  2. * File...........: linux/drivers/s390/block/dasd_devmap.c
  3. * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  4. * Horst Hummel <Horst.Hummel@de.ibm.com>
  5. * Carsten Otte <Cotte@de.ibm.com>
  6. * Martin Schwidefsky <schwidefsky@de.ibm.com>
  7. * Bugreports.to..: <Linux390@de.ibm.com>
  8. * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  9. *
  10. * Device mapping and dasd= parameter parsing functions. All devmap
  11. * functions may not be called from interrupt context. In particular
  12. * dasd_get_device is a no-no from interrupt context.
  13. *
  14. */
  15. #include <linux/config.h>
  16. #include <linux/ctype.h>
  17. #include <linux/init.h>
  18. #include <linux/module.h>
  19. #include <asm/debug.h>
  20. #include <asm/uaccess.h>
  21. /* This is ugly... */
  22. #define PRINTK_HEADER "dasd_devmap:"
  23. #include "dasd_int.h"
  24. kmem_cache_t *dasd_page_cache;
  25. EXPORT_SYMBOL(dasd_page_cache);
  26. /*
  27. * dasd_devmap_t is used to store the features and the relation
  28. * between device number and device index. To find a dasd_devmap_t
  29. * that corresponds to a device number of a device index each
  30. * dasd_devmap_t is added to two linked lists, one to search by
  31. * the device number and one to search by the device index. As
  32. * soon as big minor numbers are available the device index list
  33. * can be removed since the device number will then be identical
  34. * to the device index.
  35. */
  36. struct dasd_devmap {
  37. struct list_head list;
  38. char bus_id[BUS_ID_SIZE];
  39. unsigned int devindex;
  40. unsigned short features;
  41. struct dasd_device *device;
  42. struct dasd_uid uid;
  43. };
  44. /*
  45. * Parameter parsing functions for dasd= parameter. The syntax is:
  46. * <devno> : (0x)?[0-9a-fA-F]+
  47. * <busid> : [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+
  48. * <feature> : ro
  49. * <feature_list> : \(<feature>(:<feature>)*\)
  50. * <devno-range> : <devno>(-<devno>)?<feature_list>?
  51. * <busid-range> : <busid>(-<busid>)?<feature_list>?
  52. * <devices> : <devno-range>|<busid-range>
  53. * <dasd_module> : dasd_diag_mod|dasd_eckd_mod|dasd_fba_mod
  54. *
  55. * <dasd> : autodetect|probeonly|<devices>(,<devices>)*
  56. */
  57. int dasd_probeonly = 0; /* is true, when probeonly mode is active */
  58. int dasd_autodetect = 0; /* is true, when autodetection is active */
  59. /*
  60. * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
  61. * it is named 'dasd' to directly be filled by insmod with the comma separated
  62. * strings when running as a module.
  63. */
  64. static char *dasd[256];
  65. module_param_array(dasd, charp, NULL, 0);
  66. /*
  67. * Single spinlock to protect devmap structures and lists.
  68. */
  69. static DEFINE_SPINLOCK(dasd_devmap_lock);
  70. /*
  71. * Hash lists for devmap structures.
  72. */
  73. static struct list_head dasd_hashlists[256];
  74. int dasd_max_devindex;
  75. static struct dasd_devmap *dasd_add_busid(char *, int);
  76. static inline int
  77. dasd_hash_busid(char *bus_id)
  78. {
  79. int hash, i;
  80. hash = 0;
  81. for (i = 0; (i < BUS_ID_SIZE) && *bus_id; i++, bus_id++)
  82. hash += *bus_id;
  83. return hash & 0xff;
  84. }
  85. #ifndef MODULE
  86. /*
  87. * The parameter parsing functions for builtin-drivers are called
  88. * before kmalloc works. Store the pointers to the parameters strings
  89. * into dasd[] for later processing.
  90. */
  91. static int __init
  92. dasd_call_setup(char *str)
  93. {
  94. static int count = 0;
  95. if (count < 256)
  96. dasd[count++] = str;
  97. return 1;
  98. }
  99. __setup ("dasd=", dasd_call_setup);
  100. #endif /* #ifndef MODULE */
  101. /*
  102. * Read a device busid/devno from a string.
  103. */
  104. static inline int
  105. dasd_busid(char **str, int *id0, int *id1, int *devno)
  106. {
  107. int val, old_style;
  108. /* check for leading '0x' */
  109. old_style = 0;
  110. if ((*str)[0] == '0' && (*str)[1] == 'x') {
  111. *str += 2;
  112. old_style = 1;
  113. }
  114. if (!isxdigit((*str)[0])) /* We require at least one hex digit */
  115. return -EINVAL;
  116. val = simple_strtoul(*str, str, 16);
  117. if (old_style || (*str)[0] != '.') {
  118. *id0 = *id1 = 0;
  119. if (val < 0 || val > 0xffff)
  120. return -EINVAL;
  121. *devno = val;
  122. return 0;
  123. }
  124. /* New style x.y.z busid */
  125. if (val < 0 || val > 0xff)
  126. return -EINVAL;
  127. *id0 = val;
  128. (*str)++;
  129. if (!isxdigit((*str)[0])) /* We require at least one hex digit */
  130. return -EINVAL;
  131. val = simple_strtoul(*str, str, 16);
  132. if (val < 0 || val > 0xff || (*str)++[0] != '.')
  133. return -EINVAL;
  134. *id1 = val;
  135. if (!isxdigit((*str)[0])) /* We require at least one hex digit */
  136. return -EINVAL;
  137. val = simple_strtoul(*str, str, 16);
  138. if (val < 0 || val > 0xffff)
  139. return -EINVAL;
  140. *devno = val;
  141. return 0;
  142. }
  143. /*
  144. * Read colon separated list of dasd features. Currently there is
  145. * only one: "ro" for read-only devices. The default feature set
  146. * is empty (value 0).
  147. */
  148. static inline int
  149. dasd_feature_list(char *str, char **endp)
  150. {
  151. int features, len, rc;
  152. rc = 0;
  153. if (*str != '(') {
  154. *endp = str;
  155. return DASD_FEATURE_DEFAULT;
  156. }
  157. str++;
  158. features = 0;
  159. while (1) {
  160. for (len = 0;
  161. str[len] && str[len] != ':' && str[len] != ')'; len++);
  162. if (len == 2 && !strncmp(str, "ro", 2))
  163. features |= DASD_FEATURE_READONLY;
  164. else if (len == 4 && !strncmp(str, "diag", 4))
  165. features |= DASD_FEATURE_USEDIAG;
  166. else {
  167. MESSAGE(KERN_WARNING,
  168. "unsupported feature: %*s, "
  169. "ignoring setting", len, str);
  170. rc = -EINVAL;
  171. }
  172. str += len;
  173. if (*str != ':')
  174. break;
  175. str++;
  176. }
  177. if (*str != ')') {
  178. MESSAGE(KERN_WARNING, "%s",
  179. "missing ')' in dasd parameter string\n");
  180. rc = -EINVAL;
  181. } else
  182. str++;
  183. *endp = str;
  184. if (rc != 0)
  185. return rc;
  186. return features;
  187. }
  188. /*
  189. * Try to match the first element on the comma separated parse string
  190. * with one of the known keywords. If a keyword is found, take the approprate
  191. * action and return a pointer to the residual string. If the first element
  192. * could not be matched to any keyword then return an error code.
  193. */
  194. static char *
  195. dasd_parse_keyword( char *parsestring ) {
  196. char *nextcomma, *residual_str;
  197. int length;
  198. nextcomma = strchr(parsestring,',');
  199. if (nextcomma) {
  200. length = nextcomma - parsestring;
  201. residual_str = nextcomma + 1;
  202. } else {
  203. length = strlen(parsestring);
  204. residual_str = parsestring + length;
  205. }
  206. if (strncmp ("autodetect", parsestring, length) == 0) {
  207. dasd_autodetect = 1;
  208. MESSAGE (KERN_INFO, "%s",
  209. "turning to autodetection mode");
  210. return residual_str;
  211. }
  212. if (strncmp ("probeonly", parsestring, length) == 0) {
  213. dasd_probeonly = 1;
  214. MESSAGE(KERN_INFO, "%s",
  215. "turning to probeonly mode");
  216. return residual_str;
  217. }
  218. if (strncmp ("fixedbuffers", parsestring, length) == 0) {
  219. if (dasd_page_cache)
  220. return residual_str;
  221. dasd_page_cache =
  222. kmem_cache_create("dasd_page_cache", PAGE_SIZE, 0,
  223. SLAB_CACHE_DMA, NULL, NULL );
  224. if (!dasd_page_cache)
  225. MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
  226. "fixed buffer mode disabled.");
  227. else
  228. MESSAGE (KERN_INFO, "%s",
  229. "turning on fixed buffer mode");
  230. return residual_str;
  231. }
  232. return ERR_PTR(-EINVAL);
  233. }
  234. /*
  235. * Try to interprete the first element on the comma separated parse string
  236. * as a device number or a range of devices. If the interpretation is
  237. * successfull, create the matching dasd_devmap entries and return a pointer
  238. * to the residual string.
  239. * If interpretation fails or in case of an error, return an error code.
  240. */
  241. static char *
  242. dasd_parse_range( char *parsestring ) {
  243. struct dasd_devmap *devmap;
  244. int from, from_id0, from_id1;
  245. int to, to_id0, to_id1;
  246. int features, rc;
  247. char bus_id[BUS_ID_SIZE+1], *str;
  248. str = parsestring;
  249. rc = dasd_busid(&str, &from_id0, &from_id1, &from);
  250. if (rc == 0) {
  251. to = from;
  252. to_id0 = from_id0;
  253. to_id1 = from_id1;
  254. if (*str == '-') {
  255. str++;
  256. rc = dasd_busid(&str, &to_id0, &to_id1, &to);
  257. }
  258. }
  259. if (rc == 0 &&
  260. (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
  261. rc = -EINVAL;
  262. if (rc) {
  263. MESSAGE(KERN_ERR, "Invalid device range %s", parsestring);
  264. return ERR_PTR(rc);
  265. }
  266. features = dasd_feature_list(str, &str);
  267. if (features < 0)
  268. return ERR_PTR(-EINVAL);
  269. while (from <= to) {
  270. sprintf(bus_id, "%01x.%01x.%04x",
  271. from_id0, from_id1, from++);
  272. devmap = dasd_add_busid(bus_id, features);
  273. if (IS_ERR(devmap))
  274. return (char *)devmap;
  275. }
  276. if (*str == ',')
  277. return str + 1;
  278. if (*str == '\0')
  279. return str;
  280. MESSAGE(KERN_WARNING,
  281. "junk at end of dasd parameter string: %s\n", str);
  282. return ERR_PTR(-EINVAL);
  283. }
  284. static inline char *
  285. dasd_parse_next_element( char *parsestring ) {
  286. char * residual_str;
  287. residual_str = dasd_parse_keyword(parsestring);
  288. if (!IS_ERR(residual_str))
  289. return residual_str;
  290. residual_str = dasd_parse_range(parsestring);
  291. return residual_str;
  292. }
  293. /*
  294. * Parse parameters stored in dasd[]
  295. * The 'dasd=...' parameter allows to specify a comma separated list of
  296. * keywords and device ranges. When the dasd driver is build into the kernel,
  297. * the complete list will be stored as one element of the dasd[] array.
  298. * When the dasd driver is build as a module, then the list is broken into
  299. * it's elements and each dasd[] entry contains one element.
  300. */
  301. int
  302. dasd_parse(void)
  303. {
  304. int rc, i;
  305. char *parsestring;
  306. rc = 0;
  307. for (i = 0; i < 256; i++) {
  308. if (dasd[i] == NULL)
  309. break;
  310. parsestring = dasd[i];
  311. /* loop over the comma separated list in the parsestring */
  312. while (*parsestring) {
  313. parsestring = dasd_parse_next_element(parsestring);
  314. if(IS_ERR(parsestring)) {
  315. rc = PTR_ERR(parsestring);
  316. break;
  317. }
  318. }
  319. if (rc) {
  320. DBF_EVENT(DBF_ALERT, "%s", "invalid range found");
  321. break;
  322. }
  323. }
  324. return rc;
  325. }
  326. /*
  327. * Add a devmap for the device specified by busid. It is possible that
  328. * the devmap already exists (dasd= parameter). The order of the devices
  329. * added through this function will define the kdevs for the individual
  330. * devices.
  331. */
  332. static struct dasd_devmap *
  333. dasd_add_busid(char *bus_id, int features)
  334. {
  335. struct dasd_devmap *devmap, *new, *tmp;
  336. int hash;
  337. new = (struct dasd_devmap *)
  338. kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
  339. if (!new)
  340. return ERR_PTR(-ENOMEM);
  341. spin_lock(&dasd_devmap_lock);
  342. devmap = 0;
  343. hash = dasd_hash_busid(bus_id);
  344. list_for_each_entry(tmp, &dasd_hashlists[hash], list)
  345. if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
  346. devmap = tmp;
  347. break;
  348. }
  349. if (!devmap) {
  350. /* This bus_id is new. */
  351. new->devindex = dasd_max_devindex++;
  352. strncpy(new->bus_id, bus_id, BUS_ID_SIZE);
  353. new->features = features;
  354. new->device = 0;
  355. list_add(&new->list, &dasd_hashlists[hash]);
  356. devmap = new;
  357. new = 0;
  358. }
  359. spin_unlock(&dasd_devmap_lock);
  360. kfree(new);
  361. return devmap;
  362. }
  363. /*
  364. * Find devmap for device with given bus_id.
  365. */
  366. static struct dasd_devmap *
  367. dasd_find_busid(char *bus_id)
  368. {
  369. struct dasd_devmap *devmap, *tmp;
  370. int hash;
  371. spin_lock(&dasd_devmap_lock);
  372. devmap = ERR_PTR(-ENODEV);
  373. hash = dasd_hash_busid(bus_id);
  374. list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
  375. if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
  376. devmap = tmp;
  377. break;
  378. }
  379. }
  380. spin_unlock(&dasd_devmap_lock);
  381. return devmap;
  382. }
  383. /*
  384. * Check if busid has been added to the list of dasd ranges.
  385. */
  386. int
  387. dasd_busid_known(char *bus_id)
  388. {
  389. return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
  390. }
  391. /*
  392. * Forget all about the device numbers added so far.
  393. * This may only be called at module unload or system shutdown.
  394. */
  395. static void
  396. dasd_forget_ranges(void)
  397. {
  398. struct dasd_devmap *devmap, *n;
  399. int i;
  400. spin_lock(&dasd_devmap_lock);
  401. for (i = 0; i < 256; i++) {
  402. list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
  403. BUG_ON(devmap->device != NULL);
  404. list_del(&devmap->list);
  405. kfree(devmap);
  406. }
  407. }
  408. spin_unlock(&dasd_devmap_lock);
  409. }
  410. /*
  411. * Find the device struct by its device index.
  412. */
  413. struct dasd_device *
  414. dasd_device_from_devindex(int devindex)
  415. {
  416. struct dasd_devmap *devmap, *tmp;
  417. struct dasd_device *device;
  418. int i;
  419. spin_lock(&dasd_devmap_lock);
  420. devmap = 0;
  421. for (i = 0; (i < 256) && !devmap; i++)
  422. list_for_each_entry(tmp, &dasd_hashlists[i], list)
  423. if (tmp->devindex == devindex) {
  424. /* Found the devmap for the device. */
  425. devmap = tmp;
  426. break;
  427. }
  428. if (devmap && devmap->device) {
  429. device = devmap->device;
  430. dasd_get_device(device);
  431. } else
  432. device = ERR_PTR(-ENODEV);
  433. spin_unlock(&dasd_devmap_lock);
  434. return device;
  435. }
  436. /*
  437. * Return devmap for cdev. If no devmap exists yet, create one and
  438. * connect it to the cdev.
  439. */
  440. static struct dasd_devmap *
  441. dasd_devmap_from_cdev(struct ccw_device *cdev)
  442. {
  443. struct dasd_devmap *devmap;
  444. devmap = dasd_find_busid(cdev->dev.bus_id);
  445. if (IS_ERR(devmap))
  446. devmap = dasd_add_busid(cdev->dev.bus_id,
  447. DASD_FEATURE_DEFAULT);
  448. return devmap;
  449. }
  450. /*
  451. * Create a dasd device structure for cdev.
  452. */
  453. struct dasd_device *
  454. dasd_create_device(struct ccw_device *cdev)
  455. {
  456. struct dasd_devmap *devmap;
  457. struct dasd_device *device;
  458. int rc;
  459. devmap = dasd_devmap_from_cdev(cdev);
  460. if (IS_ERR(devmap))
  461. return (void *) devmap;
  462. cdev->dev.driver_data = devmap;
  463. device = dasd_alloc_device();
  464. if (IS_ERR(device))
  465. return device;
  466. atomic_set(&device->ref_count, 2);
  467. spin_lock(&dasd_devmap_lock);
  468. if (!devmap->device) {
  469. devmap->device = device;
  470. device->devindex = devmap->devindex;
  471. device->features = devmap->features;
  472. get_device(&cdev->dev);
  473. device->cdev = cdev;
  474. rc = 0;
  475. } else
  476. /* Someone else was faster. */
  477. rc = -EBUSY;
  478. spin_unlock(&dasd_devmap_lock);
  479. if (rc) {
  480. dasd_free_device(device);
  481. return ERR_PTR(rc);
  482. }
  483. return device;
  484. }
  485. /*
  486. * Wait queue for dasd_delete_device waits.
  487. */
  488. static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
  489. /*
  490. * Remove a dasd device structure. The passed referenced
  491. * is destroyed.
  492. */
  493. void
  494. dasd_delete_device(struct dasd_device *device)
  495. {
  496. struct ccw_device *cdev;
  497. struct dasd_devmap *devmap;
  498. /* First remove device pointer from devmap. */
  499. devmap = dasd_find_busid(device->cdev->dev.bus_id);
  500. BUG_ON(IS_ERR(devmap));
  501. spin_lock(&dasd_devmap_lock);
  502. if (devmap->device != device) {
  503. spin_unlock(&dasd_devmap_lock);
  504. dasd_put_device(device);
  505. return;
  506. }
  507. devmap->device = NULL;
  508. spin_unlock(&dasd_devmap_lock);
  509. /* Drop ref_count by 2, one for the devmap reference and
  510. * one for the passed reference. */
  511. atomic_sub(2, &device->ref_count);
  512. /* Wait for reference counter to drop to zero. */
  513. wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
  514. /* Disconnect dasd_device structure from ccw_device structure. */
  515. cdev = device->cdev;
  516. device->cdev = NULL;
  517. /* Disconnect dasd_devmap structure from ccw_device structure. */
  518. cdev->dev.driver_data = NULL;
  519. /* Put ccw_device structure. */
  520. put_device(&cdev->dev);
  521. /* Now the device structure can be freed. */
  522. dasd_free_device(device);
  523. }
  524. /*
  525. * Reference counter dropped to zero. Wake up waiter
  526. * in dasd_delete_device.
  527. */
  528. void
  529. dasd_put_device_wake(struct dasd_device *device)
  530. {
  531. wake_up(&dasd_delete_wq);
  532. }
  533. /*
  534. * Return dasd_device structure associated with cdev.
  535. */
  536. struct dasd_device *
  537. dasd_device_from_cdev(struct ccw_device *cdev)
  538. {
  539. struct dasd_devmap *devmap;
  540. struct dasd_device *device;
  541. device = ERR_PTR(-ENODEV);
  542. spin_lock(&dasd_devmap_lock);
  543. devmap = cdev->dev.driver_data;
  544. if (devmap && devmap->device) {
  545. device = devmap->device;
  546. dasd_get_device(device);
  547. }
  548. spin_unlock(&dasd_devmap_lock);
  549. return device;
  550. }
  551. /*
  552. * SECTION: files in sysfs
  553. */
  554. /*
  555. * readonly controls the readonly status of a dasd
  556. */
  557. static ssize_t
  558. dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
  559. {
  560. struct dasd_devmap *devmap;
  561. int ro_flag;
  562. devmap = dasd_find_busid(dev->bus_id);
  563. if (!IS_ERR(devmap))
  564. ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
  565. else
  566. ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
  567. return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
  568. }
  569. static ssize_t
  570. dasd_ro_store(struct device *dev, struct device_attribute *attr,
  571. const char *buf, size_t count)
  572. {
  573. struct dasd_devmap *devmap;
  574. int ro_flag;
  575. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  576. if (IS_ERR(devmap))
  577. return PTR_ERR(devmap);
  578. ro_flag = buf[0] == '1';
  579. spin_lock(&dasd_devmap_lock);
  580. if (ro_flag)
  581. devmap->features |= DASD_FEATURE_READONLY;
  582. else
  583. devmap->features &= ~DASD_FEATURE_READONLY;
  584. if (devmap->device)
  585. devmap->device->features = devmap->features;
  586. if (devmap->device && devmap->device->gdp)
  587. set_disk_ro(devmap->device->gdp, ro_flag);
  588. spin_unlock(&dasd_devmap_lock);
  589. return count;
  590. }
  591. static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
  592. /*
  593. * use_diag controls whether the driver should use diag rather than ssch
  594. * to talk to the device
  595. */
  596. static ssize_t
  597. dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
  598. {
  599. struct dasd_devmap *devmap;
  600. int use_diag;
  601. devmap = dasd_find_busid(dev->bus_id);
  602. if (!IS_ERR(devmap))
  603. use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
  604. else
  605. use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
  606. return sprintf(buf, use_diag ? "1\n" : "0\n");
  607. }
  608. static ssize_t
  609. dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
  610. const char *buf, size_t count)
  611. {
  612. struct dasd_devmap *devmap;
  613. ssize_t rc;
  614. int use_diag;
  615. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  616. if (IS_ERR(devmap))
  617. return PTR_ERR(devmap);
  618. use_diag = buf[0] == '1';
  619. spin_lock(&dasd_devmap_lock);
  620. /* Changing diag discipline flag is only allowed in offline state. */
  621. rc = count;
  622. if (!devmap->device) {
  623. if (use_diag)
  624. devmap->features |= DASD_FEATURE_USEDIAG;
  625. else
  626. devmap->features &= ~DASD_FEATURE_USEDIAG;
  627. } else
  628. rc = -EPERM;
  629. spin_unlock(&dasd_devmap_lock);
  630. return rc;
  631. }
  632. static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
  633. static ssize_t
  634. dasd_discipline_show(struct device *dev, struct device_attribute *attr,
  635. char *buf)
  636. {
  637. struct dasd_devmap *devmap;
  638. char *dname;
  639. spin_lock(&dasd_devmap_lock);
  640. dname = "none";
  641. devmap = dev->driver_data;
  642. if (devmap && devmap->device && devmap->device->discipline)
  643. dname = devmap->device->discipline->name;
  644. spin_unlock(&dasd_devmap_lock);
  645. return snprintf(buf, PAGE_SIZE, "%s\n", dname);
  646. }
  647. static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
  648. static ssize_t
  649. dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
  650. {
  651. struct dasd_devmap *devmap;
  652. int alias;
  653. devmap = dasd_find_busid(dev->bus_id);
  654. spin_lock(&dasd_devmap_lock);
  655. if (!IS_ERR(devmap))
  656. alias = devmap->uid.alias;
  657. else
  658. alias = 0;
  659. spin_unlock(&dasd_devmap_lock);
  660. return sprintf(buf, alias ? "1\n" : "0\n");
  661. }
  662. static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
  663. static ssize_t
  664. dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
  665. {
  666. struct dasd_devmap *devmap;
  667. char *vendor;
  668. devmap = dasd_find_busid(dev->bus_id);
  669. spin_lock(&dasd_devmap_lock);
  670. if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
  671. vendor = devmap->uid.vendor;
  672. else
  673. vendor = "";
  674. spin_unlock(&dasd_devmap_lock);
  675. return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
  676. }
  677. static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
  678. #define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial */ 14 + 1 +\
  679. /* SSID */ 4 + 1 + /* unit addr */ 2 + 1)
  680. static ssize_t
  681. dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
  682. {
  683. struct dasd_devmap *devmap;
  684. char uid[UID_STRLEN];
  685. devmap = dasd_find_busid(dev->bus_id);
  686. spin_lock(&dasd_devmap_lock);
  687. if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
  688. snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
  689. devmap->uid.vendor, devmap->uid.serial,
  690. devmap->uid.ssid, devmap->uid.unit_addr);
  691. else
  692. uid[0] = 0;
  693. spin_unlock(&dasd_devmap_lock);
  694. return snprintf(buf, PAGE_SIZE, "%s\n", uid);
  695. }
  696. static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
  697. /*
  698. * extended error-reporting
  699. */
  700. static ssize_t
  701. dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
  702. {
  703. struct dasd_devmap *devmap;
  704. int eer_flag;
  705. devmap = dasd_find_busid(dev->bus_id);
  706. if (!IS_ERR(devmap) && devmap->device)
  707. eer_flag = dasd_eer_enabled(devmap->device);
  708. else
  709. eer_flag = 0;
  710. return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
  711. }
  712. static ssize_t
  713. dasd_eer_store(struct device *dev, struct device_attribute *attr,
  714. const char *buf, size_t count)
  715. {
  716. struct dasd_devmap *devmap;
  717. int rc;
  718. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  719. if (IS_ERR(devmap))
  720. return PTR_ERR(devmap);
  721. if (!devmap->device)
  722. return count;
  723. if (buf[0] == '1') {
  724. rc = dasd_eer_enable(devmap->device);
  725. if (rc)
  726. return rc;
  727. } else
  728. dasd_eer_disable(devmap->device);
  729. return count;
  730. }
  731. static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
  732. static struct attribute * dasd_attrs[] = {
  733. &dev_attr_readonly.attr,
  734. &dev_attr_discipline.attr,
  735. &dev_attr_alias.attr,
  736. &dev_attr_vendor.attr,
  737. &dev_attr_uid.attr,
  738. &dev_attr_use_diag.attr,
  739. &dev_attr_eer_enabled.attr,
  740. NULL,
  741. };
  742. static struct attribute_group dasd_attr_group = {
  743. .attrs = dasd_attrs,
  744. };
  745. /*
  746. * Return copy of the device unique identifier.
  747. */
  748. int
  749. dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
  750. {
  751. struct dasd_devmap *devmap;
  752. devmap = dasd_find_busid(cdev->dev.bus_id);
  753. if (IS_ERR(devmap))
  754. return PTR_ERR(devmap);
  755. spin_lock(&dasd_devmap_lock);
  756. *uid = devmap->uid;
  757. spin_unlock(&dasd_devmap_lock);
  758. return 0;
  759. }
  760. /*
  761. * Register the given device unique identifier into devmap struct.
  762. */
  763. int
  764. dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
  765. {
  766. struct dasd_devmap *devmap;
  767. devmap = dasd_find_busid(cdev->dev.bus_id);
  768. if (IS_ERR(devmap))
  769. return PTR_ERR(devmap);
  770. spin_lock(&dasd_devmap_lock);
  771. devmap->uid = *uid;
  772. spin_unlock(&dasd_devmap_lock);
  773. return 0;
  774. }
  775. EXPORT_SYMBOL(dasd_set_uid);
  776. /*
  777. * Return value of the specified feature.
  778. */
  779. int
  780. dasd_get_feature(struct ccw_device *cdev, int feature)
  781. {
  782. struct dasd_devmap *devmap;
  783. devmap = dasd_find_busid(cdev->dev.bus_id);
  784. if (IS_ERR(devmap))
  785. return (int) PTR_ERR(devmap);
  786. return ((devmap->features & feature) != 0);
  787. }
  788. /*
  789. * Set / reset given feature.
  790. * Flag indicates wether to set (!=0) or the reset (=0) the feature.
  791. */
  792. int
  793. dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
  794. {
  795. struct dasd_devmap *devmap;
  796. devmap = dasd_find_busid(cdev->dev.bus_id);
  797. if (IS_ERR(devmap))
  798. return (int) PTR_ERR(devmap);
  799. spin_lock(&dasd_devmap_lock);
  800. if (flag)
  801. devmap->features |= feature;
  802. else
  803. devmap->features &= ~feature;
  804. if (devmap->device)
  805. devmap->device->features = devmap->features;
  806. spin_unlock(&dasd_devmap_lock);
  807. return 0;
  808. }
  809. int
  810. dasd_add_sysfs_files(struct ccw_device *cdev)
  811. {
  812. return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
  813. }
  814. void
  815. dasd_remove_sysfs_files(struct ccw_device *cdev)
  816. {
  817. sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
  818. }
  819. int
  820. dasd_devmap_init(void)
  821. {
  822. int i;
  823. /* Initialize devmap structures. */
  824. dasd_max_devindex = 0;
  825. for (i = 0; i < 256; i++)
  826. INIT_LIST_HEAD(&dasd_hashlists[i]);
  827. return 0;
  828. }
  829. void
  830. dasd_devmap_exit(void)
  831. {
  832. dasd_forget_ranges();
  833. }