|
@@ -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);
|
|
|
|
|
@@ -818,7 +817,6 @@ void qeth_clear_cmd_buffers(struct qeth_channel *channel)
|
|
|
|
|
|
for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
|
|
|
qeth_release_buffer(channel, &channel->iob[cnt]);
|
|
|
- channel->buf_no = 0;
|
|
|
channel->io_buf_no = 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers);
|
|
@@ -924,7 +922,6 @@ static int qeth_setup_channel(struct qeth_channel *channel)
|
|
|
kfree(channel->iob[cnt].data);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
- channel->buf_no = 0;
|
|
|
channel->io_buf_no = 0;
|
|
|
atomic_set(&channel->irq_pending, 0);
|
|
|
spin_lock_init(&channel->iob_lock);
|
|
@@ -1100,16 +1097,9 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|
|
{
|
|
|
int rc;
|
|
|
int cstat, dstat;
|
|
|
- struct qeth_cmd_buffer *buffer;
|
|
|
+ struct qeth_cmd_buffer *iob = NULL;
|
|
|
struct qeth_channel *channel;
|
|
|
struct qeth_card *card;
|
|
|
- struct qeth_cmd_buffer *iob;
|
|
|
- __u8 index;
|
|
|
-
|
|
|
- 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)
|
|
@@ -1127,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))
|
|
@@ -1150,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)) {
|
|
@@ -1182,25 +1189,15 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|
|
channel->state = CH_STATE_RCD_DONE;
|
|
|
goto out;
|
|
|
}
|
|
|
- if (intparm) {
|
|
|
- buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
|
|
|
- buffer->state = BUF_STATE_PROCESSED;
|
|
|
- }
|
|
|
if (channel == &card->data)
|
|
|
return;
|
|
|
if (channel == &card->read &&
|
|
|
channel->state == CH_STATE_UP)
|
|
|
__qeth_issue_next_read(card);
|
|
|
|
|
|
- iob = channel->iob;
|
|
|
- index = channel->buf_no;
|
|
|
- while (iob[index].state == BUF_STATE_PROCESSED) {
|
|
|
- if (iob[index].callback != NULL)
|
|
|
- iob[index].callback(channel, iob + index);
|
|
|
+ if (iob && iob->callback)
|
|
|
+ iob->callback(iob->channel, iob);
|
|
|
|
|
|
- index = (index + 1) % QETH_CMD_BUFFER_NO;
|
|
|
- }
|
|
|
- channel->buf_no = index;
|
|
|
out:
|
|
|
wake_up(&card->wait_q);
|
|
|
return;
|
|
@@ -1870,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) {
|
|
@@ -1888,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;
|
|
@@ -1942,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) {
|
|
@@ -1964,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);
|
|
@@ -2166,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: "
|
|
@@ -2199,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;
|
|
@@ -2211,10 +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);
|
|
|
- card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO;
|
|
|
rc = reply->rc;
|
|
|
qeth_put_reply(reply);
|
|
|
return rc;
|
|
@@ -3033,28 +3022,23 @@ static int qeth_send_startlan(struct qeth_card *card)
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-static int qeth_default_setadapterparms_cb(struct qeth_card *card,
|
|
|
- struct qeth_reply *reply, unsigned long data)
|
|
|
+static int qeth_setadpparms_inspect_rc(struct qeth_ipa_cmd *cmd)
|
|
|
{
|
|
|
- struct qeth_ipa_cmd *cmd;
|
|
|
-
|
|
|
- QETH_CARD_TEXT(card, 4, "defadpcb");
|
|
|
-
|
|
|
- cmd = (struct qeth_ipa_cmd *) data;
|
|
|
- if (cmd->hdr.return_code == 0)
|
|
|
+ if (!cmd->hdr.return_code)
|
|
|
cmd->hdr.return_code =
|
|
|
cmd->data.setadapterparms.hdr.return_code;
|
|
|
- return 0;
|
|
|
+ return cmd->hdr.return_code;
|
|
|
}
|
|
|
|
|
|
static int qeth_query_setadapterparms_cb(struct qeth_card *card,
|
|
|
struct qeth_reply *reply, unsigned long data)
|
|
|
{
|
|
|
- struct qeth_ipa_cmd *cmd;
|
|
|
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
|
|
|
|
|
QETH_CARD_TEXT(card, 3, "quyadpcb");
|
|
|
+ if (qeth_setadpparms_inspect_rc(cmd))
|
|
|
+ return 0;
|
|
|
|
|
|
- cmd = (struct qeth_ipa_cmd *) data;
|
|
|
if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) {
|
|
|
card->info.link_type =
|
|
|
cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
|
|
@@ -3062,7 +3046,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
|
|
|
}
|
|
|
card->options.adp.supported_funcs =
|
|
|
cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
|
|
|
- return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
|
|
@@ -3154,22 +3138,20 @@ EXPORT_SYMBOL_GPL(qeth_query_ipassists);
|
|
|
static int qeth_query_switch_attributes_cb(struct qeth_card *card,
|
|
|
struct qeth_reply *reply, unsigned long data)
|
|
|
{
|
|
|
- struct qeth_ipa_cmd *cmd;
|
|
|
- struct qeth_switch_info *sw_info;
|
|
|
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
|
|
struct qeth_query_switch_attributes *attrs;
|
|
|
+ struct qeth_switch_info *sw_info;
|
|
|
|
|
|
QETH_CARD_TEXT(card, 2, "qswiatcb");
|
|
|
- cmd = (struct qeth_ipa_cmd *) data;
|
|
|
- sw_info = (struct qeth_switch_info *)reply->param;
|
|
|
- if (cmd->data.setadapterparms.hdr.return_code == 0) {
|
|
|
- attrs = &cmd->data.setadapterparms.data.query_switch_attributes;
|
|
|
- sw_info->capabilities = attrs->capabilities;
|
|
|
- sw_info->settings = attrs->settings;
|
|
|
- QETH_CARD_TEXT_(card, 2, "%04x%04x", sw_info->capabilities,
|
|
|
- sw_info->settings);
|
|
|
- }
|
|
|
- qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
|
|
|
+ if (qeth_setadpparms_inspect_rc(cmd))
|
|
|
+ return 0;
|
|
|
|
|
|
+ sw_info = (struct qeth_switch_info *)reply->param;
|
|
|
+ attrs = &cmd->data.setadapterparms.data.query_switch_attributes;
|
|
|
+ sw_info->capabilities = attrs->capabilities;
|
|
|
+ sw_info->settings = attrs->settings;
|
|
|
+ QETH_CARD_TEXT_(card, 2, "%04x%04x", sw_info->capabilities,
|
|
|
+ sw_info->settings);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -4207,16 +4189,13 @@ EXPORT_SYMBOL_GPL(qeth_do_send_packet);
|
|
|
static int qeth_setadp_promisc_mode_cb(struct qeth_card *card,
|
|
|
struct qeth_reply *reply, unsigned long data)
|
|
|
{
|
|
|
- struct qeth_ipa_cmd *cmd;
|
|
|
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
|
|
struct qeth_ipacmd_setadpparms *setparms;
|
|
|
|
|
|
QETH_CARD_TEXT(card, 4, "prmadpcb");
|
|
|
|
|
|
- cmd = (struct qeth_ipa_cmd *) data;
|
|
|
setparms = &(cmd->data.setadapterparms);
|
|
|
-
|
|
|
- qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
|
|
|
- if (cmd->hdr.return_code) {
|
|
|
+ if (qeth_setadpparms_inspect_rc(cmd)) {
|
|
|
QETH_CARD_TEXT_(card, 4, "prmrc%x", cmd->hdr.return_code);
|
|
|
setparms->data.mode = SET_PROMISC_MODE_OFF;
|
|
|
}
|
|
@@ -4286,18 +4265,18 @@ EXPORT_SYMBOL_GPL(qeth_get_stats);
|
|
|
static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
|
|
|
struct qeth_reply *reply, unsigned long data)
|
|
|
{
|
|
|
- struct qeth_ipa_cmd *cmd;
|
|
|
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
|
|
|
|
|
QETH_CARD_TEXT(card, 4, "chgmaccb");
|
|
|
+ if (qeth_setadpparms_inspect_rc(cmd))
|
|
|
+ return 0;
|
|
|
|
|
|
- cmd = (struct qeth_ipa_cmd *) data;
|
|
|
if (!card->options.layer2 ||
|
|
|
!(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
|
|
|
ether_addr_copy(card->dev->dev_addr,
|
|
|
cmd->data.setadapterparms.data.change_addr.addr);
|
|
|
card->info.mac_bits |= QETH_LAYER2_MAC_READ;
|
|
|
}
|
|
|
- qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -4328,13 +4307,15 @@ EXPORT_SYMBOL_GPL(qeth_setadpparms_change_macaddr);
|
|
|
static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
|
|
|
struct qeth_reply *reply, unsigned long data)
|
|
|
{
|
|
|
- struct qeth_ipa_cmd *cmd;
|
|
|
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
|
|
|
struct qeth_set_access_ctrl *access_ctrl_req;
|
|
|
int fallback = *(int *)reply->param;
|
|
|
|
|
|
QETH_CARD_TEXT(card, 4, "setaccb");
|
|
|
+ if (cmd->hdr.return_code)
|
|
|
+ return 0;
|
|
|
+ qeth_setadpparms_inspect_rc(cmd);
|
|
|
|
|
|
- cmd = (struct qeth_ipa_cmd *) data;
|
|
|
access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
|
|
|
QETH_DBF_TEXT_(SETUP, 2, "setaccb");
|
|
|
QETH_DBF_TEXT_(SETUP, 2, "%s", card->gdev->dev.kobj.name);
|
|
@@ -4407,7 +4388,6 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
|
|
|
card->options.isolation = card->options.prev_isolation;
|
|
|
break;
|
|
|
}
|
|
|
- qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -4695,14 +4675,15 @@ out:
|
|
|
static int qeth_setadpparms_query_oat_cb(struct qeth_card *card,
|
|
|
struct qeth_reply *reply, unsigned long data)
|
|
|
{
|
|
|
- struct qeth_ipa_cmd *cmd;
|
|
|
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
|
|
|
struct qeth_qoat_priv *priv;
|
|
|
char *resdata;
|
|
|
int resdatalen;
|
|
|
|
|
|
QETH_CARD_TEXT(card, 3, "qoatcb");
|
|
|
+ if (qeth_setadpparms_inspect_rc(cmd))
|
|
|
+ return 0;
|
|
|
|
|
|
- cmd = (struct qeth_ipa_cmd *)data;
|
|
|
priv = (struct qeth_qoat_priv *)reply->param;
|
|
|
resdatalen = cmd->data.setadapterparms.hdr.cmdlength;
|
|
|
resdata = (char *)data + 28;
|
|
@@ -4796,21 +4777,18 @@ out:
|
|
|
static int qeth_query_card_info_cb(struct qeth_card *card,
|
|
|
struct qeth_reply *reply, unsigned long data)
|
|
|
{
|
|
|
- struct qeth_ipa_cmd *cmd;
|
|
|
+ struct carrier_info *carrier_info = (struct carrier_info *)reply->param;
|
|
|
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
|
|
|
struct qeth_query_card_info *card_info;
|
|
|
- struct carrier_info *carrier_info;
|
|
|
|
|
|
QETH_CARD_TEXT(card, 2, "qcrdincb");
|
|
|
- carrier_info = (struct carrier_info *)reply->param;
|
|
|
- cmd = (struct qeth_ipa_cmd *)data;
|
|
|
- card_info = &cmd->data.setadapterparms.data.card_info;
|
|
|
- if (cmd->data.setadapterparms.hdr.return_code == 0) {
|
|
|
- carrier_info->card_type = card_info->card_type;
|
|
|
- carrier_info->port_mode = card_info->port_mode;
|
|
|
- carrier_info->port_speed = card_info->port_speed;
|
|
|
- }
|
|
|
+ if (qeth_setadpparms_inspect_rc(cmd))
|
|
|
+ return 0;
|
|
|
|
|
|
- qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
|
|
|
+ card_info = &cmd->data.setadapterparms.data.card_info;
|
|
|
+ carrier_info->card_type = card_info->card_type;
|
|
|
+ carrier_info->port_mode = card_info->port_mode;
|
|
|
+ carrier_info->port_speed = card_info->port_speed;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -4857,7 +4835,7 @@ int qeth_vm_request_mac(struct qeth_card *card)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- ccw_device_get_id(CARD_DDEV(card), &id);
|
|
|
+ ccw_device_get_id(CARD_RDEV(card), &id);
|
|
|
request->resp_buf_len = sizeof(*response);
|
|
|
request->resp_version = DIAG26C_VERSION2;
|
|
|
request->op_code = DIAG26C_GET_MAC;
|
|
@@ -6563,10 +6541,14 @@ static int __init qeth_core_init(void)
|
|
|
mutex_init(&qeth_mod_mutex);
|
|
|
|
|
|
qeth_wq = create_singlethread_workqueue("qeth_wq");
|
|
|
+ if (!qeth_wq) {
|
|
|
+ rc = -ENOMEM;
|
|
|
+ goto out_err;
|
|
|
+ }
|
|
|
|
|
|
rc = qeth_register_dbf_views();
|
|
|
if (rc)
|
|
|
- goto out_err;
|
|
|
+ goto dbf_err;
|
|
|
qeth_core_root_dev = root_device_register("qeth");
|
|
|
rc = PTR_ERR_OR_ZERO(qeth_core_root_dev);
|
|
|
if (rc)
|
|
@@ -6603,6 +6585,8 @@ slab_err:
|
|
|
root_device_unregister(qeth_core_root_dev);
|
|
|
register_err:
|
|
|
qeth_unregister_dbf_views();
|
|
|
+dbf_err:
|
|
|
+ destroy_workqueue(qeth_wq);
|
|
|
out_err:
|
|
|
pr_err("Initializing the qeth device driver failed\n");
|
|
|
return rc;
|