Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9f2c028 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 's390-qeth-next'



Julian Wiedmann says:

====================
s390/qeth: updates 2019-02-28

please apply one more qeth patch series for net-next. This eliminates
some of the quirks in our reset code, and slims down the internal
state machine.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 54903572 0f7aedbd
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -483,7 +483,6 @@ struct qeth_out_q_stats {
	u64 tx_bytes;
	u64 tx_errors;
	u64 tx_dropped;
	u64 tx_carrier_errors;
};

struct qeth_qdio_out_q {
@@ -552,8 +551,6 @@ enum qeth_card_states {
	CARD_STATE_DOWN,
	CARD_STATE_HARDSETUP,
	CARD_STATE_SOFTSETUP,
	CARD_STATE_UP,
	CARD_STATE_RECOVER,
};

/**
@@ -665,6 +662,7 @@ struct qeth_card_info {
	unsigned short chpid;
	__u16 func_level;
	char mcl_level[QETH_MCL_LENGTH + 1];
	u8 open_when_online:1;
	int guestlan;
	int mac_bits;
	enum qeth_card_types type;
@@ -808,6 +806,11 @@ struct qeth_card {
	struct work_struct close_dev_work;
};

static inline bool qeth_card_hw_is_reachable(struct qeth_card *card)
{
	return card->state == CARD_STATE_SOFTSETUP;
}

struct qeth_trap_id {
	__u16 lparnr;
	char vmname[8];
@@ -942,7 +945,6 @@ extern const struct attribute_group qeth_device_attr_group;
extern const struct attribute_group qeth_device_blkt_group;
extern const struct device_type qeth_generic_devtype;

int qeth_card_hw_is_reachable(struct qeth_card *);
const char *qeth_get_cardname_short(struct qeth_card *);
int qeth_realloc_buffer_pool(struct qeth_card *, int);
int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
@@ -1002,7 +1004,6 @@ int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback);
int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
void qeth_trace_features(struct qeth_card *);
void qeth_close_dev(struct qeth_card *);
int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,
						 enum qeth_ipa_funcs,
+4 −43
Original line number Diff line number Diff line
@@ -74,34 +74,15 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf);
static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);

static struct workqueue_struct *qeth_wq;

int qeth_card_hw_is_reachable(struct qeth_card *card)
{
	return (card->state == CARD_STATE_SOFTSETUP) ||
		(card->state == CARD_STATE_UP);
}
EXPORT_SYMBOL_GPL(qeth_card_hw_is_reachable);

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 const char *qeth_get_cardname(struct qeth_card *card)
{
	if (card->info.guestlan) {
@@ -265,8 +246,7 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
{
	QETH_CARD_TEXT(card, 2, "realcbp");

	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER))
	if (card->state != CARD_STATE_DOWN)
		return -EPERM;

	/* TODO: steel/add buffers from/to a running card's buffer pool (?) */
@@ -639,7 +619,7 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
			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);
			schedule_work(&card->close_dev_work);
		} else {
			dev_warn(&card->gdev->dev,
				 "The link for interface %s on CHPID 0x%X failed\n",
@@ -3479,8 +3459,7 @@ int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
			goto out;
		}

		if (card->state != CARD_STATE_DOWN &&
		    card->state != CARD_STATE_RECOVER) {
		if (card->state != CARD_STATE_DOWN) {
			rc = -1;
			goto out;
		}
@@ -6220,7 +6199,6 @@ void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
		stats->tx_bytes += queue->stats.tx_bytes;
		stats->tx_errors += queue->stats.tx_errors;
		stats->tx_dropped += queue->stats.tx_dropped;
		stats->tx_carrier_errors += queue->stats.tx_carrier_errors;
	}
}
EXPORT_SYMBOL_GPL(qeth_get_stats64);
@@ -6230,16 +6208,11 @@ int qeth_open(struct net_device *dev)
	struct qeth_card *card = dev->ml_priv;

	QETH_CARD_TEXT(card, 4, "qethopen");
	if (card->state == CARD_STATE_UP)
		return 0;
	if (card->state != CARD_STATE_SOFTSETUP)
		return -ENODEV;

	if (qdio_stop_irq(CARD_DDEV(card), 0) < 0)
		return -EIO;

	card->data.state = CH_STATE_UP;
	card->state = CARD_STATE_UP;
	netif_start_queue(dev);

	napi_enable(&card->napi);
