dasd_devmap.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  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 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 = 0;
  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 = 0;
  375. list_add(&new->list, &dasd_hashlists[hash]);
  376. devmap = new;
  377. new = 0;
  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 = 0;
  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. * Check if the related storage server is already contained in the
  767. * dasd_serverlist. If server is not contained, create new entry.
  768. * Return 0 if server was already in serverlist,
  769. * 1 if the server was added successfully
  770. * <0 in case of error.
  771. */
  772. static int
  773. dasd_add_server(struct dasd_uid *uid)
  774. {
  775. struct dasd_servermap *new, *tmp;
  776. /* check if server is already contained */
  777. list_for_each_entry(tmp, &dasd_serverlist, list)
  778. // normale cmp?
  779. if (strncmp(tmp->sid.vendor, uid->vendor,
  780. sizeof(tmp->sid.vendor)) == 0
  781. && strncmp(tmp->sid.serial, uid->serial,
  782. sizeof(tmp->sid.serial)) == 0)
  783. return 0;
  784. new = (struct dasd_servermap *)
  785. kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL);
  786. if (!new)
  787. return -ENOMEM;
  788. strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor));
  789. strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial));
  790. list_add(&new->list, &dasd_serverlist);
  791. return 1;
  792. }
  793. /*
  794. * Return copy of the device unique identifier.
  795. */
  796. int
  797. dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
  798. {
  799. struct dasd_devmap *devmap;
  800. devmap = dasd_find_busid(cdev->dev.bus_id);
  801. if (IS_ERR(devmap))
  802. return PTR_ERR(devmap);
  803. spin_lock(&dasd_devmap_lock);
  804. *uid = devmap->uid;
  805. spin_unlock(&dasd_devmap_lock);
  806. return 0;
  807. }
  808. /*
  809. * Register the given device unique identifier into devmap struct.
  810. * Return 0 if server was already in serverlist,
  811. * 1 if the server was added successful
  812. * <0 in case of error.
  813. */
  814. int
  815. dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
  816. {
  817. struct dasd_devmap *devmap;
  818. int rc;
  819. devmap = dasd_find_busid(cdev->dev.bus_id);
  820. if (IS_ERR(devmap))
  821. return PTR_ERR(devmap);
  822. spin_lock(&dasd_devmap_lock);
  823. devmap->uid = *uid;
  824. rc = dasd_add_server(uid);
  825. spin_unlock(&dasd_devmap_lock);
  826. return rc;
  827. }
  828. EXPORT_SYMBOL_GPL(dasd_set_uid);
  829. /*
  830. * Return value of the specified feature.
  831. */
  832. int
  833. dasd_get_feature(struct ccw_device *cdev, int feature)
  834. {
  835. struct dasd_devmap *devmap;
  836. devmap = dasd_find_busid(cdev->dev.bus_id);
  837. if (IS_ERR(devmap))
  838. return PTR_ERR(devmap);
  839. return ((devmap->features & feature) != 0);
  840. }
  841. /*
  842. * Set / reset given feature.
  843. * Flag indicates wether to set (!=0) or the reset (=0) the feature.
  844. */
  845. int
  846. dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
  847. {
  848. struct dasd_devmap *devmap;
  849. devmap = dasd_find_busid(cdev->dev.bus_id);
  850. if (IS_ERR(devmap))
  851. return PTR_ERR(devmap);
  852. spin_lock(&dasd_devmap_lock);
  853. if (flag)
  854. devmap->features |= feature;
  855. else
  856. devmap->features &= ~feature;
  857. if (devmap->device)
  858. devmap->device->features = devmap->features;
  859. spin_unlock(&dasd_devmap_lock);
  860. return 0;
  861. }
  862. int
  863. dasd_add_sysfs_files(struct ccw_device *cdev)
  864. {
  865. return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
  866. }
  867. void
  868. dasd_remove_sysfs_files(struct ccw_device *cdev)
  869. {
  870. sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
  871. }
  872. int
  873. dasd_devmap_init(void)
  874. {
  875. int i;
  876. /* Initialize devmap structures. */
  877. dasd_max_devindex = 0;
  878. for (i = 0; i < 256; i++)
  879. INIT_LIST_HEAD(&dasd_hashlists[i]);
  880. /* Initialize servermap structure. */
  881. INIT_LIST_HEAD(&dasd_serverlist);
  882. return 0;
  883. }
  884. void
  885. dasd_devmap_exit(void)
  886. {
  887. dasd_forget_ranges();
  888. }