dasd_devmap.c 24 KB

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