@@ -6257,10 +6230,7 @@ int qeth_stop(struct net_device *dev)

	QETH_CARD_TEXT(card, 4, "qethstop");
	netif_tx_disable(dev);
	if (card->state == CARD_STATE_UP) {
		card->state = CARD_STATE_SOFTSETUP;
	napi_disable(&card->napi);
	}
	return 0;
}
EXPORT_SYMBOL_GPL(qeth_stop);
@@ -6271,12 +6241,6 @@ static int __init qeth_core_init(void)

	pr_info("loading core functions\n");

	qeth_wq = create_singlethread_workqueue("qeth_wq");
	if (!qeth_wq) {
		rc = -ENOMEM;
		goto out_err;
	}

	rc = qeth_register_dbf_views();
	if (rc)
		goto dbf_err;
@@ -6318,8 +6282,6 @@ static int __init qeth_core_init(void)
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;
}
@@ -6327,7 +6289,6 @@ static int __init qeth_core_init(void)
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);
+8 −15
Original line number Diff line number Diff line
@@ -29,13 +29,11 @@ static ssize_t qeth_dev_state_show(struct device *dev,
	case CARD_STATE_HARDSETUP:
		return sprintf(buf, "HARDSETUP\n");
	case CARD_STATE_SOFTSETUP:
		return sprintf(buf, "SOFTSETUP\n");
	case CARD_STATE_UP:
		if (card->dev->flags & IFF_UP)
			return sprintf(buf, "UP (LAN %s)\n",
				       netif_carrier_ok(card->dev) ? "ONLINE" :
								     "OFFLINE");
	case CARD_STATE_RECOVER:
		return sprintf(buf, "RECOVER\n");
		return sprintf(buf, "SOFTSETUP\n");
	default:
		return sprintf(buf, "UNKNOWN\n");
	}
@@ -126,8 +124,7 @@ static ssize_t qeth_dev_portno_store(struct device *dev,
		return -EINVAL;

	mutex_lock(&card->conf_mutex);
	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER)) {
	if (card->state != CARD_STATE_DOWN) {
		rc = -EPERM;
		goto out;
	}
@@ -202,8 +199,7 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
		return -EINVAL;

	mutex_lock(&card->conf_mutex);
	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER)) {
	if (card->state != CARD_STATE_DOWN) {
		rc = -EPERM;
		goto out;
	}
@@ -285,8 +281,7 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
		return -EINVAL;

	mutex_lock(&card->conf_mutex);
	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER)) {
	if (card->state != CARD_STATE_DOWN) {
		rc = -EPERM;
		goto out;
	}
@@ -421,7 +416,6 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
		goto out;
	}

	card->info.mac_bits = 0;
	if (card->discipline) {
		/* start with a new, pristine netdevice: */
		ndev = qeth_clone_netdev(card->dev);
@@ -634,8 +628,7 @@ static ssize_t qeth_dev_blkt_store(struct qeth_card *card,
		return -EINVAL;

	mutex_lock(&card->conf_mutex);
	if ((card->state != CARD_STATE_DOWN) &&
	    (card->state != CARD_STATE_RECOVER)) {
	if (card->state != CARD_STATE_DOWN) {
		rc = -EPERM;
		goto out;
	}
+32 −75
Original line number Diff line number Diff line
@@ -285,25 +285,13 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
	return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
}

static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
static void qeth_l2_stop_card(struct qeth_card *card)
{
	QETH_DBF_TEXT(SETUP , 2, "stopcard");
	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));

	qeth_set_allowed_threads(card, 0, 1);
	if (card->read.state == CH_STATE_UP &&
	    card->write.state == CH_STATE_UP &&
	    (card->state == CARD_STATE_UP)) {
		if (recovery_mode && !IS_OSN(card)) {
			qeth_stop(card->dev);
		} else {
			rtnl_lock();
			dev_close(card->dev);
			rtnl_unlock();
		}
		card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
		card->state = CARD_STATE_SOFTSETUP;
	}

	if (card->state == CARD_STATE_SOFTSETUP) {
		qeth_l2_del_all_macs(card);
		qeth_clear_ipacmd_list(card);
@@ -321,6 +309,7 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
	}

	flush_workqueue(card->event_wq);
	card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
}

