dasd_devmap.c 27 KB

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