dasd_devmap.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
  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 if (len == 8 && !strncmp(str, "failfast", 8))
  186. features |= DASD_FEATURE_FAILFAST;
  187. else {
  188. MESSAGE(KERN_WARNING,
  189. "unsupported feature: %*s, "
  190. "ignoring setting", len, str);
  191. rc = -EINVAL;
  192. }
  193. str += len;
  194. if (*str != ':')
  195. break;
  196. str++;
  197. }
  198. if (*str != ')') {
  199. MESSAGE(KERN_WARNING, "%s",
  200. "missing ')' in dasd parameter string\n");
  201. rc = -EINVAL;
  202. } else
  203. str++;
  204. *endp = str;
  205. if (rc != 0)
  206. return rc;
  207. return features;
  208. }
  209. /*
  210. * Try to match the first element on the comma separated parse string
  211. * with one of the known keywords. If a keyword is found, take the approprate
  212. * action and return a pointer to the residual string. If the first element
  213. * could not be matched to any keyword then return an error code.
  214. */
  215. static char *
  216. dasd_parse_keyword( char *parsestring ) {
  217. char *nextcomma, *residual_str;
  218. int length;
  219. nextcomma = strchr(parsestring,',');
  220. if (nextcomma) {
  221. length = nextcomma - parsestring;
  222. residual_str = nextcomma + 1;
  223. } else {
  224. length = strlen(parsestring);
  225. residual_str = parsestring + length;
  226. }
  227. if (strncmp("autodetect", parsestring, length) == 0) {
  228. dasd_autodetect = 1;
  229. MESSAGE (KERN_INFO, "%s",
  230. "turning to autodetection mode");
  231. return residual_str;
  232. }
  233. if (strncmp("probeonly", parsestring, length) == 0) {
  234. dasd_probeonly = 1;
  235. MESSAGE(KERN_INFO, "%s",
  236. "turning to probeonly mode");
  237. return residual_str;
  238. }
  239. if (strncmp("nopav", parsestring, length) == 0) {
  240. if (MACHINE_IS_VM)
  241. MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM");
  242. else {
  243. dasd_nopav = 1;
  244. MESSAGE(KERN_INFO, "%s", "disable PAV mode");
  245. }
  246. return residual_str;
  247. }
  248. if (strncmp("fixedbuffers", parsestring, length) == 0) {
  249. if (dasd_page_cache)
  250. return residual_str;
  251. dasd_page_cache =
  252. kmem_cache_create("dasd_page_cache", PAGE_SIZE,
  253. PAGE_SIZE, SLAB_CACHE_DMA,
  254. NULL);
  255. if (!dasd_page_cache)
  256. MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
  257. "fixed buffer mode disabled.");
  258. else
  259. MESSAGE (KERN_INFO, "%s",
  260. "turning on fixed buffer mode");
  261. return residual_str;
  262. }
  263. return ERR_PTR(-EINVAL);
  264. }
  265. /*
  266. * Try to interprete the first element on the comma separated parse string
  267. * as a device number or a range of devices. If the interpretation is
  268. * successfull, create the matching dasd_devmap entries and return a pointer
  269. * to the residual string.
  270. * If interpretation fails or in case of an error, return an error code.
  271. */
  272. static char *
  273. dasd_parse_range( char *parsestring ) {
  274. struct dasd_devmap *devmap;
  275. int from, from_id0, from_id1;
  276. int to, to_id0, to_id1;
  277. int features, rc;
  278. char bus_id[DASD_BUS_ID_SIZE+1], *str;
  279. str = parsestring;
  280. rc = dasd_busid(&str, &from_id0, &from_id1, &from);
  281. if (rc == 0) {
  282. to = from;
  283. to_id0 = from_id0;
  284. to_id1 = from_id1;
  285. if (*str == '-') {
  286. str++;
  287. rc = dasd_busid(&str, &to_id0, &to_id1, &to);
  288. }
  289. }
  290. if (rc == 0 &&
  291. (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
  292. rc = -EINVAL;
  293. if (rc) {
  294. MESSAGE(KERN_ERR, "Invalid device range %s", parsestring);
  295. return ERR_PTR(rc);
  296. }
  297. features = dasd_feature_list(str, &str);
  298. if (features < 0)
  299. return ERR_PTR(-EINVAL);
  300. /* each device in dasd= parameter should be set initially online */
  301. features |= DASD_FEATURE_INITIAL_ONLINE;
  302. while (from <= to) {
  303. sprintf(bus_id, "%01x.%01x.%04x",
  304. from_id0, from_id1, from++);
  305. devmap = dasd_add_busid(bus_id, features);
  306. if (IS_ERR(devmap))
  307. return (char *)devmap;
  308. }
  309. if (*str == ',')
  310. return str + 1;
  311. if (*str == '\0')
  312. return str;
  313. MESSAGE(KERN_WARNING,
  314. "junk at end of dasd parameter string: %s\n", str);
  315. return ERR_PTR(-EINVAL);
  316. }
  317. static char *
  318. dasd_parse_next_element( char *parsestring ) {
  319. char * residual_str;
  320. residual_str = dasd_parse_keyword(parsestring);
  321. if (!IS_ERR(residual_str))
  322. return residual_str;
  323. residual_str = dasd_parse_range(parsestring);
  324. return residual_str;
  325. }
  326. /*
  327. * Parse parameters stored in dasd[]
  328. * The 'dasd=...' parameter allows to specify a comma separated list of
  329. * keywords and device ranges. When the dasd driver is build into the kernel,
  330. * the complete list will be stored as one element of the dasd[] array.
  331. * When the dasd driver is build as a module, then the list is broken into
  332. * it's elements and each dasd[] entry contains one element.
  333. */
  334. int
  335. dasd_parse(void)
  336. {
  337. int rc, i;
  338. char *parsestring;
  339. rc = 0;
  340. for (i = 0; i < 256; i++) {
  341. if (dasd[i] == NULL)
  342. break;
  343. parsestring = dasd[i];
  344. /* loop over the comma separated list in the parsestring */
  345. while (*parsestring) {
  346. parsestring = dasd_parse_next_element(parsestring);
  347. if(IS_ERR(parsestring)) {
  348. rc = PTR_ERR(parsestring);
  349. break;
  350. }
  351. }
  352. if (rc) {
  353. DBF_EVENT(DBF_ALERT, "%s", "invalid range found");
  354. break;
  355. }
  356. }
  357. return rc;
  358. }
  359. /*
  360. * Add a devmap for the device specified by busid. It is possible that
  361. * the devmap already exists (dasd= parameter). The order of the devices
  362. * added through this function will define the kdevs for the individual
  363. * devices.
  364. */
  365. static struct dasd_devmap *
  366. dasd_add_busid(const char *bus_id, int features)
  367. {
  368. struct dasd_devmap *devmap, *new, *tmp;
  369. int hash;
  370. new = (struct dasd_devmap *)
  371. kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
  372. if (!new)
  373. return ERR_PTR(-ENOMEM);
  374. spin_lock(&dasd_devmap_lock);
  375. devmap = NULL;
  376. hash = dasd_hash_busid(bus_id);
  377. list_for_each_entry(tmp, &dasd_hashlists[hash], list)
  378. if (strncmp(tmp->bus_id, bus_id, DASD_BUS_ID_SIZE) == 0) {
  379. devmap = tmp;
  380. break;
  381. }
  382. if (!devmap) {
  383. /* This bus_id is new. */
  384. new->devindex = dasd_max_devindex++;
  385. strncpy(new->bus_id, bus_id, DASD_BUS_ID_SIZE);
  386. new->features = features;
  387. new->device = NULL;
  388. list_add(&new->list, &dasd_hashlists[hash]);
  389. devmap = new;
  390. new = NULL;
  391. }
  392. spin_unlock(&dasd_devmap_lock);
  393. kfree(new);
  394. return devmap;
  395. }
  396. /*
  397. * Find devmap for device with given bus_id.
  398. */
  399. static struct dasd_devmap *
  400. dasd_find_busid(const char *bus_id)
  401. {
  402. struct dasd_devmap *devmap, *tmp;
  403. int hash;
  404. spin_lock(&dasd_devmap_lock);
  405. devmap = ERR_PTR(-ENODEV);
  406. hash = dasd_hash_busid(bus_id);
  407. list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
  408. if (strncmp(tmp->bus_id, bus_id, DASD_BUS_ID_SIZE) == 0) {
  409. devmap = tmp;
  410. break;
  411. }
  412. }
  413. spin_unlock(&dasd_devmap_lock);
  414. return devmap;
  415. }
  416. /*
  417. * Check if busid has been added to the list of dasd ranges.
  418. */
  419. int
  420. dasd_busid_known(const char *bus_id)
  421. {
  422. return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
  423. }
  424. /*
  425. * Forget all about the device numbers added so far.
  426. * This may only be called at module unload or system shutdown.
  427. */
  428. static void
  429. dasd_forget_ranges(void)
  430. {
  431. struct dasd_devmap *devmap, *n;
  432. int i;
  433. spin_lock(&dasd_devmap_lock);
  434. for (i = 0; i < 256; i++) {
  435. list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
  436. BUG_ON(devmap->device != NULL);
  437. list_del(&devmap->list);
  438. kfree(devmap);
  439. }
  440. }
  441. spin_unlock(&dasd_devmap_lock);
  442. }
  443. /*
  444. * Find the device struct by its device index.
  445. */
  446. struct dasd_device *
  447. dasd_device_from_devindex(int devindex)
  448. {
  449. struct dasd_devmap *devmap, *tmp;
  450. struct dasd_device *device;
  451. int i;
  452. spin_lock(&dasd_devmap_lock);
  453. devmap = NULL;
  454. for (i = 0; (i < 256) && !devmap; i++)
  455. list_for_each_entry(tmp, &dasd_hashlists[i], list)
  456. if (tmp->devindex == devindex) {
  457. /* Found the devmap for the device. */
  458. devmap = tmp;
  459. break;
  460. }
  461. if (devmap && devmap->device) {
  462. device = devmap->device;
  463. dasd_get_device(device);
  464. } else
  465. device = ERR_PTR(-ENODEV);
  466. spin_unlock(&dasd_devmap_lock);
  467. return device;
  468. }
  469. /*
  470. * Return devmap for cdev. If no devmap exists yet, create one and
  471. * connect it to the cdev.
  472. */
  473. static struct dasd_devmap *
  474. dasd_devmap_from_cdev(struct ccw_device *cdev)
  475. {
  476. struct dasd_devmap *devmap;
  477. devmap = dasd_find_busid(dev_name(&cdev->dev));
  478. if (IS_ERR(devmap))
  479. devmap = dasd_add_busid(dev_name(&cdev->dev),
  480. DASD_FEATURE_DEFAULT);
  481. return devmap;
  482. }
  483. /*
  484. * Create a dasd device structure for cdev.
  485. */
  486. struct dasd_device *
  487. dasd_create_device(struct ccw_device *cdev)
  488. {
  489. struct dasd_devmap *devmap;
  490. struct dasd_device *device;
  491. unsigned long flags;
  492. int rc;
  493. devmap = dasd_devmap_from_cdev(cdev);
  494. if (IS_ERR(devmap))
  495. return (void *) devmap;
  496. device = dasd_alloc_device();
  497. if (IS_ERR(device))
  498. return device;
  499. atomic_set(&device->ref_count, 3);
  500. spin_lock(&dasd_devmap_lock);
  501. if (!devmap->device) {
  502. devmap->device = device;
  503. device->devindex = devmap->devindex;
  504. device->features = devmap->features;
  505. get_device(&cdev->dev);
  506. device->cdev = cdev;
  507. rc = 0;
  508. } else
  509. /* Someone else was faster. */
  510. rc = -EBUSY;
  511. spin_unlock(&dasd_devmap_lock);
  512. if (rc) {
  513. dasd_free_device(device);
  514. return ERR_PTR(rc);
  515. }
  516. spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
  517. dev_set_drvdata(&cdev->dev, device);
  518. spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
  519. return device;
  520. }
  521. /*
  522. * Wait queue for dasd_delete_device waits.
  523. */
  524. static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
  525. /*
  526. * Remove a dasd device structure. The passed referenced
  527. * is destroyed.
  528. */
  529. void
  530. dasd_delete_device(struct dasd_device *device)
  531. {
  532. struct ccw_device *cdev;
  533. struct dasd_devmap *devmap;
  534. unsigned long flags;
  535. /* First remove device pointer from devmap. */
  536. devmap = dasd_find_busid(dev_name(&device->cdev->dev));
  537. BUG_ON(IS_ERR(devmap));
  538. spin_lock(&dasd_devmap_lock);
  539. if (devmap->device != device) {
  540. spin_unlock(&dasd_devmap_lock);
  541. dasd_put_device(device);
  542. return;
  543. }
  544. devmap->device = NULL;
  545. spin_unlock(&dasd_devmap_lock);
  546. /* Disconnect dasd_device structure from ccw_device structure. */
  547. spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
  548. dev_set_drvdata(&device->cdev->dev, NULL);
  549. spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
  550. /*
  551. * Drop ref_count by 3, one for the devmap reference, one for
  552. * the cdev reference and one for the passed reference.
  553. */
  554. atomic_sub(3, &device->ref_count);
  555. /* Wait for reference counter to drop to zero. */
  556. wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
  557. /* Disconnect dasd_device structure from ccw_device structure. */
  558. cdev = device->cdev;
  559. device->cdev = NULL;
  560. /* Put ccw_device structure. */
  561. put_device(&cdev->dev);
  562. /* Now the device structure can be freed. */
  563. dasd_free_device(device);
  564. }
  565. /*
  566. * Reference counter dropped to zero. Wake up waiter
  567. * in dasd_delete_device.
  568. */
  569. void
  570. dasd_put_device_wake(struct dasd_device *device)
  571. {
  572. wake_up(&dasd_delete_wq);
  573. }
  574. /*
  575. * Return dasd_device structure associated with cdev.
  576. * This function needs to be called with the ccw device
  577. * lock held. It can be used from interrupt context.
  578. */
  579. struct dasd_device *
  580. dasd_device_from_cdev_locked(struct ccw_device *cdev)
  581. {
  582. struct dasd_device *device = dev_get_drvdata(&cdev->dev);
  583. if (!device)
  584. return ERR_PTR(-ENODEV);
  585. dasd_get_device(device);
  586. return device;
  587. }
  588. /*
  589. * Return dasd_device structure associated with cdev.
  590. */
  591. struct dasd_device *
  592. dasd_device_from_cdev(struct ccw_device *cdev)
  593. {
  594. struct dasd_device *device;
  595. unsigned long flags;
  596. spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
  597. device = dasd_device_from_cdev_locked(cdev);
  598. spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
  599. return device;
  600. }
  601. /*
  602. * SECTION: files in sysfs
  603. */
  604. /*
  605. * failfast controls the behaviour, if no path is available
  606. */
  607. static ssize_t dasd_ff_show(struct device *dev, struct device_attribute *attr,
  608. char *buf)
  609. {
  610. struct dasd_devmap *devmap;
  611. int ff_flag;
  612. devmap = dasd_find_busid(dev_name(dev));
  613. if (!IS_ERR(devmap))
  614. ff_flag = (devmap->features & DASD_FEATURE_FAILFAST) != 0;
  615. else
  616. ff_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_FAILFAST) != 0;
  617. return snprintf(buf, PAGE_SIZE, ff_flag ? "1\n" : "0\n");
  618. }
  619. static ssize_t dasd_ff_store(struct device *dev, struct device_attribute *attr,
  620. const char *buf, size_t count)
  621. {
  622. struct dasd_devmap *devmap;
  623. int val;
  624. char *endp;
  625. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  626. if (IS_ERR(devmap))
  627. return PTR_ERR(devmap);
  628. val = simple_strtoul(buf, &endp, 0);
  629. if (((endp + 1) < (buf + count)) || (val > 1))
  630. return -EINVAL;
  631. spin_lock(&dasd_devmap_lock);
  632. if (val)
  633. devmap->features |= DASD_FEATURE_FAILFAST;
  634. else
  635. devmap->features &= ~DASD_FEATURE_FAILFAST;
  636. if (devmap->device)
  637. devmap->device->features = devmap->features;
  638. spin_unlock(&dasd_devmap_lock);
  639. return count;
  640. }
  641. static DEVICE_ATTR(failfast, 0644, dasd_ff_show, dasd_ff_store);
  642. /*
  643. * readonly controls the readonly status of a dasd
  644. */
  645. static ssize_t
  646. dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
  647. {
  648. struct dasd_devmap *devmap;
  649. int ro_flag;
  650. devmap = dasd_find_busid(dev_name(dev));
  651. if (!IS_ERR(devmap))
  652. ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
  653. else
  654. ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
  655. return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
  656. }
  657. static ssize_t
  658. dasd_ro_store(struct device *dev, struct device_attribute *attr,
  659. const char *buf, size_t count)
  660. {
  661. struct dasd_devmap *devmap;
  662. int val;
  663. char *endp;
  664. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  665. if (IS_ERR(devmap))
  666. return PTR_ERR(devmap);
  667. val = simple_strtoul(buf, &endp, 0);
  668. if (((endp + 1) < (buf + count)) || (val > 1))
  669. return -EINVAL;
  670. spin_lock(&dasd_devmap_lock);
  671. if (val)
  672. devmap->features |= DASD_FEATURE_READONLY;
  673. else
  674. devmap->features &= ~DASD_FEATURE_READONLY;
  675. if (devmap->device)
  676. devmap->device->features = devmap->features;
  677. if (devmap->device && devmap->device->block
  678. && devmap->device->block->gdp)
  679. set_disk_ro(devmap->device->block->gdp, val);
  680. spin_unlock(&dasd_devmap_lock);
  681. return count;
  682. }
  683. static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
  684. /*
  685. * erplog controls the logging of ERP related data
  686. * (e.g. failing channel programs).
  687. */
  688. static ssize_t
  689. dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
  690. {
  691. struct dasd_devmap *devmap;
  692. int erplog;
  693. devmap = dasd_find_busid(dev_name(dev));
  694. if (!IS_ERR(devmap))
  695. erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
  696. else
  697. erplog = (DASD_FEATURE_DEFAULT & DASD_FEATURE_ERPLOG) != 0;
  698. return snprintf(buf, PAGE_SIZE, erplog ? "1\n" : "0\n");
  699. }
  700. static ssize_t
  701. dasd_erplog_store(struct device *dev, struct device_attribute *attr,
  702. const char *buf, size_t count)
  703. {
  704. struct dasd_devmap *devmap;
  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. if (val)
  715. devmap->features |= DASD_FEATURE_ERPLOG;
  716. else
  717. devmap->features &= ~DASD_FEATURE_ERPLOG;
  718. if (devmap->device)
  719. devmap->device->features = devmap->features;
  720. spin_unlock(&dasd_devmap_lock);
  721. return count;
  722. }
  723. static DEVICE_ATTR(erplog, 0644, dasd_erplog_show, dasd_erplog_store);
  724. /*
  725. * use_diag controls whether the driver should use diag rather than ssch
  726. * to talk to the device
  727. */
  728. static ssize_t
  729. dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
  730. {
  731. struct dasd_devmap *devmap;
  732. int use_diag;
  733. devmap = dasd_find_busid(dev_name(dev));
  734. if (!IS_ERR(devmap))
  735. use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
  736. else
  737. use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
  738. return sprintf(buf, use_diag ? "1\n" : "0\n");
  739. }
  740. static ssize_t
  741. dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
  742. const char *buf, size_t count)
  743. {
  744. struct dasd_devmap *devmap;
  745. ssize_t rc;
  746. int val;
  747. char *endp;
  748. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  749. if (IS_ERR(devmap))
  750. return PTR_ERR(devmap);
  751. val = simple_strtoul(buf, &endp, 0);
  752. if (((endp + 1) < (buf + count)) || (val > 1))
  753. return -EINVAL;
  754. spin_lock(&dasd_devmap_lock);
  755. /* Changing diag discipline flag is only allowed in offline state. */
  756. rc = count;
  757. if (!devmap->device) {
  758. if (val)
  759. devmap->features |= DASD_FEATURE_USEDIAG;
  760. else
  761. devmap->features &= ~DASD_FEATURE_USEDIAG;
  762. } else
  763. rc = -EPERM;
  764. spin_unlock(&dasd_devmap_lock);
  765. return rc;
  766. }
  767. static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
  768. static ssize_t
  769. dasd_discipline_show(struct device *dev, struct device_attribute *attr,
  770. char *buf)
  771. {
  772. struct dasd_device *device;
  773. ssize_t len;
  774. device = dasd_device_from_cdev(to_ccwdev(dev));
  775. if (!IS_ERR(device) && device->discipline) {
  776. len = snprintf(buf, PAGE_SIZE, "%s\n",
  777. device->discipline->name);
  778. dasd_put_device(device);
  779. } else
  780. len = snprintf(buf, PAGE_SIZE, "none\n");
  781. return len;
  782. }
  783. static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
  784. static ssize_t
  785. dasd_device_status_show(struct device *dev, struct device_attribute *attr,
  786. char *buf)
  787. {
  788. struct dasd_device *device;
  789. ssize_t len;
  790. device = dasd_device_from_cdev(to_ccwdev(dev));
  791. if (!IS_ERR(device)) {
  792. switch (device->state) {
  793. case DASD_STATE_NEW:
  794. len = snprintf(buf, PAGE_SIZE, "new\n");
  795. break;
  796. case DASD_STATE_KNOWN:
  797. len = snprintf(buf, PAGE_SIZE, "detected\n");
  798. break;
  799. case DASD_STATE_BASIC:
  800. len = snprintf(buf, PAGE_SIZE, "basic\n");
  801. break;
  802. case DASD_STATE_UNFMT:
  803. len = snprintf(buf, PAGE_SIZE, "unformatted\n");
  804. break;
  805. case DASD_STATE_READY:
  806. len = snprintf(buf, PAGE_SIZE, "ready\n");
  807. break;
  808. case DASD_STATE_ONLINE:
  809. len = snprintf(buf, PAGE_SIZE, "online\n");
  810. break;
  811. default:
  812. len = snprintf(buf, PAGE_SIZE, "no stat\n");
  813. break;
  814. }
  815. dasd_put_device(device);
  816. } else
  817. len = snprintf(buf, PAGE_SIZE, "unknown\n");
  818. return len;
  819. }
  820. static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL);
  821. static ssize_t
  822. dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
  823. {
  824. struct dasd_devmap *devmap;
  825. int alias;
  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, "0\n");
  831. }
  832. if (devmap->uid.type == UA_BASE_PAV_ALIAS ||
  833. devmap->uid.type == UA_HYPER_PAV_ALIAS)
  834. alias = 1;
  835. else
  836. alias = 0;
  837. spin_unlock(&dasd_devmap_lock);
  838. return sprintf(buf, alias ? "1\n" : "0\n");
  839. }
  840. static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
  841. static ssize_t
  842. dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
  843. {
  844. struct dasd_devmap *devmap;
  845. char *vendor;
  846. devmap = dasd_find_busid(dev_name(dev));
  847. spin_lock(&dasd_devmap_lock);
  848. if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
  849. vendor = devmap->uid.vendor;
  850. else
  851. vendor = "";
  852. spin_unlock(&dasd_devmap_lock);
  853. return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
  854. }
  855. static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
  856. #define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial */ 14 + 1 +\
  857. /* SSID */ 4 + 1 + /* unit addr */ 2 + 1 +\
  858. /* vduit */ 32 + 1)
  859. static ssize_t
  860. dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
  861. {
  862. struct dasd_devmap *devmap;
  863. char uid_string[UID_STRLEN];
  864. char ua_string[3];
  865. struct dasd_uid *uid;
  866. devmap = dasd_find_busid(dev_name(dev));
  867. spin_lock(&dasd_devmap_lock);
  868. if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
  869. spin_unlock(&dasd_devmap_lock);
  870. return sprintf(buf, "\n");
  871. }
  872. uid = &devmap->uid;
  873. switch (uid->type) {
  874. case UA_BASE_DEVICE:
  875. sprintf(ua_string, "%02x", uid->real_unit_addr);
  876. break;
  877. case UA_BASE_PAV_ALIAS:
  878. sprintf(ua_string, "%02x", uid->base_unit_addr);
  879. break;
  880. case UA_HYPER_PAV_ALIAS:
  881. sprintf(ua_string, "xx");
  882. break;
  883. default:
  884. /* should not happen, treat like base device */
  885. sprintf(ua_string, "%02x", uid->real_unit_addr);
  886. break;
  887. }
  888. if (strlen(uid->vduit) > 0)
  889. snprintf(uid_string, sizeof(uid_string),
  890. "%s.%s.%04x.%s.%s",
  891. uid->vendor, uid->serial,
  892. uid->ssid, ua_string,
  893. uid->vduit);
  894. else
  895. snprintf(uid_string, sizeof(uid_string),
  896. "%s.%s.%04x.%s",
  897. uid->vendor, uid->serial,
  898. uid->ssid, ua_string);
  899. spin_unlock(&dasd_devmap_lock);
  900. return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
  901. }
  902. static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
  903. /*
  904. * extended error-reporting
  905. */
  906. static ssize_t
  907. dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
  908. {
  909. struct dasd_devmap *devmap;
  910. int eer_flag;
  911. devmap = dasd_find_busid(dev_name(dev));
  912. if (!IS_ERR(devmap) && devmap->device)
  913. eer_flag = dasd_eer_enabled(devmap->device);
  914. else
  915. eer_flag = 0;
  916. return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
  917. }
  918. static ssize_t
  919. dasd_eer_store(struct device *dev, struct device_attribute *attr,
  920. const char *buf, size_t count)
  921. {
  922. struct dasd_devmap *devmap;
  923. int val, rc;
  924. char *endp;
  925. devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
  926. if (IS_ERR(devmap))
  927. return PTR_ERR(devmap);
  928. if (!devmap->device)
  929. return -ENODEV;
  930. val = simple_strtoul(buf, &endp, 0);
  931. if (((endp + 1) < (buf + count)) || (val > 1))
  932. return -EINVAL;
  933. if (val) {
  934. rc = dasd_eer_enable(devmap->device);
  935. if (rc)
  936. return rc;
  937. } else
  938. dasd_eer_disable(devmap->device);
  939. return count;
  940. }
  941. static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
  942. static struct attribute * dasd_attrs[] = {
  943. &dev_attr_readonly.attr,
  944. &dev_attr_discipline.attr,
  945. &dev_attr_status.attr,
  946. &dev_attr_alias.attr,
  947. &dev_attr_vendor.attr,
  948. &dev_attr_uid.attr,
  949. &dev_attr_use_diag.attr,
  950. &dev_attr_eer_enabled.attr,
  951. &dev_attr_erplog.attr,
  952. &dev_attr_failfast.attr,
  953. NULL,
  954. };
  955. static struct attribute_group dasd_attr_group = {
  956. .attrs = dasd_attrs,
  957. };
  958. /*
  959. * Return copy of the device unique identifier.
  960. */
  961. int
  962. dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
  963. {
  964. struct dasd_devmap *devmap;
  965. devmap = dasd_find_busid(dev_name(&cdev->dev));
  966. if (IS_ERR(devmap))
  967. return PTR_ERR(devmap);
  968. spin_lock(&dasd_devmap_lock);
  969. *uid = devmap->uid;
  970. spin_unlock(&dasd_devmap_lock);
  971. return 0;
  972. }
  973. /*
  974. * Register the given device unique identifier into devmap struct.
  975. * In addition check if the related storage server subsystem ID is already
  976. * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
  977. * create new entry.
  978. * Return 0 if server was already in serverlist,
  979. * 1 if the server was added successful
  980. * <0 in case of error.
  981. */
  982. int
  983. dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
  984. {
  985. struct dasd_devmap *devmap;
  986. devmap = dasd_find_busid(dev_name(&cdev->dev));
  987. if (IS_ERR(devmap))
  988. return PTR_ERR(devmap);
  989. spin_lock(&dasd_devmap_lock);
  990. devmap->uid = *uid;
  991. spin_unlock(&dasd_devmap_lock);
  992. return 0;
  993. }
  994. EXPORT_SYMBOL_GPL(dasd_set_uid);
  995. /*
  996. * Return value of the specified feature.
  997. */
  998. int
  999. dasd_get_feature(struct ccw_device *cdev, int feature)
  1000. {
  1001. struct dasd_devmap *devmap;
  1002. devmap = dasd_find_busid(dev_name(&cdev->dev));
  1003. if (IS_ERR(devmap))
  1004. return PTR_ERR(devmap);
  1005. return ((devmap->features & feature) != 0);
  1006. }
  1007. /*
  1008. * Set / reset given feature.
  1009. * Flag indicates wether to set (!=0) or the reset (=0) the feature.
  1010. */
  1011. int
  1012. dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
  1013. {
  1014. struct dasd_devmap *devmap;
  1015. devmap = dasd_find_busid(dev_name(&cdev->dev));
  1016. if (IS_ERR(devmap))
  1017. return PTR_ERR(devmap);
  1018. spin_lock(&dasd_devmap_lock);
  1019. if (flag)
  1020. devmap->features |= feature;
  1021. else
  1022. devmap->features &= ~feature;
  1023. if (devmap->device)
  1024. devmap->device->features = devmap->features;
  1025. spin_unlock(&dasd_devmap_lock);
  1026. return 0;
  1027. }
  1028. int
  1029. dasd_add_sysfs_files(struct ccw_device *cdev)
  1030. {
  1031. return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
  1032. }
  1033. void
  1034. dasd_remove_sysfs_files(struct ccw_device *cdev)
  1035. {
  1036. sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
  1037. }
  1038. int
  1039. dasd_devmap_init(void)
  1040. {
  1041. int i;
  1042. /* Initialize devmap structures. */
  1043. dasd_max_devindex = 0;
  1044. for (i = 0; i < 256; i++)
  1045. INIT_LIST_HEAD(&dasd_hashlists[i]);
  1046. return 0;
  1047. }
  1048. void
  1049. dasd_devmap_exit(void)
  1050. {
  1051. dasd_forget_ranges();
  1052. }