static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
@@ -622,11 +611,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,

	queue = qeth_get_tx_queue(card, skb, ipv, cast_type);

	if (card->state != CARD_STATE_UP) {
		QETH_TXQ_STAT_INC(queue, tx_carrier_errors);
		goto tx_drop;
	}

	netif_stop_queue(dev);

	if (IS_OSN(card))
@@ -644,7 +628,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
		return NETDEV_TX_BUSY;
	} /* else fall through */

tx_drop:
	QETH_TXQ_STAT_INC(queue, tx_dropped);
	QETH_TXQ_STAT_INC(queue, tx_errors);
	dev_kfree_skb_any(skb);
@@ -802,12 +785,11 @@ static void qeth_l2_trace_features(struct qeth_card *card)
		      sizeof(card->options.vnicc.sup_chars));
}

static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
static int qeth_l2_set_online(struct ccwgroup_device *gdev)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
	struct net_device *dev = card->dev;
	int rc = 0;
	enum qeth_card_states recover_flag;
	bool carrier_ok;

	mutex_lock(&card->discipline_mutex);
@@ -815,19 +797,12 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
	QETH_DBF_TEXT(SETUP, 2, "setonlin");
	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));

	recover_flag = card->state;
	rc = qeth_core_hardsetup_card(card, &carrier_ok);
	if (rc) {
		QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
		rc = -ENODEV;
		goto out_remove;
	}
	qeth_bridgeport_query_support(card);
	if (card->options.sbp.supported_funcs)
		dev_info(&card->gdev->dev,
		"The device represents a Bridge Capable Port\n");

	qeth_l2_register_dev_addr(card);

	if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
		if (card->info.hwtrap &&
@@ -836,6 +811,13 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
	} else
		card->info.hwtrap = 0;

	qeth_bridgeport_query_support(card);
	if (card->options.sbp.supported_funcs)
		dev_info(&card->gdev->dev,
		"The device represents a Bridge Capable Port\n");

	qeth_l2_register_dev_addr(card);

	/* for the rx_bcast characteristic, init VNICC after setmac */
	qeth_l2_vnicc_init(card);

@@ -881,16 +863,10 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
		netif_device_attach(dev);
		qeth_enable_hw_features(dev);

		if (recover_flag == CARD_STATE_RECOVER) {
			if (recovery_mode && !IS_OSN(card)) {
				if (!qeth_l2_validate_addr(dev)) {
					qeth_open(dev);
					qeth_l2_set_rx_mode(dev);
				}
			} else {
		if (card->info.open_when_online) {
			card->info.open_when_online = 0;
			dev_open(dev, NULL);
		}
		}
		rtnl_unlock();
	}
	/* let user_space know that device is online */
@@ -900,48 +876,42 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
	return 0;

out_remove:
	qeth_l2_stop_card(card, 0);
	qeth_l2_stop_card(card);
	ccw_device_set_offline(CARD_DDEV(card));
	ccw_device_set_offline(CARD_WDEV(card));
	ccw_device_set_offline(CARD_RDEV(card));
	qdio_free(CARD_DDEV(card));
	if (recover_flag == CARD_STATE_RECOVER)
		card->state = CARD_STATE_RECOVER;
	else
	card->state = CARD_STATE_DOWN;

	mutex_unlock(&card->conf_mutex);
	mutex_unlock(&card->discipline_mutex);
	return rc;
}

static int qeth_l2_set_online(struct ccwgroup_device *gdev)
{
	return __qeth_l2_set_online(gdev, 0);
}

static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
					int recovery_mode)
{
	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
	int rc = 0, rc2 = 0, rc3 = 0;
	enum qeth_card_states recover_flag;

	mutex_lock(&card->discipline_mutex);
	mutex_lock(&card->conf_mutex);
	QETH_DBF_TEXT(SETUP, 3, "setoffl");
	QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));

	if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
		qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
		card->info.hwtrap = 1;
	}

	rtnl_lock();
	card->info.open_when_online = card->dev->flags & IFF_UP;
	dev_close(card->dev);
	netif_device_detach(card->dev);
	netif_carrier_off(card->dev);
	rtnl_unlock();

	recover_flag = card->state;
	if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
		qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
		card->info.hwtrap = 1;
	}
	qeth_l2_stop_card(card, recovery_mode);
	qeth_l2_stop_card(card);
	rc  = ccw_device_set_offline(CARD_DDEV(card));
	rc2 = ccw_device_set_offline(CARD_WDEV(card));
	rc3 = ccw_device_set_offline(CARD_RDEV(card));
