mirror of https://gitee.com/openkylin/linux.git
Merge branch 'qeth-next'
Ursula Braun says: ==================== s390: network patches for net-next here are s390 related patches for net-next ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
17032ae32d
|
@ -1,6 +1,6 @@
|
|||
IBM s390 QDIO Ethernet Driver
|
||||
|
||||
HiperSockets Bridge Port Support
|
||||
OSA and HiperSockets Bridge Port Support
|
||||
|
||||
Uevents
|
||||
|
||||
|
@ -8,7 +8,7 @@ To generate the events the device must be assigned a role of either
|
|||
a primary or a secondary Bridge Port. For more information, see
|
||||
"z/VM Connectivity, SC24-6174".
|
||||
|
||||
When run on HiperSockets Bridge Capable Port hardware, and the state
|
||||
When run on an OSA or HiperSockets Bridge Capable Port hardware, and the state
|
||||
of some configured Bridge Port device on the channel changes, a udev
|
||||
event with ACTION=CHANGE is emitted on behalf of the corresponding
|
||||
ccwgroup device. The event has the following attributes:
|
||||
|
|
|
@ -2150,7 +2150,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
|
|||
rc = lcs_detect(card);
|
||||
if (rc) {
|
||||
LCS_DBF_TEXT(2, setup, "dtctfail");
|
||||
dev_err(&card->dev->dev,
|
||||
dev_err(&ccwgdev->dev,
|
||||
"Detecting a network adapter for LCS devices"
|
||||
" failed with rc=%d (0x%x)\n", rc, rc);
|
||||
lcs_stopcard(card);
|
||||
|
|
|
@ -175,6 +175,8 @@ struct qeth_sbp_info {
|
|||
__u32 supported_funcs;
|
||||
enum qeth_sbp_roles role;
|
||||
__u32 hostnotification:1;
|
||||
__u32 reflect_promisc:1;
|
||||
__u32 reflect_promisc_primary:1;
|
||||
};
|
||||
|
||||
static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa,
|
||||
|
|
|
@ -645,7 +645,8 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
|
|||
card->info.hwtrap = 2;
|
||||
qeth_schedule_recovery(card);
|
||||
return NULL;
|
||||
case IPA_CMD_SETBRIDGEPORT:
|
||||
case IPA_CMD_SETBRIDGEPORT_IQD:
|
||||
case IPA_CMD_SETBRIDGEPORT_OSA:
|
||||
case IPA_CMD_ADDRESS_CHANGE_NOTIF:
|
||||
if (card->discipline->control_event_handler
|
||||
(card, cmd))
|
||||
|
|
|
@ -237,6 +237,7 @@ static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
|
|||
{IPA_CMD_DELGMAC, "delgmac"},
|
||||
{IPA_CMD_SETVLAN, "setvlan"},
|
||||
{IPA_CMD_DELVLAN, "delvlan"},
|
||||
{IPA_CMD_SETBRIDGEPORT_OSA, "set_bridge_port(osa)"},
|
||||
{IPA_CMD_SETCCID, "setccid"},
|
||||
{IPA_CMD_DELCCID, "delccid"},
|
||||
{IPA_CMD_MODCCID, "modccid"},
|
||||
|
@ -249,7 +250,7 @@ static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
|
|||
{IPA_CMD_DELIP, "delip"},
|
||||
{IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
|
||||
{IPA_CMD_SET_DIAG_ASS, "set_diag_ass"},
|
||||
{IPA_CMD_SETBRIDGEPORT, "set_bridge_port"},
|
||||
{IPA_CMD_SETBRIDGEPORT_IQD, "set_bridge_port(hs)"},
|
||||
{IPA_CMD_CREATE_ADDR, "create_addr"},
|
||||
{IPA_CMD_DESTROY_ADDR, "destroy_addr"},
|
||||
{IPA_CMD_REGISTER_LOCAL_ADDR, "register_local_addr"},
|
||||
|
|
|
@ -92,6 +92,7 @@ enum qeth_ipa_cmds {
|
|||
IPA_CMD_DELGMAC = 0x24,
|
||||
IPA_CMD_SETVLAN = 0x25,
|
||||
IPA_CMD_DELVLAN = 0x26,
|
||||
IPA_CMD_SETBRIDGEPORT_OSA = 0x2b,
|
||||
IPA_CMD_SETCCID = 0x41,
|
||||
IPA_CMD_DELCCID = 0x42,
|
||||
IPA_CMD_MODCCID = 0x43,
|
||||
|
@ -104,7 +105,7 @@ enum qeth_ipa_cmds {
|
|||
IPA_CMD_DELIP = 0xb7,
|
||||
IPA_CMD_SETADAPTERPARMS = 0xb8,
|
||||
IPA_CMD_SET_DIAG_ASS = 0xb9,
|
||||
IPA_CMD_SETBRIDGEPORT = 0xbe,
|
||||
IPA_CMD_SETBRIDGEPORT_IQD = 0xbe,
|
||||
IPA_CMD_CREATE_ADDR = 0xc3,
|
||||
IPA_CMD_DESTROY_ADDR = 0xc4,
|
||||
IPA_CMD_REGISTER_LOCAL_ADDR = 0xd1,
|
||||
|
|
|
@ -137,7 +137,7 @@ static int qeth_setdel_makerc(struct qeth_card *card, int retcode)
|
|||
rc = 0;
|
||||
break;
|
||||
case IPA_RC_L2_UNSUPPORTED_CMD:
|
||||
rc = -ENOSYS;
|
||||
rc = -EOPNOTSUPP;
|
||||
break;
|
||||
case IPA_RC_L2_ADDR_TABLE_FULL:
|
||||
rc = -ENOSPC;
|
||||
|
@ -683,6 +683,39 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
|
|||
return rc ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static void qeth_promisc_to_bridge(struct qeth_card *card)
|
||||
{
|
||||
struct net_device *dev = card->dev;
|
||||
enum qeth_ipa_promisc_modes promisc_mode;
|
||||
int role;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "pmisc2br");
|
||||
|
||||
if (!card->options.sbp.reflect_promisc)
|
||||
return;
|
||||
promisc_mode = (dev->flags & IFF_PROMISC) ? SET_PROMISC_MODE_ON
|
||||
: SET_PROMISC_MODE_OFF;
|
||||
if (promisc_mode == card->info.promisc_mode)
|
||||
return;
|
||||
|
||||
if (promisc_mode == SET_PROMISC_MODE_ON) {
|
||||
if (card->options.sbp.reflect_promisc_primary)
|
||||
role = QETH_SBP_ROLE_PRIMARY;
|
||||
else
|
||||
role = QETH_SBP_ROLE_SECONDARY;
|
||||
} else
|
||||
role = QETH_SBP_ROLE_NONE;
|
||||
|
||||
rc = qeth_bridgeport_setrole(card, role);
|
||||
QETH_DBF_TEXT_(SETUP, 2, "bpm%c%04x",
|
||||
(promisc_mode == SET_PROMISC_MODE_ON) ? '+' : '-', rc);
|
||||
if (!rc) {
|
||||
card->options.sbp.role = role;
|
||||
card->info.promisc_mode = promisc_mode;
|
||||
}
|
||||
}
|
||||
|
||||
static void qeth_l2_set_multicast_list(struct net_device *dev)
|
||||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
|
@ -704,9 +737,10 @@ static void qeth_l2_set_multicast_list(struct net_device *dev)
|
|||
qeth_l2_add_mc(card, ha->addr, 1);
|
||||
|
||||
spin_unlock_bh(&card->mclock);
|
||||
if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
|
||||
return;
|
||||
if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
|
||||
qeth_setadp_promisc_mode(card);
|
||||
else
|
||||
qeth_promisc_to_bridge(card);
|
||||
}
|
||||
|
||||
static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
@ -994,7 +1028,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
qeth_bridgeport_query_support(card);
|
||||
if (card->options.sbp.supported_funcs)
|
||||
dev_info(&card->gdev->dev,
|
||||
"The device represents a HiperSockets Bridge Capable Port\n");
|
||||
"The device represents a Bridge Capable Port\n");
|
||||
qeth_trace_features(card);
|
||||
|
||||
if (!card->dev && qeth_l2_setup_netdev(card)) {
|
||||
|
@ -1247,7 +1281,8 @@ static int qeth_l2_control_event(struct qeth_card *card,
|
|||
struct qeth_ipa_cmd *cmd)
|
||||
{
|
||||
switch (cmd->hdr.command) {
|
||||
case IPA_CMD_SETBRIDGEPORT:
|
||||
case IPA_CMD_SETBRIDGEPORT_OSA:
|
||||
case IPA_CMD_SETBRIDGEPORT_IQD:
|
||||
if (cmd->data.sbp.hdr.command_code ==
|
||||
IPA_SBP_BRIDGE_PORT_STATE_CHANGE) {
|
||||
qeth_bridge_state_change(card, cmd);
|
||||
|
@ -1533,7 +1568,7 @@ static void qeth_bridge_host_event_worker(struct work_struct *work)
|
|||
|
||||
if (data->hostevs.lost_event_mask) {
|
||||
dev_info(&data->card->gdev->dev,
|
||||
"Address notification from the HiperSockets Bridge Port stopped %s (%s)\n",
|
||||
"Address notification from the Bridge Port stopped %s (%s)\n",
|
||||
data->card->dev->name,
|
||||
(data->hostevs.lost_event_mask == 0x01)
|
||||
? "Overflow"
|
||||
|
@ -1617,70 +1652,80 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
|
|||
struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd)
|
||||
{
|
||||
int rc;
|
||||
int is_iqd = (card->info.type == QETH_CARD_TYPE_IQD);
|
||||
|
||||
switch (cbctl->ipa_rc) {
|
||||
case IPA_RC_SUCCESS:
|
||||
if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) ||
|
||||
(!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc)))
|
||||
switch (cbctl->cmd_rc) {
|
||||
case 0x0000:
|
||||
rc = 0;
|
||||
break;
|
||||
case 0x2B04:
|
||||
case 0x0004:
|
||||
rc = -ENOSYS;
|
||||
rc = -EOPNOTSUPP;
|
||||
break;
|
||||
case 0x2B0C:
|
||||
case 0x000C: /* Not configured as bridge Port */
|
||||
rc = -ENODEV; /* maybe not the best code here? */
|
||||
dev_err(&card->gdev->dev,
|
||||
"The HiperSockets device is not configured as a Bridge Port\n");
|
||||
"The device is not configured as a Bridge Port\n");
|
||||
break;
|
||||
case 0x2B14:
|
||||
case 0x0014: /* Another device is Primary */
|
||||
switch (setcmd) {
|
||||
case IPA_SBP_SET_PRIMARY_BRIDGE_PORT:
|
||||
rc = -EEXIST;
|
||||
dev_err(&card->gdev->dev,
|
||||
"The HiperSockets LAN already has a primary Bridge Port\n");
|
||||
"The LAN already has a primary Bridge Port\n");
|
||||
break;
|
||||
case IPA_SBP_SET_SECONDARY_BRIDGE_PORT:
|
||||
rc = -EBUSY;
|
||||
dev_err(&card->gdev->dev,
|
||||
"The HiperSockets device is already a primary Bridge Port\n");
|
||||
"The device is already a primary Bridge Port\n");
|
||||
break;
|
||||
default:
|
||||
rc = -EIO;
|
||||
}
|
||||
break;
|
||||
case 0x2B18:
|
||||
case 0x0018: /* This device is currently Secondary */
|
||||
rc = -EBUSY;
|
||||
dev_err(&card->gdev->dev,
|
||||
"The HiperSockets device is already a secondary Bridge Port\n");
|
||||
"The device is already a secondary Bridge Port\n");
|
||||
break;
|
||||
case 0x2B1C:
|
||||
case 0x001C: /* Limit for Secondary devices reached */
|
||||
rc = -EEXIST;
|
||||
dev_err(&card->gdev->dev,
|
||||
"The HiperSockets LAN cannot have more secondary Bridge Ports\n");
|
||||
"The LAN cannot have more secondary Bridge Ports\n");
|
||||
break;
|
||||
case 0x2B24:
|
||||
case 0x0024: /* This device is currently Primary */
|
||||
rc = -EBUSY;
|
||||
dev_err(&card->gdev->dev,
|
||||
"The HiperSockets device is already a primary Bridge Port\n");
|
||||
"The device is already a primary Bridge Port\n");
|
||||
break;
|
||||
case 0x2B20:
|
||||
case 0x0020: /* Not authorized by zManager */
|
||||
rc = -EACCES;
|
||||
dev_err(&card->gdev->dev,
|
||||
"The HiperSockets device is not authorized to be a Bridge Port\n");
|
||||
"The device is not authorized to be a Bridge Port\n");
|
||||
break;
|
||||
default:
|
||||
rc = -EIO;
|
||||
}
|
||||
break;
|
||||
else
|
||||
switch (cbctl->ipa_rc) {
|
||||
case IPA_RC_NOTSUPP:
|
||||
rc = -ENOSYS;
|
||||
rc = -EOPNOTSUPP;
|
||||
break;
|
||||
case IPA_RC_UNSUPPORTED_COMMAND:
|
||||
rc = -ENOSYS;
|
||||
rc = -EOPNOTSUPP;
|
||||
break;
|
||||
default:
|
||||
rc = -EIO;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc);
|
||||
QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc);
|
||||
|
@ -1688,6 +1733,13 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static inline int ipa_cmd_sbp(struct qeth_card *card)
|
||||
{
|
||||
return (card->info.type == QETH_CARD_TYPE_IQD) ?
|
||||
IPA_CMD_SETBRIDGEPORT_IQD :
|
||||
IPA_CMD_SETBRIDGEPORT_OSA;
|
||||
}
|
||||
|
||||
static int qeth_bridgeport_query_support_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
|
@ -1719,7 +1771,7 @@ static void qeth_bridgeport_query_support(struct qeth_card *card)
|
|||
struct _qeth_sbp_cbctl cbctl;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "brqsuppo");
|
||||
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
|
||||
iob = qeth_get_ipacmd_buffer(card, ipa_cmd_sbp(card), 0);
|
||||
if (!iob)
|
||||
return;
|
||||
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
|
||||
|
@ -1796,7 +1848,7 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
|
|||
QETH_CARD_TEXT(card, 2, "brqports");
|
||||
if (!(card->options.sbp.supported_funcs & IPA_SBP_QUERY_BRIDGE_PORTS))
|
||||
return -EOPNOTSUPP;
|
||||
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
|
||||
iob = qeth_get_ipacmd_buffer(card, ipa_cmd_sbp(card), 0);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
|
||||
|
@ -1808,10 +1860,9 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
|
|||
cmd->data.sbp.hdr.seq_no = 1;
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
|
||||
(void *)&cbctl);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_bridgeport_query_ports);
|
||||
|
||||
|
@ -1864,7 +1915,7 @@ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
|
|||
}
|
||||
if (!(card->options.sbp.supported_funcs & setcmd))
|
||||
return -EOPNOTSUPP;
|
||||
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
|
||||
iob = qeth_get_ipacmd_buffer(card, ipa_cmd_sbp(card), 0);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
|
||||
|
@ -1874,10 +1925,9 @@ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
|
|||
cmd->data.sbp.hdr.seq_no = 1;
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb,
|
||||
(void *)&cbctl);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = qeth_bridgeport_makerc(card, &cbctl, setcmd);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return qeth_bridgeport_makerc(card, &cbctl, setcmd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1898,7 +1948,7 @@ static int qeth_anset_makerc(struct qeth_card *card, int pnso_rc, u16 response)
|
|||
case 0x0004:
|
||||
case 0x0100:
|
||||
case 0x0106:
|
||||
rc = -ENOSYS;
|
||||
rc = -EOPNOTSUPP;
|
||||
dev_err(&card->gdev->dev,
|
||||
"Setting address notification failed\n");
|
||||
break;
|
||||
|
|
|
@ -23,8 +23,6 @@ static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
|
|||
if (!card)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&card->conf_mutex);
|
||||
|
||||
if (qeth_card_hw_is_reachable(card) &&
|
||||
card->options.sbp.supported_funcs)
|
||||
rc = qeth_bridgeport_query_ports(card,
|
||||
|
@ -59,8 +57,6 @@ static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
|
|||
rc = sprintf(buf, "%s\n", word);
|
||||
}
|
||||
|
||||
mutex_unlock(&card->conf_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -90,7 +86,9 @@ static ssize_t qeth_bridge_port_role_store(struct device *dev,
|
|||
|
||||
mutex_lock(&card->conf_mutex);
|
||||
|
||||
if (qeth_card_hw_is_reachable(card)) {
|
||||
if (card->options.sbp.reflect_promisc) /* Forbid direct manipulation */
|
||||
rc = -EPERM;
|
||||
else if (qeth_card_hw_is_reachable(card)) {
|
||||
rc = qeth_bridgeport_setrole(card, role);
|
||||
if (!rc)
|
||||
card->options.sbp.role = role;
|
||||
|
@ -123,12 +121,8 @@ static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
|
|||
if (!card)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&card->conf_mutex);
|
||||
|
||||
enabled = card->options.sbp.hostnotification;
|
||||
|
||||
mutex_unlock(&card->conf_mutex);
|
||||
|
||||
return sprintf(buf, "%d\n", enabled);
|
||||
}
|
||||
|
||||
|
@ -167,10 +161,72 @@ static DEVICE_ATTR(bridge_hostnotify, 0644,
|
|||
qeth_bridgeport_hostnotification_show,
|
||||
qeth_bridgeport_hostnotification_store);
|
||||
|
||||
static ssize_t qeth_bridgeport_reflect_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(dev);
|
||||
char *state;
|
||||
|
||||
if (!card)
|
||||
return -EINVAL;
|
||||
|
||||
if (card->options.sbp.reflect_promisc) {
|
||||
if (card->options.sbp.reflect_promisc_primary)
|
||||
state = "primary";
|
||||
else
|
||||
state = "secondary";
|
||||
} else
|
||||
state = "none";
|
||||
|
||||
return sprintf(buf, "%s\n", state);
|
||||
}
|
||||
|
||||
static ssize_t qeth_bridgeport_reflect_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(dev);
|
||||
int enable, primary;
|
||||
int rc = 0;
|
||||
|
||||
if (!card)
|
||||
return -EINVAL;
|
||||
|
||||
if (sysfs_streq(buf, "none")) {
|
||||
enable = 0;
|
||||
primary = 0;
|
||||
} else if (sysfs_streq(buf, "primary")) {
|
||||
enable = 1;
|
||||
primary = 1;
|
||||
} else if (sysfs_streq(buf, "secondary")) {
|
||||
enable = 1;
|
||||
primary = 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&card->conf_mutex);
|
||||
|
||||
if (card->options.sbp.role != QETH_SBP_ROLE_NONE)
|
||||
rc = -EPERM;
|
||||
else {
|
||||
card->options.sbp.reflect_promisc = enable;
|
||||
card->options.sbp.reflect_promisc_primary = primary;
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
mutex_unlock(&card->conf_mutex);
|
||||
|
||||
return rc ? rc : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(bridge_reflect_promisc, 0644,
|
||||
qeth_bridgeport_reflect_show,
|
||||
qeth_bridgeport_reflect_store);
|
||||
|
||||
static struct attribute *qeth_l2_bridgeport_attrs[] = {
|
||||
&dev_attr_bridge_role.attr,
|
||||
&dev_attr_bridge_state.attr,
|
||||
&dev_attr_bridge_hostnotify.attr,
|
||||
&dev_attr_bridge_reflect_promisc.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -3198,8 +3198,7 @@ static int qeth_l3_set_features(struct net_device *dev,
|
|||
netdev_features_t features)
|
||||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
u32 changed = dev->features ^ features;
|
||||
int err;
|
||||
netdev_features_t changed = dev->features ^ features;
|
||||
|
||||
if (!(changed & NETIF_F_RXCSUM))
|
||||
return 0;
|
||||
|
@ -3208,11 +3207,7 @@ static int qeth_l3_set_features(struct net_device *dev,
|
|||
card->state == CARD_STATE_RECOVER)
|
||||
return 0;
|
||||
|
||||
err = qeth_l3_set_rx_csum(card, features & NETIF_F_RXCSUM);
|
||||
if (err)
|
||||
dev->features = features ^ NETIF_F_RXCSUM;
|
||||
|
||||
return err;
|
||||
return qeth_l3_set_rx_csum(card, features & NETIF_F_RXCSUM ? 1 : 0);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops qeth_l3_ethtool_ops = {
|
||||
|
|
Loading…
Reference in New Issue