blacklist.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * S/390 common I/O routines -- blacklisting of specific devices
  3. *
  4. * Copyright IBM Corp. 1999, 2013
  5. * Author(s): Ingo Adlung (adlung@de.ibm.com)
  6. * Cornelia Huck (cornelia.huck@de.ibm.com)
  7. * Arnd Bergmann (arndb@de.ibm.com)
  8. */
  9. #define KMSG_COMPONENT "cio"
  10. #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  11. #include <linux/init.h>
  12. #include <linux/vmalloc.h>
  13. #include <linux/proc_fs.h>
  14. #include <linux/seq_file.h>
  15. #include <linux/ctype.h>
  16. #include <linux/device.h>
  17. #include <asm/uaccess.h>
  18. #include <asm/cio.h>
  19. #include <asm/ipl.h>
  20. #include "blacklist.h"
  21. #include "cio.h"
  22. #include "cio_debug.h"
  23. #include "css.h"
  24. #include "device.h"
  25. /*
  26. * "Blacklisting" of certain devices:
  27. * Device numbers given in the commandline as cio_ignore=... won't be known
  28. * to Linux.
  29. *
  30. * These can be single devices or ranges of devices
  31. */
  32. /* 65536 bits for each set to indicate if a devno is blacklisted or not */
  33. #define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \
  34. (8*sizeof(long)))
  35. static unsigned long bl_dev[__MAX_SSID + 1][__BL_DEV_WORDS];
  36. typedef enum {add, free} range_action;
  37. /*
  38. * Function: blacklist_range
  39. * (Un-)blacklist the devices from-to
  40. */
  41. static int blacklist_range(range_action action, unsigned int from_ssid,
  42. unsigned int to_ssid, unsigned int from,
  43. unsigned int to, int msgtrigger)
  44. {
  45. if ((from_ssid > to_ssid) || ((from_ssid == to_ssid) && (from > to))) {
  46. if (msgtrigger)
  47. pr_warning("0.%x.%04x to 0.%x.%04x is not a valid "
  48. "range for cio_ignore\n", from_ssid, from,
  49. to_ssid, to);
  50. return 1;
  51. }
  52. while ((from_ssid < to_ssid) || ((from_ssid == to_ssid) &&
  53. (from <= to))) {
  54. if (action == add)
  55. set_bit(from, bl_dev[from_ssid]);
  56. else
  57. clear_bit(from, bl_dev[from_ssid]);
  58. from++;
  59. if (from > __MAX_SUBCHANNEL) {
  60. from_ssid++;
  61. from = 0;
  62. }
  63. }
  64. return 0;
  65. }
  66. static int pure_hex(char **cp, unsigned int *val, int min_digit,
  67. int max_digit, int max_val)
  68. {
  69. int diff;
  70. diff = 0;
  71. *val = 0;
  72. while (diff <= max_digit) {
  73. int value = hex_to_bin(**cp);
  74. if (value < 0)
  75. break;
  76. *val = *val * 16 + value;
  77. (*cp)++;
  78. diff++;
  79. }
  80. if ((diff < min_digit) || (diff > max_digit) || (*val > max_val))
  81. return 1;
  82. return 0;
  83. }
  84. static int parse_busid(char *str, unsigned int *cssid, unsigned int *ssid,
  85. unsigned int *devno, int msgtrigger)
  86. {
  87. char *str_work;
  88. int val, rc, ret;
  89. rc = 1;
  90. if (*str == '\0')
  91. goto out;
  92. /* old style */
  93. str_work = str;
  94. val = simple_strtoul(str, &str_work, 16);
  95. if (*str_work == '\0') {
  96. if (val <= __MAX_SUBCHANNEL) {
  97. *devno = val;
  98. *ssid = 0;
  99. *cssid = 0;
  100. rc = 0;
  101. }
  102. goto out;
  103. }
  104. /* new style */
  105. str_work = str;
  106. ret = pure_hex(&str_work, cssid, 1, 2, __MAX_CSSID);
  107. if (ret || (str_work[0] != '.'))
  108. goto out;
  109. str_work++;
  110. ret = pure_hex(&str_work, ssid, 1, 1, __MAX_SSID);
  111. if (ret || (str_work[0] != '.'))
  112. goto out;
  113. str_work++;
  114. ret = pure_hex(&str_work, devno, 4, 4, __MAX_SUBCHANNEL);
  115. if (ret || (str_work[0] != '\0'))
  116. goto out;
  117. rc = 0;
  118. out:
  119. if (rc && msgtrigger)
  120. pr_warning("%s is not a valid device for the cio_ignore "
  121. "kernel parameter\n", str);
  122. return rc;
  123. }
  124. static int blacklist_parse_parameters(char *str, range_action action,
  125. int msgtrigger)
  126. {
  127. unsigned int from_cssid, to_cssid, from_ssid, to_ssid, from, to;
  128. int rc, totalrc;
  129. char *parm;
  130. range_action ra;
  131. totalrc = 0;
  132. while ((parm = strsep(&str, ","))) {
  133. rc = 0;
  134. ra = action;
  135. if (*parm == '!') {
  136. if (ra == add)
  137. ra = free;
  138. else
  139. ra = add;
  140. parm++;
  141. }
  142. if (strcmp(parm, "all") == 0) {
  143. from_cssid = 0;
  144. from_ssid = 0;
  145. from = 0;
  146. to_cssid = __MAX_CSSID;
  147. to_ssid = __MAX_SSID;
  148. to = __MAX_SUBCHANNEL;
  149. } else if (strcmp(parm, "ipldev") == 0) {
  150. if (ipl_info.type == IPL_TYPE_CCW) {
  151. from_cssid = 0;
  152. from_ssid = ipl_info.data.ccw.dev_id.ssid;
  153. from = ipl_info.data.ccw.dev_id.devno;
  154. } else if (ipl_info.type == IPL_TYPE_FCP ||
  155. ipl_info.type == IPL_TYPE_FCP_DUMP) {
  156. from_cssid = 0;
  157. from_ssid = ipl_info.data.fcp.dev_id.ssid;
  158. from = ipl_info.data.fcp.dev_id.devno;
  159. } else {
  160. continue;
  161. }
  162. to_cssid = from_cssid;
  163. to_ssid = from_ssid;
  164. to = from;
  165. } else if (strcmp(parm, "condev") == 0) {
  166. if (console_devno == -1)
  167. continue;
  168. from_cssid = to_cssid = 0;
  169. from_ssid = to_ssid = 0;
  170. from = to = console_devno;
  171. } else {
  172. rc = parse_busid(strsep(&parm, "-"), &from_cssid,
  173. &from_ssid, &from, msgtrigger);
  174. if (!rc) {
  175. if (parm != NULL)
  176. rc = parse_busid(parm, &to_cssid,
  177. &to_ssid, &to,
  178. msgtrigger);
  179. else {
  180. to_cssid = from_cssid;
  181. to_ssid = from_ssid;
  182. to = from;
  183. }
  184. }
  185. }
  186. if (!rc) {
  187. rc = blacklist_range(ra, from_ssid, to_ssid, from, to,
  188. msgtrigger);
  189. if (rc)
  190. totalrc = -EINVAL;
  191. } else
  192. totalrc = -EINVAL;
  193. }
  194. return totalrc;
  195. }
  196. static int __init
  197. blacklist_setup (char *str)
  198. {
  199. CIO_MSG_EVENT(6, "Reading blacklist parameters\n");
  200. if (blacklist_parse_parameters(str, add, 1))
  201. return 0;
  202. return 1;
  203. }
  204. __setup ("cio_ignore=", blacklist_setup);
  205. /* Checking if devices are blacklisted */
  206. /*
  207. * Function: is_blacklisted
  208. * Returns 1 if the given devicenumber can be found in the blacklist,
  209. * otherwise 0.
  210. * Used by validate_subchannel()
  211. */
  212. int
  213. is_blacklisted (int ssid, int devno)
  214. {
  215. return test_bit (devno, bl_dev[ssid]);
  216. }
  217. #ifdef CONFIG_PROC_FS
  218. /*
  219. * Function: blacklist_parse_proc_parameters
  220. * parse the stuff which is piped to /proc/cio_ignore
  221. */
  222. static int blacklist_parse_proc_parameters(char *buf)
  223. {
  224. int rc;
  225. char *parm;
  226. parm = strsep(&buf, " ");
  227. if (strcmp("free", parm) == 0) {
  228. rc = blacklist_parse_parameters(buf, free, 0);
  229. css_schedule_eval_all_unreg(0);
  230. } else if (strcmp("add", parm) == 0)
  231. rc = blacklist_parse_parameters(buf, add, 0);
  232. else if (strcmp("purge", parm) == 0)
  233. return ccw_purge_blacklisted();
  234. else
  235. return -EINVAL;
  236. return rc;
  237. }
  238. /* Iterator struct for all devices. */
  239. struct ccwdev_iter {
  240. int devno;
  241. int ssid;
  242. int in_range;
  243. };
  244. static void *
  245. cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
  246. {
  247. struct ccwdev_iter *iter = s->private;
  248. if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
  249. return NULL;
  250. memset(iter, 0, sizeof(*iter));
  251. iter->ssid = *offset / (__MAX_SUBCHANNEL + 1);
  252. iter->devno = *offset % (__MAX_SUBCHANNEL + 1);
  253. return iter;
  254. }
  255. static void
  256. cio_ignore_proc_seq_stop(struct seq_file *s, void *it)
  257. {
  258. }
  259. static void *
  260. cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
  261. {
  262. struct ccwdev_iter *iter;
  263. if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
  264. return NULL;
  265. iter = it;
  266. if (iter->devno == __MAX_SUBCHANNEL) {
  267. iter->devno = 0;
  268. iter->ssid++;
  269. if (iter->ssid > __MAX_SSID)
  270. return NULL;
  271. } else
  272. iter->devno++;
  273. (*offset)++;
  274. return iter;
  275. }
  276. static int
  277. cio_ignore_proc_seq_show(struct seq_file *s, void *it)
  278. {
  279. struct ccwdev_iter *iter;
  280. iter = it;
  281. if (!is_blacklisted(iter->ssid, iter->devno))
  282. /* Not blacklisted, nothing to output. */
  283. return 0;
  284. if (!iter->in_range) {
  285. /* First device in range. */
  286. if ((iter->devno == __MAX_SUBCHANNEL) ||
  287. !is_blacklisted(iter->ssid, iter->devno + 1)) {
  288. /* Singular device. */
  289. seq_printf(s, "0.%x.%04x\n", iter->ssid, iter->devno);
  290. return 0;
  291. }
  292. iter->in_range = 1;
  293. seq_printf(s, "0.%x.%04x-", iter->ssid, iter->devno);
  294. return 0;
  295. }
  296. if ((iter->devno == __MAX_SUBCHANNEL) ||
  297. !is_blacklisted(iter->ssid, iter->devno + 1)) {
  298. /* Last device in range. */
  299. iter->in_range = 0;
  300. seq_printf(s, "0.%x.%04x\n", iter->ssid, iter->devno);
  301. }
  302. return 0;
  303. }
  304. static ssize_t
  305. cio_ignore_write(struct file *file, const char __user *user_buf,
  306. size_t user_len, loff_t *offset)
  307. {
  308. char *buf;
  309. ssize_t rc, ret, i;
  310. if (*offset)
  311. return -EINVAL;
  312. if (user_len > 65536)
  313. user_len = 65536;
  314. buf = vzalloc(user_len + 1); /* maybe better use the stack? */
  315. if (buf == NULL)
  316. return -ENOMEM;
  317. if (strncpy_from_user (buf, user_buf, user_len) < 0) {
  318. rc = -EFAULT;
  319. goto out_free;
  320. }
  321. i = user_len - 1;
  322. while ((i >= 0) && (isspace(buf[i]) || (buf[i] == 0))) {
  323. buf[i] = '\0';
  324. i--;
  325. }
  326. ret = blacklist_parse_proc_parameters(buf);
  327. if (ret)
  328. rc = ret;
  329. else
  330. rc = user_len;
  331. out_free:
  332. vfree (buf);
  333. return rc;
  334. }
  335. static const struct seq_operations cio_ignore_proc_seq_ops = {
  336. .start = cio_ignore_proc_seq_start,
  337. .stop = cio_ignore_proc_seq_stop,
  338. .next = cio_ignore_proc_seq_next,
  339. .show = cio_ignore_proc_seq_show,
  340. };
  341. static int
  342. cio_ignore_proc_open(struct inode *inode, struct file *file)
  343. {
  344. return seq_open_private(file, &cio_ignore_proc_seq_ops,
  345. sizeof(struct ccwdev_iter));
  346. }
  347. static const struct file_operations cio_ignore_proc_fops = {
  348. .open = cio_ignore_proc_open,
  349. .read = seq_read,
  350. .llseek = seq_lseek,
  351. .release = seq_release_private,
  352. .write = cio_ignore_write,
  353. };
  354. static int
  355. cio_ignore_proc_init (void)
  356. {
  357. struct proc_dir_entry *entry;
  358. entry = proc_create("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR, NULL,
  359. &cio_ignore_proc_fops);
  360. if (!entry)
  361. return -ENOENT;
  362. return 0;
  363. }
  364. __initcall (cio_ignore_proc_init);
  365. #endif /* CONFIG_PROC_FS */