Skip to content

Commit f97a6b6

Browse files
Sebastian OttMartin Schwidefsky
authored andcommitted
s390/cio: fix ccw_device_start_timeout API
There are cases a device driver can't start IO because the device is currently in use by cio. In this case the device driver is notified when the device is usable again. Using ccw_device_start_timeout we would set the timeout (and change an existing timeout) before we test for internal usage. Worst case this could lead to an unexpected timer deletion. Fix this by setting the timeout after we test for internal usage. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
1 parent dc24b7b commit f97a6b6

File tree

1 file changed

+32
-40
lines changed

1 file changed

+32
-40
lines changed

drivers/s390/cio/device_ops.c

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
159159
}
160160

161161
/**
162-
* ccw_device_start_key() - start a s390 channel program with key
162+
* ccw_device_start_timeout_key() - start a s390 channel program with timeout and key
163163
* @cdev: target ccw device
164164
* @cpa: logical start address of channel program
165165
* @intparm: user specific interruption parameter; will be presented back to
@@ -170,10 +170,15 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
170170
* @key: storage key to be used for the I/O
171171
* @flags: additional flags; defines the action to be performed for I/O
172172
* processing.
173+
* @expires: timeout value in jiffies
173174
*
174175
* Start a S/390 channel program. When the interrupt arrives, the
175176
* IRQ handler is called, either immediately, delayed (dev-end missing,
176177
* or sense required) or never (no IRQ handler registered).
178+
* This function notifies the device driver if the channel program has not
179+
* completed during the time specified by @expires. If a timeout occurs, the
180+
* channel program is terminated via xsch, hsch or csch, and the device's
181+
* interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
177182
* Returns:
178183
* %0, if the operation was successful;
179184
* -%EBUSY, if the device is busy, or status pending;
@@ -182,9 +187,9 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
182187
* Context:
183188
* Interrupts disabled, ccw device lock held
184189
*/
185-
int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
186-
unsigned long intparm, __u8 lpm, __u8 key,
187-
unsigned long flags)
190+
int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
191+
unsigned long intparm, __u8 lpm, __u8 key,
192+
unsigned long flags, int expires)
188193
{
189194
struct subchannel *sch;
190195
int ret;
@@ -224,6 +229,8 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
224229
switch (ret) {
225230
case 0:
226231
cdev->private->intparm = intparm;
232+
if (expires)
233+
ccw_device_set_timeout(cdev, expires);
227234
break;
228235
case -EACCES:
229236
case -ENODEV:
@@ -234,7 +241,7 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
234241
}
235242

236243
/**
237-
* ccw_device_start_timeout_key() - start a s390 channel program with timeout and key
244+
* ccw_device_start_key() - start a s390 channel program with key
238245
* @cdev: target ccw device
239246
* @cpa: logical start address of channel program
240247
* @intparm: user specific interruption parameter; will be presented back to
@@ -245,15 +252,10 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
245252
* @key: storage key to be used for the I/O
246253
* @flags: additional flags; defines the action to be performed for I/O
247254
* processing.
248-
* @expires: timeout value in jiffies
249255
*
250256
* Start a S/390 channel program. When the interrupt arrives, the
251257
* IRQ handler is called, either immediately, delayed (dev-end missing,
252258
* or sense required) or never (no IRQ handler registered).
253-
* This function notifies the device driver if the channel program has not
254-
* completed during the time specified by @expires. If a timeout occurs, the
255-
* channel program is terminated via xsch, hsch or csch, and the device's
256-
* interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
257259
* Returns:
258260
* %0, if the operation was successful;
259261
* -%EBUSY, if the device is busy, or status pending;
@@ -262,19 +264,12 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
262264
* Context:
263265
* Interrupts disabled, ccw device lock held
264266
*/
265-
int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
266-
unsigned long intparm, __u8 lpm, __u8 key,
267-
unsigned long flags, int expires)
267+
int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
268+
unsigned long intparm, __u8 lpm, __u8 key,
269+
unsigned long flags)
268270
{
269-
int ret;
270-
271-
if (!cdev)
272-
return -ENODEV;
273-
ccw_device_set_timeout(cdev, expires);
274-
ret = ccw_device_start_key(cdev, cpa, intparm, lpm, key, flags);
275-
if (ret != 0)
276-
ccw_device_set_timeout(cdev, 0);
277-
return ret;
271+
return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, key,
272+
flags, 0);
278273
}
279274

280275
/**
@@ -489,18 +484,20 @@ void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id)
489484
EXPORT_SYMBOL(ccw_device_get_id);
490485

491486
/**
492-
* ccw_device_tm_start_key() - perform start function
487+
* ccw_device_tm_start_timeout_key() - perform start function
493488
* @cdev: ccw device on which to perform the start function
494489
* @tcw: transport-command word to be started
495490
* @intparm: user defined parameter to be passed to the interrupt handler
496491
* @lpm: mask of paths to use
497492
* @key: storage key to use for storage access
493+
* @expires: time span in jiffies after which to abort request
498494
*
499495
* Start the tcw on the given ccw device. Return zero on success, non-zero
500496
* otherwise.
501497
*/
502-
int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
503-
unsigned long intparm, u8 lpm, u8 key)
498+
int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw,
499+
unsigned long intparm, u8 lpm, u8 key,
500+
int expires)
504501
{
505502
struct subchannel *sch;
506503
int rc;
@@ -527,37 +524,32 @@ int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
527524
return -EACCES;
528525
}
529526
rc = cio_tm_start_key(sch, tcw, lpm, key);
530-
if (rc == 0)
527+
if (rc == 0) {
531528
cdev->private->intparm = intparm;
529+
if (expires)
530+
ccw_device_set_timeout(cdev, expires);
531+
}
532532
return rc;
533533
}
534-
EXPORT_SYMBOL(ccw_device_tm_start_key);
534+
EXPORT_SYMBOL(ccw_device_tm_start_timeout_key);
535535

536536
/**
537-
* ccw_device_tm_start_timeout_key() - perform start function
537+
* ccw_device_tm_start_key() - perform start function
538538
* @cdev: ccw device on which to perform the start function
539539
* @tcw: transport-command word to be started
540540
* @intparm: user defined parameter to be passed to the interrupt handler
541541
* @lpm: mask of paths to use
542542
* @key: storage key to use for storage access
543-
* @expires: time span in jiffies after which to abort request
544543
*
545544
* Start the tcw on the given ccw device. Return zero on success, non-zero
546545
* otherwise.
547546
*/
548-
int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw,
549-
unsigned long intparm, u8 lpm, u8 key,
550-
int expires)
547+
int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
548+
unsigned long intparm, u8 lpm, u8 key)
551549
{
552-
int ret;
553-
554-
ccw_device_set_timeout(cdev, expires);
555-
ret = ccw_device_tm_start_key(cdev, tcw, intparm, lpm, key);
556-
if (ret != 0)
557-
ccw_device_set_timeout(cdev, 0);
558-
return ret;
550+
return ccw_device_tm_start_timeout_key(cdev, tcw, intparm, lpm, key, 0);
559551
}
560-
EXPORT_SYMBOL(ccw_device_tm_start_timeout_key);
552+
EXPORT_SYMBOL(ccw_device_tm_start_key);
561553

562554
/**
563555
* ccw_device_tm_start() - perform start function

0 commit comments

Comments
 (0)