dasd_devmap.c 25 KB

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