|
@@ -706,7 +706,6 @@ void qeth_clear_ipacmd_list(struct qeth_card *card)
|
|
|
qeth_put_reply(reply);
|
|
|
}
|
|
|
spin_unlock_irqrestore(&card->lock, flags);
|
|
|
- atomic_set(&card->write.irq_pending, 0);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list);
|
|
|
|
|
@@ -1098,14 +1097,9 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|
|
{
|
|
|
int rc;
|
|
|
int cstat, dstat;
|
|
|
+ struct qeth_cmd_buffer *iob = NULL;
|
|
|
struct qeth_channel *channel;
|
|
|
struct qeth_card *card;
|
|
|
- struct qeth_cmd_buffer *iob;
|
|
|
-
|
|
|
- if (__qeth_check_irb_error(cdev, intparm, irb))
|
|
|
- return;
|
|
|
- cstat = irb->scsw.cmd.cstat;
|
|
|
- dstat = irb->scsw.cmd.dstat;
|
|
|
|
|
|
card = CARD_FROM_CDEV(cdev);
|
|
|
if (!card)
|
|
@@ -1123,6 +1117,19 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|
|
channel = &card->data;
|
|
|
QETH_CARD_TEXT(card, 5, "data");
|
|
|
}
|
|
|
+
|
|
|
+ if (qeth_intparm_is_iob(intparm))
|
|
|
+ iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
|
|
|
+
|
|
|
+ if (__qeth_check_irb_error(cdev, intparm, irb)) {
|
|
|
+ /* IO was terminated, free its resources. */
|
|
|
+ if (iob)
|
|
|
+ qeth_release_buffer(iob->channel, iob);
|
|
|
+ atomic_set(&channel->irq_pending, 0);
|
|
|
+ wake_up(&card->wait_q);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
atomic_set(&channel->irq_pending, 0);
|
|
|
|
|
|
if (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC))
|
|
@@ -1146,6 +1153,10 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|
|
/* we don't have to handle this further */
|
|
|
intparm = 0;
|
|
|
}
|
|
|
+
|
|
|
+ cstat = irb->scsw.cmd.cstat;
|
|
|
+ dstat = irb->scsw.cmd.dstat;
|
|
|
+
|
|
|
if ((dstat & DEV_STAT_UNIT_EXCEP) ||
|
|
|
(dstat & DEV_STAT_UNIT_CHECK) ||
|
|
|
(cstat)) {
|
|
@@ -1184,11 +1195,8 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|
|
channel->state == CH_STATE_UP)
|
|
|
__qeth_issue_next_read(card);
|
|
|
|
|
|
- if (intparm) {
|
|
|
- iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
|
|
|
- if (iob->callback)
|
|
|
- iob->callback(iob->channel, iob);
|
|
|
- }
|
|
|
+ if (iob && iob->callback)
|
|
|
+ iob->callback(iob->channel, iob);
|
|
|
|
|
|
out:
|
|
|
wake_up(&card->wait_q);
|
|
@@ -1859,8 +1867,8 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
|
|
|
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
|
|
|
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
|
|
|
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
|
|
- rc = ccw_device_start(channel->ccwdev,
|
|
|
- &channel->ccw, (addr_t) iob, 0, 0);
|
|
|
+ rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
|
|
|
+ (addr_t) iob, 0, 0, QETH_TIMEOUT);
|
|
|
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
|
|
|
|
|
if (rc) {
|
|
@@ -1877,7 +1885,6 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
|
|
|
if (channel->state != CH_STATE_UP) {
|
|
|
rc = -ETIME;
|
|
|
QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
|
|
|
- qeth_clear_cmd_buffers(channel);
|
|
|
} else
|
|
|
rc = 0;
|
|
|
return rc;
|
|
@@ -1931,8 +1938,8 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel,
|
|
|
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
|
|
|
QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
|
|
|
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
|
|
- rc = ccw_device_start(channel->ccwdev,
|
|
|
- &channel->ccw, (addr_t) iob, 0, 0);
|
|
|
+ rc = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
|
|
|
+ (addr_t) iob, 0, 0, QETH_TIMEOUT);
|
|
|
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
|
|
|
|
|
if (rc) {
|
|
@@ -1953,7 +1960,6 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel,
|
|
|
QETH_DBF_MESSAGE(2, "%s IDX activate timed out\n",
|
|
|
dev_name(&channel->ccwdev->dev));
|
|
|
QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME);
|
|
|
- qeth_clear_cmd_buffers(channel);
|
|
|
return -ETIME;
|
|
|
}
|
|
|
return qeth_idx_activate_get_answer(channel, idx_reply_cb);
|
|
@@ -2155,8 +2161,8 @@ int qeth_send_control_data(struct qeth_card *card, int len,
|
|
|
|
|
|
QETH_CARD_TEXT(card, 6, "noirqpnd");
|
|
|
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
|
|
|
- rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
|
|
|
- (addr_t) iob, 0, 0);
|
|
|
+ rc = ccw_device_start_timeout(CARD_WDEV(card), &card->write.ccw,
|
|
|
+ (addr_t) iob, 0, 0, event_timeout);
|
|
|
spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
|
|
|
if (rc) {
|
|
|
QETH_DBF_MESSAGE(2, "%s qeth_send_control_data: "
|
|
@@ -2188,8 +2194,6 @@ int qeth_send_control_data(struct qeth_card *card, int len,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (reply->rc == -EIO)
|
|
|
- goto error;
|
|
|
rc = reply->rc;
|
|
|
qeth_put_reply(reply);
|
|
|
return rc;
|
|
@@ -2200,9 +2204,6 @@ time_err:
|
|
|
list_del_init(&reply->list);
|
|
|
spin_unlock_irqrestore(&reply->card->lock, flags);
|
|
|
atomic_inc(&reply->received);
|
|
|
-error:
|
|
|
- atomic_set(&card->write.irq_pending, 0);
|
|
|
- qeth_release_buffer(iob->channel, iob);
|
|
|
rc = reply->rc;
|
|
|
qeth_put_reply(reply);
|
|
|
return rc;
|