diff options
author | David S. Miller <davem@davemloft.net> | 2010-02-28 22:23:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-28 22:23:06 -0500 |
commit | 47871889c601d8199c51a4086f77eebd77c29b0b (patch) | |
tree | 40cdcac3bff0ee40cc33dcca61d0577cdf965f77 /drivers/s390 | |
parent | c16cc0b464b8876cfd57ce1c1dbcb6f9a6a0bce3 (diff) | |
parent | 30ff056c42c665b9ea535d8515890857ae382540 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts:
drivers/firmware/iscsi_ibft.c
Diffstat (limited to 'drivers/s390')
37 files changed, 1075 insertions, 847 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 5905936c7c60..9ab1ae40565f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
21 | #include <linux/hdreg.h> | 21 | #include <linux/hdreg.h> |
22 | #include <linux/async.h> | 22 | #include <linux/async.h> |
23 | #include <linux/mutex.h> | ||
23 | 24 | ||
24 | #include <asm/ccwdev.h> | 25 | #include <asm/ccwdev.h> |
25 | #include <asm/ebcdic.h> | 26 | #include <asm/ebcdic.h> |
@@ -112,6 +113,7 @@ struct dasd_device *dasd_alloc_device(void) | |||
112 | INIT_WORK(&device->restore_device, do_restore_device); | 113 | INIT_WORK(&device->restore_device, do_restore_device); |
113 | device->state = DASD_STATE_NEW; | 114 | device->state = DASD_STATE_NEW; |
114 | device->target = DASD_STATE_NEW; | 115 | device->target = DASD_STATE_NEW; |
116 | mutex_init(&device->state_mutex); | ||
115 | 117 | ||
116 | return device; | 118 | return device; |
117 | } | 119 | } |
@@ -321,8 +323,8 @@ static int dasd_state_ready_to_basic(struct dasd_device *device) | |||
321 | device->state = DASD_STATE_READY; | 323 | device->state = DASD_STATE_READY; |
322 | return rc; | 324 | return rc; |
323 | } | 325 | } |
324 | dasd_destroy_partitions(block); | ||
325 | dasd_flush_request_queue(block); | 326 | dasd_flush_request_queue(block); |
327 | dasd_destroy_partitions(block); | ||
326 | block->blocks = 0; | 328 | block->blocks = 0; |
327 | block->bp_block = 0; | 329 | block->bp_block = 0; |
328 | block->s2b_shift = 0; | 330 | block->s2b_shift = 0; |
@@ -484,10 +486,8 @@ static void dasd_change_state(struct dasd_device *device) | |||
484 | if (rc) | 486 | if (rc) |
485 | device->target = device->state; | 487 | device->target = device->state; |
486 | 488 | ||
487 | if (device->state == device->target) { | 489 | if (device->state == device->target) |
488 | wake_up(&dasd_init_waitq); | 490 | wake_up(&dasd_init_waitq); |
489 | dasd_put_device(device); | ||
490 | } | ||
491 | 491 | ||
492 | /* let user-space know that the device status changed */ | 492 | /* let user-space know that the device status changed */ |
493 | kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); | 493 | kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); |
@@ -502,7 +502,9 @@ static void dasd_change_state(struct dasd_device *device) | |||
502 | static void do_kick_device(struct work_struct *work) | 502 | static void do_kick_device(struct work_struct *work) |
503 | { | 503 | { |
504 | struct dasd_device *device = container_of(work, struct dasd_device, kick_work); | 504 | struct dasd_device *device = container_of(work, struct dasd_device, kick_work); |
505 | mutex_lock(&device->state_mutex); | ||
505 | dasd_change_state(device); | 506 | dasd_change_state(device); |
507 | mutex_unlock(&device->state_mutex); | ||
506 | dasd_schedule_device_bh(device); | 508 | dasd_schedule_device_bh(device); |
507 | dasd_put_device(device); | 509 | dasd_put_device(device); |
508 | } | 510 | } |
@@ -539,18 +541,19 @@ void dasd_restore_device(struct dasd_device *device) | |||
539 | void dasd_set_target_state(struct dasd_device *device, int target) | 541 | void dasd_set_target_state(struct dasd_device *device, int target) |
540 | { | 542 | { |
541 | dasd_get_device(device); | 543 | dasd_get_device(device); |
544 | mutex_lock(&device->state_mutex); | ||
542 | /* If we are in probeonly mode stop at DASD_STATE_READY. */ | 545 | /* If we are in probeonly mode stop at DASD_STATE_READY. */ |
543 | if (dasd_probeonly && target > DASD_STATE_READY) | 546 | if (dasd_probeonly && target > DASD_STATE_READY) |
544 | target = DASD_STATE_READY; | 547 | target = DASD_STATE_READY; |
545 | if (device->target != target) { | 548 | if (device->target != target) { |
546 | if (device->state == target) { | 549 | if (device->state == target) |
547 | wake_up(&dasd_init_waitq); | 550 | wake_up(&dasd_init_waitq); |
548 | dasd_put_device(device); | ||
549 | } | ||
550 | device->target = target; | 551 | device->target = target; |
551 | } | 552 | } |
552 | if (device->state != device->target) | 553 | if (device->state != device->target) |
553 | dasd_change_state(device); | 554 | dasd_change_state(device); |
555 | mutex_unlock(&device->state_mutex); | ||
556 | dasd_put_device(device); | ||
554 | } | 557 | } |
555 | 558 | ||
556 | /* | 559 | /* |
@@ -1000,12 +1003,20 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, | |||
1000 | return; | 1003 | return; |
1001 | } | 1004 | } |
1002 | 1005 | ||
1003 | device = (struct dasd_device *) cqr->startdev; | 1006 | device = dasd_device_from_cdev_locked(cdev); |
1004 | if (device == NULL || | 1007 | if (IS_ERR(device)) { |
1005 | device != dasd_device_from_cdev_locked(cdev) || | 1008 | DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", |
1006 | strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { | 1009 | "unable to get device from cdev"); |
1010 | return; | ||
1011 | } | ||
1012 | |||
1013 | if (!cqr->startdev || | ||
1014 | device != cqr->startdev || | ||
1015 | strncmp(cqr->startdev->discipline->ebcname, | ||
1016 | (char *) &cqr->magic, 4)) { | ||
1007 | DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", | 1017 | DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", |
1008 | "invalid device in request"); | 1018 | "invalid device in request"); |
1019 | dasd_put_device(device); | ||
1009 | return; | 1020 | return; |
1010 | } | 1021 | } |
1011 | 1022 | ||
@@ -1692,7 +1703,6 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr) | |||
1692 | cqr, rc); | 1703 | cqr, rc); |
1693 | } else { | 1704 | } else { |
1694 | cqr->stopclk = get_clock(); | 1705 | cqr->stopclk = get_clock(); |
1695 | rc = 1; | ||
1696 | } | 1706 | } |
1697 | break; | 1707 | break; |
1698 | default: /* already finished or clear pending - do nothing */ | 1708 | default: /* already finished or clear pending - do nothing */ |
@@ -2170,9 +2180,13 @@ static void dasd_flush_request_queue(struct dasd_block *block) | |||
2170 | static int dasd_open(struct block_device *bdev, fmode_t mode) | 2180 | static int dasd_open(struct block_device *bdev, fmode_t mode) |
2171 | { | 2181 | { |
2172 | struct dasd_block *block = bdev->bd_disk->private_data; | 2182 | struct dasd_block *block = bdev->bd_disk->private_data; |
2173 | struct dasd_device *base = block->base; | 2183 | struct dasd_device *base; |
2174 | int rc; | 2184 | int rc; |
2175 | 2185 | ||
2186 | if (!block) | ||
2187 | return -ENODEV; | ||
2188 | |||
2189 | base = block->base; | ||
2176 | atomic_inc(&block->open_count); | 2190 | atomic_inc(&block->open_count); |
2177 | if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) { | 2191 | if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) { |
2178 | rc = -ENODEV; | 2192 | rc = -ENODEV; |
@@ -2285,11 +2299,6 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie) | |||
2285 | if (ret) | 2299 | if (ret) |
2286 | pr_warning("%s: Setting the DASD online failed with rc=%d\n", | 2300 | pr_warning("%s: Setting the DASD online failed with rc=%d\n", |
2287 | dev_name(&cdev->dev), ret); | 2301 | dev_name(&cdev->dev), ret); |
2288 | else { | ||
2289 | struct dasd_device *device = dasd_device_from_cdev(cdev); | ||
2290 | wait_event(dasd_init_waitq, _wait_for_device(device)); | ||
2291 | dasd_put_device(device); | ||
2292 | } | ||
2293 | } | 2302 | } |
2294 | 2303 | ||
2295 | /* | 2304 | /* |
@@ -2424,6 +2433,9 @@ int dasd_generic_set_online(struct ccw_device *cdev, | |||
2424 | } else | 2433 | } else |
2425 | pr_debug("dasd_generic device %s found\n", | 2434 | pr_debug("dasd_generic device %s found\n", |
2426 | dev_name(&cdev->dev)); | 2435 | dev_name(&cdev->dev)); |
2436 | |||
2437 | wait_event(dasd_init_waitq, _wait_for_device(device)); | ||
2438 | |||
2427 | dasd_put_device(device); | 2439 | dasd_put_device(device); |
2428 | return rc; | 2440 | return rc; |
2429 | } | 2441 | } |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 4cac5b54f26a..d49766f3b940 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -874,12 +874,19 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr, | |||
874 | ssize_t len; | 874 | ssize_t len; |
875 | 875 | ||
876 | device = dasd_device_from_cdev(to_ccwdev(dev)); | 876 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
877 | if (!IS_ERR(device) && device->discipline) { | 877 | if (IS_ERR(device)) |
878 | goto out; | ||
879 | else if (!device->discipline) { | ||
880 | dasd_put_device(device); | ||
881 | goto out; | ||
882 | } else { | ||
878 | len = snprintf(buf, PAGE_SIZE, "%s\n", | 883 | len = snprintf(buf, PAGE_SIZE, "%s\n", |
879 | device->discipline->name); | 884 | device->discipline->name); |
880 | dasd_put_device(device); | 885 | dasd_put_device(device); |
881 | } else | 886 | return len; |
882 | len = snprintf(buf, PAGE_SIZE, "none\n"); | 887 | } |
888 | out: | ||
889 | len = snprintf(buf, PAGE_SIZE, "none\n"); | ||
883 | return len; | 890 | return len; |
884 | } | 891 | } |
885 | 892 | ||
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index d3198303b93c..94f92a1247f2 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c | |||
@@ -88,6 +88,7 @@ void dasd_gendisk_free(struct dasd_block *block) | |||
88 | if (block->gdp) { | 88 | if (block->gdp) { |
89 | del_gendisk(block->gdp); | 89 | del_gendisk(block->gdp); |
90 | block->gdp->queue = NULL; | 90 | block->gdp->queue = NULL; |
91 | block->gdp->private_data = NULL; | ||
91 | put_disk(block->gdp); | 92 | put_disk(block->gdp); |
92 | block->gdp = NULL; | 93 | block->gdp = NULL; |
93 | } | 94 | } |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index e4c2143dabf6..ed73ce550822 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -368,6 +368,7 @@ struct dasd_device { | |||
368 | 368 | ||
369 | /* Device state and target state. */ | 369 | /* Device state and target state. */ |
370 | int state, target; | 370 | int state, target; |
371 | struct mutex state_mutex; | ||
371 | int stopped; /* device (ccw_device_start) was stopped */ | 372 | int stopped; /* device (ccw_device_start) was stopped */ |
372 | 373 | ||
373 | /* reference count. */ | 374 | /* reference count. */ |
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 71f95f54866f..f13a0bdd148c 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c | |||
@@ -165,51 +165,32 @@ static const struct file_operations dasd_devices_file_ops = { | |||
165 | .release = seq_release, | 165 | .release = seq_release, |
166 | }; | 166 | }; |
167 | 167 | ||
168 | static int | ||
169 | dasd_calc_metrics(char *page, char **start, off_t off, | ||
170 | int count, int *eof, int len) | ||
171 | { | ||
172 | len = (len > off) ? len - off : 0; | ||
173 | if (len > count) | ||
174 | len = count; | ||
175 | if (len < count) | ||
176 | *eof = 1; | ||
177 | *start = page + off; | ||
178 | return len; | ||
179 | } | ||
180 | |||
181 | #ifdef CONFIG_DASD_PROFILE | 168 | #ifdef CONFIG_DASD_PROFILE |
182 | static char * | 169 | static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int factor) |
183 | dasd_statistics_array(char *str, unsigned int *array, int factor) | ||
184 | { | 170 | { |
185 | int i; | 171 | int i; |
186 | 172 | ||
187 | for (i = 0; i < 32; i++) { | 173 | for (i = 0; i < 32; i++) { |
188 | str += sprintf(str, "%7d ", array[i] / factor); | 174 | seq_printf(m, "%7d ", array[i] / factor); |
189 | if (i == 15) | 175 | if (i == 15) |
190 | str += sprintf(str, "\n"); | 176 | seq_putc(m, '\n'); |
191 | } | 177 | } |
192 | str += sprintf(str,"\n"); | 178 | seq_putc(m, '\n'); |
193 | return str; | ||
194 | } | 179 | } |
195 | #endif /* CONFIG_DASD_PROFILE */ | 180 | #endif /* CONFIG_DASD_PROFILE */ |
196 | 181 | ||
197 | static int | 182 | static int dasd_stats_proc_show(struct seq_file *m, void *v) |
198 | dasd_statistics_read(char *page, char **start, off_t off, | ||
199 | int count, int *eof, void *data) | ||
200 | { | 183 | { |
201 | unsigned long len; | ||
202 | #ifdef CONFIG_DASD_PROFILE | 184 | #ifdef CONFIG_DASD_PROFILE |
203 | struct dasd_profile_info_t *prof; | 185 | struct dasd_profile_info_t *prof; |
204 | char *str; | ||
205 | int factor; | 186 | int factor; |
206 | 187 | ||
207 | /* check for active profiling */ | 188 | /* check for active profiling */ |
208 | if (dasd_profile_level == DASD_PROFILE_OFF) { | 189 | if (dasd_profile_level == DASD_PROFILE_OFF) { |
209 | len = sprintf(page, "Statistics are off - they might be " | 190 | seq_printf(m, "Statistics are off - they might be " |
210 | "switched on using 'echo set on > " | 191 | "switched on using 'echo set on > " |
211 | "/proc/dasd/statistics'\n"); | 192 | "/proc/dasd/statistics'\n"); |
212 | return dasd_calc_metrics(page, start, off, count, eof, len); | 193 | return 0; |
213 | } | 194 | } |
214 | 195 | ||
215 | prof = &dasd_global_profile; | 196 | prof = &dasd_global_profile; |
@@ -217,47 +198,49 @@ dasd_statistics_read(char *page, char **start, off_t off, | |||
217 | for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999; | 198 | for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999; |
218 | factor *= 10); | 199 | factor *= 10); |
219 | 200 | ||
220 | str = page; | 201 | seq_printf(m, "%d dasd I/O requests\n", prof->dasd_io_reqs); |
221 | str += sprintf(str, "%d dasd I/O requests\n", prof->dasd_io_reqs); | 202 | seq_printf(m, "with %u sectors(512B each)\n", |
222 | str += sprintf(str, "with %u sectors(512B each)\n", | ||
223 | prof->dasd_io_sects); | 203 | prof->dasd_io_sects); |
224 | str += sprintf(str, "Scale Factor is %d\n", factor); | 204 | seq_printf(m, "Scale Factor is %d\n", factor); |
225 | str += sprintf(str, | 205 | seq_printf(m, |
226 | " __<4 ___8 __16 __32 __64 _128 " | 206 | " __<4 ___8 __16 __32 __64 _128 " |
227 | " _256 _512 __1k __2k __4k __8k " | 207 | " _256 _512 __1k __2k __4k __8k " |
228 | " _16k _32k _64k 128k\n"); | 208 | " _16k _32k _64k 128k\n"); |
229 | str += sprintf(str, | 209 | seq_printf(m, |
230 | " _256 _512 __1M __2M __4M __8M " | 210 | " _256 _512 __1M __2M __4M __8M " |
231 | " _16M _32M _64M 128M 256M 512M " | 211 | " _16M _32M _64M 128M 256M 512M " |
232 | " __1G __2G __4G " " _>4G\n"); | 212 | " __1G __2G __4G " " _>4G\n"); |
233 | 213 | ||
234 | str += sprintf(str, "Histogram of sizes (512B secs)\n"); | 214 | seq_printf(m, "Histogram of sizes (512B secs)\n"); |
235 | str = dasd_statistics_array(str, prof->dasd_io_secs, factor); | 215 | dasd_statistics_array(m, prof->dasd_io_secs, factor); |
236 | str += sprintf(str, "Histogram of I/O times (microseconds)\n"); | 216 | seq_printf(m, "Histogram of I/O times (microseconds)\n"); |
237 | str = dasd_statistics_array(str, prof->dasd_io_times, factor); | 217 | dasd_statistics_array(m, prof->dasd_io_times, factor); |
238 | str += sprintf(str, "Histogram of I/O times per sector\n"); | 218 | seq_printf(m, "Histogram of I/O times per sector\n"); |
239 | str = dasd_statistics_array(str, prof->dasd_io_timps, factor); | 219 | dasd_statistics_array(m, prof->dasd_io_timps, factor); |
240 | str += sprintf(str, "Histogram of I/O time till ssch\n"); | 220 | seq_printf(m, "Histogram of I/O time till ssch\n"); |
241 | str = dasd_statistics_array(str, prof->dasd_io_time1, factor); | 221 | dasd_statistics_array(m, prof->dasd_io_time1, factor); |
242 | str += sprintf(str, "Histogram of I/O time between ssch and irq\n"); | 222 | seq_printf(m, "Histogram of I/O time between ssch and irq\n"); |
243 | str = dasd_statistics_array(str, prof->dasd_io_time2, factor); | 223 | dasd_statistics_array(m, prof->dasd_io_time2, factor); |
244 | str += sprintf(str, "Histogram of I/O time between ssch " | 224 | seq_printf(m, "Histogram of I/O time between ssch " |
245 | "and irq per sector\n"); | 225 | "and irq per sector\n"); |
246 | str = dasd_statistics_array(str, prof->dasd_io_time2ps, factor); | 226 | dasd_statistics_array(m, prof->dasd_io_time2ps, factor); |
247 | str += sprintf(str, "Histogram of I/O time between irq and end\n"); | 227 | seq_printf(m, "Histogram of I/O time between irq and end\n"); |
248 | str = dasd_statistics_array(str, prof->dasd_io_time3, factor); | 228 | dasd_statistics_array(m, prof->dasd_io_time3, factor); |
249 | str += sprintf(str, "# of req in chanq at enqueuing (1..32) \n"); | 229 | seq_printf(m, "# of req in chanq at enqueuing (1..32) \n"); |
250 | str = dasd_statistics_array(str, prof->dasd_io_nr_req, factor); | 230 | dasd_statistics_array(m, prof->dasd_io_nr_req, factor); |
251 | len = str - page; | ||
252 | #else | 231 | #else |
253 | len = sprintf(page, "Statistics are not activated in this kernel\n"); | 232 | seq_printf(m, "Statistics are not activated in this kernel\n"); |
254 | #endif | 233 | #endif |
255 | return dasd_calc_metrics(page, start, off, count, eof, len); | 234 | return 0; |
256 | } | 235 | } |
257 | 236 | ||
258 | static int | 237 | static int dasd_stats_proc_open(struct inode *inode, struct file *file) |
259 | dasd_statistics_write(struct file *file, const char __user *user_buf, | 238 | { |
260 | unsigned long user_len, void *data) | 239 | return single_open(file, dasd_stats_proc_show, NULL); |
240 | } | ||
241 | |||
242 | static ssize_t dasd_stats_proc_write(struct file *file, | ||
243 | const char __user *user_buf, size_t user_len, loff_t *pos) | ||
261 | { | 244 | { |
262 | #ifdef CONFIG_DASD_PROFILE | 245 | #ifdef CONFIG_DASD_PROFILE |
263 | char *buffer, *str; | 246 | char *buffer, *str; |
@@ -308,6 +291,15 @@ out_error: | |||
308 | #endif /* CONFIG_DASD_PROFILE */ | 291 | #endif /* CONFIG_DASD_PROFILE */ |
309 | } | 292 | } |
310 | 293 | ||
294 | static const struct file_operations dasd_stats_proc_fops = { | ||
295 | .owner = THIS_MODULE, | ||
296 | .open = dasd_stats_proc_open, | ||
297 | .read = seq_read, | ||
298 | .llseek = seq_lseek, | ||
299 | .release = single_release, | ||
300 | .write = dasd_stats_proc_write, | ||
301 | }; | ||
302 | |||
311 | /* | 303 | /* |
312 | * Create dasd proc-fs entries. | 304 | * Create dasd proc-fs entries. |
313 | * In case creation failed, cleanup and return -ENOENT. | 305 | * In case creation failed, cleanup and return -ENOENT. |
@@ -324,13 +316,12 @@ dasd_proc_init(void) | |||
324 | &dasd_devices_file_ops); | 316 | &dasd_devices_file_ops); |
325 | if (!dasd_devices_entry) | 317 | if (!dasd_devices_entry) |
326 | goto out_nodevices; | 318 | goto out_nodevices; |
327 | dasd_statistics_entry = create_proc_entry("statistics", | 319 | dasd_statistics_entry = proc_create("statistics", |
328 | S_IFREG | S_IRUGO | S_IWUSR, | 320 | S_IFREG | S_IRUGO | S_IWUSR, |
329 | dasd_proc_root_entry); | 321 | dasd_proc_root_entry, |
322 | &dasd_stats_proc_fops); | ||
330 | if (!dasd_statistics_entry) | 323 | if (!dasd_statistics_entry) |
331 | goto out_nostatistics; | 324 | goto out_nostatistics; |
332 | dasd_statistics_entry->read_proc = dasd_statistics_read; | ||
333 | dasd_statistics_entry->write_proc = dasd_statistics_write; | ||
334 | return 0; | 325 | return 0; |
335 | 326 | ||
336 | out_nostatistics: | 327 | out_nostatistics: |
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 82daa3c1dc9c..3438658b66b7 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/miscdevice.h> | 16 | #include <linux/miscdevice.h> |
17 | #include <linux/debugfs.h> | 17 | #include <linux/debugfs.h> |
18 | #include <asm/asm-offsets.h> | ||
18 | #include <asm/ipl.h> | 19 | #include <asm/ipl.h> |
19 | #include <asm/sclp.h> | 20 | #include <asm/sclp.h> |
20 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
@@ -40,12 +41,12 @@ enum arch_id { | |||
40 | /* dump system info */ | 41 | /* dump system info */ |
41 | 42 | ||
42 | struct sys_info { | 43 | struct sys_info { |
43 | enum arch_id arch; | 44 | enum arch_id arch; |
44 | unsigned long sa_base; | 45 | unsigned long sa_base; |
45 | u32 sa_size; | 46 | u32 sa_size; |
46 | int cpu_map[NR_CPUS]; | 47 | int cpu_map[NR_CPUS]; |
47 | unsigned long mem_size; | 48 | unsigned long mem_size; |
48 | union save_area lc_mask; | 49 | struct save_area lc_mask; |
49 | }; | 50 | }; |
50 | 51 | ||
51 | struct ipib_info { | 52 | struct ipib_info { |
@@ -183,52 +184,9 @@ static int memcpy_real_user(void __user *dest, unsigned long src, size_t count) | |||
183 | return 0; | 184 | return 0; |
184 | } | 185 | } |
185 | 186 | ||
186 | #ifdef __s390x__ | ||
187 | /* | ||
188 | * Convert s390x (64 bit) cpu info to s390 (32 bit) cpu info | ||
189 | */ | ||
190 | static void __init s390x_to_s390_regs(union save_area *out, union save_area *in, | ||
191 | int cpu) | ||
192 | { | ||
193 | int i; | ||
194 | |||
195 | for (i = 0; i < 16; i++) { | ||
196 | out->s390.gp_regs[i] = in->s390x.gp_regs[i] & 0x00000000ffffffff; | ||
197 | out->s390.acc_regs[i] = in->s390x.acc_regs[i]; | ||
198 | out->s390.ctrl_regs[i] = | ||
199 | in->s390x.ctrl_regs[i] & 0x00000000ffffffff; | ||
200 | } | ||
201 | /* locore for 31 bit has only space for fpregs 0,2,4,6 */ | ||
202 | out->s390.fp_regs[0] = in->s390x.fp_regs[0]; | ||
203 | out->s390.fp_regs[1] = in->s390x.fp_regs[2]; | ||
204 | out->s390.fp_regs[2] = in->s390x.fp_regs[4]; | ||
205 | out->s390.fp_regs[3] = in->s390x.fp_regs[6]; | ||
206 | memcpy(&(out->s390.psw[0]), &(in->s390x.psw[0]), 4); | ||
207 | out->s390.psw[1] |= 0x8; /* set bit 12 */ | ||
208 | memcpy(&(out->s390.psw[4]),&(in->s390x.psw[12]), 4); | ||
209 | out->s390.psw[4] |= 0x80; /* set (31bit) addressing bit */ | ||
210 | out->s390.pref_reg = in->s390x.pref_reg; | ||
211 | out->s390.timer = in->s390x.timer; | ||
212 | out->s390.clk_cmp = in->s390x.clk_cmp; | ||
213 | } | ||
214 | |||
215 | static void __init s390x_to_s390_save_areas(void) | ||
216 | { | ||
217 | int i = 1; | ||
218 | static union save_area tmp; | ||
219 | |||
220 | while (zfcpdump_save_areas[i]) { | ||
221 | s390x_to_s390_regs(&tmp, zfcpdump_save_areas[i], i); | ||
222 | memcpy(zfcpdump_save_areas[i], &tmp, sizeof(tmp)); | ||
223 | i++; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | #endif /* __s390x__ */ | ||
228 | |||
229 | static int __init init_cpu_info(enum arch_id arch) | 187 | static int __init init_cpu_info(enum arch_id arch) |
230 | { | 188 | { |
231 | union save_area *sa; | 189 | struct save_area *sa; |
232 | 190 | ||
233 | /* get info for boot cpu from lowcore, stored in the HSA */ | 191 | /* get info for boot cpu from lowcore, stored in the HSA */ |
234 | 192 | ||
@@ -241,20 +199,12 @@ static int __init init_cpu_info(enum arch_id arch) | |||
241 | return -EIO; | 199 | return -EIO; |
242 | } | 200 | } |
243 | zfcpdump_save_areas[0] = sa; | 201 | zfcpdump_save_areas[0] = sa; |
244 | |||
245 | #ifdef __s390x__ | ||
246 | /* convert s390x regs to s390, if we are dumping an s390 Linux */ | ||
247 | |||
248 | if (arch == ARCH_S390) | ||
249 | s390x_to_s390_save_areas(); | ||
250 | #endif | ||
251 | |||
252 | return 0; | 202 | return 0; |
253 | } | 203 | } |
254 | 204 | ||
255 | static DEFINE_MUTEX(zcore_mutex); | 205 | static DEFINE_MUTEX(zcore_mutex); |
256 | 206 | ||
257 | #define DUMP_VERSION 0x3 | 207 | #define DUMP_VERSION 0x5 |
258 | #define DUMP_MAGIC 0xa8190173618f23fdULL | 208 | #define DUMP_MAGIC 0xa8190173618f23fdULL |
259 | #define DUMP_ARCH_S390X 2 | 209 | #define DUMP_ARCH_S390X 2 |
260 | #define DUMP_ARCH_S390 1 | 210 | #define DUMP_ARCH_S390 1 |
@@ -279,7 +229,14 @@ struct zcore_header { | |||
279 | u32 volnr; | 229 | u32 volnr; |
280 | u32 build_arch; | 230 | u32 build_arch; |
281 | u64 rmem_size; | 231 | u64 rmem_size; |
282 | char pad2[4016]; | 232 | u8 mvdump; |
233 | u16 cpu_cnt; | ||
234 | u16 real_cpu_cnt; | ||
235 | u8 end_pad1[0x200-0x061]; | ||
236 | u64 mvdump_sign; | ||
237 | u64 mvdump_zipl_time; | ||
238 | u8 end_pad2[0x800-0x210]; | ||
239 | u32 lc_vec[512]; | ||
283 | } __attribute__((packed,__aligned__(16))); | 240 | } __attribute__((packed,__aligned__(16))); |
284 | 241 | ||
285 | static struct zcore_header zcore_header = { | 242 | static struct zcore_header zcore_header = { |
@@ -289,7 +246,7 @@ static struct zcore_header zcore_header = { | |||
289 | .dump_level = 0, | 246 | .dump_level = 0, |
290 | .page_size = PAGE_SIZE, | 247 | .page_size = PAGE_SIZE, |
291 | .mem_start = 0, | 248 | .mem_start = 0, |
292 | #ifdef __s390x__ | 249 | #ifdef CONFIG_64BIT |
293 | .build_arch = DUMP_ARCH_S390X, | 250 | .build_arch = DUMP_ARCH_S390X, |
294 | #else | 251 | #else |
295 | .build_arch = DUMP_ARCH_S390, | 252 | .build_arch = DUMP_ARCH_S390, |
@@ -340,11 +297,7 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) | |||
340 | unsigned long prefix; | 297 | unsigned long prefix; |
341 | unsigned long sa_off, len, buf_off; | 298 | unsigned long sa_off, len, buf_off; |
342 | 299 | ||
343 | if (sys_info.arch == ARCH_S390) | 300 | prefix = zfcpdump_save_areas[i]->pref_reg; |
344 | prefix = zfcpdump_save_areas[i]->s390.pref_reg; | ||
345 | else | ||
346 | prefix = zfcpdump_save_areas[i]->s390x.pref_reg; | ||
347 | |||
348 | sa_start = prefix + sys_info.sa_base; | 301 | sa_start = prefix + sys_info.sa_base; |
349 | sa_end = prefix + sys_info.sa_base + sys_info.sa_size; | 302 | sa_end = prefix + sys_info.sa_base + sys_info.sa_size; |
350 | 303 | ||
@@ -561,34 +514,39 @@ static const struct file_operations zcore_reipl_fops = { | |||
561 | .release = zcore_reipl_release, | 514 | .release = zcore_reipl_release, |
562 | }; | 515 | }; |
563 | 516 | ||
517 | #ifdef CONFIG_32BIT | ||
564 | 518 | ||
565 | static void __init set_s390_lc_mask(union save_area *map) | 519 | static void __init set_lc_mask(struct save_area *map) |
566 | { | 520 | { |
567 | memset(&map->s390.ext_save, 0xff, sizeof(map->s390.ext_save)); | 521 | memset(&map->ext_save, 0xff, sizeof(map->ext_save)); |
568 | memset(&map->s390.timer, 0xff, sizeof(map->s390.timer)); | 522 | memset(&map->timer, 0xff, sizeof(map->timer)); |
569 | memset(&map->s390.clk_cmp, 0xff, sizeof(map->s390.clk_cmp)); | 523 | memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp)); |
570 | memset(&map->s390.psw, 0xff, sizeof(map->s390.psw)); | 524 | memset(&map->psw, 0xff, sizeof(map->psw)); |
571 | memset(&map->s390.pref_reg, 0xff, sizeof(map->s390.pref_reg)); | 525 | memset(&map->pref_reg, 0xff, sizeof(map->pref_reg)); |
572 | memset(&map->s390.acc_regs, 0xff, sizeof(map->s390.acc_regs)); | 526 | memset(&map->acc_regs, 0xff, sizeof(map->acc_regs)); |
573 | memset(&map->s390.fp_regs, 0xff, sizeof(map->s390.fp_regs)); | 527 | memset(&map->fp_regs, 0xff, sizeof(map->fp_regs)); |
574 | memset(&map->s390.gp_regs, 0xff, sizeof(map->s390.gp_regs)); | 528 | memset(&map->gp_regs, 0xff, sizeof(map->gp_regs)); |
575 | memset(&map->s390.ctrl_regs, 0xff, sizeof(map->s390.ctrl_regs)); | 529 | memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs)); |
576 | } | 530 | } |
577 | 531 | ||
578 | static void __init set_s390x_lc_mask(union save_area *map) | 532 | #else /* CONFIG_32BIT */ |
533 | |||
534 | static void __init set_lc_mask(struct save_area *map) | ||
579 | { | 535 | { |
580 | memset(&map->s390x.fp_regs, 0xff, sizeof(map->s390x.fp_regs)); | 536 | memset(&map->fp_regs, 0xff, sizeof(map->fp_regs)); |
581 | memset(&map->s390x.gp_regs, 0xff, sizeof(map->s390x.gp_regs)); | 537 | memset(&map->gp_regs, 0xff, sizeof(map->gp_regs)); |
582 | memset(&map->s390x.psw, 0xff, sizeof(map->s390x.psw)); | 538 | memset(&map->psw, 0xff, sizeof(map->psw)); |
583 | memset(&map->s390x.pref_reg, 0xff, sizeof(map->s390x.pref_reg)); | 539 | memset(&map->pref_reg, 0xff, sizeof(map->pref_reg)); |
584 | memset(&map->s390x.fp_ctrl_reg, 0xff, sizeof(map->s390x.fp_ctrl_reg)); | 540 | memset(&map->fp_ctrl_reg, 0xff, sizeof(map->fp_ctrl_reg)); |
585 | memset(&map->s390x.tod_reg, 0xff, sizeof(map->s390x.tod_reg)); | 541 | memset(&map->tod_reg, 0xff, sizeof(map->tod_reg)); |
586 | memset(&map->s390x.timer, 0xff, sizeof(map->s390x.timer)); | 542 | memset(&map->timer, 0xff, sizeof(map->timer)); |
587 | memset(&map->s390x.clk_cmp, 0xff, sizeof(map->s390x.clk_cmp)); | 543 | memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp)); |
588 | memset(&map->s390x.acc_regs, 0xff, sizeof(map->s390x.acc_regs)); | 544 | memset(&map->acc_regs, 0xff, sizeof(map->acc_regs)); |
589 | memset(&map->s390x.ctrl_regs, 0xff, sizeof(map->s390x.ctrl_regs)); | 545 | memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs)); |
590 | } | 546 | } |
591 | 547 | ||
548 | #endif /* CONFIG_32BIT */ | ||
549 | |||
592 | /* | 550 | /* |
593 | * Initialize dump globals for a given architecture | 551 | * Initialize dump globals for a given architecture |
594 | */ | 552 | */ |
@@ -599,21 +557,18 @@ static int __init sys_info_init(enum arch_id arch) | |||
599 | switch (arch) { | 557 | switch (arch) { |
600 | case ARCH_S390X: | 558 | case ARCH_S390X: |
601 | pr_alert("DETECTED 'S390X (64 bit) OS'\n"); | 559 | pr_alert("DETECTED 'S390X (64 bit) OS'\n"); |
602 | sys_info.sa_base = SAVE_AREA_BASE_S390X; | ||
603 | sys_info.sa_size = sizeof(struct save_area_s390x); | ||
604 | set_s390x_lc_mask(&sys_info.lc_mask); | ||
605 | break; | 560 | break; |
606 | case ARCH_S390: | 561 | case ARCH_S390: |
607 | pr_alert("DETECTED 'S390 (32 bit) OS'\n"); | 562 | pr_alert("DETECTED 'S390 (32 bit) OS'\n"); |
608 | sys_info.sa_base = SAVE_AREA_BASE_S390; | ||
609 | sys_info.sa_size = sizeof(struct save_area_s390); | ||
610 | set_s390_lc_mask(&sys_info.lc_mask); | ||
611 | break; | 563 | break; |
612 | default: | 564 | default: |
613 | pr_alert("0x%x is an unknown architecture.\n",arch); | 565 | pr_alert("0x%x is an unknown architecture.\n",arch); |
614 | return -EINVAL; | 566 | return -EINVAL; |
615 | } | 567 | } |
568 | sys_info.sa_base = SAVE_AREA_BASE; | ||
569 | sys_info.sa_size = sizeof(struct save_area); | ||
616 | sys_info.arch = arch; | 570 | sys_info.arch = arch; |
571 | set_lc_mask(&sys_info.lc_mask); | ||
617 | rc = init_cpu_info(arch); | 572 | rc = init_cpu_info(arch); |
618 | if (rc) | 573 | if (rc) |
619 | return rc; | 574 | return rc; |
@@ -660,8 +615,9 @@ static int __init get_mem_size(unsigned long *mem) | |||
660 | 615 | ||
661 | static int __init zcore_header_init(int arch, struct zcore_header *hdr) | 616 | static int __init zcore_header_init(int arch, struct zcore_header *hdr) |
662 | { | 617 | { |
663 | int rc; | 618 | int rc, i; |
664 | unsigned long memory = 0; | 619 | unsigned long memory = 0; |
620 | u32 prefix; | ||
665 | 621 | ||
666 | if (arch == ARCH_S390X) | 622 | if (arch == ARCH_S390X) |
667 | hdr->arch_id = DUMP_ARCH_S390X; | 623 | hdr->arch_id = DUMP_ARCH_S390X; |
@@ -676,6 +632,14 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr) | |||
676 | hdr->num_pages = memory / PAGE_SIZE; | 632 | hdr->num_pages = memory / PAGE_SIZE; |
677 | hdr->tod = get_clock(); | 633 | hdr->tod = get_clock(); |
678 | get_cpu_id(&hdr->cpu_id); | 634 | get_cpu_id(&hdr->cpu_id); |
635 | for (i = 0; zfcpdump_save_areas[i]; i++) { | ||
636 | prefix = zfcpdump_save_areas[i]->pref_reg; | ||
637 | hdr->real_cpu_cnt++; | ||
638 | if (!prefix) | ||
639 | continue; | ||
640 | hdr->lc_vec[hdr->cpu_cnt] = prefix; | ||
641 | hdr->cpu_cnt++; | ||
642 | } | ||
679 | return 0; | 643 | return 0; |
680 | } | 644 | } |
681 | 645 | ||
@@ -741,14 +705,21 @@ static int __init zcore_init(void) | |||
741 | if (rc) | 705 | if (rc) |
742 | goto fail; | 706 | goto fail; |
743 | 707 | ||
744 | #ifndef __s390x__ | 708 | #ifdef CONFIG_64BIT |
709 | if (arch == ARCH_S390) { | ||
710 | pr_alert("The 64-bit dump tool cannot be used for a " | ||
711 | "32-bit system\n"); | ||
712 | rc = -EINVAL; | ||
713 | goto fail; | ||
714 | } | ||
715 | #else /* CONFIG_64BIT */ | ||
745 | if (arch == ARCH_S390X) { | 716 | if (arch == ARCH_S390X) { |
746 | pr_alert("The 32-bit dump tool cannot be used for a " | 717 | pr_alert("The 32-bit dump tool cannot be used for a " |
747 | "64-bit system\n"); | 718 | "64-bit system\n"); |
748 | rc = -EINVAL; | 719 | rc = -EINVAL; |
749 | goto fail; | 720 | goto fail; |
750 | } | 721 | } |
751 | #endif | 722 | #endif /* CONFIG_64BIT */ |
752 | 723 | ||
753 | rc = sys_info_init(arch); | 724 | rc = sys_info_init(arch); |
754 | if (rc) | 725 | if (rc) |
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c index 7a28a3029a3f..37df42af05ec 100644 --- a/drivers/s390/cio/ccwreq.c +++ b/drivers/s390/cio/ccwreq.c | |||
@@ -224,8 +224,8 @@ static void ccwreq_log_status(struct ccw_device *cdev, enum io_status status) | |||
224 | */ | 224 | */ |
225 | void ccw_request_handler(struct ccw_device *cdev) | 225 | void ccw_request_handler(struct ccw_device *cdev) |
226 | { | 226 | { |
227 | struct irb *irb = (struct irb *)&S390_lowcore.irb; | ||
227 | struct ccw_request *req = &cdev->private->req; | 228 | struct ccw_request *req = &cdev->private->req; |
228 | struct irb *irb = (struct irb *) __LC_IRB; | ||
229 | enum io_status status; | 229 | enum io_status status; |
230 | int rc = -EOPNOTSUPP; | 230 | int rc = -EOPNOTSUPP; |
231 | 231 | ||
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 1ecd3e567648..4038f5b4f144 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -574,7 +574,7 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable, void *page) | |||
574 | secm_area->request.length = 0x0050; | 574 | secm_area->request.length = 0x0050; |
575 | secm_area->request.code = 0x0016; | 575 | secm_area->request.code = 0x0016; |
576 | 576 | ||
577 | secm_area->key = PAGE_DEFAULT_KEY; | 577 | secm_area->key = PAGE_DEFAULT_KEY >> 4; |
578 | secm_area->cub_addr1 = (u64)(unsigned long)css->cub_addr1; | 578 | secm_area->cub_addr1 = (u64)(unsigned long)css->cub_addr1; |
579 | secm_area->cub_addr2 = (u64)(unsigned long)css->cub_addr2; | 579 | secm_area->cub_addr2 = (u64)(unsigned long)css->cub_addr2; |
580 | 580 | ||
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index c84ac9443079..852612f5dba0 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c | |||
@@ -51,7 +51,7 @@ static void chsc_subchannel_irq(struct subchannel *sch) | |||
51 | { | 51 | { |
52 | struct chsc_private *private = sch->private; | 52 | struct chsc_private *private = sch->private; |
53 | struct chsc_request *request = private->request; | 53 | struct chsc_request *request = private->request; |
54 | struct irb *irb = (struct irb *)__LC_IRB; | 54 | struct irb *irb = (struct irb *)&S390_lowcore.irb; |
55 | 55 | ||
56 | CHSC_LOG(4, "irb"); | 56 | CHSC_LOG(4, "irb"); |
57 | CHSC_LOG_HEX(4, irb, sizeof(*irb)); | 57 | CHSC_LOG_HEX(4, irb, sizeof(*irb)); |
@@ -237,7 +237,7 @@ static int chsc_async(struct chsc_async_area *chsc_area, | |||
237 | int ret = -ENODEV; | 237 | int ret = -ENODEV; |
238 | char dbf[10]; | 238 | char dbf[10]; |
239 | 239 | ||
240 | chsc_area->header.key = PAGE_DEFAULT_KEY; | 240 | chsc_area->header.key = PAGE_DEFAULT_KEY >> 4; |
241 | while ((sch = chsc_get_next_subchannel(sch))) { | 241 | while ((sch = chsc_get_next_subchannel(sch))) { |
242 | spin_lock(sch->lock); | 242 | spin_lock(sch->lock); |
243 | private = sch->private; | 243 | private = sch->private; |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 126f240715a4..f736cdcf08ad 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -625,8 +625,8 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
625 | /* | 625 | /* |
626 | * Get interrupt information from lowcore | 626 | * Get interrupt information from lowcore |
627 | */ | 627 | */ |
628 | tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID; | 628 | tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; |
629 | irb = (struct irb *) __LC_IRB; | 629 | irb = (struct irb *)&S390_lowcore.irb; |
630 | do { | 630 | do { |
631 | kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; | 631 | kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; |
632 | /* | 632 | /* |
@@ -661,7 +661,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
661 | * We don't do this for VM because a tpi drops the cpu | 661 | * We don't do this for VM because a tpi drops the cpu |
662 | * out of the sie which costs more cycles than it saves. | 662 | * out of the sie which costs more cycles than it saves. |
663 | */ | 663 | */ |
664 | } while (!MACHINE_IS_VM && tpi (NULL) != 0); | 664 | } while (MACHINE_IS_LPAR && tpi(NULL) != 0); |
665 | irq_exit(); | 665 | irq_exit(); |
666 | set_irq_regs(old_regs); | 666 | set_irq_regs(old_regs); |
667 | } | 667 | } |
@@ -682,10 +682,10 @@ static int cio_tpi(void) | |||
682 | struct irb *irb; | 682 | struct irb *irb; |
683 | int irq_context; | 683 | int irq_context; |
684 | 684 | ||
685 | tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID; | 685 | tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; |
686 | if (tpi(NULL) != 1) | 686 | if (tpi(NULL) != 1) |
687 | return 0; | 687 | return 0; |
688 | irb = (struct irb *) __LC_IRB; | 688 | irb = (struct irb *)&S390_lowcore.irb; |
689 | /* Store interrupt response block to lowcore. */ | 689 | /* Store interrupt response block to lowcore. */ |
690 | if (tsch(tpi_info->schid, irb) != 0) | 690 | if (tsch(tpi_info->schid, irb) != 0) |
691 | /* Not status pending or not operational. */ | 691 | /* Not status pending or not operational. */ |
@@ -885,7 +885,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid) | |||
885 | struct tpi_info ti; | 885 | struct tpi_info ti; |
886 | 886 | ||
887 | if (tpi(&ti)) { | 887 | if (tpi(&ti)) { |
888 | tsch(ti.schid, (struct irb *)__LC_IRB); | 888 | tsch(ti.schid, (struct irb *)&S390_lowcore.irb); |
889 | if (schid_equal(&ti.schid, &schid)) | 889 | if (schid_equal(&ti.schid, &schid)) |
890 | return 0; | 890 | return 0; |
891 | } | 891 | } |
@@ -1083,7 +1083,7 @@ int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo) | |||
1083 | struct subchannel_id schid; | 1083 | struct subchannel_id schid; |
1084 | struct schib schib; | 1084 | struct schib schib; |
1085 | 1085 | ||
1086 | schid = *(struct subchannel_id *)__LC_SUBCHANNEL_ID; | 1086 | schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id; |
1087 | if (!schid.one) | 1087 | if (!schid.one) |
1088 | return -ENODEV; | 1088 | return -ENODEV; |
1089 | if (stsch(schid, &schib)) | 1089 | if (stsch(schid, &schib)) |
diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c index d157665d0e76..425f741a280c 100644 --- a/drivers/s390/cio/crw.c +++ b/drivers/s390/cio/crw.c | |||
@@ -8,15 +8,16 @@ | |||
8 | * Heiko Carstens <heiko.carstens@de.ibm.com>, | 8 | * Heiko Carstens <heiko.carstens@de.ibm.com>, |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/semaphore.h> | ||
12 | #include <linux/mutex.h> | 11 | #include <linux/mutex.h> |
13 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
14 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/wait.h> | ||
15 | #include <asm/crw.h> | 15 | #include <asm/crw.h> |
16 | 16 | ||
17 | static struct semaphore crw_semaphore; | ||
18 | static DEFINE_MUTEX(crw_handler_mutex); | 17 | static DEFINE_MUTEX(crw_handler_mutex); |
19 | static crw_handler_t crw_handlers[NR_RSCS]; | 18 | static crw_handler_t crw_handlers[NR_RSCS]; |
19 | static atomic_t crw_nr_req = ATOMIC_INIT(0); | ||
20 | static DECLARE_WAIT_QUEUE_HEAD(crw_handler_wait_q); | ||
20 | 21 | ||
21 | /** | 22 | /** |
22 | * crw_register_handler() - register a channel report word handler | 23 | * crw_register_handler() - register a channel report word handler |
@@ -59,12 +60,14 @@ void crw_unregister_handler(int rsc) | |||
59 | static int crw_collect_info(void *unused) | 60 | static int crw_collect_info(void *unused) |
60 | { | 61 | { |
61 | struct crw crw[2]; | 62 | struct crw crw[2]; |
62 | int ccode; | 63 | int ccode, signal; |
63 | unsigned int chain; | 64 | unsigned int chain; |
64 | int ignore; | ||
65 | 65 | ||
66 | repeat: | 66 | repeat: |
67 | ignore = down_interruptible(&crw_semaphore); | 67 | signal = wait_event_interruptible(crw_handler_wait_q, |
68 | atomic_read(&crw_nr_req) > 0); | ||
69 | if (unlikely(signal)) | ||
70 | atomic_inc(&crw_nr_req); | ||
68 | chain = 0; | 71 | chain = 0; |
69 | while (1) { | 72 | while (1) { |
70 | crw_handler_t handler; | 73 | crw_handler_t handler; |
@@ -122,25 +125,23 @@ repeat: | |||
122 | /* chain is always 0 or 1 here. */ | 125 | /* chain is always 0 or 1 here. */ |
123 | chain = crw[chain].chn ? chain + 1 : 0; | 126 | chain = crw[chain].chn ? chain + 1 : 0; |
124 | } | 127 | } |
128 | if (atomic_dec_and_test(&crw_nr_req)) | ||
129 | wake_up(&crw_handler_wait_q); | ||
125 | goto repeat; | 130 | goto repeat; |
126 | return 0; | 131 | return 0; |
127 | } | 132 | } |
128 | 133 | ||
129 | void crw_handle_channel_report(void) | 134 | void crw_handle_channel_report(void) |
130 | { | 135 | { |
131 | up(&crw_semaphore); | 136 | atomic_inc(&crw_nr_req); |
137 | wake_up(&crw_handler_wait_q); | ||
132 | } | 138 | } |
133 | 139 | ||
134 | /* | 140 | void crw_wait_for_channel_report(void) |
135 | * Separate initcall needed for semaphore initialization since | ||
136 | * crw_handle_channel_report might be called before crw_machine_check_init. | ||
137 | */ | ||
138 | static int __init crw_init_semaphore(void) | ||
139 | { | 141 | { |
140 | init_MUTEX_LOCKED(&crw_semaphore); | 142 | crw_handle_channel_report(); |
141 | return 0; | 143 | wait_event(crw_handler_wait_q, atomic_read(&crw_nr_req) == 0); |
142 | } | 144 | } |
143 | pure_initcall(crw_init_semaphore); | ||
144 | 145 | ||
145 | /* | 146 | /* |
146 | * Machine checks for the channel subsystem must be enabled | 147 | * Machine checks for the channel subsystem must be enabled |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 7679aee6fa14..2769da54f2b9 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/reboot.h> | 19 | #include <linux/reboot.h> |
20 | #include <linux/suspend.h> | 20 | #include <linux/suspend.h> |
21 | #include <linux/proc_fs.h> | ||
21 | #include <asm/isc.h> | 22 | #include <asm/isc.h> |
22 | #include <asm/crw.h> | 23 | #include <asm/crw.h> |
23 | 24 | ||
@@ -232,7 +233,7 @@ void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo) | |||
232 | if (!get_device(&sch->dev)) | 233 | if (!get_device(&sch->dev)) |
233 | return; | 234 | return; |
234 | sch->todo = todo; | 235 | sch->todo = todo; |
235 | if (!queue_work(slow_path_wq, &sch->todo_work)) { | 236 | if (!queue_work(cio_work_q, &sch->todo_work)) { |
236 | /* Already queued, release workqueue ref. */ | 237 | /* Already queued, release workqueue ref. */ |
237 | put_device(&sch->dev); | 238 | put_device(&sch->dev); |
238 | } | 239 | } |
@@ -543,7 +544,7 @@ static void css_slow_path_func(struct work_struct *unused) | |||
543 | } | 544 | } |
544 | 545 | ||
545 | static DECLARE_WORK(slow_path_work, css_slow_path_func); | 546 | static DECLARE_WORK(slow_path_work, css_slow_path_func); |
546 | struct workqueue_struct *slow_path_wq; | 547 | struct workqueue_struct *cio_work_q; |
547 | 548 | ||
548 | void css_schedule_eval(struct subchannel_id schid) | 549 | void css_schedule_eval(struct subchannel_id schid) |
549 | { | 550 | { |
@@ -552,7 +553,7 @@ void css_schedule_eval(struct subchannel_id schid) | |||
552 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 553 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
553 | idset_sch_add(slow_subchannel_set, schid); | 554 | idset_sch_add(slow_subchannel_set, schid); |
554 | atomic_set(&css_eval_scheduled, 1); | 555 | atomic_set(&css_eval_scheduled, 1); |
555 | queue_work(slow_path_wq, &slow_path_work); | 556 | queue_work(cio_work_q, &slow_path_work); |
556 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 557 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
557 | } | 558 | } |
558 | 559 | ||
@@ -563,7 +564,7 @@ void css_schedule_eval_all(void) | |||
563 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 564 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
564 | idset_fill(slow_subchannel_set); | 565 | idset_fill(slow_subchannel_set); |
565 | atomic_set(&css_eval_scheduled, 1); | 566 | atomic_set(&css_eval_scheduled, 1); |
566 | queue_work(slow_path_wq, &slow_path_work); | 567 | queue_work(cio_work_q, &slow_path_work); |
567 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 568 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
568 | } | 569 | } |
569 | 570 | ||
@@ -594,14 +595,14 @@ void css_schedule_eval_all_unreg(void) | |||
594 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 595 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
595 | idset_add_set(slow_subchannel_set, unreg_set); | 596 | idset_add_set(slow_subchannel_set, unreg_set); |
596 | atomic_set(&css_eval_scheduled, 1); | 597 | atomic_set(&css_eval_scheduled, 1); |
597 | queue_work(slow_path_wq, &slow_path_work); | 598 | queue_work(cio_work_q, &slow_path_work); |
598 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 599 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
599 | idset_free(unreg_set); | 600 | idset_free(unreg_set); |
600 | } | 601 | } |
601 | 602 | ||
602 | void css_wait_for_slow_path(void) | 603 | void css_wait_for_slow_path(void) |
603 | { | 604 | { |
604 | flush_workqueue(slow_path_wq); | 605 | flush_workqueue(cio_work_q); |
605 | } | 606 | } |
606 | 607 | ||
607 | /* Schedule reprobing of all unregistered subchannels. */ | 608 | /* Schedule reprobing of all unregistered subchannels. */ |
@@ -992,12 +993,21 @@ static int __init channel_subsystem_init(void) | |||
992 | ret = css_bus_init(); | 993 | ret = css_bus_init(); |
993 | if (ret) | 994 | if (ret) |
994 | return ret; | 995 | return ret; |
995 | 996 | cio_work_q = create_singlethread_workqueue("cio"); | |
997 | if (!cio_work_q) { | ||
998 | ret = -ENOMEM; | ||
999 | goto out_bus; | ||
1000 | } | ||
996 | ret = io_subchannel_init(); | 1001 | ret = io_subchannel_init(); |
997 | if (ret) | 1002 | if (ret) |
998 | css_bus_cleanup(); | 1003 | goto out_wq; |
999 | 1004 | ||
1000 | return ret; | 1005 | return ret; |
1006 | out_wq: | ||
1007 | destroy_workqueue(cio_work_q); | ||
1008 | out_bus: | ||
1009 | css_bus_cleanup(); | ||
1010 | return ret; | ||
1001 | } | 1011 | } |
1002 | subsys_initcall(channel_subsystem_init); | 1012 | subsys_initcall(channel_subsystem_init); |
1003 | 1013 | ||
@@ -1006,10 +1016,25 @@ static int css_settle(struct device_driver *drv, void *unused) | |||
1006 | struct css_driver *cssdrv = to_cssdriver(drv); | 1016 | struct css_driver *cssdrv = to_cssdriver(drv); |
1007 | 1017 | ||
1008 | if (cssdrv->settle) | 1018 | if (cssdrv->settle) |
1009 | cssdrv->settle(); | 1019 | return cssdrv->settle(); |
1010 | return 0; | 1020 | return 0; |
1011 | } | 1021 | } |
1012 | 1022 | ||
1023 | int css_complete_work(void) | ||
1024 | { | ||
1025 | int ret; | ||
1026 | |||
1027 | /* Wait for the evaluation of subchannels to finish. */ | ||
1028 | ret = wait_event_interruptible(css_eval_wq, | ||
1029 | atomic_read(&css_eval_scheduled) == 0); | ||
1030 | if (ret) | ||
1031 | return -EINTR; | ||
1032 | flush_workqueue(cio_work_q); | ||
1033 | /* Wait for the subchannel type specific initialization to finish */ | ||
1034 | return bus_for_each_drv(&css_bus_type, NULL, NULL, css_settle); | ||
1035 | } | ||
1036 | |||
1037 | |||
1013 | /* | 1038 | /* |
1014 | * Wait for the initialization of devices to finish, to make sure we are | 1039 | * Wait for the initialization of devices to finish, to make sure we are |
1015 | * done with our setup if the search for the root device starts. | 1040 | * done with our setup if the search for the root device starts. |
@@ -1018,13 +1043,41 @@ static int __init channel_subsystem_init_sync(void) | |||
1018 | { | 1043 | { |
1019 | /* Start initial subchannel evaluation. */ | 1044 | /* Start initial subchannel evaluation. */ |
1020 | css_schedule_eval_all(); | 1045 | css_schedule_eval_all(); |
1021 | /* Wait for the evaluation of subchannels to finish. */ | 1046 | css_complete_work(); |
1022 | wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0); | 1047 | return 0; |
1023 | /* Wait for the subchannel type specific initialization to finish */ | ||
1024 | return bus_for_each_drv(&css_bus_type, NULL, NULL, css_settle); | ||
1025 | } | 1048 | } |
1026 | subsys_initcall_sync(channel_subsystem_init_sync); | 1049 | subsys_initcall_sync(channel_subsystem_init_sync); |
1027 | 1050 | ||
1051 | #ifdef CONFIG_PROC_FS | ||
1052 | static ssize_t cio_settle_write(struct file *file, const char __user *buf, | ||
1053 | size_t count, loff_t *ppos) | ||
1054 | { | ||
1055 | int ret; | ||
1056 | |||
1057 | /* Handle pending CRW's. */ | ||
1058 | crw_wait_for_channel_report(); | ||
1059 | ret = css_complete_work(); | ||
1060 | |||
1061 | return ret ? ret : count; | ||
1062 | } | ||
1063 | |||
1064 | static const struct file_operations cio_settle_proc_fops = { | ||
1065 | .write = cio_settle_write, | ||
1066 | }; | ||
1067 | |||
1068 | static int __init cio_settle_init(void) | ||
1069 | { | ||
1070 | struct proc_dir_entry *entry; | ||
1071 | |||
1072 | entry = proc_create("cio_settle", S_IWUSR, NULL, | ||
1073 | &cio_settle_proc_fops); | ||
1074 | if (!entry) | ||
1075 | return -ENOMEM; | ||
1076 | return 0; | ||
1077 | } | ||
1078 | device_initcall(cio_settle_init); | ||
1079 | #endif /*CONFIG_PROC_FS*/ | ||
1080 | |||
1028 | int sch_is_pseudo_sch(struct subchannel *sch) | 1081 | int sch_is_pseudo_sch(struct subchannel *sch) |
1029 | { | 1082 | { |
1030 | return sch == to_css(sch->dev.parent)->pseudo_subchannel; | 1083 | return sch == to_css(sch->dev.parent)->pseudo_subchannel; |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index fe84b92cde60..7e37886de231 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -95,7 +95,7 @@ struct css_driver { | |||
95 | int (*freeze)(struct subchannel *); | 95 | int (*freeze)(struct subchannel *); |
96 | int (*thaw) (struct subchannel *); | 96 | int (*thaw) (struct subchannel *); |
97 | int (*restore)(struct subchannel *); | 97 | int (*restore)(struct subchannel *); |
98 | void (*settle)(void); | 98 | int (*settle)(void); |
99 | const char *name; | 99 | const char *name; |
100 | }; | 100 | }; |
101 | 101 | ||
@@ -146,12 +146,13 @@ extern struct channel_subsystem *channel_subsystems[]; | |||
146 | /* Helper functions to build lists for the slow path. */ | 146 | /* Helper functions to build lists for the slow path. */ |
147 | void css_schedule_eval(struct subchannel_id schid); | 147 | void css_schedule_eval(struct subchannel_id schid); |
148 | void css_schedule_eval_all(void); | 148 | void css_schedule_eval_all(void); |
149 | int css_complete_work(void); | ||
149 | 150 | ||
150 | int sch_is_pseudo_sch(struct subchannel *); | 151 | int sch_is_pseudo_sch(struct subchannel *); |
151 | struct schib; | 152 | struct schib; |
152 | int css_sch_is_valid(struct schib *); | 153 | int css_sch_is_valid(struct schib *); |
153 | 154 | ||
154 | extern struct workqueue_struct *slow_path_wq; | 155 | extern struct workqueue_struct *cio_work_q; |
155 | void css_wait_for_slow_path(void); | 156 | void css_wait_for_slow_path(void); |
156 | void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo); | 157 | void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo); |
157 | #endif | 158 | #endif |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index a6c7d5426fb2..c6abb75c4615 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -136,7 +136,6 @@ static int io_subchannel_sch_event(struct subchannel *, int); | |||
136 | static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, | 136 | static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, |
137 | int); | 137 | int); |
138 | static void recovery_func(unsigned long data); | 138 | static void recovery_func(unsigned long data); |
139 | struct workqueue_struct *ccw_device_work; | ||
140 | wait_queue_head_t ccw_device_init_wq; | 139 | wait_queue_head_t ccw_device_init_wq; |
141 | atomic_t ccw_device_init_count; | 140 | atomic_t ccw_device_init_count; |
142 | 141 | ||
@@ -159,11 +158,16 @@ static int io_subchannel_prepare(struct subchannel *sch) | |||
159 | return 0; | 158 | return 0; |
160 | } | 159 | } |
161 | 160 | ||
162 | static void io_subchannel_settle(void) | 161 | static int io_subchannel_settle(void) |
163 | { | 162 | { |
164 | wait_event(ccw_device_init_wq, | 163 | int ret; |
165 | atomic_read(&ccw_device_init_count) == 0); | 164 | |
166 | flush_workqueue(ccw_device_work); | 165 | ret = wait_event_interruptible(ccw_device_init_wq, |
166 | atomic_read(&ccw_device_init_count) == 0); | ||
167 | if (ret) | ||
168 | return -EINTR; | ||
169 | flush_workqueue(cio_work_q); | ||
170 | return 0; | ||
167 | } | 171 | } |
168 | 172 | ||
169 | static struct css_driver io_subchannel_driver = { | 173 | static struct css_driver io_subchannel_driver = { |
@@ -188,27 +192,13 @@ int __init io_subchannel_init(void) | |||
188 | atomic_set(&ccw_device_init_count, 0); | 192 | atomic_set(&ccw_device_init_count, 0); |
189 | setup_timer(&recovery_timer, recovery_func, 0); | 193 | setup_timer(&recovery_timer, recovery_func, 0); |
190 | 194 | ||
191 | ccw_device_work = create_singlethread_workqueue("cio"); | 195 | ret = bus_register(&ccw_bus_type); |
192 | if (!ccw_device_work) | 196 | if (ret) |
193 | return -ENOMEM; | 197 | return ret; |
194 | slow_path_wq = create_singlethread_workqueue("kslowcrw"); | ||
195 | if (!slow_path_wq) { | ||
196 | ret = -ENOMEM; | ||
197 | goto out_err; | ||
198 | } | ||
199 | if ((ret = bus_register (&ccw_bus_type))) | ||
200 | goto out_err; | ||
201 | |||
202 | ret = css_driver_register(&io_subchannel_driver); | 198 | ret = css_driver_register(&io_subchannel_driver); |
203 | if (ret) | 199 | if (ret) |
204 | goto out_err; | 200 | bus_unregister(&ccw_bus_type); |
205 | 201 | ||
206 | return 0; | ||
207 | out_err: | ||
208 | if (ccw_device_work) | ||
209 | destroy_workqueue(ccw_device_work); | ||
210 | if (slow_path_wq) | ||
211 | destroy_workqueue(slow_path_wq); | ||
212 | return ret; | 202 | return ret; |
213 | } | 203 | } |
214 | 204 | ||
@@ -1348,7 +1338,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) | |||
1348 | /* Not operational. */ | 1338 | /* Not operational. */ |
1349 | if (!cdev) | 1339 | if (!cdev) |
1350 | return IO_SCH_UNREG; | 1340 | return IO_SCH_UNREG; |
1351 | if (!ccw_device_notify(cdev, CIO_GONE)) | 1341 | if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) |
1352 | return IO_SCH_UNREG; | 1342 | return IO_SCH_UNREG; |
1353 | return IO_SCH_ORPH_UNREG; | 1343 | return IO_SCH_ORPH_UNREG; |
1354 | } | 1344 | } |
@@ -1356,12 +1346,12 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) | |||
1356 | if (!cdev) | 1346 | if (!cdev) |
1357 | return IO_SCH_ATTACH; | 1347 | return IO_SCH_ATTACH; |
1358 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { | 1348 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { |
1359 | if (!ccw_device_notify(cdev, CIO_GONE)) | 1349 | if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) |
1360 | return IO_SCH_UNREG_ATTACH; | 1350 | return IO_SCH_UNREG_ATTACH; |
1361 | return IO_SCH_ORPH_ATTACH; | 1351 | return IO_SCH_ORPH_ATTACH; |
1362 | } | 1352 | } |
1363 | if ((sch->schib.pmcw.pam & sch->opm) == 0) { | 1353 | if ((sch->schib.pmcw.pam & sch->opm) == 0) { |
1364 | if (!ccw_device_notify(cdev, CIO_NO_PATH)) | 1354 | if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) |
1365 | return IO_SCH_UNREG; | 1355 | return IO_SCH_UNREG; |
1366 | return IO_SCH_DISC; | 1356 | return IO_SCH_DISC; |
1367 | } | 1357 | } |
@@ -1410,6 +1400,12 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) | |||
1410 | rc = 0; | 1400 | rc = 0; |
1411 | goto out_unlock; | 1401 | goto out_unlock; |
1412 | case IO_SCH_VERIFY: | 1402 | case IO_SCH_VERIFY: |
1403 | if (cdev->private->flags.resuming == 1) { | ||
1404 | if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) { | ||
1405 | ccw_device_set_notoper(cdev); | ||
1406 | break; | ||
1407 | } | ||
1408 | } | ||
1413 | /* Trigger path verification. */ | 1409 | /* Trigger path verification. */ |
1414 | io_subchannel_verify(sch); | 1410 | io_subchannel_verify(sch); |
1415 | rc = 0; | 1411 | rc = 0; |
@@ -1448,7 +1444,8 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) | |||
1448 | break; | 1444 | break; |
1449 | case IO_SCH_UNREG_ATTACH: | 1445 | case IO_SCH_UNREG_ATTACH: |
1450 | /* Unregister ccw device. */ | 1446 | /* Unregister ccw device. */ |
1451 | ccw_device_unregister(cdev); | 1447 | if (!cdev->private->flags.resuming) |
1448 | ccw_device_unregister(cdev); | ||
1452 | break; | 1449 | break; |
1453 | default: | 1450 | default: |
1454 | break; | 1451 | break; |
@@ -1457,7 +1454,8 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) | |||
1457 | switch (action) { | 1454 | switch (action) { |
1458 | case IO_SCH_ORPH_UNREG: | 1455 | case IO_SCH_ORPH_UNREG: |
1459 | case IO_SCH_UNREG: | 1456 | case IO_SCH_UNREG: |
1460 | css_sch_device_unregister(sch); | 1457 | if (!cdev || !cdev->private->flags.resuming) |
1458 | css_sch_device_unregister(sch); | ||
1461 | break; | 1459 | break; |
1462 | case IO_SCH_ORPH_ATTACH: | 1460 | case IO_SCH_ORPH_ATTACH: |
1463 | case IO_SCH_UNREG_ATTACH: | 1461 | case IO_SCH_UNREG_ATTACH: |
@@ -1779,26 +1777,42 @@ static void __ccw_device_pm_restore(struct ccw_device *cdev) | |||
1779 | { | 1777 | { |
1780 | struct subchannel *sch = to_subchannel(cdev->dev.parent); | 1778 | struct subchannel *sch = to_subchannel(cdev->dev.parent); |
1781 | 1779 | ||
1782 | if (cio_is_console(sch->schid)) | 1780 | spin_lock_irq(sch->lock); |
1783 | goto out; | 1781 | if (cio_is_console(sch->schid)) { |
1782 | cio_enable_subchannel(sch, (u32)(addr_t)sch); | ||
1783 | goto out_unlock; | ||
1784 | } | ||
1784 | /* | 1785 | /* |
1785 | * While we were sleeping, devices may have gone or become | 1786 | * While we were sleeping, devices may have gone or become |
1786 | * available again. Kick re-detection. | 1787 | * available again. Kick re-detection. |
1787 | */ | 1788 | */ |
1788 | spin_lock_irq(sch->lock); | ||
1789 | cdev->private->flags.resuming = 1; | 1789 | cdev->private->flags.resuming = 1; |
1790 | css_schedule_eval(sch->schid); | ||
1791 | spin_unlock_irq(sch->lock); | ||
1792 | css_complete_work(); | ||
1793 | |||
1794 | /* cdev may have been moved to a different subchannel. */ | ||
1795 | sch = to_subchannel(cdev->dev.parent); | ||
1796 | spin_lock_irq(sch->lock); | ||
1797 | if (cdev->private->state != DEV_STATE_ONLINE && | ||
1798 | cdev->private->state != DEV_STATE_OFFLINE) | ||
1799 | goto out_unlock; | ||
1800 | |||
1790 | ccw_device_recognition(cdev); | 1801 | ccw_device_recognition(cdev); |
1791 | spin_unlock_irq(sch->lock); | 1802 | spin_unlock_irq(sch->lock); |
1792 | wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev) || | 1803 | wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev) || |
1793 | cdev->private->state == DEV_STATE_DISCONNECTED); | 1804 | cdev->private->state == DEV_STATE_DISCONNECTED); |
1794 | out: | 1805 | spin_lock_irq(sch->lock); |
1806 | |||
1807 | out_unlock: | ||
1795 | cdev->private->flags.resuming = 0; | 1808 | cdev->private->flags.resuming = 0; |
1809 | spin_unlock_irq(sch->lock); | ||
1796 | } | 1810 | } |
1797 | 1811 | ||
1798 | static int resume_handle_boxed(struct ccw_device *cdev) | 1812 | static int resume_handle_boxed(struct ccw_device *cdev) |
1799 | { | 1813 | { |
1800 | cdev->private->state = DEV_STATE_BOXED; | 1814 | cdev->private->state = DEV_STATE_BOXED; |
1801 | if (ccw_device_notify(cdev, CIO_BOXED)) | 1815 | if (ccw_device_notify(cdev, CIO_BOXED) == NOTIFY_OK) |
1802 | return 0; | 1816 | return 0; |
1803 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 1817 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
1804 | return -ENODEV; | 1818 | return -ENODEV; |
@@ -1807,7 +1821,7 @@ static int resume_handle_boxed(struct ccw_device *cdev) | |||
1807 | static int resume_handle_disc(struct ccw_device *cdev) | 1821 | static int resume_handle_disc(struct ccw_device *cdev) |
1808 | { | 1822 | { |
1809 | cdev->private->state = DEV_STATE_DISCONNECTED; | 1823 | cdev->private->state = DEV_STATE_DISCONNECTED; |
1810 | if (ccw_device_notify(cdev, CIO_GONE)) | 1824 | if (ccw_device_notify(cdev, CIO_GONE) == NOTIFY_OK) |
1811 | return 0; | 1825 | return 0; |
1812 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 1826 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
1813 | return -ENODEV; | 1827 | return -ENODEV; |
@@ -1816,40 +1830,31 @@ static int resume_handle_disc(struct ccw_device *cdev) | |||
1816 | static int ccw_device_pm_restore(struct device *dev) | 1830 | static int ccw_device_pm_restore(struct device *dev) |
1817 | { | 1831 | { |
1818 | struct ccw_device *cdev = to_ccwdev(dev); | 1832 | struct ccw_device *cdev = to_ccwdev(dev); |
1819 | struct subchannel *sch = to_subchannel(cdev->dev.parent); | 1833 | struct subchannel *sch; |
1820 | int ret = 0, cm_enabled; | 1834 | int ret = 0; |
1821 | 1835 | ||
1822 | __ccw_device_pm_restore(cdev); | 1836 | __ccw_device_pm_restore(cdev); |
1837 | sch = to_subchannel(cdev->dev.parent); | ||
1823 | spin_lock_irq(sch->lock); | 1838 | spin_lock_irq(sch->lock); |
1824 | if (cio_is_console(sch->schid)) { | 1839 | if (cio_is_console(sch->schid)) |
1825 | cio_enable_subchannel(sch, (u32)(addr_t)sch); | ||
1826 | spin_unlock_irq(sch->lock); | ||
1827 | goto out_restore; | 1840 | goto out_restore; |
1828 | } | 1841 | |
1829 | cdev->private->flags.donotify = 0; | ||
1830 | /* check recognition results */ | 1842 | /* check recognition results */ |
1831 | switch (cdev->private->state) { | 1843 | switch (cdev->private->state) { |
1832 | case DEV_STATE_OFFLINE: | 1844 | case DEV_STATE_OFFLINE: |
1845 | case DEV_STATE_ONLINE: | ||
1846 | cdev->private->flags.donotify = 0; | ||
1833 | break; | 1847 | break; |
1834 | case DEV_STATE_BOXED: | 1848 | case DEV_STATE_BOXED: |
1835 | ret = resume_handle_boxed(cdev); | 1849 | ret = resume_handle_boxed(cdev); |
1836 | spin_unlock_irq(sch->lock); | ||
1837 | if (ret) | 1850 | if (ret) |
1838 | goto out; | 1851 | goto out_unlock; |
1839 | goto out_restore; | 1852 | goto out_restore; |
1840 | case DEV_STATE_DISCONNECTED: | ||
1841 | goto out_disc_unlock; | ||
1842 | default: | 1853 | default: |
1843 | goto out_unreg_unlock; | 1854 | ret = resume_handle_disc(cdev); |
1844 | } | 1855 | if (ret) |
1845 | /* check if the device id has changed */ | 1856 | goto out_unlock; |
1846 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { | 1857 | goto out_restore; |
1847 | CIO_MSG_EVENT(0, "resume: sch 0.%x.%04x: failed (devno " | ||
1848 | "changed from %04x to %04x)\n", | ||
1849 | sch->schid.ssid, sch->schid.sch_no, | ||
1850 | cdev->private->dev_id.devno, | ||
1851 | sch->schib.pmcw.dev); | ||
1852 | goto out_unreg_unlock; | ||
1853 | } | 1858 | } |
1854 | /* check if the device type has changed */ | 1859 | /* check if the device type has changed */ |
1855 | if (!ccw_device_test_sense_data(cdev)) { | 1860 | if (!ccw_device_test_sense_data(cdev)) { |
@@ -1858,24 +1863,30 @@ static int ccw_device_pm_restore(struct device *dev) | |||
1858 | ret = -ENODEV; | 1863 | ret = -ENODEV; |
1859 | goto out_unlock; | 1864 | goto out_unlock; |
1860 | } | 1865 | } |
1861 | if (!cdev->online) { | 1866 | if (!cdev->online) |
1862 | ret = 0; | ||
1863 | goto out_unlock; | 1867 | goto out_unlock; |
1864 | } | ||
1865 | ret = ccw_device_online(cdev); | ||
1866 | if (ret) | ||
1867 | goto out_disc_unlock; | ||
1868 | 1868 | ||
1869 | cm_enabled = cdev->private->cmb != NULL; | 1869 | if (ccw_device_online(cdev)) { |
1870 | ret = resume_handle_disc(cdev); | ||
1871 | if (ret) | ||
1872 | goto out_unlock; | ||
1873 | goto out_restore; | ||
1874 | } | ||
1870 | spin_unlock_irq(sch->lock); | 1875 | spin_unlock_irq(sch->lock); |
1871 | |||
1872 | wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); | 1876 | wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); |
1873 | if (cdev->private->state != DEV_STATE_ONLINE) { | 1877 | spin_lock_irq(sch->lock); |
1874 | spin_lock_irq(sch->lock); | 1878 | |
1875 | goto out_disc_unlock; | 1879 | if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_BAD) { |
1880 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | ||
1881 | ret = -ENODEV; | ||
1882 | goto out_unlock; | ||
1876 | } | 1883 | } |
1877 | if (cm_enabled) { | 1884 | |
1885 | /* reenable cmf, if needed */ | ||
1886 | if (cdev->private->cmb) { | ||
1887 | spin_unlock_irq(sch->lock); | ||
1878 | ret = ccw_set_cmf(cdev, 1); | 1888 | ret = ccw_set_cmf(cdev, 1); |
1889 | spin_lock_irq(sch->lock); | ||
1879 | if (ret) { | 1890 | if (ret) { |
1880 | CIO_MSG_EVENT(2, "resume: cdev 0.%x.%04x: cmf failed " | 1891 | CIO_MSG_EVENT(2, "resume: cdev 0.%x.%04x: cmf failed " |
1881 | "(rc=%d)\n", cdev->private->dev_id.ssid, | 1892 | "(rc=%d)\n", cdev->private->dev_id.ssid, |
@@ -1885,21 +1896,11 @@ static int ccw_device_pm_restore(struct device *dev) | |||
1885 | } | 1896 | } |
1886 | 1897 | ||
1887 | out_restore: | 1898 | out_restore: |
1899 | spin_unlock_irq(sch->lock); | ||
1888 | if (cdev->online && cdev->drv && cdev->drv->restore) | 1900 | if (cdev->online && cdev->drv && cdev->drv->restore) |
1889 | ret = cdev->drv->restore(cdev); | 1901 | ret = cdev->drv->restore(cdev); |
1890 | out: | ||
1891 | return ret; | 1902 | return ret; |
1892 | 1903 | ||
1893 | out_disc_unlock: | ||
1894 | ret = resume_handle_disc(cdev); | ||
1895 | spin_unlock_irq(sch->lock); | ||
1896 | if (ret) | ||
1897 | return ret; | ||
1898 | goto out_restore; | ||
1899 | |||
1900 | out_unreg_unlock: | ||
1901 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG_EVAL); | ||
1902 | ret = -ENODEV; | ||
1903 | out_unlock: | 1904 | out_unlock: |
1904 | spin_unlock_irq(sch->lock); | 1905 | spin_unlock_irq(sch->lock); |
1905 | return ret; | 1906 | return ret; |
@@ -2028,7 +2029,7 @@ void ccw_device_sched_todo(struct ccw_device *cdev, enum cdev_todo todo) | |||
2028 | /* Get workqueue ref. */ | 2029 | /* Get workqueue ref. */ |
2029 | if (!get_device(&cdev->dev)) | 2030 | if (!get_device(&cdev->dev)) |
2030 | return; | 2031 | return; |
2031 | if (!queue_work(slow_path_wq, &cdev->private->todo_work)) { | 2032 | if (!queue_work(cio_work_q, &cdev->private->todo_work)) { |
2032 | /* Already queued, release workqueue ref. */ | 2033 | /* Already queued, release workqueue ref. */ |
2033 | put_device(&cdev->dev); | 2034 | put_device(&cdev->dev); |
2034 | } | 2035 | } |
@@ -2041,5 +2042,4 @@ EXPORT_SYMBOL(ccw_driver_register); | |||
2041 | EXPORT_SYMBOL(ccw_driver_unregister); | 2042 | EXPORT_SYMBOL(ccw_driver_unregister); |
2042 | EXPORT_SYMBOL(get_ccwdev_by_busid); | 2043 | EXPORT_SYMBOL(get_ccwdev_by_busid); |
2043 | EXPORT_SYMBOL(ccw_bus_type); | 2044 | EXPORT_SYMBOL(ccw_bus_type); |
2044 | EXPORT_SYMBOL(ccw_device_work); | ||
2045 | EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); | 2045 | EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index bcfe13e42638..379de2d1ec49 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <asm/ccwdev.h> | 4 | #include <asm/ccwdev.h> |
5 | #include <asm/atomic.h> | 5 | #include <asm/atomic.h> |
6 | #include <linux/wait.h> | 6 | #include <linux/wait.h> |
7 | 7 | #include <linux/notifier.h> | |
8 | #include "io_sch.h" | 8 | #include "io_sch.h" |
9 | 9 | ||
10 | /* | 10 | /* |
@@ -71,7 +71,6 @@ dev_fsm_final_state(struct ccw_device *cdev) | |||
71 | cdev->private->state == DEV_STATE_BOXED); | 71 | cdev->private->state == DEV_STATE_BOXED); |
72 | } | 72 | } |
73 | 73 | ||
74 | extern struct workqueue_struct *ccw_device_work; | ||
75 | extern wait_queue_head_t ccw_device_init_wq; | 74 | extern wait_queue_head_t ccw_device_init_wq; |
76 | extern atomic_t ccw_device_init_count; | 75 | extern atomic_t ccw_device_init_count; |
77 | int __init io_subchannel_init(void); | 76 | int __init io_subchannel_init(void); |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index ae760658a131..c56ab94612f9 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -313,21 +313,43 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err) | |||
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
316 | /** | ||
317 | * ccw_device_notify() - inform the device's driver about an event | ||
318 | * @cdev: device for which an event occured | ||
319 | * @event: event that occurred | ||
320 | * | ||
321 | * Returns: | ||
322 | * -%EINVAL if the device is offline or has no driver. | ||
323 | * -%EOPNOTSUPP if the device's driver has no notifier registered. | ||
324 | * %NOTIFY_OK if the driver wants to keep the device. | ||
325 | * %NOTIFY_BAD if the driver doesn't want to keep the device. | ||
326 | */ | ||
316 | int ccw_device_notify(struct ccw_device *cdev, int event) | 327 | int ccw_device_notify(struct ccw_device *cdev, int event) |
317 | { | 328 | { |
329 | int ret = -EINVAL; | ||
330 | |||
318 | if (!cdev->drv) | 331 | if (!cdev->drv) |
319 | return 0; | 332 | goto out; |
320 | if (!cdev->online) | 333 | if (!cdev->online) |
321 | return 0; | 334 | goto out; |
322 | CIO_MSG_EVENT(2, "notify called for 0.%x.%04x, event=%d\n", | 335 | CIO_MSG_EVENT(2, "notify called for 0.%x.%04x, event=%d\n", |
323 | cdev->private->dev_id.ssid, cdev->private->dev_id.devno, | 336 | cdev->private->dev_id.ssid, cdev->private->dev_id.devno, |
324 | event); | 337 | event); |
325 | return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0; | 338 | if (!cdev->drv->notify) { |
339 | ret = -EOPNOTSUPP; | ||
340 | goto out; | ||
341 | } | ||
342 | if (cdev->drv->notify(cdev, event)) | ||
343 | ret = NOTIFY_OK; | ||
344 | else | ||
345 | ret = NOTIFY_BAD; | ||
346 | out: | ||
347 | return ret; | ||
326 | } | 348 | } |
327 | 349 | ||
328 | static void ccw_device_oper_notify(struct ccw_device *cdev) | 350 | static void ccw_device_oper_notify(struct ccw_device *cdev) |
329 | { | 351 | { |
330 | if (ccw_device_notify(cdev, CIO_OPER)) { | 352 | if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) { |
331 | /* Reenable channel measurements, if needed. */ | 353 | /* Reenable channel measurements, if needed. */ |
332 | ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF); | 354 | ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF); |
333 | return; | 355 | return; |
@@ -361,14 +383,15 @@ ccw_device_done(struct ccw_device *cdev, int state) | |||
361 | case DEV_STATE_BOXED: | 383 | case DEV_STATE_BOXED: |
362 | CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", | 384 | CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", |
363 | cdev->private->dev_id.devno, sch->schid.sch_no); | 385 | cdev->private->dev_id.devno, sch->schid.sch_no); |
364 | if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED)) | 386 | if (cdev->online && |
387 | ccw_device_notify(cdev, CIO_BOXED) != NOTIFY_OK) | ||
365 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 388 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
366 | cdev->private->flags.donotify = 0; | 389 | cdev->private->flags.donotify = 0; |
367 | break; | 390 | break; |
368 | case DEV_STATE_NOT_OPER: | 391 | case DEV_STATE_NOT_OPER: |
369 | CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n", | 392 | CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n", |
370 | cdev->private->dev_id.devno, sch->schid.sch_no); | 393 | cdev->private->dev_id.devno, sch->schid.sch_no); |
371 | if (!ccw_device_notify(cdev, CIO_GONE)) | 394 | if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) |
372 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 395 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
373 | else | 396 | else |
374 | ccw_device_set_disconnected(cdev); | 397 | ccw_device_set_disconnected(cdev); |
@@ -378,7 +401,7 @@ ccw_device_done(struct ccw_device *cdev, int state) | |||
378 | CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel " | 401 | CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel " |
379 | "%04x\n", cdev->private->dev_id.devno, | 402 | "%04x\n", cdev->private->dev_id.devno, |
380 | sch->schid.sch_no); | 403 | sch->schid.sch_no); |
381 | if (!ccw_device_notify(cdev, CIO_NO_PATH)) | 404 | if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) |
382 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 405 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
383 | else | 406 | else |
384 | ccw_device_set_disconnected(cdev); | 407 | ccw_device_set_disconnected(cdev); |
@@ -586,7 +609,7 @@ ccw_device_offline(struct ccw_device *cdev) | |||
586 | static void ccw_device_generic_notoper(struct ccw_device *cdev, | 609 | static void ccw_device_generic_notoper(struct ccw_device *cdev, |
587 | enum dev_event dev_event) | 610 | enum dev_event dev_event) |
588 | { | 611 | { |
589 | if (!ccw_device_notify(cdev, CIO_GONE)) | 612 | if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK) |
590 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); | 613 | ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); |
591 | else | 614 | else |
592 | ccw_device_set_disconnected(cdev); | 615 | ccw_device_set_disconnected(cdev); |
@@ -667,7 +690,7 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event) | |||
667 | struct irb *irb; | 690 | struct irb *irb; |
668 | int is_cmd; | 691 | int is_cmd; |
669 | 692 | ||
670 | irb = (struct irb *) __LC_IRB; | 693 | irb = (struct irb *)&S390_lowcore.irb; |
671 | is_cmd = !scsw_is_tm(&irb->scsw); | 694 | is_cmd = !scsw_is_tm(&irb->scsw); |
672 | /* Check for unsolicited interrupt. */ | 695 | /* Check for unsolicited interrupt. */ |
673 | if (!scsw_is_solicited(&irb->scsw)) { | 696 | if (!scsw_is_solicited(&irb->scsw)) { |
@@ -732,7 +755,7 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) | |||
732 | { | 755 | { |
733 | struct irb *irb; | 756 | struct irb *irb; |
734 | 757 | ||
735 | irb = (struct irb *) __LC_IRB; | 758 | irb = (struct irb *)&S390_lowcore.irb; |
736 | /* Check for unsolicited interrupt. */ | 759 | /* Check for unsolicited interrupt. */ |
737 | if (scsw_stctl(&irb->scsw) == | 760 | if (scsw_stctl(&irb->scsw) == |
738 | (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { | 761 | (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { |
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 44f2f6a97f33..48aa0647432b 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -208,18 +208,27 @@ struct qdio_dev_perf_stat { | |||
208 | unsigned int eqbs_partial; | 208 | unsigned int eqbs_partial; |
209 | unsigned int sqbs; | 209 | unsigned int sqbs; |
210 | unsigned int sqbs_partial; | 210 | unsigned int sqbs_partial; |
211 | } ____cacheline_aligned; | ||
212 | |||
213 | struct qdio_queue_perf_stat { | ||
214 | /* | ||
215 | * Sorted into order-2 buckets: 1, 2-3, 4-7, ... 64-127, 128. | ||
216 | * Since max. 127 SBALs are scanned reuse entry for 128 as queue full | ||
217 | * aka 127 SBALs found. | ||
218 | */ | ||
219 | unsigned int nr_sbals[8]; | ||
220 | unsigned int nr_sbal_error; | ||
221 | unsigned int nr_sbal_nop; | ||
222 | unsigned int nr_sbal_total; | ||
211 | }; | 223 | }; |
212 | 224 | ||
213 | struct qdio_input_q { | 225 | struct qdio_input_q { |
214 | /* input buffer acknowledgement flag */ | 226 | /* input buffer acknowledgement flag */ |
215 | int polling; | 227 | int polling; |
216 | |||
217 | /* first ACK'ed buffer */ | 228 | /* first ACK'ed buffer */ |
218 | int ack_start; | 229 | int ack_start; |
219 | |||
220 | /* how much sbals are acknowledged with qebsm */ | 230 | /* how much sbals are acknowledged with qebsm */ |
221 | int ack_count; | 231 | int ack_count; |
222 | |||
223 | /* last time of noticing incoming data */ | 232 | /* last time of noticing incoming data */ |
224 | u64 timestamp; | 233 | u64 timestamp; |
225 | }; | 234 | }; |
@@ -227,40 +236,27 @@ struct qdio_input_q { | |||
227 | struct qdio_output_q { | 236 | struct qdio_output_q { |
228 | /* PCIs are enabled for the queue */ | 237 | /* PCIs are enabled for the queue */ |
229 | int pci_out_enabled; | 238 | int pci_out_enabled; |
230 | |||
231 | /* IQDIO: output multiple buffers (enhanced SIGA) */ | 239 | /* IQDIO: output multiple buffers (enhanced SIGA) */ |
232 | int use_enh_siga; | 240 | int use_enh_siga; |
233 | |||
234 | /* timer to check for more outbound work */ | 241 | /* timer to check for more outbound work */ |
235 | struct timer_list timer; | 242 | struct timer_list timer; |
236 | }; | 243 | }; |
237 | 244 | ||
245 | /* | ||
246 | * Note on cache alignment: grouped slsb and write mostly data at the beginning | ||
247 | * sbal[] is read-only and starts on a new cacheline followed by read mostly. | ||
248 | */ | ||
238 | struct qdio_q { | 249 | struct qdio_q { |
239 | struct slsb slsb; | 250 | struct slsb slsb; |
251 | |||
240 | union { | 252 | union { |
241 | struct qdio_input_q in; | 253 | struct qdio_input_q in; |
242 | struct qdio_output_q out; | 254 | struct qdio_output_q out; |
243 | } u; | 255 | } u; |
244 | 256 | ||
245 | /* queue number */ | ||
246 | int nr; | ||
247 | |||
248 | /* bitmask of queue number */ | ||
249 | int mask; | ||
250 | |||
251 | /* input or output queue */ | ||
252 | int is_input_q; | ||
253 | |||
254 | /* list of thinint input queues */ | ||
255 | struct list_head entry; | ||
256 | |||
257 | /* upper-layer program handler */ | ||
258 | qdio_handler_t (*handler); | ||
259 | |||
260 | /* | 257 | /* |
261 | * inbound: next buffer the program should check for | 258 | * inbound: next buffer the program should check for |
262 | * outbound: next buffer to check for having been processed | 259 | * outbound: next buffer to check if adapter processed it |
263 | * by the card | ||
264 | */ | 260 | */ |
265 | int first_to_check; | 261 | int first_to_check; |
266 | 262 | ||
@@ -273,16 +269,32 @@ struct qdio_q { | |||
273 | /* number of buffers in use by the adapter */ | 269 | /* number of buffers in use by the adapter */ |
274 | atomic_t nr_buf_used; | 270 | atomic_t nr_buf_used; |
275 | 271 | ||
276 | struct qdio_irq *irq_ptr; | ||
277 | struct dentry *debugfs_q; | ||
278 | struct tasklet_struct tasklet; | ||
279 | |||
280 | /* error condition during a data transfer */ | 272 | /* error condition during a data transfer */ |
281 | unsigned int qdio_error; | 273 | unsigned int qdio_error; |
282 | 274 | ||
283 | struct sl *sl; | 275 | struct tasklet_struct tasklet; |
284 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; | 276 | struct qdio_queue_perf_stat q_stats; |
277 | |||
278 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q] ____cacheline_aligned; | ||
279 | |||
280 | /* queue number */ | ||
281 | int nr; | ||
282 | |||
283 | /* bitmask of queue number */ | ||
284 | int mask; | ||
285 | |||
286 | /* input or output queue */ | ||
287 | int is_input_q; | ||
288 | |||
289 | /* list of thinint input queues */ | ||
290 | struct list_head entry; | ||
285 | 291 | ||
292 | /* upper-layer program handler */ | ||
293 | qdio_handler_t (*handler); | ||
294 | |||
295 | struct dentry *debugfs_q; | ||
296 | struct qdio_irq *irq_ptr; | ||
297 | struct sl *sl; | ||
286 | /* | 298 | /* |
287 | * Warning: Leave this member at the end so it won't be cleared in | 299 | * Warning: Leave this member at the end so it won't be cleared in |
288 | * qdio_fill_qs. A page is allocated under this pointer and used for | 300 | * qdio_fill_qs. A page is allocated under this pointer and used for |
@@ -317,12 +329,8 @@ struct qdio_irq { | |||
317 | struct qdio_ssqd_desc ssqd_desc; | 329 | struct qdio_ssqd_desc ssqd_desc; |
318 | void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); | 330 | void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); |
319 | 331 | ||
320 | struct qdio_dev_perf_stat perf_stat; | ||
321 | int perf_stat_enabled; | 332 | int perf_stat_enabled; |
322 | /* | 333 | |
323 | * Warning: Leave these members together at the end so they won't be | ||
324 | * cleared in qdio_setup_irq. | ||
325 | */ | ||
326 | struct qdr *qdr; | 334 | struct qdr *qdr; |
327 | unsigned long chsc_page; | 335 | unsigned long chsc_page; |
328 | 336 | ||
@@ -331,6 +339,7 @@ struct qdio_irq { | |||
331 | 339 | ||
332 | debug_info_t *debug_area; | 340 | debug_info_t *debug_area; |
333 | struct mutex setup_mutex; | 341 | struct mutex setup_mutex; |
342 | struct qdio_dev_perf_stat perf_stat; | ||
334 | }; | 343 | }; |
335 | 344 | ||
336 | /* helper functions */ | 345 | /* helper functions */ |
@@ -341,9 +350,20 @@ struct qdio_irq { | |||
341 | (irq->qib.qfmt == QDIO_IQDIO_QFMT || \ | 350 | (irq->qib.qfmt == QDIO_IQDIO_QFMT || \ |
342 | css_general_characteristics.aif_osa) | 351 | css_general_characteristics.aif_osa) |
343 | 352 | ||
344 | #define qperf(qdev,attr) qdev->perf_stat.attr | 353 | #define qperf(__qdev, __attr) ((__qdev)->perf_stat.(__attr)) |
345 | #define qperf_inc(q,attr) if (q->irq_ptr->perf_stat_enabled) \ | 354 | |
346 | q->irq_ptr->perf_stat.attr++ | 355 | #define qperf_inc(__q, __attr) \ |
356 | ({ \ | ||
357 | struct qdio_irq *qdev = (__q)->irq_ptr; \ | ||
358 | if (qdev->perf_stat_enabled) \ | ||
359 | (qdev->perf_stat.__attr)++; \ | ||
360 | }) | ||
361 | |||
362 | static inline void account_sbals_error(struct qdio_q *q, int count) | ||
363 | { | ||
364 | q->q_stats.nr_sbal_error += count; | ||
365 | q->q_stats.nr_sbal_total += count; | ||
366 | } | ||
347 | 367 | ||
348 | /* the highest iqdio queue is used for multicast */ | 368 | /* the highest iqdio queue is used for multicast */ |
349 | static inline int multicast_outbound(struct qdio_q *q) | 369 | static inline int multicast_outbound(struct qdio_q *q) |
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index f49761ff9a00..c94eb2a0fa2e 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c | |||
@@ -60,7 +60,7 @@ static int qstat_show(struct seq_file *m, void *v) | |||
60 | seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move); | 60 | seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move); |
61 | seq_printf(m, "polling: %d ack start: %d ack count: %d\n", | 61 | seq_printf(m, "polling: %d ack start: %d ack count: %d\n", |
62 | q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count); | 62 | q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count); |
63 | seq_printf(m, "slsb buffer states:\n"); | 63 | seq_printf(m, "SBAL states:\n"); |
64 | seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); | 64 | seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); |
65 | 65 | ||
66 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { | 66 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { |
@@ -97,6 +97,20 @@ static int qstat_show(struct seq_file *m, void *v) | |||
97 | } | 97 | } |
98 | seq_printf(m, "\n"); | 98 | seq_printf(m, "\n"); |
99 | seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n"); | 99 | seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n"); |
100 | |||
101 | seq_printf(m, "\nSBAL statistics:"); | ||
102 | if (!q->irq_ptr->perf_stat_enabled) { | ||
103 | seq_printf(m, " disabled\n"); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | seq_printf(m, "\n1 2.. 4.. 8.. " | ||
108 | "16.. 32.. 64.. 127\n"); | ||
109 | for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++) | ||
110 | seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]); | ||
111 | seq_printf(m, "\nError NOP Total\n%-10u %-10u %-10u\n\n", | ||
112 | q->q_stats.nr_sbal_error, q->q_stats.nr_sbal_nop, | ||
113 | q->q_stats.nr_sbal_total); | ||
100 | return 0; | 114 | return 0; |
101 | } | 115 | } |
102 | 116 | ||
@@ -181,9 +195,10 @@ static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf, | |||
181 | { | 195 | { |
182 | struct seq_file *seq = file->private_data; | 196 | struct seq_file *seq = file->private_data; |
183 | struct qdio_irq *irq_ptr = seq->private; | 197 | struct qdio_irq *irq_ptr = seq->private; |
198 | struct qdio_q *q; | ||
184 | unsigned long val; | 199 | unsigned long val; |
185 | char buf[8]; | 200 | char buf[8]; |
186 | int ret; | 201 | int ret, i; |
187 | 202 | ||
188 | if (!irq_ptr) | 203 | if (!irq_ptr) |
189 | return 0; | 204 | return 0; |
@@ -201,6 +216,10 @@ static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf, | |||
201 | case 0: | 216 | case 0: |
202 | irq_ptr->perf_stat_enabled = 0; | 217 | irq_ptr->perf_stat_enabled = 0; |
203 | memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); | 218 | memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); |
219 | for_each_input_queue(irq_ptr, q, i) | ||
220 | memset(&q->q_stats, 0, sizeof(q->q_stats)); | ||
221 | for_each_output_queue(irq_ptr, q, i) | ||
222 | memset(&q->q_stats, 0, sizeof(q->q_stats)); | ||
204 | break; | 223 | break; |
205 | case 1: | 224 | case 1: |
206 | irq_ptr->perf_stat_enabled = 1; | 225 | irq_ptr->perf_stat_enabled = 1; |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 62b654af9237..232ef047ba34 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -392,6 +392,20 @@ static inline void qdio_stop_polling(struct qdio_q *q) | |||
392 | set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT); | 392 | set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT); |
393 | } | 393 | } |
394 | 394 | ||
395 | static inline void account_sbals(struct qdio_q *q, int count) | ||
396 | { | ||
397 | int pos = 0; | ||
398 | |||
399 | q->q_stats.nr_sbal_total += count; | ||
400 | if (count == QDIO_MAX_BUFFERS_MASK) { | ||
401 | q->q_stats.nr_sbals[7]++; | ||
402 | return; | ||
403 | } | ||
404 | while (count >>= 1) | ||
405 | pos++; | ||
406 | q->q_stats.nr_sbals[pos]++; | ||
407 | } | ||
408 | |||
395 | static void announce_buffer_error(struct qdio_q *q, int count) | 409 | static void announce_buffer_error(struct qdio_q *q, int count) |
396 | { | 410 | { |
397 | q->qdio_error |= QDIO_ERROR_SLSB_STATE; | 411 | q->qdio_error |= QDIO_ERROR_SLSB_STATE; |
@@ -487,16 +501,22 @@ static int get_inbound_buffer_frontier(struct qdio_q *q) | |||
487 | q->first_to_check = add_buf(q->first_to_check, count); | 501 | q->first_to_check = add_buf(q->first_to_check, count); |
488 | if (atomic_sub(count, &q->nr_buf_used) == 0) | 502 | if (atomic_sub(count, &q->nr_buf_used) == 0) |
489 | qperf_inc(q, inbound_queue_full); | 503 | qperf_inc(q, inbound_queue_full); |
504 | if (q->irq_ptr->perf_stat_enabled) | ||
505 | account_sbals(q, count); | ||
490 | break; | 506 | break; |
491 | case SLSB_P_INPUT_ERROR: | 507 | case SLSB_P_INPUT_ERROR: |
492 | announce_buffer_error(q, count); | 508 | announce_buffer_error(q, count); |
493 | /* process the buffer, the upper layer will take care of it */ | 509 | /* process the buffer, the upper layer will take care of it */ |
494 | q->first_to_check = add_buf(q->first_to_check, count); | 510 | q->first_to_check = add_buf(q->first_to_check, count); |
495 | atomic_sub(count, &q->nr_buf_used); | 511 | atomic_sub(count, &q->nr_buf_used); |
512 | if (q->irq_ptr->perf_stat_enabled) | ||
513 | account_sbals_error(q, count); | ||
496 | break; | 514 | break; |
497 | case SLSB_CU_INPUT_EMPTY: | 515 | case SLSB_CU_INPUT_EMPTY: |
498 | case SLSB_P_INPUT_NOT_INIT: | 516 | case SLSB_P_INPUT_NOT_INIT: |
499 | case SLSB_P_INPUT_ACK: | 517 | case SLSB_P_INPUT_ACK: |
518 | if (q->irq_ptr->perf_stat_enabled) | ||
519 | q->q_stats.nr_sbal_nop++; | ||
500 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop"); | 520 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop"); |
501 | break; | 521 | break; |
502 | default: | 522 | default: |
@@ -514,7 +534,7 @@ static int qdio_inbound_q_moved(struct qdio_q *q) | |||
514 | 534 | ||
515 | if ((bufnr != q->last_move) || q->qdio_error) { | 535 | if ((bufnr != q->last_move) || q->qdio_error) { |
516 | q->last_move = bufnr; | 536 | q->last_move = bufnr; |
517 | if (!is_thinint_irq(q->irq_ptr) && !MACHINE_IS_VM) | 537 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) |
518 | q->u.in.timestamp = get_usecs(); | 538 | q->u.in.timestamp = get_usecs(); |
519 | return 1; | 539 | return 1; |
520 | } else | 540 | } else |
@@ -643,15 +663,21 @@ static int get_outbound_buffer_frontier(struct qdio_q *q) | |||
643 | 663 | ||
644 | atomic_sub(count, &q->nr_buf_used); | 664 | atomic_sub(count, &q->nr_buf_used); |
645 | q->first_to_check = add_buf(q->first_to_check, count); | 665 | q->first_to_check = add_buf(q->first_to_check, count); |
666 | if (q->irq_ptr->perf_stat_enabled) | ||
667 | account_sbals(q, count); | ||
646 | break; | 668 | break; |
647 | case SLSB_P_OUTPUT_ERROR: | 669 | case SLSB_P_OUTPUT_ERROR: |
648 | announce_buffer_error(q, count); | 670 | announce_buffer_error(q, count); |
649 | /* process the buffer, the upper layer will take care of it */ | 671 | /* process the buffer, the upper layer will take care of it */ |
650 | q->first_to_check = add_buf(q->first_to_check, count); | 672 | q->first_to_check = add_buf(q->first_to_check, count); |
651 | atomic_sub(count, &q->nr_buf_used); | 673 | atomic_sub(count, &q->nr_buf_used); |
674 | if (q->irq_ptr->perf_stat_enabled) | ||
675 | account_sbals_error(q, count); | ||
652 | break; | 676 | break; |
653 | case SLSB_CU_OUTPUT_PRIMED: | 677 | case SLSB_CU_OUTPUT_PRIMED: |
654 | /* the adapter has not fetched the output yet */ | 678 | /* the adapter has not fetched the output yet */ |
679 | if (q->irq_ptr->perf_stat_enabled) | ||
680 | q->q_stats.nr_sbal_nop++; | ||
655 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d", q->nr); | 681 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d", q->nr); |
656 | break; | 682 | break; |
657 | case SLSB_P_OUTPUT_NOT_INIT: | 683 | case SLSB_P_OUTPUT_NOT_INIT: |
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 8c2dea5fa2b4..7f4a75465140 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c | |||
@@ -333,10 +333,10 @@ static void __qdio_allocate_fill_qdr(struct qdio_irq *irq_ptr, | |||
333 | irq_ptr->qdr->qdf0[i + nr].slsba = | 333 | irq_ptr->qdr->qdf0[i + nr].slsba = |
334 | (unsigned long)&irq_ptr_qs[i]->slsb.val[0]; | 334 | (unsigned long)&irq_ptr_qs[i]->slsb.val[0]; |
335 | 335 | ||
336 | irq_ptr->qdr->qdf0[i + nr].akey = PAGE_DEFAULT_KEY; | 336 | irq_ptr->qdr->qdf0[i + nr].akey = PAGE_DEFAULT_KEY >> 4; |
337 | irq_ptr->qdr->qdf0[i + nr].bkey = PAGE_DEFAULT_KEY; | 337 | irq_ptr->qdr->qdf0[i + nr].bkey = PAGE_DEFAULT_KEY >> 4; |
338 | irq_ptr->qdr->qdf0[i + nr].ckey = PAGE_DEFAULT_KEY; | 338 | irq_ptr->qdr->qdf0[i + nr].ckey = PAGE_DEFAULT_KEY >> 4; |
339 | irq_ptr->qdr->qdf0[i + nr].dkey = PAGE_DEFAULT_KEY; | 339 | irq_ptr->qdr->qdf0[i + nr].dkey = PAGE_DEFAULT_KEY >> 4; |
340 | } | 340 | } |
341 | 341 | ||
342 | static void setup_qdr(struct qdio_irq *irq_ptr, | 342 | static void setup_qdr(struct qdio_irq *irq_ptr, |
@@ -350,7 +350,7 @@ static void setup_qdr(struct qdio_irq *irq_ptr, | |||
350 | irq_ptr->qdr->iqdsz = sizeof(struct qdesfmt0) / 4; /* size in words */ | 350 | irq_ptr->qdr->iqdsz = sizeof(struct qdesfmt0) / 4; /* size in words */ |
351 | irq_ptr->qdr->oqdsz = sizeof(struct qdesfmt0) / 4; | 351 | irq_ptr->qdr->oqdsz = sizeof(struct qdesfmt0) / 4; |
352 | irq_ptr->qdr->qiba = (unsigned long)&irq_ptr->qib; | 352 | irq_ptr->qdr->qiba = (unsigned long)&irq_ptr->qib; |
353 | irq_ptr->qdr->qkey = PAGE_DEFAULT_KEY; | 353 | irq_ptr->qdr->qkey = PAGE_DEFAULT_KEY >> 4; |
354 | 354 | ||
355 | for (i = 0; i < qdio_init->no_input_qs; i++) | 355 | for (i = 0; i < qdio_init->no_input_qs; i++) |
356 | __qdio_allocate_fill_qdr(irq_ptr, irq_ptr->input_qs, i, 0); | 356 | __qdio_allocate_fill_qdr(irq_ptr, irq_ptr->input_qs, i, 0); |
@@ -382,7 +382,15 @@ int qdio_setup_irq(struct qdio_initialize *init_data) | |||
382 | struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; | 382 | struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; |
383 | int rc; | 383 | int rc; |
384 | 384 | ||
385 | memset(irq_ptr, 0, ((char *)&irq_ptr->qdr) - ((char *)irq_ptr)); | 385 | memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); |
386 | memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); | ||
387 | memset(&irq_ptr->ccw, 0, sizeof(irq_ptr->ccw)); | ||
388 | memset(&irq_ptr->ssqd_desc, 0, sizeof(irq_ptr->ssqd_desc)); | ||
389 | memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); | ||
390 | |||
391 | irq_ptr->debugfs_dev = irq_ptr->debugfs_perf = NULL; | ||
392 | irq_ptr->sch_token = irq_ptr->state = irq_ptr->perf_stat_enabled = 0; | ||
393 | |||
386 | /* wipes qib.ac, required by ar7063 */ | 394 | /* wipes qib.ac, required by ar7063 */ |
387 | memset(irq_ptr->qdr, 0, sizeof(struct qdr)); | 395 | memset(irq_ptr->qdr, 0, sizeof(struct qdr)); |
388 | 396 | ||
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 091d904d3182..9942c1031b25 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
@@ -198,8 +198,8 @@ static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset) | |||
198 | .code = 0x0021, | 198 | .code = 0x0021, |
199 | }; | 199 | }; |
200 | scssc_area->operation_code = 0; | 200 | scssc_area->operation_code = 0; |
201 | scssc_area->ks = PAGE_DEFAULT_KEY; | 201 | scssc_area->ks = PAGE_DEFAULT_KEY >> 4; |
202 | scssc_area->kc = PAGE_DEFAULT_KEY; | 202 | scssc_area->kc = PAGE_DEFAULT_KEY >> 4; |
203 | scssc_area->isc = QDIO_AIRQ_ISC; | 203 | scssc_area->isc = QDIO_AIRQ_ISC; |
204 | scssc_area->schid = irq_ptr->schid; | 204 | scssc_area->schid = irq_ptr->schid; |
205 | 205 | ||
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index c68be24e27d9..ba50fe02e572 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/miscdevice.h> | 33 | #include <linux/miscdevice.h> |
34 | #include <linux/fs.h> | 34 | #include <linux/fs.h> |
35 | #include <linux/proc_fs.h> | 35 | #include <linux/proc_fs.h> |
36 | #include <linux/seq_file.h> | ||
36 | #include <linux/compat.h> | 37 | #include <linux/compat.h> |
37 | #include <linux/smp_lock.h> | 38 | #include <linux/smp_lock.h> |
38 | #include <asm/atomic.h> | 39 | #include <asm/atomic.h> |
@@ -912,126 +913,105 @@ static struct miscdevice zcrypt_misc_device = { | |||
912 | */ | 913 | */ |
913 | static struct proc_dir_entry *zcrypt_entry; | 914 | static struct proc_dir_entry *zcrypt_entry; |
914 | 915 | ||
915 | static int sprintcl(unsigned char *outaddr, unsigned char *addr, | 916 | static void sprintcl(struct seq_file *m, unsigned char *addr, unsigned int len) |
916 | unsigned int len) | ||
917 | { | 917 | { |
918 | int hl, i; | 918 | int i; |
919 | 919 | ||
920 | hl = 0; | ||
921 | for (i = 0; i < len; i++) | 920 | for (i = 0; i < len; i++) |
922 | hl += sprintf(outaddr+hl, "%01x", (unsigned int) addr[i]); | 921 | seq_printf(m, "%01x", (unsigned int) addr[i]); |
923 | hl += sprintf(outaddr+hl, " "); | 922 | seq_putc(m, ' '); |
924 | return hl; | ||
925 | } | 923 | } |
926 | 924 | ||
927 | static int sprintrw(unsigned char *outaddr, unsigned char *addr, | 925 | static void sprintrw(struct seq_file *m, unsigned char *addr, unsigned int len) |
928 | unsigned int len) | ||
929 | { | 926 | { |
930 | int hl, inl, c, cx; | 927 | int inl, c, cx; |
931 | 928 | ||
932 | hl = sprintf(outaddr, " "); | 929 | seq_printf(m, " "); |
933 | inl = 0; | 930 | inl = 0; |
934 | for (c = 0; c < (len / 16); c++) { | 931 | for (c = 0; c < (len / 16); c++) { |
935 | hl += sprintcl(outaddr+hl, addr+inl, 16); | 932 | sprintcl(m, addr+inl, 16); |
936 | inl += 16; | 933 | inl += 16; |
937 | } | 934 | } |
938 | cx = len%16; | 935 | cx = len%16; |
939 | if (cx) { | 936 | if (cx) { |
940 | hl += sprintcl(outaddr+hl, addr+inl, cx); | 937 | sprintcl(m, addr+inl, cx); |
941 | inl += cx; | 938 | inl += cx; |
942 | } | 939 | } |
943 | hl += sprintf(outaddr+hl, "\n"); | 940 | seq_putc(m, '\n'); |
944 | return hl; | ||
945 | } | 941 | } |
946 | 942 | ||
947 | static int sprinthx(unsigned char *title, unsigned char *outaddr, | 943 | static void sprinthx(unsigned char *title, struct seq_file *m, |
948 | unsigned char *addr, unsigned int len) | 944 | unsigned char *addr, unsigned int len) |
949 | { | 945 | { |
950 | int hl, inl, r, rx; | 946 | int inl, r, rx; |
951 | 947 | ||
952 | hl = sprintf(outaddr, "\n%s\n", title); | 948 | seq_printf(m, "\n%s\n", title); |
953 | inl = 0; | 949 | inl = 0; |
954 | for (r = 0; r < (len / 64); r++) { | 950 | for (r = 0; r < (len / 64); r++) { |
955 | hl += sprintrw(outaddr+hl, addr+inl, 64); | 951 | sprintrw(m, addr+inl, 64); |
956 | inl += 64; | 952 | inl += 64; |
957 | } | 953 | } |
958 | rx = len % 64; | 954 | rx = len % 64; |
959 | if (rx) { | 955 | if (rx) { |
960 | hl += sprintrw(outaddr+hl, addr+inl, rx); | 956 | sprintrw(m, addr+inl, rx); |
961 | inl += rx; | 957 | inl += rx; |
962 | } | 958 | } |
963 | hl += sprintf(outaddr+hl, "\n"); | 959 | seq_putc(m, '\n'); |
964 | return hl; | ||
965 | } | 960 | } |
966 | 961 | ||
967 | static int sprinthx4(unsigned char *title, unsigned char *outaddr, | 962 | static void sprinthx4(unsigned char *title, struct seq_file *m, |
968 | unsigned int *array, unsigned int len) | 963 | unsigned int *array, unsigned int len) |
969 | { | 964 | { |
970 | int hl, r; | 965 | int r; |
971 | 966 | ||
972 | hl = sprintf(outaddr, "\n%s\n", title); | 967 | seq_printf(m, "\n%s\n", title); |
973 | for (r = 0; r < len; r++) { | 968 | for (r = 0; r < len; r++) { |
974 | if ((r % 8) == 0) | 969 | if ((r % 8) == 0) |
975 | hl += sprintf(outaddr+hl, " "); | 970 | seq_printf(m, " "); |
976 | hl += sprintf(outaddr+hl, "%08X ", array[r]); | 971 | seq_printf(m, "%08X ", array[r]); |
977 | if ((r % 8) == 7) | 972 | if ((r % 8) == 7) |
978 | hl += sprintf(outaddr+hl, "\n"); | 973 | seq_putc(m, '\n'); |
979 | } | 974 | } |
980 | hl += sprintf(outaddr+hl, "\n"); | 975 | seq_putc(m, '\n'); |
981 | return hl; | ||
982 | } | 976 | } |
983 | 977 | ||
984 | static int zcrypt_status_read(char *resp_buff, char **start, off_t offset, | 978 | static int zcrypt_proc_show(struct seq_file *m, void *v) |
985 | int count, int *eof, void *data) | ||
986 | { | 979 | { |
987 | unsigned char *workarea; | 980 | char workarea[sizeof(int) * AP_DEVICES]; |
988 | int len; | 981 | |
989 | 982 | seq_printf(m, "\nzcrypt version: %d.%d.%d\n", | |
990 | len = 0; | 983 | ZCRYPT_VERSION, ZCRYPT_RELEASE, ZCRYPT_VARIANT); |
991 | 984 | seq_printf(m, "Cryptographic domain: %d\n", ap_domain_index); | |
992 | /* resp_buff is a page. Use the right half for a work area */ | 985 | seq_printf(m, "Total device count: %d\n", zcrypt_device_count); |
993 | workarea = resp_buff + 2000; | 986 | seq_printf(m, "PCICA count: %d\n", zcrypt_count_type(ZCRYPT_PCICA)); |
994 | len += sprintf(resp_buff + len, "\nzcrypt version: %d.%d.%d\n", | 987 | seq_printf(m, "PCICC count: %d\n", zcrypt_count_type(ZCRYPT_PCICC)); |
995 | ZCRYPT_VERSION, ZCRYPT_RELEASE, ZCRYPT_VARIANT); | 988 | seq_printf(m, "PCIXCC MCL2 count: %d\n", |
996 | len += sprintf(resp_buff + len, "Cryptographic domain: %d\n", | 989 | zcrypt_count_type(ZCRYPT_PCIXCC_MCL2)); |
997 | ap_domain_index); | 990 | seq_printf(m, "PCIXCC MCL3 count: %d\n", |
998 | len += sprintf(resp_buff + len, "Total device count: %d\n", | 991 | zcrypt_count_type(ZCRYPT_PCIXCC_MCL3)); |
999 | zcrypt_device_count); | 992 | seq_printf(m, "CEX2C count: %d\n", zcrypt_count_type(ZCRYPT_CEX2C)); |
1000 | len += sprintf(resp_buff + len, "PCICA count: %d\n", | 993 | seq_printf(m, "CEX2A count: %d\n", zcrypt_count_type(ZCRYPT_CEX2A)); |
1001 | zcrypt_count_type(ZCRYPT_PCICA)); | 994 | seq_printf(m, "CEX3C count: %d\n", zcrypt_count_type(ZCRYPT_CEX3C)); |
1002 | len += sprintf(resp_buff + len, "PCICC count: %d\n", | 995 | seq_printf(m, "CEX3A count: %d\n", zcrypt_count_type(ZCRYPT_CEX3A)); |
1003 | zcrypt_count_type(ZCRYPT_PCICC)); | 996 | seq_printf(m, "requestq count: %d\n", zcrypt_requestq_count()); |
1004 | len += sprintf(resp_buff + len, "PCIXCC MCL2 count: %d\n", | 997 | seq_printf(m, "pendingq count: %d\n", zcrypt_pendingq_count()); |
1005 | zcrypt_count_type(ZCRYPT_PCIXCC_MCL2)); | 998 | seq_printf(m, "Total open handles: %d\n\n", |
1006 | len += sprintf(resp_buff + len, "PCIXCC MCL3 count: %d\n", | 999 | atomic_read(&zcrypt_open_count)); |
1007 | zcrypt_count_type(ZCRYPT_PCIXCC_MCL3)); | ||
1008 | len += sprintf(resp_buff + len, "CEX2C count: %d\n", | ||
1009 | zcrypt_count_type(ZCRYPT_CEX2C)); | ||
1010 | len += sprintf(resp_buff + len, "CEX2A count: %d\n", | ||
1011 | zcrypt_count_type(ZCRYPT_CEX2A)); | ||
1012 | len += sprintf(resp_buff + len, "CEX3C count: %d\n", | ||
1013 | zcrypt_count_type(ZCRYPT_CEX3C)); | ||
1014 | len += sprintf(resp_buff + len, "CEX3A count: %d\n", | ||
1015 | zcrypt_count_type(ZCRYPT_CEX3A)); | ||
1016 | len += sprintf(resp_buff + len, "requestq count: %d\n", | ||
1017 | zcrypt_requestq_count()); | ||
1018 | len += sprintf(resp_buff + len, "pendingq count: %d\n", | ||
1019 | zcrypt_pendingq_count()); | ||
1020 | len += sprintf(resp_buff + len, "Total open handles: %d\n\n", | ||
1021 | atomic_read(&zcrypt_open_count)); | ||
1022 | zcrypt_status_mask(workarea); | 1000 | zcrypt_status_mask(workarea); |
1023 | len += sprinthx("Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) " | 1001 | sprinthx("Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) " |
1024 | "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A 7=CEX3C 8=CEX3A", | 1002 | "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A 7=CEX3C 8=CEX3A", |
1025 | resp_buff+len, workarea, AP_DEVICES); | 1003 | m, workarea, AP_DEVICES); |
1026 | zcrypt_qdepth_mask(workarea); | 1004 | zcrypt_qdepth_mask(workarea); |
1027 | len += sprinthx("Waiting work element counts", | 1005 | sprinthx("Waiting work element counts", m, workarea, AP_DEVICES); |
1028 | resp_buff+len, workarea, AP_DEVICES); | ||
1029 | zcrypt_perdev_reqcnt((int *) workarea); | 1006 | zcrypt_perdev_reqcnt((int *) workarea); |
1030 | len += sprinthx4("Per-device successfully completed request counts", | 1007 | sprinthx4("Per-device successfully completed request counts", |
1031 | resp_buff+len,(unsigned int *) workarea, AP_DEVICES); | 1008 | m, (unsigned int *) workarea, AP_DEVICES); |
1032 | *eof = 1; | 1009 | return 0; |
1033 | memset((void *) workarea, 0x00, AP_DEVICES * sizeof(unsigned int)); | 1010 | } |
1034 | return len; | 1011 | |
1012 | static int zcrypt_proc_open(struct inode *inode, struct file *file) | ||
1013 | { | ||
1014 | return single_open(file, zcrypt_proc_show, NULL); | ||
1035 | } | 1015 | } |
1036 | 1016 | ||
1037 | static void zcrypt_disable_card(int index) | 1017 | static void zcrypt_disable_card(int index) |
@@ -1061,11 +1041,11 @@ static void zcrypt_enable_card(int index) | |||
1061 | spin_unlock_bh(&zcrypt_device_lock); | 1041 | spin_unlock_bh(&zcrypt_device_lock); |
1062 | } | 1042 | } |
1063 | 1043 | ||
1064 | static int zcrypt_status_write(struct file *file, const char __user *buffer, | 1044 | static ssize_t zcrypt_proc_write(struct file *file, const char __user *buffer, |
1065 | unsigned long count, void *data) | 1045 | size_t count, loff_t *pos) |
1066 | { | 1046 | { |
1067 | unsigned char *lbuf, *ptr; | 1047 | unsigned char *lbuf, *ptr; |
1068 | unsigned long local_count; | 1048 | size_t local_count; |
1069 | int j; | 1049 | int j; |
1070 | 1050 | ||
1071 | if (count <= 0) | 1051 | if (count <= 0) |
@@ -1115,6 +1095,15 @@ out: | |||
1115 | return count; | 1095 | return count; |
1116 | } | 1096 | } |
1117 | 1097 | ||
1098 | static const struct file_operations zcrypt_proc_fops = { | ||
1099 | .owner = THIS_MODULE, | ||
1100 | .open = zcrypt_proc_open, | ||
1101 | .read = seq_read, | ||
1102 | .llseek = seq_lseek, | ||
1103 | .release = single_release, | ||
1104 | .write = zcrypt_proc_write, | ||
1105 | }; | ||
1106 | |||
1118 | static int zcrypt_rng_device_count; | 1107 | static int zcrypt_rng_device_count; |
1119 | static u32 *zcrypt_rng_buffer; | 1108 | static u32 *zcrypt_rng_buffer; |
1120 | static int zcrypt_rng_buffer_index; | 1109 | static int zcrypt_rng_buffer_index; |
@@ -1197,14 +1186,11 @@ int __init zcrypt_api_init(void) | |||
1197 | goto out; | 1186 | goto out; |
1198 | 1187 | ||
1199 | /* Set up the proc file system */ | 1188 | /* Set up the proc file system */ |
1200 | zcrypt_entry = create_proc_entry("driver/z90crypt", 0644, NULL); | 1189 | zcrypt_entry = proc_create("driver/z90crypt", 0644, NULL, &zcrypt_proc_fops); |
1201 | if (!zcrypt_entry) { | 1190 | if (!zcrypt_entry) { |
1202 | rc = -ENOMEM; | 1191 | rc = -ENOMEM; |
1203 | goto out_misc; | 1192 | goto out_misc; |
1204 | } | 1193 | } |
1205 | zcrypt_entry->data = NULL; | ||
1206 | zcrypt_entry->read_proc = zcrypt_status_read; | ||
1207 | zcrypt_entry->write_proc = zcrypt_status_write; | ||
1208 | 1194 | ||
1209 | return 0; | 1195 | return 0; |
1210 | 1196 | ||
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 2930fc763ac5..b2fc4fd63f7f 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -340,11 +340,11 @@ static void kvm_extint_handler(u16 code) | |||
340 | return; | 340 | return; |
341 | 341 | ||
342 | /* The LSB might be overloaded, we have to mask it */ | 342 | /* The LSB might be overloaded, we have to mask it */ |
343 | vq = (struct virtqueue *) ((*(long *) __LC_PFAULT_INTPARM) & ~1UL); | 343 | vq = (struct virtqueue *)(S390_lowcore.ext_params2 & ~1UL); |
344 | 344 | ||
345 | /* We use the LSB of extparam, to decide, if this interrupt is a config | 345 | /* We use the LSB of extparam, to decide, if this interrupt is a config |
346 | * change or a "standard" interrupt */ | 346 | * change or a "standard" interrupt */ |
347 | config_changed = (*(int *) __LC_EXT_PARAMS & 1); | 347 | config_changed = S390_lowcore.ext_params & 1; |
348 | 348 | ||
349 | if (config_changed) { | 349 | if (config_changed) { |
350 | struct virtio_driver *drv; | 350 | struct virtio_driver *drv; |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 9d0c941b7d33..66d6c01fcf3e 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Module interface and handling of zfcp data structures. | 4 | * Module interface and handling of zfcp data structures. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2002, 2009 | 6 | * Copyright IBM Corporation 2002, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
33 | #include "zfcp_ext.h" | 33 | #include "zfcp_ext.h" |
34 | #include "zfcp_fc.h" | 34 | #include "zfcp_fc.h" |
35 | #include "zfcp_reqlist.h" | ||
35 | 36 | ||
36 | #define ZFCP_BUS_ID_SIZE 20 | 37 | #define ZFCP_BUS_ID_SIZE 20 |
37 | 38 | ||
@@ -49,36 +50,6 @@ static struct kmem_cache *zfcp_cache_hw_align(const char *name, | |||
49 | return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL); | 50 | return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL); |
50 | } | 51 | } |
51 | 52 | ||
52 | static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter) | ||
53 | { | ||
54 | int idx; | ||
55 | |||
56 | adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head), | ||
57 | GFP_KERNEL); | ||
58 | if (!adapter->req_list) | ||
59 | return -ENOMEM; | ||
60 | |||
61 | for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) | ||
62 | INIT_LIST_HEAD(&adapter->req_list[idx]); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * zfcp_reqlist_isempty - is the request list empty | ||
68 | * @adapter: pointer to struct zfcp_adapter | ||
69 | * | ||
70 | * Returns: true if list is empty, false otherwise | ||
71 | */ | ||
72 | int zfcp_reqlist_isempty(struct zfcp_adapter *adapter) | ||
73 | { | ||
74 | unsigned int idx; | ||
75 | |||
76 | for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) | ||
77 | if (!list_empty(&adapter->req_list[idx])) | ||
78 | return 0; | ||
79 | return 1; | ||
80 | } | ||
81 | |||
82 | static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | 53 | static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) |
83 | { | 54 | { |
84 | struct ccw_device *cdev; | 55 | struct ccw_device *cdev; |
@@ -110,7 +81,7 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | |||
110 | flush_work(&unit->scsi_work); | 81 | flush_work(&unit->scsi_work); |
111 | 82 | ||
112 | out_unit: | 83 | out_unit: |
113 | put_device(&port->sysfs_device); | 84 | put_device(&port->dev); |
114 | out_port: | 85 | out_port: |
115 | zfcp_ccw_adapter_put(adapter); | 86 | zfcp_ccw_adapter_put(adapter); |
116 | out_ccw_device: | 87 | out_ccw_device: |
@@ -255,7 +226,7 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) | |||
255 | read_lock_irqsave(&port->unit_list_lock, flags); | 226 | read_lock_irqsave(&port->unit_list_lock, flags); |
256 | list_for_each_entry(unit, &port->unit_list, list) | 227 | list_for_each_entry(unit, &port->unit_list, list) |
257 | if (unit->fcp_lun == fcp_lun) { | 228 | if (unit->fcp_lun == fcp_lun) { |
258 | if (!get_device(&unit->sysfs_device)) | 229 | if (!get_device(&unit->dev)) |
259 | unit = NULL; | 230 | unit = NULL; |
260 | read_unlock_irqrestore(&port->unit_list_lock, flags); | 231 | read_unlock_irqrestore(&port->unit_list_lock, flags); |
261 | return unit; | 232 | return unit; |
@@ -280,7 +251,7 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, | |||
280 | read_lock_irqsave(&adapter->port_list_lock, flags); | 251 | read_lock_irqsave(&adapter->port_list_lock, flags); |
281 | list_for_each_entry(port, &adapter->port_list, list) | 252 | list_for_each_entry(port, &adapter->port_list, list) |
282 | if (port->wwpn == wwpn) { | 253 | if (port->wwpn == wwpn) { |
283 | if (!get_device(&port->sysfs_device)) | 254 | if (!get_device(&port->dev)) |
284 | port = NULL; | 255 | port = NULL; |
285 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | 256 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
286 | return port; | 257 | return port; |
@@ -298,10 +269,9 @@ struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, | |||
298 | */ | 269 | */ |
299 | static void zfcp_unit_release(struct device *dev) | 270 | static void zfcp_unit_release(struct device *dev) |
300 | { | 271 | { |
301 | struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, | 272 | struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); |
302 | sysfs_device); | ||
303 | 273 | ||
304 | put_device(&unit->port->sysfs_device); | 274 | put_device(&unit->port->dev); |
305 | kfree(unit); | 275 | kfree(unit); |
306 | } | 276 | } |
307 | 277 | ||
@@ -318,11 +288,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
318 | struct zfcp_unit *unit; | 288 | struct zfcp_unit *unit; |
319 | int retval = -ENOMEM; | 289 | int retval = -ENOMEM; |
320 | 290 | ||
321 | get_device(&port->sysfs_device); | 291 | get_device(&port->dev); |
322 | 292 | ||
323 | unit = zfcp_get_unit_by_lun(port, fcp_lun); | 293 | unit = zfcp_get_unit_by_lun(port, fcp_lun); |
324 | if (unit) { | 294 | if (unit) { |
325 | put_device(&unit->sysfs_device); | 295 | put_device(&unit->dev); |
326 | retval = -EEXIST; | 296 | retval = -EEXIST; |
327 | goto err_out; | 297 | goto err_out; |
328 | } | 298 | } |
@@ -333,10 +303,10 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
333 | 303 | ||
334 | unit->port = port; | 304 | unit->port = port; |
335 | unit->fcp_lun = fcp_lun; | 305 | unit->fcp_lun = fcp_lun; |
336 | unit->sysfs_device.parent = &port->sysfs_device; | 306 | unit->dev.parent = &port->dev; |
337 | unit->sysfs_device.release = zfcp_unit_release; | 307 | unit->dev.release = zfcp_unit_release; |
338 | 308 | ||
339 | if (dev_set_name(&unit->sysfs_device, "0x%016llx", | 309 | if (dev_set_name(&unit->dev, "0x%016llx", |
340 | (unsigned long long) fcp_lun)) { | 310 | (unsigned long long) fcp_lun)) { |
341 | kfree(unit); | 311 | kfree(unit); |
342 | goto err_out; | 312 | goto err_out; |
@@ -353,13 +323,12 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
353 | unit->latencies.cmd.channel.min = 0xFFFFFFFF; | 323 | unit->latencies.cmd.channel.min = 0xFFFFFFFF; |
354 | unit->latencies.cmd.fabric.min = 0xFFFFFFFF; | 324 | unit->latencies.cmd.fabric.min = 0xFFFFFFFF; |
355 | 325 | ||
356 | if (device_register(&unit->sysfs_device)) { | 326 | if (device_register(&unit->dev)) { |
357 | put_device(&unit->sysfs_device); | 327 | put_device(&unit->dev); |
358 | goto err_out; | 328 | goto err_out; |
359 | } | 329 | } |
360 | 330 | ||
361 | if (sysfs_create_group(&unit->sysfs_device.kobj, | 331 | if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) |
362 | &zfcp_sysfs_unit_attrs)) | ||
363 | goto err_out_put; | 332 | goto err_out_put; |
364 | 333 | ||
365 | write_lock_irq(&port->unit_list_lock); | 334 | write_lock_irq(&port->unit_list_lock); |
@@ -371,9 +340,9 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
371 | return unit; | 340 | return unit; |
372 | 341 | ||
373 | err_out_put: | 342 | err_out_put: |
374 | device_unregister(&unit->sysfs_device); | 343 | device_unregister(&unit->dev); |
375 | err_out: | 344 | err_out: |
376 | put_device(&port->sysfs_device); | 345 | put_device(&port->dev); |
377 | return ERR_PTR(retval); | 346 | return ERR_PTR(retval); |
378 | } | 347 | } |
379 | 348 | ||
@@ -539,7 +508,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
539 | if (zfcp_allocate_low_mem_buffers(adapter)) | 508 | if (zfcp_allocate_low_mem_buffers(adapter)) |
540 | goto failed; | 509 | goto failed; |
541 | 510 | ||
542 | if (zfcp_reqlist_alloc(adapter)) | 511 | adapter->req_list = zfcp_reqlist_alloc(); |
512 | if (!adapter->req_list) | ||
543 | goto failed; | 513 | goto failed; |
544 | 514 | ||
545 | if (zfcp_dbf_adapter_register(adapter)) | 515 | if (zfcp_dbf_adapter_register(adapter)) |
@@ -560,8 +530,6 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
560 | INIT_LIST_HEAD(&adapter->erp_ready_head); | 530 | INIT_LIST_HEAD(&adapter->erp_ready_head); |
561 | INIT_LIST_HEAD(&adapter->erp_running_head); | 531 | INIT_LIST_HEAD(&adapter->erp_running_head); |
562 | 532 | ||
563 | spin_lock_init(&adapter->req_list_lock); | ||
564 | |||
565 | rwlock_init(&adapter->erp_lock); | 533 | rwlock_init(&adapter->erp_lock); |
566 | rwlock_init(&adapter->abort_lock); | 534 | rwlock_init(&adapter->abort_lock); |
567 | 535 | ||
@@ -640,8 +608,7 @@ void zfcp_device_unregister(struct device *dev, | |||
640 | 608 | ||
641 | static void zfcp_port_release(struct device *dev) | 609 | static void zfcp_port_release(struct device *dev) |
642 | { | 610 | { |
643 | struct zfcp_port *port = container_of(dev, struct zfcp_port, | 611 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); |
644 | sysfs_device); | ||
645 | 612 | ||
646 | zfcp_ccw_adapter_put(port->adapter); | 613 | zfcp_ccw_adapter_put(port->adapter); |
647 | kfree(port); | 614 | kfree(port); |
@@ -669,7 +636,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
669 | 636 | ||
670 | port = zfcp_get_port_by_wwpn(adapter, wwpn); | 637 | port = zfcp_get_port_by_wwpn(adapter, wwpn); |
671 | if (port) { | 638 | if (port) { |
672 | put_device(&port->sysfs_device); | 639 | put_device(&port->dev); |
673 | retval = -EEXIST; | 640 | retval = -EEXIST; |
674 | goto err_out; | 641 | goto err_out; |
675 | } | 642 | } |
@@ -689,22 +656,21 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
689 | port->d_id = d_id; | 656 | port->d_id = d_id; |
690 | port->wwpn = wwpn; | 657 | port->wwpn = wwpn; |
691 | port->rport_task = RPORT_NONE; | 658 | port->rport_task = RPORT_NONE; |
692 | port->sysfs_device.parent = &adapter->ccw_device->dev; | 659 | port->dev.parent = &adapter->ccw_device->dev; |
693 | port->sysfs_device.release = zfcp_port_release; | 660 | port->dev.release = zfcp_port_release; |
694 | 661 | ||
695 | if (dev_set_name(&port->sysfs_device, "0x%016llx", | 662 | if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) { |
696 | (unsigned long long)wwpn)) { | ||
697 | kfree(port); | 663 | kfree(port); |
698 | goto err_out; | 664 | goto err_out; |
699 | } | 665 | } |
700 | retval = -EINVAL; | 666 | retval = -EINVAL; |
701 | 667 | ||
702 | if (device_register(&port->sysfs_device)) { | 668 | if (device_register(&port->dev)) { |
703 | put_device(&port->sysfs_device); | 669 | put_device(&port->dev); |
704 | goto err_out; | 670 | goto err_out; |
705 | } | 671 | } |
706 | 672 | ||
707 | if (sysfs_create_group(&port->sysfs_device.kobj, | 673 | if (sysfs_create_group(&port->dev.kobj, |
708 | &zfcp_sysfs_port_attrs)) | 674 | &zfcp_sysfs_port_attrs)) |
709 | goto err_out_put; | 675 | goto err_out_put; |
710 | 676 | ||
@@ -717,7 +683,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
717 | return port; | 683 | return port; |
718 | 684 | ||
719 | err_out_put: | 685 | err_out_put: |
720 | device_unregister(&port->sysfs_device); | 686 | device_unregister(&port->dev); |
721 | err_out: | 687 | err_out: |
722 | zfcp_ccw_adapter_put(adapter); | 688 | zfcp_ccw_adapter_put(adapter); |
723 | return ERR_PTR(retval); | 689 | return ERR_PTR(retval); |
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index c22cb72a5ae8..ce1cc7a11fb4 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -3,13 +3,14 @@ | |||
3 | * | 3 | * |
4 | * Registration and callback for the s390 common I/O layer. | 4 | * Registration and callback for the s390 common I/O layer. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2002, 2009 | 6 | * Copyright IBM Corporation 2002, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
11 | 11 | ||
12 | #include "zfcp_ext.h" | 12 | #include "zfcp_ext.h" |
13 | #include "zfcp_reqlist.h" | ||
13 | 14 | ||
14 | #define ZFCP_MODEL_PRIV 0x4 | 15 | #define ZFCP_MODEL_PRIV 0x4 |
15 | 16 | ||
@@ -122,12 +123,10 @@ static void zfcp_ccw_remove(struct ccw_device *cdev) | |||
122 | zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */ | 123 | zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */ |
123 | 124 | ||
124 | list_for_each_entry_safe(unit, u, &unit_remove_lh, list) | 125 | list_for_each_entry_safe(unit, u, &unit_remove_lh, list) |
125 | zfcp_device_unregister(&unit->sysfs_device, | 126 | zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs); |
126 | &zfcp_sysfs_unit_attrs); | ||
127 | 127 | ||
128 | list_for_each_entry_safe(port, p, &port_remove_lh, list) | 128 | list_for_each_entry_safe(port, p, &port_remove_lh, list) |
129 | zfcp_device_unregister(&port->sysfs_device, | 129 | zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); |
130 | &zfcp_sysfs_port_attrs); | ||
131 | 130 | ||
132 | zfcp_adapter_unregister(adapter); | 131 | zfcp_adapter_unregister(adapter); |
133 | } | 132 | } |
@@ -162,7 +161,7 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev) | |||
162 | } | 161 | } |
163 | 162 | ||
164 | /* initialize request counter */ | 163 | /* initialize request counter */ |
165 | BUG_ON(!zfcp_reqlist_isempty(adapter)); | 164 | BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); |
166 | adapter->req_no = 0; | 165 | adapter->req_no = 0; |
167 | 166 | ||
168 | zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, | 167 | zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, |
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 7369c8911bcf..7a149fd85f6d 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -140,9 +140,9 @@ void _zfcp_dbf_hba_fsf_response(const char *tag2, int level, | |||
140 | memcpy(response->fsf_status_qual, | 140 | memcpy(response->fsf_status_qual, |
141 | fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE); | 141 | fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE); |
142 | response->fsf_req_status = fsf_req->status; | 142 | response->fsf_req_status = fsf_req->status; |
143 | response->sbal_first = fsf_req->queue_req.sbal_first; | 143 | response->sbal_first = fsf_req->qdio_req.sbal_first; |
144 | response->sbal_last = fsf_req->queue_req.sbal_last; | 144 | response->sbal_last = fsf_req->qdio_req.sbal_last; |
145 | response->sbal_response = fsf_req->queue_req.sbal_response; | 145 | response->sbal_response = fsf_req->qdio_req.sbal_response; |
146 | response->pool = fsf_req->pool != NULL; | 146 | response->pool = fsf_req->pool != NULL; |
147 | response->erp_action = (unsigned long)fsf_req->erp_action; | 147 | response->erp_action = (unsigned long)fsf_req->erp_action; |
148 | 148 | ||
@@ -576,7 +576,8 @@ void zfcp_dbf_rec_adapter(char *id, void *ref, struct zfcp_dbf *dbf) | |||
576 | struct zfcp_adapter *adapter = dbf->adapter; | 576 | struct zfcp_adapter *adapter = dbf->adapter; |
577 | 577 | ||
578 | zfcp_dbf_rec_target(id, ref, dbf, &adapter->status, | 578 | zfcp_dbf_rec_target(id, ref, dbf, &adapter->status, |
579 | &adapter->erp_counter, 0, 0, 0); | 579 | &adapter->erp_counter, 0, 0, |
580 | ZFCP_DBF_INVALID_LUN); | ||
580 | } | 581 | } |
581 | 582 | ||
582 | /** | 583 | /** |
@@ -590,8 +591,8 @@ void zfcp_dbf_rec_port(char *id, void *ref, struct zfcp_port *port) | |||
590 | struct zfcp_dbf *dbf = port->adapter->dbf; | 591 | struct zfcp_dbf *dbf = port->adapter->dbf; |
591 | 592 | ||
592 | zfcp_dbf_rec_target(id, ref, dbf, &port->status, | 593 | zfcp_dbf_rec_target(id, ref, dbf, &port->status, |
593 | &port->erp_counter, port->wwpn, port->d_id, | 594 | &port->erp_counter, port->wwpn, port->d_id, |
594 | 0); | 595 | ZFCP_DBF_INVALID_LUN); |
595 | } | 596 | } |
596 | 597 | ||
597 | /** | 598 | /** |
@@ -642,10 +643,9 @@ void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action, | |||
642 | r->u.trigger.ps = atomic_read(&port->status); | 643 | r->u.trigger.ps = atomic_read(&port->status); |
643 | r->u.trigger.wwpn = port->wwpn; | 644 | r->u.trigger.wwpn = port->wwpn; |
644 | } | 645 | } |
645 | if (unit) { | 646 | if (unit) |
646 | r->u.trigger.us = atomic_read(&unit->status); | 647 | r->u.trigger.us = atomic_read(&unit->status); |
647 | r->u.trigger.fcp_lun = unit->fcp_lun; | 648 | r->u.trigger.fcp_lun = unit ? unit->fcp_lun : ZFCP_DBF_INVALID_LUN; |
648 | } | ||
649 | debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r)); | 649 | debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r)); |
650 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | 650 | spin_unlock_irqrestore(&dbf->rec_lock, flags); |
651 | } | 651 | } |
@@ -668,7 +668,7 @@ void zfcp_dbf_rec_action(char *id2, struct zfcp_erp_action *erp_action) | |||
668 | r->u.action.action = (unsigned long)erp_action; | 668 | r->u.action.action = (unsigned long)erp_action; |
669 | r->u.action.status = erp_action->status; | 669 | r->u.action.status = erp_action->status; |
670 | r->u.action.step = erp_action->step; | 670 | r->u.action.step = erp_action->step; |
671 | r->u.action.fsf_req = (unsigned long)erp_action->fsf_req; | 671 | r->u.action.fsf_req = erp_action->fsf_req_id; |
672 | debug_event(dbf->rec, 5, r, sizeof(*r)); | 672 | debug_event(dbf->rec, 5, r, sizeof(*r)); |
673 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | 673 | spin_unlock_irqrestore(&dbf->rec_lock, flags); |
674 | } | 674 | } |
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 8b7fd9a1033e..457e046f2d28 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h | |||
@@ -30,6 +30,8 @@ | |||
30 | #define ZFCP_DBF_TAG_SIZE 4 | 30 | #define ZFCP_DBF_TAG_SIZE 4 |
31 | #define ZFCP_DBF_ID_SIZE 7 | 31 | #define ZFCP_DBF_ID_SIZE 7 |
32 | 32 | ||
33 | #define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull | ||
34 | |||
33 | struct zfcp_dbf_dump { | 35 | struct zfcp_dbf_dump { |
34 | u8 tag[ZFCP_DBF_TAG_SIZE]; | 36 | u8 tag[ZFCP_DBF_TAG_SIZE]; |
35 | u32 total_size; /* size of total dump data */ | 37 | u32 total_size; /* size of total dump data */ |
@@ -192,10 +194,10 @@ struct zfcp_dbf_san_record { | |||
192 | struct zfcp_dbf_san_record_ct_response ct_resp; | 194 | struct zfcp_dbf_san_record_ct_response ct_resp; |
193 | struct zfcp_dbf_san_record_els els; | 195 | struct zfcp_dbf_san_record_els els; |
194 | } u; | 196 | } u; |
195 | #define ZFCP_DBF_SAN_MAX_PAYLOAD 1024 | ||
196 | u8 payload[32]; | ||
197 | } __attribute__ ((packed)); | 197 | } __attribute__ ((packed)); |
198 | 198 | ||
199 | #define ZFCP_DBF_SAN_MAX_PAYLOAD 1024 | ||
200 | |||
199 | struct zfcp_dbf_scsi_record { | 201 | struct zfcp_dbf_scsi_record { |
200 | u8 tag[ZFCP_DBF_TAG_SIZE]; | 202 | u8 tag[ZFCP_DBF_TAG_SIZE]; |
201 | u8 tag2[ZFCP_DBF_TAG_SIZE]; | 203 | u8 tag2[ZFCP_DBF_TAG_SIZE]; |
@@ -301,17 +303,31 @@ void zfcp_dbf_scsi(const char *tag, const char *tag2, int level, | |||
301 | 303 | ||
302 | /** | 304 | /** |
303 | * zfcp_dbf_scsi_result - trace event for SCSI command completion | 305 | * zfcp_dbf_scsi_result - trace event for SCSI command completion |
304 | * @tag: tag indicating success or failure of SCSI command | 306 | * @dbf: adapter dbf trace |
305 | * @level: trace level applicable for this event | 307 | * @scmd: SCSI command pointer |
306 | * @adapter: adapter that has been used to issue the SCSI command | 308 | * @req: FSF request used to issue SCSI command |
309 | */ | ||
310 | static inline | ||
311 | void zfcp_dbf_scsi_result(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd, | ||
312 | struct zfcp_fsf_req *req) | ||
313 | { | ||
314 | if (scmd->result != 0) | ||
315 | zfcp_dbf_scsi("rslt", "erro", 3, dbf, scmd, req, 0); | ||
316 | else if (scmd->retries > 0) | ||
317 | zfcp_dbf_scsi("rslt", "retr", 4, dbf, scmd, req, 0); | ||
318 | else | ||
319 | zfcp_dbf_scsi("rslt", "norm", 6, dbf, scmd, req, 0); | ||
320 | } | ||
321 | |||
322 | /** | ||
323 | * zfcp_dbf_scsi_fail_send - trace event for failure to send SCSI command | ||
324 | * @dbf: adapter dbf trace | ||
307 | * @scmd: SCSI command pointer | 325 | * @scmd: SCSI command pointer |
308 | * @fsf_req: request used to issue SCSI command (might be NULL) | ||
309 | */ | 326 | */ |
310 | static inline | 327 | static inline |
311 | void zfcp_dbf_scsi_result(const char *tag, int level, struct zfcp_dbf *dbf, | 328 | void zfcp_dbf_scsi_fail_send(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd) |
312 | struct scsi_cmnd *scmd, struct zfcp_fsf_req *fsf_req) | ||
313 | { | 329 | { |
314 | zfcp_dbf_scsi("rslt", tag, level, dbf, scmd, fsf_req, 0); | 330 | zfcp_dbf_scsi("rslt", "fail", 4, dbf, scmd, NULL, 0); |
315 | } | 331 | } |
316 | 332 | ||
317 | /** | 333 | /** |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index e1b5b88e2ddb..7131c7db1f04 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Global definitions for the zfcp device driver. | 4 | * Global definitions for the zfcp device driver. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2002, 2009 | 6 | * Copyright IBM Corporation 2002, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef ZFCP_DEF_H | 9 | #ifndef ZFCP_DEF_H |
@@ -33,15 +33,13 @@ | |||
33 | #include <scsi/scsi_transport_fc.h> | 33 | #include <scsi/scsi_transport_fc.h> |
34 | #include <scsi/scsi_bsg_fc.h> | 34 | #include <scsi/scsi_bsg_fc.h> |
35 | #include <asm/ccwdev.h> | 35 | #include <asm/ccwdev.h> |
36 | #include <asm/qdio.h> | ||
37 | #include <asm/debug.h> | 36 | #include <asm/debug.h> |
38 | #include <asm/ebcdic.h> | 37 | #include <asm/ebcdic.h> |
39 | #include <asm/sysinfo.h> | 38 | #include <asm/sysinfo.h> |
40 | #include "zfcp_fsf.h" | 39 | #include "zfcp_fsf.h" |
40 | #include "zfcp_qdio.h" | ||
41 | 41 | ||
42 | /********************* GENERAL DEFINES *********************************/ | 42 | struct zfcp_reqlist; |
43 | |||
44 | #define REQUEST_LIST_SIZE 128 | ||
45 | 43 | ||
46 | /********************* SCSI SPECIFIC DEFINES *********************************/ | 44 | /********************* SCSI SPECIFIC DEFINES *********************************/ |
47 | #define ZFCP_SCSI_ER_TIMEOUT (10*HZ) | 45 | #define ZFCP_SCSI_ER_TIMEOUT (10*HZ) |
@@ -129,12 +127,6 @@ struct zfcp_adapter_mempool { | |||
129 | mempool_t *qtcb_pool; | 127 | mempool_t *qtcb_pool; |
130 | }; | 128 | }; |
131 | 129 | ||
132 | struct zfcp_qdio_queue { | ||
133 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; | ||
134 | u8 first; /* index of next free bfr in queue */ | ||
135 | atomic_t count; /* number of free buffers in queue */ | ||
136 | }; | ||
137 | |||
138 | struct zfcp_erp_action { | 130 | struct zfcp_erp_action { |
139 | struct list_head list; | 131 | struct list_head list; |
140 | int action; /* requested action code */ | 132 | int action; /* requested action code */ |
@@ -143,8 +135,7 @@ struct zfcp_erp_action { | |||
143 | struct zfcp_unit *unit; | 135 | struct zfcp_unit *unit; |
144 | u32 status; /* recovery status */ | 136 | u32 status; /* recovery status */ |
145 | u32 step; /* active step of this erp action */ | 137 | u32 step; /* active step of this erp action */ |
146 | struct zfcp_fsf_req *fsf_req; /* fsf request currently pending | 138 | unsigned long fsf_req_id; |
147 | for this action */ | ||
148 | struct timer_list timer; | 139 | struct timer_list timer; |
149 | }; | 140 | }; |
150 | 141 | ||
@@ -167,29 +158,6 @@ struct zfcp_latencies { | |||
167 | spinlock_t lock; | 158 | spinlock_t lock; |
168 | }; | 159 | }; |
169 | 160 | ||
170 | /** struct zfcp_qdio - basic QDIO data structure | ||
171 | * @resp_q: response queue | ||
172 | * @req_q: request queue | ||
173 | * @stat_lock: lock to protect req_q_util and req_q_time | ||
174 | * @req_q_lock; lock to serialize access to request queue | ||
175 | * @req_q_time: time of last fill level change | ||
176 | * @req_q_util: used for accounting | ||
177 | * @req_q_full: queue full incidents | ||
178 | * @req_q_wq: used to wait for SBAL availability | ||
179 | * @adapter: adapter used in conjunction with this QDIO structure | ||
180 | */ | ||
181 | struct zfcp_qdio { | ||
182 | struct zfcp_qdio_queue resp_q; | ||
183 | struct zfcp_qdio_queue req_q; | ||
184 | spinlock_t stat_lock; | ||
185 | spinlock_t req_q_lock; | ||
186 | unsigned long long req_q_time; | ||
187 | u64 req_q_util; | ||
188 | atomic_t req_q_full; | ||
189 | wait_queue_head_t req_q_wq; | ||
190 | struct zfcp_adapter *adapter; | ||
191 | }; | ||
192 | |||
193 | struct zfcp_adapter { | 161 | struct zfcp_adapter { |
194 | struct kref ref; | 162 | struct kref ref; |
195 | u64 peer_wwnn; /* P2P peer WWNN */ | 163 | u64 peer_wwnn; /* P2P peer WWNN */ |
@@ -207,8 +175,7 @@ struct zfcp_adapter { | |||
207 | struct list_head port_list; /* remote port list */ | 175 | struct list_head port_list; /* remote port list */ |
208 | rwlock_t port_list_lock; /* port list lock */ | 176 | rwlock_t port_list_lock; /* port list lock */ |
209 | unsigned long req_no; /* unique FSF req number */ | 177 | unsigned long req_no; /* unique FSF req number */ |
210 | struct list_head *req_list; /* list of pending reqs */ | 178 | struct zfcp_reqlist *req_list; |
211 | spinlock_t req_list_lock; /* request list lock */ | ||
212 | u32 fsf_req_seq_no; /* FSF cmnd seq number */ | 179 | u32 fsf_req_seq_no; /* FSF cmnd seq number */ |
213 | rwlock_t abort_lock; /* Protects against SCSI | 180 | rwlock_t abort_lock; /* Protects against SCSI |
214 | stack abort/command | 181 | stack abort/command |
@@ -241,7 +208,7 @@ struct zfcp_adapter { | |||
241 | }; | 208 | }; |
242 | 209 | ||
243 | struct zfcp_port { | 210 | struct zfcp_port { |
244 | struct device sysfs_device; /* sysfs device */ | 211 | struct device dev; |
245 | struct fc_rport *rport; /* rport of fc transport class */ | 212 | struct fc_rport *rport; /* rport of fc transport class */ |
246 | struct list_head list; /* list of remote ports */ | 213 | struct list_head list; /* list of remote ports */ |
247 | struct zfcp_adapter *adapter; /* adapter used to access port */ | 214 | struct zfcp_adapter *adapter; /* adapter used to access port */ |
@@ -263,7 +230,7 @@ struct zfcp_port { | |||
263 | }; | 230 | }; |
264 | 231 | ||
265 | struct zfcp_unit { | 232 | struct zfcp_unit { |
266 | struct device sysfs_device; /* sysfs device */ | 233 | struct device dev; |
267 | struct list_head list; /* list of logical units */ | 234 | struct list_head list; /* list of logical units */ |
268 | struct zfcp_port *port; /* remote port of unit */ | 235 | struct zfcp_port *port; /* remote port of unit */ |
269 | atomic_t status; /* status of this logical unit */ | 236 | atomic_t status; /* status of this logical unit */ |
@@ -277,33 +244,11 @@ struct zfcp_unit { | |||
277 | }; | 244 | }; |
278 | 245 | ||
279 | /** | 246 | /** |
280 | * struct zfcp_queue_req - queue related values for a request | ||
281 | * @sbal_number: number of free SBALs | ||
282 | * @sbal_first: first SBAL for this request | ||
283 | * @sbal_last: last SBAL for this request | ||
284 | * @sbal_limit: last possible SBAL for this request | ||
285 | * @sbale_curr: current SBALE at creation of this request | ||
286 | * @sbal_response: SBAL used in interrupt | ||
287 | * @qdio_outb_usage: usage of outbound queue | ||
288 | * @qdio_inb_usage: usage of inbound queue | ||
289 | */ | ||
290 | struct zfcp_queue_req { | ||
291 | u8 sbal_number; | ||
292 | u8 sbal_first; | ||
293 | u8 sbal_last; | ||
294 | u8 sbal_limit; | ||
295 | u8 sbale_curr; | ||
296 | u8 sbal_response; | ||
297 | u16 qdio_outb_usage; | ||
298 | u16 qdio_inb_usage; | ||
299 | }; | ||
300 | |||
301 | /** | ||
302 | * struct zfcp_fsf_req - basic FSF request structure | 247 | * struct zfcp_fsf_req - basic FSF request structure |
303 | * @list: list of FSF requests | 248 | * @list: list of FSF requests |
304 | * @req_id: unique request ID | 249 | * @req_id: unique request ID |
305 | * @adapter: adapter this request belongs to | 250 | * @adapter: adapter this request belongs to |
306 | * @queue_req: queue related values | 251 | * @qdio_req: qdio queue related values |
307 | * @completion: used to signal the completion of the request | 252 | * @completion: used to signal the completion of the request |
308 | * @status: status of the request | 253 | * @status: status of the request |
309 | * @fsf_command: FSF command issued | 254 | * @fsf_command: FSF command issued |
@@ -321,7 +266,7 @@ struct zfcp_fsf_req { | |||
321 | struct list_head list; | 266 | struct list_head list; |
322 | unsigned long req_id; | 267 | unsigned long req_id; |
323 | struct zfcp_adapter *adapter; | 268 | struct zfcp_adapter *adapter; |
324 | struct zfcp_queue_req queue_req; | 269 | struct zfcp_qdio_req qdio_req; |
325 | struct completion completion; | 270 | struct completion completion; |
326 | u32 status; | 271 | u32 status; |
327 | u32 fsf_command; | 272 | u32 fsf_command; |
@@ -352,45 +297,4 @@ struct zfcp_data { | |||
352 | #define ZFCP_SET 0x00000100 | 297 | #define ZFCP_SET 0x00000100 |
353 | #define ZFCP_CLEAR 0x00000200 | 298 | #define ZFCP_CLEAR 0x00000200 |
354 | 299 | ||
355 | /* | ||
356 | * Helper functions for request ID management. | ||
357 | */ | ||
358 | static inline int zfcp_reqlist_hash(unsigned long req_id) | ||
359 | { | ||
360 | return req_id % REQUEST_LIST_SIZE; | ||
361 | } | ||
362 | |||
363 | static inline void zfcp_reqlist_remove(struct zfcp_adapter *adapter, | ||
364 | struct zfcp_fsf_req *fsf_req) | ||
365 | { | ||
366 | list_del(&fsf_req->list); | ||
367 | } | ||
368 | |||
369 | static inline struct zfcp_fsf_req * | ||
370 | zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id) | ||
371 | { | ||
372 | struct zfcp_fsf_req *request; | ||
373 | unsigned int idx; | ||
374 | |||
375 | idx = zfcp_reqlist_hash(req_id); | ||
376 | list_for_each_entry(request, &adapter->req_list[idx], list) | ||
377 | if (request->req_id == req_id) | ||
378 | return request; | ||
379 | return NULL; | ||
380 | } | ||
381 | |||
382 | static inline struct zfcp_fsf_req * | ||
383 | zfcp_reqlist_find_safe(struct zfcp_adapter *adapter, struct zfcp_fsf_req *req) | ||
384 | { | ||
385 | struct zfcp_fsf_req *request; | ||
386 | unsigned int idx; | ||
387 | |||
388 | for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) { | ||
389 | list_for_each_entry(request, &adapter->req_list[idx], list) | ||
390 | if (request == req) | ||
391 | return request; | ||
392 | } | ||
393 | return NULL; | ||
394 | } | ||
395 | |||
396 | #endif /* ZFCP_DEF_H */ | 300 | #endif /* ZFCP_DEF_H */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index b51a11a82e63..0be5e7ea2828 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Error Recovery Procedures (ERP). | 4 | * Error Recovery Procedures (ERP). |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2002, 2009 | 6 | * Copyright IBM Corporation 2002, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
13 | #include "zfcp_ext.h" | 13 | #include "zfcp_ext.h" |
14 | #include "zfcp_reqlist.h" | ||
14 | 15 | ||
15 | #define ZFCP_MAX_ERPS 3 | 16 | #define ZFCP_MAX_ERPS 3 |
16 | 17 | ||
@@ -174,7 +175,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
174 | 175 | ||
175 | switch (need) { | 176 | switch (need) { |
176 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 177 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
177 | if (!get_device(&unit->sysfs_device)) | 178 | if (!get_device(&unit->dev)) |
178 | return NULL; | 179 | return NULL; |
179 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); | 180 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); |
180 | erp_action = &unit->erp_action; | 181 | erp_action = &unit->erp_action; |
@@ -184,7 +185,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, | |||
184 | 185 | ||
185 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 186 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
186 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 187 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
187 | if (!get_device(&port->sysfs_device)) | 188 | if (!get_device(&port->dev)) |
188 | return NULL; | 189 | return NULL; |
189 | zfcp_erp_action_dismiss_port(port); | 190 | zfcp_erp_action_dismiss_port(port); |
190 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); | 191 | atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); |
@@ -478,26 +479,27 @@ static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | |||
478 | static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) | 479 | static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) |
479 | { | 480 | { |
480 | struct zfcp_adapter *adapter = act->adapter; | 481 | struct zfcp_adapter *adapter = act->adapter; |
482 | struct zfcp_fsf_req *req; | ||
481 | 483 | ||
482 | if (!act->fsf_req) | 484 | if (!act->fsf_req_id) |
483 | return; | 485 | return; |
484 | 486 | ||
485 | spin_lock(&adapter->req_list_lock); | 487 | spin_lock(&adapter->req_list->lock); |
486 | if (zfcp_reqlist_find_safe(adapter, act->fsf_req) && | 488 | req = _zfcp_reqlist_find(adapter->req_list, act->fsf_req_id); |
487 | act->fsf_req->erp_action == act) { | 489 | if (req && req->erp_action == act) { |
488 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | | 490 | if (act->status & (ZFCP_STATUS_ERP_DISMISSED | |
489 | ZFCP_STATUS_ERP_TIMEDOUT)) { | 491 | ZFCP_STATUS_ERP_TIMEDOUT)) { |
490 | act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; | 492 | req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; |
491 | zfcp_dbf_rec_action("erscf_1", act); | 493 | zfcp_dbf_rec_action("erscf_1", act); |
492 | act->fsf_req->erp_action = NULL; | 494 | req->erp_action = NULL; |
493 | } | 495 | } |
494 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) | 496 | if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) |
495 | zfcp_dbf_rec_action("erscf_2", act); | 497 | zfcp_dbf_rec_action("erscf_2", act); |
496 | if (act->fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) | 498 | if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) |
497 | act->fsf_req = NULL; | 499 | act->fsf_req_id = 0; |
498 | } else | 500 | } else |
499 | act->fsf_req = NULL; | 501 | act->fsf_req_id = 0; |
500 | spin_unlock(&adapter->req_list_lock); | 502 | spin_unlock(&adapter->req_list->lock); |
501 | } | 503 | } |
502 | 504 | ||
503 | /** | 505 | /** |
@@ -1179,19 +1181,19 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) | |||
1179 | switch (act->action) { | 1181 | switch (act->action) { |
1180 | case ZFCP_ERP_ACTION_REOPEN_UNIT: | 1182 | case ZFCP_ERP_ACTION_REOPEN_UNIT: |
1181 | if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { | 1183 | if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { |
1182 | get_device(&unit->sysfs_device); | 1184 | get_device(&unit->dev); |
1183 | if (scsi_queue_work(unit->port->adapter->scsi_host, | 1185 | if (scsi_queue_work(unit->port->adapter->scsi_host, |
1184 | &unit->scsi_work) <= 0) | 1186 | &unit->scsi_work) <= 0) |
1185 | put_device(&unit->sysfs_device); | 1187 | put_device(&unit->dev); |
1186 | } | 1188 | } |
1187 | put_device(&unit->sysfs_device); | 1189 | put_device(&unit->dev); |
1188 | break; | 1190 | break; |
1189 | 1191 | ||
1190 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1192 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
1191 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1193 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
1192 | if (result == ZFCP_ERP_SUCCEEDED) | 1194 | if (result == ZFCP_ERP_SUCCEEDED) |
1193 | zfcp_scsi_schedule_rport_register(port); | 1195 | zfcp_scsi_schedule_rport_register(port); |
1194 | put_device(&port->sysfs_device); | 1196 | put_device(&port->dev); |
1195 | break; | 1197 | break; |
1196 | 1198 | ||
1197 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 1199 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 66bdb34143cb..8786a79c7f8f 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -21,7 +21,6 @@ extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); | |||
21 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, | 21 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, |
22 | u32); | 22 | u32); |
23 | extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); | 23 | extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); |
24 | extern int zfcp_reqlist_isempty(struct zfcp_adapter *); | ||
25 | extern void zfcp_sg_free_table(struct scatterlist *, int); | 24 | extern void zfcp_sg_free_table(struct scatterlist *, int); |
26 | extern int zfcp_sg_setup_table(struct scatterlist *, int); | 25 | extern int zfcp_sg_setup_table(struct scatterlist *, int); |
27 | extern void zfcp_device_unregister(struct device *, | 26 | extern void zfcp_device_unregister(struct device *, |
@@ -144,13 +143,9 @@ extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int); | |||
144 | /* zfcp_qdio.c */ | 143 | /* zfcp_qdio.c */ |
145 | extern int zfcp_qdio_setup(struct zfcp_adapter *); | 144 | extern int zfcp_qdio_setup(struct zfcp_adapter *); |
146 | extern void zfcp_qdio_destroy(struct zfcp_qdio *); | 145 | extern void zfcp_qdio_destroy(struct zfcp_qdio *); |
147 | extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_queue_req *); | 146 | extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_qdio_req *); |
148 | extern struct qdio_buffer_element | ||
149 | *zfcp_qdio_sbale_req(struct zfcp_qdio *, struct zfcp_queue_req *); | ||
150 | extern struct qdio_buffer_element | ||
151 | *zfcp_qdio_sbale_curr(struct zfcp_qdio *, struct zfcp_queue_req *); | ||
152 | extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, | 147 | extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, |
153 | struct zfcp_queue_req *, unsigned long, | 148 | struct zfcp_qdio_req *, unsigned long, |
154 | struct scatterlist *, int); | 149 | struct scatterlist *, int); |
155 | extern int zfcp_qdio_open(struct zfcp_qdio *); | 150 | extern int zfcp_qdio_open(struct zfcp_qdio *); |
156 | extern void zfcp_qdio_close(struct zfcp_qdio *); | 151 | extern void zfcp_qdio_close(struct zfcp_qdio *); |
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 271399f62f1b..5219670f0c99 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Fibre Channel related functions for the zfcp device driver. | 4 | * Fibre Channel related functions for the zfcp device driver. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2008, 2009 | 6 | * Copyright IBM Corporation 2008, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
@@ -316,7 +316,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work) | |||
316 | 316 | ||
317 | zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL); | 317 | zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL); |
318 | out: | 318 | out: |
319 | put_device(&port->sysfs_device); | 319 | put_device(&port->dev); |
320 | } | 320 | } |
321 | 321 | ||
322 | /** | 322 | /** |
@@ -325,9 +325,9 @@ out: | |||
325 | */ | 325 | */ |
326 | void zfcp_fc_trigger_did_lookup(struct zfcp_port *port) | 326 | void zfcp_fc_trigger_did_lookup(struct zfcp_port *port) |
327 | { | 327 | { |
328 | get_device(&port->sysfs_device); | 328 | get_device(&port->dev); |
329 | if (!queue_work(port->adapter->work_queue, &port->gid_pn_work)) | 329 | if (!queue_work(port->adapter->work_queue, &port->gid_pn_work)) |
330 | put_device(&port->sysfs_device); | 330 | put_device(&port->dev); |
331 | } | 331 | } |
332 | 332 | ||
333 | /** | 333 | /** |
@@ -389,7 +389,7 @@ static void zfcp_fc_adisc_handler(void *data) | |||
389 | zfcp_scsi_schedule_rport_register(port); | 389 | zfcp_scsi_schedule_rport_register(port); |
390 | out: | 390 | out: |
391 | atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status); | 391 | atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status); |
392 | put_device(&port->sysfs_device); | 392 | put_device(&port->dev); |
393 | kmem_cache_free(zfcp_data.adisc_cache, adisc); | 393 | kmem_cache_free(zfcp_data.adisc_cache, adisc); |
394 | } | 394 | } |
395 | 395 | ||
@@ -436,7 +436,7 @@ void zfcp_fc_link_test_work(struct work_struct *work) | |||
436 | container_of(work, struct zfcp_port, test_link_work); | 436 | container_of(work, struct zfcp_port, test_link_work); |
437 | int retval; | 437 | int retval; |
438 | 438 | ||
439 | get_device(&port->sysfs_device); | 439 | get_device(&port->dev); |
440 | port->rport_task = RPORT_DEL; | 440 | port->rport_task = RPORT_DEL; |
441 | zfcp_scsi_rport_work(&port->rport_work); | 441 | zfcp_scsi_rport_work(&port->rport_work); |
442 | 442 | ||
@@ -455,7 +455,7 @@ void zfcp_fc_link_test_work(struct work_struct *work) | |||
455 | zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL); | 455 | zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL); |
456 | 456 | ||
457 | out: | 457 | out: |
458 | put_device(&port->sysfs_device); | 458 | put_device(&port->dev); |
459 | } | 459 | } |
460 | 460 | ||
461 | /** | 461 | /** |
@@ -468,9 +468,9 @@ out: | |||
468 | */ | 468 | */ |
469 | void zfcp_fc_test_link(struct zfcp_port *port) | 469 | void zfcp_fc_test_link(struct zfcp_port *port) |
470 | { | 470 | { |
471 | get_device(&port->sysfs_device); | 471 | get_device(&port->dev); |
472 | if (!queue_work(port->adapter->work_queue, &port->test_link_work)) | 472 | if (!queue_work(port->adapter->work_queue, &port->test_link_work)) |
473 | put_device(&port->sysfs_device); | 473 | put_device(&port->dev); |
474 | } | 474 | } |
475 | 475 | ||
476 | static void zfcp_free_sg_env(struct zfcp_fc_gpn_ft *gpn_ft, int buf_num) | 476 | static void zfcp_free_sg_env(struct zfcp_fc_gpn_ft *gpn_ft, int buf_num) |
@@ -617,8 +617,7 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, | |||
617 | 617 | ||
618 | list_for_each_entry_safe(port, tmp, &remove_lh, list) { | 618 | list_for_each_entry_safe(port, tmp, &remove_lh, list) { |
619 | zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL); | 619 | zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL); |
620 | zfcp_device_unregister(&port->sysfs_device, | 620 | zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); |
621 | &zfcp_sysfs_port_attrs); | ||
622 | } | 621 | } |
623 | 622 | ||
624 | return ret; | 623 | return ret; |
@@ -731,7 +730,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job, | |||
731 | return -EINVAL; | 730 | return -EINVAL; |
732 | 731 | ||
733 | d_id = port->d_id; | 732 | d_id = port->d_id; |
734 | put_device(&port->sysfs_device); | 733 | put_device(&port->dev); |
735 | } else | 734 | } else |
736 | d_id = ntoh24(job->request->rqst_data.h_els.port_id); | 735 | d_id = ntoh24(job->request->rqst_data.h_els.port_id); |
737 | 736 | ||
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index e8fb4d9baa8b..6538742b421a 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Implementation of FSF commands. | 4 | * Implementation of FSF commands. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2002, 2009 | 6 | * Copyright IBM Corporation 2002, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
@@ -14,6 +14,8 @@ | |||
14 | #include "zfcp_ext.h" | 14 | #include "zfcp_ext.h" |
15 | #include "zfcp_fc.h" | 15 | #include "zfcp_fc.h" |
16 | #include "zfcp_dbf.h" | 16 | #include "zfcp_dbf.h" |
17 | #include "zfcp_qdio.h" | ||
18 | #include "zfcp_reqlist.h" | ||
17 | 19 | ||
18 | static void zfcp_fsf_request_timeout_handler(unsigned long data) | 20 | static void zfcp_fsf_request_timeout_handler(unsigned long data) |
19 | { | 21 | { |
@@ -393,7 +395,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) | |||
393 | case FSF_PROT_LINK_DOWN: | 395 | case FSF_PROT_LINK_DOWN: |
394 | zfcp_fsf_link_down_info_eval(req, "fspse_5", | 396 | zfcp_fsf_link_down_info_eval(req, "fspse_5", |
395 | &psq->link_down_info); | 397 | &psq->link_down_info); |
396 | /* FIXME: reopening adapter now? better wait for link up */ | 398 | /* go through reopen to flush pending requests */ |
397 | zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req); | 399 | zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req); |
398 | break; | 400 | break; |
399 | case FSF_PROT_REEST_QUEUE: | 401 | case FSF_PROT_REEST_QUEUE: |
@@ -457,15 +459,10 @@ static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) | |||
457 | void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) | 459 | void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) |
458 | { | 460 | { |
459 | struct zfcp_fsf_req *req, *tmp; | 461 | struct zfcp_fsf_req *req, *tmp; |
460 | unsigned long flags; | ||
461 | LIST_HEAD(remove_queue); | 462 | LIST_HEAD(remove_queue); |
462 | unsigned int i; | ||
463 | 463 | ||
464 | BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP); | 464 | BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP); |
465 | spin_lock_irqsave(&adapter->req_list_lock, flags); | 465 | zfcp_reqlist_move(adapter->req_list, &remove_queue); |
466 | for (i = 0; i < REQUEST_LIST_SIZE; i++) | ||
467 | list_splice_init(&adapter->req_list[i], &remove_queue); | ||
468 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
469 | 466 | ||
470 | list_for_each_entry_safe(req, tmp, &remove_queue, list) { | 467 | list_for_each_entry_safe(req, tmp, &remove_queue, list) { |
471 | list_del(&req->list); | 468 | list_del(&req->list); |
@@ -495,8 +492,6 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) | |||
495 | fc_host_port_id(shost) = ntoh24(bottom->s_id); | 492 | fc_host_port_id(shost) = ntoh24(bottom->s_id); |
496 | fc_host_speed(shost) = bottom->fc_link_speed; | 493 | fc_host_speed(shost) = bottom->fc_link_speed; |
497 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; | 494 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; |
498 | fc_host_supported_fc4s(shost)[2] = 1; /* FCP */ | ||
499 | fc_host_active_fc4s(shost)[2] = 1; /* FCP */ | ||
500 | 495 | ||
501 | adapter->hydra_version = bottom->adapter_type; | 496 | adapter->hydra_version = bottom->adapter_type; |
502 | adapter->timer_ticks = bottom->timer_interval; | 497 | adapter->timer_ticks = bottom->timer_interval; |
@@ -619,6 +614,10 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) | |||
619 | fc_host_permanent_port_name(shost) = fc_host_port_name(shost); | 614 | fc_host_permanent_port_name(shost) = fc_host_port_name(shost); |
620 | fc_host_maxframe_size(shost) = bottom->maximum_frame_size; | 615 | fc_host_maxframe_size(shost) = bottom->maximum_frame_size; |
621 | fc_host_supported_speeds(shost) = bottom->supported_speed; | 616 | fc_host_supported_speeds(shost) = bottom->supported_speed; |
617 | memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, | ||
618 | FC_FC4_LIST_SIZE); | ||
619 | memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, | ||
620 | FC_FC4_LIST_SIZE); | ||
622 | } | 621 | } |
623 | 622 | ||
624 | static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) | 623 | static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) |
@@ -725,12 +724,12 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio, | |||
725 | req->adapter = adapter; | 724 | req->adapter = adapter; |
726 | req->fsf_command = fsf_cmd; | 725 | req->fsf_command = fsf_cmd; |
727 | req->req_id = adapter->req_no; | 726 | req->req_id = adapter->req_no; |
728 | req->queue_req.sbal_number = 1; | 727 | req->qdio_req.sbal_number = 1; |
729 | req->queue_req.sbal_first = req_q->first; | 728 | req->qdio_req.sbal_first = req_q->first; |
730 | req->queue_req.sbal_last = req_q->first; | 729 | req->qdio_req.sbal_last = req_q->first; |
731 | req->queue_req.sbale_curr = 1; | 730 | req->qdio_req.sbale_curr = 1; |
732 | 731 | ||
733 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 732 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
734 | sbale[0].addr = (void *) req->req_id; | 733 | sbale[0].addr = (void *) req->req_id; |
735 | sbale[0].flags |= SBAL_FLAGS0_COMMAND; | 734 | sbale[0].flags |= SBAL_FLAGS0_COMMAND; |
736 | 735 | ||
@@ -745,6 +744,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio, | |||
745 | return ERR_PTR(-ENOMEM); | 744 | return ERR_PTR(-ENOMEM); |
746 | } | 745 | } |
747 | 746 | ||
747 | req->seq_no = adapter->fsf_req_seq_no; | ||
748 | req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; | 748 | req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; |
749 | req->qtcb->prefix.req_id = req->req_id; | 749 | req->qtcb->prefix.req_id = req->req_id; |
750 | req->qtcb->prefix.ulp_info = 26; | 750 | req->qtcb->prefix.ulp_info = 26; |
@@ -752,8 +752,6 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio, | |||
752 | req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION; | 752 | req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION; |
753 | req->qtcb->header.req_handle = req->req_id; | 753 | req->qtcb->header.req_handle = req->req_id; |
754 | req->qtcb->header.fsf_command = req->fsf_command; | 754 | req->qtcb->header.fsf_command = req->fsf_command; |
755 | req->seq_no = adapter->fsf_req_seq_no; | ||
756 | req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; | ||
757 | sbale[1].addr = (void *) req->qtcb; | 755 | sbale[1].addr = (void *) req->qtcb; |
758 | sbale[1].length = sizeof(struct fsf_qtcb); | 756 | sbale[1].length = sizeof(struct fsf_qtcb); |
759 | } | 757 | } |
@@ -770,25 +768,17 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) | |||
770 | { | 768 | { |
771 | struct zfcp_adapter *adapter = req->adapter; | 769 | struct zfcp_adapter *adapter = req->adapter; |
772 | struct zfcp_qdio *qdio = adapter->qdio; | 770 | struct zfcp_qdio *qdio = adapter->qdio; |
773 | unsigned long flags; | 771 | int with_qtcb = (req->qtcb != NULL); |
774 | int idx; | 772 | int req_id = req->req_id; |
775 | int with_qtcb = (req->qtcb != NULL); | ||
776 | 773 | ||
777 | /* put allocated FSF request into hash table */ | 774 | zfcp_reqlist_add(adapter->req_list, req); |
778 | spin_lock_irqsave(&adapter->req_list_lock, flags); | ||
779 | idx = zfcp_reqlist_hash(req->req_id); | ||
780 | list_add_tail(&req->list, &adapter->req_list[idx]); | ||
781 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
782 | 775 | ||
783 | req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count); | 776 | req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q.count); |
784 | req->issued = get_clock(); | 777 | req->issued = get_clock(); |
785 | if (zfcp_qdio_send(qdio, &req->queue_req)) { | 778 | if (zfcp_qdio_send(qdio, &req->qdio_req)) { |
786 | del_timer(&req->timer); | 779 | del_timer(&req->timer); |
787 | spin_lock_irqsave(&adapter->req_list_lock, flags); | ||
788 | /* lookup request again, list might have changed */ | 780 | /* lookup request again, list might have changed */ |
789 | if (zfcp_reqlist_find_safe(adapter, req)) | 781 | zfcp_reqlist_find_rm(adapter->req_list, req_id); |
790 | zfcp_reqlist_remove(adapter, req); | ||
791 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
792 | zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req); | 782 | zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req); |
793 | return -EIO; | 783 | return -EIO; |
794 | } | 784 | } |
@@ -826,9 +816,9 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) | |||
826 | goto out; | 816 | goto out; |
827 | } | 817 | } |
828 | 818 | ||
829 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 819 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
830 | sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY; | 820 | sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY; |
831 | req->queue_req.sbale_curr = 2; | 821 | req->qdio_req.sbale_curr = 2; |
832 | 822 | ||
833 | sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC); | 823 | sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC); |
834 | if (!sr_buf) { | 824 | if (!sr_buf) { |
@@ -837,7 +827,7 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) | |||
837 | } | 827 | } |
838 | memset(sr_buf, 0, sizeof(*sr_buf)); | 828 | memset(sr_buf, 0, sizeof(*sr_buf)); |
839 | req->data = sr_buf; | 829 | req->data = sr_buf; |
840 | sbale = zfcp_qdio_sbale_curr(qdio, &req->queue_req); | 830 | sbale = zfcp_qdio_sbale_curr(qdio, &req->qdio_req); |
841 | sbale->addr = (void *) sr_buf; | 831 | sbale->addr = (void *) sr_buf; |
842 | sbale->length = sizeof(*sr_buf); | 832 | sbale->length = sizeof(*sr_buf); |
843 | 833 | ||
@@ -934,7 +924,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, | |||
934 | ZFCP_STATUS_COMMON_UNBLOCKED))) | 924 | ZFCP_STATUS_COMMON_UNBLOCKED))) |
935 | goto out_error_free; | 925 | goto out_error_free; |
936 | 926 | ||
937 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 927 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
938 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 928 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
939 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 929 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
940 | 930 | ||
@@ -1029,7 +1019,7 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, | |||
1029 | { | 1019 | { |
1030 | struct zfcp_adapter *adapter = req->adapter; | 1020 | struct zfcp_adapter *adapter = req->adapter; |
1031 | struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio, | 1021 | struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio, |
1032 | &req->queue_req); | 1022 | &req->qdio_req); |
1033 | u32 feat = adapter->adapter_features; | 1023 | u32 feat = adapter->adapter_features; |
1034 | int bytes; | 1024 | int bytes; |
1035 | 1025 | ||
@@ -1047,15 +1037,15 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, | |||
1047 | return 0; | 1037 | return 0; |
1048 | } | 1038 | } |
1049 | 1039 | ||
1050 | bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req, | 1040 | bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, |
1051 | SBAL_FLAGS0_TYPE_WRITE_READ, | 1041 | SBAL_FLAGS0_TYPE_WRITE_READ, |
1052 | sg_req, max_sbals); | 1042 | sg_req, max_sbals); |
1053 | if (bytes <= 0) | 1043 | if (bytes <= 0) |
1054 | return -EIO; | 1044 | return -EIO; |
1055 | req->qtcb->bottom.support.req_buf_length = bytes; | 1045 | req->qtcb->bottom.support.req_buf_length = bytes; |
1056 | req->queue_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; | 1046 | req->qdio_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; |
1057 | 1047 | ||
1058 | bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req, | 1048 | bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, |
1059 | SBAL_FLAGS0_TYPE_WRITE_READ, | 1049 | SBAL_FLAGS0_TYPE_WRITE_READ, |
1060 | sg_resp, max_sbals); | 1050 | sg_resp, max_sbals); |
1061 | req->qtcb->bottom.support.resp_buf_length = bytes; | 1051 | req->qtcb->bottom.support.resp_buf_length = bytes; |
@@ -1251,7 +1241,7 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
1251 | } | 1241 | } |
1252 | 1242 | ||
1253 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 1243 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
1254 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1244 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1255 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1245 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1256 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1246 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1257 | 1247 | ||
@@ -1262,13 +1252,13 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
1262 | FSF_FEATURE_UPDATE_ALERT; | 1252 | FSF_FEATURE_UPDATE_ALERT; |
1263 | req->erp_action = erp_action; | 1253 | req->erp_action = erp_action; |
1264 | req->handler = zfcp_fsf_exchange_config_data_handler; | 1254 | req->handler = zfcp_fsf_exchange_config_data_handler; |
1265 | erp_action->fsf_req = req; | 1255 | erp_action->fsf_req_id = req->req_id; |
1266 | 1256 | ||
1267 | zfcp_fsf_start_erp_timer(req); | 1257 | zfcp_fsf_start_erp_timer(req); |
1268 | retval = zfcp_fsf_req_send(req); | 1258 | retval = zfcp_fsf_req_send(req); |
1269 | if (retval) { | 1259 | if (retval) { |
1270 | zfcp_fsf_req_free(req); | 1260 | zfcp_fsf_req_free(req); |
1271 | erp_action->fsf_req = NULL; | 1261 | erp_action->fsf_req_id = 0; |
1272 | } | 1262 | } |
1273 | out: | 1263 | out: |
1274 | spin_unlock_bh(&qdio->req_q_lock); | 1264 | spin_unlock_bh(&qdio->req_q_lock); |
@@ -1293,7 +1283,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio, | |||
1293 | goto out_unlock; | 1283 | goto out_unlock; |
1294 | } | 1284 | } |
1295 | 1285 | ||
1296 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1286 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1297 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1287 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1298 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1288 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1299 | req->handler = zfcp_fsf_exchange_config_data_handler; | 1289 | req->handler = zfcp_fsf_exchange_config_data_handler; |
@@ -1349,19 +1339,19 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) | |||
1349 | } | 1339 | } |
1350 | 1340 | ||
1351 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 1341 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
1352 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1342 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1353 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1343 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1354 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1344 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1355 | 1345 | ||
1356 | req->handler = zfcp_fsf_exchange_port_data_handler; | 1346 | req->handler = zfcp_fsf_exchange_port_data_handler; |
1357 | req->erp_action = erp_action; | 1347 | req->erp_action = erp_action; |
1358 | erp_action->fsf_req = req; | 1348 | erp_action->fsf_req_id = req->req_id; |
1359 | 1349 | ||
1360 | zfcp_fsf_start_erp_timer(req); | 1350 | zfcp_fsf_start_erp_timer(req); |
1361 | retval = zfcp_fsf_req_send(req); | 1351 | retval = zfcp_fsf_req_send(req); |
1362 | if (retval) { | 1352 | if (retval) { |
1363 | zfcp_fsf_req_free(req); | 1353 | zfcp_fsf_req_free(req); |
1364 | erp_action->fsf_req = NULL; | 1354 | erp_action->fsf_req_id = 0; |
1365 | } | 1355 | } |
1366 | out: | 1356 | out: |
1367 | spin_unlock_bh(&qdio->req_q_lock); | 1357 | spin_unlock_bh(&qdio->req_q_lock); |
@@ -1398,7 +1388,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio, | |||
1398 | if (data) | 1388 | if (data) |
1399 | req->data = data; | 1389 | req->data = data; |
1400 | 1390 | ||
1401 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1391 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1402 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1392 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1403 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1393 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1404 | 1394 | ||
@@ -1484,7 +1474,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1484 | } | 1474 | } |
1485 | 1475 | ||
1486 | out: | 1476 | out: |
1487 | put_device(&port->sysfs_device); | 1477 | put_device(&port->dev); |
1488 | } | 1478 | } |
1489 | 1479 | ||
1490 | /** | 1480 | /** |
@@ -1513,7 +1503,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
1513 | } | 1503 | } |
1514 | 1504 | ||
1515 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 1505 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
1516 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1506 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1517 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1507 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1518 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1508 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1519 | 1509 | ||
@@ -1521,15 +1511,15 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
1521 | hton24(req->qtcb->bottom.support.d_id, port->d_id); | 1511 | hton24(req->qtcb->bottom.support.d_id, port->d_id); |
1522 | req->data = port; | 1512 | req->data = port; |
1523 | req->erp_action = erp_action; | 1513 | req->erp_action = erp_action; |
1524 | erp_action->fsf_req = req; | 1514 | erp_action->fsf_req_id = req->req_id; |
1525 | get_device(&port->sysfs_device); | 1515 | get_device(&port->dev); |
1526 | 1516 | ||
1527 | zfcp_fsf_start_erp_timer(req); | 1517 | zfcp_fsf_start_erp_timer(req); |
1528 | retval = zfcp_fsf_req_send(req); | 1518 | retval = zfcp_fsf_req_send(req); |
1529 | if (retval) { | 1519 | if (retval) { |
1530 | zfcp_fsf_req_free(req); | 1520 | zfcp_fsf_req_free(req); |
1531 | erp_action->fsf_req = NULL; | 1521 | erp_action->fsf_req_id = 0; |
1532 | put_device(&port->sysfs_device); | 1522 | put_device(&port->dev); |
1533 | } | 1523 | } |
1534 | out: | 1524 | out: |
1535 | spin_unlock_bh(&qdio->req_q_lock); | 1525 | spin_unlock_bh(&qdio->req_q_lock); |
@@ -1583,7 +1573,7 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
1583 | } | 1573 | } |
1584 | 1574 | ||
1585 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 1575 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
1586 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1576 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1587 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1577 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1588 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1578 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1589 | 1579 | ||
@@ -1591,13 +1581,13 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
1591 | req->data = erp_action->port; | 1581 | req->data = erp_action->port; |
1592 | req->erp_action = erp_action; | 1582 | req->erp_action = erp_action; |
1593 | req->qtcb->header.port_handle = erp_action->port->handle; | 1583 | req->qtcb->header.port_handle = erp_action->port->handle; |
1594 | erp_action->fsf_req = req; | 1584 | erp_action->fsf_req_id = req->req_id; |
1595 | 1585 | ||
1596 | zfcp_fsf_start_erp_timer(req); | 1586 | zfcp_fsf_start_erp_timer(req); |
1597 | retval = zfcp_fsf_req_send(req); | 1587 | retval = zfcp_fsf_req_send(req); |
1598 | if (retval) { | 1588 | if (retval) { |
1599 | zfcp_fsf_req_free(req); | 1589 | zfcp_fsf_req_free(req); |
1600 | erp_action->fsf_req = NULL; | 1590 | erp_action->fsf_req_id = 0; |
1601 | } | 1591 | } |
1602 | out: | 1592 | out: |
1603 | spin_unlock_bh(&qdio->req_q_lock); | 1593 | spin_unlock_bh(&qdio->req_q_lock); |
@@ -1660,7 +1650,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port) | |||
1660 | } | 1650 | } |
1661 | 1651 | ||
1662 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 1652 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
1663 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1653 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1664 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1654 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1665 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1655 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1666 | 1656 | ||
@@ -1715,7 +1705,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port) | |||
1715 | } | 1705 | } |
1716 | 1706 | ||
1717 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 1707 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
1718 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1708 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1719 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1709 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1720 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1710 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1721 | 1711 | ||
@@ -1809,7 +1799,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
1809 | } | 1799 | } |
1810 | 1800 | ||
1811 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 1801 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
1812 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1802 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1813 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1803 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1814 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1804 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1815 | 1805 | ||
@@ -1817,13 +1807,13 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
1817 | req->qtcb->header.port_handle = erp_action->port->handle; | 1807 | req->qtcb->header.port_handle = erp_action->port->handle; |
1818 | req->erp_action = erp_action; | 1808 | req->erp_action = erp_action; |
1819 | req->handler = zfcp_fsf_close_physical_port_handler; | 1809 | req->handler = zfcp_fsf_close_physical_port_handler; |
1820 | erp_action->fsf_req = req; | 1810 | erp_action->fsf_req_id = req->req_id; |
1821 | 1811 | ||
1822 | zfcp_fsf_start_erp_timer(req); | 1812 | zfcp_fsf_start_erp_timer(req); |
1823 | retval = zfcp_fsf_req_send(req); | 1813 | retval = zfcp_fsf_req_send(req); |
1824 | if (retval) { | 1814 | if (retval) { |
1825 | zfcp_fsf_req_free(req); | 1815 | zfcp_fsf_req_free(req); |
1826 | erp_action->fsf_req = NULL; | 1816 | erp_action->fsf_req_id = 0; |
1827 | } | 1817 | } |
1828 | out: | 1818 | out: |
1829 | spin_unlock_bh(&qdio->req_q_lock); | 1819 | spin_unlock_bh(&qdio->req_q_lock); |
@@ -1982,7 +1972,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
1982 | } | 1972 | } |
1983 | 1973 | ||
1984 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 1974 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
1985 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 1975 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
1986 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1976 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1987 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1977 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1988 | 1978 | ||
@@ -1991,7 +1981,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
1991 | req->handler = zfcp_fsf_open_unit_handler; | 1981 | req->handler = zfcp_fsf_open_unit_handler; |
1992 | req->data = erp_action->unit; | 1982 | req->data = erp_action->unit; |
1993 | req->erp_action = erp_action; | 1983 | req->erp_action = erp_action; |
1994 | erp_action->fsf_req = req; | 1984 | erp_action->fsf_req_id = req->req_id; |
1995 | 1985 | ||
1996 | if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) | 1986 | if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) |
1997 | req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING; | 1987 | req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING; |
@@ -2000,7 +1990,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
2000 | retval = zfcp_fsf_req_send(req); | 1990 | retval = zfcp_fsf_req_send(req); |
2001 | if (retval) { | 1991 | if (retval) { |
2002 | zfcp_fsf_req_free(req); | 1992 | zfcp_fsf_req_free(req); |
2003 | erp_action->fsf_req = NULL; | 1993 | erp_action->fsf_req_id = 0; |
2004 | } | 1994 | } |
2005 | out: | 1995 | out: |
2006 | spin_unlock_bh(&qdio->req_q_lock); | 1996 | spin_unlock_bh(&qdio->req_q_lock); |
@@ -2068,7 +2058,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
2068 | } | 2058 | } |
2069 | 2059 | ||
2070 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 2060 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
2071 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 2061 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
2072 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 2062 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
2073 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 2063 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
2074 | 2064 | ||
@@ -2077,13 +2067,13 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
2077 | req->handler = zfcp_fsf_close_unit_handler; | 2067 | req->handler = zfcp_fsf_close_unit_handler; |
2078 | req->data = erp_action->unit; | 2068 | req->data = erp_action->unit; |
2079 | req->erp_action = erp_action; | 2069 | req->erp_action = erp_action; |
2080 | erp_action->fsf_req = req; | 2070 | erp_action->fsf_req_id = req->req_id; |
2081 | 2071 | ||
2082 | zfcp_fsf_start_erp_timer(req); | 2072 | zfcp_fsf_start_erp_timer(req); |
2083 | retval = zfcp_fsf_req_send(req); | 2073 | retval = zfcp_fsf_req_send(req); |
2084 | if (retval) { | 2074 | if (retval) { |
2085 | zfcp_fsf_req_free(req); | 2075 | zfcp_fsf_req_free(req); |
2086 | erp_action->fsf_req = NULL; | 2076 | erp_action->fsf_req_id = 0; |
2087 | } | 2077 | } |
2088 | out: | 2078 | out: |
2089 | spin_unlock_bh(&qdio->req_q_lock); | 2079 | spin_unlock_bh(&qdio->req_q_lock); |
@@ -2111,8 +2101,8 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) | |||
2111 | blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC; | 2101 | blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC; |
2112 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 2102 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
2113 | blktrc.flags |= ZFCP_BLK_REQ_ERROR; | 2103 | blktrc.flags |= ZFCP_BLK_REQ_ERROR; |
2114 | blktrc.inb_usage = req->queue_req.qdio_inb_usage; | 2104 | blktrc.inb_usage = req->qdio_req.qdio_inb_usage; |
2115 | blktrc.outb_usage = req->queue_req.qdio_outb_usage; | 2105 | blktrc.outb_usage = req->qdio_req.qdio_outb_usage; |
2116 | 2106 | ||
2117 | if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) { | 2107 | if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) { |
2118 | blktrc.flags |= ZFCP_BLK_LAT_VALID; | 2108 | blktrc.flags |= ZFCP_BLK_LAT_VALID; |
@@ -2169,12 +2159,7 @@ static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req) | |||
2169 | zfcp_fsf_req_trace(req, scpnt); | 2159 | zfcp_fsf_req_trace(req, scpnt); |
2170 | 2160 | ||
2171 | skip_fsfstatus: | 2161 | skip_fsfstatus: |
2172 | if (scpnt->result != 0) | 2162 | zfcp_dbf_scsi_result(req->adapter->dbf, scpnt, req); |
2173 | zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req); | ||
2174 | else if (scpnt->retries > 0) | ||
2175 | zfcp_dbf_scsi_result("retr", 4, req->adapter->dbf, scpnt, req); | ||
2176 | else | ||
2177 | zfcp_dbf_scsi_result("norm", 6, req->adapter->dbf, scpnt, req); | ||
2178 | 2163 | ||
2179 | scpnt->host_scribble = NULL; | 2164 | scpnt->host_scribble = NULL; |
2180 | (scpnt->scsi_done) (scpnt); | 2165 | (scpnt->scsi_done) (scpnt); |
@@ -2274,7 +2259,7 @@ skip_fsfstatus: | |||
2274 | else { | 2259 | else { |
2275 | zfcp_fsf_send_fcp_command_task_handler(req); | 2260 | zfcp_fsf_send_fcp_command_task_handler(req); |
2276 | req->unit = NULL; | 2261 | req->unit = NULL; |
2277 | put_device(&unit->sysfs_device); | 2262 | put_device(&unit->dev); |
2278 | } | 2263 | } |
2279 | } | 2264 | } |
2280 | 2265 | ||
@@ -2312,7 +2297,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, | |||
2312 | } | 2297 | } |
2313 | 2298 | ||
2314 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; | 2299 | req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; |
2315 | get_device(&unit->sysfs_device); | 2300 | get_device(&unit->dev); |
2316 | req->unit = unit; | 2301 | req->unit = unit; |
2317 | req->data = scsi_cmnd; | 2302 | req->data = scsi_cmnd; |
2318 | req->handler = zfcp_fsf_send_fcp_command_handler; | 2303 | req->handler = zfcp_fsf_send_fcp_command_handler; |
@@ -2346,11 +2331,11 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, | |||
2346 | fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; | 2331 | fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; |
2347 | zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd); | 2332 | zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd); |
2348 | 2333 | ||
2349 | real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype, | 2334 | real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sbtype, |
2350 | scsi_sglist(scsi_cmnd), | 2335 | scsi_sglist(scsi_cmnd), |
2351 | FSF_MAX_SBALS_PER_REQ); | 2336 | FSF_MAX_SBALS_PER_REQ); |
2352 | if (unlikely(real_bytes < 0)) { | 2337 | if (unlikely(real_bytes < 0)) { |
2353 | if (req->queue_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) { | 2338 | if (req->qdio_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) { |
2354 | dev_err(&adapter->ccw_device->dev, | 2339 | dev_err(&adapter->ccw_device->dev, |
2355 | "Oversize data package, unit 0x%016Lx " | 2340 | "Oversize data package, unit 0x%016Lx " |
2356 | "on port 0x%016Lx closed\n", | 2341 | "on port 0x%016Lx closed\n", |
@@ -2369,7 +2354,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit, | |||
2369 | goto out; | 2354 | goto out; |
2370 | 2355 | ||
2371 | failed_scsi_cmnd: | 2356 | failed_scsi_cmnd: |
2372 | put_device(&unit->sysfs_device); | 2357 | put_device(&unit->dev); |
2373 | zfcp_fsf_req_free(req); | 2358 | zfcp_fsf_req_free(req); |
2374 | scsi_cmnd->host_scribble = NULL; | 2359 | scsi_cmnd->host_scribble = NULL; |
2375 | out: | 2360 | out: |
@@ -2415,7 +2400,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags) | |||
2415 | req->qtcb->bottom.io.service_class = FSF_CLASS_3; | 2400 | req->qtcb->bottom.io.service_class = FSF_CLASS_3; |
2416 | req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN; | 2401 | req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN; |
2417 | 2402 | ||
2418 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 2403 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
2419 | sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; | 2404 | sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; |
2420 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 2405 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
2421 | 2406 | ||
@@ -2478,14 +2463,14 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter, | |||
2478 | 2463 | ||
2479 | req->handler = zfcp_fsf_control_file_handler; | 2464 | req->handler = zfcp_fsf_control_file_handler; |
2480 | 2465 | ||
2481 | sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req); | 2466 | sbale = zfcp_qdio_sbale_req(qdio, &req->qdio_req); |
2482 | sbale[0].flags |= direction; | 2467 | sbale[0].flags |= direction; |
2483 | 2468 | ||
2484 | bottom = &req->qtcb->bottom.support; | 2469 | bottom = &req->qtcb->bottom.support; |
2485 | bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; | 2470 | bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; |
2486 | bottom->option = fsf_cfdc->option; | 2471 | bottom->option = fsf_cfdc->option; |
2487 | 2472 | ||
2488 | bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, | 2473 | bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, |
2489 | direction, fsf_cfdc->sg, | 2474 | direction, fsf_cfdc->sg, |
2490 | FSF_MAX_SBALS_PER_REQ); | 2475 | FSF_MAX_SBALS_PER_REQ); |
2491 | if (bytes != ZFCP_CFDC_MAX_SIZE) { | 2476 | if (bytes != ZFCP_CFDC_MAX_SIZE) { |
@@ -2516,15 +2501,14 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) | |||
2516 | struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx]; | 2501 | struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx]; |
2517 | struct qdio_buffer_element *sbale; | 2502 | struct qdio_buffer_element *sbale; |
2518 | struct zfcp_fsf_req *fsf_req; | 2503 | struct zfcp_fsf_req *fsf_req; |
2519 | unsigned long flags, req_id; | 2504 | unsigned long req_id; |
2520 | int idx; | 2505 | int idx; |
2521 | 2506 | ||
2522 | for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) { | 2507 | for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) { |
2523 | 2508 | ||
2524 | sbale = &sbal->element[idx]; | 2509 | sbale = &sbal->element[idx]; |
2525 | req_id = (unsigned long) sbale->addr; | 2510 | req_id = (unsigned long) sbale->addr; |
2526 | spin_lock_irqsave(&adapter->req_list_lock, flags); | 2511 | fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id); |
2527 | fsf_req = zfcp_reqlist_find(adapter, req_id); | ||
2528 | 2512 | ||
2529 | if (!fsf_req) | 2513 | if (!fsf_req) |
2530 | /* | 2514 | /* |
@@ -2534,11 +2518,8 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) | |||
2534 | panic("error: unknown req_id (%lx) on adapter %s.\n", | 2518 | panic("error: unknown req_id (%lx) on adapter %s.\n", |
2535 | req_id, dev_name(&adapter->ccw_device->dev)); | 2519 | req_id, dev_name(&adapter->ccw_device->dev)); |
2536 | 2520 | ||
2537 | list_del(&fsf_req->list); | 2521 | fsf_req->qdio_req.sbal_response = sbal_idx; |
2538 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | 2522 | fsf_req->qdio_req.qdio_inb_usage = |
2539 | |||
2540 | fsf_req->queue_req.sbal_response = sbal_idx; | ||
2541 | fsf_req->queue_req.qdio_inb_usage = | ||
2542 | atomic_read(&qdio->resp_q.count); | 2523 | atomic_read(&qdio->resp_q.count); |
2543 | zfcp_fsf_req_complete(fsf_req); | 2524 | zfcp_fsf_req_complete(fsf_req); |
2544 | 2525 | ||
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 6c5228b627fc..71b97ff77cf0 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
11 | 11 | ||
12 | #include "zfcp_ext.h" | 12 | #include "zfcp_ext.h" |
13 | #include "zfcp_qdio.h" | ||
13 | 14 | ||
14 | #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) | 15 | #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) |
15 | 16 | ||
@@ -28,12 +29,6 @@ static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal) | |||
28 | return 0; | 29 | return 0; |
29 | } | 30 | } |
30 | 31 | ||
31 | static struct qdio_buffer_element * | ||
32 | zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx) | ||
33 | { | ||
34 | return &q->sbal[sbal_idx]->element[sbale_idx]; | ||
35 | } | ||
36 | |||
37 | static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id) | 32 | static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id) |
38 | { | 33 | { |
39 | struct zfcp_adapter *adapter = qdio->adapter; | 34 | struct zfcp_adapter *adapter = qdio->adapter; |
@@ -106,7 +101,7 @@ static void zfcp_qdio_resp_put_back(struct zfcp_qdio *qdio, int processed) | |||
106 | 101 | ||
107 | if (unlikely(retval)) { | 102 | if (unlikely(retval)) { |
108 | atomic_set(&queue->count, count); | 103 | atomic_set(&queue->count, count); |
109 | /* FIXME: Recover this with an adapter reopen? */ | 104 | zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdrpb_1", NULL); |
110 | } else { | 105 | } else { |
111 | queue->first += count; | 106 | queue->first += count; |
112 | queue->first %= QDIO_MAX_BUFFERS_PER_Q; | 107 | queue->first %= QDIO_MAX_BUFFERS_PER_Q; |
@@ -145,32 +140,8 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, | |||
145 | zfcp_qdio_resp_put_back(qdio, count); | 140 | zfcp_qdio_resp_put_back(qdio, count); |
146 | } | 141 | } |
147 | 142 | ||
148 | /** | ||
149 | * zfcp_qdio_sbale_req - return ptr to SBALE of req_q for a struct zfcp_fsf_req | ||
150 | * @qdio: pointer to struct zfcp_qdio | ||
151 | * @q_rec: pointer to struct zfcp_queue_rec | ||
152 | * Returns: pointer to qdio_buffer_element (SBALE) structure | ||
153 | */ | ||
154 | struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_qdio *qdio, | ||
155 | struct zfcp_queue_req *q_req) | ||
156 | { | ||
157 | return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last, 0); | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * zfcp_qdio_sbale_curr - return curr SBALE on req_q for a struct zfcp_fsf_req | ||
162 | * @fsf_req: pointer to struct fsf_req | ||
163 | * Returns: pointer to qdio_buffer_element (SBALE) structure | ||
164 | */ | ||
165 | struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio, | ||
166 | struct zfcp_queue_req *q_req) | ||
167 | { | ||
168 | return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last, | ||
169 | q_req->sbale_curr); | ||
170 | } | ||
171 | |||
172 | static void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio, | 143 | static void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio, |
173 | struct zfcp_queue_req *q_req, int max_sbals) | 144 | struct zfcp_qdio_req *q_req, int max_sbals) |
174 | { | 145 | { |
175 | int count = atomic_read(&qdio->req_q.count); | 146 | int count = atomic_read(&qdio->req_q.count); |
176 | count = min(count, max_sbals); | 147 | count = min(count, max_sbals); |
@@ -179,7 +150,7 @@ static void zfcp_qdio_sbal_limit(struct zfcp_qdio *qdio, | |||
179 | } | 150 | } |
180 | 151 | ||
181 | static struct qdio_buffer_element * | 152 | static struct qdio_buffer_element * |
182 | zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req, | 153 | zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, |
183 | unsigned long sbtype) | 154 | unsigned long sbtype) |
184 | { | 155 | { |
185 | struct qdio_buffer_element *sbale; | 156 | struct qdio_buffer_element *sbale; |
@@ -214,7 +185,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req, | |||
214 | } | 185 | } |
215 | 186 | ||
216 | static struct qdio_buffer_element * | 187 | static struct qdio_buffer_element * |
217 | zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req, | 188 | zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, |
218 | unsigned int sbtype) | 189 | unsigned int sbtype) |
219 | { | 190 | { |
220 | if (q_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL) | 191 | if (q_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL) |
@@ -224,7 +195,7 @@ zfcp_qdio_sbale_next(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req, | |||
224 | } | 195 | } |
225 | 196 | ||
226 | static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio, | 197 | static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio, |
227 | struct zfcp_queue_req *q_req) | 198 | struct zfcp_qdio_req *q_req) |
228 | { | 199 | { |
229 | struct qdio_buffer **sbal = qdio->req_q.sbal; | 200 | struct qdio_buffer **sbal = qdio->req_q.sbal; |
230 | int first = q_req->sbal_first; | 201 | int first = q_req->sbal_first; |
@@ -235,7 +206,7 @@ static void zfcp_qdio_undo_sbals(struct zfcp_qdio *qdio, | |||
235 | } | 206 | } |
236 | 207 | ||
237 | static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio, | 208 | static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio, |
238 | struct zfcp_queue_req *q_req, | 209 | struct zfcp_qdio_req *q_req, |
239 | unsigned int sbtype, void *start_addr, | 210 | unsigned int sbtype, void *start_addr, |
240 | unsigned int total_length) | 211 | unsigned int total_length) |
241 | { | 212 | { |
@@ -271,8 +242,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_qdio *qdio, | |||
271 | * @max_sbals: upper bound for number of SBALs to be used | 242 | * @max_sbals: upper bound for number of SBALs to be used |
272 | * Returns: number of bytes, or error (negativ) | 243 | * Returns: number of bytes, or error (negativ) |
273 | */ | 244 | */ |
274 | int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, | 245 | int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, |
275 | struct zfcp_queue_req *q_req, | ||
276 | unsigned long sbtype, struct scatterlist *sg, | 246 | unsigned long sbtype, struct scatterlist *sg, |
277 | int max_sbals) | 247 | int max_sbals) |
278 | { | 248 | { |
@@ -304,10 +274,10 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, | |||
304 | /** | 274 | /** |
305 | * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO | 275 | * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO |
306 | * @qdio: pointer to struct zfcp_qdio | 276 | * @qdio: pointer to struct zfcp_qdio |
307 | * @q_req: pointer to struct zfcp_queue_req | 277 | * @q_req: pointer to struct zfcp_qdio_req |
308 | * Returns: 0 on success, error otherwise | 278 | * Returns: 0 on success, error otherwise |
309 | */ | 279 | */ |
310 | int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_queue_req *q_req) | 280 | int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) |
311 | { | 281 | { |
312 | struct zfcp_qdio_queue *req_q = &qdio->req_q; | 282 | struct zfcp_qdio_queue *req_q = &qdio->req_q; |
313 | int first = q_req->sbal_first; | 283 | int first = q_req->sbal_first; |
diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h new file mode 100644 index 000000000000..8cca54631e1e --- /dev/null +++ b/drivers/s390/scsi/zfcp_qdio.h | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * zfcp device driver | ||
3 | * | ||
4 | * Header file for zfcp qdio interface | ||
5 | * | ||
6 | * Copyright IBM Corporation 2010 | ||
7 | */ | ||
8 | |||
9 | #ifndef ZFCP_QDIO_H | ||
10 | #define ZFCP_QDIO_H | ||
11 | |||
12 | #include <asm/qdio.h> | ||
13 | |||
14 | /** | ||
15 | * struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count | ||
16 | * @sbal: qdio buffers | ||
17 | * @first: index of next free buffer in queue | ||
18 | * @count: number of free buffers in queue | ||
19 | */ | ||
20 | struct zfcp_qdio_queue { | ||
21 | struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; | ||
22 | u8 first; | ||
23 | atomic_t count; | ||
24 | }; | ||
25 | |||
26 | /** | ||
27 | * struct zfcp_qdio - basic qdio data structure | ||
28 | * @resp_q: response queue | ||
29 | * @req_q: request queue | ||
30 | * @stat_lock: lock to protect req_q_util and req_q_time | ||
31 | * @req_q_lock: lock to serialize access to request queue | ||
32 | * @req_q_time: time of last fill level change | ||
33 | * @req_q_util: used for accounting | ||
34 | * @req_q_full: queue full incidents | ||
35 | * @req_q_wq: used to wait for SBAL availability | ||
36 | * @adapter: adapter used in conjunction with this qdio structure | ||
37 | */ | ||
38 | struct zfcp_qdio { | ||
39 | struct zfcp_qdio_queue resp_q; | ||
40 | struct zfcp_qdio_queue req_q; | ||
41 | spinlock_t stat_lock; | ||
42 | spinlock_t req_q_lock; | ||
43 | unsigned long long req_q_time; | ||
44 | u64 req_q_util; | ||
45 | atomic_t req_q_full; | ||
46 | wait_queue_head_t req_q_wq; | ||
47 | struct zfcp_adapter *adapter; | ||
48 | }; | ||
49 | |||
50 | /** | ||
51 | * struct zfcp_qdio_req - qdio queue related values for a request | ||
52 | * @sbal_number: number of free sbals | ||
53 | * @sbal_first: first sbal for this request | ||
54 | * @sbal_last: last sbal for this request | ||
55 | * @sbal_limit: last possible sbal for this request | ||
56 | * @sbale_curr: current sbale at creation of this request | ||
57 | * @sbal_response: sbal used in interrupt | ||
58 | * @qdio_outb_usage: usage of outbound queue | ||
59 | * @qdio_inb_usage: usage of inbound queue | ||
60 | */ | ||
61 | struct zfcp_qdio_req { | ||
62 | u8 sbal_number; | ||
63 | u8 sbal_first; | ||
64 | u8 sbal_last; | ||
65 | u8 sbal_limit; | ||
66 | u8 sbale_curr; | ||
67 | u8 sbal_response; | ||
68 | u16 qdio_outb_usage; | ||
69 | u16 qdio_inb_usage; | ||
70 | }; | ||
71 | |||
72 | /** | ||
73 | * zfcp_qdio_sbale - return pointer to sbale in qdio queue | ||
74 | * @q: queue where to find sbal | ||
75 | * @sbal_idx: sbal index in queue | ||
76 | * @sbale_idx: sbale index in sbal | ||
77 | */ | ||
78 | static inline struct qdio_buffer_element * | ||
79 | zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx) | ||
80 | { | ||
81 | return &q->sbal[sbal_idx]->element[sbale_idx]; | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * zfcp_qdio_sbale_req - return pointer to sbale on req_q for a request | ||
86 | * @qdio: pointer to struct zfcp_qdio | ||
87 | * @q_rec: pointer to struct zfcp_qdio_req | ||
88 | * Returns: pointer to qdio_buffer_element (sbale) structure | ||
89 | */ | ||
90 | static inline struct qdio_buffer_element * | ||
91 | zfcp_qdio_sbale_req(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | ||
92 | { | ||
93 | return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last, 0); | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * zfcp_qdio_sbale_curr - return current sbale on req_q for a request | ||
98 | * @qdio: pointer to struct zfcp_qdio | ||
99 | * @fsf_req: pointer to struct zfcp_fsf_req | ||
100 | * Returns: pointer to qdio_buffer_element (sbale) structure | ||
101 | */ | ||
102 | static inline struct qdio_buffer_element * | ||
103 | zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) | ||
104 | { | ||
105 | return zfcp_qdio_sbale(&qdio->req_q, q_req->sbal_last, | ||
106 | q_req->sbale_curr); | ||
107 | } | ||
108 | |||
109 | #endif /* ZFCP_QDIO_H */ | ||
diff --git a/drivers/s390/scsi/zfcp_reqlist.h b/drivers/s390/scsi/zfcp_reqlist.h new file mode 100644 index 000000000000..a72d1b730aba --- /dev/null +++ b/drivers/s390/scsi/zfcp_reqlist.h | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * zfcp device driver | ||
3 | * | ||
4 | * Data structure and helper functions for tracking pending FSF | ||
5 | * requests. | ||
6 | * | ||
7 | * Copyright IBM Corporation 2009 | ||
8 | */ | ||
9 | |||
10 | #ifndef ZFCP_REQLIST_H | ||
11 | #define ZFCP_REQLIST_H | ||
12 | |||
13 | /* number of hash buckets */ | ||
14 | #define ZFCP_REQ_LIST_BUCKETS 128 | ||
15 | |||
16 | /** | ||
17 | * struct zfcp_reqlist - Container for request list (reqlist) | ||
18 | * @lock: Spinlock for protecting the hash list | ||
19 | * @list: Array of hashbuckets, each is a list of requests in this bucket | ||
20 | */ | ||
21 | struct zfcp_reqlist { | ||
22 | spinlock_t lock; | ||
23 | struct list_head buckets[ZFCP_REQ_LIST_BUCKETS]; | ||
24 | }; | ||
25 | |||
26 | static inline int zfcp_reqlist_hash(unsigned long req_id) | ||
27 | { | ||
28 | return req_id % ZFCP_REQ_LIST_BUCKETS; | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * zfcp_reqlist_alloc - Allocate and initialize reqlist | ||
33 | * | ||
34 | * Returns pointer to allocated reqlist on success, or NULL on | ||
35 | * allocation failure. | ||
36 | */ | ||
37 | static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void) | ||
38 | { | ||
39 | unsigned int i; | ||
40 | struct zfcp_reqlist *rl; | ||
41 | |||
42 | rl = kzalloc(sizeof(struct zfcp_reqlist), GFP_KERNEL); | ||
43 | if (!rl) | ||
44 | return NULL; | ||
45 | |||
46 | spin_lock_init(&rl->lock); | ||
47 | |||
48 | for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++) | ||
49 | INIT_LIST_HEAD(&rl->buckets[i]); | ||
50 | |||
51 | return rl; | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * zfcp_reqlist_isempty - Check whether the request list empty | ||
56 | * @rl: pointer to reqlist | ||
57 | * | ||
58 | * Returns: 1 if list is empty, 0 if not | ||
59 | */ | ||
60 | static inline int zfcp_reqlist_isempty(struct zfcp_reqlist *rl) | ||
61 | { | ||
62 | unsigned int i; | ||
63 | |||
64 | for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++) | ||
65 | if (!list_empty(&rl->buckets[i])) | ||
66 | return 0; | ||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * zfcp_reqlist_free - Free allocated memory for reqlist | ||
72 | * @rl: The reqlist where to free memory | ||
73 | */ | ||
74 | static inline void zfcp_reqlist_free(struct zfcp_reqlist *rl) | ||
75 | { | ||
76 | /* sanity check */ | ||
77 | BUG_ON(!zfcp_reqlist_isempty(rl)); | ||
78 | |||
79 | kfree(rl); | ||
80 | } | ||
81 | |||
82 | static inline struct zfcp_fsf_req * | ||
83 | _zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id) | ||
84 | { | ||
85 | struct zfcp_fsf_req *req; | ||
86 | unsigned int i; | ||
87 | |||
88 | i = zfcp_reqlist_hash(req_id); | ||
89 | list_for_each_entry(req, &rl->buckets[i], list) | ||
90 | if (req->req_id == req_id) | ||
91 | return req; | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * zfcp_reqlist_find - Lookup FSF request by its request id | ||
97 | * @rl: The reqlist where to lookup the FSF request | ||
98 | * @req_id: The request id to look for | ||
99 | * | ||
100 | * Returns a pointer to the FSF request with the specified request id | ||
101 | * or NULL if there is no known FSF request with this id. | ||
102 | */ | ||
103 | static inline struct zfcp_fsf_req * | ||
104 | zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id) | ||
105 | { | ||
106 | unsigned long flags; | ||
107 | struct zfcp_fsf_req *req; | ||
108 | |||
109 | spin_lock_irqsave(&rl->lock, flags); | ||
110 | req = _zfcp_reqlist_find(rl, req_id); | ||
111 | spin_unlock_irqrestore(&rl->lock, flags); | ||
112 | |||
113 | return req; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * zfcp_reqlist_find_rm - Lookup request by id and remove it from reqlist | ||
118 | * @rl: reqlist where to search and remove entry | ||
119 | * @req_id: The request id of the request to look for | ||
120 | * | ||
121 | * This functions tries to find the FSF request with the specified | ||
122 | * id and then removes it from the reqlist. The reqlist lock is held | ||
123 | * during both steps of the operation. | ||
124 | * | ||
125 | * Returns: Pointer to the FSF request if the request has been found, | ||
126 | * NULL if it has not been found. | ||
127 | */ | ||
128 | static inline struct zfcp_fsf_req * | ||
129 | zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, unsigned long req_id) | ||
130 | { | ||
131 | unsigned long flags; | ||
132 | struct zfcp_fsf_req *req; | ||
133 | |||
134 | spin_lock_irqsave(&rl->lock, flags); | ||
135 | req = _zfcp_reqlist_find(rl, req_id); | ||
136 | if (req) | ||
137 | list_del(&req->list); | ||
138 | spin_unlock_irqrestore(&rl->lock, flags); | ||
139 | |||
140 | return req; | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * zfcp_reqlist_add - Add entry to reqlist | ||
145 | * @rl: reqlist where to add the entry | ||
146 | * @req: The entry to add | ||
147 | * | ||
148 | * The request id always increases. As an optimization new requests | ||
149 | * are added here with list_add_tail at the end of the bucket lists | ||
150 | * while old requests are looked up starting at the beginning of the | ||
151 | * lists. | ||
152 | */ | ||
153 | static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl, | ||
154 | struct zfcp_fsf_req *req) | ||
155 | { | ||
156 | unsigned int i; | ||
157 | unsigned long flags; | ||
158 | |||
159 | i = zfcp_reqlist_hash(req->req_id); | ||
160 | |||
161 | spin_lock_irqsave(&rl->lock, flags); | ||
162 | list_add_tail(&req->list, &rl->buckets[i]); | ||
163 | spin_unlock_irqrestore(&rl->lock, flags); | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * zfcp_reqlist_move - Move all entries from reqlist to simple list | ||
168 | * @rl: The zfcp_reqlist where to remove all entries | ||
169 | * @list: The list where to move all entries | ||
170 | */ | ||
171 | static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl, | ||
172 | struct list_head *list) | ||
173 | { | ||
174 | unsigned int i; | ||
175 | unsigned long flags; | ||
176 | |||
177 | spin_lock_irqsave(&rl->lock, flags); | ||
178 | for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++) | ||
179 | list_splice_init(&rl->buckets[i], list); | ||
180 | spin_unlock_irqrestore(&rl->lock, flags); | ||
181 | } | ||
182 | |||
183 | #endif /* ZFCP_REQLIST_H */ | ||
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 8e6fc68d6bd4..c3c4178888af 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Interface to Linux SCSI midlayer. | 4 | * Interface to Linux SCSI midlayer. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2002, 2009 | 6 | * Copyright IBM Corporation 2002, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
@@ -15,6 +15,7 @@ | |||
15 | #include "zfcp_ext.h" | 15 | #include "zfcp_ext.h" |
16 | #include "zfcp_dbf.h" | 16 | #include "zfcp_dbf.h" |
17 | #include "zfcp_fc.h" | 17 | #include "zfcp_fc.h" |
18 | #include "zfcp_reqlist.h" | ||
18 | 19 | ||
19 | static unsigned int default_depth = 32; | 20 | static unsigned int default_depth = 32; |
20 | module_param_named(queue_depth, default_depth, uint, 0600); | 21 | module_param_named(queue_depth, default_depth, uint, 0600); |
@@ -43,7 +44,7 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | |||
43 | { | 44 | { |
44 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; | 45 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; |
45 | unit->device = NULL; | 46 | unit->device = NULL; |
46 | put_device(&unit->sysfs_device); | 47 | put_device(&unit->dev); |
47 | } | 48 | } |
48 | 49 | ||
49 | static int zfcp_scsi_slave_configure(struct scsi_device *sdp) | 50 | static int zfcp_scsi_slave_configure(struct scsi_device *sdp) |
@@ -59,10 +60,9 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) | |||
59 | { | 60 | { |
60 | struct zfcp_adapter *adapter = | 61 | struct zfcp_adapter *adapter = |
61 | (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; | 62 | (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; |
63 | |||
62 | set_host_byte(scpnt, result); | 64 | set_host_byte(scpnt, result); |
63 | if ((scpnt->device != NULL) && (scpnt->device->host != NULL)) | 65 | zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt); |
64 | zfcp_dbf_scsi_result("fail", 4, adapter->dbf, scpnt, NULL); | ||
65 | /* return directly */ | ||
66 | scpnt->scsi_done(scpnt); | 66 | scpnt->scsi_done(scpnt); |
67 | } | 67 | } |
68 | 68 | ||
@@ -86,18 +86,10 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, | |||
86 | adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; | 86 | adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; |
87 | unit = scpnt->device->hostdata; | 87 | unit = scpnt->device->hostdata; |
88 | 88 | ||
89 | BUG_ON(!adapter || (adapter != unit->port->adapter)); | ||
90 | BUG_ON(!scpnt->scsi_done); | ||
91 | |||
92 | if (unlikely(!unit)) { | ||
93 | zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | scsi_result = fc_remote_port_chkready(rport); | 89 | scsi_result = fc_remote_port_chkready(rport); |
98 | if (unlikely(scsi_result)) { | 90 | if (unlikely(scsi_result)) { |
99 | scpnt->result = scsi_result; | 91 | scpnt->result = scsi_result; |
100 | zfcp_dbf_scsi_result("fail", 4, adapter->dbf, scpnt, NULL); | 92 | zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt); |
101 | scpnt->scsi_done(scpnt); | 93 | scpnt->scsi_done(scpnt); |
102 | return 0; | 94 | return 0; |
103 | } | 95 | } |
@@ -189,9 +181,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
189 | /* avoid race condition between late normal completion and abort */ | 181 | /* avoid race condition between late normal completion and abort */ |
190 | write_lock_irqsave(&adapter->abort_lock, flags); | 182 | write_lock_irqsave(&adapter->abort_lock, flags); |
191 | 183 | ||
192 | spin_lock(&adapter->req_list_lock); | 184 | old_req = zfcp_reqlist_find(adapter->req_list, old_reqid); |
193 | old_req = zfcp_reqlist_find(adapter, old_reqid); | ||
194 | spin_unlock(&adapter->req_list_lock); | ||
195 | if (!old_req) { | 185 | if (!old_req) { |
196 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 186 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
197 | zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL, | 187 | zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL, |
@@ -521,7 +511,7 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) | |||
521 | 511 | ||
522 | if (port) { | 512 | if (port) { |
523 | zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); | 513 | zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); |
524 | put_device(&port->sysfs_device); | 514 | put_device(&port->dev); |
525 | } | 515 | } |
526 | } | 516 | } |
527 | 517 | ||
@@ -563,23 +553,23 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port) | |||
563 | 553 | ||
564 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) | 554 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) |
565 | { | 555 | { |
566 | get_device(&port->sysfs_device); | 556 | get_device(&port->dev); |
567 | port->rport_task = RPORT_ADD; | 557 | port->rport_task = RPORT_ADD; |
568 | 558 | ||
569 | if (!queue_work(port->adapter->work_queue, &port->rport_work)) | 559 | if (!queue_work(port->adapter->work_queue, &port->rport_work)) |
570 | put_device(&port->sysfs_device); | 560 | put_device(&port->dev); |
571 | } | 561 | } |
572 | 562 | ||
573 | void zfcp_scsi_schedule_rport_block(struct zfcp_port *port) | 563 | void zfcp_scsi_schedule_rport_block(struct zfcp_port *port) |
574 | { | 564 | { |
575 | get_device(&port->sysfs_device); | 565 | get_device(&port->dev); |
576 | port->rport_task = RPORT_DEL; | 566 | port->rport_task = RPORT_DEL; |
577 | 567 | ||
578 | if (port->rport && queue_work(port->adapter->work_queue, | 568 | if (port->rport && queue_work(port->adapter->work_queue, |
579 | &port->rport_work)) | 569 | &port->rport_work)) |
580 | return; | 570 | return; |
581 | 571 | ||
582 | put_device(&port->sysfs_device); | 572 | put_device(&port->dev); |
583 | } | 573 | } |
584 | 574 | ||
585 | void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter) | 575 | void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter) |
@@ -608,7 +598,7 @@ void zfcp_scsi_rport_work(struct work_struct *work) | |||
608 | } | 598 | } |
609 | } | 599 | } |
610 | 600 | ||
611 | put_device(&port->sysfs_device); | 601 | put_device(&port->dev); |
612 | } | 602 | } |
613 | 603 | ||
614 | 604 | ||
@@ -626,7 +616,7 @@ void zfcp_scsi_scan(struct work_struct *work) | |||
626 | scsilun_to_int((struct scsi_lun *) | 616 | scsilun_to_int((struct scsi_lun *) |
627 | &unit->fcp_lun), 0); | 617 | &unit->fcp_lun), 0); |
628 | 618 | ||
629 | put_device(&unit->sysfs_device); | 619 | put_device(&unit->dev); |
630 | } | 620 | } |
631 | 621 | ||
632 | struct fc_function_template zfcp_transport_functions = { | 622 | struct fc_function_template zfcp_transport_functions = { |
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index f539e006683c..a43035d4bd70 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * sysfs attributes. | 4 | * sysfs attributes. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2008, 2009 | 6 | * Copyright IBM Corporation 2008, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
@@ -19,8 +19,7 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev, \ | |||
19 | struct device_attribute *at,\ | 19 | struct device_attribute *at,\ |
20 | char *buf) \ | 20 | char *buf) \ |
21 | { \ | 21 | { \ |
22 | struct _feat_def *_feat = container_of(dev, struct _feat_def, \ | 22 | struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \ |
23 | sysfs_device); \ | ||
24 | \ | 23 | \ |
25 | return sprintf(buf, _format, _value); \ | 24 | return sprintf(buf, _format, _value); \ |
26 | } \ | 25 | } \ |
@@ -87,8 +86,7 @@ static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev, \ | |||
87 | struct device_attribute *attr, \ | 86 | struct device_attribute *attr, \ |
88 | char *buf) \ | 87 | char *buf) \ |
89 | { \ | 88 | { \ |
90 | struct _feat_def *_feat = container_of(dev, struct _feat_def, \ | 89 | struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \ |
91 | sysfs_device); \ | ||
92 | \ | 90 | \ |
93 | if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \ | 91 | if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED) \ |
94 | return sprintf(buf, "1\n"); \ | 92 | return sprintf(buf, "1\n"); \ |
@@ -99,12 +97,11 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \ | |||
99 | struct device_attribute *attr,\ | 97 | struct device_attribute *attr,\ |
100 | const char *buf, size_t count)\ | 98 | const char *buf, size_t count)\ |
101 | { \ | 99 | { \ |
102 | struct _feat_def *_feat = container_of(dev, struct _feat_def, \ | 100 | struct _feat_def *_feat = container_of(dev, struct _feat_def, dev); \ |
103 | sysfs_device); \ | ||
104 | unsigned long val; \ | 101 | unsigned long val; \ |
105 | int retval = 0; \ | 102 | int retval = 0; \ |
106 | \ | 103 | \ |
107 | if (!(_feat && get_device(&_feat->sysfs_device))) \ | 104 | if (!(_feat && get_device(&_feat->dev))) \ |
108 | return -EBUSY; \ | 105 | return -EBUSY; \ |
109 | \ | 106 | \ |
110 | if (strict_strtoul(buf, 0, &val) || val != 0) { \ | 107 | if (strict_strtoul(buf, 0, &val) || val != 0) { \ |
@@ -118,7 +115,7 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \ | |||
118 | _reopen_id, NULL); \ | 115 | _reopen_id, NULL); \ |
119 | zfcp_erp_wait(_adapter); \ | 116 | zfcp_erp_wait(_adapter); \ |
120 | out: \ | 117 | out: \ |
121 | put_device(&_feat->sysfs_device); \ | 118 | put_device(&_feat->dev); \ |
122 | return retval ? retval : (ssize_t) count; \ | 119 | return retval ? retval : (ssize_t) count; \ |
123 | } \ | 120 | } \ |
124 | static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ | 121 | static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ |
@@ -224,10 +221,10 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, | |||
224 | list_del(&port->list); | 221 | list_del(&port->list); |
225 | write_unlock_irq(&adapter->port_list_lock); | 222 | write_unlock_irq(&adapter->port_list_lock); |
226 | 223 | ||
227 | put_device(&port->sysfs_device); | 224 | put_device(&port->dev); |
228 | 225 | ||
229 | zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); | 226 | zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); |
230 | zfcp_device_unregister(&port->sysfs_device, &zfcp_sysfs_port_attrs); | 227 | zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); |
231 | out: | 228 | out: |
232 | zfcp_ccw_adapter_put(adapter); | 229 | zfcp_ccw_adapter_put(adapter); |
233 | return retval ? retval : (ssize_t) count; | 230 | return retval ? retval : (ssize_t) count; |
@@ -258,13 +255,12 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, | |||
258 | struct device_attribute *attr, | 255 | struct device_attribute *attr, |
259 | const char *buf, size_t count) | 256 | const char *buf, size_t count) |
260 | { | 257 | { |
261 | struct zfcp_port *port = container_of(dev, struct zfcp_port, | 258 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); |
262 | sysfs_device); | ||
263 | struct zfcp_unit *unit; | 259 | struct zfcp_unit *unit; |
264 | u64 fcp_lun; | 260 | u64 fcp_lun; |
265 | int retval = -EINVAL; | 261 | int retval = -EINVAL; |
266 | 262 | ||
267 | if (!(port && get_device(&port->sysfs_device))) | 263 | if (!(port && get_device(&port->dev))) |
268 | return -EBUSY; | 264 | return -EBUSY; |
269 | 265 | ||
270 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) | 266 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) |
@@ -280,7 +276,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, | |||
280 | zfcp_erp_wait(unit->port->adapter); | 276 | zfcp_erp_wait(unit->port->adapter); |
281 | flush_work(&unit->scsi_work); | 277 | flush_work(&unit->scsi_work); |
282 | out: | 278 | out: |
283 | put_device(&port->sysfs_device); | 279 | put_device(&port->dev); |
284 | return retval ? retval : (ssize_t) count; | 280 | return retval ? retval : (ssize_t) count; |
285 | } | 281 | } |
286 | static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); | 282 | static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); |
@@ -289,13 +285,12 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
289 | struct device_attribute *attr, | 285 | struct device_attribute *attr, |
290 | const char *buf, size_t count) | 286 | const char *buf, size_t count) |
291 | { | 287 | { |
292 | struct zfcp_port *port = container_of(dev, struct zfcp_port, | 288 | struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); |
293 | sysfs_device); | ||
294 | struct zfcp_unit *unit; | 289 | struct zfcp_unit *unit; |
295 | u64 fcp_lun; | 290 | u64 fcp_lun; |
296 | int retval = -EINVAL; | 291 | int retval = -EINVAL; |
297 | 292 | ||
298 | if (!(port && get_device(&port->sysfs_device))) | 293 | if (!(port && get_device(&port->dev))) |
299 | return -EBUSY; | 294 | return -EBUSY; |
300 | 295 | ||
301 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) | 296 | if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) |
@@ -314,12 +309,12 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
314 | list_del(&unit->list); | 309 | list_del(&unit->list); |
315 | write_unlock_irq(&port->unit_list_lock); | 310 | write_unlock_irq(&port->unit_list_lock); |
316 | 311 | ||
317 | put_device(&unit->sysfs_device); | 312 | put_device(&unit->dev); |
318 | 313 | ||
319 | zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); | 314 | zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); |
320 | zfcp_device_unregister(&unit->sysfs_device, &zfcp_sysfs_unit_attrs); | 315 | zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs); |
321 | out: | 316 | out: |
322 | put_device(&port->sysfs_device); | 317 | put_device(&port->dev); |
323 | return retval ? retval : (ssize_t) count; | 318 | return retval ? retval : (ssize_t) count; |
324 | } | 319 | } |
325 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); | 320 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); |