dasd_devmap.c 27 KB

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