dasd_devmap.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  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, 0,
  241. SLAB_CACHE_DMA, NULL, NULL );
  242. if (!dasd_page_cache)
  243. MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
  244. "fixed buffer mode disabled.");
  245. else
  246. MESSAGE (KERN_INFO, "%s",
  247. "turning on fixed buffer mode");
  248. return residual_str;
  249. }
  250. return ERR_PTR(-EINVAL);
  251. }
  252. /*
  253. * Try to interprete the first element on the comma separated parse string
  254. * as a device number or a range of devices. If the interpretation is
  255. * successfull, create the matching dasd_devmap entries and return a pointer
  256. * to the residual string.
  257. * If interpretation fails or in case of an error, return an error code.
  258. */
  259. static char *
  260. dasd_parse_range( char *parsestring ) {
  261. struct dasd_devmap *devmap;
  262. int from, from_id0, from_id1;
  263. int to, to_id0, to_id1;
  264. int features, rc;
  265. char bus_id[BUS_ID_SIZE+1], *str;
  266. str = parsestring;
  267. rc = dasd_busid(&str, &from_id0, &from_id1, &from);
  268. if (rc == 0) {
  269. to = from;
  270. to_id0 = from_id0;
  271. to_id1 = from_id1;
  272. if (*str == '-') {
  273. str++;
  274. rc = dasd_busid(&str, &to_id0, &to_id1, &to);
  275. }
  276. }
  277. if (rc == 0 &&
  278. (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
  279. rc = -EINVAL;
  280. if (rc) {
  281. MESSAGE(KERN_ERR, "Invalid device range %s", parsestring);
  282. return ERR_PTR(rc);
  283. }
  284. features = dasd_feature_list(str, &str);
  285. if (features < 0)
  286. return ERR_PTR(-EINVAL);
  287. /* each device in dasd= parameter should be set initially online */
  288. features |= DASD_FEATURE_INITIAL_ONLINE;
  289. while (from <= to) {
  290. sprintf(bus_id, "%01x.%01x.%04x",
  291. from_id0, from_id1, from++);
  292. devmap = dasd_add_busid(bus_id, features);
  293. if (IS_ERR(devmap))
  294. return (char *)devmap;
  295. }
  296. if (*str == ',')
  297. return str + 1;
  298. if (*str == '\0')
  299. return str;
  300. MESSAGE(KERN_WARNING,
  301. "junk at end of dasd parameter string: %s\n", str);
  302. return ERR_PTR(-EINVAL);
  303. }
  304. static inline char *
  305. dasd_parse_next_element( char *parsestring ) {
  306. char * residual_str;
  307. residual_str = dasd_parse_keyword(parsestring);
  308. if (!IS_ERR(residual_str))
  309. return residual_str;
  310. residual_str = dasd_parse_range(parsestring);
  311. return residual_str;
  312. }
  313. /*
  314. * Parse parameters stored in dasd[]
  315. * The 'dasd=...' parameter allows to specify a comma separated list of
  316. * keywords and device ranges. When the dasd driver is build into the kernel,
  317. * the complete list will be stored as one element of the dasd[] array.
  318. * When the dasd driver is build as a module, then the list is broken into
  319. * it's elements and each dasd[] entry contains one element.
  320. */
  321. int
  322. dasd_parse(void)
  323. {
  324. int rc, i;
  325. char *parsestring;
  326. rc = 0;
  327. for (i = 0; i < 256; i++) {
  328. if (dasd[i] == NULL)
  329. break;
  330. parsestring = dasd[i];
  331. /* loop over the comma separated list in the parsestring */
  332. while (*parsestring) {
  333. parsestring = dasd_parse_next_element(parsestring);
  334. if(IS_ERR(parsestring)) {
  335. rc = PTR_ERR(parsestring);
  336. break;
  337. }
  338. }
  339. if (rc) {
  340. DBF_EVENT(DBF_ALERT, "%s", "invalid range found");
  341. break;
  342. }
  343. }
  344. return rc;
  345. }
  346. /*
  347. * Add a devmap for the device specified by busid. It is possible that
  348. * the devmap already exists (dasd= parameter). The order of the devices
  349. * added through this function will define the kdevs for the individual
  350. * devices.
  351. */
  352. static struct dasd_devmap *
  353. dasd_add_busid(char *bus_id, int features)
  354. {
  355. struct dasd_devmap *devmap, *new, *tmp;
  356. int hash;
  357. new = (struct dasd_devmap *)
  358. kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
  359. if (!new)
  360. return ERR_PTR(-ENOMEM);
  361. spin_lock(&dasd_devmap_lock);
  362. devmap = NULL;
  363. hash = dasd_hash_busid(bus_id);
  364. list_for_each_entry(tmp, &dasd_hashlists[hash], list)
  365. if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
  366. devmap = tmp;
  367. break;
  368. }
  369. if (!devmap) {
  370. /* This bus_id is new. */
  371. new->devindex = dasd_max_devindex++;
  372. strncpy(new->bus_id, bus_id, BUS_ID_SIZE);
  373. new->features = features;
  374. new->device = NULL;
  375. list_add(&new->list, &dasd_hashlists[hash]);
  376. devmap = new;
  377. new = NULL;
  378. }
  379. spin_unlock(&dasd_devmap_lock);
  380. kfree(new);
  381. return devmap;
  382. }
  383. /*
  384. * Find devmap for device with given bus_id.
  385. */
  386. static struct dasd_devmap *
  387. dasd_find_busid(char *bus_id)
  388. {
  389. struct dasd_devmap *devmap, *tmp;
  390. int hash;
  391. spin_lock(&dasd_devmap_lock);
  392. devmap = ERR_PTR(-ENODEV);
  393. hash = dasd_hash_busid(bus_id);
  394. list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
  395. if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
  396. devmap = tmp;
  397. break;
  398. }
  399. }
  400. spin_unlock(&dasd_devmap_lock);
  401. return devmap;
  402. }
  403. /*
  404. * Check if busid has been added to the list of dasd ranges.
  405. */
  406. int
  407. dasd_busid_known(char *bus_id)
  408. {
  409. return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
  410. }
  411. /*
  412. * Forget all about the device numbers added so far.
  413. * This may only be called at module unload or system shutdown.
  414. */
  415. static void
  416. dasd_forget_ranges(void)
  417. {
  418. struct dasd_devmap *devmap, *n;
  419. int i;
  420. spin_lock(&dasd_devmap_lock);
  421. for (i = 0; i < 256; i++) {
  422. list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
  423. BUG_ON(devmap->device != NULL);
  424. list_del(&devmap->list);
  425. kfree(devmap);
  426. }
  427. }
  428. spin_unlock(&dasd_devmap_lock);
  429. }
  430. /*
  431. * Find the device struct by its device index.
  432. */
  433. struct dasd_device *
  434. dasd_device_from_devindex(int devindex)
  435. {
  436. struct dasd_devmap *devmap, *tmp;
  437. struct dasd_device *device;
  438. int i;
  439. spin_lock(&dasd_devmap_lock);
  440. devmap = NULL;
  441. for (i = 0; (i < 256) && !devmap; i++)
  442. list_for_each_entry(tmp, &dasd_hashlists[i], list)
  443. if (tmp->devindex == devindex) {
  444. /* Found the devmap for the device. */
  445. devmap = tmp;
  446. break;
  447. }
  448. if (devmap && devmap->device) {
  449. device = devmap->device;
  450. dasd_get_device(device);
  451. } else
  452. device = ERR_PTR(-ENODEV);
  453. spin_unlock(&dasd_devmap_lock);
  454. return device;
  455. }
  456. /*
  457. * Return devmap for cdev. If no devmap exists yet, create one and
  458. * connect it to the cdev.
  459. */
  460. static struct dasd_devmap *
  461. dasd_devmap_from_cdev(struct ccw_device *cdev)
  462. {
  463. struct dasd_devmap *devmap;
  464. devmap = dasd_find_busid(cdev->dev.bus_id);
  465. if (IS_ERR(devmap))
  466. devmap = dasd_add_busid(cdev->dev.bus_id,
  467. DASD_FEATURE_DEFAULT);
  468. return devmap;
  469. }
  470. /*
  471. * Create a dasd device structure for cdev.
  472. */
  473. struct dasd_device *
  474. dasd_create_device(struct ccw_device *cdev)
  475. {
  476. struct dasd_devmap *devmap;
  477. struct dasd_device *device;
  478. int rc;
  479. devmap = dasd_devmap_from_cdev(cdev);
  480. if (IS_ERR(devmap))
  481. return (void *) devmap;
  482. cdev->dev.driver_data = devmap;
  483. device = dasd_alloc_device();
  484. if (IS_ERR(device))
  485. return device;
  486. atomic_set(&device->ref_count, 2);
  487. spin_lock(&dasd_devmap_lock);
  488. if (!devmap->device) {
  489. devmap->device = device;
  490. device->devindex = devmap->devindex;
  491. device->features = devmap->features;
  492. get_device(&cdev->dev);
  493. device->cdev = cdev;
  494. rc = 0;
  495. } else
  496. /* Someone else was faster. */
  497. rc = -EBUSY;
  498. spin_unlock(&dasd_devmap_lock);
  499. if (rc) {
  500. dasd_free_device(device);
  501. return ERR_PTR(rc);
  502. }
  503. return device;
  504. }
  505. /*
  506. * Wait queue for dasd_delete_device waits.
  507. */
  508. static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
  509. /*
  510. * Remove a dasd device structure. The passed referenced
  511. * is destroyed.
  512. */
  513. void
  514. dasd_delete_device(struct dasd_device *device)
  515. {
  516. struct ccw_device *cdev;
  517. struct dasd_devmap *devmap;
  518. /* First remove device pointer from devmap. */
  519. devmap = dasd_find_busid(device->cdev->dev.bus_id);
  520. BUG_ON(IS_ERR(devmap));
  521. spin_lock(&dasd_devmap_lock);
  522. if (devmap->device != device) {
  523. spin_unlock(&dasd_devmap_lock);
  524. dasd_put_device(device);
  525. return;
  526. }
  527. devmap->device = NULL;
  528. spin_unlock(&dasd_devmap_lock);
  529. /* Drop ref_count by 2, one for the devmap reference and
  530. * one for the passed reference. */
  531. atomic_sub(2, &device->ref_count);
  532. /* Wait for reference counter to drop to zero. */
  533. wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
  534. /* Disconnect dasd_device structure from ccw_device structure. */
  535. cdev = device->cdev;
  536. device->cdev = NULL;
  537. /* Disconnect dasd_devmap structure from ccw_device structure. */
  538. cdev->dev.driver_data = NULL;
  539. /* Put ccw_device structure. */
  540. put_device(&cdev->dev);
  541. /* Now the device structure can be freed. */
  542. dasd_free_device(device);
  543. }
  544. /*
  545. * Reference counter dropped to zero. Wake up waiter
  546. * in dasd_delete_device.
  547. */
  548. void
  549. dasd_put_device_wake(struct dasd_device *device)
  550. {
  551. wake_up(&dasd_delete_wq);
  552. }
  553. /*
  554. * Return dasd_device structure associated with cdev.
  555. */
  556. struct dasd_device *
  557. dasd_device_from_cdev(struct ccw_device *cdev)
  558. {
  559. struct dasd_devmap *devmap;
  560. struct dasd_device *device;
  561. device = ERR_PTR(-ENODEV);
  562. spin_lock(&dasd_devmap_lock);
  563. devmap = cdev->dev.driver_data;
  564. if (devmap && devmap->device) {
  565. device = devmap->device;
  566. dasd_get_device(device);
  567. }
  568. spin_unlock(&dasd_devmap_lock);
  569. return device;
  570. }
  571. /*
  572. * SECTION: files in sysfs
  573. */
  574. /*
  575. * readonly controls the readonly status of a dasd
  576. */
  577. static ssize_t
  578. dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
  579. {
  580. struct dasd_devmap *devmap;
  581. int ro_flag;
  582. devmap = dasd_find_busid(dev->bus_id);
  583. if (!IS_ERR(devmap))
  584. ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
  585. else
  586. ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
  587. return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
  588. }
  589. static ssize_t
  590. dasd_ro_store(struct device *dev, struct device_attribute *attr,
  591. const char *buf, size_t count)
  592. {
  593. struct dasd_devmap *devmap;
  594. int ro_flag;
  595. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  596. if (IS_ERR(devmap))
  597. return PTR_ERR(devmap);
  598. ro_flag = buf[0] == '1';
  599. spin_lock(&dasd_devmap_lock);
  600. if (ro_flag)
  601. devmap->features |= DASD_FEATURE_READONLY;
  602. else
  603. devmap->features &= ~DASD_FEATURE_READONLY;
  604. if (devmap->device)
  605. devmap->device->features = devmap->features;
  606. if (devmap->device && devmap->device->gdp)
  607. set_disk_ro(devmap->device->gdp, ro_flag);
  608. spin_unlock(&dasd_devmap_lock);
  609. return count;
  610. }
  611. static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
  612. /*
  613. * use_diag controls whether the driver should use diag rather than ssch
  614. * to talk to the device
  615. */
  616. static ssize_t
  617. dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
  618. {
  619. struct dasd_devmap *devmap;
  620. int use_diag;
  621. devmap = dasd_find_busid(dev->bus_id);
  622. if (!IS_ERR(devmap))
  623. use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
  624. else
  625. use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
  626. return sprintf(buf, use_diag ? "1\n" : "0\n");
  627. }
  628. static ssize_t
  629. dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
  630. const char *buf, size_t count)
  631. {
  632. struct dasd_devmap *devmap;
  633. ssize_t rc;
  634. int use_diag;
  635. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  636. if (IS_ERR(devmap))
  637. return PTR_ERR(devmap);
  638. use_diag = buf[0] == '1';
  639. spin_lock(&dasd_devmap_lock);
  640. /* Changing diag discipline flag is only allowed in offline state. */
  641. rc = count;
  642. if (!devmap->device) {
  643. if (use_diag)
  644. devmap->features |= DASD_FEATURE_USEDIAG;
  645. else
  646. devmap->features &= ~DASD_FEATURE_USEDIAG;
  647. } else
  648. rc = -EPERM;
  649. spin_unlock(&dasd_devmap_lock);
  650. return rc;
  651. }
  652. static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
  653. static ssize_t
  654. dasd_discipline_show(struct device *dev, struct device_attribute *attr,
  655. char *buf)
  656. {
  657. struct dasd_devmap *devmap;
  658. char *dname;
  659. spin_lock(&dasd_devmap_lock);
  660. dname = "none";
  661. devmap = dev->driver_data;
  662. if (devmap && devmap->device && devmap->device->discipline)
  663. dname = devmap->device->discipline->name;
  664. spin_unlock(&dasd_devmap_lock);
  665. return snprintf(buf, PAGE_SIZE, "%s\n", dname);
  666. }
  667. static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
  668. static ssize_t
  669. dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
  670. {
  671. struct dasd_devmap *devmap;
  672. int alias;
  673. devmap = dasd_find_busid(dev->bus_id);
  674. spin_lock(&dasd_devmap_lock);
  675. if (!IS_ERR(devmap))
  676. alias = devmap->uid.alias;
  677. else
  678. alias = 0;
  679. spin_unlock(&dasd_devmap_lock);
  680. return sprintf(buf, alias ? "1\n" : "0\n");
  681. }
  682. static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
  683. static ssize_t
  684. dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
  685. {
  686. struct dasd_devmap *devmap;
  687. char *vendor;
  688. devmap = dasd_find_busid(dev->bus_id);
  689. spin_lock(&dasd_devmap_lock);
  690. if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
  691. vendor = devmap->uid.vendor;
  692. else
  693. vendor = "";
  694. spin_unlock(&dasd_devmap_lock);
  695. return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
  696. }
  697. static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
  698. #define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial */ 14 + 1 +\
  699. /* SSID */ 4 + 1 + /* unit addr */ 2 + 1)
  700. static ssize_t
  701. dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
  702. {
  703. struct dasd_devmap *devmap;
  704. char uid[UID_STRLEN];
  705. devmap = dasd_find_busid(dev->bus_id);
  706. spin_lock(&dasd_devmap_lock);
  707. if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
  708. snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
  709. devmap->uid.vendor, devmap->uid.serial,
  710. devmap->uid.ssid, devmap->uid.unit_addr);
  711. else
  712. uid[0] = 0;
  713. spin_unlock(&dasd_devmap_lock);
  714. return snprintf(buf, PAGE_SIZE, "%s\n", uid);
  715. }
  716. static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
  717. /*
  718. * extended error-reporting
  719. */
  720. static ssize_t
  721. dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
  722. {
  723. struct dasd_devmap *devmap;
  724. int eer_flag;
  725. devmap = dasd_find_busid(dev->bus_id);
  726. if (!IS_ERR(devmap) && devmap->device)
  727. eer_flag = dasd_eer_enabled(devmap->device);
  728. else
  729. eer_flag = 0;
  730. return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
  731. }
  732. static ssize_t
  733. dasd_eer_store(struct device *dev, struct device_attribute *attr,
  734. const char *buf, size_t count)
  735. {
  736. struct dasd_devmap *devmap;
  737. int rc;
  738. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  739. if (IS_ERR(devmap))
  740. return PTR_ERR(devmap);
  741. if (!devmap->device)
  742. return count;
  743. if (buf[0] == '1') {
  744. rc = dasd_eer_enable(devmap->device);
  745. if (rc)
  746. return rc;
  747. } else
  748. dasd_eer_disable(devmap->device);
  749. return count;
  750. }
  751. static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
  752. static struct attribute * dasd_attrs[] = {
  753. &dev_attr_readonly.attr,
  754. &dev_attr_discipline.attr,
  755. &dev_attr_alias.attr,
  756. &dev_attr_vendor.attr,
  757. &dev_attr_uid.attr,
  758. &dev_attr_use_diag.attr,
  759. &dev_attr_eer_enabled.attr,
  760. NULL,
  761. };
  762. static struct attribute_group dasd_attr_group = {
  763. .attrs = dasd_attrs,
  764. };
  765. /*
  766. * Return copy of the device unique identifier.
  767. */
  768. int
  769. dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
  770. {
  771. struct dasd_devmap *devmap;
  772. devmap = dasd_find_busid(cdev->dev.bus_id);
  773. if (IS_ERR(devmap))
  774. return PTR_ERR(devmap);
  775. spin_lock(&dasd_devmap_lock);
  776. *uid = devmap->uid;
  777. spin_unlock(&dasd_devmap_lock);
  778. return 0;
  779. }
  780. /*
  781. * Register the given device unique identifier into devmap struct.
  782. * In addition check if the related storage server is already contained in the
  783. * dasd_serverlist. If server is not contained, create new entry.
  784. * Return 0 if server was already in serverlist,
  785. * 1 if the server was added successful
  786. * <0 in case of error.
  787. */
  788. int
  789. dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
  790. {
  791. struct dasd_devmap *devmap;
  792. struct dasd_servermap *srv, *tmp;
  793. devmap = dasd_find_busid(cdev->dev.bus_id);
  794. if (IS_ERR(devmap))
  795. return PTR_ERR(devmap);
  796. /* generate entry for servermap */
  797. srv = (struct dasd_servermap *)
  798. kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL);
  799. if (!srv)
  800. return -ENOMEM;
  801. strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1);
  802. strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1);
  803. /* server is already contained ? */
  804. spin_lock(&dasd_devmap_lock);
  805. devmap->uid = *uid;
  806. list_for_each_entry(tmp, &dasd_serverlist, list) {
  807. if (!memcmp(&srv->sid, &tmp->sid,
  808. sizeof(struct dasd_servermap))) {
  809. kfree(srv);
  810. srv = NULL;
  811. break;
  812. }
  813. }
  814. /* add servermap to serverlist */
  815. if (srv)
  816. list_add(&srv->list, &dasd_serverlist);
  817. spin_unlock(&dasd_devmap_lock);
  818. return (srv ? 1 : 0);
  819. }
  820. EXPORT_SYMBOL_GPL(dasd_set_uid);
  821. /*
  822. * Return value of the specified feature.
  823. */
  824. int
  825. dasd_get_feature(struct ccw_device *cdev, int feature)
  826. {
  827. struct dasd_devmap *devmap;
  828. devmap = dasd_find_busid(cdev->dev.bus_id);
  829. if (IS_ERR(devmap))
  830. return PTR_ERR(devmap);
  831. return ((devmap->features & feature) != 0);
  832. }
  833. /*
  834. * Set / reset given feature.
  835. * Flag indicates wether to set (!=0) or the reset (=0) the feature.
  836. */
  837. int
  838. dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
  839. {
  840. struct dasd_devmap *devmap;
  841. devmap = dasd_find_busid(cdev->dev.bus_id);
  842. if (IS_ERR(devmap))
  843. return PTR_ERR(devmap);
  844. spin_lock(&dasd_devmap_lock);
  845. if (flag)
  846. devmap->features |= feature;
  847. else
  848. devmap->features &= ~feature;
  849. if (devmap->device)
  850. devmap->device->features = devmap->features;
  851. spin_unlock(&dasd_devmap_lock);
  852. return 0;
  853. }
  854. int
  855. dasd_add_sysfs_files(struct ccw_device *cdev)
  856. {
  857. return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
  858. }
  859. void
  860. dasd_remove_sysfs_files(struct ccw_device *cdev)
  861. {
  862. sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
  863. }
  864. int
  865. dasd_devmap_init(void)
  866. {
  867. int i;
  868. /* Initialize devmap structures. */
  869. dasd_max_devindex = 0;
  870. for (i = 0; i < 256; i++)
  871. INIT_LIST_HEAD(&dasd_hashlists[i]);
  872. /* Initialize servermap structure. */
  873. INIT_LIST_HEAD(&dasd_serverlist);
  874. return 0;
  875. }
  876. void
  877. dasd_devmap_exit(void)
  878. {
  879. dasd_forget_ranges();
  880. }