@@ -950,8 +920,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
	if (rc)
		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
	qdio_free(CARD_DDEV(card));
	if (recover_flag == CARD_STATE_UP)
		card->state = CARD_STATE_RECOVER;

	/* let user_space know that device is offline */
	kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
	mutex_unlock(&card->conf_mutex);
@@ -977,12 +946,12 @@ static int qeth_l2_recover(void *ptr)
	dev_warn(&card->gdev->dev,
		"A recovery process has been started for the device\n");
	__qeth_l2_set_offline(card->gdev, 1);
	rc = __qeth_l2_set_online(card->gdev, 1);
	rc = qeth_l2_set_online(card->gdev);
	if (!rc)
		dev_info(&card->gdev->dev,
			"Device successfully recovered!\n");
	else {
		qeth_close_dev(card);
		ccwgroup_set_offline(card->gdev);
		dev_warn(&card->gdev->dev, "The qeth device driver "
				"failed to recover an error on the device\n");
	}
@@ -1010,29 +979,17 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
	if (gdev->state == CCWGROUP_OFFLINE)
		return 0;
	if (card->state == CARD_STATE_UP) {
		if (card->info.hwtrap)
			qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
		__qeth_l2_set_offline(card->gdev, 1);
	} else
		__qeth_l2_set_offline(card->gdev, 0);

	qeth_l2_set_offline(gdev);
	return 0;
}

static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
	int rc = 0;
	int rc;

	if (card->state == CARD_STATE_RECOVER) {
		rc = __qeth_l2_set_online(card->gdev, 1);
		if (rc) {
			rtnl_lock();
			dev_close(card->dev);
			rtnl_unlock();
		}
	} else
		rc = __qeth_l2_set_online(card->gdev, 0);
	rc = qeth_l2_set_online(gdev);

	qeth_set_allowed_threads(card, 0xffffffff, 0);
	if (rc)
+26 −66
Original line number Diff line number Diff line
@@ -1406,27 +1406,17 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
	return work_done;
}

static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
static void qeth_l3_stop_card(struct qeth_card *card)
{
	QETH_DBF_TEXT(SETUP, 2, "stopcard");
	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));

	qeth_set_allowed_threads(card, 0, 1);

	if (card->options.sniffer &&
	    (card->info.promisc_mode == SET_PROMISC_MODE_ON))
		qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
	if (card->read.state == CH_STATE_UP &&
	    card->write.state == CH_STATE_UP &&
	    (card->state == CARD_STATE_UP)) {
		if (recovery_mode)
			qeth_stop(card->dev);
		else {
			rtnl_lock();
			dev_close(card->dev);
			rtnl_unlock();
		}
		card->state = CARD_STATE_SOFTSETUP;
	}

	if (card->state == CARD_STATE_SOFTSETUP) {
		qeth_l3_clear_ip_htable(card, 1);
		qeth_clear_ipacmd_list(card);
@@ -2084,11 +2074,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
			goto tx_drop;
	}

	if (card->state != CARD_STATE_UP) {
		QETH_TXQ_STAT_INC(queue, tx_carrier_errors);
		goto tx_drop;
	}

	if (cast_type == RTN_BROADCAST && !card->info.broadcast_capable)
		goto tx_drop;

@@ -2299,12 +2284,11 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
	qeth_l3_clear_ipato_list(card);
}

static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
static int qeth_l3_set_online(struct ccwgroup_device *gdev)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
	struct net_device *dev = card->dev;
	int rc = 0;
	enum qeth_card_states recover_flag;
	bool carrier_ok;

	mutex_lock(&card->discipline_mutex);
