aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-11-16 12:27:13 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-11-16 12:27:13 -0500
commit2ebc8ec86fe0f3f3acf9ba9b41a368f819e7807e (patch)
treec0b3d4f14ae6dd98318d78fcf7d16f47954e06a4 /drivers/s390
parentdf6e61d4ca268dc8706db38222fde9f04701566c (diff)
parent89480801a17a3069f45169d40b828c8e511aa005 (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.c68
-rw-r--r--drivers/s390/char/vmlogrdr.c36
-rw-r--r--drivers/s390/cio/device.c11
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
212struct tape_med_state_work_data {
213 struct tape_device *device;
214 enum tape_medium_state state;
215 struct work_struct work;
216};
217
218static void
219tape_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
248static void
249tape_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
212void 262void
213tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) 263tape_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: