summaryrefslogtreecommitdiff
path: root/drivers/s390/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net')
-rw-r--r--drivers/s390/net/Kconfig4
-rw-r--r--drivers/s390/net/claw.c4
-rw-r--r--drivers/s390/net/ctcm_main.c4
-rw-r--r--drivers/s390/net/ctcm_mpc.c3
-rw-r--r--drivers/s390/net/lcs.c2
-rw-r--r--drivers/s390/net/qeth_core.h11
-rw-r--r--drivers/s390/net/qeth_core_main.c329
-rw-r--r--drivers/s390/net/qeth_core_mpc.c1
-rw-r--r--drivers/s390/net/qeth_core_mpc.h5
-rw-r--r--drivers/s390/net/qeth_core_sys.c3
-rw-r--r--drivers/s390/net/qeth_l2_main.c33
-rw-r--r--drivers/s390/net/qeth_l3_main.c43
12 files changed, 285 insertions, 157 deletions
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index dfda748c4000..8b3f55991805 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -74,8 +74,8 @@ config QETH
depends on CCW && NETDEVICES && IP_MULTICAST && QDIO
help
This driver supports the IBM System z OSA Express adapters
- in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN
- interfaces in QDIO and HIPER mode.
+ in QDIO mode (all media types), HiperSockets interfaces and z/VM
+ virtual NICs for Guest LAN and VSWITCH.
For details please refer to the documentation provided by IBM at
<http://www.ibm.com/developerworks/linux/linux390>
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index a0a4afe537d0..83bc9c5fa0c1 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -282,7 +282,7 @@ static struct ccw_driver claw_ccw_driver = {
.ids = claw_ids,
.probe = ccwgroup_probe_ccwdev,
.remove = ccwgroup_remove_ccwdev,
- .int_class = IOINT_CLW,
+ .int_class = IRQIO_CLW,
};
static ssize_t claw_driver_group_store(struct device_driver *ddrv,
@@ -3018,10 +3018,8 @@ claw_remove_device(struct ccwgroup_device *cgdev)
{
struct claw_privbk *priv;
- BUG_ON(!cgdev);
CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev));
priv = dev_get_drvdata(&cgdev->dev);
- BUG_ON(!priv);
dev_info(&cgdev->dev, " will be removed.\n");
if (cgdev->state == CCWGROUP_ONLINE)
claw_shutdown_device(cgdev);
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 98ea9cc6f1aa..676f12049a36 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1691,8 +1691,6 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev)
{
struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev);
- BUG_ON(priv == NULL);
-
CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
"removing device %p, proto : %d",
cgdev, priv->protocol);
@@ -1757,7 +1755,7 @@ static struct ccw_driver ctcm_ccw_driver = {
.ids = ctcm_ids,
.probe = ccwgroup_probe_ccwdev,
.remove = ccwgroup_remove_ccwdev,
- .int_class = IOINT_CTC,
+ .int_class = IRQIO_CTC,
};
static struct ccwgroup_driver ctcm_group_driver = {
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 05b734a2b5b7..2dbc77b5137b 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -1367,7 +1367,6 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
struct mpc_group *grp;
struct channel *wch;
- BUG_ON(dev == NULL);
CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name);
priv = dev->ml_priv;
@@ -1472,8 +1471,6 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
struct channel *wch;
struct channel *rch;
- BUG_ON(dev == NULL);
-
priv = dev->ml_priv;
grp = priv->mpcg;
wch = priv->channel[CTCM_WRITE];
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 2ca0f1dd7a00..c645dc9e98af 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -2384,7 +2384,7 @@ static struct ccw_driver lcs_ccw_driver = {
.ids = lcs_ids,
.probe = ccwgroup_probe_ccwdev,
.remove = ccwgroup_remove_ccwdev,
- .int_class = IOINT_LCS,
+ .int_class = IRQIO_LCS,
};
/**
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index fa7adad6f9ba..d87961d4c0de 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -678,6 +678,7 @@ struct qeth_card_options {
int performance_stats;
int rx_sg_cb;
enum qeth_ipa_isolation_modes isolation;
+ enum qeth_ipa_isolation_modes prev_isolation;
int sniffer;
enum qeth_cq cq;
char hsuid[9];
@@ -789,6 +790,7 @@ struct qeth_card {
struct qeth_rx rx;
struct delayed_work buffer_reclaim_work;
int reclaim_index;
+ struct work_struct close_dev_work;
};
struct qeth_card_list_struct {
@@ -816,7 +818,7 @@ static inline struct qeth_card *CARD_FROM_CDEV(struct ccw_device *cdev)
static inline int qeth_get_micros(void)
{
- return (int) (get_clock() >> 12);
+ return (int) (get_tod_clock() >> 12);
}
static inline int qeth_get_ip_version(struct sk_buff *skb)
@@ -909,9 +911,6 @@ struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
int qeth_mdio_read(struct net_device *, int, int);
int qeth_snmp_command(struct qeth_card *, char __user *);
int qeth_query_oat_command(struct qeth_card *, char __user *);
-struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32);
-int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *,
- unsigned long);
int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
void *reply_param);
@@ -928,11 +927,13 @@ void qeth_core_get_strings(struct net_device *, u32, u8 *);
void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
-int qeth_set_access_ctrl_online(struct qeth_card *card);
+int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback);
int qeth_hdr_chk_and_bounce(struct sk_buff *, int);
int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
+void qeth_trace_features(struct qeth_card *);
+void qeth_close_dev(struct qeth_card *);
/* exports for OSN */
int qeth_osn_assist(struct net_device *, void *, int);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 3e25d3150456..0d8cdff81813 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -68,18 +68,39 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
enum qeth_qdio_buffer_states newbufstate);
static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
+static struct workqueue_struct *qeth_wq;
+
+static void qeth_close_dev_handler(struct work_struct *work)
+{
+ struct qeth_card *card;
+
+ card = container_of(work, struct qeth_card, close_dev_work);
+ QETH_CARD_TEXT(card, 2, "cldevhdl");
+ rtnl_lock();
+ dev_close(card->dev);
+ rtnl_unlock();
+ ccwgroup_set_offline(card->gdev);
+}
+
+void qeth_close_dev(struct qeth_card *card)
+{
+ QETH_CARD_TEXT(card, 2, "cldevsubm");
+ queue_work(qeth_wq, &card->close_dev_work);
+}
+EXPORT_SYMBOL_GPL(qeth_close_dev);
+
static inline const char *qeth_get_cardname(struct qeth_card *card)
{
if (card->info.guestlan) {
switch (card->info.type) {
case QETH_CARD_TYPE_OSD:
- return " Guest LAN QDIO";
+ return " Virtual NIC QDIO";
case QETH_CARD_TYPE_IQD:
- return " Guest LAN Hiper";
+ return " Virtual NIC Hiper";
case QETH_CARD_TYPE_OSM:
- return " Guest LAN QDIO - OSM";
+ return " Virtual NIC QDIO - OSM";
case QETH_CARD_TYPE_OSX:
- return " Guest LAN QDIO - OSX";
+ return " Virtual NIC QDIO - OSX";
default:
return " unknown";
}
@@ -108,13 +129,13 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
if (card->info.guestlan) {
switch (card->info.type) {
case QETH_CARD_TYPE_OSD:
- return "GuestLAN QDIO";
+ return "Virt.NIC QDIO";
case QETH_CARD_TYPE_IQD:
- return "GuestLAN Hiper";
+ return "Virt.NIC Hiper";
case QETH_CARD_TYPE_OSM:
- return "GuestLAN OSM";
+ return "Virt.NIC OSM";
case QETH_CARD_TYPE_OSX:
- return "GuestLAN OSX";
+ return "Virt.NIC OSX";
default:
return "unknown";
}
@@ -383,7 +404,7 @@ static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q,
qeth_release_skbs(c);
c = f->next_pending;
- BUG_ON(head->next_pending != f);
+ WARN_ON_ONCE(head->next_pending != f);
head->next_pending = c;
kmem_cache_free(qeth_qdio_outbuf_cache, f);
} else {
@@ -415,13 +436,12 @@ static inline void qeth_qdio_handle_aob(struct qeth_card *card,
buffer = (struct qeth_qdio_out_buffer *) aob->user1;
QETH_CARD_TEXT_(card, 5, "%lx", aob->user1);
- BUG_ON(buffer == NULL);
-
if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) {
notification = TX_NOTIFY_OK;
} else {
- BUG_ON(atomic_read(&buffer->state) != QETH_QDIO_BUF_PENDING);
+ WARN_ON_ONCE(atomic_read(&buffer->state) !=
+ QETH_QDIO_BUF_PENDING);
atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
notification = TX_NOTIFY_DELAYED_OK;
}
@@ -543,11 +563,23 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
} else {
switch (cmd->hdr.command) {
case IPA_CMD_STOPLAN:
- dev_warn(&card->gdev->dev,
+ if (cmd->hdr.return_code ==
+ IPA_RC_VEPA_TO_VEB_TRANSITION) {
+ dev_err(&card->gdev->dev,
+ "Interface %s is down because the "
+ "adjacent port is no longer in "
+ "reflective relay mode\n",
+ QETH_CARD_IFNAME(card));
+ qeth_close_dev(card);
+ } else {
+ dev_warn(&card->gdev->dev,
"The link for interface %s on CHPID"
" 0x%X failed\n",
QETH_CARD_IFNAME(card),
card->info.chpid);
+ qeth_issue_ipa_msg(cmd,
+ cmd->hdr.return_code, card);
+ }
card->lan_online = 0;
if (card->dev && netif_carrier_ok(card->dev))
netif_carrier_off(card->dev);
@@ -1131,7 +1163,7 @@ static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
notify_general_error = 1;
/* release may never happen from within CQ tasklet scope */
- BUG_ON(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
+ WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
skb = skb_dequeue(&buf->skb_list);
while (skb) {
@@ -1417,6 +1449,7 @@ static int qeth_setup_card(struct qeth_card *card)
/* init QDIO stuff */
qeth_init_qdio_info(card);
INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work);
+ INIT_WORK(&card->close_dev_work, qeth_close_dev_handler);
return 0;
}
@@ -2280,7 +2313,6 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
unsigned long data)
{
struct qeth_cmd_buffer *iob;
- int rc = 0;
QETH_DBF_TEXT(SETUP, 2, "ulpstpcb");
@@ -2296,7 +2328,7 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
iob->rc = -EMLINK;
}
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
- return rc;
+ return 0;
}
static int qeth_ulp_setup(struct qeth_card *card)
@@ -2401,7 +2433,7 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
card->qdio.out_qs[i]->queue_no = i;
/* give outbound qeth_qdio_buffers their qdio_buffers */
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
- BUG_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
+ WARN_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j))
goto out_freeoutqbufs;
}
@@ -2870,7 +2902,7 @@ int qeth_send_startlan(struct qeth_card *card)
}
EXPORT_SYMBOL_GPL(qeth_send_startlan);
-int qeth_default_setadapterparms_cb(struct qeth_card *card,
+static int qeth_default_setadapterparms_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct qeth_ipa_cmd *cmd;
@@ -2883,7 +2915,6 @@ int qeth_default_setadapterparms_cb(struct qeth_card *card,
cmd->data.setadapterparms.hdr.return_code;
return 0;
}
-EXPORT_SYMBOL_GPL(qeth_default_setadapterparms_cb);
static int qeth_query_setadapterparms_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
@@ -2903,7 +2934,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
}
-struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
+static struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
__u32 command, __u32 cmdlen)
{
struct qeth_cmd_buffer *iob;
@@ -2919,7 +2950,6 @@ struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
return iob;
}
-EXPORT_SYMBOL_GPL(qeth_get_adapter_cmd);
int qeth_query_setadapterparms(struct qeth_card *card)
{
@@ -2942,16 +2972,33 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
QETH_DBF_TEXT(SETUP, 2, "qipasscb");
cmd = (struct qeth_ipa_cmd *) data;
+
+ switch (cmd->hdr.return_code) {
+ case IPA_RC_NOTSUPP:
+ case IPA_RC_L2_UNSUPPORTED_CMD:
+ QETH_DBF_TEXT(SETUP, 2, "ipaunsup");
+ card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS;
+ card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS;
+ return -0;
+ default:
+ if (cmd->hdr.return_code) {
+ QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled "
+ "rc=%d\n",
+ dev_name(&card->gdev->dev),
+ cmd->hdr.return_code);
+ return 0;
+ }
+ }
+
if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
- } else {
+ } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) {
card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
- }
- QETH_DBF_TEXT(SETUP, 2, "suppenbl");
- QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported);
- QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled);
+ } else
+ QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected"
+ "\n", dev_name(&card->gdev->dev));
return 0;
}
@@ -3549,7 +3596,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
if (queue->bufstates &&
(queue->bufstates[bidx].flags &
QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) {
- BUG_ON(card->options.cq != QETH_CQ_ENABLED);
+ WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED);
if (atomic_cmpxchg(&buffer->state,
QETH_QDIO_BUF_PRIMED,
@@ -3563,7 +3610,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
QETH_CARD_TEXT(queue->card, 5, "aob");
QETH_CARD_TEXT_(queue->card, 5, "%lx",
virt_to_phys(buffer->aob));
- BUG_ON(bidx < 0 || bidx >= QDIO_MAX_BUFFERS_PER_Q);
if (qeth_init_qdio_out_buf(queue, bidx)) {
QETH_CARD_TEXT(card, 2, "outofbuf");
qeth_schedule_recovery(card);
@@ -4045,6 +4091,7 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
{
struct qeth_ipa_cmd *cmd;
struct qeth_set_access_ctrl *access_ctrl_req;
+ int fallback = *(int *)reply->param;
QETH_CARD_TEXT(card, 4, "setaccb");
@@ -4054,12 +4101,14 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
QETH_DBF_TEXT_(SETUP, 2, "%s", card->gdev->dev.kobj.name);
QETH_DBF_TEXT_(SETUP, 2, "rc=%d",
cmd->data.setadapterparms.hdr.return_code);
+ if (cmd->data.setadapterparms.hdr.return_code !=
+ SET_ACCESS_CTRL_RC_SUCCESS)
+ QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%s,%d)==%d\n",
+ card->gdev->dev.kobj.name,
+ access_ctrl_req->subcmd_code,
+ cmd->data.setadapterparms.hdr.return_code);
switch (cmd->data.setadapterparms.hdr.return_code) {
case SET_ACCESS_CTRL_RC_SUCCESS:
- case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED:
- case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED:
- {
- card->options.isolation = access_ctrl_req->subcmd_code;
if (card->options.isolation == ISOLATION_MODE_NONE) {
dev_info(&card->gdev->dev,
"QDIO data connection isolation is deactivated\n");
@@ -4067,72 +4116,64 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
dev_info(&card->gdev->dev,
"QDIO data connection isolation is activated\n");
}
- QETH_DBF_MESSAGE(3, "OK:SET_ACCESS_CTRL(%s, %d)==%d\n",
- card->gdev->dev.kobj.name,
- access_ctrl_req->subcmd_code,
- cmd->data.setadapterparms.hdr.return_code);
break;
- }
+ case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED:
+ QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already "
+ "deactivated\n", dev_name(&card->gdev->dev));
+ if (fallback)
+ card->options.isolation = card->options.prev_isolation;
+ break;
+ case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED:
+ QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already"
+ " activated\n", dev_name(&card->gdev->dev));
+ if (fallback)
+ card->options.isolation = card->options.prev_isolation;
+ break;
case SET_ACCESS_CTRL_RC_NOT_SUPPORTED:
- {
- QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%s,%d)==%d\n",
- card->gdev->dev.kobj.name,
- access_ctrl_req->subcmd_code,
- cmd->data.setadapterparms.hdr.return_code);
dev_err(&card->gdev->dev, "Adapter does not "
"support QDIO data connection isolation\n");
-
- /* ensure isolation mode is "none" */
- card->options.isolation = ISOLATION_MODE_NONE;
break;
- }
case SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER:
- {
- QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d\n",
- card->gdev->dev.kobj.name,
- access_ctrl_req->subcmd_code,
- cmd->data.setadapterparms.hdr.return_code);
dev_err(&card->gdev->dev,
"Adapter is dedicated. "
"QDIO data connection isolation not supported\n");
-
- /* ensure isolation mode is "none" */
- card->options.isolation = ISOLATION_MODE_NONE;
+ if (fallback)
+ card->options.isolation = card->options.prev_isolation;
break;
- }
case SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF:
- {
- QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d\n",
- card->gdev->dev.kobj.name,
- access_ctrl_req->subcmd_code,
- cmd->data.setadapterparms.hdr.return_code);
dev_err(&card->gdev->dev,
"TSO does not permit QDIO data connection isolation\n");
-
- /* ensure isolation mode is "none" */
- card->options.isolation = ISOLATION_MODE_NONE;
+ if (fallback)
+ card->options.isolation = card->options.prev_isolation;
+ break;
+ case SET_ACCESS_CTRL_RC_REFLREL_UNSUPPORTED:
+ dev_err(&card->gdev->dev, "The adjacent switch port does not "
+ "support reflective relay mode\n");
+ if (fallback)
+ card->options.isolation = card->options.prev_isolation;
+ break;
+ case SET_ACCESS_CTRL_RC_REFLREL_FAILED:
+ dev_err(&card->gdev->dev, "The reflective relay mode cannot be "
+ "enabled at the adjacent switch port");
+ if (fallback)
+ card->options.isolation = card->options.prev_isolation;
+ break;
+ case SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED:
+ dev_warn(&card->gdev->dev, "Turning off reflective relay mode "
+ "at the adjacent switch failed\n");
break;
- }
default:
- {
/* this should never happen */
- QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d"
- "==UNKNOWN\n",
- card->gdev->dev.kobj.name,
- access_ctrl_req->subcmd_code,
- cmd->data.setadapterparms.hdr.return_code);
-
- /* ensure isolation mode is "none" */
- card->options.isolation = ISOLATION_MODE_NONE;
+ if (fallback)
+ card->options.isolation = card->options.prev_isolation;
break;
}
- }
qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
return 0;
}
static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
- enum qeth_ipa_isolation_modes isolation)
+ enum qeth_ipa_isolation_modes isolation, int fallback)
{
int rc;
struct qeth_cmd_buffer *iob;
@@ -4152,12 +4193,12 @@ static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
access_ctrl_req->subcmd_code = isolation;
rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_set_access_ctrl_cb,
- NULL);
+ &fallback);
QETH_DBF_TEXT_(SETUP, 2, "rc=%d", rc);
return rc;
}
-int qeth_set_access_ctrl_online(struct qeth_card *card)
+int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback)
{
int rc = 0;
@@ -4167,12 +4208,13 @@ int qeth_set_access_ctrl_online(struct qeth_card *card)
card->info.type == QETH_CARD_TYPE_OSX) &&
qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) {
rc = qeth_setadpparms_set_access_ctrl(card,
- card->options.isolation);
+ card->options.isolation, fallback);
if (rc) {
QETH_DBF_MESSAGE(3,
"IPA(SET_ACCESS_CTRL,%s,%d) sent failed\n",
card->gdev->dev.kobj.name,
rc);
+ rc = -EOPNOTSUPP;
}
} else if (card->options.isolation != ISOLATION_MODE_NONE) {
card->options.isolation = ISOLATION_MODE_NONE;
@@ -4658,7 +4700,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
init_data.output_sbal_state_array = card->qdio.out_bufstates;
init_data.scan_threshold =
- (card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32;
+ (card->info.type == QETH_CARD_TYPE_IQD) ? 1 : 32;
if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) {
@@ -4711,6 +4753,19 @@ static void qeth_core_free_card(struct qeth_card *card)
kfree(card);
}
+void qeth_trace_features(struct qeth_card *card)
+{
+ QETH_CARD_TEXT(card, 2, "features");
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.supported_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.enabled_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.supported_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.enabled_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.supported_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.enabled_funcs);
+ QETH_CARD_TEXT_(card, 2, "%x", card->info.diagass_support);
+}
+EXPORT_SYMBOL_GPL(qeth_trace_features);
+
static struct ccw_device_id qeth_ids[] = {
{CCW_DEVICE_DEVTYPE(0x1731, 0x01, 0x1732, 0x01),
.driver_info = QETH_CARD_TYPE_OSD},
@@ -4738,14 +4793,14 @@ static struct ccw_driver qeth_ccw_driver = {
int qeth_core_hardsetup_card(struct qeth_card *card)
{
- int retries = 0;
+ int retries = 3;
int rc;
QETH_DBF_TEXT(SETUP, 2, "hrdsetup");
atomic_set(&card->force_alloc_skb, 0);
qeth_update_from_chp_desc(card);
retry:
- if (retries)
+ if (retries < 3)
QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n",
dev_name(&card->gdev->dev));
ccw_device_set_offline(CARD_DDEV(card));
@@ -4767,7 +4822,7 @@ retriable:
return rc;
} else if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
- if (++retries > 3)
+ if (--retries < 0)
goto out;
else
goto retry;
@@ -5067,13 +5122,81 @@ static const struct device_type qeth_osn_devtype = {
.groups = qeth_osn_attr_groups,
};
+#define DBF_NAME_LEN 20
+
+struct qeth_dbf_entry {
+ char dbf_name[DBF_NAME_LEN];
+ debug_info_t *dbf_info;
+ struct list_head dbf_list;
+};
+
+static LIST_HEAD(qeth_dbf_list);
+static DEFINE_MUTEX(qeth_dbf_list_mutex);
+
+static debug_info_t *qeth_get_dbf_entry(char *name)
+{
+ struct qeth_dbf_entry *entry;
+ debug_info_t *rc = NULL;
+
+ mutex_lock(&qeth_dbf_list_mutex);
+ list_for_each_entry(entry, &qeth_dbf_list, dbf_list) {
+ if (strcmp(entry->dbf_name, name) == 0) {
+ rc = entry->dbf_info;
+ break;
+ }
+ }
+ mutex_unlock(&qeth_dbf_list_mutex);
+ return rc;
+}
+
+static int qeth_add_dbf_entry(struct qeth_card *card, char *name)
+{
+ struct qeth_dbf_entry *new_entry;
+
+ card->debug = debug_register(name, 2, 1, 8);
+ if (!card->debug) {
+ QETH_DBF_TEXT_(SETUP, 2, "%s", "qcdbf");
+ goto err;
+ }
+ if (debug_register_view(card->debug, &debug_hex_ascii_view))
+ goto err_dbg;
+ new_entry = kzalloc(sizeof(struct qeth_dbf_entry), GFP_KERNEL);
+ if (!new_entry)
+ goto err_dbg;
+ strncpy(new_entry->dbf_name, name, DBF_NAME_LEN);
+ new_entry->dbf_info = card->debug;
+ mutex_lock(&qeth_dbf_list_mutex);
+ list_add(&new_entry->dbf_list, &qeth_dbf_list);
+ mutex_unlock(&qeth_dbf_list_mutex);
+
+ return 0;
+
+err_dbg:
+ debug_unregister(card->debug);
+err:
+ return -ENOMEM;
+}
+
+static void qeth_clear_dbf_list(void)
+{
+ struct qeth_dbf_entry *entry, *tmp;
+
+ mutex_lock(&qeth_dbf_list_mutex);
+ list_for_each_entry_safe(entry, tmp, &qeth_dbf_list, dbf_list) {
+ list_del(&entry->dbf_list);
+ debug_unregister(entry->dbf_info);
+ kfree(entry);
+ }
+ mutex_unlock(&qeth_dbf_list_mutex);
+}
+
static int qeth_core_probe_device(struct ccwgroup_device *gdev)
{
struct qeth_card *card;
struct device *dev;
int rc;
unsigned long flags;
- char dbf_name[20];
+ char dbf_name[DBF_NAME_LEN];
QETH_DBF_TEXT(SETUP, 2, "probedev");
@@ -5092,13 +5215,12 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
snprintf(dbf_name, sizeof(dbf_name), "qeth_card_%s",
dev_name(&gdev->dev));
- card->debug = debug_register(dbf_name, 2, 1, 8);
+ card->debug = qeth_get_dbf_entry(dbf_name);
if (!card->debug) {
- QETH_DBF_TEXT_(SETUP, 2, "%s", "qcdbf");
- rc = -ENOMEM;
- goto err_card;
+ rc = qeth_add_dbf_entry(card, dbf_name);
+ if (rc)
+ goto err_card;
}
- debug_register_view(card->debug, &debug_hex_ascii_view);
card->read.ccwdev = gdev->cdev[0];
card->write.ccwdev = gdev->cdev[1];
@@ -5112,12 +5234,12 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
rc = qeth_determine_card_type(card);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
- goto err_dbf;
+ goto err_card;
}
rc = qeth_setup_card(card);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
- goto err_dbf;
+ goto err_card;
}
if (card->info.type == QETH_CARD_TYPE_OSN)
@@ -5130,7 +5252,7 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
case QETH_CARD_TYPE_OSM:
rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
if (rc)
- goto err_dbf;
+ goto err_card;
rc = card->discipline->setup(card->gdev);
if (rc)
goto err_disc;
@@ -5149,8 +5271,6 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
err_disc:
qeth_core_free_discipline(card);
-err_dbf:
- debug_unregister(card->debug);
err_card:
qeth_core_free_card(card);
err_dev:
@@ -5170,7 +5290,6 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev)
qeth_core_free_discipline(card);
}
- debug_unregister(card->debug);
write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
list_del(&card->list);
write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
@@ -5417,17 +5536,14 @@ void qeth_core_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
struct qeth_card *card = dev->ml_priv;
- if (card->options.layer2)
- strcpy(info->driver, "qeth_l2");
- else
- strcpy(info->driver, "qeth_l3");
- strcpy(info->version, "1.0");
- strcpy(info->fw_version, card->info.mcl_level);
- sprintf(info->bus_info, "%s/%s/%s",
- CARD_RDEV_ID(card),
- CARD_WDEV_ID(card),
- CARD_DDEV_ID(card));
+ strlcpy(info->driver, card->options.layer2 ? "qeth_l2" : "qeth_l3",
+ sizeof(info->driver));
+ strlcpy(info->version, "1.0", sizeof(info->version));
+ strlcpy(info->fw_version, card->info.mcl_level,
+ sizeof(info->fw_version));
+ snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s",
+ CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card));
}
EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
@@ -5527,9 +5643,12 @@ static int __init qeth_core_init(void)
pr_info("loading core functions\n");
INIT_LIST_HEAD(&qeth_core_card_list.list);
+ INIT_LIST_HEAD(&qeth_dbf_list);
rwlock_init(&qeth_core_card_list.rwlock);
mutex_init(&qeth_mod_mutex);
+ qeth_wq = create_singlethread_workqueue("qeth_wq");
+
rc = qeth_register_dbf_views();
if (rc)
goto out_err;
@@ -5576,6 +5695,8 @@ out_err:
static void __exit qeth_core_exit(void)
{
+ qeth_clear_dbf_list();
+ destroy_workqueue(qeth_wq);
ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
ccw_driver_unregister(&qeth_ccw_driver);
kmem_cache_destroy(qeth_qdio_outbuf_cache);
diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c
index 5cebfddb86bd..06c55780005e 100644
--- a/drivers/s390/net/qeth_core_mpc.c
+++ b/drivers/s390/net/qeth_core_mpc.c
@@ -204,6 +204,7 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
{IPA_RC_INVALID_SETRTG_INDICATOR, "Invalid SETRTG indicator"},
{IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"},
{IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"},
+ {IPA_RC_VEPA_TO_VEB_TRANSITION, "Adj. switch disabled port mode RR"},
{IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"},
{IPA_RC_ENOMEM, "Memory problem"},
{IPA_RC_FFFF, "Unknown Error"}
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index 3690bbf2cb3c..07085d55f9a1 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -177,6 +177,7 @@ enum qeth_ipa_return_codes {
IPA_RC_INVALID_SETRTG_INDICATOR = 0xe012,
IPA_RC_MC_ADDR_ALREADY_DEFINED = 0xe013,
IPA_RC_LAN_OFFLINE = 0xe080,
+ IPA_RC_VEPA_TO_VEB_TRANSITION = 0xe090,
IPA_RC_INVALID_IP_VERSION2 = 0xf001,
IPA_RC_ENOMEM = 0xfffe,
IPA_RC_FFFF = 0xffff
@@ -269,6 +270,9 @@ enum qeth_ipa_set_access_mode_rc {
SET_ACCESS_CTRL_RC_ALREADY_ISOLATED = 0x0010,
SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER = 0x0014,
SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF = 0x0018,
+ SET_ACCESS_CTRL_RC_REFLREL_UNSUPPORTED = 0x0022,
+ SET_ACCESS_CTRL_RC_REFLREL_FAILED = 0x0024,
+ SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED = 0x0028,
};
@@ -386,6 +390,7 @@ struct qeth_snmp_ureq {
/* SET_ACCESS_CONTROL: same format for request and reply */
struct qeth_set_access_ctrl {
__u32 subcmd_code;
+ __u8 reserved[8];
} __attribute__((packed));
struct qeth_query_oat {
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index 9655dc0ea0ec..425c0ecf1f3b 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -513,10 +513,11 @@ static ssize_t qeth_dev_isolation_store(struct device *dev,
rc = count;
/* defer IP assist if device is offline (until discipline->set_online)*/
+ card->options.prev_isolation = card->options.isolation;
card->options.isolation = isolation;
if (card->state == CARD_STATE_SOFTSETUP ||
card->state == CARD_STATE_UP) {
- int ipa_rc = qeth_set_access_ctrl_online(card);
+ int ipa_rc = qeth_set_access_ctrl_online(card, 1);
if (ipa_rc != 0)
rc = ipa_rc;
}
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index e67e0258aec5..d690166efeaf 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -411,7 +411,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
unsigned int len;
*done = 0;
- BUG_ON(!budget);
+ WARN_ON_ONCE(!budget);
while (budget) {
skb = qeth_core_get_next_skb(card,
&card->qdio.in_q->bufs[card->rx.b_index],
@@ -626,10 +626,13 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
QETH_DBF_TEXT(SETUP, 2, "doL2init");
QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
- rc = qeth_query_setadapterparms(card);
- if (rc) {
- QETH_DBF_MESSAGE(2, "could not query adapter parameters on "
- "device %s: x%x\n", CARD_BUS_ID(card), rc);
+ if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
+ rc = qeth_query_setadapterparms(card);
+ if (rc) {
+ QETH_DBF_MESSAGE(2, "could not query adapter "
+ "parameters on device %s: x%x\n",
+ CARD_BUS_ID(card), rc);
+ }
}
if (card->info.type == QETH_CARD_TYPE_IQD ||
@@ -676,7 +679,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
return -ERESTARTSYS;
}
rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
- if (!rc)
+ if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND))
rc = qeth_l2_send_setmac(card, addr->sa_data);
return rc ? -EINVAL : 0;
}
@@ -970,7 +973,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
int rc = 0;
enum qeth_card_states recover_flag;
- BUG_ON(!card);
mutex_lock(&card->discipline_mutex);
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin");
@@ -983,6 +985,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
rc = -ENODEV;
goto out_remove;
}
+ qeth_trace_features(card);
if (!card->dev && qeth_l2_setup_netdev(card)) {
rc = -ENODEV;
@@ -1022,9 +1025,14 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
contin:
if ((card->info.type == QETH_CARD_TYPE_OSD) ||
- (card->info.type == QETH_CARD_TYPE_OSX))
+ (card->info.type == QETH_CARD_TYPE_OSX)) {
/* configure isolation level */
- qeth_set_access_ctrl_online(card);
+ rc = qeth_set_access_ctrl_online(card, 0);
+ if (rc) {
+ rc = -ENODEV;
+ goto out_remove;
+ }
+ }
if (card->info.type != QETH_CARD_TYPE_OSN &&
card->info.type != QETH_CARD_TYPE_OSM)
@@ -1141,12 +1149,9 @@ static int qeth_l2_recover(void *ptr)
dev_info(&card->gdev->dev,
"Device successfully recovered!\n");
else {
- if (rtnl_trylock()) {
- dev_close(card->dev);
- rtnl_unlock();
- dev_warn(&card->gdev->dev, "The qeth device driver "
+ qeth_close_dev(card);
+ dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
- }
}
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 5ba390658498..091ca0efa1c5 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1449,7 +1449,8 @@ static int qeth_l3_start_ipassists(struct qeth_card *card)
{
QETH_CARD_TEXT(card, 3, "strtipas");
- qeth_set_access_ctrl_online(card); /* go on*/
+ if (qeth_set_access_ctrl_online(card, 0))
+ return -EIO;
qeth_l3_start_ipa_arp_processing(card); /* go on*/
qeth_l3_start_ipa_ip_fragmentation(card); /* go on*/
qeth_l3_start_ipa_source_mac(card); /* go on*/
@@ -1640,6 +1641,7 @@ static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev)
}
}
+/* called with rcu_read_lock */
static void qeth_l3_add_vlan_mc(struct qeth_card *card)
{
struct in_device *in_dev;
@@ -1652,19 +1654,14 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card)
for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
struct net_device *netdev;
- rcu_read_lock();
netdev = __vlan_find_dev_deep(card->dev, vid);
- rcu_read_unlock();
if (netdev == NULL ||
!(netdev->flags & IFF_UP))
continue;
- in_dev = in_dev_get(netdev);
+ in_dev = __in_dev_get_rcu(netdev);
if (!in_dev)
continue;
- rcu_read_lock();
qeth_l3_add_mc(card, in_dev);
- rcu_read_unlock();
- in_dev_put(in_dev);
}
}
@@ -1673,14 +1670,14 @@ static void qeth_l3_add_multicast_ipv4(struct qeth_card *card)
struct in_device *in4_dev;
QETH_CARD_TEXT(card, 4, "chkmcv4");
- in4_dev = in_dev_get(card->dev);
- if (in4_dev == NULL)
- return;
rcu_read_lock();
+ in4_dev = __in_dev_get_rcu(card->dev);
+ if (in4_dev == NULL)
+ goto unlock;
qeth_l3_add_mc(card, in4_dev);
qeth_l3_add_vlan_mc(card);
+unlock:
rcu_read_unlock();
- in_dev_put(in4_dev);
}
#ifdef CONFIG_QETH_IPV6
@@ -1705,6 +1702,7 @@ static void qeth_l3_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
}
}
+/* called with rcu_read_lock */
static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
{
struct inet6_dev *in_dev;
@@ -1741,10 +1739,12 @@ static void qeth_l3_add_multicast_ipv6(struct qeth_card *card)
in6_dev = in6_dev_get(card->dev);
if (in6_dev == NULL)
return;
+ rcu_read_lock();
read_lock_bh(&in6_dev->lock);
qeth_l3_add_mc6(card, in6_dev);
qeth_l3_add_vlan_mc6(card);
read_unlock_bh(&in6_dev->lock);
+ rcu_read_unlock();
in6_dev_put(in6_dev);
}
#endif /* CONFIG_QETH_IPV6 */
@@ -1813,8 +1813,10 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
unsigned short vid)
{
+ rcu_read_lock();
qeth_l3_free_vlan_addresses4(card, vid);
qeth_l3_free_vlan_addresses6(card, vid);
+ rcu_read_unlock();
}
static int qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
@@ -1939,7 +1941,7 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
__u16 magic;
*done = 0;
- BUG_ON(!budget);
+ WARN_ON_ONCE(!budget);
while (budget) {
skb = qeth_core_get_next_skb(card,
&card->qdio.in_q->bufs[card->rx.b_index],
@@ -3334,7 +3336,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
int rc = 0;
enum qeth_card_states recover_flag;
- BUG_ON(!card);
mutex_lock(&card->discipline_mutex);
mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin");
@@ -3347,6 +3348,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
rc = -ENODEV;
goto out_remove;
}
+ qeth_trace_features(card);
if (!card->dev && qeth_l3_setup_netdev(card)) {
rc = -ENODEV;
@@ -3387,8 +3389,10 @@ contin:
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
if (!card->options.sniffer) {
rc = qeth_l3_start_ipassists(card);
- if (rc)
+ if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
+ goto out_remove;
+ }
rc = qeth_l3_setrouting_v4(card);
if (rc)
QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc);
@@ -3510,12 +3514,9 @@ static int qeth_l3_recover(void *ptr)
dev_info(&card->gdev->dev,
"Device successfully recovered!\n");
else {
- if (rtnl_trylock()) {
- dev_close(card->dev);
- rtnl_unlock();
- dev_warn(&card->gdev->dev, "The qeth device driver "
+ qeth_close_dev(card);
+ dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
- }
}
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
@@ -3714,9 +3715,9 @@ static void qeth_l3_unregister_notifiers(void)
{
QETH_DBF_TEXT(SETUP, 5, "unregnot");
- BUG_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
+ WARN_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
#ifdef CONFIG_QETH_IPV6
- BUG_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
+ WARN_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
#endif /* QETH_IPV6 */
}