@@ -2312,7 +2296,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
	QETH_DBF_TEXT(SETUP, 2, "setonlin");
	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));

	recover_flag = card->state;
	rc = qeth_core_hardsetup_card(card, &carrier_ok);
	if (rc) {
		QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
@@ -2375,14 +2358,10 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
		netif_device_attach(dev);
		qeth_enable_hw_features(dev);

		if (recover_flag == CARD_STATE_RECOVER) {
			if (recovery_mode) {
				qeth_open(dev);
				qeth_l3_set_rx_mode(dev);
			} else {
		if (card->info.open_when_online) {
			card->info.open_when_online = 0;
			dev_open(dev, NULL);
		}
		}
		rtnl_unlock();
	}
	qeth_trace_features(card);
@@ -2392,49 +2371,43 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
	mutex_unlock(&card->discipline_mutex);
	return 0;
out_remove:
	qeth_l3_stop_card(card, 0);
	qeth_l3_stop_card(card);
	ccw_device_set_offline(CARD_DDEV(card));
	ccw_device_set_offline(CARD_WDEV(card));
	ccw_device_set_offline(CARD_RDEV(card));
	qdio_free(CARD_DDEV(card));
	if (recover_flag == CARD_STATE_RECOVER)
		card->state = CARD_STATE_RECOVER;
	else
	card->state = CARD_STATE_DOWN;

	mutex_unlock(&card->conf_mutex);
	mutex_unlock(&card->discipline_mutex);
	return rc;
}

static int qeth_l3_set_online(struct ccwgroup_device *gdev)
{
	return __qeth_l3_set_online(gdev, 0);
}

static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
			int recovery_mode)
{
	struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
	int rc = 0, rc2 = 0, rc3 = 0;
	enum qeth_card_states recover_flag;

	mutex_lock(&card->discipline_mutex);
	mutex_lock(&card->conf_mutex);
	QETH_DBF_TEXT(SETUP, 3, "setoffl");
	QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));

	if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
		qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
		card->info.hwtrap = 1;
	}

	rtnl_lock();
	card->info.open_when_online = card->dev->flags & IFF_UP;
	dev_close(card->dev);
	netif_device_detach(card->dev);
	netif_carrier_off(card->dev);
	rtnl_unlock();

	recover_flag = card->state;
	if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
		qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
		card->info.hwtrap = 1;
	}
	qeth_l3_stop_card(card, recovery_mode);
	if ((card->options.cq == QETH_CQ_ENABLED) && card->dev) {
	qeth_l3_stop_card(card);
	if (card->options.cq == QETH_CQ_ENABLED) {
		rtnl_lock();
		call_netdevice_notifiers(NETDEV_REBOOT, card->dev);
		rtnl_unlock();
@@ -2447,8 +2420,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
	if (rc)
		QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
	qdio_free(CARD_DDEV(card));
	if (recover_flag == CARD_STATE_UP)
		card->state = CARD_STATE_RECOVER;

	/* let user_space know that device is offline */
	kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
	mutex_unlock(&card->conf_mutex);
@@ -2475,12 +2447,12 @@ static int qeth_l3_recover(void *ptr)
	dev_warn(&card->gdev->dev,
		"A recovery process has been started for the device\n");
	__qeth_l3_set_offline(card->gdev, 1);
	rc = __qeth_l3_set_online(card->gdev, 1);
	rc = qeth_l3_set_online(card->gdev);
	if (!rc)
		dev_info(&card->gdev->dev,
			"Device successfully recovered!\n");
	else {
		qeth_close_dev(card);
		ccwgroup_set_offline(card->gdev);
		dev_warn(&card->gdev->dev, "The qeth device driver "
				"failed to recover an error on the device\n");
	}
@@ -2497,29 +2469,17 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
	if (gdev->state == CCWGROUP_OFFLINE)
		return 0;
	if (card->state == CARD_STATE_UP) {
		if (card->info.hwtrap)
			qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
		__qeth_l3_set_offline(card->gdev, 1);
	} else
		__qeth_l3_set_offline(card->gdev, 0);

	qeth_l3_set_offline(gdev);
	return 0;
}

static int qeth_l3_pm_resume(struct ccwgroup_device *gdev)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
	int rc = 0;
	int rc;

	if (card->state == CARD_STATE_RECOVER) {
		rc = __qeth_l3_set_online(card->gdev, 1);
		if (rc) {
			rtnl_lock();
			dev_close(card->dev);
			rtnl_unlock();
		}
	} else
		rc = __qeth_l3_set_online(card->gdev, 0);
	rc = qeth_l3_set_online(gdev);

	qeth_set_allowed_threads(card, 0xffffffff, 0);
	if (rc)
Loading