Merge branch 's390-qeth-fixes'
Julian Wiedmann says: ==================== s390/qeth: fixes 2018-04-19 Please apply the following qeth fixes for 4.17. The common theme seems to be error handling improvements in various areas of cmd IO. Patches 1-3 should also go back to stable. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
353697e6e6
|
@ -557,7 +557,6 @@ enum qeth_prot_versions {
|
|||
enum qeth_cmd_buffer_state {
|
||||
BUF_STATE_FREE,
|
||||
BUF_STATE_LOCKED,
|
||||
BUF_STATE_PROCESSED,
|
||||
};
|
||||
|
||||
enum qeth_cq {
|
||||
|
@ -601,7 +600,6 @@ struct qeth_channel {
|
|||
struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
|
||||
atomic_t irq_pending;
|
||||
int io_buf_no;
|
||||
int buf_no;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -35,6 +35,18 @@ extern unsigned char IPA_PDU_HEADER[];
|
|||
#define QETH_HALT_CHANNEL_PARM -11
|
||||
#define QETH_RCD_PARM -12
|
||||
|
||||
static inline bool qeth_intparm_is_iob(unsigned long intparm)
|
||||
{
|
||||
switch (intparm) {
|
||||
case QETH_CLEAR_CHANNEL_PARM:
|
||||
case QETH_HALT_CHANNEL_PARM:
|
||||
case QETH_RCD_PARM:
|
||||
case 0:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* IP Assist related definitions */
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -121,13 +121,10 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
|
|||
QETH_CARD_TEXT(card, 2, "L2Setmac");
|
||||
rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC);
|
||||
if (rc == 0) {
|
||||
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
|
||||
ether_addr_copy(card->dev->dev_addr, mac);
|
||||
dev_info(&card->gdev->dev,
|
||||
"MAC address %pM successfully registered on device %s\n",
|
||||
card->dev->dev_addr, card->dev->name);
|
||||
"MAC address %pM successfully registered on device %s\n",
|
||||
mac, card->dev->name);
|
||||
} else {
|
||||
card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
|
||||
switch (rc) {
|
||||
case -EEXIST:
|
||||
dev_warn(&card->gdev->dev,
|
||||
|
@ -142,19 +139,6 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac)
|
||||
{
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "L2Delmac");
|
||||
if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
|
||||
return 0;
|
||||
rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC);
|
||||
if (rc == 0)
|
||||
card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac)
|
||||
{
|
||||
enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ?
|
||||
|
@ -519,6 +503,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
|
|||
{
|
||||
struct sockaddr *addr = p;
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
u8 old_addr[ETH_ALEN];
|
||||
int rc = 0;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "setmac");
|
||||
|
@ -530,14 +515,35 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
QETH_CARD_HEX(card, 3, addr->sa_data, ETH_ALEN);
|
||||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
|
||||
QETH_CARD_TEXT(card, 3, "setmcREC");
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
|
||||
if (!rc || (rc == -ENOENT))
|
||||
rc = qeth_l2_send_setmac(card, addr->sa_data);
|
||||
return rc ? -EINVAL : 0;
|
||||
|
||||
if (!qeth_card_hw_is_reachable(card)) {
|
||||
ether_addr_copy(dev->dev_addr, addr->sa_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* don't register the same address twice */
|
||||
if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) &&
|
||||
(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
|
||||
return 0;
|
||||
|
||||
/* add the new address, switch over, drop the old */
|
||||
rc = qeth_l2_send_setmac(card, addr->sa_data);
|
||||
if (rc)
|
||||
return rc;
|
||||
ether_addr_copy(old_addr, dev->dev_addr);
|
||||
ether_addr_copy(dev->dev_addr, addr->sa_data);
|
||||
|
||||
if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)
|
||||
qeth_l2_remove_mac(card, old_addr);
|
||||
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qeth_promisc_to_bridge(struct qeth_card *card)
|
||||
|
@ -1067,8 +1073,9 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
goto out_remove;
|
||||
}
|
||||
|
||||
if (card->info.type != QETH_CARD_TYPE_OSN)
|
||||
qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
|
||||
if (card->info.type != QETH_CARD_TYPE_OSN &&
|
||||
!qeth_l2_send_setmac(card, card->dev->dev_addr))
|
||||
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
|
||||
|
||||
if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
|
||||
if (card->info.hwtrap &&
|
||||
|
@ -1338,8 +1345,8 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
|
|||
qeth_prepare_control_data(card, len, iob);
|
||||
QETH_CARD_TEXT(card, 6, "osnoirqp");
|
||||
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, QETH_IPA_TIMEOUT);
|
||||
spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
|
||||
if (rc) {
|
||||
QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "
|
||||
|
|
Loading…
Reference in New Issue