aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/blacklist.c
diff options
context:
space:
mode:
authorCornelia Huck <cohuck@de.ibm.com>2006-01-06 03:19:25 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:52 -0500
commitfb6958a594da49ece869793e6ec163b89fc5f79f (patch)
tree0746cc23ab13a059f9a34d7fc134aaf6410d07b8 /drivers/s390/cio/blacklist.c
parent678a395b356a98368a93c3640252502b70c3676f (diff)
[PATCH] s390: multiple subchannel sets support
Add support for multiple subchannel sets. Works with arbitrary devices in subchannel set 1 and is transparent to device drivers. Although currently only two subchannel sets are available, this will work with the architectured maximum number of subchannel sets as well. Signed-off-by: Cornelia Huck <cohuck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/s390/cio/blacklist.c')
-rw-r--r--drivers/s390/cio/blacklist.c86
1 files changed, 50 insertions, 36 deletions
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index daea41c63329..2d444cb2fdf7 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/s390/cio/blacklist.c 2 * drivers/s390/cio/blacklist.c
3 * S/390 common I/O routines -- blacklisting of specific devices 3 * S/390 common I/O routines -- blacklisting of specific devices
4 * $Revision: 1.35 $ 4 * $Revision: 1.39 $
5 * 5 *
6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, 6 * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
7 * IBM Corporation 7 * IBM Corporation
@@ -35,10 +35,10 @@
35 * These can be single devices or ranges of devices 35 * These can be single devices or ranges of devices
36 */ 36 */
37 37
38/* 65536 bits to indicate if a devno is blacklisted or not */ 38/* 65536 bits for each set to indicate if a devno is blacklisted or not */
39#define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \ 39#define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \
40 (8*sizeof(long))) 40 (8*sizeof(long)))
41static unsigned long bl_dev[__BL_DEV_WORDS]; 41static unsigned long bl_dev[__MAX_SSID + 1][__BL_DEV_WORDS];
42typedef enum {add, free} range_action; 42typedef enum {add, free} range_action;
43 43
44/* 44/*
@@ -46,21 +46,23 @@ typedef enum {add, free} range_action;
46 * (Un-)blacklist the devices from-to 46 * (Un-)blacklist the devices from-to
47 */ 47 */
48static inline void 48static inline void
49blacklist_range (range_action action, unsigned int from, unsigned int to) 49blacklist_range (range_action action, unsigned int from, unsigned int to,
50 unsigned int ssid)
50{ 51{
51 if (!to) 52 if (!to)
52 to = from; 53 to = from;
53 54
54 if (from > to || to > __MAX_SUBCHANNEL) { 55 if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) {
55 printk (KERN_WARNING "Invalid blacklist range " 56 printk (KERN_WARNING "Invalid blacklist range "
56 "0x%04x to 0x%04x, skipping\n", from, to); 57 "0.%x.%04x to 0.%x.%04x, skipping\n",
58 ssid, from, ssid, to);
57 return; 59 return;
58 } 60 }
59 for (; from <= to; from++) { 61 for (; from <= to; from++) {
60 if (action == add) 62 if (action == add)
61 set_bit (from, bl_dev); 63 set_bit (from, bl_dev[ssid]);
62 else 64 else
63 clear_bit (from, bl_dev); 65 clear_bit (from, bl_dev[ssid]);
64 } 66 }
65} 67}
66 68
@@ -70,7 +72,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to)
70 * Shamelessly grabbed from dasd_devmap.c. 72 * Shamelessly grabbed from dasd_devmap.c.
71 */ 73 */
72static inline int 74static inline int
73blacklist_busid(char **str, int *id0, int *id1, int *devno) 75blacklist_busid(char **str, int *id0, int *ssid, int *devno)
74{ 76{
75 int val, old_style; 77 int val, old_style;
76 char *sav; 78 char *sav;
@@ -87,7 +89,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
87 goto confused; 89 goto confused;
88 val = simple_strtoul(*str, str, 16); 90 val = simple_strtoul(*str, str, 16);
89 if (old_style || (*str)[0] != '.') { 91 if (old_style || (*str)[0] != '.') {
90 *id0 = *id1 = 0; 92 *id0 = *ssid = 0;
91 if (val < 0 || val > 0xffff) 93 if (val < 0 || val > 0xffff)
92 goto confused; 94 goto confused;
93 *devno = val; 95 *devno = val;
@@ -106,7 +108,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
106 val = simple_strtoul(*str, str, 16); 108 val = simple_strtoul(*str, str, 16);
107 if (val < 0 || val > 0xff || (*str)++[0] != '.') 109 if (val < 0 || val > 0xff || (*str)++[0] != '.')
108 goto confused; 110 goto confused;
109 *id1 = val; 111 *ssid = val;
110 if (!isxdigit((*str)[0])) /* We require at least one hex digit */ 112 if (!isxdigit((*str)[0])) /* We require at least one hex digit */
111 goto confused; 113 goto confused;
112 val = simple_strtoul(*str, str, 16); 114 val = simple_strtoul(*str, str, 16);
@@ -126,7 +128,7 @@ confused:
126static inline int 128static inline int
127blacklist_parse_parameters (char *str, range_action action) 129blacklist_parse_parameters (char *str, range_action action)
128{ 130{
129 unsigned int from, to, from_id0, to_id0, from_id1, to_id1; 131 unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid;
130 132
131 while (*str != 0 && *str != '\n') { 133 while (*str != 0 && *str != '\n') {
132 range_action ra = action; 134 range_action ra = action;
@@ -143,23 +145,25 @@ blacklist_parse_parameters (char *str, range_action action)
143 */ 145 */
144 if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 || 146 if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 ||
145 strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) { 147 strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) {
146 from = 0; 148 int j;
147 to = __MAX_SUBCHANNEL; 149
148 str += 3; 150 str += 3;
151 for (j=0; j <= __MAX_SSID; j++)
152 blacklist_range(ra, 0, __MAX_SUBCHANNEL, j);
149 } else { 153 } else {
150 int rc; 154 int rc;
151 155
152 rc = blacklist_busid(&str, &from_id0, 156 rc = blacklist_busid(&str, &from_id0,
153 &from_id1, &from); 157 &from_ssid, &from);
154 if (rc) 158 if (rc)
155 continue; 159 continue;
156 to = from; 160 to = from;
157 to_id0 = from_id0; 161 to_id0 = from_id0;
158 to_id1 = from_id1; 162 to_ssid = from_ssid;
159 if (*str == '-') { 163 if (*str == '-') {
160 str++; 164 str++;
161 rc = blacklist_busid(&str, &to_id0, 165 rc = blacklist_busid(&str, &to_id0,
162 &to_id1, &to); 166 &to_ssid, &to);
163 if (rc) 167 if (rc)
164 continue; 168 continue;
165 } 169 }
@@ -169,18 +173,19 @@ blacklist_parse_parameters (char *str, range_action action)
169 strsep(&str, ",\n")); 173 strsep(&str, ",\n"));
170 continue; 174 continue;
171 } 175 }
172 if ((from_id0 != to_id0) || (from_id1 != to_id1)) { 176 if ((from_id0 != to_id0) ||
177 (from_ssid != to_ssid)) {
173 printk(KERN_WARNING "invalid cio_ignore range " 178 printk(KERN_WARNING "invalid cio_ignore range "
174 "%x.%x.%04x-%x.%x.%04x\n", 179 "%x.%x.%04x-%x.%x.%04x\n",
175 from_id0, from_id1, from, 180 from_id0, from_ssid, from,
176 to_id0, to_id1, to); 181 to_id0, to_ssid, to);
177 continue; 182 continue;
178 } 183 }
184 pr_debug("blacklist_setup: adding range "
185 "from %x.%x.%04x to %x.%x.%04x\n",
186 from_id0, from_ssid, from, to_id0, to_ssid, to);
187 blacklist_range (ra, from, to, to_ssid);
179 } 188 }
180 /* FIXME: ignoring id0 and id1 here. */
181 pr_debug("blacklist_setup: adding range "
182 "from 0.0.%04x to 0.0.%04x\n", from, to);
183 blacklist_range (ra, from, to);
184 } 189 }
185 return 1; 190 return 1;
186} 191}
@@ -214,9 +219,9 @@ __setup ("cio_ignore=", blacklist_setup);
214 * Used by validate_subchannel() 219 * Used by validate_subchannel()
215 */ 220 */
216int 221int
217is_blacklisted (int devno) 222is_blacklisted (int ssid, int devno)
218{ 223{
219 return test_bit (devno, bl_dev); 224 return test_bit (devno, bl_dev[ssid]);
220} 225}
221 226
222#ifdef CONFIG_PROC_FS 227#ifdef CONFIG_PROC_FS
@@ -283,6 +288,7 @@ blacklist_parse_proc_parameters (char *buf)
283/* Iterator struct for all devices. */ 288/* Iterator struct for all devices. */
284struct ccwdev_iter { 289struct ccwdev_iter {
285 int devno; 290 int devno;
291 int ssid;
286 int in_range; 292 int in_range;
287}; 293};
288 294
@@ -291,13 +297,14 @@ cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
291{ 297{
292 struct ccwdev_iter *iter; 298 struct ccwdev_iter *iter;
293 299
294 if (*offset > __MAX_SUBCHANNEL) 300 if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
295 return NULL; 301 return NULL;
296 iter = kmalloc(sizeof(struct ccwdev_iter), GFP_KERNEL); 302 iter = kmalloc(sizeof(struct ccwdev_iter), GFP_KERNEL);
297 if (!iter) 303 if (!iter)
298 return ERR_PTR(-ENOMEM); 304 return ERR_PTR(-ENOMEM);
299 memset(iter, 0, sizeof(struct ccwdev_iter)); 305 memset(iter, 0, sizeof(struct ccwdev_iter));
300 iter->devno = *offset; 306 iter->ssid = *offset / (__MAX_SUBCHANNEL + 1);
307 iter->devno = *offset % (__MAX_SUBCHANNEL + 1);
301 return iter; 308 return iter;
302} 309}
303 310
@@ -313,10 +320,16 @@ cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
313{ 320{
314 struct ccwdev_iter *iter; 321 struct ccwdev_iter *iter;
315 322
316 if (*offset > __MAX_SUBCHANNEL) 323 if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
317 return NULL; 324 return NULL;
318 iter = (struct ccwdev_iter *)it; 325 iter = (struct ccwdev_iter *)it;
319 iter->devno++; 326 if (iter->devno == __MAX_SUBCHANNEL) {
327 iter->devno = 0;
328 iter->ssid++;
329 if (iter->ssid > __MAX_SSID)
330 return NULL;
331 } else
332 iter->devno++;
320 (*offset)++; 333 (*offset)++;
321 return iter; 334 return iter;
322} 335}
@@ -327,23 +340,24 @@ cio_ignore_proc_seq_show(struct seq_file *s, void *it)
327 struct ccwdev_iter *iter; 340 struct ccwdev_iter *iter;
328 341
329 iter = (struct ccwdev_iter *)it; 342 iter = (struct ccwdev_iter *)it;
330 if (!is_blacklisted(iter->devno)) 343 if (!is_blacklisted(iter->ssid, iter->devno))
331 /* Not blacklisted, nothing to output. */ 344 /* Not blacklisted, nothing to output. */
332 return 0; 345 return 0;
333 if (!iter->in_range) { 346 if (!iter->in_range) {
334 /* First device in range. */ 347 /* First device in range. */
335 if ((iter->devno == __MAX_SUBCHANNEL) || 348 if ((iter->devno == __MAX_SUBCHANNEL) ||
336 !is_blacklisted(iter->devno + 1)) 349 !is_blacklisted(iter->ssid, iter->devno + 1))
337 /* Singular device. */ 350 /* Singular device. */
338 return seq_printf(s, "0.0.%04x\n", iter->devno); 351 return seq_printf(s, "0.%x.%04x\n",
352 iter->ssid, iter->devno);
339 iter->in_range = 1; 353 iter->in_range = 1;
340 return seq_printf(s, "0.0.%04x-", iter->devno); 354 return seq_printf(s, "0.%x.%04x-", iter->ssid, iter->devno);
341 } 355 }
342 if ((iter->devno == __MAX_SUBCHANNEL) || 356 if ((iter->devno == __MAX_SUBCHANNEL) ||
343 !is_blacklisted(iter->devno + 1)) { 357 !is_blacklisted(iter->ssid, iter->devno + 1)) {
344 /* Last device in range. */ 358 /* Last device in range. */
345 iter->in_range = 0; 359 iter->in_range = 0;
346 return seq_printf(s, "0.0.%04x\n", iter->devno); 360 return seq_printf(s, "0.%x.%04x\n", iter->ssid, iter->devno);
347 } 361 }
348 return 0; 362 return 0;
349} 363}