diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-16 12:27:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-16 12:27:13 -0500 |
commit | 2ebc8ec86fe0f3f3acf9ba9b41a368f819e7807e (patch) | |
tree | c0b3d4f14ae6dd98318d78fcf7d16f47954e06a4 /drivers/s390 | |
parent | df6e61d4ca268dc8706db38222fde9f04701566c (diff) | |
parent | 89480801a17a3069f45169d40b828c8e511aa005 (diff) |
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6:
[S390] kprobes: Fix the return address of multiple kretprobes
[S390] kprobes: disable interrupts throughout
[S390] ftrace: build without frame pointers on s390
[S390] mm: add devmem_is_allowed() for STRICT_DEVMEM checking
[S390] vmlogrdr: purge after recording is switched off
[S390] cio: fix incorrect ccw_device_init_count
[S390] tape: add medium state notifications
[S390] fix get_user_pages_fast
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/char/tape_core.c | 68 | ||||
-rw-r--r-- | drivers/s390/char/vmlogrdr.c | 36 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 11 |
3 files changed, 93 insertions, 22 deletions
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 6c408670e08d..b3a3e8e8656e 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c | |||
@@ -209,29 +209,79 @@ tape_state_set(struct tape_device *device, enum tape_state newstate) | |||
209 | wake_up(&device->state_change_wq); | 209 | wake_up(&device->state_change_wq); |
210 | } | 210 | } |
211 | 211 | ||
212 | struct tape_med_state_work_data { | ||
213 | struct tape_device *device; | ||
214 | enum tape_medium_state state; | ||
215 | struct work_struct work; | ||
216 | }; | ||
217 | |||
218 | static void | ||
219 | tape_med_state_work_handler(struct work_struct *work) | ||
220 | { | ||
221 | static char env_state_loaded[] = "MEDIUM_STATE=LOADED"; | ||
222 | static char env_state_unloaded[] = "MEDIUM_STATE=UNLOADED"; | ||
223 | struct tape_med_state_work_data *p = | ||
224 | container_of(work, struct tape_med_state_work_data, work); | ||
225 | struct tape_device *device = p->device; | ||
226 | char *envp[] = { NULL, NULL }; | ||
227 | |||
228 | switch (p->state) { | ||
229 | case MS_UNLOADED: | ||
230 | pr_info("%s: The tape cartridge has been successfully " | ||
231 | "unloaded\n", dev_name(&device->cdev->dev)); | ||
232 | envp[0] = env_state_unloaded; | ||
233 | kobject_uevent_env(&device->cdev->dev.kobj, KOBJ_CHANGE, envp); | ||
234 | break; | ||
235 | case MS_LOADED: | ||
236 | pr_info("%s: A tape cartridge has been mounted\n", | ||
237 | dev_name(&device->cdev->dev)); | ||
238 | envp[0] = env_state_loaded; | ||
239 | kobject_uevent_env(&device->cdev->dev.kobj, KOBJ_CHANGE, envp); | ||
240 | break; | ||
241 | default: | ||
242 | break; | ||
243 | } | ||
244 | tape_put_device(device); | ||
245 | kfree(p); | ||
246 | } | ||
247 | |||
248 | static void | ||
249 | tape_med_state_work(struct tape_device *device, enum tape_medium_state state) | ||
250 | { | ||
251 | struct tape_med_state_work_data *p; | ||
252 | |||
253 | p = kzalloc(sizeof(*p), GFP_ATOMIC); | ||
254 | if (p) { | ||
255 | INIT_WORK(&p->work, tape_med_state_work_handler); | ||
256 | p->device = tape_get_device(device); | ||
257 | p->state = state; | ||
258 | schedule_work(&p->work); | ||
259 | } | ||
260 | } | ||
261 | |||
212 | void | 262 | void |
213 | tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) | 263 | tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) |
214 | { | 264 | { |
215 | if (device->medium_state == newstate) | 265 | enum tape_medium_state oldstate; |
266 | |||
267 | oldstate = device->medium_state; | ||
268 | if (oldstate == newstate) | ||
216 | return; | 269 | return; |
270 | device->medium_state = newstate; | ||
217 | switch(newstate){ | 271 | switch(newstate){ |
218 | case MS_UNLOADED: | 272 | case MS_UNLOADED: |
219 | device->tape_generic_status |= GMT_DR_OPEN(~0); | 273 | device->tape_generic_status |= GMT_DR_OPEN(~0); |
220 | if (device->medium_state == MS_LOADED) | 274 | if (oldstate == MS_LOADED) |
221 | pr_info("%s: The tape cartridge has been successfully " | 275 | tape_med_state_work(device, MS_UNLOADED); |
222 | "unloaded\n", dev_name(&device->cdev->dev)); | ||
223 | break; | 276 | break; |
224 | case MS_LOADED: | 277 | case MS_LOADED: |
225 | device->tape_generic_status &= ~GMT_DR_OPEN(~0); | 278 | device->tape_generic_status &= ~GMT_DR_OPEN(~0); |
226 | if (device->medium_state == MS_UNLOADED) | 279 | if (oldstate == MS_UNLOADED) |
227 | pr_info("%s: A tape cartridge has been mounted\n", | 280 | tape_med_state_work(device, MS_LOADED); |
228 | dev_name(&device->cdev->dev)); | ||
229 | break; | 281 | break; |
230 | default: | 282 | default: |
231 | // print nothing | ||
232 | break; | 283 | break; |
233 | } | 284 | } |
234 | device->medium_state = newstate; | ||
235 | wake_up(&device->state_change_wq); | 285 | wake_up(&device->state_change_wq); |
236 | } | 286 | } |
237 | 287 | ||
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 9f661426e4a1..1cc726b98ec8 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c | |||
@@ -249,27 +249,25 @@ static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, | |||
249 | char cp_command[80]; | 249 | char cp_command[80]; |
250 | char cp_response[160]; | 250 | char cp_response[160]; |
251 | char *onoff, *qid_string; | 251 | char *onoff, *qid_string; |
252 | int rc; | ||
252 | 253 | ||
253 | memset(cp_command, 0x00, sizeof(cp_command)); | 254 | onoff = ((action == 1) ? "ON" : "OFF"); |
254 | memset(cp_response, 0x00, sizeof(cp_response)); | ||
255 | |||
256 | onoff = ((action == 1) ? "ON" : "OFF"); | ||
257 | qid_string = ((recording_class_AB == 1) ? " QID * " : ""); | 255 | qid_string = ((recording_class_AB == 1) ? " QID * " : ""); |
258 | 256 | ||
259 | /* | 257 | /* |
260 | * The recording commands needs to be called with option QID | 258 | * The recording commands needs to be called with option QID |
261 | * for guests that have previlege classes A or B. | 259 | * for guests that have previlege classes A or B. |
262 | * Purging has to be done as separate step, because recording | 260 | * Purging has to be done as separate step, because recording |
263 | * can't be switched on as long as records are on the queue. | 261 | * can't be switched on as long as records are on the queue. |
264 | * Doing both at the same time doesn't work. | 262 | * Doing both at the same time doesn't work. |
265 | */ | 263 | */ |
266 | 264 | if (purge && (action == 1)) { | |
267 | if (purge) { | 265 | memset(cp_command, 0x00, sizeof(cp_command)); |
266 | memset(cp_response, 0x00, sizeof(cp_response)); | ||
268 | snprintf(cp_command, sizeof(cp_command), | 267 | snprintf(cp_command, sizeof(cp_command), |
269 | "RECORDING %s PURGE %s", | 268 | "RECORDING %s PURGE %s", |
270 | logptr->recording_name, | 269 | logptr->recording_name, |
271 | qid_string); | 270 | qid_string); |
272 | |||
273 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); | 271 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); |
274 | } | 272 | } |
275 | 273 | ||
@@ -279,19 +277,33 @@ static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, | |||
279 | logptr->recording_name, | 277 | logptr->recording_name, |
280 | onoff, | 278 | onoff, |
281 | qid_string); | 279 | qid_string); |
282 | |||
283 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); | 280 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); |
284 | /* The recording command will usually answer with 'Command complete' | 281 | /* The recording command will usually answer with 'Command complete' |
285 | * on success, but when the specific service was never connected | 282 | * on success, but when the specific service was never connected |
286 | * before then there might be an additional informational message | 283 | * before then there might be an additional informational message |
287 | * 'HCPCRC8072I Recording entry not found' before the | 284 | * 'HCPCRC8072I Recording entry not found' before the |
288 | * 'Command complete'. So I use strstr rather then the strncmp. | 285 | * 'Command complete'. So I use strstr rather then the strncmp. |
289 | */ | 286 | */ |
290 | if (strstr(cp_response,"Command complete")) | 287 | if (strstr(cp_response,"Command complete")) |
291 | return 0; | 288 | rc = 0; |
292 | else | 289 | else |
293 | return -EIO; | 290 | rc = -EIO; |
291 | /* | ||
292 | * If we turn recording off, we have to purge any remaining records | ||
293 | * afterwards, as a large number of queued records may impact z/VM | ||
294 | * performance. | ||
295 | */ | ||
296 | if (purge && (action == 0)) { | ||
297 | memset(cp_command, 0x00, sizeof(cp_command)); | ||
298 | memset(cp_response, 0x00, sizeof(cp_response)); | ||
299 | snprintf(cp_command, sizeof(cp_command), | ||
300 | "RECORDING %s PURGE %s", | ||
301 | logptr->recording_name, | ||
302 | qid_string); | ||
303 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); | ||
304 | } | ||
294 | 305 | ||
306 | return rc; | ||
295 | } | 307 | } |
296 | 308 | ||
297 | 309 | ||
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 2ff8a22d4257..e8391b89eff4 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -1455,7 +1455,16 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) | |||
1455 | break; | 1455 | break; |
1456 | case IO_SCH_UNREG_ATTACH: | 1456 | case IO_SCH_UNREG_ATTACH: |
1457 | case IO_SCH_UNREG: | 1457 | case IO_SCH_UNREG: |
1458 | if (cdev) | 1458 | if (!cdev) |
1459 | break; | ||
1460 | if (cdev->private->state == DEV_STATE_SENSE_ID) { | ||
1461 | /* | ||
1462 | * Note: delayed work triggered by this event | ||
1463 | * and repeated calls to sch_event are synchronized | ||
1464 | * by the above check for work_pending(cdev). | ||
1465 | */ | ||
1466 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); | ||
1467 | } else | ||
1459 | ccw_device_set_notoper(cdev); | 1468 | ccw_device_set_notoper(cdev); |
1460 | break; | 1469 | break; |
1461 | case IO_SCH_NOP: | 1470 | case IO_SCH_NOP: |